Support custom types for uploaded files

This commit is contained in:
Zaid Abdulla committed 2021-03-12 15:30:13 -08:00
1 parent 556424d4d6
commit f290ce696f
5 files changed
+79 -7

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
/**
* Copyright 2013-2021 GenieACS Inc.
*
* This file is part of GenieACS.
*
* GenieACS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* GenieACS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
*/
import m, { ClosureComponent, Component, Vnode } from "mithril";
const elements: Map<string, Vnode> = new Map();
// Source: https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
function hash(str: string): number {
let res = 0;
for (let i = 0; i < str.length; ++i) {
const c = str.charCodeAt(i);
res = (res << 5) - res + c;
res |= 0;
}
return res;
}
export function getDatalistId(options: string[]): string {
const id = "datalist" + options.reduce((acc, cur) => acc ^ hash(cur), 0);
if (!elements.has(id)) {
const n = m(
"datalist",
{ id },
options.map((o) => m("option", { value: o }))
);
elements.set(id, n);
}
return id;
}
const component: ClosureComponent = (): Component => {
return {
view: () => {
return [...elements.values()];
},
onupdate: () => {
for (const id of elements.keys()) {
const used = document.querySelector(`[list='${id}']`);
if (!used) elements.delete(id);
}
},
};
};
export default component;
+9 -6
View File
@@ -121,12 +121,15 @@ function renderStagingDownload(task: StageTask): Children {
if (productClass) productClass = decodeURIComponent(productClass); if (productClass) productClass = decodeURIComponent(productClass);
const typesList = [ const typesList = [
"", ...new Set([
"1 Firmware Upgrade Image", "",
"2 Web Content", "1 Firmware Upgrade Image",
"3 Vendor Configuration File", "2 Web Content",
"4 Tone File", "3 Vendor Configuration File",
"5 Ringer File", "4 Tone File",
"5 Ringer File",
...files.value.map((f) => f["metadata.fileType"]).filter((f) => f),
]),
].map((t) => ].map((t) =>
m( m(
"option", "option",
-1
View File
@@ -45,7 +45,6 @@ const attributes: {
{ {
id: "metadata.fileType", id: "metadata.fileType",
label: "Type", label: "Type",
type: "combo",
options: [ options: [
"1 Firmware Upgrade Image", "1 Firmware Upgrade Image",
"2 Web Content", "2 Web Content",
+2
View File
@@ -24,6 +24,7 @@ import userMenu from "./user-menu";
import adminMenu from "./admin-menu"; import adminMenu from "./admin-menu";
import * as overlay from "./overlay"; import * as overlay from "./overlay";
import { version as VERSION } from "../package.json"; import { version as VERSION } from "../package.json";
import datalist from "./datalist";
const adminPages = [ const adminPages = [
"presets", "presets",
@@ -69,6 +70,7 @@ const component: ClosureComponent = (): Component => {
]) ])
), ),
overlay.render(), overlay.render(),
m(datalist),
]; ];
}, },
}; };
+6
View File
@@ -20,6 +20,7 @@
import { VnodeDOM, ClosureComponent, Component, Children } from "mithril"; import { VnodeDOM, ClosureComponent, Component, Children } from "mithril";
import { m } from "./components"; import { m } from "./components";
import codeEditorComponent from "./code-editor-component"; import codeEditorComponent from "./code-editor-component";
import { getDatalistId } from "./datalist";
const singular = { const singular = {
presets: "preset", presets: "preset",
@@ -151,9 +152,14 @@ function createField(current, attr, focus): Children {
}); });
} }
let datalist: string = null;
if (attr.options) datalist = getDatalistId(attr.options);
return m("input", { return m("input", {
type: attr.type === "password" ? "password" : "text", type: attr.type === "password" ? "password" : "text",
name: attr.id, name: attr.id,
list: datalist,
autocomplete: datalist ? "off" : null,
disabled: attr.id === "_id" && !current.isNew, disabled: attr.id === "_id" && !current.isNew,
value: current.object[attr.id], value: current.object[attr.id],
oncreate: focus oncreate: focus