diff options
Diffstat (limited to 'html')
-rw-r--r-- | html/DOM_helpers.js | 2 | ||||
-rw-r--r-- | html/base.css | 82 | ||||
-rw-r--r-- | html/dialog.html | 72 | ||||
-rw-r--r-- | html/dialog.js | 112 | ||||
-rw-r--r-- | html/grid.css | 75 | ||||
-rw-r--r-- | html/item_list.html | 61 | ||||
-rw-r--r-- | html/item_list.js | 189 | ||||
-rw-r--r-- | html/item_preview.html | 89 | ||||
-rw-r--r-- | html/item_preview.js | 151 |
9 files changed, 766 insertions, 67 deletions
diff --git a/html/DOM_helpers.js b/html/DOM_helpers.js index 55320cb..88092e5 100644 --- a/html/DOM_helpers.js +++ b/html/DOM_helpers.js @@ -70,7 +70,7 @@ function clone_template(template_id) while (to_process.length > 0) { const element = to_process.pop(); - const template_key = element.getAttribute("data-template"); + let template_key = element.getAttribute("data-template") || element.id; if (template_key) result_object[template_key] = element; diff --git a/html/base.css b/html/base.css index dde50e7..6085f5f 100644 --- a/html/base.css +++ b/html/base.css @@ -34,101 +34,51 @@ body { overflow: auto; } -.bold, h2 { +.bold, h1, h2, h3 { font-weight: bold; } +h1, h2, h3 { + margin: 0.3em; + text-shadow: 0 0 0 #454; +} + h2 { - margin: 8px; font-size: 120%; } h3 { - padding: 5px; font-size: 108%; - text-shadow: 0 0 0 #454; } -textarea { - font-family: monospace; +li { + margin-top: 0.25em; + margin-bottom: 0.25em; } -input[type="checkbox"], input[type="radio"], .hide { - display: none; -} - -.camouflage { - visibility: hidden; +li:first-child { + margin-top: 0; } -.show_next:not(:checked)+* { +.hide { display: none; } -.show_hide_next2:not(:checked)+* { - display: none; -} - -.show_hide_next2:checked+*+* { - display: none; -} - -button, .button { +button { background-color: #4CAF50; border: none; - border-radius: 8px; + border-radius: 0.4em; color: white; text-align: center; text-decoration: none; display: inline-block; - padding: 6px 12px; - margin: 2px 0px; + padding: 0.4em 0.8em; -moz-user-select: none; user-select: none; cursor: pointer; - font: 400 15px sans-serif; -} - -button.slimbutton, .button.slimbutton { - padding: 2px 4px; - margin: 0; + font: 400 0.9em sans-serif; } button:hover, .button:hover { box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); } - -aside { - background: #3f8dc6; - margin: 5px 0; - padding: 0.3em 1em; - border-radius: 3px; - color: #fff; -} - -textarea: { - resize: none; -} - -.has_bottom_line::after, .has_upper_line::before { - content: ""; - display: block; - height: 8px; - background: linear-gradient(transparent, #555); -} - -.has_bottom_line::after { - background: linear-gradient(#555, transparent); -} - -.has_bottom_thin_line { - border-bottom: dashed #4CAF50 1px; -} - -.has_upper_thin_line { - border-top: dashed #4CAF50 1px; -} - -.nowrap { - white-space: nowrap; -} diff --git a/html/dialog.html b/html/dialog.html new file mode 100644 index 0000000..d4e69b9 --- /dev/null +++ b/html/dialog.html @@ -0,0 +1,72 @@ +#IF !DIALOG_LOADED +#DEFINE DIALOG_LOADED +<!-- + SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + + Show an error/info/question dalog. + + This file is part of Haketilo. + + Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org> + + File is dual-licensed. You can choose either GPLv3+, CC BY-SA or both. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + I, Wojtek Kosior, thereby promise not to sue for violation of this file's + licenses. Although I request that you do not make use of this code in a + proprietary program, I am not going to enforce this in court. + --> + +<!-- + This is not a standalone page. This file is meant to be imported into other + HTML code. + --> + +#LOADCSS html/reset.css +#LOADCSS html/base.css +<style> + .left_space { + margin-left: 3em; + } + .right_space { + margin-right: 3em; + } + .dialog_buts { + margin-right: auto; + margin-left: auto; + max-width: -moz-fit-content; + max-width: fit-content; + } + .dialog_msg { + margin-bottom: 2em; + text-align: center; + } + .dialog_main_div { + margin: 1.4em; + } +</style> +<template> + <div id="dialog" data-template="main_div" class="dialog_main_div"> + <div data-template="msg" class="dialog_msg"></div> + <div data-template="ask_buts" class="dialog_buts"> + <button data-template="yes_but" class="right_space">Yes</button> + <button data-template="no_but" class="left_space">No</button> + </div> + <div data-template="conf_buts" class="dialog_buts"> + <button data-template="ok_but">Ok</button> + </div> + </div> +</template> +#ENDIF diff --git a/html/dialog.js b/html/dialog.js new file mode 100644 index 0000000..6345b2d --- /dev/null +++ b/html/dialog.js @@ -0,0 +1,112 @@ +/** + * This file is part of Haketilo. + * + * Function: Showing and error/info/confirmation dialog. + * + * Copyright (C) 2022 Wojtek Kosior + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * As additional permission under GNU GPL version 3 section 7, you + * may distribute forms of that code without the copy of the GNU + * GPL normally required by section 4, provided you include this + * license notice and, in case of non-source distribution, a URL + * through which recipients can access the Corresponding Source. + * If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * As a special exception to the GPL, any HTML file which merely + * makes function calls to this code, and for that purpose + * includes it by reference shall be deemed a separate work for + * copyright law purposes. If you modify this code, you may extend + * this exception to your version of the code, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * I, Wojtek Kosior, thereby promise not to sue for violation of this file's + * license. Although I request that you do not make use of this code in a + * proprietary program, I am not going to enforce this in court. + */ + +#FROM html/DOM_helpers.js IMPORT clone_template +#FROM common/lock.js IMPORT make_lock, lock, unlock + +function make(on_dialog_show, on_dialog_hide) +{ + const dialog_context = clone_template("dialog"); + Object.assign(dialog_context, { + on_dialog_show, + on_dialog_hide, + shown: false, + queue: 0, + lock: make_lock(), + callback: null + }); + + for (const [id, val] of [["yes", true], ["no", false], ["ok", undefined]]) { + const but = dialog_context[`${id}_but`]; + but.haketilo_dialog_result = val; + but.addEventListener("click", e => close_dialog(dialog_context, e)); + } + + return dialog_context; +} +#EXPORT make + +function close_dialog(dialog_context, event) +{ + if (dialog_context.queue > 0) + dialog_context.callback(event.target.haketilo_dialog_result); +} + +async function show_dialog(dialog_context, shown_buts_id, msg) +{ + dialog_context.queue++; + + if (!dialog_context.shown) { + dialog_context.shown = true; + dialog_context.on_dialog_show(); + } + + await lock(dialog_context.lock); + + dialog_context.msg.innerText = msg; + for (const buts_id of ["ask_buts", "conf_buts"]) { + const action = buts_id == shown_buts_id ? "remove" : "add"; + dialog_context[buts_id].classList[action]("hide"); + } + + const result = await new Promise(cb => dialog_context.callback = cb); + + if (--dialog_context.queue == 0) { + dialog_context.shown = false; + dialog_context.on_dialog_hide(); + } + + unlock(dialog_context.lock); + + return result; +} + +const error = (ctx, msg) => show_dialog(ctx, "conf_buts", msg); +#EXPORT error + +/* info() and error() are the same for now, we might later change that. */ +const info = error; +#EXPORT info + +const ask = (ctx, msg) => show_dialog(ctx, "ask_buts", msg); +#EXPORT ask diff --git a/html/grid.css b/html/grid.css new file mode 100644 index 0000000..59b5bb7 --- /dev/null +++ b/html/grid.css @@ -0,0 +1,75 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + * + * Styling for use with `display: grid`. + * + * This file is part of Haketilo. + * + * Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org> + * + * File is dual-licensed. You can choose either GPLv3+, CC BY-SA or both. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * I, Wojtek Kosior, thereby promise not to sue for violation of this file's + * licenses. Although I request that you do not make use of this code in a + * proprietary program, I am not going to enforce this in court. + */ + +.grid_2 { + display: grid; + grid-template-columns: 1fr 1fr; +} + +.grid_col_1 { + grid-column: 1 / span 1; +} + +.grid_col_2 { + grid-column: 2 / span 1; +} + +.grid_col_both { + grid-column: 1 / span 2; +} + +span.grid_col_1 { + text-align: right; +} + +.grid_col_both { + text-align: center; +} + +div.grid_col_both { + text-align: initial; +} + +.grid_2>span { + margin-top: 0.75em; +} + +.grid_form>span { + margin-top: 1.5em; + margin-left: 1em; + margin-right: 1em; +} + +.grid_form>span { + font-weight: bold; +} + +span.grid_col_2 { + font-weight: initial; +} diff --git a/html/item_list.html b/html/item_list.html new file mode 100644 index 0000000..41c7734 --- /dev/null +++ b/html/item_list.html @@ -0,0 +1,61 @@ +#IF !ITEM_LIST_LOADED +#DEFINE ITEM_LIST_LOADED +<!-- + SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + + Show a list of resources/mappings. + + This file is part of Haketilo. + + Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org> + + File is dual-licensed. You can choose either GPLv3+, CC BY-SA or both. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + I, Wojtek Kosior, thereby promise not to sue for violation of this file's + licenses. Although I request that you do not make use of this code in a + proprietary program, I am not going to enforce this in court. + --> + +<!-- + This is not a standalone page. This file is meant to be imported into other + HTML code. + --> + +#INCLUDE html/item_preview.html +#INCLUDE html/dialog.html + +#LOADCSS html/reset.css +#LOADCSS html/base.css +#LOADCSS html/grid.css +<style> + .item_li_highlight { + background-color: #c0c0c0; + } +</style> +<template> + <div id="item_list" data-template="main_div" class="grid_2"> + <ul data-template="ul"></ul> + <div data-template="preview_container"> + <!-- preview div will be dynamically inserted here --> + + <button data-template="remove_but">Remove</button> + <!--<button data-template="export_but">Export</button>--> + </div> + <div data-template="dialog_container" class="hide"> + </div> + </div> +</template> +#ENDIF diff --git a/html/item_list.js b/html/item_list.js new file mode 100644 index 0000000..f6b9bd3 --- /dev/null +++ b/html/item_list.js @@ -0,0 +1,189 @@ +/** + * This file is part of Haketilo. + * + * Function: Showing a list of resources/mappings in a browser. + * + * Copyright (C) 2022 Wojtek Kosior + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * As additional permission under GNU GPL version 3 section 7, you + * may distribute forms of that code without the copy of the GNU + * GPL normally required by section 4, provided you include this + * license notice and, in case of non-source distribution, a URL + * through which recipients can access the Corresponding Source. + * If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * As a special exception to the GPL, any HTML file which merely + * makes function calls to this code, and for that purpose + * includes it by reference shall be deemed a separate work for + * copyright law purposes. If you modify this code, you may extend + * this exception to your version of the code, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * I, Wojtek Kosior, thereby promise not to sue for violation of this file's + * license. Although I request that you do not make use of this code in a + * proprietary program, I am not going to enforce this in court. + */ + +#IMPORT common/indexeddb.js AS haketilodb +#IMPORT html/dialog.js + +#FROM html/item_preview.js IMPORT resource_preview, mapping_preview +#FROM html/DOM_helpers.js IMPORT clone_template + +function preview_item(list_ctx, item, ignore_dialog=false) +{ + if (list_ctx.dialog_ctx.shown && !ignore_dialog) + return; + + list_ctx.preview_ctx = + list_ctx.preview_cb(item.definition, list_ctx.preview_ctx); + list_ctx.preview_container + .prepend(list_ctx.preview_ctx.main_div); + + if (list_ctx.previewed_item !== null) + list_ctx.previewed_item.li.classList.remove("item_li_highlight"); + + list_ctx.previewed_item = item; + item.li.classList.add("item_li_highlight"); + + list_ctx.preview_container.classList.remove("hide"); +} + +function insert_item(list_ctx, definition, idx) +{ + const li = document.createElement("li"); + li.innerText = definition.long_name; + if (idx) + list_ctx.items[idx - 1].li.after(li); + else + list_ctx.ul.prepend(li); + + const item = {definition, li}; + list_ctx.items.splice(idx, 0, item); + list_ctx.by_identifier.set(definition.identifier, item); + + li.addEventListener("click", () => preview_item(list_ctx, item)); + + return item; +} + +const coll = new Intl.Collator(); + +function item_cmp(def1, def2) +{ + return coll.compare(def1.long_name, def2.long_name) || + coll.compare(def1.identifier, def2.identifier); +} + +function find_item_idx(definition) +{ + /* Perform a binary search of item's (new or not) index in sorted array. */ + let left = 0, right = list_ctx.items.length; + + while (left < right) { + const mid = (left + right) >> 1; + if (item_cmp(definition, list_ctx.items[mid].definition) > 0) + left = mid + 1; + else /* <= 0 */ + right = mid; + } + + return left; +} + +function item_changed(list_ctx, change) +{ + + /* Remove item. */ + const old_item = list_ctx.by_identifier.get(change.key); + if (old_item !== undefined) { + list_ctx.items.splice(find_item_idx(old_item.definition), 1); + list_ctx.by_identifier.delete(change.key); + old_item.li.remove(); + + if (list_ctx.previewed_item === old_item) { + list_ctx.preview_container.classList.add("hide"); + list_ctx.previewed_item = null; + } + } + + if (change.new_val === undefined) + return; + + const new_item = insert_item(list_ctx, change.new_val, + find_item_idx(change.new_val)); + if (list_ctx.previewed_item === old_item) + preview_item(list_ctx, new_item, true); +} + +async function item_list(preview_cb, track_cb) +{ + const list_ctx = clone_template("item_list"); + + const [tracking, definitions] = + await track_cb(ch => item_changed(list_ctx, ch)); + + definitions.sort(item_cmp); + + Object.assign(list_ctx, { + items: [], + by_identifier: new Map(), + tracking, + previewed_item: null, + preview_cb, + dialog_ctx: dialog.make(() => on_dialog_show(list_ctx), + () => on_dialog_hide(list_ctx)) + }); + list_ctx.dialog_container.append(list_ctx.dialog_ctx.main_div); + + for (const def of definitions) + insert_item(list_ctx, def, list_ctx.items.length); + + return list_ctx; +} + +function on_dialog_show(list_ctx) +{ + list_ctx.ul; + list_ctx.preview_container.classList.add("hide"); + list_ctx.dialog_container.classList.remove("hide"); +} + +function on_dialog_hide(list_ctx) +{ + list_ctx.ul; + list_ctx.preview_container.classList.remove("hide"); + list_ctx.dialog_container.classList.add("hide"); +} + +const resource_list = + () => item_list(resource_preview, haketilodb.track.resources); +#EXPORT resource_list + +const mapping_list = + () => item_list(mapping_preview, haketilodb.track.mappings); +#EXPORT mapping_list + +function destroy_list(list_ctx) +{ + haketilodb.untrack(list_ctx.tracking); + list_ctx.main_div.remove(); +} +#EXPORT destroy_list diff --git a/html/item_preview.html b/html/item_preview.html new file mode 100644 index 0000000..76c6da6 --- /dev/null +++ b/html/item_preview.html @@ -0,0 +1,89 @@ +#IF !ITEM_PREVIEW_LOADED +#DEFINE ITEM_PREVIEW_LOADED +<!-- + SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + + Show preview of a resource/mapping. + + This file is part of Haketilo. + + Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org> + + File is dual-licensed. You can choose either GPLv3+, CC BY-SA or both. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + I, Wojtek Kosior, thereby promise not to sue for violation of this file's + licenses. Although I request that you do not make use of this code in a + proprietary program, I am not going to enforce this in court. + --> + +<!-- + This is not a standalone page. This file is meant to be imported into other + HTML code. + --> + +#LOADCSS html/reset.css +#LOADCSS html/base.css +#LOADCSS html/grid.css +<style> + .dialog_main_div { + margin: 1.4em; + } +</style> +<template> + <div id="resource_preview_div" data-template="main_div" + class="grid_2 grid_form preview_main_div"> + <h3 class="grid_col_both">resource preview</h3> + <span class="grid_col_1">identifier:</span> + <span data-template="identifier" class="grid_col_2">...</span> + <span class="grid_col_1">long name:</span> + <span data-template="long_name" class="grid_col_2">...</span> + <span class="grid_col_1">UUID:</span> + <span data-template="uuid" class="grid_col_2">...</span> + <span class="grid_col_1">version:</span> + <span data-template="version" class="grid_col_2">...</span> + <span class="grid_col_1">description:</span> + <span data-template="description" class="grid_col_2">...</span> + <span class="grid_col_1">dependencies:</span> + <span class="grid_col_2"><ul data-template="dependencies"></ul></span> + <span class="grid_col_1">scripts:</span> + <span class="grid_col_2"><ul data-template="scripts"></ul></span> + <span class="grid_col_1">source name:</span> + <span data-template="source_name" class="grid_col_2">...</span> + <span class="grid_col_1">copyright:</span> + <span class="grid_col_2"><ul data-template="copyright"></ul></span> + </div> + <div id="mapping_preview_div" data-template="main_div" + class="grid_2 grid_form"> + <h3 class="grid_col_both">mapping preview</h3> + <span class="grid_col_1">identifier:</span> + <span data-template="identifier" class="grid_col_2">...</span> + <span class="grid_col_1">long name:</span> + <span data-template="long_name" class="grid_col_2">...</span> + <span class="grid_col_1">UUID:</span> + <span data-template="uuid" class="grid_col_2">...</span> + <span class="grid_col_1">version:</span> + <span data-template="version" class="grid_col_2">...</span> + <span class="grid_col_1">description:</span> + <span data-template="description" class="grid_col_2">...</span> + <span class="grid_col_both">payloads:</span> + <div data-template="payloads" class="grid_col_both grid_2"></div> + <span class="grid_col_1">source name:</span> + <span data-template="source_name" class="grid_col_2">...</span> + <span class="grid_col_1">copyright:</span> + <span class="grid_col_2"><ul data-template="copyright"></ul></span> + </div> +</template> +#ENDIF diff --git a/html/item_preview.js b/html/item_preview.js new file mode 100644 index 0000000..f59e30e --- /dev/null +++ b/html/item_preview.js @@ -0,0 +1,151 @@ +/** + * This file is part of Haketilo. + * + * Function: Showing resource/mapping details in a browser. + * + * Copyright (C) 2022 Wojtek Kosior + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * As additional permission under GNU GPL version 3 section 7, you + * may distribute forms of that code without the copy of the GNU + * GPL normally required by section 4, provided you include this + * license notice and, in case of non-source distribution, a URL + * through which recipients can access the Corresponding Source. + * If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * As a special exception to the GPL, any HTML file which merely + * makes function calls to this code, and for that purpose + * includes it by reference shall be deemed a separate work for + * copyright law purposes. If you modify this code, you may extend + * this exception to your version of the code, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * I, Wojtek Kosior, thereby promise not to sue for violation of this file's + * license. Although I request that you do not make use of this code in a + * proprietary program, I am not going to enforce this in court. + */ + +#IMPORT common/indexeddb.js AS haketilodb +#IMPORT html/dialog.js + +#FROM html/DOM_helpers.js IMPORT clone_template + +function populate_list(ul, items) +{ + for (const item of items) { + const li = document.createElement("li"); + li.append(item); + ul.append(li); + } +} + +async function file_link_clicked(preview_object, file_ref, event) +{ + event.preventDefault(); + + const db = await haketilodb.get(); + const file = await haketilodb.idb_get(db.transaction("files"), + "files", file_ref.hash_key); + if (file === undefined) { + dialog.error(preview_object.dialog_context, + "File missing from Haketilo's inernal database :("); + } else { + const encoded_file = encodeURIComponent(file.contents); + open(`data:text/plain;charset=utf8,${encoded_file}`, '_blank'); + } +} + +function make_file_link(preview_object, file_ref) +{ + const a = document.createElement("a"); + a.href = "javascript:void(0)"; + a.innerText = file_ref.file; + a.addEventListener("click", + e => file_link_clicked(preview_object, file_ref, e)); + + return a; +} + +function resource_preview(resource, preview_object, dialog_context) +{ + if (preview_object === undefined) + preview_object = clone_template("resource_preview_div"); + + preview_object.identifier.innerText = resource.identifier; + preview_object.long_name.innerText = resource.long_name; + preview_object.uuid.innerText = resource.uuid; + preview_object.version.innerText = + `${resource.version.join(".")}-${resource.revision}`; + preview_object.description.innerText = resource.description; + preview_object.source_name.innerText = resource.source_name; + + [...preview_object.dependencies.childNodes].forEach(n => n.remove()); + populate_list(preview_object.dependencies, resource.dependencies); + + const link_maker = file_ref => make_file_link(preview_object, file_ref); + + [...preview_object.scripts.childNodes].forEach(n => n.remove()); + populate_list(preview_object.scripts, resource.scripts.map(link_maker)); + + [...preview_object.copyright.childNodes].forEach(n => n.remove()); + populate_list(preview_object.copyright, + resource.source_copyright.map(link_maker)); + + preview_object.dialog_context = dialog_context; + + return preview_object; +} +#EXPORT resource_preview + +function mapping_preview(mapping, preview_object, dialog_context) +{ + if (preview_object === undefined) + preview_object = clone_template("mapping_preview_div"); + + preview_object.identifier.innerText = mapping.identifier; + preview_object.long_name.innerText = mapping.long_name; + preview_object.uuid.innerText = mapping.uuid; + preview_object.version.innerText = mapping.version.join("."); + preview_object.description.innerText = mapping.description; + preview_object.source_name.innerText = mapping.source_name; + + [...preview_object.payloads.childNodes].forEach(n => n.remove()); + for (const [pattern, payload] of Object.entries(mapping.payloads).sort()) { + /* We use a non-breaking space because normal space would be ignored. */ + const [nbsp, rarrow] = [160, 0x2192].map(n => String.fromCodePoint(n)); + const texts = [`${pattern}${nbsp}`, `${rarrow} ${payload.identifier}`]; + for (let i = 0; i < texts.length; i++) { + const span = document.createElement("span"); + span.innerText = texts[i]; + span.classList.add(`grid_col_${i + 1}`); + preview_object.payloads.append(span); + } + } + + const link_maker = file_ref => make_file_link(preview_object, file_ref); + + [...preview_object.copyright.childNodes].forEach(n => n.remove()); + populate_list(preview_object.copyright, + mapping.source_copyright.map(link_maker)); + + preview_object.dialog_context = dialog_context; + + return preview_object; +} +#EXPORT mapping_preview |