tg-prepare 1.1.0__py3-none-any.whl → 2.1.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tg-prepare might be problematic. Click here for more details.
- {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/METADATA +3 -3
- tg_prepare-2.1.0b2.dist-info/RECORD +78 -0
- {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/WHEEL +1 -1
- tg_prepare-2.1.0b2.dist-info/projects/.secret_key +1 -0
- tgp_backend/__init__.py +3 -4
- tgp_backend/config.py +31 -0
- tgp_backend/directories.py +6 -8
- tgp_backend/nextcloud.py +40 -19
- tgp_backend/project.py +172 -45
- tgp_backend/session_manager.py +47 -0
- tgp_backend/util.py +73 -25
- tgp_ui/app.py +43 -335
- tgp_ui/routes/__init__.py +0 -0
- tgp_ui/routes/collection.py +272 -0
- tgp_ui/routes/data.py +228 -0
- tgp_ui/routes/project.py +102 -0
- tgp_ui/routes/publication.py +129 -0
- tgp_ui/routes/tabs.py +34 -0
- tgp_ui/routes/views.py +62 -0
- tgp_ui/static/css/bootstrap.min.css.map +1 -0
- tgp_ui/static/css/navbar.css +92 -0
- tgp_ui/static/img/favicon.ico +0 -0
- tgp_ui/static/img/textgrid-logo.svg +1 -0
- tgp_ui/static/js/collectionManager.js +60 -0
- tgp_ui/static/js/fileManager.js +186 -0
- tgp_ui/static/js/main.js +32 -485
- tgp_ui/static/js/modalManager.js +105 -0
- tgp_ui/static/js/navbarManager.js +151 -0
- tgp_ui/static/js/projectManager.js +60 -0
- tgp_ui/static/js/require.js +5 -0
- tgp_ui/static/js/sidebarManager.js +32 -0
- tgp_ui/static/js/tabManager.js +79 -0
- tgp_ui/templates/details/empty_container.html +16 -0
- tgp_ui/templates/details/manage_collection.html +205 -0
- tgp_ui/templates/includes/set_session_id_form.html +16 -0
- tgp_ui/templates/includes/upload_form.html +131 -0
- tgp_ui/templates/layout.html +9 -48
- tgp_ui/templates/macros.html +79 -72
- tgp_ui/templates/modal/delete_project.html +25 -0
- tgp_ui/templates/modal/empty_container.html +9 -0
- tgp_ui/templates/modal/file_explorer_content.html +34 -0
- tgp_ui/templates/modal/file_explorer_main.html +22 -0
- tgp_ui/templates/modal/file_explorer_nextcloud.html +27 -0
- tgp_ui/templates/modal/github_modal.html +29 -0
- tgp_ui/templates/modal/nextcloud_login.html +48 -0
- tgp_ui/templates/modal/tei_explorer.html +58 -0
- tgp_ui/templates/modal/xpath_parser.html +52 -0
- tgp_ui/templates/project_main.html +36 -0
- tgp_ui/templates/project_navbar.html +81 -0
- tgp_ui/templates/{projects.html → projects_main.html} +13 -28
- tgp_ui/templates/tab_final_upload.html +29 -0
- tgp_ui/templates/tabs/check_result.html +90 -0
- tgp_ui/templates/tabs/edit_project.html +113 -0
- tgp_ui/templates/tabs/empty_container.html +12 -0
- tgp_ui/templates/tabs/import_data.html +138 -0
- tgp_ui/templates/tabs/manage_collections.html +88 -0
- tgp_ui/templates/tabs/select_directories.html +41 -0
- tgp_ui/templates/tabs/upload.html +42 -0
- tgp_ui/templates/tabs/validate_metadata.html +227 -0
- tg_prepare-1.1.0.dist-info/RECORD +0 -39
- tgp_ui/templates/collection.html +0 -194
- tgp_ui/templates/file_upload.html +0 -24
- tgp_ui/templates/nxc_file_tree.html +0 -33
- tgp_ui/templates/project.html +0 -26
- tgp_ui/templates/storage.html +0 -49
- tgp_ui/templates/tei_explorer.html +0 -48
- tgp_ui/templates/xpath_parser_modal_content.html +0 -37
- {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/entry_points.txt +0 -0
- {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/licenses/LICENSE +0 -0
- {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
define([], function () {
|
|
2
|
+
const NavbarManager = {
|
|
3
|
+
resetButtons: function (buttons, additionalClasses = []) {
|
|
4
|
+
buttons.forEach(btn => {
|
|
5
|
+
btn.classList.remove('animate-to-long', 'border-primary', ...additionalClasses);
|
|
6
|
+
const icon = btn.querySelector('i');
|
|
7
|
+
const subButtons = btn.querySelector('.sub-buttons');
|
|
8
|
+
|
|
9
|
+
if (icon) icon.classList.remove('d-none');
|
|
10
|
+
if (subButtons) {
|
|
11
|
+
subButtons.classList.add('d-none');
|
|
12
|
+
subButtons.style.opacity = '0';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
btn.style.width = ''; // Reset width
|
|
16
|
+
|
|
17
|
+
// Füge für kleine Buttons die Outline-Secondary-Klasse wieder hinzu
|
|
18
|
+
if (btn.classList.contains('btn-sm')) {
|
|
19
|
+
btn.classList.add('btn-outline-secondary');
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
activateButton: function (button, index, buttons) {
|
|
25
|
+
// Vorherige Buttons hervorheben / Progress anzeigen
|
|
26
|
+
for (let i = 0; i <= index; i++) {
|
|
27
|
+
buttons[i].classList.add('border-primary');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Aktuellen Button erweitern
|
|
31
|
+
button.classList.add('animate-to-long');
|
|
32
|
+
const icon = button.querySelector('i');
|
|
33
|
+
const subButtons = button.querySelector('.sub-buttons');
|
|
34
|
+
|
|
35
|
+
if (icon) icon.classList.add('d-none');
|
|
36
|
+
if (subButtons) {
|
|
37
|
+
subButtons.classList.remove('d-none');
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
subButtons.style.opacity = '1';
|
|
40
|
+
}, 300);
|
|
41
|
+
|
|
42
|
+
// Ersten kleinen Button klicken, wenn kein last-opened vorhanden
|
|
43
|
+
const lastOpenedButton = subButtons.querySelector('.last-opened');
|
|
44
|
+
if (lastOpenedButton) {
|
|
45
|
+
lastOpenedButton.click();
|
|
46
|
+
} else {
|
|
47
|
+
const firstSmButton = subButtons.querySelector('.btn-sm');
|
|
48
|
+
if (firstSmButton) firstSmButton.click();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Dynamische Breite basierend auf kleinen Buttons
|
|
53
|
+
const smallButtonsCount = subButtons?.querySelectorAll('.btn-sm').length || 0;
|
|
54
|
+
const sizeAdjustment = smallButtonsCount * 5.4;
|
|
55
|
+
button.style.width = `${sizeAdjustment}rem`;
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
adjustLine: function (button) {
|
|
59
|
+
const container = document.querySelector('.container.bg'); // Container der Buttons
|
|
60
|
+
const lineBlue = document.querySelector('.line.blue'); // Zweite Linie
|
|
61
|
+
const containerRect = container.getBoundingClientRect(); // Position des Containers
|
|
62
|
+
const buttonRect = button.getBoundingClientRect(); // Position des angeklickten Buttons
|
|
63
|
+
|
|
64
|
+
// Berechne die Breite der Linie basierend auf der Position des Buttons
|
|
65
|
+
const newWidth = buttonRect.left - containerRect.left + buttonRect.width / 2;
|
|
66
|
+
lineBlue.style.width = `${newWidth}px`; // Setze die neue Breite der Linie
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
triggerLastOpenedTab: function (projectname) {
|
|
70
|
+
fetch(`/get_last_tab/${projectname}`)
|
|
71
|
+
.then(response => response.json())
|
|
72
|
+
.then(data => {
|
|
73
|
+
if (data.initial_tab) {
|
|
74
|
+
const initialTab = document.querySelector(`.btn-sm[data-bs-target="#${data.initial_tab}"]`);
|
|
75
|
+
if (initialTab) {
|
|
76
|
+
initialTab.closest('.btn-xl').click();
|
|
77
|
+
initialTab.click();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.catch(error => console.error('Error fetching initial tab:', error));
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
setLastOpenedTab: function (projectname, tab) {
|
|
85
|
+
fetch(`/set_last_tab/${projectname}/${tab}`, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: {
|
|
88
|
+
'Content-Type': 'application/json'
|
|
89
|
+
},
|
|
90
|
+
body: JSON.stringify({ projectname: projectname, tab: tab })
|
|
91
|
+
})
|
|
92
|
+
.then(response => response.json())
|
|
93
|
+
.catch(error => console.error('Error writing last tab:', error));
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
init: function () {
|
|
97
|
+
// Event-Listener für große Buttons (btn-xl)
|
|
98
|
+
document.querySelectorAll('.btn-xl').forEach((button, index, buttons) => {
|
|
99
|
+
button.addEventListener('click', () => {
|
|
100
|
+
// Delete activate class from all small buttons
|
|
101
|
+
const smBtnContainer = button.closest('.container.bg');
|
|
102
|
+
smBtnContainer.querySelectorAll('.btn-sm').forEach(btn => {
|
|
103
|
+
btn.classList.remove('active');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
this.resetButtons(document.querySelectorAll('.btn-xl'));
|
|
107
|
+
this.activateButton(button, index, buttons);
|
|
108
|
+
this.adjustLine(button);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Event-Listener für kleine Buttons (btn-sm)
|
|
113
|
+
document.querySelectorAll('.btn-sm').forEach(button => {
|
|
114
|
+
button.addEventListener('click', event => {
|
|
115
|
+
event.stopPropagation(); // Verhindert, dass der große Button reagiert
|
|
116
|
+
|
|
117
|
+
// Alle kleinen Buttons in der gleichen Sektion zurücksetzen
|
|
118
|
+
const parentSection = button.closest('.sub-buttons');
|
|
119
|
+
this.resetButtons(parentSection.querySelectorAll('.btn-sm'), ['btn-outline-primary', 'last-opened']);
|
|
120
|
+
|
|
121
|
+
// Aktuellen Button aktivieren
|
|
122
|
+
button.classList.add('btn-outline-primary', 'last-opened');
|
|
123
|
+
button.classList.remove('btn-outline-secondary');
|
|
124
|
+
|
|
125
|
+
// Setze den zuletzt geöffneten Tab
|
|
126
|
+
const projectname = this.getActiveProjectName();
|
|
127
|
+
const tab = button.getAttribute('data-bs-target').replace('#', '');
|
|
128
|
+
this.setLastOpenedTab(projectname, tab);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Initialisiere den zuletzt geöffneten Tab
|
|
133
|
+
const projectname = this.getActiveProjectName();
|
|
134
|
+
if (projectname) {
|
|
135
|
+
this.triggerLastOpenedTab(projectname);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
getActiveProjectName: function () {
|
|
140
|
+
const activeBtn = Array.from(document.querySelectorAll('.project-btn'))
|
|
141
|
+
.find(btn => btn.querySelector('.bi.bi-circle-fill'));
|
|
142
|
+
if (activeBtn) {
|
|
143
|
+
const nameSpan = activeBtn.querySelector('.projectname');
|
|
144
|
+
return nameSpan ? nameSpan.textContent : null;
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return NavbarManager;
|
|
151
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
define([], function () {
|
|
2
|
+
const ProjectManager = {
|
|
3
|
+
addMultiInputAttributes: function (event) {
|
|
4
|
+
event.preventDefault();
|
|
5
|
+
|
|
6
|
+
// Clone the current input group element
|
|
7
|
+
const currentInputGroup = event.target.closest('.input-group');
|
|
8
|
+
const newInputGroup = currentInputGroup.cloneNode(true);
|
|
9
|
+
|
|
10
|
+
// Clear the input field in the cloned element
|
|
11
|
+
const input = newInputGroup.querySelector('input');
|
|
12
|
+
if (input) {
|
|
13
|
+
input.value = '';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Replace the plus symbol with a minus symbol and add the 'remove-multi-input' class
|
|
17
|
+
const button = newInputGroup.querySelector('.add-multi-input');
|
|
18
|
+
if (button) {
|
|
19
|
+
button.classList.remove('add-multi-input');
|
|
20
|
+
button.classList.add('remove-multi-input');
|
|
21
|
+
const logo = button.querySelector('i');
|
|
22
|
+
logo.classList.remove('bi-plus-circle-dotted');
|
|
23
|
+
logo.classList.add('bi-dash-circle-dotted');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Append the cloned element at the end of the parent container
|
|
27
|
+
currentInputGroup.parentNode.appendChild(newInputGroup);
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
removeMultiInputAttributes: function (event) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
|
|
33
|
+
// Remove the parent div of the minus button
|
|
34
|
+
const inputGroup = event.target.closest('.input-group');
|
|
35
|
+
if (inputGroup) {
|
|
36
|
+
inputGroup.remove();
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
focusInputProjectname: function () {
|
|
41
|
+
const projectInput = document.getElementById('projectNameInput');
|
|
42
|
+
if (projectInput) {
|
|
43
|
+
projectInput.focus();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
init: function () {
|
|
48
|
+
// Event binding for adding a new multi-input field
|
|
49
|
+
$(document).on('click', '.add-multi-input', this.addMultiInputAttributes);
|
|
50
|
+
|
|
51
|
+
// Event binding for removing a multi-input field
|
|
52
|
+
$(document).on('click', '.remove-multi-input', this.removeMultiInputAttributes);
|
|
53
|
+
|
|
54
|
+
// Event binding for focusing on the project name input in the modal
|
|
55
|
+
$(document).on('shown.bs.modal', '#newProject', this.focusInputProjectname);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return ProjectManager;
|
|
60
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** vim: et:ts=4:sw=4:sts=4
|
|
2
|
+
* @license RequireJS 2.3.7 Copyright jQuery Foundation and other contributors.
|
|
3
|
+
* Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
|
|
4
|
+
*/
|
|
5
|
+
var requirejs, require, define; !function (global, setTimeout) { var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, version = "2.3.7", commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm, cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, jsSuffixRegExp = /\.js$/, currDirRegExp = /^\.\//, op = Object.prototype, ostring = op.toString, hasOwn = op.hasOwnProperty, isBrowser = !("undefined" == typeof window || "undefined" == typeof navigator || !window.document), isWebWorker = !isBrowser && "undefined" != typeof importScripts, readyRegExp = isBrowser && "PLAYSTATION 3" === navigator.platform ? /^complete$/ : /^(complete|loaded)$/, defContextName = "_", isOpera = "undefined" != typeof opera && "[object Opera]" === opera.toString(), contexts = {}, cfg = {}, globalDefQueue = [], useInteractive = !1, disallowedProps = ["__proto__", "constructor"]; function commentReplace(e, t) { return t || "" } function isFunction(e) { return "[object Function]" === ostring.call(e) } function isArray(e) { return "[object Array]" === ostring.call(e) } function each(e, t) { if (e) for (var i = 0; i < e.length && (!e[i] || !t(e[i], i, e)); i += 1); } function eachReverse(e, t) { if (e) for (var i = e.length - 1; -1 < i && (!e[i] || !t(e[i], i, e)); --i); } function hasProp(e, t) { return hasOwn.call(e, t) } function getOwn(e, t) { return hasProp(e, t) && e[t] } function eachProp(e, t) { for (var i in e) if (hasProp(e, i) && -1 == disallowedProps.indexOf(i) && t(e[i], i)) break } function mixin(i, e, r, n) { e && eachProp(e, function (e, t) { !r && hasProp(i, t) || (!n || "object" != typeof e || !e || isArray(e) || isFunction(e) || e instanceof RegExp ? i[t] = e : (i[t] || (i[t] = {}), mixin(i[t], e, r, n))) }) } function bind(e, t) { return function () { return t.apply(e, arguments) } } function scripts() { return document.getElementsByTagName("script") } function defaultOnError(e) { throw e } function getGlobal(e) { var t; return e && (t = global, each(e.split("."), function (e) { t = t[e] }), t) } function makeError(e, t, i, r) { t = new Error(t + "\nhttps://requirejs.org/docs/errors.html#" + e); return t.requireType = e, t.requireModules = r, i && (t.originalError = i), t } if (void 0 === define) { if (void 0 !== requirejs) { if (isFunction(requirejs)) return; cfg = requirejs, requirejs = void 0 } void 0 === require || isFunction(require) || (cfg = require, require = void 0), req = requirejs = function (e, t, i, r) { var n, o = defContextName; return isArray(e) || "string" == typeof e || (n = e, isArray(t) ? (e = t, t = i, i = r) : e = []), n && n.context && (o = n.context), r = (r = getOwn(contexts, o)) || (contexts[o] = req.s.newContext(o)), n && r.configure(n), r.require(e, t, i) }, req.config = function (e) { return req(e) }, req.nextTick = void 0 !== setTimeout ? function (e) { setTimeout(e, 4) } : function (e) { e() }, require = require || req, req.version = version, req.jsExtRegExp = /^\/|:|\?|\.js$/, req.isBrowser = isBrowser, s = req.s = { contexts: contexts, newContext: newContext }, req({}), each(["toUrl", "undef", "defined", "specified"], function (t) { req[t] = function () { var e = contexts[defContextName]; return e.require[t].apply(e, arguments) } }), isBrowser && (head = s.head = document.getElementsByTagName("head")[0], baseElement = document.getElementsByTagName("base")[0], baseElement) && (head = s.head = baseElement.parentNode), req.onError = defaultOnError, req.createNode = function (e, t, i) { var r = e.xhtml ? document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : document.createElement("script"); return r.type = e.scriptType || "text/javascript", r.charset = "utf-8", r.async = !0, r }, req.load = function (t, i, r) { var e, n = t && t.config || {}; if (isBrowser) return (e = req.createNode(n, i, r)).setAttribute("data-requirecontext", t.contextName), e.setAttribute("data-requiremodule", i), !e.attachEvent || e.attachEvent.toString && e.attachEvent.toString().indexOf("[native code") < 0 || isOpera ? (e.addEventListener("load", t.onScriptLoad, !1), e.addEventListener("error", t.onScriptError, !1)) : (useInteractive = !0, e.attachEvent("onreadystatechange", t.onScriptLoad)), e.src = r, n.onNodeCreated && n.onNodeCreated(e, n, i, r), currentlyAddingScript = e, baseElement ? head.insertBefore(e, baseElement) : head.appendChild(e), currentlyAddingScript = null, e; if (isWebWorker) try { setTimeout(function () { }, 0), importScripts(r), t.completeLoad(i) } catch (e) { t.onError(makeError("importscripts", "importScripts failed for " + i + " at " + r, e, [i])) } }, isBrowser && !cfg.skipDataMain && eachReverse(scripts(), function (e) { if (head = head || e.parentNode, dataMain = e.getAttribute("data-main")) return mainScript = dataMain, cfg.baseUrl || -1 !== mainScript.indexOf("!") || (mainScript = (src = mainScript.split("/")).pop(), subPath = src.length ? src.join("/") + "/" : "./", cfg.baseUrl = subPath), mainScript = mainScript.replace(jsSuffixRegExp, ""), req.jsExtRegExp.test(mainScript) && (mainScript = dataMain), cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript], !0 }), define = function (e, i, t) { var r, n; "string" != typeof e && (t = i, i = e, e = null), isArray(i) || (t = i, i = null), !i && isFunction(t) && (i = [], t.length) && (t.toString().replace(commentRegExp, commentReplace).replace(cjsRequireRegExp, function (e, t) { i.push(t) }), i = (1 === t.length ? ["require"] : ["require", "exports", "module"]).concat(i)), useInteractive && (r = currentlyAddingScript || getInteractiveScript()) && (e = e || r.getAttribute("data-requiremodule"), n = contexts[r.getAttribute("data-requirecontext")]), n ? (n.defQueue.push([e, i, t]), n.defQueueMap[e] = !0) : globalDefQueue.push([e, i, t]) }, define.amd = { jQuery: !0 }, req.exec = function (text) { return eval(text) }, req(cfg) } function newContext(u) { var t, e, f, c, i, b = { waitSeconds: 7, baseUrl: "./", paths: {}, bundles: {}, pkgs: {}, shim: {}, config: {} }, d = {}, p = {}, r = {}, l = [], h = {}, n = {}, m = {}, g = 1, x = 1; function v(e, t, i) { var r, n, o, a, s, u, c, d, p, f = t && t.split("/"), l = b.map, h = l && l["*"]; if (e) { t = (e = e.split("/")).length - 1, b.nodeIdCompat && jsSuffixRegExp.test(e[t]) && (e[t] = e[t].replace(jsSuffixRegExp, "")); for (var m, g = e = "." === e[0].charAt(0) && f ? f.slice(0, f.length - 1).concat(e) : e, x = 0; x < g.length; x++)"." === (m = g[x]) ? (g.splice(x, 1), --x) : ".." !== m || 0 === x || 1 === x && ".." === g[2] || ".." === g[x - 1] || 0 < x && (g.splice(x - 1, 2), x -= 2); e = e.join("/") } if (i && l && (f || h)) { e: for (o = (n = e.split("/")).length; 0 < o; --o) { if (s = n.slice(0, o).join("/"), f) for (a = f.length; 0 < a; --a)if (r = (r = getOwn(l, f.slice(0, a).join("/"))) && getOwn(r, s)) { u = r, c = o; break e } !d && h && getOwn(h, s) && (d = getOwn(h, s), p = o) } !u && d && (u = d, c = p), u && (n.splice(0, c, u), e = n.join("/")) } return getOwn(b.pkgs, e) || e } function q(t) { isBrowser && each(scripts(), function (e) { if (e.getAttribute("data-requiremodule") === t && e.getAttribute("data-requirecontext") === f.contextName) return e.parentNode.removeChild(e), !0 }) } function E(e) { var t = getOwn(b.paths, e); return t && isArray(t) && 1 < t.length && (t.shift(), f.require.undef(e), f.makeRequire(null, { skipMap: !0 })([e]), 1) } function w(e) { var t, i = e ? e.indexOf("!") : -1; return -1 < i && (t = e.substring(0, i), e = e.substring(i + 1, e.length)), [t, e] } function y(e, t, i, r) { var n, o, a, s = null, u = t ? t.name : null, c = e, d = !0, p = ""; return e || (d = !1, e = "_@r" + (g += 1)), s = (a = w(e))[0], e = a[1], s && (s = v(s, u, r), o = getOwn(h, s)), e && (s ? p = i ? e : o && o.normalize ? o.normalize(e, function (e) { return v(e, u, r) }) : -1 === e.indexOf("!") ? v(e, u, r) : e : (s = (a = w(p = v(e, u, r)))[0], i = !0, n = f.nameToUrl(p = a[1]))), { prefix: s, name: p, parentMap: t, unnormalized: !!(e = !s || o || i ? "" : "_unnormalized" + (x += 1)), url: n, originalName: c, isDefine: d, id: (s ? s + "!" + p : p) + e } } function S(e) { var t = e.id; return getOwn(d, t) || (d[t] = new f.Module(e)) } function k(e, t, i) { var r = e.id, n = getOwn(d, r); !hasProp(h, r) || n && !n.defineEmitComplete ? (n = S(e)).error && "error" === t ? i(n.error) : n.on(t, i) : "defined" === t && i(h[r]) } function M(t, e) { var i = t.requireModules, r = !1; e ? e(t) : (each(i, function (e) { e = getOwn(d, e); e && (e.error = t, e.events.error) && (r = !0, e.emit("error", t)) }), r || req.onError(t)) } function O() { globalDefQueue.length && (each(globalDefQueue, function (e) { var t = e[0]; "string" == typeof t && (f.defQueueMap[t] = !0), l.push(e) }), globalDefQueue = []) } function j(e) { delete d[e], delete p[e] } function P() { var r, e = 1e3 * b.waitSeconds, n = e && f.startTime + e < (new Date).getTime(), o = [], a = [], s = !1, u = !0; if (!t) { if (t = !0, eachProp(p, function (e) { var t = e.map, i = t.id; if (e.enabled && (t.isDefine || a.push(e), !e.error)) if (!e.inited && n) E(i) ? s = r = !0 : (o.push(i), q(i)); else if (!e.inited && e.fetched && t.isDefine && (s = !0, !t.prefix)) return u = !1 }), n && o.length) return (e = makeError("timeout", "Load timeout for modules: " + o, null, o)).contextName = f.contextName, M(e); u && each(a, function (e) { !function r(n, o, a) { var e = n.map.id; n.error ? n.emit("error", n.error) : (o[e] = !0, each(n.depMaps, function (e, t) { var e = e.id, i = getOwn(d, e); !i || n.depMatched[t] || a[e] || (getOwn(o, e) ? (n.defineDep(t, h[e]), n.check()) : r(i, o, a)) }), a[e] = !0) }(e, {}, {}) }), n && !r || !s || (isBrowser || isWebWorker) && (i = i || setTimeout(function () { i = 0, P() }, 50)), t = !1 } } function a(e) { hasProp(h, e[0]) || S(y(e[0], null, !0)).init(e[1], e[2]) } function o(e, t, i, r) { e.detachEvent && !isOpera ? r && e.detachEvent(r, t) : e.removeEventListener(i, t, !1) } function s(e) { e = e.currentTarget || e.srcElement; return o(e, f.onScriptLoad, "load", "onreadystatechange"), o(e, f.onScriptError, "error"), { node: e, id: e && e.getAttribute("data-requiremodule") } } function R() { var e; for (O(); l.length;) { if (null === (e = l.shift())[0]) return M(makeError("mismatch", "Mismatched anonymous define() module: " + e[e.length - 1])); a(e) } f.defQueueMap = {} } return c = { require: function (e) { return e.require || (e.require = f.makeRequire(e.map)) }, exports: function (e) { if (e.usingExports = !0, e.map.isDefine) return e.exports ? h[e.map.id] = e.exports : e.exports = h[e.map.id] = {} }, module: function (e) { return e.module || (e.module = { id: e.map.id, uri: e.map.url, config: function () { return getOwn(b.config, e.map.id) || {} }, exports: e.exports || (e.exports = {}) }) } }, (e = function (e) { this.events = getOwn(r, e.id) || {}, this.map = e, this.shim = getOwn(b.shim, e.id), this.depExports = [], this.depMaps = [], this.depMatched = [], this.pluginMaps = {}, this.depCount = 0 }).prototype = { init: function (e, t, i, r) { r = r || {}, this.inited || (this.factory = t, i ? this.on("error", i) : this.events.error && (i = bind(this, function (e) { this.emit("error", e) })), this.depMaps = e && e.slice(0), this.errback = i, this.inited = !0, this.ignore = r.ignore, r.enabled || this.enabled ? this.enable() : this.check()) }, defineDep: function (e, t) { this.depMatched[e] || (this.depMatched[e] = !0, --this.depCount, this.depExports[e] = t) }, fetch: function () { if (!this.fetched) { this.fetched = !0, f.startTime = (new Date).getTime(); var e = this.map; if (!this.shim) return e.prefix ? this.callPlugin() : this.load(); f.makeRequire(this.map, { enableBuildCallback: !0 })(this.shim.deps || [], bind(this, function () { return e.prefix ? this.callPlugin() : this.load() })) } }, load: function () { var e = this.map.url; n[e] || (n[e] = !0, f.load(this.map.id, e)) }, check: function () { if (this.enabled && !this.enabling) { var t, i, e = this.map.id, r = this.depExports, n = this.exports, o = this.factory; if (this.inited) { if (this.error) this.emit("error", this.error); else if (!this.defining) { if (this.defining = !0, this.depCount < 1 && !this.defined) { if (isFunction(o)) { if (this.events.error && this.map.isDefine || req.onError !== defaultOnError) try { n = f.execCb(e, o, r, n) } catch (e) { t = e } else n = f.execCb(e, o, r, n); if (this.map.isDefine && void 0 === n && ((r = this.module) ? n = r.exports : this.usingExports && (n = this.exports)), t) return t.requireMap = this.map, t.requireModules = this.map.isDefine ? [this.map.id] : null, t.requireType = this.map.isDefine ? "define" : "require", M(this.error = t) } else n = o; this.exports = n, this.map.isDefine && !this.ignore && (h[e] = n, req.onResourceLoad) && (i = [], each(this.depMaps, function (e) { i.push(e.normalizedMap || e) }), req.onResourceLoad(f, this.map, i)), j(e), this.defined = !0 } this.defining = !1, this.defined && !this.defineEmitted && (this.defineEmitted = !0, this.emit("defined", this.exports), this.defineEmitComplete = !0) } } else hasProp(f.defQueueMap, e) || this.fetch() } }, callPlugin: function () { var s = this.map, u = s.id, e = y(s.prefix); this.depMaps.push(e), k(e, "defined", bind(this, function (e) { var o, t, i = getOwn(m, this.map.id), r = this.map.name, n = this.map.parentMap ? this.map.parentMap.name : null, a = f.makeRequire(s.parentMap, { enableBuildCallback: !0 }); this.map.unnormalized ? (e.normalize && (r = e.normalize(r, function (e) { return v(e, n, !0) }) || ""), k(t = y(s.prefix + "!" + r, this.map.parentMap, !0), "defined", bind(this, function (e) { this.map.normalizedMap = t, this.init([], function () { return e }, null, { enabled: !0, ignore: !0 }) })), (r = getOwn(d, t.id)) && (this.depMaps.push(t), this.events.error && r.on("error", bind(this, function (e) { this.emit("error", e) })), r.enable())) : i ? (this.map.url = f.nameToUrl(i), this.load()) : ((o = bind(this, function (e) { this.init([], function () { return e }, null, { enabled: !0 }) })).error = bind(this, function (e) { this.inited = !0, (this.error = e).requireModules = [u], eachProp(d, function (e) { 0 === e.map.id.indexOf(u + "_unnormalized") && j(e.map.id) }), M(e) }), o.fromText = bind(this, function (e, t) { var i = s.name, r = y(i), n = useInteractive; t && (e = t), n && (useInteractive = !1), S(r), hasProp(b.config, u) && (b.config[i] = b.config[u]); try { req.exec(e) } catch (e) { return M(makeError("fromtexteval", "fromText eval for " + u + " failed: " + e, e, [u])) } n && (useInteractive = !0), this.depMaps.push(r), f.completeLoad(i), a([i], o) }), e.load(s.name, a, o, b)) })), f.enable(e, this), this.pluginMaps[e.id] = e }, enable: function () { (p[this.map.id] = this).enabled = !0, this.enabling = !0, each(this.depMaps, bind(this, function (e, t) { var i, r; if ("string" == typeof e) { if (e = y(e, this.map.isDefine ? this.map : this.map.parentMap, !1, !this.skipMap), this.depMaps[t] = e, r = getOwn(c, e.id)) return void (this.depExports[t] = r(this)); this.depCount += 1, k(e, "defined", bind(this, function (e) { this.undefed || (this.defineDep(t, e), this.check()) })), this.errback ? k(e, "error", bind(this, this.errback)) : this.events.error && k(e, "error", bind(this, function (e) { this.emit("error", e) })) } r = e.id, i = d[r], hasProp(c, r) || !i || i.enabled || f.enable(e, this) })), eachProp(this.pluginMaps, bind(this, function (e) { var t = getOwn(d, e.id); t && !t.enabled && f.enable(e, this) })), this.enabling = !1, this.check() }, on: function (e, t) { (this.events[e] || (this.events[e] = [])).push(t) }, emit: function (e, t) { each(this.events[e], function (e) { e(t) }), "error" === e && delete this.events[e] } }, (f = { config: b, contextName: u, registry: d, defined: h, urlFetched: n, defQueue: l, defQueueMap: {}, Module: e, makeModuleMap: y, nextTick: req.nextTick, onError: M, configure: function (e) { e.baseUrl && "/" !== e.baseUrl.charAt(e.baseUrl.length - 1) && (e.baseUrl += "/"), "string" == typeof e.urlArgs && (i = e.urlArgs, e.urlArgs = function (e, t) { return (-1 === t.indexOf("?") ? "?" : "&") + i }); var i, r = b.shim, n = { paths: !0, bundles: !0, config: !0, map: !0 }; eachProp(e, function (e, t) { n[t] ? (b[t] || (b[t] = {}), mixin(b[t], e, !0, !0)) : b[t] = e }), e.bundles && eachProp(e.bundles, function (e, t) { each(e, function (e) { e !== t && (m[e] = t) }) }), e.shim && (eachProp(e.shim, function (e, t) { !(e = isArray(e) ? { deps: e } : e).exports && !e.init || e.exportsFn || (e.exportsFn = f.makeShimExports(e)), r[t] = e }), b.shim = r), e.packages && each(e.packages, function (e) { var t = (e = "string" == typeof e ? { name: e } : e).name; e.location && (b.paths[t] = e.location), b.pkgs[t] = e.name + "/" + (e.main || "main").replace(currDirRegExp, "").replace(jsSuffixRegExp, "") }), eachProp(d, function (e, t) { e.inited || e.map.unnormalized || (e.map = y(t, null, !0)) }), (e.deps || e.callback) && f.require(e.deps || [], e.callback) }, makeShimExports: function (t) { return function () { var e; return (e = t.init ? t.init.apply(global, arguments) : e) || t.exports && getGlobal(t.exports) } }, makeRequire: function (o, a) { function s(e, t, i) { var r, n; return a.enableBuildCallback && t && isFunction(t) && (t.__requireJsBuild = !0), "string" == typeof e ? isFunction(t) ? M(makeError("requireargs", "Invalid require call"), i) : o && hasProp(c, e) ? c[e](d[o.id]) : req.get ? req.get(f, e, o, s) : (r = y(e, o, !1, !0).id, hasProp(h, r) ? h[r] : M(makeError("notloaded", 'Module name "' + r + '" has not been loaded yet for context: ' + u + (o ? "" : ". Use require([])")))) : (R(), f.nextTick(function () { R(), (n = S(y(null, o))).skipMap = a.skipMap, n.init(e, t, i, { enabled: !0 }), P() }), s) } return a = a || {}, mixin(s, { isBrowser: isBrowser, toUrl: function (e) { var t, i = e.lastIndexOf("."), r = e.split("/")[0]; return -1 !== i && (!("." === r || ".." === r) || 1 < i) && (t = e.substring(i, e.length), e = e.substring(0, i)), f.nameToUrl(v(e, o && o.id, !0), t, !0) }, defined: function (e) { return hasProp(h, y(e, o, !1, !0).id) }, specified: function (e) { return e = y(e, o, !1, !0).id, hasProp(h, e) || hasProp(d, e) } }), o || (s.undef = function (i) { O(); var e = y(i, o, !0), t = getOwn(d, i); t.undefed = !0, q(i), delete h[i], delete n[e.url], delete r[i], eachReverse(l, function (e, t) { e[0] === i && l.splice(t, 1) }), delete f.defQueueMap[i], t && (t.events.defined && (r[i] = t.events), j(i)) }), s }, enable: function (e) { getOwn(d, e.id) && S(e).enable() }, completeLoad: function (e) { var t, i, r, n = getOwn(b.shim, e) || {}, o = n.exports; for (O(); l.length;) { if (null === (i = l.shift())[0]) { if (i[0] = e, t) break; t = !0 } else i[0] === e && (t = !0); a(i) } if (f.defQueueMap = {}, r = getOwn(d, e), !t && !hasProp(h, e) && r && !r.inited) { if (!(!b.enforceDefine || o && getGlobal(o))) return E(e) ? void 0 : M(makeError("nodefine", "No define call for " + e, null, [e])); a([e, n.deps || [], n.exportsFn]) } P() }, nameToUrl: function (e, t, i) { var r, n, o, a, s, u = getOwn(b.pkgs, e); if (u = getOwn(m, e = u ? u : e)) return f.nameToUrl(u, t, i); if (req.jsExtRegExp.test(e)) a = e + (t || ""); else { for (r = b.paths, o = (n = e.split("/")).length; 0 < o; --o)if (s = getOwn(r, n.slice(0, o).join("/"))) { isArray(s) && (s = s[0]), n.splice(0, o, s); break } a = n.join("/"), a = ("/" === (a += t || (/^data\:|^blob\:|\?/.test(a) || i ? "" : ".js")).charAt(0) || a.match(/^[\w\+\.\-]+:/) ? "" : b.baseUrl) + a } return b.urlArgs && !/^blob\:/.test(a) ? a + b.urlArgs(e, a) : a }, load: function (e, t) { req.load(f, e, t) }, execCb: function (e, t, i, r) { return t.apply(r, i) }, onScriptLoad: function (e) { "load" !== e.type && !readyRegExp.test((e.currentTarget || e.srcElement).readyState) || (interactiveScript = null, e = s(e), f.completeLoad(e.id)) }, onScriptError: function (e) { var i, r = s(e); if (!E(r.id)) return i = [], eachProp(d, function (e, t) { 0 !== t.indexOf("_@r") && each(e.depMaps, function (e) { if (e.id === r.id) return i.push(t), !0 }) }), M(makeError("scripterror", 'Script error for "' + r.id + (i.length ? '", needed by: ' + i.join(", ") : '"'), e, [r.id])) } }).require = f.makeRequire(), f } function getInteractiveScript() { return interactiveScript && "interactive" === interactiveScript.readyState || eachReverse(scripts(), function (e) { if ("interactive" === e.readyState) return interactiveScript = e }), interactiveScript } }(this, "undefined" == typeof setTimeout ? void 0 : setTimeout);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
define([], function () {
|
|
2
|
+
const SidebarManager = {
|
|
3
|
+
sidebar: document.querySelector("#sidebar"),
|
|
4
|
+
|
|
5
|
+
toggleSidebar: function () {
|
|
6
|
+
this.sidebar.classList.toggle("expand");
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
checkSidebarVisibility: function () {
|
|
10
|
+
const isCurrentlyVisible = window.innerWidth >= 1080;
|
|
11
|
+
this.sidebar.classList.toggle("expand", isCurrentlyVisible);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
init: function () {
|
|
15
|
+
// Toggle Sidebar on Button Click
|
|
16
|
+
document.querySelector(".toggle-btn").addEventListener("click", () => {
|
|
17
|
+
this.toggleSidebar();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Check Sidebar Visibility on Resize
|
|
21
|
+
window.addEventListener("resize", () => {
|
|
22
|
+
this.checkSidebarVisibility();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Initial Sidebar Visibility Check
|
|
26
|
+
this.checkSidebarVisibility();
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return SidebarManager;
|
|
32
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
define([], function () {
|
|
2
|
+
const TabManager = {
|
|
3
|
+
loadTab: function () {
|
|
4
|
+
const self = $(this);
|
|
5
|
+
const tab = $(self.data('bs-target'));
|
|
6
|
+
if (!tab.hasClass('loaded')) {
|
|
7
|
+
tab.load('/tabs/container')
|
|
8
|
+
tab.load(self.data('url'), function () {
|
|
9
|
+
tab.addClass('loaded');
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
formSubmit: function (event) {
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
const form = $(this);
|
|
17
|
+
const formData = new FormData(this);
|
|
18
|
+
|
|
19
|
+
const submitButton = form.find('button[type="submit"]');
|
|
20
|
+
submitButton.prop('disabled', true);
|
|
21
|
+
const originalButtonText = submitButton.html();
|
|
22
|
+
submitButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
|
|
23
|
+
$.ajax({
|
|
24
|
+
url: form.attr('action'),
|
|
25
|
+
type: form.attr("method") || 'POST',
|
|
26
|
+
data: formData,
|
|
27
|
+
processData: false, // Important for file upload
|
|
28
|
+
contentType: false, // Important for file upload
|
|
29
|
+
success: function (response) {
|
|
30
|
+
const next_target_id = form.data('next-target');
|
|
31
|
+
const reload_subtab_id = form.data('reload-subtab');
|
|
32
|
+
if (next_target_id) {
|
|
33
|
+
$(form.closest('.tab-pane')).html(response);
|
|
34
|
+
const nextTarget = $(next_target_id);
|
|
35
|
+
const nextTargetButton = $('[data-bs-target="' + next_target_id + '"]')
|
|
36
|
+
nextTarget.removeClass('loaded');
|
|
37
|
+
nextTargetButton.trigger('click');
|
|
38
|
+
|
|
39
|
+
} else if (reload_subtab_id) {
|
|
40
|
+
const response_html = $(response);
|
|
41
|
+
const filteredContent = response_html.find(reload_subtab_id);
|
|
42
|
+
$(reload_subtab_id).html(filteredContent.html());
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
$(form.closest('.tab-pane')).html(response);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
complete: function () {
|
|
49
|
+
submitButton.prop('disabled', false);
|
|
50
|
+
submitButton.html(originalButtonText);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
loadNextTab: function (e) {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
const self = $(this);
|
|
58
|
+
const nextTargetId = self.data('next-target');
|
|
59
|
+
const additionalButtonId = self.data('additional-button');
|
|
60
|
+
const nextTarget = $(nextTargetId);
|
|
61
|
+
const nextTargetButton = $(`[data-bs-target="${nextTargetId}"]`);
|
|
62
|
+
|
|
63
|
+
nextTarget.removeClass('loaded');
|
|
64
|
+
nextTargetButton.trigger('click');
|
|
65
|
+
if (additionalButtonId) {
|
|
66
|
+
const additionalButton = $(additionalButtonId);
|
|
67
|
+
additionalButton.trigger('click');
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
init: function () {
|
|
72
|
+
$(document).on('show.bs.tab', 'div[data-bs-toggle="tab"].btn-sm', this.loadTab);
|
|
73
|
+
$(document).on('click', 'button.btn-next', this.loadNextTab);
|
|
74
|
+
$(document).on('submit', '.tab-area form.js-tab-submit', this.formSubmit);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return TabManager;
|
|
79
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<div class="card-body" id="detailsContent">
|
|
3
|
+
{% if show_spinner %}
|
|
4
|
+
<div class="text-center text-muted">
|
|
5
|
+
<div class="spinner-border text-secondary" role="status">
|
|
6
|
+
<span class="visually-hidden">Loading...</span>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
{% else %}
|
|
10
|
+
<p class="text-muted">Select a collection to view or edit its details.</p>
|
|
11
|
+
<div class="text-center text-muted">
|
|
12
|
+
<i class="bi bi-info-circle" style="font-size: 2rem;"></i>
|
|
13
|
+
<p>No collection selected.</p>
|
|
14
|
+
</div>
|
|
15
|
+
{% endif %}
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
{% from "macros.html" import classification_input, multi_input, xpath_or_value_input, required_fields_disclaimer with
|
|
2
|
+
context %}
|
|
3
|
+
<div class="container py-4">
|
|
4
|
+
<!-- Navigation -->
|
|
5
|
+
<ul class="nav nav-pills mb-4" id="collectionNav" role="tablist">
|
|
6
|
+
<li class="nav-item" role="presentation">
|
|
7
|
+
<button class="nav-link active" id="basic-attributes-tab" data-bs-toggle="pill"
|
|
8
|
+
data-bs-target="#basicAttributes" type="button" role="tab" aria-controls="basicAttributes"
|
|
9
|
+
aria-selected="true">Basic Attributes</button>
|
|
10
|
+
</li>
|
|
11
|
+
<li class="nav-item" role="presentation">
|
|
12
|
+
<button class="nav-link" id="classificationAttributes-tab" data-bs-toggle="pill"
|
|
13
|
+
data-bs-target="#classificationAttributes" type="button" role="tab"
|
|
14
|
+
aria-controls="classificationAttributes" aria-selected="false">Classifications</button>
|
|
15
|
+
</li>
|
|
16
|
+
<li class="nav-item" role="presentation">
|
|
17
|
+
<button class="nav-link" id="work-attributes-tab" data-bs-toggle="pill" data-bs-target="#workAttributes"
|
|
18
|
+
type="button" role="tab" aria-controls="workAttributes" aria-selected="false">Work</button>
|
|
19
|
+
</li>
|
|
20
|
+
<li class="nav-item" role="presentation">
|
|
21
|
+
<button class="nav-link" id="edition-attributes-tab" data-bs-toggle="pill"
|
|
22
|
+
data-bs-target="#editionAttributes" type="button" role="tab" aria-controls="editionAttributes"
|
|
23
|
+
aria-selected="false">Edition</button>
|
|
24
|
+
</li>
|
|
25
|
+
<li class="nav-item" role="presentation">
|
|
26
|
+
<button class="nav-link" id="eltecAttributes-tab" data-bs-toggle="pill" data-bs-target="#eltecAttributes"
|
|
27
|
+
type="button" role="tab" aria-controls="eltecAttributes" aria-selected="false">ELTEC
|
|
28
|
+
Specifications</button>
|
|
29
|
+
</li>
|
|
30
|
+
</ul>
|
|
31
|
+
|
|
32
|
+
<!-- Inhalte -->
|
|
33
|
+
<div class="tab-content" id="collectionTabContent">
|
|
34
|
+
{% set collection_parser = project.get_collection_parser(collection) %}
|
|
35
|
+
|
|
36
|
+
<!-- Tab 1: Basic Attributes -->
|
|
37
|
+
<div class="tab-pane fade show active" id="basicAttributes" role="tabpanel"
|
|
38
|
+
aria-labelledby="basic-attributes-tab">
|
|
39
|
+
<form class="js-tab-submit" method="POST" enctype="multipart/form-data"
|
|
40
|
+
data-reload-subtab="#basicAttributes" action=" {{ url_for('collection.save_collection_attributes',
|
|
41
|
+
projectname=project.path, collectionname=collectionname) }}">
|
|
42
|
+
<div class="mb-3 row text-center">
|
|
43
|
+
<label class="col-sm-12 col-form-label text-center"><i>Basic Attributes</i>
|
|
44
|
+
</label>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="mb-3">
|
|
47
|
+
<label class="form-label">Short title</label>
|
|
48
|
+
<input type="text" class="form-control" name="short_title"
|
|
49
|
+
value="{{ collection.short_title or '' }}" required>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="mb-3">
|
|
52
|
+
<label class="form-label">Long title</label>
|
|
53
|
+
<input type="text" class="form-control" name="long_title" value="{{ collection.long_title or '' }}"
|
|
54
|
+
required>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div class="mb-3">
|
|
58
|
+
<label class="form-label">
|
|
59
|
+
Rights Holder
|
|
60
|
+
<span class="text-danger">*</span>
|
|
61
|
+
</label>
|
|
62
|
+
{{ multi_input(collection.rights_holder or [{}], 'rights_holder') }}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="mb-3">
|
|
66
|
+
<label class="form-label">
|
|
67
|
+
Collector
|
|
68
|
+
<span class="text-danger">*</span>
|
|
69
|
+
</label>
|
|
70
|
+
{{ multi_input(collection.collector or [{}], 'collector') }}
|
|
71
|
+
</div>
|
|
72
|
+
<div class="mt-3 row text-center">
|
|
73
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
|
74
|
+
</div>
|
|
75
|
+
</form>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<!-- Tab 2: Classifications -->
|
|
79
|
+
<div class="tab-pane fade" id="classificationAttributes" role="tabpanel"
|
|
80
|
+
aria-labelledby="classificationAttributes-tab">
|
|
81
|
+
<form class="js-tab-submit" method="POST" data-reload-subtab="#classificationAttributes"
|
|
82
|
+
action="{{ url_for('collection.save_collection_classifications', projectname=project.path, collectionname=collectionname) }}">
|
|
83
|
+
{{ classification_input('basic_classifications', 'Basic classification(s)',
|
|
84
|
+
collection.basic_classifications) }}
|
|
85
|
+
|
|
86
|
+
{{ classification_input('gnd_subjects', 'GND Subject Area(s)', collection.gnd_subjects) }}
|
|
87
|
+
<div class="mt-3 row text-center">
|
|
88
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
|
89
|
+
</div>
|
|
90
|
+
</form>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<!-- Tab 3: Work -->
|
|
94
|
+
<div class="tab-pane fade" id="workAttributes" role="tabpanel" aria-labelledby="work-attributes-tab">
|
|
95
|
+
<form class="js-tab-submit" method="POST" data-reload-subtab="#workAttributes"
|
|
96
|
+
action="{{ url_for('collection.save_collection_metadata', projectname=project.path, collectionname=collectionname) }}">
|
|
97
|
+
<div class="mb-3 row text-center">
|
|
98
|
+
<label class="col-sm-12 col-form-label text-center"><i>General</i>
|
|
99
|
+
</label>
|
|
100
|
+
</div>
|
|
101
|
+
{{ xpath_or_value_input('ID', 'work_id',
|
|
102
|
+
collection.work_id, collection_parser) }}
|
|
103
|
+
{{ xpath_or_value_input('Title', 'work_title', collection.work_title, collection_parser) }}
|
|
104
|
+
{{ xpath_or_value_input('Genre', 'genre', collection.genre, collection_parser, required=True) }}
|
|
105
|
+
{{ xpath_or_value_input('Place of publication', 'work_publication_place',
|
|
106
|
+
collection.work_publication_place, collection_parser) }}
|
|
107
|
+
|
|
108
|
+
<div class="mb-3 row">
|
|
109
|
+
<label class="col-sm-12 col-form-label text-center"><i>Author</i>
|
|
110
|
+
</label>
|
|
111
|
+
</div>
|
|
112
|
+
{{ xpath_or_value_input('ID', 'author_id', collection.author_id, collection_parser)
|
|
113
|
+
}}
|
|
114
|
+
{{ xpath_or_value_input('Firstname', 'author_firstname', collection.author_firstname, collection_parser)
|
|
115
|
+
}}
|
|
116
|
+
{{ xpath_or_value_input('Lastname', 'author_lastname', collection.author_lastname, collection_parser) }}
|
|
117
|
+
{{ xpath_or_value_input('Fullname', 'author_fullname', collection.author_fullname, collection_parser) }}
|
|
118
|
+
<div class="mb-3 row">
|
|
119
|
+
<label class="col-sm-12 col-form-label text-center">
|
|
120
|
+
<i title="Set Date OR notBefore + notAfter!">
|
|
121
|
+
Date of Creation
|
|
122
|
+
<span class="text-danger">*</span>
|
|
123
|
+
</i>
|
|
124
|
+
</label>
|
|
125
|
+
</div>
|
|
126
|
+
{{ xpath_or_value_input('Date', 'work_publication_date',
|
|
127
|
+
collection.work_publication_date,
|
|
128
|
+
collection_parser) }}
|
|
129
|
+
{{ xpath_or_value_input('notBefore', 'work_publication_notBefore',
|
|
130
|
+
collection.work_publication_notBefore,
|
|
131
|
+
collection_parser) }}
|
|
132
|
+
{{ xpath_or_value_input('notAfter', 'work_publication_notAfter',
|
|
133
|
+
collection.work_publication_notAfter,
|
|
134
|
+
collection_parser) }}
|
|
135
|
+
<div class="mt-3 row text-center">
|
|
136
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
|
137
|
+
</div>
|
|
138
|
+
</form>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<!-- Tab 4: Edition -->
|
|
142
|
+
<div class="tab-pane fade" id="editionAttributes" role="tabpanel" aria-labelledby="edition-attributes-tab">
|
|
143
|
+
<form class="js-tab-submit" method="POST" data-reload-subtab="#editionAttributes"
|
|
144
|
+
action="{{ url_for('collection.save_collection_metadata', projectname=project.path, collectionname=collectionname) }}">
|
|
145
|
+
<div class="mb-3 row text-center">
|
|
146
|
+
<label class="col-sm-12 col-form-label text-center"><i>General</i>
|
|
147
|
+
</label>
|
|
148
|
+
</div>
|
|
149
|
+
{{ xpath_or_value_input('Title', 'edition_title', collection.edition_title, collection_parser) }}
|
|
150
|
+
{{ xpath_or_value_input('Author ID', 'edition_author', collection.edition_author, collection_parser) }}
|
|
151
|
+
{{ xpath_or_value_input('Language', 'language', collection.language, collection_parser) }}
|
|
152
|
+
{{ xpath_or_value_input('Wordcount', 'wordcount', collection.wordcount, collection_parser) }}
|
|
153
|
+
<div class="mb-3 row text-center">
|
|
154
|
+
<label class="col-sm-12 col-form-label text-center"><i>Publication</i>
|
|
155
|
+
</label>
|
|
156
|
+
</div>
|
|
157
|
+
{{ xpath_or_value_input('Date', 'edition_publication_date',
|
|
158
|
+
collection.edition_publication_date, collection_parser) }}
|
|
159
|
+
{{ xpath_or_value_input('Place', 'edition_publication_place',
|
|
160
|
+
collection.edition_publication_place, collection_parser) }}
|
|
161
|
+
<div class="mb-3 row text-center">
|
|
162
|
+
<label class="col-sm-12 col-form-label text-center"><i>License</i>
|
|
163
|
+
</label>
|
|
164
|
+
</div>
|
|
165
|
+
{{ xpath_or_value_input('Title', 'edition_license_title',
|
|
166
|
+
collection.edition_license_title, collection_parser) }}
|
|
167
|
+
{{ xpath_or_value_input('URL', 'edition_license_url',
|
|
168
|
+
collection.edition_license_url, collection_parser) }}
|
|
169
|
+
<div class="mt-3 row text-center">
|
|
170
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
|
171
|
+
</div>
|
|
172
|
+
</form>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<!-- Tab 5: ELTEC Specifications -->
|
|
176
|
+
<div class="tab-pane fade" id="eltecAttributes" role="tabpanel" aria-labelledby="eltecAttributes-tab">
|
|
177
|
+
<form class="js-tab-submit" method="POST" data-reload-subtab="#eltecAttributes"
|
|
178
|
+
action="{{ url_for('collection.save_collection_metadata', projectname=project.path, collectionname=collectionname) }}">
|
|
179
|
+
<div class="mb-3 row text-center">
|
|
180
|
+
<label class="col-sm-12 col-form-label text-center"><i>General</i>
|
|
181
|
+
</label>
|
|
182
|
+
</div>
|
|
183
|
+
{{ xpath_or_value_input('Author gender', 'eltec_author_gender', collection.eltec_author_gender,
|
|
184
|
+
collection_parser) }}
|
|
185
|
+
{{ xpath_or_value_input('Reprint count', 'eltec_reprintCount', collection.eltec_reprintCount,
|
|
186
|
+
collection_parser) }}
|
|
187
|
+
{{ xpath_or_value_input('Author gender', 'eltec_author_gender', collection.eltec_author_gender,
|
|
188
|
+
collection_parser) }}
|
|
189
|
+
{{ xpath_or_value_input('Timeslot', 'eltec_time_slot', collection.eltec_time_slot,
|
|
190
|
+
collection_parser) }}
|
|
191
|
+
{{ xpath_or_value_input('Corpus collection', 'eltec_corpus', collection.eltec_corpus,
|
|
192
|
+
collection_parser) }}
|
|
193
|
+
{{ xpath_or_value_input('Size', 'eltec_size', collection.eltec_size,
|
|
194
|
+
collection_parser) }}
|
|
195
|
+
<div class="mt-3 row text-center">
|
|
196
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
|
197
|
+
</div>
|
|
198
|
+
</form>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
{{ required_fields_disclaimer() }}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="text-center">
|
|
2
|
+
<h4 class="mb-3">Set Session ID of TextGrid-{{ instance|capitalize }} Instance</h4>
|
|
3
|
+
<form class="row justify-content-center pb-3 js-tab-submit" method="POST"
|
|
4
|
+
action="{{ url_for('publication.save_session_id', projectname=project.name, instance=instance) }}">
|
|
5
|
+
<input type="hidden" name="selected_instance" value="{{ instance }}">
|
|
6
|
+
<div class="col-md-6 mb-3">
|
|
7
|
+
<input type="text" class="form-control" name="tg_auth_session_id" placeholder="TgAuth Session ID"
|
|
8
|
+
value="{{ tg_session_id if tg_session_id }}">
|
|
9
|
+
</div>
|
|
10
|
+
<div class="col-md-2">
|
|
11
|
+
<button type="submit" class="btn btn-primary w-100">
|
|
12
|
+
<span class="bi bi-floppy2-fill"></span> Save
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
</form>
|
|
16
|
+
</div>
|