Address Javascript errors

This commit is contained in:
Max Berger
2026-03-08 00:30:25 +01:00
parent 93610213e3
commit 64885fe32e
6 changed files with 88 additions and 58 deletions

8
radicale/web/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Built-in web UI
If you have tsc installed, you can type-check all JavaScript using
``` lang=shell
tsc -p radicale/web/jsconfig.json --noEmit --pretty
```

View File

@@ -42,17 +42,12 @@ export class CreateEditCollectionScene {
/** @type {HTMLElement} */ let title_form = edit ? html_scene.querySelector("[data-name=title]") : null; /** @type {HTMLElement} */ let title_form = edit ? html_scene.querySelector("[data-name=title]") : null;
/** @type {HTMLElement} */ let error_form = html_scene.querySelector("[data-name=error]"); /** @type {HTMLElement} */ let error_form = html_scene.querySelector("[data-name=error]");
/** @type {HTMLInputElement} */ let href_form = html_scene.querySelector("[data-name=href]"); /** @type {HTMLInputElement} */ let href_form = html_scene.querySelector("[data-name=href]");
/** @type {HTMLElement} */ let href_label = html_scene.querySelector("label[for=href]");
/** @type {HTMLInputElement} */ let displayname_form = html_scene.querySelector("[data-name=displayname]"); /** @type {HTMLInputElement} */ let displayname_form = html_scene.querySelector("[data-name=displayname]");
/** @type {HTMLElement} */ let displayname_label = html_scene.querySelector("label[for=displayname]");
/** @type {HTMLInputElement} */ let description_form = html_scene.querySelector("[data-name=description]"); /** @type {HTMLInputElement} */ let description_form = html_scene.querySelector("[data-name=description]");
/** @type {HTMLElement} */ let description_label = html_scene.querySelector("label[for=description]");
/** @type {HTMLInputElement} */ let source_form = html_scene.querySelector("[data-name=source]"); /** @type {HTMLInputElement} */ let source_form = html_scene.querySelector("[data-name=source]");
/** @type {HTMLElement} */ let source_label = html_scene.querySelector("label[for=source]"); /** @type {HTMLElement} */ let source_label = html_scene.querySelector("label[for=source]");
/** @type {HTMLSelectElement} */ let type_form = html_scene.querySelector("[data-name=type]"); /** @type {HTMLSelectElement} */ let type_form = html_scene.querySelector("[data-name=type]");
/** @type {HTMLElement} */ let type_label = html_scene.querySelector("label[for=type]");
/** @type {HTMLInputElement} */ let color_form = html_scene.querySelector("[data-name=color]"); /** @type {HTMLInputElement} */ let color_form = html_scene.querySelector("[data-name=color]");
/** @type {HTMLElement} */ let color_label = html_scene.querySelector("label[for=color]");
/** @type {HTMLElement} */ let submit_btn = html_scene.querySelector("[data-name=submit]"); /** @type {HTMLElement} */ let submit_btn = html_scene.querySelector("[data-name=submit]");
/** @type {HTMLElement} */ let cancel_btn = html_scene.querySelector("[data-name=cancel]"); /** @type {HTMLElement} */ let cancel_btn = html_scene.querySelector("[data-name=cancel]");
@@ -119,7 +114,7 @@ export class CreateEditCollectionScene {
error_form.classList.remove("hidden"); error_form.classList.remove("hidden");
} }
error_form.classList.add("hidden"); error_form.classList.add("hidden");
onTypeChange(); onTypeChange(null);
type_form.addEventListener("change", onTypeChange); type_form.addEventListener("change", onTypeChange);
} }
@@ -173,8 +168,10 @@ export class CreateEditCollectionScene {
return false; return false;
} }
/**
function onTypeChange(e) { * @param {Event} _e
*/
function onTypeChange(_e) {
if (type_form.value == CollectionType.WEBCAL) { if (type_form.value == CollectionType.WEBCAL) {
source_label.classList.remove("hidden"); source_label.classList.remove("hidden");
source_form.classList.remove("hidden"); source_form.classList.remove("hidden");

View File

@@ -21,16 +21,17 @@
import { Scene } from "./scene_manager.js"; import { Scene } from "./scene_manager.js";
/** /**
* @constructor
* @implements {Scene} * @implements {Scene}
*/ */
export function LoadingScene() { export class LoadingScene {
let html_scene = document.getElementById("loadingscene"); constructor() {
this.show = function() { let html_scene = document.getElementById("loadingscene");
html_scene.classList.remove("hidden"); this.show = function () {
}; html_scene.classList.remove("hidden");
this.hide = function() { };
html_scene.classList.add("hidden"); this.hide = function () {
}; html_scene.classList.add("hidden");
this.release = function() {}; };
this.release = function () { };
}
} }

View File

@@ -65,6 +65,7 @@ export function get_principal(user, password, callback) {
"", "",
"", "",
0, 0,
0,
""), null); ""), null);
} else { } else {
callback(null, "Internal error"); callback(null, "Internal error");

View File

@@ -18,21 +18,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** export class CollectionType {
* @enum {string} // Private Fields
*/ static #_PRINCIPAL = "PRINCIPAL";
export const CollectionType = { static #_ADDRESSBOOK = "ADDRESSBOOK";
PRINCIPAL: "PRINCIPAL", static #_CALENDAR_JOURNAL_TASKS = "CALENDAR_JOURNAL_TASKS";
ADDRESSBOOK: "ADDRESSBOOK", static #_CALENDAR_JOURNAL = "CALENDAR_JOURNAL";
CALENDAR_JOURNAL_TASKS: "CALENDAR_JOURNAL_TASKS", static #_CALENDAR_TASKS = "CALENDAR_TASKS";
CALENDAR_JOURNAL: "CALENDAR_JOURNAL", static #_JOURNAL_TASKS = "JOURNAL_TASKS";
CALENDAR_TASKS: "CALENDAR_TASKS", static #_CALENDAR = "CALENDAR";
JOURNAL_TASKS: "JOURNAL_TASKS", static #_JOURNAL = "JOURNAL";
CALENDAR: "CALENDAR", static #_TASKS = "TASKS";
JOURNAL: "JOURNAL", static #_WEBCAL = "WEBCAL";
TASKS: "TASKS",
WEBCAL: "WEBCAL", // Accessors for "get" functions only (no "set" functions)
is_subset: function(a, b) { static get PRINCIPAL() { return this.#_PRINCIPAL; }
static get ADDRESSBOOK() { return this.#_ADDRESSBOOK; }
static get CALENDAR_JOURNAL_TASKS() { return this.#_CALENDAR_JOURNAL_TASKS; }
static get CALENDAR_JOURNAL() { return this.#_CALENDAR_JOURNAL; }
static get CALENDAR_TASKS() { return this.#_CALENDAR_TASKS; }
static get JOURNAL_TASKS() { return this.#_JOURNAL_TASKS; }
static get CALENDAR() { return this.#_CALENDAR; }
static get JOURNAL() { return this.#_JOURNAL; }
static get TASKS() { return this.#_TASKS; }
static get WEBCAL() { return this.#_WEBCAL; }
static is_subset(/** @type {string} */ a, /** @type {string} */ b) {
let components = a.split("_"); let components = a.split("_");
for (let i = 0; i < components.length; i++) { for (let i = 0; i < components.length; i++) {
if (b.search(components[i]) === -1) { if (b.search(components[i]) === -1) {
@@ -40,8 +51,9 @@ export const CollectionType = {
} }
} }
return true; return true;
}, }
union: function(a, b) {
static union(/** @type {string} */ a, /** @type {string} */ b) {
if (a.search(this.ADDRESSBOOK) !== -1 || b.search(this.ADDRESSBOOK) !== -1) { if (a.search(this.ADDRESSBOOK) !== -1 || b.search(this.ADDRESSBOOK) !== -1) {
if (a && a !== this.ADDRESSBOOK || b && b !== this.ADDRESSBOOK) { if (a && a !== this.ADDRESSBOOK || b && b !== this.ADDRESSBOOK) {
throw "Invalid union: " + a + " " + b; throw "Invalid union: " + a + " " + b;
@@ -62,10 +74,14 @@ export const CollectionType = {
union.push(this.WEBCAL); union.push(this.WEBCAL);
} }
return union.join("_"); return union.join("_");
}, }
valid_options_for_type: function(a){
/**
* @param {string} a
*/
static valid_options_for_type(a) {
a = a.trim().toUpperCase(); a = a.trim().toUpperCase();
switch(a){ switch (a) {
case CollectionType.CALENDAR_JOURNAL_TASKS: case CollectionType.CALENDAR_JOURNAL_TASKS:
case CollectionType.CALENDAR_JOURNAL: case CollectionType.CALENDAR_JOURNAL:
case CollectionType.CALENDAR_TASKS: case CollectionType.CALENDAR_TASKS:
@@ -80,24 +96,28 @@ export const CollectionType = {
return [a]; return [a];
} }
} }
}; }
/**
* @constructor export class Collection {
* @struct /**
* @param {string} href Must always start and end with /. * @param {string} href Must always start and end with /.
* @param {CollectionType} type * @param {string} type
* @param {string} displayname * @param {string} displayname
* @param {string} description * @param {string} description
* @param {string} color * @param {string} color
*/ * @param {number} contentcount
export function Collection(href, type, displayname, description, color, contentcount, size, source) { * @param {number} size
this.href = href; * @param {string} source
this.type = type; */
this.displayname = displayname; constructor(href, type, displayname, description, color, contentcount, size, source) {
this.color = color; this.href = href;
this.description = description; this.type = type;
this.source = source; this.displayname = displayname;
this.contentcount = contentcount; this.color = color;
this.size = size; this.description = description;
this.source = source;
this.contentcount = contentcount;
this.size = size;
}
} }

View File

@@ -2,7 +2,10 @@
"compilerOptions": { "compilerOptions": {
"module": "CommonJS", "module": "CommonJS",
"target": "ES6", "target": "ES6",
"checkJs": true "checkJs": true,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}, },
"include": [ "include": [
"internal_data/**/*.js" "internal_data/**/*.js"