chore (eslint): lint frontend

This commit is contained in:
MickaelK
2023-10-14 04:45:13 -07:00
parent afb821b653
commit 32924e8ec8
30 changed files with 156 additions and 174 deletions
+2 -3
View File
@@ -1,5 +1,4 @@
import rxjs, { ajax } from "../lib/rx.js";
import { loadScript, init as initCSS } from "../helpers/loader.js";
import { init as initCSS } from "../helpers/loader.js";
import { report } from "../helpers/log.js";
import { $error } from "./common.js";
@@ -45,5 +44,5 @@ async function setup_history() {
}
async function setup_css() {
return initCSS()
return initCSS();
}
+11 -10
View File
@@ -8,7 +8,9 @@ class ComponentBreadcrumb extends HTMLDivElement {
super();
if (new window.URL(location.href).searchParams.get("nav") === "false") return null;
const htmlLogout = isRunningFromAnIframe ? "" : `
const htmlLogout = isRunningFromAnIframe
? ""
: `
<a href="/logout" data-link>
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODkuODg4IDQ4OS44ODgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ4OS44ODggNDg5Ljg4ODsiPgogIDxwYXRoIGZpbGw9IiM2ZjZmNmYiIGQ9Ik0yNS4zODMsMjkwLjVjLTcuMi03Ny41LDI1LjktMTQ3LjcsODAuOC0xOTIuM2MyMS40LTE3LjQsNTMuNC0yLjUsNTMuNCwyNWwwLDBjMCwxMC4xLTQuOCwxOS40LTEyLjYsMjUuNyAgICBjLTM4LjksMzEuNy02Mi4zLDgxLjctNTYuNiwxMzYuOWM3LjQsNzEuOSw2NSwxMzAuMSwxMzYuOCwxMzguMWM5My43LDEwLjUsMTczLjMtNjIuOSwxNzMuMy0xNTQuNWMwLTQ4LjYtMjIuNS05Mi4xLTU3LjYtMTIwLjYgICAgYy03LjgtNi4zLTEyLjUtMTUuNi0xMi41LTI1LjZsMCwwYzAtMjcuMiwzMS41LTQyLjYsNTIuNy0yNS42YzUwLjIsNDAuNSw4Mi40LDEwMi40LDgyLjQsMTcxLjhjMCwxMjYuOS0xMDcuOCwyMjkuMi0yMzYuNywyMTkuOSAgICBDMTIyLjE4Myw0ODEuOCwzNS4yODMsMzk2LjksMjUuMzgzLDI5MC41eiBNMjQ0Ljg4MywwYy0xOCwwLTMyLjUsMTQuNi0zMi41LDMyLjV2MTQ5LjdjMCwxOCwxNC42LDMyLjUsMzIuNSwzMi41ICAgIHMzMi41LTE0LjYsMzIuNS0zMi41VjMyLjVDMjc3LjM4MywxNC42LDI2Mi44ODMsMCwyNDQuODgzLDB6IiAvPgo8L3N2Zz4K" alt="power">
</a>
@@ -18,18 +20,17 @@ class ComponentBreadcrumb extends HTMLDivElement {
const htmlPathChunks = paths.map((chunk, idx) => {
const label = idx === 0 ? "Filestash" : chunk;
const link = paths.slice(0, idx + 1).join("/") + "/";
const minify = function() {
if (idx === 0) return false;
else if (paths.length <= (document.body.clientWidth > 800 ? 5 : 4)) return false;
else if (idx > paths.length - (document.body.clientWidth > 1000 ? 4 : 3)) return false;
return true;
}();
// const minify = (function() {
// if (idx === 0) return false;
// else if (paths.length <= (document.body.clientWidth > 800 ? 5 : 4)) return false;
// else if (idx > paths.length - (document.body.clientWidth > 1000 ? 4 : 3)) return false;
// return true;
// }());
const limitSize = (word, highlight = false) => {
if (highlight === true && word.length > 30) return word.substring(0, 12).trim() + "..." +
word.substring(word.length - 10, word.length).trim();
if (highlight === true && word.length > 30) { return word.substring(0, 12).trim() + "..." +
word.substring(word.length - 10, word.length).trim(); }
else if (word.length > 27) return word.substring(0, 20).trim() + "...";
return word;
};
const isLast = idx === paths.length - 1;
if (isLast) return `
+2 -2
View File
@@ -214,7 +214,7 @@ export function $renderInput(options = {}) {
`);
$select.value = value || props.default;
attrs.map((setAttribute) => setAttribute($select));
(options || []).map((name) => {
(options || []).forEach((name) => {
const $option = createElement(`
<option></option>
`);
@@ -274,7 +274,7 @@ export function $renderInput(options = {}) {
`);
$input.value = `unknown element type ${type}`;
$input.setAttribute("name", path.join("."));
}}
} }
};
}
+1 -1
View File
@@ -20,7 +20,7 @@ class Loader extends window.HTMLElement {
position: fixed;
left: 0;
right: 0;
top: calc(50% - 200px);`
top: calc(50% - 200px);`;
return `
<div class="component_loader">
<svg width="120px" height="120px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
+4 -4
View File
@@ -2,7 +2,7 @@ import { createElement, nop } from "../lib/skeleton/index.js";
import rxjs, { applyMutation } from "../lib/rx.js";
import { animate } from "../lib/animate.js";
import { qs, qsa } from "../lib/dom.js";
import { ApplicationError } from "../lib/error.js";
import { CSS } from "../helpers/loader.js";
export default class Modal {
@@ -11,7 +11,7 @@ export default class Modal {
}
}
const createModal = async () => createElement(`
const createModal = async() => createElement(`
<div class="component_modal" id="modal-box">
<style>${await CSS(import.meta.url, "modal.css")}</style>
<div>
@@ -35,9 +35,9 @@ class ModalComponent extends window.HTMLElement {
const { onQuit = nop, withButtonsLeft = null, withButtonsRight = null } = opts;
// feature: build the dom
qs($modal, `[data-bind="body"]`).replaceChildren($node);
qs($modal, "[data-bind=\"body\"]").replaceChildren($node);
this.replaceChildren($modal);
qsa($modal, `.component_popup > div.buttons > button`).forEach(($button, i) => {
qsa($modal, ".component_popup > div.buttons > button").forEach(($button, i) => {
let currentLabel = null;
if (i === 0) currentLabel = withButtonsLeft;
else if (i === 1) currentLabel = withButtonsRight;
+2 -6
View File
@@ -3,7 +3,7 @@ import { ApplicationError } from "../lib/error.js";
import { animate, slideYIn, slideYOut } from "../lib/animate.js";
import { CSS } from "../helpers/loader.js";
const createNotification = async (msg, type) => createElement(`
const createNotification = async(msg, type) => createElement(`
<span class="component_notification">
<style>${await CSS(import.meta.url, "notification.css")}</style>
<div class="no-select">
@@ -20,10 +20,6 @@ const createNotification = async (msg, type) => createElement(`
class NotificationComponent extends window.HTMLElement {
buffer = [];
constructor() {
super();
}
async trigger(message, type) {
if (this.buffer.length > 20) this.buffer.pop(); // failsafe
this.buffer.push({ message, type });
@@ -44,7 +40,7 @@ class NotificationComponent extends window.HTMLElement {
keyframes: slideYIn(50),
time: 100,
});
const ids = []
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))),
+2 -2
View File
@@ -1,7 +1,7 @@
export function generateSkeleton(n) {
let tmpl = `<div class="component_skeleton"></div>`;
const tmpl = "<div class=\"component_skeleton\"></div>";
let html = "";
for (let i=0; i<n; i++) {
for (let i = 0; i < n; i++) {
html += tmpl;
}
return html;
+1 -1
View File
@@ -7,7 +7,7 @@ export { onDestroy } from "./lifecycle.js";
let pageLoader;
export default async function($root, routes, opts = {}) {
window.addEventListener("pagechange", async () => {
window.addEventListener("pagechange", async() => {
try {
const route = currentRoute(routes, "");
const [ctrl] = await Promise.all([
+3 -2
View File
@@ -6,7 +6,7 @@
"main": "index.js",
"scripts": {
"check": "tsc && eslint .",
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest"
"test": "npx jest"
},
"author": "Mickael Kerjean",
"license": "AGPL",
@@ -71,7 +71,8 @@
"no-return-assign": ["off"],
"brace-style": ["off"],
"no-useless-escape": ["off"],
"comma-dangle": [0]
"comma-dangle": ["off"],
"curly": ["off"]
}
}
}
+1 -3
View File
@@ -1,5 +1,3 @@
let htmlSelect = "";
class BoxItem extends window.HTMLDivElement {
constructor() {
super();
@@ -31,7 +29,7 @@ class BoxItem extends window.HTMLDivElement {
toggleSelection(opt = {}) {
const { tmpl, isSelected = !this.classList.contains("active") } = opt;
let $icon = this.querySelector(".icon");
const $icon = this.querySelector(".icon");
if (isSelected) {
this.classList.add("active");
if (tmpl) $icon.innerHTML = tmpl;
+1 -1
View File
@@ -18,6 +18,6 @@ export default AdminHOC(async function(render) {
effect(getRelease().pipe(
rxjs.map(({ html }) => html),
stateMutation(qs($page, `[data-bind="about"]`), "innerHTML"),
stateMutation(qs($page, "[data-bind=\"about\"]"), "innerHTML"),
));
});
+2 -2
View File
@@ -19,6 +19,6 @@ export default AdminHOC(async function(render) {
render(transition($page));
await initConfig();
componentStorageBackend(createRender(qs($page, `[data-bind="backend"]`)));
componentAuthenticationMiddleware(createRender(qs($page, `[data-bind="authentication_middleware"]`)));
componentStorageBackend(createRender(qs($page, "[data-bind=\"backend\"]")));
componentAuthenticationMiddleware(createRender(qs($page, "[data-bind=\"authentication_middleware\"]")));
});
@@ -1,18 +1,16 @@
import { createElement } from "../../lib/skeleton/index.js";
import rxjs, { effect, applyMutation, applyMutations, onClick } from "../../lib/rx.js";
import ajax from "../../lib/ajax.js";
import { createForm, mutateForm } from "../../lib/form.js";
import { qs, qsa } from "../../lib/dom.js";
import { formTmpl } from "../../components/form.js";
import { generateSkeleton } from "../../components/skeleton.js";
import { get as getConfig } from "../../model/config.js";
import {
initMiddleware, initStorage, getState,
getMiddlewareAvailable, getMiddlewareEnabled, toggleMiddleware,
getBackendAvailable, getBackendEnabled,
} from "./ctrl_backend_state.js";
import { formObjToJSON$, renderLeaf } from "./helper_form.js";
import { renderLeaf } from "./helper_form.js";
import { get as getAdminConfig, save as saveConfig } from "./model_config.js";
import "./component_box-item.js";
@@ -42,7 +40,7 @@ export default async function(render) {
`))),
rxjs.tap(() => {
qs($page, "h2").classList.remove("hidden");
qs($page, `.box-container`).innerHTML = "";
qs($page, ".box-container").innerHTML = "";
}),
applyMutations(qs($page, ".box-container"), "appendChild"),
rxjs.share(),
@@ -53,10 +51,10 @@ export default async function(render) {
effect(init$.pipe(
rxjs.concatMap(() => getMiddlewareEnabled()),
rxjs.filter((backend) => !!backend),
rxjs.tap((backend) => qsa($page, `[is="box-item"]`).forEach(($button) => {
$button.getAttribute("data-label") === backend ?
$button.classList.add("active") :
$button.classList.remove("active");
rxjs.tap((backend) => qsa($page, "[is=\"box-item\"]").forEach(($button) => {
$button.getAttribute("data-label") === backend
? $button.classList.add("active")
: $button.classList.remove("active");
})),
));
@@ -78,10 +76,10 @@ export default async function(render) {
params: JSON.parse(cfg?.middleware?.identity_provider?.params?.value || "{}"),
})),
)),
rxjs.concatMap(async ([availableSpecs, idpState = {}]) => {
rxjs.concatMap(async([availableSpecs, idpState = {}]) => {
const { type, params } = idpState;
const idps = []
for (let key in availableSpecs) {
const idps = [];
for (const key in availableSpecs) {
let idpSpec = availableSpecs[key];
delete idpSpec.type;
if (key === type) idpSpec = mutateForm(idpSpec, params);
@@ -95,7 +93,7 @@ export default async function(render) {
}
return idps;
}),
applyMutations(qs($page, `[data-bind="idp"]`), "appendChild"),
applyMutations(qs($page, "[data-bind=\"idp\"]"), "appendChild"),
rxjs.share(),
);
effect(setupIDPForm$);
@@ -104,15 +102,15 @@ export default async function(render) {
effect(setupIDPForm$.pipe(
rxjs.concatMap(() => getMiddlewareEnabled()),
rxjs.tap((currentMiddleware) => {
qsa($page, `[data-bind="idp"] .formbuilder`).forEach(($node) => {
$node.getAttribute("id") === currentMiddleware ?
$node.classList.remove("hidden") :
$node.classList.add("hidden");
qsa($page, "[data-bind=\"idp\"] .formbuilder").forEach(($node) => {
$node.getAttribute("id") === currentMiddleware
? $node.classList.remove("hidden")
: $node.classList.add("hidden");
});
const $attrMap = qs($page, `[data-bind="attribute-mapping"]`);
currentMiddleware ?
$attrMap.classList.remove("hidden") :
$attrMap.classList.add("hidden");
const $attrMap = qs($page, "[data-bind=\"attribute-mapping\"]");
currentMiddleware
? $attrMap.classList.remove("hidden")
: $attrMap.classList.add("hidden");
qsa($page, ".box-item").forEach(($button) => {
const $icon = qs($button, ".icon");
@@ -124,20 +122,20 @@ export default async function(render) {
$button.classList.remove("active");
$icon.style.transform = "";
}
})
});
}),
));
// feature: setup the attribute mapping form
const setupAMForm$ = init$.pipe(
rxjs.mapTo({
"attribute_mapping": {
"related_backend": {
"type": "text",
"datalist": [],
"multi": true,
"autocomplete": false,
"value": "",
attribute_mapping: {
related_backend: {
type: "text",
datalist: [],
multi: true,
autocomplete: false,
value: "",
},
// dynamic form here is generated reactively from the value of the "related_backend" field
}
@@ -150,8 +148,8 @@ export default async function(render) {
return spec;
}),
)),
rxjs.concatMap(async (specs) => await createForm(specs, formTmpl({}))),
applyMutation(qs($page, `[data-bind="attribute-mapping"]`), "replaceChildren"),
rxjs.concatMap(async(specs) => await createForm(specs, formTmpl({}))),
applyMutation(qs($page, "[data-bind=\"attribute-mapping\"]"), "replaceChildren"),
rxjs.share(),
);
effect(setupAMForm$);
@@ -160,14 +158,14 @@ export default async function(render) {
effect(setupAMForm$.pipe(
rxjs.switchMap(() => rxjs.merge(
getBackendEnabled(),
rxjs.fromEvent(qs(document, `[data-bind="backend-enabled"]`), "input").pipe(
rxjs.fromEvent(qs(document, "[data-bind=\"backend-enabled\"]"), "input").pipe(
rxjs.debounceTime(500),
rxjs.mergeMap(() => getState().pipe(rxjs.map(({ connections }) => connections))),
),
)),
rxjs.map((connections) => connections.map(({ label }) => label)),
rxjs.tap((datalist) => {
const $input = $page.querySelector(`[name="attribute_mapping.related_backend"]`);
const $input = $page.querySelector("[name=\"attribute_mapping.related_backend\"]");
$input.setAttribute("datalist", datalist.join(","));
$input.refresh();
}),
@@ -177,16 +175,16 @@ export default async function(render) {
effect(setupAMForm$.pipe(
rxjs.switchMap(() => rxjs.merge(
// case 1: user is typing in the related backend field
rxjs.fromEvent(qs($page, `[name="attribute_mapping.related_backend"]`), "input").pipe(
rxjs.fromEvent(qs($page, "[name=\"attribute_mapping.related_backend\"]"), "input").pipe(
rxjs.map((e) => e.target.value),
),
// case 2: user is adding / removing a storage backend
getBackendEnabled().pipe(
rxjs.map(() => qs($page, `[name="attribute_mapping.related_backend"]`).value)
rxjs.map(() => qs($page, "[name=\"attribute_mapping.related_backend\"]").value)
),
// case 3: user is changing the storage backend label
rxjs.fromEvent(qs(document, `[data-bind="backend-enabled"]`), "input").pipe(
rxjs.map(() => qs($page, `[name="attribute_mapping.related_backend"]`).value),
rxjs.fromEvent(qs(document, "[data-bind=\"backend-enabled\"]"), "input").pipe(
rxjs.map(() => qs($page, "[name=\"attribute_mapping.related_backend\"]").value),
),
)),
rxjs.map((value) => value.split(",").map((val) => (val || "").trim()).filter((t) => !!t)),
@@ -194,15 +192,15 @@ export default async function(render) {
rxjs.map(({ connections }) => connections),
rxjs.first(),
rxjs.map((enabledBackends) => inputBackends
.map((label) => enabledBackends.find((b) => b.label === label))
.filter((label) => !!label)),
.map((label) => enabledBackends.find((b) => b.label === label))
.filter((label) => !!label)),
)),
rxjs.mergeMap((backends) => getBackendAvailable().pipe(rxjs.first(), rxjs.map((specs) => {
// we don't want to show the "normal" form but a flat version of it
// so we're getting rid of anything that could make some magic happen like toggle and
// ids which enable those interactions
for (let key in specs) {
for (let input in specs[key]) {
for (const key in specs) {
for (const input in specs[key]) {
if (specs[key][input]["type"] === "enable") {
delete specs[key][input];
} else if ("id" in specs[key][input]) {
@@ -213,11 +211,11 @@ export default async function(render) {
return [backends, specs];
}))),
rxjs.map(([backends, formSpec]) => {
let spec = {};
const spec = {};
backends.forEach(({ label, type }) => {
if (formSpec[type]) spec[label] = JSON.parse(JSON.stringify(formSpec[type]));
});
return spec
return spec;
}),
rxjs.mergeMap((spec) => getAdminConfig().pipe(
rxjs.first(),
@@ -225,9 +223,9 @@ export default async function(render) {
rxjs.map((cfg) => {
// transform the form state from legacy format (= an object struct which was replicating the spec object)
// to the new format which leverage the dom (= or the input name attribute to be precise) to store the entire schema
let state = {};
for (let key1 in cfg) {
for (let key2 in cfg[key1]) {
const state = {};
for (const key1 in cfg) {
for (const key2 in cfg[key1]) {
state[`${key1}.${key2}`] = cfg[key1][key2];
}
}
@@ -235,12 +233,12 @@ export default async function(render) {
}),
)),
rxjs.map(([formSpec, formState]) => mutateForm(formSpec, formState)),
rxjs.mergeMap(async (formSpec) => await createForm(formSpec, formTmpl({
renderLeaf: () => createElement(`<label></label>`),
rxjs.mergeMap(async(formSpec) => await createForm(formSpec, formTmpl({
renderLeaf: () => createElement("<label></label>"),
}))),
rxjs.tap(($node) => {
let $relatedBackendField;
$page.querySelectorAll(`[data-bind="attribute-mapping"] fieldset`).forEach(($el, i) => {
$page.querySelectorAll("[data-bind=\"attribute-mapping\"] fieldset").forEach(($el, i) => {
if (i === 0) $relatedBackendField = $el;
else $el.remove();
});
@@ -6,8 +6,7 @@ import { formTmpl } from "../../components/form.js";
import { generateSkeleton } from "../../components/skeleton.js";
import { initStorage, getState, getBackendAvailable, getBackendEnabled, addBackendEnabled, removeBackendEnabled } from "./ctrl_backend_state.js";
import { formObjToJSON$ } from "./helper_form.js";
import { get as getAdminConfig, save as saveConfig } from "./model_config.js";
import { save as saveConfig } from "./model_config.js";
import "./component_box-item.js";
@@ -26,11 +25,11 @@ export default async function(render) {
// feature: setup the buttons
const init$ = getBackendAvailable().pipe(
rxjs.tap(() => qs($page, `[data-bind="backend-available"]`).innerHTML = ""),
rxjs.tap(() => qs($page, "[data-bind=\"backend-available\"]").innerHTML = ""),
rxjs.mergeMap((specs) => Promise.all(Object.keys(specs).map((label) => createElement(`
<div is="box-item" data-label="${label}"></div>
`)))),
applyMutations(qs($page, `[data-bind="backend-available"]`), "appendChild"),
applyMutations(qs($page, "[data-bind=\"backend-available\"]"), "appendChild"),
rxjs.share(),
);
effect(init$);
@@ -45,10 +44,10 @@ export default async function(render) {
});
return enabledSet;
}),
rxjs.tap((backends) => qsa($page, `[is="box-item"]`).forEach(($button) => {
backends.has($button.getAttribute("data-label")) ?
$button.classList.add("active") :
$button.classList.remove("active");
rxjs.tap((backends) => qsa($page, "[is=\"box-item\"]").forEach(($button) => {
backends.has($button.getAttribute("data-label"))
? $button.classList.add("active")
: $button.classList.remove("active");
})),
));
@@ -63,10 +62,12 @@ export default async function(render) {
// feature: setup form
const setupForm$ = getBackendEnabled().pipe(
// initialise the forms
rxjs.mergeMap((enabled) => Promise.all(enabled.map(({ type, label }) => createForm({ [type]: {
"": { type: "text", placeholder: "Label", value: label },
}}, formTmpl({
renderLeaf: () => createElement(`<label></label>`),
rxjs.mergeMap((enabled) => Promise.all(enabled.map(({ type, label }) => createForm({
[type]: {
"": { type: "text", placeholder: "Label", value: label },
}
}, formTmpl({
renderLeaf: () => createElement("<label></label>"),
renderNode: ({ label, format }) => {
const $fieldset = createElement(`
<fieldset>
@@ -86,15 +87,15 @@ export default async function(render) {
},
}))))),
rxjs.map((nodeList) => {
if (nodeList.length === 0) return [createElement(`
if (nodeList.length === 0) { return [createElement(`
<div class="alert">
You need to select at least 1 storage backend
</div>
`)];
`)]; }
return nodeList;
}),
rxjs.tap(() => qs($page, `[data-bind="backend-enabled"]`).innerHTML = ""),
applyMutations(qs($page, `[data-bind="backend-enabled"]`), "appendChild"),
rxjs.tap(() => qs($page, "[data-bind=\"backend-enabled\"]").innerHTML = ""),
applyMutations(qs($page, "[data-bind=\"backend-enabled\"]"), "appendChild"),
rxjs.share(),
);
effect(setupForm$);
+7 -7
View File
@@ -25,11 +25,11 @@ export function addBackendEnabled(type) {
existingLabels.add(obj.label.toLowerCase());
});
let label = "", i = 1;
let label = ""; let i = 1;
while (true) {
label = type + (i === 1 ? "" : ` ${i}`);
if (existingLabels.has(label) === false) break;
i+=1;
i += 1;
}
const b = backendsEnabled$.value.concat({ type, label });
@@ -74,7 +74,7 @@ export function getState() {
formObjToJSON$(),
rxjs.map((config) => { // connections
const connections = [];
const formData = new FormData(qs(document, `[data-bind="backend-enabled"]`));
const formData = new FormData(qs(document, "[data-bind=\"backend-enabled\"]"));
for (const [type, label] of formData.entries()) {
connections.push({ type, label });
}
@@ -83,8 +83,8 @@ export function getState() {
}),
rxjs.map((config) => { // middleware
const authType = document
.querySelector(`[data-bind="authentication_middleware"] [is="box-item"].active`)
?.getAttribute("data-label");
.querySelector("[data-bind=\"authentication_middleware\"] [is=\"box-item\"].active")
?.getAttribute("data-label");
config.middleware = {
identity_provider: { type: null },
@@ -92,7 +92,7 @@ export function getState() {
};
if (!authType) return config;
let formValues = [...new FormData(document.querySelector(`[data-bind="idp"]`))];
let formValues = [...new FormData(document.querySelector("[data-bind=\"idp\"]"))];
config.middleware.identity_provider = {
type: authType,
params: JSON.stringify(
@@ -109,7 +109,7 @@ export function getState() {
),
};
formValues = [...new FormData(document.querySelector(`[data-bind="attribute-mapping"]`))];
formValues = [...new FormData(document.querySelector("[data-bind=\"attribute-mapping\"]"))];
config.middleware.attribute_mapping = {
related_backend: formValues.shift()[1],
params: JSON.stringify(formValues.reduce((acc, [key, value]) => {
+1 -1
View File
@@ -7,7 +7,7 @@ import componentAuditor from "./ctrl_log_audit.js";
import transition from "./animate.js";
import AdminHOC from "./decorator.js";
export default AdminHOC(async function (render) {
export default AdminHOC(async function(render) {
const $page = createElement(`
<div class="component_logpage sticky">
<h2>Logging</h2>
+2 -2
View File
@@ -34,7 +34,7 @@ export default function(render) {
effect(setup$.pipe(
rxjs.first(),
rxjs.tap(() => updateLoop($page, audit$)),
))
));
}
function updateLoop($page, audit$) {
@@ -47,7 +47,7 @@ function updateLoop($page, audit$) {
// feature2: update to the query form
effect(rxjs.of(null).pipe(
useForm$(() => qsa($page, `form [name]`)),
useForm$(() => qsa($page, "form [name]")),
rxjs.tap(() => setLoader(true)),
rxjs.debounceTime(1000),
rxjs.first(),
+2 -2
View File
@@ -33,7 +33,7 @@ export default function(render) {
// feature2: form change
effect(setup$.pipe(
useForm$(() => qsa($form, `[name]`)),
useForm$(() => qsa($form, "[name]")),
rxjs.combineLatestWith(getAdminConfig().pipe(rxjs.first())),
rxjs.map(([formState, formSpec]) => {
const fstate = Object.fromEntries(Object.entries(formState).map(([key, value]) => ([
@@ -50,7 +50,7 @@ export default function(render) {
}),
saveConfig(),
rxjs.catchError((err) => {
notification.error(err && err.message || t("Oops"));
notification.error((err && err.message) || t("Oops"));
return rxjs.EMPTY;
}),
));
+1 -1
View File
@@ -43,7 +43,7 @@ export default async function(render) {
rxjs.switchMap((creds) => authenticate$(creds).pipe(
rxjs.catchError((err) => {
if (err instanceof AjaxError) {
switch(err.code()) {
switch (err.code()) {
case "INTERNAL_SERVER_ERROR":
ctrlError(err)(render);
return rxjs.EMPTY;
+4 -4
View File
@@ -4,7 +4,6 @@ import { qs, qsa } from "../../lib/dom.js";
import { createForm, mutateForm } from "../../lib/form.js";
import { formTmpl } from "../../components/form.js";
import { generateSkeleton } from "../../components/skeleton.js";
import notification from "../../components/notification.js";
import { get as getConfig } from "../../model/config.js";
import { get as getAdminConfig, save as saveConfig, initConfig } from "./model_config.js";
@@ -39,21 +38,22 @@ export default AdminHOC(async function(render) {
</div>
`);
},
renderLeaf, autocomplete: false,
renderLeaf,
autocomplete: false,
});
// feature: setup the form
const init$ = config$.pipe(
rxjs.mergeMap((formSpec) => createForm(formSpec, tmpl)),
rxjs.map(($form) => [$form]),
applyMutation(qs($container, `[data-bind="form"]`), "replaceChildren"),
applyMutation(qs($container, "[data-bind=\"form\"]"), "replaceChildren"),
rxjs.share(),
);
effect(init$);
// feature: handle form change
effect(init$.pipe(
useForm$(() => qsa($container, `[data-bind="form"] [name]`)),
useForm$(() => qsa($container, "[data-bind=\"form\"] [name]")),
rxjs.combineLatestWith(config$.pipe(rxjs.first())),
rxjs.map(([formState, formSpec]) => mutateForm(formSpec, formState)),
reshapeConfigBeforeSave,
+11 -12
View File
@@ -1,5 +1,5 @@
import { createElement, createRender, onDestroy } from "../../lib/skeleton/index.js";
import rxjs, { effect, stateMutation, applyMutation, preventDefault } from "../../lib/rx.js";
import { createElement, createRender } from "../../lib/skeleton/index.js";
import rxjs, { effect, applyMutation, preventDefault } from "../../lib/rx.js";
import { qs } from "../../lib/dom.js";
import { ApplicationError } from "../../lib/error.js";
import { transition, animate, zoomIn, slideXOut, slideXIn } from "../../lib/animate.js";
@@ -35,7 +35,7 @@ export default async function(render) {
else if (step === 2) return WithShell(componentStep2);
throw new ApplicationError("INTERNAL_ERROR", "Assumption failed");
}),
rxjs.tap((ctrl) => ctrl(createRender(qs($page, `[data-bind="multistep-form"]`)))),
rxjs.tap((ctrl) => ctrl(createRender(qs($page, "[data-bind=\"multistep-form\"]")))),
rxjs.catchError((err) => ctrlError(err)(render)),
));
};
@@ -92,10 +92,9 @@ const reshapeConfigBeforeSave = rxjs.pipe(
config["connections"] = publicConfig["connections"];
return config;
}),
)
);
function componentStep2(render) {
const deps = [];
const $page = createElement(`
<div id="step2">
<h4>
@@ -112,7 +111,7 @@ function componentStep2(render) {
effect(getDeps().pipe(
rxjs.mergeMap((deps) => deps),
rxjs.map(({ name_success, name_failure, pass, severe, message }) => ({
className: (severe ? "severe" : "") + " " +(pass ? "yes" : "no"),
className: (severe ? "severe" : "") + " " + (pass ? "yes" : "no"),
label: pass ? name_success : name_failure,
extraLabel: pass ? "" : ": " + message,
})),
@@ -121,11 +120,11 @@ function componentStep2(render) {
<span>${label}</span>${extraLabel}
</div>
`)),
applyMutation(qs($page, `[data-bind="dependencies"]`), "appendChild"),
))
applyMutation(qs($page, "[data-bind=\"dependencies\"]"), "appendChild"),
));
// feature: navigate previous step
effect(rxjs.fromEvent(qs($page, `[data-bind="previous"]`), "click").pipe(
effect(rxjs.fromEvent(qs($page, "[data-bind=\"previous\"]"), "click").pipe(
rxjs.tap(() => stepper$.next(1))
));
@@ -162,12 +161,12 @@ function componentStep2(render) {
withButtonsRight: "OK",
onQuit: () => next(config),
});
qs($modal, `[type="checkbox"]`).oninput = (e) => {
qs($modal, "[type=\"checkbox\"]").oninput = (e) => {
if (!e.target.checked) return;
qs(document, "component-modal > div").click();
}
};
})),
rxjs.filter(() => qs($modal, `[type="checkbox"]`).checked),
rxjs.filter(() => qs($modal, "[type=\"checkbox\"]").checked),
rxjs.map((config) => {
config["log"]["telemetry"] = true;
return config;
+3 -3
View File
@@ -6,7 +6,7 @@ import "../../components/loader.js";
export default function HOC(ctrlPage) {
const ctrlLoading = (render) => {
render(createElement(`<component-loader inlined></component-loader>`));
render(createElement("<component-loader inlined></component-loader>"));
};
return (render) => {
@@ -14,6 +14,6 @@ export default function HOC(ctrlPage) {
return (render) => {
WithShell(ctrlLoading)(render);
}
}
};
};
}
+5 -5
View File
@@ -26,14 +26,14 @@ export function useForm$($inputNodeList) {
rxjs.mergeMap(($el) => rxjs.fromEvent($el, "input")),
rxjs.map((e) => ({
name: e.target.getAttribute("name"),
value: function() {
switch(e.target.getAttribute("type")) {
value: (function() {
switch (e.target.getAttribute("type")) {
case "checkbox":
return e.target.checked;
default:
return e.target.value;
}
}(),
}()),
})),
rxjs.scan((store, keyValue) => {
store[keyValue.name] = keyValue.value;
@@ -45,7 +45,7 @@ export function useForm$($inputNodeList) {
export function formObjToJSON$() {
const formObjToJSON = (o, level = 0) => {
const obj = Object.assign({}, o);
Object.keys(obj).map((key) => {
Object.keys(obj).forEach((key) => {
const t = obj[key];
if ("label" in t && "type" in t && "default" in t && "value" in t) {
obj[key] = obj[key].value;
@@ -54,6 +54,6 @@ export function formObjToJSON$() {
}
});
return obj;
}
};
return rxjs.map(formObjToJSON);
}
-1
View File
@@ -1,5 +1,4 @@
import rxjs from "../../lib/rx.js";
import ajax from "../../lib/ajax.js";
import { getBackends as _getBackends } from "../../model/backend.js";
import { isSaving } from "./model_config.js";
+1 -1
View File
@@ -12,7 +12,7 @@ const config$ = isSaving$.pipe(
})),
rxjs.map((res) => res.responseJSON.result),
rxjs.shareReplay(1),
)
);
export async function initConfig() {
if (isSaving$.value === true) isSaving$.next(false);
+1 -1
View File
@@ -2,7 +2,7 @@ import rxjs from "../../lib/rx.js";
import ajax from "../../lib/ajax.js";
const log$ = ajax({
url: url(1024*100), // fetch the last 100kb by default
url: url(1024 * 100), // fetch the last 100kb by default
responseType: "text",
}).pipe(
rxjs.map(({ response }) => response),
+20 -20
View File
@@ -7,29 +7,29 @@ export function getDeps() {
formObjToJSON$(),
rxjs.map(({ constant }) => ([
{
"name_success": "SSL is configured properly",
"name_failure": "SSL is not configured properly",
"pass": window.location.protocol !== "http:",
"severe": true,
"message": "This can lead to data leaks. Please use a SSL certificate",
name_success: "SSL is configured properly",
name_failure: "SSL is not configured properly",
pass: window.location.protocol !== "http:",
severe: true,
message: "This can lead to data leaks. Please use a SSL certificate",
}, {
"name_success": "Application is running as '" + constant.user.value + "'",
"name_failure": "Application is running as root",
"pass": constant.user !== "root",
"severe": true,
"message": "This is dangerous, you should use another user with less privileges",
name_success: "Application is running as '" + constant.user.value + "'",
name_failure: "Application is running as root",
pass: constant.user !== "root",
severe: true,
message: "This is dangerous, you should use another user with less privileges",
}, {
"name_success": "Emacs is installed",
"name_failure": "Emacs is not installed",
"pass": !!constant.emacs,
"severe": false,
"message": "If you want to use all the org-mode features of Filestash, you need to install emacs",
name_success: "Emacs is installed",
name_failure: "Emacs is not installed",
pass: !!constant.emacs,
severe: false,
message: "If you want to use all the org-mode features of Filestash, you need to install emacs",
}, {
"name_success": "Pdftotext is installed",
"name_failure": "Pdftotext is not installed",
"pass": !!constant.pdftotext,
"severe": false,
"message": "You won't be able to search through PDF documents without it",
name_success: "Pdftotext is installed",
name_failure: "Pdftotext is not installed",
pass: !!constant.pdftotext,
severe: false,
message: "You won't be able to search through PDF documents without it",
},
])),
);
+2 -2
View File
@@ -34,13 +34,13 @@ export default function(err) {
render($page);
// feature: show error details
effect(rxjs.fromEvent(qs($page, `button[data-bind="details"]`), "click").pipe(
effect(rxjs.fromEvent(qs($page, "button[data-bind=\"details\"]"), "click").pipe(
rxjs.mapTo(["hidden"]),
applyMutation(qs($page, "pre"), "classList", "toggle")
));
// feature: refresh button
effect(rxjs.fromEvent(qs($page, `button[data-bind="refresh"]`), "click").pipe(
effect(rxjs.fromEvent(qs($page, "button[data-bind=\"refresh\"]"), "click").pipe(
rxjs.tap(() => location.reload())
));
-10
View File
@@ -14,13 +14,3 @@ export default function(render) {
`);
render($page);
}
const tmp = () => {
const { previous } = history.state;
if (!previous) return;
const path = previous.split("/").slice(2)
};
const cleanupPath = (path = "") => path.split("/").slice(2);
+1 -1
View File
@@ -32,7 +32,7 @@ export default async function(render) {
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" ? "" : "/"),
link: (files[i].type === "file" ? "/view" : "/files") + path + files[i].name + (files[i].type === "file" ? "" : "/"),
}));
}
qs($page, ".list").appendChild($fs);