mirror of
https://github.com/mickael-kerjean/filestash
synced 2026-01-05 23:35:34 +01:00
chore (tsc): type check and linter
This commit is contained in:
parent
cdfc614c8b
commit
5a09186770
22 changed files with 124 additions and 68 deletions
|
|
@ -57,13 +57,13 @@ function setup_translation() {
|
|||
selectedLanguage = "zh_tw";
|
||||
break;
|
||||
default:
|
||||
const userLanguage = window.navigator.language.split("-")[0];
|
||||
const userLanguage = window.navigator.language.split("-")[0] || "en";
|
||||
const idx = [
|
||||
"az", "be", "bg", "ca", "cs", "da", "de", "el", "es", "et",
|
||||
"eu", "fi", "fr", "gl", "hr", "hu", "id", "is", "it", "ja",
|
||||
"ka", "ko", "lt", "lv", "mn", "nb", "nl", "pl", "pt", "ro",
|
||||
"ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh"
|
||||
].indexOf(window.navigator.language.split("-")[0]);
|
||||
].indexOf(window.navigator.language.split("-")[0] || "");
|
||||
if (idx !== -1) {
|
||||
selectedLanguage = userLanguage;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const css = await CSS(import.meta.url, "breadcrumb.css");
|
|||
class ComponentBreadcrumb extends HTMLDivElement {
|
||||
constructor() {
|
||||
super();
|
||||
if (new window.URL(location.href).searchParams.get("nav") === "false") return null;
|
||||
if (new window.URL(location.href).searchParams.get("nav") === "false") return;
|
||||
|
||||
const htmlLogout = isRunningFromAnIframe
|
||||
? ""
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { createElement } from "../lib/skeleton/index.js";
|
||||
import { gid } from "../lib/random.js";
|
||||
import { ApplicationError } from "../lib/error.js";
|
||||
|
||||
import "./icon.js";
|
||||
|
||||
|
|
@ -76,7 +77,8 @@ export function $renderInput(options = {}) {
|
|||
class="component_input"
|
||||
/>
|
||||
`);
|
||||
$input.setAttribute("value", value || "");
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
|
||||
if (!datalist) return $input;
|
||||
|
|
@ -94,17 +96,19 @@ export function $renderInput(options = {}) {
|
|||
$datalist.appendChild(new Option(value));
|
||||
});
|
||||
if (!props.multi) return $wrapper;
|
||||
// @ts-ignore
|
||||
$input.refresh = () => {
|
||||
const _datalist = $input.getAttribute("datalist").split(",");
|
||||
const _datalist = $input?.getAttribute("datalist")?.split(",");
|
||||
$datalist.innerHTML = "";
|
||||
multicomplete($input.getAttribute("value"), _datalist).forEach((value) => {
|
||||
$datalist.appendChild(new Option(value));
|
||||
});
|
||||
};
|
||||
$input.oninput = (e) => {
|
||||
$input.oninput = () => {
|
||||
for (const $option of $datalist.children) {
|
||||
$option.remove();
|
||||
}
|
||||
// @ts-ignore
|
||||
$input.refresh();
|
||||
};
|
||||
return $wrapper;
|
||||
|
|
@ -130,7 +134,8 @@ export function $renderInput(options = {}) {
|
|||
class="component_input"
|
||||
/>
|
||||
`);
|
||||
$input.setAttribute("value", value);
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
return $input;
|
||||
}
|
||||
|
|
@ -145,14 +150,16 @@ export function $renderInput(options = {}) {
|
|||
</div>
|
||||
`);
|
||||
const $input = $div.querySelector("input");
|
||||
$input.value = value;
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
|
||||
const $icon = $div.querySelector("component-icon");
|
||||
if ($icon instanceof window.HTMLElement) {
|
||||
$icon.onclick = function(e) {
|
||||
if (!(e.target instanceof window.HTMLElement)) return;
|
||||
const $input = e.target.parentElement.previousElementSibling;
|
||||
const $input = e.target?.parentElement?.previousElementSibling;
|
||||
if (!$input) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
if ($input.getAttribute("type") === "password") $input.setAttribute("type", "text");
|
||||
else $input.setAttribute("type", "password");
|
||||
};
|
||||
|
|
@ -166,7 +173,8 @@ export function $renderInput(options = {}) {
|
|||
rows="8"
|
||||
></textarea>
|
||||
`);
|
||||
$textarea.setAttribute("value", value);
|
||||
if (!($textarea instanceof window.HTMLTextAreaElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $textarea.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($textarea));
|
||||
return $textarea;
|
||||
}
|
||||
|
|
@ -178,7 +186,8 @@ export function $renderInput(options = {}) {
|
|||
readonly
|
||||
/>
|
||||
`);
|
||||
$input.setAttribute("value", value);
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
return $input;
|
||||
}
|
||||
|
|
@ -186,7 +195,8 @@ export function $renderInput(options = {}) {
|
|||
const $input = createElement(`
|
||||
<input type="hidden" />
|
||||
`);
|
||||
$input.setAttribute("value", value);
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
$input.setAttribute("name", path.join("."));
|
||||
return $input;
|
||||
}
|
||||
|
|
@ -208,7 +218,8 @@ export function $renderInput(options = {}) {
|
|||
const $select = createElement(`
|
||||
<select class="component_select"></select>
|
||||
`);
|
||||
$select.setAttribute("value", value || props.default);
|
||||
if (!($select instanceof window.HTMLSelectElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $select.value = value || props.default;
|
||||
attrs.map((setAttribute) => setAttribute($select));
|
||||
(options || []).forEach((name) => {
|
||||
const $option = createElement(`
|
||||
|
|
@ -230,7 +241,8 @@ export function $renderInput(options = {}) {
|
|||
class="component_input"
|
||||
/>
|
||||
`);
|
||||
$input.setAttribute("value", value);
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
return $input;
|
||||
}
|
||||
|
|
@ -241,7 +253,8 @@ export function $renderInput(options = {}) {
|
|||
class="component_input"
|
||||
/>
|
||||
`);
|
||||
$input.setAttribute("value", value);
|
||||
if (!($input instanceof window.HTMLInputElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing input");
|
||||
else if (value) $input.value = value;
|
||||
attrs.map((setAttribute) => setAttribute($input));
|
||||
return $input;
|
||||
}
|
||||
|
|
@ -285,7 +298,7 @@ export function format(name) {
|
|||
if (word.length < 1) {
|
||||
return word;
|
||||
}
|
||||
return word[0].toUpperCase() + word.substring(1);
|
||||
return (word[0] || "").toUpperCase() + word.substring(1);
|
||||
})
|
||||
.join(" ");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class Loader extends window.HTMLElement {
|
|||
this.innerHTML = this.render({
|
||||
inline: this.hasAttribute("inlined"),
|
||||
});
|
||||
}, parseInt(this.getAttribute("delay")) || 0);
|
||||
}, parseInt(this.getAttribute("delay") || "0"));
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ class NotificationComponent extends window.HTMLElement {
|
|||
this.buffer.push({ message, type });
|
||||
if (this.buffer.length !== 1) {
|
||||
const $close = this.querySelector(".close");
|
||||
if ($close && typeof $close.onclick === "function") $close.onclick();
|
||||
if (!($close instanceof window.HTMLElement) || !$close.onclick) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: notification close button missing");
|
||||
$close.onclick(new window.MouseEvent("mousedown"));
|
||||
return;
|
||||
}
|
||||
await this.run();
|
||||
|
|
@ -42,8 +43,14 @@ class NotificationComponent extends window.HTMLElement {
|
|||
});
|
||||
const ids = [];
|
||||
await Promise.race([
|
||||
new Promise((done) => ids.push(window.setTimeout(done, this.buffer.length === 1 ? 8000 : 800))),
|
||||
new Promise((done) => ids.push(window.setTimeout(() => $notification.querySelector(".close").onclick = done, 1000))),
|
||||
new Promise((done) => ids.push(window.setTimeout(() => {
|
||||
done(new window.MouseEvent("mousedown"));
|
||||
}, this.buffer.length === 1 ? 8000 : 800))),
|
||||
new Promise((done) => ids.push(window.setTimeout(() => {
|
||||
const $close = $notification.querySelector(".close");
|
||||
if (!($close instanceof window.HTMLElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: notification close button missing");
|
||||
$close.onclick = done;
|
||||
}, 1000))),
|
||||
]);
|
||||
ids.forEach((id) => window.clearTimeout(id));
|
||||
await animate($notification, {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ async function loadSingleCSS(baseURL, filename) {
|
|||
cache: "force-cache",
|
||||
});
|
||||
if (res.status !== 200) return `/* ERROR: ${res.status} */`;
|
||||
else if (!res.headers.get("Content-Type").startsWith("text/css")) return `/* ERROR: wrong type, got "${res.headers.get("Content-Type")}"*/`;
|
||||
else if (!res.headers.get("Content-Type")?.startsWith("text/css")) `/* ERROR: wrong type, got "${res.headers?.get("Content-Type")}"*/`;
|
||||
return await res.text();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createElement } from "./skeleton/index.js";
|
||||
import { ApplicationError } from "./error.js";
|
||||
import { animate } from "./animate.js";
|
||||
|
||||
export function mutateForm(formSpec, formState) {
|
||||
|
|
@ -7,8 +8,12 @@ export function mutateForm(formSpec, formState) {
|
|||
const keys = inputName.split(".");
|
||||
|
||||
let ptr = formSpec;
|
||||
while (keys.length > 1) ptr = ptr[keys.shift()];
|
||||
const key = keys.shift();
|
||||
while (keys.length > 1) {
|
||||
let k = keys.shift();
|
||||
if (!k) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing key");
|
||||
ptr = ptr[k];
|
||||
}
|
||||
const key = keys.shift() || "";
|
||||
if (ptr && ptr[key]) ptr[key].value = (value === "" ? null : value);
|
||||
});
|
||||
return formSpec;
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
export default function t(str = "", replacementString, requestedKey) {
|
||||
return str;
|
||||
// const calculatedKey = str.toUpperCase()
|
||||
// .replace(/ /g, "_")
|
||||
// .replace(/[^a-zA-Z0-9\-\_\*\{\}\?]/g, "")
|
||||
// .replace(/\_+$/, "");
|
||||
// const value = requestedKey === undefined ?
|
||||
// window.LNG && window.LNG[calculatedKey] :
|
||||
// window.LNG && window.LNG[requestedKey];
|
||||
// return reformat(
|
||||
// value || str || "",
|
||||
// str,
|
||||
// ).replace("{{VALUE}}", replacementString);
|
||||
const calculatedKey = str.toUpperCase()
|
||||
.replace(/ /g, "_")
|
||||
.replace(/[^a-zA-Z0-9\-\_\*\{\}\?]/g, "")
|
||||
.replace(/\_+$/, "");
|
||||
const value = requestedKey === undefined ?
|
||||
window.LNG && window.LNG[calculatedKey] :
|
||||
window.LNG && window.LNG[requestedKey];
|
||||
return reformat(
|
||||
value || str || "",
|
||||
str,
|
||||
).replace("{{VALUE}}", replacementString);
|
||||
}
|
||||
|
||||
// function reformat(translated, initial) {
|
||||
// if (initial[0] && initial[0].toLowerCase() === initial[0]) {
|
||||
// return translated || "";
|
||||
// }
|
||||
// return (translated[0] && translated[0].toUpperCase() + translated.substring(1)) || "";
|
||||
// }
|
||||
function reformat(translated, initial) {
|
||||
if (initial[0] && initial[0].toLowerCase() === initial[0]) {
|
||||
return translated || "";
|
||||
}
|
||||
return (translated[0] && translated[0].toUpperCase() + translated.substring(1)) || "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ describe("router", () => {
|
|||
// then
|
||||
expect(fn).toBeCalled();
|
||||
});
|
||||
xit("trigger a page change when clicking on a link with [data-link] attribute", () => {
|
||||
it("trigger a page change when clicking on a link with [data-link] attribute", () => {
|
||||
// given
|
||||
const fn = jest.fn();
|
||||
const $link = createElement("<a href=\"/something\" data-link></a>");
|
||||
|
|
|
|||
1
public/lib/vendor/bcrypt.js
vendored
1
public/lib/vendor/bcrypt.js
vendored
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-nocheck
|
||||
// code was adapted from https://github.com/dcodeIO/bcrypt.js, meaning:
|
||||
// - we took the code from a CDN https://cdnjs.cloudflare.com/ajax/libs/bcryptjs/2.2.0/bcrypt.js
|
||||
// - remove the amd,commonJS stuff on the top of the file
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { ApplicationError } from "../../lib/error.js";
|
||||
|
||||
class BoxItem extends window.HTMLDivElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
@ -11,12 +13,11 @@ class BoxItem extends window.HTMLDivElement {
|
|||
attributeChangedCallback() {
|
||||
this.innerHTML = this.render({
|
||||
label: this.getAttribute("data-label"),
|
||||
selected: false,
|
||||
});
|
||||
this.classList.add("box-item", "pointer", "no-select");
|
||||
}
|
||||
|
||||
render({ label, selected }) {
|
||||
render({ label }) {
|
||||
return `
|
||||
<div>
|
||||
<strong>${label}</strong>
|
||||
|
|
@ -30,6 +31,7 @@ class BoxItem extends window.HTMLDivElement {
|
|||
toggleSelection(opt = {}) {
|
||||
const { tmpl, isSelected = !this.classList.contains("active") } = opt;
|
||||
const $icon = this.querySelector(".icon");
|
||||
if (!$icon) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: no icon");
|
||||
if (isSelected) {
|
||||
this.classList.add("active");
|
||||
if (tmpl) $icon.innerHTML = tmpl;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { createElement } from "../../lib/skeleton/index.js";
|
|||
import rxjs, { effect, applyMutation, applyMutations, onClick } from "../../lib/rx.js";
|
||||
import { createForm, mutateForm } from "../../lib/form.js";
|
||||
import { qs, qsa } from "../../lib/dom.js";
|
||||
import { ApplicationError } from "../../lib/error.js";
|
||||
import { formTmpl } from "../../components/form.js";
|
||||
import { generateSkeleton } from "../../components/skeleton.js";
|
||||
|
||||
|
|
@ -77,7 +78,10 @@ export default async function(render) {
|
|||
})),
|
||||
rxjs.map((idpState) => [availableSpecs, idpState]),
|
||||
)),
|
||||
rxjs.concatMap(async([availableSpecs, idpState = {}]) => {
|
||||
rxjs.concatMap(async([
|
||||
availableSpecs,
|
||||
idpState = { type: null, params: null },
|
||||
]) => {
|
||||
const { type, params } = idpState;
|
||||
const idps = [];
|
||||
for (const key in availableSpecs) {
|
||||
|
|
@ -167,7 +171,9 @@ export default async function(render) {
|
|||
rxjs.map((connections) => connections.map(({ label }) => label)),
|
||||
rxjs.tap((datalist) => {
|
||||
const $input = $page.querySelector("[name=\"attribute_mapping.related_backend\"]");
|
||||
if (!$input) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: missing related backend");
|
||||
$input.setAttribute("datalist", datalist.join(","));
|
||||
// @ts-ignore
|
||||
$input.refresh();
|
||||
}),
|
||||
));
|
||||
|
|
@ -238,6 +244,7 @@ export default async function(render) {
|
|||
renderLeaf: () => createElement("<label></label>"),
|
||||
}))),
|
||||
rxjs.tap(($node) => {
|
||||
/** @type { Element | undefined} */
|
||||
let $relatedBackendField;
|
||||
$page.querySelectorAll("[data-bind=\"attribute-mapping\"] fieldset").forEach(($el, i) => {
|
||||
if (i === 0) $relatedBackendField = $el;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import rxjs from "../../lib/rx.js";
|
||||
import { qs } from "../../lib/dom.js";
|
||||
import { ApplicationError } from "../../lib/error.js";
|
||||
import { get as getConfig } from "../../model/config.js";
|
||||
import { get as getAdminConfig } from "./model_config.js";
|
||||
import { formObjToJSON$ } from "./helper_form.js";
|
||||
|
|
@ -92,15 +93,18 @@ export function getState() {
|
|||
};
|
||||
if (!authType) return config;
|
||||
|
||||
let formValues = [...new FormData(document.querySelector("[data-bind=\"idp\"]"))];
|
||||
const $formIDP = document.querySelector("[data-bind=\"idp\"]")
|
||||
if (!($formIDP instanceof window.HTMLFormElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: idp isn't a form");
|
||||
let formValues = [...new FormData($formIDP)];
|
||||
config.middleware.identity_provider = {
|
||||
type: authType,
|
||||
params: JSON.stringify(
|
||||
formValues
|
||||
.filter(([key, value]) => key.startsWith(`${authType}.`)) // remove elements that aren't in scope
|
||||
.filter(([key]) => key.startsWith(`${authType}.`)) // remove elements that aren't in scope
|
||||
.map(([key, value]) => [key.replace(new RegExp(`^${authType}\.`), ""), value]) // format the relevant keys
|
||||
.reduce((acc, [key, value]) => { // transform onto something ready to be saved
|
||||
if (key === "type") return acc;
|
||||
else if (typeof key !== "string") return acc;
|
||||
return {
|
||||
...acc,
|
||||
[key]: value,
|
||||
|
|
@ -109,14 +113,16 @@ export function getState() {
|
|||
),
|
||||
};
|
||||
|
||||
formValues = [...new FormData(document.querySelector("[data-bind=\"attribute-mapping\"]"))];
|
||||
const $formAM = document.querySelector("[data-bind=\"attribute-mapping\"]");
|
||||
if (!($formAM instanceof window.HTMLFormElement)) throw new ApplicationError("INTERNAL_ERROR", "assumption failed: attribute mapping isn't a form");
|
||||
formValues = [...new FormData($formAM)];
|
||||
config.middleware.attribute_mapping = {
|
||||
related_backend: formValues.shift()[1],
|
||||
related_backend: (formValues.shift() || [])[1],
|
||||
params: JSON.stringify(formValues.reduce((acc, [key, value]) => {
|
||||
const k = key.split(".");
|
||||
if (k.length !== 2) return acc;
|
||||
if (!acc[k[0]]) acc[k[0]] = {};
|
||||
if (value !== "") acc[k[0]][k[1]] = value;
|
||||
if (!acc[`${k[0]}`]) acc[`${k[0]}`] = {};
|
||||
if (value !== "") acc[`${k[0]}`][`${k[1]}`] = value;
|
||||
return acc;
|
||||
}, {})),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ function updateLoop($page, audit$) {
|
|||
const p = new URLSearchParams();
|
||||
for (const [key, value] of formData.entries()) {
|
||||
if (!value) continue;
|
||||
p.set(key.replace(new RegExp("^search\."), ""), value);
|
||||
p.set(key.replace(new RegExp("^search\."), ""), `${value}`);
|
||||
}
|
||||
return p;
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createElement } from "../../lib/skeleton/index.js";
|
||||
import rxjs from "../../lib/rx.js";
|
||||
|
||||
export function renderLeaf({ format, type, label, description }) {
|
||||
export function renderLeaf({ format, label, description }) {
|
||||
return createElement(`
|
||||
<label class="no-select">
|
||||
<div class="flex">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import rxjs from "../../lib/rx.js";
|
||||
import ajax from "../../lib/ajax.js";
|
||||
|
||||
const sessionSubject$ = new rxjs.Subject(1);
|
||||
const sessionSubject$ = new rxjs.Subject();
|
||||
|
||||
const adminSession$ = rxjs.merge(
|
||||
sessionSubject$,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const log$ = ajax({
|
|||
rxjs.map(({ response }) => response),
|
||||
);
|
||||
|
||||
export function url(logSize = null) {
|
||||
export function url(logSize = 0) {
|
||||
return "/admin/api/logs" + (logSize ? `?maxSize=${logSize}` : "");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function get() {
|
|||
const a = document.createElement("html");
|
||||
a.innerHTML = response;
|
||||
return {
|
||||
html: a.querySelector("table").outerHTML,
|
||||
html: a.querySelector("table")?.outerHTML,
|
||||
version: responseHeaders["x-powered-by"].trim().replace(/^Filestash\/([v\.0-9]*).*$/, "$1")
|
||||
};
|
||||
})
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export default async function(render) {
|
|||
// feature4: insert all the connection form
|
||||
const tmpl = formTmpl({
|
||||
renderNode: () => createElement("<div></div>"),
|
||||
renderLeaf: ({ label, type, format }) => {
|
||||
renderLeaf: ({ label, type }) => {
|
||||
if (type === "enable") {
|
||||
return createElement(`
|
||||
<label class="advanced">
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ export default async function(render) {
|
|||
if (!files[i]) continue;
|
||||
$fs.appendChild(createThing({
|
||||
name: files[i].name,
|
||||
type: files[i].type,
|
||||
size: files[i].size,
|
||||
time: files[i].time,
|
||||
// type: files[i].type,
|
||||
// size: files[i].size,
|
||||
// time: files[i].time,
|
||||
link: (files[i].type === "file" ? "/view" : "/files") + path + files[i].name + (files[i].type === "file" ? "" : "/"),
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,17 +33,17 @@ const $tmpl = createElement(`
|
|||
// drag and drop on other folders and many other non obvious stuff
|
||||
export function createThing({
|
||||
name = null,
|
||||
type = "N/A",
|
||||
size = 0,
|
||||
time = null,
|
||||
// type = "N/A",
|
||||
// size = 0,
|
||||
// time = null,
|
||||
link = "",
|
||||
permissions = {}
|
||||
// permissions = {}
|
||||
}) {
|
||||
const $thing = $tmpl.cloneNode(true);
|
||||
if ($thing instanceof HTMLElement) {
|
||||
const $label = $thing.querySelector(".component_filename .file-details > span");
|
||||
if ($label instanceof HTMLElement) $label.textContent = name;
|
||||
$thing.querySelector("a").setAttribute("href", link);
|
||||
$thing?.querySelector("a")?.setAttribute("href", link);
|
||||
}
|
||||
return $thing;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,21 @@
|
|||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"noEmit": true,
|
||||
"strict": false,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"strictBindCallApply": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strict": false,
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
|
|
@ -14,8 +25,13 @@
|
|||
],
|
||||
"module": "es2022",
|
||||
"target": "es2022",
|
||||
"types": []
|
||||
"typeRoots": [
|
||||
"types/app.d.ts"
|
||||
]
|
||||
},
|
||||
"input": ["pages/ctrl_boot.d.ts", "pages/*.js"],
|
||||
"exclude": ["**/*.test.js", "lib/vendor/bcrypt.js", "worker/sw_cache.js", "coverage", "jest.setup.js"]
|
||||
"exclude": [
|
||||
"**/*.test.js", "worker/sw_cache.js",
|
||||
"coverage", "jest.setup.js"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue