Change new map to use dialog
This allows setting additional properties
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { COLOR_RE, ROOT_PATH, SERVER } from "./constants.js";
|
||||
import { Collection, CollectionType } from "./models.js";
|
||||
import { SERVER, ROOT_PATH, COLOR_RE } from "./constants.js";
|
||||
import { escape_xml } from "./utils.js";
|
||||
|
||||
export let server_features = {};
|
||||
@@ -34,7 +34,7 @@ export let server_features = {};
|
||||
export function get_principal(user, password, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("PROPFIND", SERVER + ROOT_PATH, true, user, encodeURIComponent(password));
|
||||
request.onreadystatechange = function() {
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
@@ -59,12 +59,12 @@ export function get_principal(user, password, callback) {
|
||||
}
|
||||
};
|
||||
request.send('<?xml version="1.0" encoding="utf-8" ?>' +
|
||||
'<propfind xmlns="DAV:">' +
|
||||
'<prop>' +
|
||||
'<current-user-principal />' +
|
||||
'<displayname />' +
|
||||
'</prop>' +
|
||||
'</propfind>');
|
||||
'<propfind xmlns="DAV:">' +
|
||||
'<prop>' +
|
||||
'<current-user-principal />' +
|
||||
'<displayname />' +
|
||||
'</prop>' +
|
||||
'</propfind>');
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ export function get_collections(user, password, collection, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("PROPFIND", SERVER + collection.href, true, user, encodeURIComponent(password));
|
||||
request.setRequestHeader("depth", "1");
|
||||
request.onreadystatechange = function() {
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ export function get_collections(user, password, collection, callback) {
|
||||
collections.push(new Collection(href, type, displayname, description, sane_color, count, size, source));
|
||||
}
|
||||
}
|
||||
collections.sort(function(a, b) {
|
||||
collections.sort(function (a, b) {
|
||||
/** @type {string} */ let ca = a.displayname || a.href;
|
||||
/** @type {string} */ let cb = b.displayname || b.href;
|
||||
return ca.localeCompare(cb);
|
||||
@@ -166,28 +166,28 @@ export function get_collections(user, password, collection, callback) {
|
||||
}
|
||||
};
|
||||
request.send('<?xml version="1.0" encoding="utf-8" ?>' +
|
||||
'<propfind ' +
|
||||
'xmlns="DAV:" ' +
|
||||
'xmlns:C="urn:ietf:params:xml:ns:caldav" ' +
|
||||
'xmlns:CR="urn:ietf:params:xml:ns:carddav" ' +
|
||||
'xmlns:CS="http://calendarserver.org/ns/" ' +
|
||||
'xmlns:I="http://apple.com/ns/ical/" ' +
|
||||
'xmlns:INF="http://inf-it.com/ns/ab/" ' +
|
||||
'xmlns:RADICALE="http://radicale.org/ns/"' +
|
||||
'>' +
|
||||
'<prop>' +
|
||||
'<resourcetype />' +
|
||||
'<RADICALE:displayname />' +
|
||||
'<I:calendar-color />' +
|
||||
'<INF:addressbook-color />' +
|
||||
'<C:calendar-description />' +
|
||||
'<C:supported-calendar-component-set />' +
|
||||
'<CR:addressbook-description />' +
|
||||
'<CS:source />' +
|
||||
'<RADICALE:getcontentcount />' +
|
||||
'<getcontentlength />' +
|
||||
'</prop>' +
|
||||
'</propfind>');
|
||||
'<propfind ' +
|
||||
'xmlns="DAV:" ' +
|
||||
'xmlns:C="urn:ietf:params:xml:ns:caldav" ' +
|
||||
'xmlns:CR="urn:ietf:params:xml:ns:carddav" ' +
|
||||
'xmlns:CS="http://calendarserver.org/ns/" ' +
|
||||
'xmlns:I="http://apple.com/ns/ical/" ' +
|
||||
'xmlns:INF="http://inf-it.com/ns/ab/" ' +
|
||||
'xmlns:RADICALE="http://radicale.org/ns/"' +
|
||||
'>' +
|
||||
'<prop>' +
|
||||
'<resourcetype />' +
|
||||
'<RADICALE:displayname />' +
|
||||
'<I:calendar-color />' +
|
||||
'<INF:addressbook-color />' +
|
||||
'<C:calendar-description />' +
|
||||
'<C:supported-calendar-component-set />' +
|
||||
'<CR:addressbook-description />' +
|
||||
'<CS:source />' +
|
||||
'<RADICALE:getcontentcount />' +
|
||||
'<getcontentlength />' +
|
||||
'</prop>' +
|
||||
'</propfind>');
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ export function get_collections(user, password, collection, callback) {
|
||||
export function upload_collection(user, password, collection_href, file, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("PUT", SERVER + collection_href, true, user, encodeURIComponent(password));
|
||||
request.onreadystatechange = function() {
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ export function upload_collection(user, password, collection_href, file, callbac
|
||||
export function delete_collection(user, password, collection, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("DELETE", SERVER + collection.href, true, user, encodeURIComponent(password));
|
||||
request.onreadystatechange = function() {
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
@@ -252,7 +252,7 @@ export function delete_collection(user, password, collection, callback) {
|
||||
function create_edit_collection(user, password, collection, create, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open(create ? "MKCOL" : "PROPPATCH", SERVER + collection.href, true, user, encodeURIComponent(password));
|
||||
request.onreadystatechange = function() {
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
@@ -295,30 +295,30 @@ function create_edit_collection(user, password, collection, create, callback) {
|
||||
}
|
||||
let xml_request = create ? "mkcol" : "propertyupdate";
|
||||
request.send('<?xml version="1.0" encoding="UTF-8" ?>' +
|
||||
'<' + xml_request + ' xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CR="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/" xmlns:I="http://apple.com/ns/ical/" xmlns:INF="http://inf-it.com/ns/ab/">' +
|
||||
'<set>' +
|
||||
'<prop>' +
|
||||
(create ? '<resourcetype><collection />' + resourcetype + '</resourcetype>' : '') +
|
||||
(components ? '<C:supported-calendar-component-set>' + components + '</C:supported-calendar-component-set>' : '') +
|
||||
(displayname ? '<displayname>' + displayname + '</displayname>' : '') +
|
||||
(calendar_color ? '<I:calendar-color>' + calendar_color + '</I:calendar-color>' : '') +
|
||||
(addressbook_color ? '<INF:addressbook-color>' + addressbook_color + '</INF:addressbook-color>' : '') +
|
||||
(addressbook_description ? '<CR:addressbook-description>' + addressbook_description + '</CR:addressbook-description>' : '') +
|
||||
(calendar_description ? '<C:calendar-description>' + calendar_description + '</C:calendar-description>' : '') +
|
||||
(calendar_source ? '<CS:source>' + calendar_source + '</CS:source>' : '') +
|
||||
'</prop>' +
|
||||
'</set>' +
|
||||
(!create ? ('<remove>' +
|
||||
'<prop>' +
|
||||
(!components ? '<C:supported-calendar-component-set />' : '') +
|
||||
(!displayname ? '<displayname />' : '') +
|
||||
(!calendar_color ? '<I:calendar-color />' : '') +
|
||||
(!addressbook_color ? '<INF:addressbook-color />' : '') +
|
||||
(!addressbook_description ? '<CR:addressbook-description />' : '') +
|
||||
(!calendar_description ? '<C:calendar-description />' : '') +
|
||||
'</prop>' +
|
||||
'</remove>'): '') +
|
||||
'</' + xml_request + '>');
|
||||
'<' + xml_request + ' xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CR="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/" xmlns:I="http://apple.com/ns/ical/" xmlns:INF="http://inf-it.com/ns/ab/">' +
|
||||
'<set>' +
|
||||
'<prop>' +
|
||||
(create ? '<resourcetype><collection />' + resourcetype + '</resourcetype>' : '') +
|
||||
(components ? '<C:supported-calendar-component-set>' + components + '</C:supported-calendar-component-set>' : '') +
|
||||
(displayname ? '<displayname>' + displayname + '</displayname>' : '') +
|
||||
(calendar_color ? '<I:calendar-color>' + calendar_color + '</I:calendar-color>' : '') +
|
||||
(addressbook_color ? '<INF:addressbook-color>' + addressbook_color + '</INF:addressbook-color>' : '') +
|
||||
(addressbook_description ? '<CR:addressbook-description>' + addressbook_description + '</CR:addressbook-description>' : '') +
|
||||
(calendar_description ? '<C:calendar-description>' + calendar_description + '</C:calendar-description>' : '') +
|
||||
(calendar_source ? '<CS:source>' + calendar_source + '</CS:source>' : '') +
|
||||
'</prop>' +
|
||||
'</set>' +
|
||||
(!create ? ('<remove>' +
|
||||
'<prop>' +
|
||||
(!components ? '<C:supported-calendar-component-set />' : '') +
|
||||
(!displayname ? '<displayname />' : '') +
|
||||
(!calendar_color ? '<I:calendar-color />' : '') +
|
||||
(!addressbook_color ? '<INF:addressbook-color />' : '') +
|
||||
(!addressbook_description ? '<CR:addressbook-description />' : '') +
|
||||
(!calendar_description ? '<C:calendar-description />' : '') +
|
||||
'</prop>' +
|
||||
'</remove>') : '') +
|
||||
'</' + xml_request + '>');
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -345,128 +345,171 @@ export function edit_collection(user, password, collection, callback) {
|
||||
}
|
||||
/* Sharing API */
|
||||
|
||||
/**
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {string} path
|
||||
* @param {object} body
|
||||
* @param {function(string):void} on_success
|
||||
* @param {function():void} on_not_found
|
||||
* @param {function(string):void} on_error
|
||||
* @returns {XMLHttpRequest}
|
||||
*/
|
||||
function call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
path,
|
||||
body,
|
||||
on_success,
|
||||
on_not_found = null,
|
||||
on_error = null,
|
||||
) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open(
|
||||
"POST",
|
||||
SERVER + ROOT_PATH + ".sharing/v1/" + path,
|
||||
true,
|
||||
user,
|
||||
encodeURIComponent(password),
|
||||
);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
if (200 <= request.status && request.status < 300) {
|
||||
on_success(request.responseText);
|
||||
} else if (request.status === 404) {
|
||||
if (on_not_found) {
|
||||
on_not_found();
|
||||
} else if (on_error) {
|
||||
on_error("Not found");
|
||||
} else {
|
||||
console.error("Not found");
|
||||
}
|
||||
} else {
|
||||
if (on_error) {
|
||||
on_error(request.status + " " + request.statusText);
|
||||
} else {
|
||||
console.error(request.status + " " + request.statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.setRequestHeader("Accept", "application/json");
|
||||
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
request.send(body ? JSON.stringify(body) : null);
|
||||
return request;
|
||||
password,
|
||||
path,
|
||||
body,
|
||||
on_success,
|
||||
on_not_found = null,
|
||||
on_error = null,
|
||||
) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open(
|
||||
"POST",
|
||||
SERVER + ROOT_PATH + ".sharing/v1/" + path,
|
||||
true,
|
||||
user,
|
||||
encodeURIComponent(password),
|
||||
);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
if (200 <= request.status && request.status < 300) {
|
||||
on_success(request.responseText);
|
||||
} else if (request.status === 404) {
|
||||
if (on_not_found) {
|
||||
on_not_found();
|
||||
} else if (on_error) {
|
||||
on_error("Not found");
|
||||
} else {
|
||||
console.error("Not found");
|
||||
}
|
||||
} else {
|
||||
if (on_error) {
|
||||
on_error(request.status + " " + request.statusText);
|
||||
} else {
|
||||
console.error(request.status + " " + request.statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.setRequestHeader("Accept", "application/json");
|
||||
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
request.send(body ? JSON.stringify(body) : null);
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {function():void} callback
|
||||
*/
|
||||
export function discover_server_features(user, password, callback) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"all/info",
|
||||
{},
|
||||
function (response) {
|
||||
server_features["sharing"] = JSON.parse(response);
|
||||
callback();
|
||||
},
|
||||
function () {
|
||||
// sharing is disabled on the server
|
||||
server_features["sharing"] = {};
|
||||
callback();
|
||||
},
|
||||
function (error) {
|
||||
console.error("Failed to discover sharing features: " + error);
|
||||
},
|
||||
);
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"all/info",
|
||||
{},
|
||||
function (response) {
|
||||
server_features["sharing"] = JSON.parse(response);
|
||||
callback();
|
||||
},
|
||||
function () {
|
||||
// sharing is disabled on the server
|
||||
server_features["sharing"] = {};
|
||||
callback();
|
||||
},
|
||||
function (error) {
|
||||
console.error("Failed to discover sharing features: " + error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {Collection} collection
|
||||
* @param {function(object):void} callback
|
||||
*/
|
||||
export function reload_sharing_list(user, password, collection, callback) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"all/list",
|
||||
{ PathMapped: collection.href },
|
||||
function (response) {
|
||||
callback(JSON.parse(response));
|
||||
},
|
||||
);
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"all/list",
|
||||
{ PathMapped: collection.href },
|
||||
function (response) {
|
||||
callback(JSON.parse(response));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {string} pathMapped
|
||||
* @param {string} permissions
|
||||
* @param {boolean} enabled
|
||||
* @param {boolean} hidden
|
||||
* @param {string} properties
|
||||
* @param {function():void} callback
|
||||
*/
|
||||
export function add_share_by_token(
|
||||
user,
|
||||
password,
|
||||
collection,
|
||||
permissions,
|
||||
callback,
|
||||
) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"token/create",
|
||||
{
|
||||
PathMapped: collection.href,
|
||||
Permissions: permissions,
|
||||
},
|
||||
function (response) {
|
||||
let json_response = JSON.parse(response);
|
||||
if (json_response["Status"] !== "success") {
|
||||
console.error("Failed to create share token: " + (json_response["Status"] || "Unknown error"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
);
|
||||
pathMapped,
|
||||
permissions,
|
||||
enabled,
|
||||
hidden,
|
||||
properties,
|
||||
callback,
|
||||
) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"token/create",
|
||||
{
|
||||
PathMapped: pathMapped,
|
||||
Permissions: permissions,
|
||||
Enabled: enabled,
|
||||
Hidden: hidden,
|
||||
Properties: properties,
|
||||
},
|
||||
function (response) {
|
||||
let json_response = JSON.parse(response);
|
||||
if (json_response["Status"] !== "success") {
|
||||
console.error("Failed to create share token: " + (json_response["Status"] || "Unknown error"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {string} token
|
||||
* @param {function():void} callback
|
||||
*/
|
||||
export function delete_share_by_token(
|
||||
user,
|
||||
password,
|
||||
token,
|
||||
callback,
|
||||
) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"token/delete",
|
||||
{ PathOrToken: token },
|
||||
function (response) {
|
||||
let json_response = JSON.parse(response);
|
||||
if (json_response["Status"] !== "success") {
|
||||
console.error("Failed to create delete token " + token + ": " + (json_response["Status"] || "Unknown error"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
);
|
||||
token,
|
||||
callback,
|
||||
) {
|
||||
call_sharing_api(
|
||||
user,
|
||||
password,
|
||||
"token/delete",
|
||||
{ PathOrToken: token },
|
||||
function (response) {
|
||||
let json_response = JSON.parse(response);
|
||||
if (json_response["Status"] !== "success") {
|
||||
console.error("Failed to create delete token " + token + ": " + (json_response["Status"] || "Unknown error"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user