forked from enviPath/enviPy
[Feature] Modern UI roll out (#236)
This PR moves all the collection pages into the new UI in a rough push. I did not put the same amount of care into these as into search, index, and predict. ## Major changes - All modals are now migrated to a state based alpine.js implementation. - jQuery is no longer present in the base layout; ajax is replace by native fetch api - most of the pps.js is now obsolte (as I understand it; the code is not referenced any more @jebus please double check) - in-memory pagination for large result lists (set to 50; we can make that configurable later; performance degrades at around 1k) stukk a bit rough tracked in #235 ## Minor things - Sarch and index also use alpine now - The loading spinner is now CSS animated (not sure if it currently gets correctly called) ## Not done - Ihave not even cheked the admin pages. Not sure If these need migrations - The temporary migration pages still use the old template. Not sure what is supposed to happen with those? @jebus ## What I did to test - opend all pages in browse, and user ; plus all pages reachable from there. - Interacted and tested the functionality of each modal superfically with exception of the API key modal (no functional test). --- This PR is massive sorry for that; just did not want to push half-brokenn state. @jebus @liambrydon I would be glad if you could click around and try to break it :) Finally closes #133 Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#236 Co-authored-by: Tobias O <tobias.olenyi@envipath.com> Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
This commit is contained in:
@ -1,48 +0,0 @@
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
id="citemodal"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="myLargeModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>How to cite enviPath</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ol class="list-group list-group-numbered">
|
||||
<li class="list-group-item">
|
||||
Hafner, J., Lorsbach, T., Schmidt, S. <em>et al.</em>
|
||||
<cite
|
||||
>Advancements in biotransformation pathway prediction:
|
||||
enhancements, datasets, and novel functionalities in
|
||||
enviPath.</cite
|
||||
>
|
||||
<a href="https://doi.org/10.1186/s13321-024-00881-6" target="_blank"
|
||||
>J Cheminform 16, 93 (2024)</a
|
||||
>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
Wicker, J., Lorsbach, T., Gütlein, M., Schmid, E., Latino, D.,
|
||||
Kramer, S., Fenner, K.
|
||||
<cite
|
||||
>enviPath - The environmental contaminant biotransformation
|
||||
pathway resource</cite
|
||||
>
|
||||
<a href="https://doi.org/10.1093/nar/gkv1229" target="_blank">
|
||||
Nucleic Acids Research, Volume 44, Issue D1, 4 January 2016, Pages
|
||||
D502-D508
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,70 +1,85 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="import_legacy_package_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="import_legacy_package_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Import Package from legacy System</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Create a Package based on the JSON Export of the legacy system.</p>
|
||||
<form
|
||||
id="import-legacy-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label class="btn btn-primary" for="legacyJsonFile">
|
||||
<input
|
||||
id="legacyJsonFile"
|
||||
name="file"
|
||||
type="file"
|
||||
style="display:none;"
|
||||
onchange="$('#upload-legacy-file-info').html(this.files[0].name)"
|
||||
/>
|
||||
Choose JSON File
|
||||
</label>
|
||||
<span class="label label-info" id="upload-legacy-file-info"></span>
|
||||
<input
|
||||
type="hidden"
|
||||
value="import-legacy-package-json"
|
||||
name="hidden"
|
||||
readonly=""
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a
|
||||
id="import-legacy-package-modal-form-submit"
|
||||
class="btn btn-primary"
|
||||
href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Import Package from Legacy System</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Create a Package based on the JSON Export of the legacy system.
|
||||
</p>
|
||||
<form
|
||||
id="import-legacy-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Legacy JSON File</span>
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
id="legacyJsonFile"
|
||||
name="file"
|
||||
class="file-input file-input-bordered w-full"
|
||||
accept=".json"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
type="hidden"
|
||||
value="import-legacy-package-json"
|
||||
name="hidden"
|
||||
readonly
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('import-legacy-package-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Importing...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#import-legacy-package-modal-form-submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#import-legacy-package-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,70 +1,83 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="import_package_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="import_package_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Import Package</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Create a Package based on a JSON Export.</p>
|
||||
<form
|
||||
id="import-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label class="btn btn-primary" for="jsonFile">
|
||||
<input
|
||||
id="jsonFile"
|
||||
name="file"
|
||||
type="file"
|
||||
style="display:none;"
|
||||
onchange="$('#upload-file-info').html(this.files[0].name)"
|
||||
/>
|
||||
Choose JSON File
|
||||
</label>
|
||||
<span class="label label-info" id="upload-file-info"></span>
|
||||
<input
|
||||
type="hidden"
|
||||
value="import-package-json"
|
||||
name="hidden"
|
||||
readonly=""
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a
|
||||
id="import-package-modal-form-submit"
|
||||
class="btn btn-primary"
|
||||
href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Import Package</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">Create a Package based on a JSON Export.</p>
|
||||
<form
|
||||
id="import-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">JSON File</span>
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
id="jsonFile"
|
||||
name="file"
|
||||
class="file-input file-input-bordered w-full"
|
||||
accept=".json"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
type="hidden"
|
||||
value="import-package-json"
|
||||
name="hidden"
|
||||
readonly
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('import-package-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Importing...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#import-package-modal-form-submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#import-package-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,119 +1,137 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
|
||||
<dialog
|
||||
id="new_compound_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="new_compound_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Create a new Compound</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="new_compound_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package compound list' meta.current_package.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="compound-name">Name</label>
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Create a new Compound</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="new-compound-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package compound list' meta.current_package.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="compound-name"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<label for="compound-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="compound-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<label for="compound-smiles">SMILES</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-smiles">
|
||||
<span class="label-text">SMILES</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="compound-smiles"
|
||||
placeholder="SMILES"
|
||||
id="compound-smiles"
|
||||
/>
|
||||
<p></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="new_compound_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
<p></p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="new_compound_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<iframe
|
||||
id="new_compound_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new-compound-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function newCompoundModalketcherToNewCompoundModalTextInput() {
|
||||
$("#compound-smiles").val(this.ketcher.getSmiles());
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#new_compound_ketcher").on("load", function () {
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
document
|
||||
.getElementById("new_compound_ketcher")
|
||||
.addEventListener("load", function () {
|
||||
const iframe = this;
|
||||
const checkKetcherReady = () => {
|
||||
win = this.contentWindow;
|
||||
const win = iframe.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
win.ketcher.editor.event.change.handlers.push({
|
||||
once: false,
|
||||
priority: 0,
|
||||
f: newCompoundModalketcherToNewCompoundModalTextInput,
|
||||
f: function () {
|
||||
document.getElementById("compound-smiles").value =
|
||||
this.ketcher.getSmiles();
|
||||
},
|
||||
ketcher: win.ketcher,
|
||||
});
|
||||
} else {
|
||||
setTimeout(checkKetcherReady, 100);
|
||||
}
|
||||
};
|
||||
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$("#new_compound_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
// submit form
|
||||
$("#new_compound_modal_form").submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,70 +1,96 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
{% load static %}
|
||||
|
||||
<dialog
|
||||
id="new_group_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="new_group_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">New Group</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Create new Group. You can assign users to the group once it is
|
||||
created. Description can be changed after creation.
|
||||
</p>
|
||||
<form
|
||||
id="new_group_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ SERVER_BASE }}/group"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
name="group-name"
|
||||
class="form-control"
|
||||
placeholder="Name"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="description">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Description..."
|
||||
name="group-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="new_group_modal_form_submit" class="btn btn-primary" href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">New Group</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Create new Group. You can assign users to the group once it is created.
|
||||
Description can be changed after creation.
|
||||
</p>
|
||||
|
||||
<form
|
||||
id="new-group-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ SERVER_BASE }}/group"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="group-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="group-name"
|
||||
class="input input-bordered w-full"
|
||||
name="group-name"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="group-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="group-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Description..."
|
||||
name="group-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new-group-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#new_group_modal_form_submit").on("click", function () {
|
||||
$("#new_group_modal_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,30 +1,66 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="new_model_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="new_model_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
modelType: '',
|
||||
buildAppDomain: false,
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.modelType = '';
|
||||
this.buildAppDomain = false;
|
||||
},
|
||||
|
||||
get showMlrr() {
|
||||
return this.modelType === 'mlrr';
|
||||
},
|
||||
|
||||
get showRbrr() {
|
||||
return this.modelType === 'rbrr';
|
||||
},
|
||||
|
||||
get showEnviformer() {
|
||||
return this.modelType === 'enviformer';
|
||||
},
|
||||
|
||||
submit(formId) {
|
||||
const form = document.getElementById(formId);
|
||||
if (form && form.checkValidity()) {
|
||||
this.isSubmitting = true;
|
||||
form.submit();
|
||||
} else if (form) {
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">New Model</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="new_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_package.url }}/model"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="jumbotron">
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">New Model</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="new_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_package.url }}/model"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="alert alert-info mb-4">
|
||||
<span>
|
||||
Create a new Model to limit the number of degradation products in
|
||||
the prediction. You just need to set a name and the packages you
|
||||
want the object to be based on. There are multiple types of models
|
||||
@ -32,239 +68,270 @@
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/relative-reasoning"
|
||||
role="button"
|
||||
class="link"
|
||||
>wiki >></a
|
||||
>
|
||||
</div>
|
||||
<!-- Name -->
|
||||
<label for="model-name">Name</label>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Name -->
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="model-name"
|
||||
name="model-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<label for="model-description">Description</label>
|
||||
<!-- Description -->
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="model-description"
|
||||
name="model-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Description"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Model Type -->
|
||||
<label for="model-type">Model Type</label>
|
||||
<!-- Model Type -->
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-type">
|
||||
<span class="label-text">Model Type</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-type"
|
||||
name="model-type"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="modelType"
|
||||
required
|
||||
>
|
||||
<option disabled selected>Select Model Type</option>
|
||||
<option value="" disabled selected>Select Model Type</option>
|
||||
{% for k, v in model_types.items %}
|
||||
<option value="{{ v }}">{{ k }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Rule Packages -->
|
||||
<div id="rule-packages" class="ep-model-param mlrr rbrr">
|
||||
<label for="model-rule-packages">Rule Packages</label>
|
||||
<select
|
||||
id="model-rule-packages"
|
||||
name="model-rule-packages"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
multiple
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Reviewed Packages</option>
|
||||
<!-- Rule Packages (MLRR, RBRR) -->
|
||||
<div class="form-control mb-3" x-show="showMlrr || showRbrr" x-cloak>
|
||||
<label class="label" for="model-rule-packages">
|
||||
<span class="label-text">Rule Packages</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-rule-packages"
|
||||
name="model-rule-packages"
|
||||
class="select select-bordered w-full h-32"
|
||||
multiple
|
||||
>
|
||||
<optgroup label="Reviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<option disabled>Unreviewed Packages</option>
|
||||
</optgroup>
|
||||
<optgroup label="Unreviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</optgroup>
|
||||
</select>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Hold Ctrl/Cmd to select multiple</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Data Packages -->
|
||||
<div id="data-packages" class="ep-model-param mlrr rbrr enviformer">
|
||||
<label for="model-data-packages">Data Packages</label>
|
||||
<select
|
||||
id="model-data-packages"
|
||||
name="model-data-packages"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
multiple
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Reviewed Packages</option>
|
||||
<!-- Data Packages (MLRR, RBRR, Enviformer) -->
|
||||
<div
|
||||
class="form-control mb-3"
|
||||
x-show="showMlrr || showRbrr || showEnviformer"
|
||||
x-cloak
|
||||
>
|
||||
<label class="label" for="model-data-packages">
|
||||
<span class="label-text">Data Packages</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-data-packages"
|
||||
name="model-data-packages"
|
||||
class="select select-bordered w-full h-32"
|
||||
multiple
|
||||
>
|
||||
<optgroup label="Reviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<option disabled>Unreviewed Packages</option>
|
||||
</optgroup>
|
||||
<optgroup label="Unreviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</optgroup>
|
||||
</select>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Hold Ctrl/Cmd to select multiple</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Fingerprinter -->
|
||||
<div id="fingerprinter" class="ep-model-param mlrr">
|
||||
<label for="model-fingerprinter">Fingerprinter</label>
|
||||
<select
|
||||
id="model-fingerprinter"
|
||||
name="model-fingerprinter"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
multiple
|
||||
data-width="100%"
|
||||
>
|
||||
<option value="MACCS" selected>MACCS Fingerprinter</option>
|
||||
{% if meta.enabled_features.PLUGINS and additional_descriptors %}
|
||||
<option disabled selected>
|
||||
Select Additional Fingerprinter / Descriptor
|
||||
</option>
|
||||
<!-- Fingerprinter (MLRR) -->
|
||||
<div class="form-control mb-3" x-show="showMlrr" x-cloak>
|
||||
<label class="label" for="model-fingerprinter">
|
||||
<span class="label-text">Fingerprinter</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-fingerprinter"
|
||||
name="model-fingerprinter"
|
||||
class="select select-bordered w-full h-32"
|
||||
multiple
|
||||
>
|
||||
<option value="MACCS" selected>MACCS Fingerprinter</option>
|
||||
{% if meta.enabled_features.PLUGINS and additional_descriptors %}
|
||||
<optgroup label="Additional Fingerprinter / Descriptor">
|
||||
{% for k, v in additional_descriptors.items %}
|
||||
<option value="{{ v }}">{{ k }}</option>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
</optgroup>
|
||||
{% endif %}
|
||||
</select>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Hold Ctrl/Cmd to select multiple</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Threshold -->
|
||||
<div id="threshold" class="ep-model-param mlrr enviformer">
|
||||
<label for="model-threshold">Threshold</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
value="0.5"
|
||||
id="model-threshold"
|
||||
name="model-threshold"
|
||||
class="form-control"
|
||||
/>
|
||||
</div>
|
||||
<!-- Threshold (MLRR, Enviformer) -->
|
||||
<div
|
||||
class="form-control mb-3"
|
||||
x-show="showMlrr || showEnviformer"
|
||||
x-cloak
|
||||
>
|
||||
<label class="label" for="model-threshold">
|
||||
<span class="label-text">Threshold</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
value="0.5"
|
||||
id="model-threshold"
|
||||
name="model-threshold"
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="appdomain" class="ep-model-param mlrr">
|
||||
{% if meta.enabled_features.APPLICABILITY_DOMAIN %}
|
||||
<!-- Build AD? -->
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="build-app-domain"
|
||||
name="build-app-domain"
|
||||
/>Also build an Applicability Domain?
|
||||
<!-- Applicability Domain (MLRR) -->
|
||||
{% if meta.enabled_features.APPLICABILITY_DOMAIN %}
|
||||
<div x-show="showMlrr" x-cloak>
|
||||
<div class="form-control mb-3">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="build-app-domain"
|
||||
name="build-app-domain"
|
||||
class="checkbox"
|
||||
x-model="buildAppDomain"
|
||||
/>
|
||||
<span class="label-text"
|
||||
>Also build an Applicability Domain?</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="buildAppDomain" x-cloak class="ml-4 space-y-3">
|
||||
<div class="form-control">
|
||||
<label class="label" for="num-neighbors">
|
||||
<span class="label-text">Number of Neighbors</span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="ad-params" style="display:none">
|
||||
<!-- Num Neighbors -->
|
||||
<label for="num-neighbors">Number of Neighbors</label>
|
||||
<input
|
||||
id="num-neighbors"
|
||||
name="num-neighbors"
|
||||
type="number"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
value="5"
|
||||
step="1"
|
||||
min="0"
|
||||
max="10"
|
||||
/>
|
||||
<!-- Local Compatibility -->
|
||||
<label for="local-compatibility-threshold"
|
||||
>Local Compatibility Threshold</label
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="local-compatibility-threshold">
|
||||
<span class="label-text">Local Compatibility Threshold</span>
|
||||
</label>
|
||||
<input
|
||||
id="local-compatibility-threshold"
|
||||
name="local-compatibility-threshold"
|
||||
type="number"
|
||||
class="form-control"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
/>
|
||||
<!-- Reliability -->
|
||||
<label for="reliability-threshold">Reliability Threshold</label>
|
||||
<input
|
||||
id="reliability-threshold"
|
||||
name="reliability-threshold"
|
||||
type="number"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
/>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label" for="reliability-threshold">
|
||||
<span class="label-text">Reliability Threshold</span>
|
||||
</label>
|
||||
<input
|
||||
id="reliability-threshold"
|
||||
name="reliability-threshold"
|
||||
type="number"
|
||||
class="input input-bordered w-full"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="new_model_modal_form_submit" class="btn btn-primary" href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new_model_form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
// Built in Model Types
|
||||
var nativeModelTypes = ["mlrr", "rbrr", "enviformer"];
|
||||
|
||||
// Initially hide all "specific" forms
|
||||
$(".ep-model-param").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
$("#model-type").selectpicker();
|
||||
$("#model-fingerprinter").selectpicker();
|
||||
$("#model-rule-packages").selectpicker();
|
||||
$("#model-data-packages").selectpicker();
|
||||
|
||||
$("#build-app-domain").change(function () {
|
||||
if ($(this).is(":checked")) {
|
||||
$("#ad-params").show();
|
||||
} else {
|
||||
$("#ad-params").hide();
|
||||
}
|
||||
});
|
||||
|
||||
// On change hide all and show only selected
|
||||
$("#model-type").change(function () {
|
||||
$(".ep-model-param").hide();
|
||||
var modelType = $("#model-type").val();
|
||||
if (nativeModelTypes.indexOf(modelType) !== -1) {
|
||||
$("." + modelType).show();
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
|
||||
$("#new_model_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#new_model_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,68 +1,93 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
{% load static %}
|
||||
|
||||
<dialog
|
||||
id="new_package_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="new_package_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">New Package</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Create new package. Description can be changed later.</p>
|
||||
<form
|
||||
id="new_package_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
class="form-control"
|
||||
name="package-name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="description">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
type="text"
|
||||
rows="3"
|
||||
class="form-control"
|
||||
placeholder="Description..."
|
||||
name="package-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="new_package_modal_form_submit" class="btn btn-primary" href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">New Package</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">Create new package. Description can be changed later.</p>
|
||||
|
||||
<form
|
||||
id="new-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="package-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="package-name"
|
||||
class="input input-bordered w-full"
|
||||
name="package-name"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="package-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="package-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Description..."
|
||||
name="package-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new-package-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#new_package_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#new_package_modal_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,376 +0,0 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
id="new_pathway_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="new_pathway_modal"
|
||||
aria-hidden="true"
|
||||
style="overflow-y: auto;"
|
||||
>
|
||||
<!-- FIXME: make width dynamic-->
|
||||
<div class="modal-dialog" id="new_pathway_modal_dialog" style="width:900px">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="js-title-step"></h4>
|
||||
</div>
|
||||
<div class="modal-body hide" data-step="1" data-title="New Pathway">
|
||||
<div class="jumbotron">
|
||||
Create a new pathway by entering the root compound and a name. Then
|
||||
select if you want to use the prediction engine to generate a
|
||||
predicted pathway or create an empty pathway that you fill in by
|
||||
yourself. If you choose to predict a pathway, you can modify the
|
||||
settings for the prediction, or use the default settings and just
|
||||
click Submit.
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if current_user.name == 'anonymous' %}
|
||||
<div class="alert alert-warning">
|
||||
You are currently logged in as Anonymous. Please note: Pathways
|
||||
entered or predicted as anonymous user will be deleted after 30
|
||||
days. Please log in to save your results.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
class="form-control"
|
||||
name="name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<label for="description">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
class="form-control"
|
||||
name="description"
|
||||
placeholder="no description"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="predict">Predict pathway or build yourself?</label>
|
||||
<div class="radio" id="predict">
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioPredict"
|
||||
value="predict"
|
||||
checked
|
||||
/>Predict pathway
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioIncremental"
|
||||
value="incremental"
|
||||
/>Incremental prediction
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioBuild"
|
||||
value="build"
|
||||
/>Build pathway
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="smilesinput">SMILES</label>
|
||||
<table style="width: 100%">
|
||||
<colgroup>
|
||||
<col span="1" style="width: 90%;" />
|
||||
<col span="1" style="width: 10%;" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td>
|
||||
<input
|
||||
id="smilesinput"
|
||||
class="form-control"
|
||||
name="smilesinput"
|
||||
placeholder="C1CCCCC1"
|
||||
autocapitalize="none"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-default" id="render-button">
|
||||
Render
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p id="ketcher_container"></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="ifKetcher"
|
||||
src="{% static '/js/ketcher/ketcher.html' %}"
|
||||
width="850"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="modal-body hide"
|
||||
data-step="2"
|
||||
data-title="New Pathway - Advanced Settings"
|
||||
>
|
||||
<div class="jumbotron">
|
||||
Choose if you want to use an existing setting, or create a new one for
|
||||
this pathway prediction. Then click Submit to use the specified
|
||||
setting, or click next to set the parameters.
|
||||
</div>
|
||||
<div id="settings">
|
||||
<div class="radio" id="settingRadio">
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="existing"
|
||||
id="radioDefault"
|
||||
value="exisiting"
|
||||
checked
|
||||
/>
|
||||
Use Default
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="existing"
|
||||
id="radioExists"
|
||||
value="exisiting"
|
||||
/>
|
||||
Select Existing
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="existing"
|
||||
id="radioNew"
|
||||
value="temporary"
|
||||
/>
|
||||
Create New
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<select id="settingSelect" name="settingSelect" class="form-control">
|
||||
{% for setting in available_settings %}
|
||||
<option value="{{ setting.id }}">{{ setting.name|safe }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
{% with step_offset=1 %}
|
||||
{% include "templates/modals/collections/new_setting_modal_body.html" %}
|
||||
{% endwith %}
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default js-btn-step pull-left"
|
||||
data-orientation="cancel"
|
||||
onclick="reset()"
|
||||
data-dismiss="modal"
|
||||
></button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default js-btn-step"
|
||||
data-orientation="previous"
|
||||
id="backbutton"
|
||||
></button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default js-btn-step"
|
||||
data-orientation="next"
|
||||
id="nextbutton"
|
||||
></button>
|
||||
<a id="modal-form-submit" class="btn btn-primary" href="#">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
s = new Setting(
|
||||
"settingName",
|
||||
"package_multi_select",
|
||||
"modelSelect",
|
||||
"cutoff",
|
||||
"evalType",
|
||||
"availableTS",
|
||||
"forms",
|
||||
"truncatorTable",
|
||||
"summaryTable",
|
||||
);
|
||||
|
||||
$(function () {
|
||||
// hide all forms
|
||||
$("#forms").children().hide();
|
||||
|
||||
$("#render-button").on("click", function () {
|
||||
syncKetcherAndTextInput("text", "ifKetcher", "smilesinput");
|
||||
});
|
||||
|
||||
// If theres a change in the in '#smilesinput' sync the value to ketcher
|
||||
$("#smilesinput").on("input", function () {
|
||||
syncKetcherAndTextInput("text", "ifKetcher", "smilesinput");
|
||||
});
|
||||
|
||||
// If theres an update in ketcher sync it to textinput
|
||||
setInterval(function () {
|
||||
syncKetcherAndTextInput("ketcher", "ifKetcher", "smilesinput");
|
||||
}, 250);
|
||||
|
||||
$("#smilesinput").on("blur", function () {
|
||||
syncKetcherAndTextInput("text", "ifKetcher", "smilesinput");
|
||||
});
|
||||
|
||||
$("#smilesinput").on("keypress", function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
syncKetcherAndTextInput("text", "ifKetcher", "smilesinput");
|
||||
}
|
||||
});
|
||||
|
||||
// Show forms depending on the selected TS
|
||||
$("#availableTS").on("change", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var type = $(this).val();
|
||||
// hide current content
|
||||
$("#forms").children().hide();
|
||||
|
||||
if (type === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
$("#" + type + "_form").show();
|
||||
});
|
||||
|
||||
$("#modelSelect").on("change", function () {
|
||||
setCutoff = function (thresh) {
|
||||
$("#cutoff").val(thresh);
|
||||
};
|
||||
|
||||
var modelUri = $("#modelSelect :selected").val();
|
||||
fillPRCurve(modelUri, setCutoff);
|
||||
});
|
||||
|
||||
// Add a TS to the setting
|
||||
$("#add-ts-button").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
s.addTruncator();
|
||||
});
|
||||
|
||||
$("input[type=radio][name=predict]").change(function () {
|
||||
if (this.id == "radioBuild") {
|
||||
$("#nextbutton").prop("disabled", true);
|
||||
} else {
|
||||
$("#nextbutton").prop("disabled", false);
|
||||
}
|
||||
});
|
||||
|
||||
$("input[type=radio][name=existing]").change(function () {
|
||||
if (this.id == "radioDefault" || this.id == "radioExists") {
|
||||
if (this.id == "radioDefault") {
|
||||
$("#settingSelect").prop("disabled", true);
|
||||
} else {
|
||||
$("#settingSelect").prop("disabled", false);
|
||||
}
|
||||
$("#nextbutton").prop("disabled", true);
|
||||
} else {
|
||||
// build...
|
||||
$("#settingSelect").prop("disabled", true);
|
||||
$("#nextbutton").prop("disabled", false);
|
||||
}
|
||||
});
|
||||
|
||||
var pwStep1 = function () {
|
||||
console.log("pw step 1");
|
||||
// Make "Next" to "Advanced"
|
||||
$("#nextbutton").val("Advanced");
|
||||
};
|
||||
|
||||
var pwStep2 = function () {
|
||||
console.log("pw step 2");
|
||||
// Make "Advanced" to "Next"
|
||||
$("#nextbutton").val("Next");
|
||||
// As "Use default is preselected" disable "Next" button
|
||||
$("#nextbutton").prop("disabled", true);
|
||||
// Disable setting dropdown as long as the correspndonding radio isnt checked
|
||||
$("#settingSelect").prop("disabled", true);
|
||||
// Show submit button
|
||||
$("#modal-form-submit").show();
|
||||
};
|
||||
|
||||
var settingStep1 = function () {
|
||||
// First step sets name and packages
|
||||
s.extractName();
|
||||
s.extractSelectedPackages();
|
||||
};
|
||||
|
||||
var settingStep2 = function () {
|
||||
// Seconds step gathers relative reasoning params
|
||||
s.extractRelativeReasoning();
|
||||
s.extractCutoff();
|
||||
s.extractEvaluationType();
|
||||
};
|
||||
|
||||
var settingStep3 = function () {
|
||||
s.updateTable();
|
||||
s.updateSummaryTable();
|
||||
// hide duplicate submit...
|
||||
$("#nextbutton").hide();
|
||||
};
|
||||
|
||||
var postPathway = function () {
|
||||
console.log("Complete!");
|
||||
console.log(s.tsParams);
|
||||
console.log("Getting SMILES");
|
||||
};
|
||||
|
||||
function dummy() {
|
||||
console.log("dummy");
|
||||
}
|
||||
|
||||
$("#new_pathway_modal").modalSteps({
|
||||
btnCancelHtml: "Cancel",
|
||||
btnPreviousHtml: "Back",
|
||||
btnNextHtml: "Next",
|
||||
btnLastStepHtml: "Submit",
|
||||
disableNextButton: false,
|
||||
completeCallback: postPathway,
|
||||
callbacks: {
|
||||
1: pwStep1,
|
||||
2: pwStep2,
|
||||
3: dummy,
|
||||
4: settingStep1,
|
||||
5: settingStep2,
|
||||
6: settingStep3,
|
||||
},
|
||||
});
|
||||
|
||||
$("#modal-form-submit").on("click", function () {
|
||||
e.preventDefault();
|
||||
postPathway();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -1,185 +1,260 @@
|
||||
{% load static %}
|
||||
|
||||
<div id="new_prediction_setting_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Create a Prediction Setting</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
To create a Prediction Setting fill the form below and click "Create"
|
||||
</p>
|
||||
<form
|
||||
id="new-prediction-setting-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<dialog
|
||||
id="new_prediction_setting_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
tpMethod: '',
|
||||
|
||||
<label for="prediction-setting-name">Name</label>
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.tpMethod = '';
|
||||
},
|
||||
|
||||
async submit() {
|
||||
const form = document.getElementById('new-prediction-setting-modal-form');
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSubmitting = true;
|
||||
const formData = new FormData(form);
|
||||
|
||||
try {
|
||||
const response = await fetch('/setting', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
if (response.ok) {
|
||||
location.reload();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating setting:', error);
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box max-w-2xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Create a Prediction Setting</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
To create a Prediction Setting fill the form below and click "Create"
|
||||
</p>
|
||||
<form
|
||||
id="new-prediction-setting-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="prediction-setting-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="prediction-setting-name"
|
||||
name="prediction-setting-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<label for="prediction-setting-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="prediction-setting-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="prediction-setting-description"
|
||||
name="prediction-setting-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Description"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label for="prediction-setting-max-nodes">Max #Nodes</label>
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="prediction-setting-max-nodes">
|
||||
<span class="label-text">Max #Nodes</span>
|
||||
</label>
|
||||
<input
|
||||
id="prediction-setting-max-nodes"
|
||||
type="number"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="prediction-setting-max-nodes"
|
||||
value="30"
|
||||
min="1"
|
||||
max="50"
|
||||
step="1"
|
||||
/>
|
||||
<label for="prediction-setting-max-depth">Max Depth</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="prediction-setting-max-depth">
|
||||
<span class="label-text">Max Depth</span>
|
||||
</label>
|
||||
<input
|
||||
id="prediction-setting-max-depth"
|
||||
type="number"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="prediction-setting-max-depth"
|
||||
value="5"
|
||||
min="1"
|
||||
max="8"
|
||||
step="1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label for="tp-generation-method">TP Generation Method</label>
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="tp-generation-method">
|
||||
<span class="label-text">TP Generation Method</span>
|
||||
</label>
|
||||
<select
|
||||
id="tp-generation-method"
|
||||
name="tp-generation-method"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="tpMethod"
|
||||
required
|
||||
>
|
||||
<option disabled selected>Select how TPs are generated</option>
|
||||
<option value="" disabled selected>
|
||||
Select how TPs are generated
|
||||
</option>
|
||||
<option value="rule-based-prediction-setting">Rule Based</option>
|
||||
<option value="model-based-prediction-setting">Model Based</option>
|
||||
</select>
|
||||
<div id="rule-based-prediction-setting-specific-form">
|
||||
<!-- Rule Packages -->
|
||||
<label>Rule Packages</label><br />
|
||||
</div>
|
||||
|
||||
<!-- Rule Based Settings -->
|
||||
<div x-show="tpMethod === 'rule-based-prediction-setting'" x-cloak>
|
||||
<div class="form-control mb-3">
|
||||
<label class="label">
|
||||
<span class="label-text">Rule Packages</span>
|
||||
</label>
|
||||
<select
|
||||
id="rule-based-prediction-setting-packages"
|
||||
name="rule-based-prediction-setting-packages"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
class="select select-bordered w-full h-32"
|
||||
multiple
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Reviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<option disabled>Unreviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<optgroup label="Reviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
<optgroup label="Unreviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
</select>
|
||||
<label class="label">
|
||||
<span class="label-text-alt"
|
||||
>Hold Ctrl/Cmd to select multiple</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div id="model-based-prediction-setting-specific-form">
|
||||
<label>Select Model</label><br />
|
||||
</div>
|
||||
|
||||
<!-- Model Based Settings -->
|
||||
<div x-show="tpMethod === 'model-based-prediction-setting'" x-cloak>
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-based-prediction-setting-model">
|
||||
<span class="label-text">Select Model</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-based-prediction-setting-model"
|
||||
name="model-based-prediction-setting-model"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
>
|
||||
<option disabled selected>Select the model</option>
|
||||
<option value="" disabled selected>Select the model</option>
|
||||
{% for m in models %}
|
||||
<option value="{{ m.url }}">{{ m.name|safe }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="model-based-prediction-setting-threshold"
|
||||
>Threshold</label
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-based-prediction-setting-threshold">
|
||||
<span class="label-text">Threshold</span>
|
||||
</label>
|
||||
<input
|
||||
id="model-based-prediction-setting-threshold"
|
||||
name="model-based-prediction-setting-threshold"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="0.25"
|
||||
type="number"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value="on"
|
||||
id="prediction-setting-new-default"
|
||||
name="prediction-setting-new-default"
|
||||
/>
|
||||
<label class="form-check-label" for="prediction-setting-new-default"
|
||||
>Set this setting as new default</label
|
||||
>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="new-prediction-setting-modal-submit"
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
value="on"
|
||||
id="prediction-setting-new-default"
|
||||
name="prediction-setting-new-default"
|
||||
/>
|
||||
<span class="label-text">Set this setting as new default</span>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Create</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
// Initially hide all "specific" forms
|
||||
$("div[id$='-specific-form']").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
$("#rule-based-prediction-setting-packages").selectpicker();
|
||||
|
||||
// On change hide all and show only selected
|
||||
$("#tp-generation-method").change(function () {
|
||||
$("div[id$='-specific-form']").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
val = $("option:selected", this).val();
|
||||
$("#" + val + "-specific-form").show();
|
||||
});
|
||||
|
||||
$("#new-prediction-setting-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
// $('#new-prediction-setting-modal-form').submit();
|
||||
|
||||
const formData = $("#new-prediction-setting-modal-form").serialize();
|
||||
$.post("/setting", formData, function (response) {
|
||||
location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,91 +1,105 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
|
||||
<dialog
|
||||
id="new_reaction_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="new_reaction_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Create a new Reaction</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="new_reaction_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package reaction list' meta.current_package.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="reaction-name">Name</label>
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Create a new Reaction</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="new-reaction-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package reaction list' meta.current_package.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="reaction-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="reaction-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="reaction-name"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<label for="reaction-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="reaction-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="reaction-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="reaction-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<p></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="new_reaction_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
<input type="hidden" name="reaction-smirks" id="reaction-smirks" />
|
||||
<p></p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="new_reaction_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<iframe
|
||||
id="new_reaction_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="reaction-smirks" id="reaction-smirks" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="
|
||||
const k = getKetcher('new_reaction_ketcher');
|
||||
document.getElementById('reaction-smirks').value = k.getSmiles();
|
||||
submit('new-reaction-modal-form');
|
||||
"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#new_reaction_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
k = getKetcher("new_reaction_ketcher");
|
||||
$("#reaction-smirks").val(k.getSmiles());
|
||||
|
||||
// submit form
|
||||
$("#new_reaction_modal_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,120 +1,140 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
|
||||
<dialog
|
||||
id="new_rule_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="new_rule_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="{
|
||||
...modalForm(),
|
||||
smirksVizHtml: '',
|
||||
updateSmirksViz() {
|
||||
const smirks = document.getElementById('rule-smirks').value;
|
||||
if (!smirks) {
|
||||
this.smirksVizHtml = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const img = new Image();
|
||||
img.src = '{% url 'depict' %}?is_query_smirks=true&smirks=' + encodeURIComponent(smirks);
|
||||
img.style.width = '100%';
|
||||
img.style.height = '100%';
|
||||
img.style.objectFit = 'cover';
|
||||
|
||||
img.onload = () => {
|
||||
this.smirksVizHtml = img.outerHTML;
|
||||
};
|
||||
|
||||
img.onerror = () => {
|
||||
this.smirksVizHtml = `
|
||||
<div class='alert alert-error' role='alert'>
|
||||
<h4 class='alert-heading'>Could not render SMIRKS!</h4>
|
||||
<p>Could not render SMIRKS - Have you entered a valid SMIRKS?</p>
|
||||
</div>`;
|
||||
};
|
||||
}
|
||||
}"
|
||||
@close="reset(); smirksVizHtml = ''"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Create a new Rule</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="new_rule_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package rule list' meta.current_package.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="rule-name">Name</label>
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Create a new Rule</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="new-rule-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package rule list' meta.current_package.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="rule-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="rule-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="rule-name"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<label for="rule-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="rule-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="rule-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="rule-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<label for="rule-smirks">SMIRKS</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="rule-smirks">
|
||||
<span class="label-text">SMIRKS</span>
|
||||
</label>
|
||||
<input
|
||||
id="rule-smirks"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="rule-smirks"
|
||||
placeholder="SMIRKS"
|
||||
@input="updateSmirksViz()"
|
||||
/>
|
||||
<p></p>
|
||||
<div id="rule-smirks-viz"></div>
|
||||
<input
|
||||
type="hidden"
|
||||
name="rule-type"
|
||||
id="rule-type"
|
||||
value="SimpleAmbitRule"
|
||||
/>
|
||||
<p></p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="new_rule_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="rule-smirks-viz" class="mb-3" x-html="smirksVizHtml"></div>
|
||||
|
||||
<input
|
||||
type="hidden"
|
||||
name="rule-type"
|
||||
id="rule-type"
|
||||
value="SimpleAmbitRule"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new-rule-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#rule-smirks").on("input", function (e) {
|
||||
$("#rule-smirks-viz").empty();
|
||||
|
||||
smirks = $("#rule-smirks").val();
|
||||
|
||||
const img = new Image();
|
||||
img.src =
|
||||
"{% url 'depict' %}?is_query_smirks=true&smirks=" +
|
||||
encodeURIComponent(smirks);
|
||||
img.style.width = "100%";
|
||||
img.style.height = "100%";
|
||||
img.style.objectFit = "cover";
|
||||
|
||||
img.onload = function () {
|
||||
$("#rule-smirks-viz").append(img);
|
||||
};
|
||||
|
||||
img.onerror = function () {
|
||||
error_tpl = `
|
||||
<div class="alert alert-error" role="alert">
|
||||
<h4 class="alert-heading">Could not render SMIRKS!</h4>
|
||||
<p>Could not render SMIRKS - Have you entered a valid SMIRKS?</a>
|
||||
</p>
|
||||
</div>`;
|
||||
$("#rule-smirks-viz").append(error_tpl);
|
||||
};
|
||||
});
|
||||
|
||||
$("#new_rule_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
// submit form
|
||||
$("#new_rule_modal_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,30 +1,45 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
{% load static %}
|
||||
|
||||
<dialog
|
||||
id="new_scenario_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="new_scenario_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="{
|
||||
...modalForm(),
|
||||
scenarioType: 'empty',
|
||||
validateYear(el) {
|
||||
if (el.value && el.value.length < 4) {
|
||||
el.value = new Date().getFullYear();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">New Scenario</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="new_scenario_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_package.url }}/scenario"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="jumbotron">
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">New Scenario</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="new-scenario-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_package.url }}/scenario"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="alert alert-info mb-4">
|
||||
<span>
|
||||
Please enter name, description, and date of scenario. Date should be
|
||||
associated to the data, not the current date. For example, this
|
||||
could reflect the publishing date of a study. You can leave all
|
||||
@ -32,122 +47,131 @@
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/scenario"
|
||||
role="button"
|
||||
class="link"
|
||||
>wiki >></a
|
||||
>
|
||||
</div>
|
||||
<label for="scenario-name">Name</label>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="scenario-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="scenario-name"
|
||||
name="scenario-name"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Name"
|
||||
required
|
||||
/>
|
||||
<label for="scenario-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="scenario-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="scenario-description"
|
||||
name="scenario-description"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<label id="dateField" for="dateYear">Date</label>
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
<input
|
||||
type="number"
|
||||
id="dateYear"
|
||||
name="scenario-date-year"
|
||||
class="form-control"
|
||||
placeholder="YYYY"
|
||||
max="{% now "Y" %}"
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<input
|
||||
type="number"
|
||||
id="dateMonth"
|
||||
name="scenario-date-month"
|
||||
min="1"
|
||||
max="12"
|
||||
class="form-control"
|
||||
placeholder="MM"
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<input
|
||||
type="number"
|
||||
id="dateDay"
|
||||
name="scenario-date-day"
|
||||
min="1"
|
||||
max="31"
|
||||
class="form-control"
|
||||
placeholder="DD"
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
<label for="scenario-type">Scenario Type</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label">
|
||||
<span class="label-text">Date</span>
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
type="number"
|
||||
id="dateYear"
|
||||
name="scenario-date-year"
|
||||
class="input input-bordered w-24"
|
||||
placeholder="YYYY"
|
||||
max="{% now 'Y' %}"
|
||||
@blur="validateYear($el)"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
id="dateMonth"
|
||||
name="scenario-date-month"
|
||||
min="1"
|
||||
max="12"
|
||||
class="input input-bordered w-20"
|
||||
placeholder="MM"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
id="dateDay"
|
||||
name="scenario-date-day"
|
||||
min="1"
|
||||
max="31"
|
||||
class="input input-bordered w-20"
|
||||
placeholder="DD"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="scenario-type">
|
||||
<span class="label-text">Scenario Type</span>
|
||||
</label>
|
||||
<select
|
||||
id="scenario-type"
|
||||
name="scenario-type"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="scenarioType"
|
||||
>
|
||||
<option value="empty" selected>Empty Scenario</option>
|
||||
{% for k, v in scenario_types.items %}
|
||||
<option value="{{ v.name }}">{{ k }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{% for type in scenario_types.values %}
|
||||
<div id="{{ type.name }}-specific-inputs">
|
||||
{% for widget in type.widgets %}
|
||||
{{ widget|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="new_scenario_modal_form_submit" class="btn btn-primary" href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
{% for type in scenario_types.values %}
|
||||
<div
|
||||
id="{{ type.name }}-specific-inputs"
|
||||
x-show="scenarioType === '{{ type.name }}'"
|
||||
x-cloak
|
||||
>
|
||||
{% for widget in type.widgets %}
|
||||
{{ widget|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('new-scenario-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Creating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
// Initially hide all "specific" forms
|
||||
$("div[id$='-specific-inputs']").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
// On change hide all and show only selected
|
||||
$("#scenario-type").change(function () {
|
||||
$("div[id$='-specific-inputs']").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
val = $("option:selected", this).val();
|
||||
$("#" + val + "-specific-inputs").show();
|
||||
});
|
||||
|
||||
$("#new_scenario_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#new_scenario_form").submit();
|
||||
});
|
||||
|
||||
var dateYear = document.getElementById("dateYear");
|
||||
dateYear.addEventListener("change", () => {
|
||||
console.log("Final value after editing:", dateYear.value);
|
||||
if (dateYear.value.length < 4) {
|
||||
dateYear.value = new Date().getFullYear();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,92 +1,117 @@
|
||||
{% load static %}
|
||||
<!-- Add Additional Information-->
|
||||
<div id="add_additional_information_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Add Additional Information</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Add Additional Information -->
|
||||
<dialog
|
||||
id="add_additional_information_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
selectedType: '',
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.selectedType = '';
|
||||
},
|
||||
|
||||
submit() {
|
||||
if (!this.selectedType) return;
|
||||
|
||||
const form = document.getElementById('add_' + this.selectedType + '_add-additional-information-modal-form');
|
||||
if (form && form.checkValidity()) {
|
||||
this.isSubmitting = true;
|
||||
form.submit();
|
||||
} else if (form) {
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Add Additional Information</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="select-additional-information-type">
|
||||
<span class="label-text">Select the type to add</span>
|
||||
</label>
|
||||
<select
|
||||
id="select-additional-information-type"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="selectedType"
|
||||
>
|
||||
<option selected disabled>Select the type to add</option>
|
||||
<option value="" selected disabled>Select the type to add</option>
|
||||
{% for add_inf in available_additional_information %}
|
||||
<option value="{{ add_inf.name }}">
|
||||
{{ add_inf.display_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% for add_inf in available_additional_information %}
|
||||
<div class="aiform {{ add_inf.name }}" style="display: none;">
|
||||
<form
|
||||
id="add_{{ add_inf.name }}_add-additional-information-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
{{ add_inf.widget|safe }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="add-additional-information"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="add-additional-information-modal-submit"
|
||||
|
||||
{% for add_inf in available_additional_information %}
|
||||
<div
|
||||
class="mt-4"
|
||||
x-show="selectedType === '{{ add_inf.name }}'"
|
||||
x-cloak
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
<form
|
||||
id="add_{{ add_inf.name }}_add-additional-information-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
{{ add_inf.widget|safe }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="add-additional-information"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting || !selectedType"
|
||||
>
|
||||
<span x-show="!isSubmitting">Add</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Adding...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#select-additional-information-type").change(function (e) {
|
||||
var selectedType = $(
|
||||
"#select-additional-information-type :selected",
|
||||
).val();
|
||||
$(".aiform").hide();
|
||||
$("." + selectedType).show();
|
||||
});
|
||||
|
||||
$("#add-additional-information-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var selectedType = $(
|
||||
"#select-additional-information-type :selected",
|
||||
).val();
|
||||
console.log(selectedType);
|
||||
if (
|
||||
selectedType !== null &&
|
||||
selectedType !== undefined &&
|
||||
selectedType !== ""
|
||||
) {
|
||||
$("." + selectedType + " >form").submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,67 +1,107 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
<dialog
|
||||
id="add_pathway_edge_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="add_pathway_edge_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
reactionImageUrl: '',
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.reactionImageUrl = '';
|
||||
},
|
||||
|
||||
updateReactionImage() {
|
||||
const substratesSelect = document.getElementById('add_pathway_edge_substrates');
|
||||
const productsSelect = document.getElementById('add_pathway_edge_products');
|
||||
|
||||
const substrates = [];
|
||||
for (const option of substratesSelect.selectedOptions) {
|
||||
substrates.push(option.dataset.smiles);
|
||||
}
|
||||
|
||||
const products = [];
|
||||
for (const option of productsSelect.selectedOptions) {
|
||||
products.push(option.dataset.smiles);
|
||||
}
|
||||
|
||||
if (substrates.length > 0 && products.length > 0) {
|
||||
const reaction = substrates.join('.') + '>>' + products.join('.');
|
||||
this.reactionImageUrl = '{% url "depict" %}?smirks=' + encodeURIComponent(reaction);
|
||||
} else {
|
||||
this.reactionImageUrl = '';
|
||||
}
|
||||
},
|
||||
|
||||
submit() {
|
||||
this.isSubmitting = true;
|
||||
document.getElementById('add_pathway_edge_modal_form').submit();
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Add a Reaction</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="add_pathway_edge_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package pathway edge list' meta.current_package.uuid pathway.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="edge-name">Name</label>
|
||||
<div class="modal-box max-w-4xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Add a Reaction</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="add_pathway_edge_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package pathway edge list' meta.current_package.uuid pathway.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="edge-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="edge-name"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="edge-name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<label for="edge-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="edge-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="edge-description"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="edge-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<p></p>
|
||||
<div class="row">
|
||||
<div class="col-xs-5">
|
||||
<legend>Substrate(s)</legend>
|
||||
</div>
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-5">
|
||||
<legend>Product(s)</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-5">
|
||||
</div>
|
||||
|
||||
<div class="mb-3 grid grid-cols-11 gap-2">
|
||||
<div class="col-span-5">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-semibold">Substrate(s)</span>
|
||||
</label>
|
||||
<select
|
||||
id="add_pathway_edge_substrates"
|
||||
name="edge-substrates"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
class="select select-bordered h-32 w-full"
|
||||
multiple
|
||||
data-width="100%"
|
||||
@change="updateReactionImage()"
|
||||
>
|
||||
{% for n in pathway.nodes %}
|
||||
<option
|
||||
@ -73,20 +113,21 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
class="col-xs-2"
|
||||
style="display: flex; justify-content: center; align-items: center;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-arrow-right"></i>
|
||||
</div>
|
||||
<div class="col-xs-5">
|
||||
</div>
|
||||
<div class="col-span-1 flex items-center justify-center">
|
||||
<span class="text-2xl">→</span>
|
||||
</div>
|
||||
<div class="col-span-5">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text font-semibold">Product(s)</span>
|
||||
</label>
|
||||
<select
|
||||
id="add_pathway_edge_products"
|
||||
name="edge-products"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
class="select select-bordered h-32 w-full"
|
||||
multiple
|
||||
data-width="100%"
|
||||
@change="updateReactionImage()"
|
||||
>
|
||||
{% for n in pathway.nodes %}
|
||||
<option
|
||||
@ -99,76 +140,42 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p></p>
|
||||
<div class="col-xs-12" id="reaction_image"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="add_pathway_edge_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3" x-show="reactionImageUrl" x-cloak>
|
||||
<img :src="reactionImageUrl" class="w-full" alt="Reaction preview" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function reactionImage() {
|
||||
var substrates = [];
|
||||
$("#add_pathway_edge_substrates option:selected").each(function () {
|
||||
var smiles = $(this).data("smiles"); // read data-smiles attribute
|
||||
substrates.push(smiles);
|
||||
});
|
||||
|
||||
var products = [];
|
||||
$("#add_pathway_edge_products option:selected").each(function () {
|
||||
var smiles = $(this).data("smiles"); // read data-smiles attribute
|
||||
products.push(smiles);
|
||||
});
|
||||
|
||||
if (substrates.length > 0 && products.length > 0) {
|
||||
reaction = substrates.join(".") + ">>" + products.join(".");
|
||||
$("#reaction_image").empty();
|
||||
$("#reaction_image").append(
|
||||
"<img width='100%' src='{% url 'depict' %}?smirks=" +
|
||||
encodeURIComponent(reaction) +
|
||||
"'>",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#add_pathway_edge_substrates").selectpicker();
|
||||
$("#add_pathway_edge_products").selectpicker();
|
||||
|
||||
$("#add_pathway_edge_substrates").on("change", function (e) {
|
||||
reactionImage();
|
||||
});
|
||||
|
||||
$("#add_pathway_edge_products").on("change", function (e) {
|
||||
reactionImage();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$("#add_pathway_edge_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
// submit form
|
||||
$("#add_pathway_edge_modal_form").submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,119 +1,137 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
<dialog
|
||||
id="add_pathway_node_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="add_pathway_node_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Add a Node</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="add_pathway_node_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package pathway node list' meta.current_package.uuid pathway.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="node-name">Name</label>
|
||||
<div class="modal-box max-w-4xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Add a Node</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="add_pathway_node_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package pathway node list' meta.current_package.uuid pathway.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="node-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="node-name"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="node-name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<label for="node-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="node-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="node-description"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="node-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<label for="node-smiles">SMILES</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="node-smiles">
|
||||
<span class="label-text">SMILES</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="node-smiles"
|
||||
placeholder="SMILES"
|
||||
id="node-smiles"
|
||||
/>
|
||||
<p></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="add_node_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
<p></p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="add_pathway_node_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<iframe
|
||||
id="add_node_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('add_pathway_node_modal_form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function newStructureModalketcherToNewStructureModalTextInput() {
|
||||
$("#node-smiles").val(this.ketcher.getSmiles());
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#add_node_ketcher").on("load", function () {
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
document
|
||||
.getElementById("add_node_ketcher")
|
||||
.addEventListener("load", function () {
|
||||
const iframe = this;
|
||||
const checkKetcherReady = () => {
|
||||
win = this.contentWindow;
|
||||
const win = iframe.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
win.ketcher.editor.event.change.handlers.push({
|
||||
once: false,
|
||||
priority: 0,
|
||||
f: newStructureModalketcherToNewStructureModalTextInput,
|
||||
f: function () {
|
||||
document.getElementById("node-smiles").value =
|
||||
this.ketcher.getSmiles();
|
||||
},
|
||||
ketcher: win.ketcher,
|
||||
});
|
||||
} else {
|
||||
setTimeout(checkKetcherReady, 100);
|
||||
}
|
||||
};
|
||||
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$("#add_pathway_node_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
// submit form
|
||||
$("#add_pathway_node_modal_form").submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,119 +1,137 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
<dialog
|
||||
id="add_structure_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="add_structure_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Create a new Structure</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="add_structure_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package compound structure list' meta.current_package.uuid compound.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="structure-name">Name</label>
|
||||
<div class="modal-box max-w-4xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Create a new Structure</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="add_structure_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{% url 'package compound structure list' meta.current_package.uuid compound.uuid %}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="structure-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="structure-name"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="structure-name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<label for="structure-description">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="structure-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="structure-description"
|
||||
class="form-control"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="structure-description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
<label for="structure-smiles">SMILES</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="structure-smiles">
|
||||
<span class="label-text">SMILES</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered w-full"
|
||||
name="structure-smiles"
|
||||
placeholder="SMILES"
|
||||
id="structure-smiles"
|
||||
/>
|
||||
<p></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="add_structure_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
<p></p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="add_structure_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<iframe
|
||||
id="add_structure_ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('add_structure_modal_form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function newStructureModalketcherToNewStructureModalTextInput() {
|
||||
$("#structure-smiles").val(this.ketcher.getSmiles());
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#add_structure_ketcher").on("load", function () {
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
document
|
||||
.getElementById("add_structure_ketcher")
|
||||
.addEventListener("load", function () {
|
||||
const iframe = this;
|
||||
const checkKetcherReady = () => {
|
||||
win = this.contentWindow;
|
||||
const win = iframe.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
win.ketcher.editor.event.change.handlers.push({
|
||||
once: false,
|
||||
priority: 0,
|
||||
f: newStructureModalketcherToNewStructureModalTextInput,
|
||||
f: function () {
|
||||
document.getElementById("structure-smiles").value =
|
||||
this.ketcher.getSmiles();
|
||||
},
|
||||
ketcher: win.ketcher,
|
||||
});
|
||||
} else {
|
||||
setTimeout(checkKetcherReady, 100);
|
||||
}
|
||||
};
|
||||
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$("#add_structure_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
// submit form
|
||||
$("#add_structure_modal_form").submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,36 +1,48 @@
|
||||
{% load static %}
|
||||
<!-- Delete Edge -->
|
||||
<div id="delete_pathway_edge_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Delete Edge</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<dialog
|
||||
id="delete_pathway_edge_modal"
|
||||
class="modal"
|
||||
x-data="modalForm({ state: { selectedEdge: '', imageUrl: '' } })"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Delete Edge</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Deletes the Edge. Nodes referenced by this edge will remain.
|
||||
<p></p>
|
||||
<form
|
||||
id="delete-pathway-edge-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
</p>
|
||||
<form
|
||||
id="delete-pathway-edge-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label" for="delete_pathway_edge_edges">
|
||||
<span class="label-text">Select Reaction to delete</span>
|
||||
</label>
|
||||
<select
|
||||
id="delete_pathway_edge_edges"
|
||||
name="edge-url"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="selectedEdge"
|
||||
@change="imageUrl = selectedEdge ? selectedEdge + '?image=svg' : ''"
|
||||
required
|
||||
>
|
||||
<option value="" disabled selected>
|
||||
Select Reaction to delete
|
||||
@ -39,51 +51,44 @@
|
||||
<option value="{{ e.url }}">{{ e.edge_label.name|safe }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="hidden" id="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
<p></p>
|
||||
<div id="delete_pathway_edge_image"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="delete-pathway-edge-modal-submit"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" id="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
|
||||
<!-- Image Preview -->
|
||||
<div class="mt-4" x-show="imageUrl" x-cloak>
|
||||
<img :src="imageUrl" class="w-full" alt="Edge preview" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error"
|
||||
@click="setFormAction('delete-pathway-edge-modal-form', selectedEdge); submit('delete-pathway-edge-modal-form')"
|
||||
:disabled="isSubmitting || !selectedEdge"
|
||||
>
|
||||
<span x-show="!isSubmitting">Delete</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Deleting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#delete_pathway_edge_edges").selectpicker();
|
||||
|
||||
$("#delete_pathway_edge_edges").on("change", function (e) {
|
||||
edge_url = $("#delete_pathway_edge_edges option:selected").val();
|
||||
|
||||
if (edge_url !== "") {
|
||||
$("#delete_pathway_edge_image").empty();
|
||||
$("#delete_pathway_edge_image").append(
|
||||
"<img width='100%' src='" + edge_url + "?image=svg'>",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$("#delete-pathway-edge-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
edge_url = $("#delete_pathway_edge_edges option:selected").val();
|
||||
|
||||
if (edge_url === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
$("#delete-pathway-edge-modal-form").attr("action", edge_url);
|
||||
$("#delete-pathway-edge-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,38 +1,49 @@
|
||||
{% load static %}
|
||||
|
||||
<!-- Delete Node -->
|
||||
<div id="delete_pathway_node_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Delete Node</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<dialog
|
||||
id="delete_pathway_node_modal"
|
||||
class="modal"
|
||||
x-data="modalForm({ state: { selectedNode: '', imageUrl: '' } })"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Delete Node</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Deletes the Node. Edges having this Node as Substrate or Product will be
|
||||
removed as well.
|
||||
<p></p>
|
||||
<form
|
||||
id="delete-pathway-node-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
</p>
|
||||
<form
|
||||
id="delete-pathway-node-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label" for="delete_pathway_node_nodes">
|
||||
<span class="label-text">Select Compound to delete</span>
|
||||
</label>
|
||||
<select
|
||||
id="delete_pathway_node_nodes"
|
||||
name="node-url"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="selectedNode"
|
||||
@change="imageUrl = selectedNode ? selectedNode + '?image=svg' : ''"
|
||||
required
|
||||
>
|
||||
<option value="" disabled selected>
|
||||
Select Compound to delete
|
||||
@ -43,51 +54,44 @@
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="hidden" id="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
<p></p>
|
||||
<div id="delete_pathway_node_image"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="delete-pathway-node-modal-submit"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" id="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
|
||||
<!-- Image Preview -->
|
||||
<div class="mt-4" x-show="imageUrl" x-cloak>
|
||||
<img :src="imageUrl" class="w-full" alt="Node preview" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error"
|
||||
@click="setFormAction('delete-pathway-node-modal-form', selectedNode); submit('delete-pathway-node-modal-form')"
|
||||
:disabled="isSubmitting || !selectedNode"
|
||||
>
|
||||
<span x-show="!isSubmitting">Delete</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Deleting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#delete_pathway_node_nodes").selectpicker();
|
||||
|
||||
$("#delete_pathway_node_nodes").on("change", function (e) {
|
||||
node_url = $("#delete_pathway_node_nodes option:selected").val();
|
||||
|
||||
if (node_url !== "") {
|
||||
$("#delete_pathway_node_image").empty();
|
||||
$("#delete_pathway_node_image").append(
|
||||
"<img width='100%' src='" + node_url + "?image=svg'>",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$("#delete-pathway-node-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
node_url = $("#delete_pathway_node_nodes option:selected").val();
|
||||
|
||||
if (node_url === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
$("#delete-pathway-node-modal-form").attr("action", node_url);
|
||||
$("#delete-pathway-node-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,53 +1,69 @@
|
||||
{% load static %}
|
||||
<!-- Download Pathway -->
|
||||
<div id="download_pathway_csv_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Download Pathway as CSV</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<dialog
|
||||
id="download_pathway_csv_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Download Pathway as CSV</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p>
|
||||
By clicking on Download the Pathway will be converted into a CSV and
|
||||
directly downloaded.
|
||||
<form
|
||||
id="download-pathway-csv-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ pathway.url }}"
|
||||
data-remote="true"
|
||||
method="GET"
|
||||
>
|
||||
<input type="hidden" name="download" value="true" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="download-pathway-csv-modal-submit"
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<form
|
||||
id="download-pathway-csv-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ pathway.url }}"
|
||||
method="GET"
|
||||
>
|
||||
<input type="hidden" name="download" value="true" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('download-pathway-csv-modal-form'); $el.closest('dialog').close();"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Download</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#download-pathway-csv-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#download-pathway-csv-modal-form").submit();
|
||||
$("#download_pathway_csv_modal").modal("hide");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,43 +1,57 @@
|
||||
{% load static %}
|
||||
<!-- Download Pathway -->
|
||||
<div id="download_pathway_image_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Download Pathway as Image</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
By clicking on Download the Pathway will be saved as SVG.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="download-pathway-image-modal-submit"
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="download_pathway_image_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Download Pathway as Image</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p>By clicking on Download the Pathway will be saved as SVG.</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="isSubmitting = true; downloadSVG(document.getElementById('pwsvg'), '{{ pathway.name.split|join:'_' }}.svg'); $el.closest('dialog').close();"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Download</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#download-pathway-image-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
downloadSVG($("#pwsvg")[0], '{{ pathway.name.split|join:"_" }}.svg');
|
||||
$("#download_pathway_image_modal").modal("hide");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,70 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Compound -->
|
||||
<div id="edit_compound_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Compound</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit Compound.</p>
|
||||
<form
|
||||
id="edit-compound-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="compound-name">Name</label>
|
||||
<input
|
||||
id="compound-name"
|
||||
class="form-control"
|
||||
name="compound-name"
|
||||
value="{{ compound.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="compound-description">Description</label>
|
||||
<input
|
||||
id="compound-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ compound.description|safe }}"
|
||||
name="compound-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-compound-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_compound_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Edit Compound</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-compound-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-name"
|
||||
class="input input-bordered w-full"
|
||||
name="compound-name"
|
||||
value="{{ compound.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ compound.description|safe }}"
|
||||
name="compound-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-compound-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-compound-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-compound-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,70 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Compound -->
|
||||
<div id="edit_compound_structure_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Create a Compound</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit a Compound Structure.</p>
|
||||
<form
|
||||
id="edit-compound-structure-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="compound-structure-name">Name</label>
|
||||
<input
|
||||
id="compound-structure-name"
|
||||
class="form-control"
|
||||
name="compound-structure-name"
|
||||
value="{{ compound_structure.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="compound-structure-description">Description</label>
|
||||
<input
|
||||
id="compound-structure-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ compound_structure.description|safe }}"
|
||||
name="compound-structure-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-compound-structure-modal-submit"
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_compound_structure_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Edit Compound Structure</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-compound-structure-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-structure-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-structure-name"
|
||||
class="input input-bordered w-full"
|
||||
name="compound-structure-name"
|
||||
value="{{ compound_structure.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="compound-structure-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="compound-structure-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ compound_structure.description|safe }}"
|
||||
name="compound-structure-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-compound-structure-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-compound-structure-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-compound-structure-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,151 +1,150 @@
|
||||
{% load static %}
|
||||
<!-- Edit Package Permission -->
|
||||
<div id="edit_group_member_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Add or Remove Group Member</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
To add member (either User or entire Groups) to this group select the
|
||||
entity you want to add below and click the check mark.
|
||||
<br />
|
||||
To remove member simply click the <code>X</code> next to the member.
|
||||
</p>
|
||||
<!-- Edit Group Member -->
|
||||
<dialog
|
||||
id="edit_group_member_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-8">
|
||||
<legend>User or Group</legend>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<legend>Add/Remove</legend>
|
||||
</div>
|
||||
</div>
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
},
|
||||
|
||||
<div class="row">
|
||||
<form
|
||||
id="modal-form-group-member"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-8">
|
||||
<select
|
||||
id="select_member"
|
||||
name="member"
|
||||
data-actions-box="true"
|
||||
class="selPackages"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled selected>User</option>
|
||||
submitForm(form) {
|
||||
if (form && form.checkValidity()) {
|
||||
form.submit();
|
||||
} else if (form) {
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Add or Remove Group Member</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
To add member (either User or entire Groups) to this group select the
|
||||
entity you want to add below and click the check mark.
|
||||
<br />
|
||||
To remove member simply click the X button next to the member.
|
||||
</p>
|
||||
|
||||
<!-- Add Member Form -->
|
||||
<form
|
||||
id="modal-form-group-member"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
class="mb-4"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="flex gap-2 items-end">
|
||||
<div class="form-control flex-1">
|
||||
<label class="label">
|
||||
<span class="label-text">User or Group</span>
|
||||
</label>
|
||||
<select
|
||||
id="select_member"
|
||||
name="member"
|
||||
class="select select-bordered w-full"
|
||||
required
|
||||
>
|
||||
<optgroup label="Users">
|
||||
{% for u in users %}
|
||||
<option value="{{ u.url }}">{{ u.username }}</option>
|
||||
{% endfor %}
|
||||
<option disabled>Groups</option>
|
||||
</optgroup>
|
||||
<optgroup label="Groups">
|
||||
{% for g in groups %}
|
||||
<option value="{{ g.url }}">{{ g.name|safe }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="hidden" name="action" value="add" />
|
||||
</div>
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-2">
|
||||
<button type="submit" style="width:60%;" class="btn col-xs-2">
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</optgroup>
|
||||
</select>
|
||||
<input type="hidden" name="action" value="add" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Add</button>
|
||||
</div>
|
||||
<p></p>
|
||||
{% for u in group.user_member.all %}
|
||||
<div class="row">
|
||||
</form>
|
||||
|
||||
<!-- User Members -->
|
||||
{% if group.user_member.all %}
|
||||
<div class="divider">User Members</div>
|
||||
<div class="space-y-2">
|
||||
{% for u in group.user_member.all %}
|
||||
<form
|
||||
id="modal-form-group-member_{{ u.uuid }}"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-8">
|
||||
{{ u.username }}
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="flex-1">{{ u.username }}</span>
|
||||
<input type="hidden" name="member" value="{{ u.url }}" />
|
||||
<input type="hidden" name="action" value="remove" />
|
||||
</div>
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-2">
|
||||
<button type="submit" style="width:60%;" class="btn col-xs-2">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
<button type="submit" class="btn btn-error btn-sm">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<p></p>
|
||||
{% for g in group.group_member.all %}
|
||||
<div class="row">
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Group Members -->
|
||||
{% if group.group_member.all %}
|
||||
<div class="divider">Group Members</div>
|
||||
<div class="space-y-2">
|
||||
{% for g in group.group_member.all %}
|
||||
<form
|
||||
id="modal-form-group-member_{{ g.uuid }}"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-8">
|
||||
{{ g.name|safe }}
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="flex-1">{{ g.name|safe }}</span>
|
||||
<input type="hidden" name="member" value="{{ g.url }}" />
|
||||
<input type="hidden" name="action" value="remove" />
|
||||
</div>
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-2">
|
||||
<button type="submit" style="width:60%;" class="btn col-xs-2">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
<button type="submit" class="btn btn-error btn-sm">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-package-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-package-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-package-modal-form").submit();
|
||||
});
|
||||
|
||||
$("#select_member").selectpicker();
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,71 +1,94 @@
|
||||
{% load static %}
|
||||
<!-- Edit Model -->
|
||||
<div id="edit_model_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Update Model</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Alter Name and Description of the Model.</p>
|
||||
<form
|
||||
id="edit-model-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="model-name">Name</label>
|
||||
<input
|
||||
id="model-name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="model-name"
|
||||
value="{{ model.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="model-description">Description</label>
|
||||
<input
|
||||
id="model-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="model-description"
|
||||
value="{{ model.description|safe }}"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-model-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_model_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update Model</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">Alter Name and Description of the Model.</p>
|
||||
|
||||
<form
|
||||
id="edit-model-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="model-name"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="model-name"
|
||||
value="{{ model.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="model-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="model-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
name="model-description"
|
||||
value="{{ model.description|safe }}"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-model-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-model-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-model-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,70 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Node -->
|
||||
<div id="edit_node_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Node</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit Node.</p>
|
||||
<form
|
||||
id="edit-node-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="node-name">Name</label>
|
||||
<input
|
||||
id="node-name"
|
||||
class="form-control"
|
||||
name="node-name"
|
||||
value="{{ node.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="node-description">Description</label>
|
||||
<input
|
||||
id="node-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ node.description|safe }}"
|
||||
name="node-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-node-modal-submit"
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_node_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Edit Node</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-node-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="node-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="node-name"
|
||||
class="input input-bordered w-full"
|
||||
name="node-name"
|
||||
value="{{ node.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="node-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="node-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ node.description|safe }}"
|
||||
name="node-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-node-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-node-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-node-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,70 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Package -->
|
||||
<div id="edit_package_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Update Package</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit a Package.</p>
|
||||
<form
|
||||
id="edit-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="package-name">Name</label>
|
||||
<input
|
||||
id="package-name"
|
||||
class="form-control"
|
||||
name="package-name"
|
||||
value="{{ package.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="package-description">Description</label>
|
||||
<input
|
||||
id="package-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ package.description|safe }}"
|
||||
name="package-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-package-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_package_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update Package</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="package-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="package-name"
|
||||
class="input input-bordered w-full"
|
||||
name="package-name"
|
||||
value="{{ package.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="package-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="package-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ package.description|safe }}"
|
||||
name="package-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-package-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-package-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-package-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,264 +1,271 @@
|
||||
{% load static %}
|
||||
<!-- Edit Package Permission -->
|
||||
<div id="edit_package_permissions_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Grant or Revoke Permissions</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Modify permissions for this package. Note that if you give
|
||||
<code>write</code> permissions to a user or group,
|
||||
<code>read</code> permissions will be granted automatically.
|
||||
<br />
|
||||
To allow users to perform destructive actions, such as deleting the
|
||||
package, <code>owner</code>
|
||||
permissions must be granted.
|
||||
</p>
|
||||
<!-- Edit Package Permissions -->
|
||||
<dialog
|
||||
id="edit_package_permissions_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
updatePermissions(checkbox) {
|
||||
const parts = checkbox.id.split('_');
|
||||
const perm = parts[0];
|
||||
const id = parts[1];
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<legend>User or Group</legend>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<legend>Read</legend>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<legend>Write</legend>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<legend>Owner</legend>
|
||||
</div>
|
||||
</div>
|
||||
const readBox = document.getElementById('read_' + id);
|
||||
const writeBox = document.getElementById('write_' + id);
|
||||
const ownerBox = document.getElementById('owner_' + id);
|
||||
|
||||
<div class="row">
|
||||
<form
|
||||
id="modal-form-permissions"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-4">
|
||||
<select
|
||||
id="select_grantee"
|
||||
name="grantee"
|
||||
data-actions-box="true"
|
||||
class="selPackages"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled selected>User</option>
|
||||
if (perm === 'read' && !readBox.checked) {
|
||||
writeBox.checked = false;
|
||||
ownerBox.checked = false;
|
||||
}
|
||||
|
||||
if (perm === 'write') {
|
||||
if (writeBox.checked) {
|
||||
readBox.checked = true;
|
||||
} else {
|
||||
ownerBox.checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (perm === 'owner' && ownerBox.checked) {
|
||||
readBox.checked = true;
|
||||
writeBox.checked = true;
|
||||
}
|
||||
}
|
||||
}"
|
||||
>
|
||||
<div class="modal-box max-w-2xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Grant or Revoke Permissions</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2">
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Modify permissions for this package. Note that if you give
|
||||
<code class="badge badge-ghost">write</code> permissions to a user or
|
||||
group, <code class="badge badge-ghost">read</code> permissions will be
|
||||
granted automatically.
|
||||
<br />
|
||||
To allow users to perform destructive actions, such as deleting the
|
||||
package, <code class="badge badge-ghost">owner</code> permissions must
|
||||
be granted.
|
||||
</p>
|
||||
|
||||
<!-- Add New Permission -->
|
||||
<form
|
||||
id="modal-form-permissions"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
class="mb-4"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="grid grid-cols-12 gap-2 items-end">
|
||||
<div class="col-span-5">
|
||||
<label class="label">
|
||||
<span class="label-text">User or Group</span>
|
||||
</label>
|
||||
<select
|
||||
id="select_grantee"
|
||||
name="grantee"
|
||||
class="select select-bordered w-full select-sm"
|
||||
required
|
||||
>
|
||||
<optgroup label="Users">
|
||||
{% for u in users %}
|
||||
<option value="{{ u.url }}">{{ u.username }}</option>
|
||||
{% endfor %}
|
||||
<option disabled>Groups</option>
|
||||
</optgroup>
|
||||
<optgroup label="Groups">
|
||||
{% for g in groups %}
|
||||
<option value="{{ g.url }}">{{ g.name|safe }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input type="checkbox" name="read" id="read_new" />
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input type="checkbox" name="write" id="write_new" />
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input type="checkbox" name="owner" id="owner_new" />
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<button
|
||||
type="submit"
|
||||
style="width:60%;"
|
||||
class="btn col-xs-2 modify-perm-button"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<label class="label justify-center">
|
||||
<span class="label-text">Read</span>
|
||||
</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="read"
|
||||
id="read_new"
|
||||
class="checkbox"
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<label class="label justify-center">
|
||||
<span class="label-text">Write</span>
|
||||
</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="write"
|
||||
id="write_new"
|
||||
class="checkbox"
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<label class="label justify-center">
|
||||
<span class="label-text">Owner</span>
|
||||
</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="owner"
|
||||
id="owner_new"
|
||||
class="checkbox"
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-1">
|
||||
<button type="submit" class="btn btn-primary btn-sm">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<p></p>
|
||||
{% for up in user_permissions %}
|
||||
<div class="row">
|
||||
</form>
|
||||
|
||||
<!-- User Permissions -->
|
||||
{% if user_permissions %}
|
||||
<div class="divider">User Permissions</div>
|
||||
<div class="space-y-2">
|
||||
{% for up in user_permissions %}
|
||||
<form
|
||||
id="modal-form-permissions_{{ up.user.uuid }}"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-4">
|
||||
{{ up.user.username }}
|
||||
<input type="hidden" name="grantee" value="{{ up.user.url }}" />
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="read"
|
||||
id="read_{{ up.user.uuid }}"
|
||||
{% if up.has_read %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="write"
|
||||
id="write_{{ up.user.uuid }}"
|
||||
{% if up.has_write %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="owner"
|
||||
id="owner_{{ up.user.uuid }}"
|
||||
{% if up.has_all %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<button
|
||||
type="submit"
|
||||
style="width:60%;"
|
||||
class="btn col-xs-2 modify-perm-button"
|
||||
>
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
<div class="grid grid-cols-12 gap-2 items-center">
|
||||
<div class="col-span-5 truncate">
|
||||
{{ up.user.username }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="grantee"
|
||||
value="{{ up.user.url }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="read"
|
||||
id="read_{{ up.user.uuid }}"
|
||||
class="checkbox"
|
||||
{% if up.has_read %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="write"
|
||||
id="write_{{ up.user.uuid }}"
|
||||
class="checkbox"
|
||||
{% if up.has_write %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="owner"
|
||||
id="owner_{{ up.user.uuid }}"
|
||||
class="checkbox"
|
||||
{% if up.has_all %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-1">
|
||||
<button type="submit" class="btn btn-sm btn-ghost">✓</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<p></p>
|
||||
{% for gp in group_permissions %}
|
||||
<div class="row">
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Group Permissions -->
|
||||
{% if group_permissions %}
|
||||
<div class="divider">Group Permissions</div>
|
||||
<div class="space-y-2">
|
||||
{% for gp in group_permissions %}
|
||||
<form
|
||||
id="modal-form-permissions_{{ gp.user.uuid }}"
|
||||
class="form-inline"
|
||||
role="form"
|
||||
id="modal-form-permissions_{{ gp.group.uuid }}"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="col-xs-4">
|
||||
{{ gp.group.name|safe }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="grantee"
|
||||
value="{{ gp.group.url }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="read"
|
||||
id="read_{{ gp.group.uuid }}"
|
||||
{% if gp.has_read %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="write"
|
||||
id="write_{{ gp.group.uuid }}"
|
||||
{% if gp.has_write %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="owner"
|
||||
id="owner_{{ gp.group.uuid }}"
|
||||
{% if gp.has_all %}checked{% endif %}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<button
|
||||
type="submit"
|
||||
style="width:60%;"
|
||||
class="btn col-xs-2 modify-perm-button"
|
||||
>
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
<div class="grid grid-cols-12 gap-2 items-center">
|
||||
<div class="col-span-5 truncate">
|
||||
{{ gp.group.name|safe }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="grantee"
|
||||
value="{{ gp.group.url }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="read"
|
||||
id="read_{{ gp.group.uuid }}"
|
||||
class="checkbox"
|
||||
{% if gp.has_read %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="write"
|
||||
id="write_{{ gp.group.uuid }}"
|
||||
class="checkbox"
|
||||
{% if gp.has_write %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 text-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="owner"
|
||||
id="owner_{{ gp.group.uuid }}"
|
||||
class="checkbox"
|
||||
{% if gp.has_all %}checked{% endif %}
|
||||
@click="updatePermissions($el)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-1">
|
||||
<button type="submit" class="btn btn-sm btn-ghost">✓</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-package-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function checkboxClick() {
|
||||
// id looks like read_3cadef24-220e-4587-9fa5-0e9a17aca2da
|
||||
parts = this.id.split("_");
|
||||
perm = parts[0];
|
||||
id = parts[1];
|
||||
|
||||
readbox = "#read_" + id;
|
||||
writebox = "#write_" + id;
|
||||
ownerbox = "#owner_" + id;
|
||||
|
||||
if (perm == "read" && !$(readbox).prop("checked")) {
|
||||
$(writebox).prop("checked", false);
|
||||
$(ownerbox).prop("checked", false);
|
||||
}
|
||||
|
||||
if (perm == "write") {
|
||||
if ($(writebox).prop("checked")) {
|
||||
$(readbox).prop("checked", true);
|
||||
}
|
||||
if (!$(writebox).prop("checked")) {
|
||||
$(ownerbox).prop("checked", false);
|
||||
}
|
||||
}
|
||||
|
||||
if (perm == "owner") {
|
||||
if ($(ownerbox).prop("checked")) {
|
||||
$(readbox).prop("checked", true);
|
||||
$(writebox).prop("checked", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#edit-package-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-package-modal-form").submit();
|
||||
});
|
||||
|
||||
$("#select_grantee").selectpicker();
|
||||
|
||||
// Add click functions to permission checkboxes
|
||||
$('[id^="read_"]').on("click", checkboxClick);
|
||||
$('[id^="write_"]').on("click", checkboxClick);
|
||||
$('[id^="owner_"]').on("click", checkboxClick);
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,82 +1,119 @@
|
||||
{% load static %}
|
||||
<!-- Edit Package -->
|
||||
<div id="edit_password_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Update your Password</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>To change your password please fill out the following inputs</p>
|
||||
<form
|
||||
id="edit-password-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="old-password">Old Password</label>
|
||||
<input
|
||||
id="old-password"
|
||||
class="form-control"
|
||||
name="old-password"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="new-password">New Password</label>
|
||||
<input
|
||||
id="new-password"
|
||||
class="form-control"
|
||||
name="new-password"
|
||||
type="password"
|
||||
,
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="new-password-repeat">Repeat New Password</label>
|
||||
<input
|
||||
id="new-password-repeat"
|
||||
class="form-control"
|
||||
name="new-password-repeat"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-password-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_password_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update your Password</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
To change your password please fill out the following inputs
|
||||
</p>
|
||||
|
||||
<form
|
||||
id="edit-password-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="hidden" value="update-password" />
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="old-password">
|
||||
<span class="label-text">Old Password</span>
|
||||
</label>
|
||||
<input
|
||||
id="old-password"
|
||||
class="input input-bordered w-full"
|
||||
name="old-password"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="new-password">
|
||||
<span class="label-text">New Password</span>
|
||||
</label>
|
||||
<input
|
||||
id="new-password"
|
||||
class="input input-bordered w-full"
|
||||
name="new-password"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="new-password-repeat">
|
||||
<span class="label-text">Repeat New Password</span>
|
||||
</label>
|
||||
<input
|
||||
id="new-password-repeat"
|
||||
class="input input-bordered w-full"
|
||||
name="new-password-repeat"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
@input="validatePasswordMatch('new-password', 'new-password-repeat')"
|
||||
/>
|
||||
<label class="label" x-show="errors['new-password-repeat']">
|
||||
<span
|
||||
class="label-text-alt text-error"
|
||||
x-text="errors['new-password-repeat']"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="if (validatePasswordMatch('new-password', 'new-password-repeat')) submit('edit-password-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-password-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-password-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,72 +1,92 @@
|
||||
{% load static %}
|
||||
<!-- Edit Pathway -->
|
||||
<div id="edit_pathway_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Pathway</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit Pathway.</p>
|
||||
<form
|
||||
id="edit-pathway-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="pathway-name">Name</label>
|
||||
<input
|
||||
id="pathway-name"
|
||||
class="form-control"
|
||||
name="pathway-name"
|
||||
value="{{ pathway.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="pathway-description">Description</label>
|
||||
<textarea
|
||||
id="pathway-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="pathway-description"
|
||||
rows="10"
|
||||
>
|
||||
|
||||
<dialog
|
||||
id="edit_pathway_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Edit Pathway</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-pathway-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="pathway-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="pathway-name"
|
||||
class="input input-bordered w-full"
|
||||
name="pathway-name"
|
||||
value="{{ pathway.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="pathway-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="pathway-description"
|
||||
class="textarea textarea-bordered w-full"
|
||||
name="pathway-description"
|
||||
rows="10"
|
||||
>
|
||||
{{ pathway.description|safe }}</textarea
|
||||
>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-pathway-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-pathway-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-pathway-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-pathway-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,163 +1,156 @@
|
||||
{% load static %}
|
||||
<!-- Edit Package -->
|
||||
<div id="update_prediction_settings_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Update Prediction Setting</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
To update your prediction setting modify parameters in the form below
|
||||
und click "Update"
|
||||
</p>
|
||||
<form
|
||||
id="edit-prediction-setting-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div id="prediction-setting" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<table class="table-bordered table-hover table">
|
||||
<tr style="background-color: rgba(0, 0, 0, 0.08);">
|
||||
<th scope="col" width="20%">Parameter</th>
|
||||
<th scope="col" width="80%">Value</th>
|
||||
<!-- Edit Prediction Setting -->
|
||||
<dialog
|
||||
id="update_prediction_settings_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Update Prediction Setting</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
To update your prediction setting modify parameters in the form below
|
||||
and click "Update"
|
||||
</p>
|
||||
<form
|
||||
id="edit-prediction-setting-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-zebra w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-1/5">Parameter</th>
|
||||
<th class="w-4/5">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if 'model' in user.prediction_settings %}
|
||||
<tr>
|
||||
<td>Model</td>
|
||||
<td>
|
||||
<div class="form-control">
|
||||
<select
|
||||
id="model"
|
||||
name="model"
|
||||
class="select select-bordered w-full"
|
||||
>
|
||||
{% for m in models %}
|
||||
<option
|
||||
value="{{ m.id }}"
|
||||
{% if user.prediction_settings.model.url == m.url %}selected{% endif %}
|
||||
>
|
||||
{{ m.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% for k, v in user.prediction_settings.model_parameters.items %}
|
||||
{% if k == 'threshold' %}
|
||||
<div class="form-control mt-2">
|
||||
<label class="label">
|
||||
<span class="label-text">Threshold</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
class="input input-bordered w-full"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
/>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
{% if 'model' in user.prediction_settings %}
|
||||
<tr>
|
||||
<td width="20%">Model</td>
|
||||
<td width="80%">
|
||||
<table
|
||||
width="100%"
|
||||
class="table-bordered table-hover table"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<select
|
||||
id="model"
|
||||
name="model"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
>
|
||||
{% for m in models %}
|
||||
<option
|
||||
value="{{ m.id }}"
|
||||
{% if user.prediction_settings.model.url == m.url %}selected{% endif %}
|
||||
>
|
||||
{{ m.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
{% for k, v in user.prediction_settings.model_parameters.items %}
|
||||
<tr>
|
||||
<th width="20%">Model Parameter</th>
|
||||
<th width="80%">Parameter Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%">
|
||||
{% if k == 'threshold' %}
|
||||
Threshold
|
||||
{% endif %}
|
||||
</td>
|
||||
<td width="80%">
|
||||
{% if k == 'threshold' %}
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
/>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for k, v in user.prediction_settings.truncator.items %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
{% if k == 'max_nodes' %}
|
||||
Max Nodes
|
||||
{% elif k == 'max_depth' %}
|
||||
Max Depth
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
{% if k == 'max_nodes' %}
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="1"
|
||||
max="50"
|
||||
step="1"
|
||||
/>
|
||||
{% elif k == 'max_depth' %}
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="1"
|
||||
max="8"
|
||||
step="1"
|
||||
/>
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-prediction-setting-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for k, v in user.prediction_settings.truncator.items %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if k == 'max_nodes' %}
|
||||
Max Nodes
|
||||
{% elif k == 'max_depth' %}
|
||||
Max Depth
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if k == 'max_nodes' %}
|
||||
<input
|
||||
type="number"
|
||||
class="input input-bordered w-full"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="1"
|
||||
max="50"
|
||||
step="1"
|
||||
/>
|
||||
{% elif k == 'max_depth' %}
|
||||
<input
|
||||
type="number"
|
||||
class="input input-bordered w-full"
|
||||
name="{{ k }}"
|
||||
value="{{ v }}"
|
||||
min="1"
|
||||
max="8"
|
||||
step="1"
|
||||
/>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-prediction-setting-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-prediction-setting-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-prediction-setting-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,69 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Reaction -->
|
||||
<div id="edit_reaction_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Update Reaction</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="edit-reaction-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="reaction-name">Name</label>
|
||||
<input
|
||||
id="reaction-name"
|
||||
class="form-control"
|
||||
name="reaction-name"
|
||||
value="{{ reaction.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="reaction-description">Description</label>
|
||||
<input
|
||||
id="reaction-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ reaction.description|safe }}"
|
||||
name="reaction-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-reaction-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_reaction_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update Reaction</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-reaction-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="reaction-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="reaction-name"
|
||||
class="input input-bordered w-full"
|
||||
name="reaction-name"
|
||||
value="{{ reaction.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="reaction-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="reaction-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ reaction.description|safe }}"
|
||||
name="reaction-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-reaction-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-reaction-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-reaction-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,69 +1,91 @@
|
||||
{% load static %}
|
||||
<!-- Edit Rule -->
|
||||
<div id="edit_rule_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Update Rule</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="edit-rule-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="rule-name">Name</label>
|
||||
<input
|
||||
id="rule-name"
|
||||
class="form-control"
|
||||
name="rule-name"
|
||||
value="{{ rule.name|safe }}"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="rule-description">Description</label>
|
||||
<input
|
||||
id="rule-description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
value="{{ rule.description|safe }}"
|
||||
name="rule-description"
|
||||
/>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-rule-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_rule_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update Rule</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-rule-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="rule-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
id="rule-name"
|
||||
class="input input-bordered w-full"
|
||||
name="rule-name"
|
||||
value="{{ rule.name|safe }}"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="rule-description">
|
||||
<span class="label-text">Description</span>
|
||||
</label>
|
||||
<input
|
||||
id="rule-description"
|
||||
type="text"
|
||||
class="input input-bordered w-full"
|
||||
value="{{ rule.description|safe }}"
|
||||
name="rule-description"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-rule-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-rule-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-rule-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,110 +1,128 @@
|
||||
{% load static %}
|
||||
<!-- Edit User -->
|
||||
<div id="edit_user_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Update User Defaults</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Edit User Defaults.</p>
|
||||
<form
|
||||
id="edit-user-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="default-package">Default Package</label>
|
||||
<select
|
||||
id="default-package"
|
||||
name="default-package"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Select a Package</option>
|
||||
{% for p in meta.writeable_packages %}
|
||||
<option
|
||||
value="{{ p.url }}"
|
||||
{% if p.id == meta.user.default_package.id %}selected{% endif %}
|
||||
>
|
||||
{{ p.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label for="default-group">Default Group</label>
|
||||
<select
|
||||
id="default-group"
|
||||
name="default-group"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Select a Group</option>
|
||||
{% for g in meta.available_groups %}
|
||||
<option
|
||||
value="{{ g.url }}"
|
||||
{% if g.id == meta.user.default_group.id %}selected{% endif %}
|
||||
>
|
||||
{{ g.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label for="default-prediction-setting"
|
||||
>Default Prediction Setting</label
|
||||
>
|
||||
<select
|
||||
id="default-prediction-setting"
|
||||
name="default-prediction-setting"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Select a Setting</option>
|
||||
{% for s in meta.available_settings %}
|
||||
<option
|
||||
value="{{ s.url }}"
|
||||
{% if s.id == meta.user.default_setting.id %}selected{% endif %}
|
||||
>
|
||||
{{ s.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-user-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<dialog
|
||||
id="edit_user_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Update User Defaults</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-user-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="default-package">
|
||||
<span class="label-text">Default Package</span>
|
||||
</label>
|
||||
<select
|
||||
id="default-package"
|
||||
name="default-package"
|
||||
class="select select-bordered w-full"
|
||||
>
|
||||
<option disabled>Select a Package</option>
|
||||
{% for p in meta.writeable_packages %}
|
||||
<option
|
||||
value="{{ p.url }}"
|
||||
{% if p.id == meta.user.default_package.id %}selected{% endif %}
|
||||
>
|
||||
{{ p.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="default-group">
|
||||
<span class="label-text">Default Group</span>
|
||||
</label>
|
||||
<select
|
||||
id="default-group"
|
||||
name="default-group"
|
||||
class="select select-bordered w-full"
|
||||
>
|
||||
<option disabled>Select a Group</option>
|
||||
{% for g in meta.available_groups %}
|
||||
<option
|
||||
value="{{ g.url }}"
|
||||
{% if g.id == meta.user.default_group.id %}selected{% endif %}
|
||||
>
|
||||
{{ g.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="default-prediction-setting">
|
||||
<span class="label-text">Default Prediction Setting</span>
|
||||
</label>
|
||||
<select
|
||||
id="default-prediction-setting"
|
||||
name="default-prediction-setting"
|
||||
class="select select-bordered w-full"
|
||||
>
|
||||
<option disabled>Select a Setting</option>
|
||||
{% for s in meta.available_settings %}
|
||||
<option
|
||||
value="{{ s.url }}"
|
||||
{% if s.id == meta.user.default_setting.id %}selected{% endif %}
|
||||
>
|
||||
{{ s.name|safe }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-user-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-user-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-user-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,93 +1,123 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="evaluate_model_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="evaluate_model_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Evaluate Model</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="evaluate_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="jumbotron">
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Evaluate Model</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="evaluate_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="alert alert-info mb-4">
|
||||
<span>
|
||||
For evaluation, you need to select the packages you want to use.
|
||||
While the model is evaluating, you can use the model for
|
||||
predictions.
|
||||
</div>
|
||||
<!-- Evaluation Packages -->
|
||||
<label for="model-evaluation-packages">Evaluation Packages</label>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Evaluation Packages -->
|
||||
<div class="form-control">
|
||||
<label class="label" for="model-evaluation-packages">
|
||||
<span class="label-text">Evaluation Packages</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-evaluation-packages"
|
||||
name="model-evaluation-packages"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
class="select select-bordered w-full h-48"
|
||||
multiple
|
||||
data-width="100%"
|
||||
required
|
||||
>
|
||||
<option disabled>Reviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<option disabled>Unreviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<optgroup label="Reviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
<optgroup label="Unreviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
</select>
|
||||
<label class="label">
|
||||
<span class="label-text-alt"
|
||||
>Hold Ctrl/Cmd to select multiple packages</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Eval Type -->
|
||||
<label for="model-evaluation-type">Evaluation Type</label>
|
||||
<!-- Eval Type -->
|
||||
<div class="form-control mt-4">
|
||||
<label class="label" for="model-evaluation-type">
|
||||
<span class="label-text">Evaluation Type</span>
|
||||
</label>
|
||||
<select
|
||||
id="model-evaluation-type"
|
||||
name="model-evaluation-type"
|
||||
class="form-control"
|
||||
class="select select-bordered w-full"
|
||||
required
|
||||
>
|
||||
<option disabled selected>Select evaluation type</option>
|
||||
<option value="" disabled selected>Select evaluation type</option>
|
||||
<option value="sg">Single Generation</option>
|
||||
<option value="mg">Multiple Generations</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="hidden" value="evaluate" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="evaluate_model_form_submit" class="btn btn-primary" href="#"
|
||||
>Evaluate</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" name="hidden" value="evaluate" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('evaluate_model_form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Evaluate</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Evaluating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
$("#model-evaluation-packages").selectpicker();
|
||||
|
||||
$("#evaluate_model_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#evaluate_model_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,53 +1,56 @@
|
||||
{% load static %}
|
||||
<!-- Export Package -->
|
||||
<div id="export_package_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Export Package as JSON</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<dialog
|
||||
id="export_package_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Export Package as JSON</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p>
|
||||
By clicking on Export the Package will be serialized into a JSON and
|
||||
directly downloaded.
|
||||
<form
|
||||
id="export-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ package.url }}"
|
||||
data-remote="true"
|
||||
method="GET"
|
||||
>
|
||||
<input type="hidden" name="export" value="true" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="export-package-modal-form-submit"
|
||||
>
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
opened in a new tab.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="window.open('{{ package.url }}?export=true', '_blank'); $el.closest('dialog').close();"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#export-package-modal-form-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#export-package-modal-form").submit();
|
||||
$("#export_package_modal").modal("hide");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,109 +1,142 @@
|
||||
{% load static %}
|
||||
<!-- Copy Object -->
|
||||
<div id="generic_copy_object_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Copy {{ object_type|capfirst }}</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="generic-copy-object-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="target-package"
|
||||
>Select the Target Package you want to copy this {{ object_type }}
|
||||
into</label
|
||||
>
|
||||
<dialog
|
||||
id="generic_copy_object_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
errorMessage: '',
|
||||
targetPackage: '',
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.errorMessage = '';
|
||||
this.targetPackage = '';
|
||||
},
|
||||
|
||||
async submit() {
|
||||
if (!this.targetPackage) return;
|
||||
|
||||
this.isSubmitting = true;
|
||||
this.errorMessage = '';
|
||||
|
||||
try {
|
||||
const response = await fetch(this.targetPackage, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
hidden: 'copy',
|
||||
object_to_copy: '{{ current_object.url }}'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
window.location.href = data.success;
|
||||
} else {
|
||||
if (data.error && data.error.indexOf('to the same package') > -1) {
|
||||
this.errorMessage = 'The target Package is the same as the source Package. Please select another target!';
|
||||
} else {
|
||||
this.errorMessage = data.error || 'An error occurred';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMessage = 'An error occurred while copying';
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Copy {{ object_type|capfirst }}</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="generic-copy-object-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label" for="target-package">
|
||||
<span class="label-text">
|
||||
Select the Target Package you want to copy this {{ object_type }}
|
||||
into
|
||||
</span>
|
||||
</label>
|
||||
<select
|
||||
id="target-package"
|
||||
name="target-package"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="targetPackage"
|
||||
required
|
||||
>
|
||||
<option disabled selected>Select Target Package</option>
|
||||
<option value="" disabled selected>Select Target Package</option>
|
||||
{% for p in meta.writeable_packages %}
|
||||
<option value="{{ p.url }}">{{ p.name|safe }}</option>
|
||||
`
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="hidden" name="hidden" value="copy" />
|
||||
</form>
|
||||
<div
|
||||
id="copy-object-error-message"
|
||||
class="alert alert-danger"
|
||||
role="alert"
|
||||
style="display: none"
|
||||
></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="generic-copy-object-modal-form-submit"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" name="hidden" value="copy" />
|
||||
</form>
|
||||
|
||||
<!-- Error Message -->
|
||||
<div
|
||||
x-show="errorMessage"
|
||||
x-cloak
|
||||
class="alert alert-error mt-4"
|
||||
role="alert"
|
||||
>
|
||||
<span x-text="errorMessage"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting || !targetPackage"
|
||||
>
|
||||
<span x-show="!isSubmitting">Copy</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Copying...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#generic-copy-object-modal-form-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#copy-object-error-message").hide();
|
||||
|
||||
const packageUrl = $("#target-package").find(":selected").val();
|
||||
|
||||
if (
|
||||
packageUrl === "Select Target Package" ||
|
||||
packageUrl === "" ||
|
||||
packageUrl === null ||
|
||||
packageUrl === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const formData = {
|
||||
hidden: "copy",
|
||||
object_to_copy: "{{ current_object.url }}",
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: "post",
|
||||
data: formData,
|
||||
url: packageUrl,
|
||||
success: function (data, textStatus) {
|
||||
window.location.href = data.success;
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
if (jqXHR.responseJSON.error.indexOf("to the same package") > -1) {
|
||||
$("#copy-object-error-message").append(
|
||||
"<p>The target Package is the same as the source Package. Please select another target!</p>",
|
||||
);
|
||||
} else {
|
||||
$("#copy-object-error-message").append(
|
||||
"<p>" + jqXHR.responseJSON.error + "</p>",
|
||||
);
|
||||
}
|
||||
$("#copy-object-error-message").show();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,58 +1,99 @@
|
||||
{% load static %}
|
||||
<!-- Delete Object -->
|
||||
<div id="generic_delete_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Delete {{ object_type|capfirst }}</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
<!--
|
||||
Generic Delete Modal - Delete object with confirmation
|
||||
|
||||
Migrated from Bootstrap + jQuery to DaisyUI + Alpine.js
|
||||
Uses native <dialog> element with .showModal() API
|
||||
-->
|
||||
|
||||
<dialog
|
||||
id="generic_delete_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Delete {{ object_type|capfirst }}</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<!-- Warning message -->
|
||||
<div class="alert alert-warning">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="stroke-current shrink-0 h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if object_type == 'user' %}
|
||||
Clicking "Delete" will <strong>permanently</strong> delete the User
|
||||
and associated data. This action can't be undone!
|
||||
{% else %}
|
||||
Deletes the {{ object_type|capfirst }}. Related objects that depend on
|
||||
this {{ object_type|capfirst }} will be deleted as well.
|
||||
{% endif %}
|
||||
<form
|
||||
id="generic-delete-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" id="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="generic-delete-modal-form-submit"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
{% if object_type == 'user' %}
|
||||
Clicking "Delete" will <strong>permanently</strong> delete the User
|
||||
and associated data. This action can't be undone!
|
||||
{% else %}
|
||||
Deletes the {{ object_type|capfirst }}. Related objects that depend
|
||||
on this {{ object_type|capfirst }} will be deleted as well.
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Hidden form -->
|
||||
<form
|
||||
id="generic-delete-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="hidden" value="delete" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error"
|
||||
@click="submit('generic-delete-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Delete</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Deleting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#generic-delete-modal-form-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#generic-delete-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop (click to close) -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,213 +1,173 @@
|
||||
{% load static %}
|
||||
|
||||
<style>
|
||||
.alias-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
cursor: text;
|
||||
min-height: 38px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.alias {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background-color: #5bc0de;
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
margin: 3px 3px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.alias .remove {
|
||||
margin-left: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.alias-input {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 3px 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-control.alias-container {
|
||||
height: auto;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
<dialog
|
||||
id="set_aliases_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="set_aliases_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">
|
||||
Set Aliases for {{ current_object.name|safe }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="set_aliases_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="alias-input">Aliases:</label>
|
||||
<div class="form-control alias-container" id="alias-box">
|
||||
{% for alias in current_object.aliases %}
|
||||
<span class="alias"
|
||||
>{{ alias|escape }}<span class="remove">×</span></span
|
||||
>
|
||||
{% endfor %}
|
||||
<input
|
||||
type="text"
|
||||
id="alias-input"
|
||||
class="alias-input"
|
||||
placeholder="Add Alias..."
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
id="add-alias-error-message"
|
||||
class="alert alert-danger"
|
||||
role="alert"
|
||||
style="display: none"
|
||||
></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="set_aliases_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
function addAlias(aliasText) {
|
||||
aliasText = aliasText.trim();
|
||||
if (aliasText === "") return;
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
aliases: [{% for alias in current_object.aliases %}'{{ alias|escapejs }}'{% if not forloop.last %},{% endif %}{% endfor %}],
|
||||
newAlias: '',
|
||||
errorMessage: '',
|
||||
|
||||
// Avoid duplicate aliass
|
||||
var exists = false;
|
||||
$("#alias-box .alias").each(function () {
|
||||
if (
|
||||
$(this).text().replace("×", "").trim().toLowerCase() ===
|
||||
aliasText.toLowerCase()
|
||||
) {
|
||||
exists = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.errorMessage = '';
|
||||
},
|
||||
|
||||
addAlias() {
|
||||
const aliasText = this.newAlias.trim();
|
||||
if (aliasText === '') return;
|
||||
|
||||
// Check for duplicates (case-insensitive)
|
||||
const exists = this.aliases.some(
|
||||
a => a.toLowerCase() === aliasText.toLowerCase()
|
||||
);
|
||||
|
||||
if (!exists) {
|
||||
var aliasHtml =
|
||||
'<span class="alias">' +
|
||||
$("<div>").text(aliasText).html() +
|
||||
'<span class="remove">×</span></span>';
|
||||
$(aliasHtml).insertBefore("#alias-input");
|
||||
this.aliases.push(aliasText);
|
||||
}
|
||||
|
||||
$("#alias-input").val("");
|
||||
}
|
||||
this.newAlias = '';
|
||||
},
|
||||
|
||||
// Add alias when Enter is pressed
|
||||
$("#alias-input").on("keypress", function (e) {
|
||||
if (e.which === 13) {
|
||||
removeAlias(index) {
|
||||
this.aliases.splice(index, 1);
|
||||
},
|
||||
|
||||
handleKeypress(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
addAlias($(this).val());
|
||||
this.addAlias();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Add alias when input loses focus
|
||||
$("#alias-input").on("blur", function () {
|
||||
var val = $(this).val();
|
||||
if (val.trim() !== "") {
|
||||
addAlias(val);
|
||||
handleBlur() {
|
||||
if (this.newAlias.trim() !== '') {
|
||||
this.addAlias();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Remove alias when clicking ×
|
||||
$("#alias-box").on("click", ".remove", function () {
|
||||
$(this).closest(".alias").remove();
|
||||
});
|
||||
async submit() {
|
||||
this.isSubmitting = true;
|
||||
this.errorMessage = '';
|
||||
|
||||
// Focus input when clicking the container
|
||||
$("#alias-box").on("click", function () {
|
||||
$("#alias-input").focus();
|
||||
});
|
||||
|
||||
$("#set_aliases_modal_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let aliases = [];
|
||||
$("#alias-box .alias").each(function () {
|
||||
aliases.push($(this).text().replace("×", "").trim());
|
||||
});
|
||||
|
||||
if (aliases.length === 0) {
|
||||
// Set empty string for deletion of all aliases
|
||||
// If empty list is sent, its gets removed entirely from post data
|
||||
aliases = [""];
|
||||
const formData = new URLSearchParams();
|
||||
if (this.aliases.length === 0) {
|
||||
formData.append('aliases', '');
|
||||
} else {
|
||||
this.aliases.forEach(alias => {
|
||||
formData.append('aliases', alias);
|
||||
});
|
||||
}
|
||||
|
||||
formData = {
|
||||
aliases: aliases,
|
||||
};
|
||||
try {
|
||||
const response = await fetch('{{ current_object.url }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: "post",
|
||||
data: formData,
|
||||
url: "{{ current_object.url }}",
|
||||
traditional: true,
|
||||
success: function (data, textStatus) {
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
window.location.href = data.success;
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
$("#add-alias-error-message").append(
|
||||
"<p>Setting aliases failed!</p>",
|
||||
);
|
||||
$("#add-alias-error-message").show();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
} else {
|
||||
this.errorMessage = 'Setting aliases failed!';
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMessage = 'Setting aliases failed!';
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box max-w-4xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">
|
||||
Set Aliases for {{ current_object.name|safe }}
|
||||
</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Aliases:</span>
|
||||
</label>
|
||||
<div
|
||||
class="flex flex-wrap items-center gap-1 p-2 border border-base-300 rounded-lg bg-base-100 min-h-[38px] cursor-text"
|
||||
@click="$refs.aliasInput.focus()"
|
||||
>
|
||||
<template x-for="(alias, index) in aliases" :key="index">
|
||||
<span class="badge badge-info gap-1 py-3">
|
||||
<span x-text="alias"></span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-xs p-0 h-auto min-h-0"
|
||||
@click.stop="removeAlias(index)"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</span>
|
||||
</template>
|
||||
<input
|
||||
type="text"
|
||||
x-ref="aliasInput"
|
||||
x-model="newAlias"
|
||||
class="flex-1 min-w-[120px] border-none outline-none bg-transparent text-sm"
|
||||
placeholder="Add Alias..."
|
||||
@keypress="handleKeypress($event)"
|
||||
@blur="handleBlur()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Message -->
|
||||
<div x-show="errorMessage" x-cloak class="alert alert-error mt-4">
|
||||
<span x-text="errorMessage"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,97 +1,137 @@
|
||||
{% load static %}
|
||||
<!-- Delete Object -->
|
||||
<div id="generic_set_external_reference_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Add External References</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="generic-set-external-reference-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="database-select"
|
||||
>Select the Database you want to attach an External Reference
|
||||
for</label
|
||||
>
|
||||
<!-- Set External Reference -->
|
||||
<dialog
|
||||
id="generic_set_external_reference_modal"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
selectedDatabase: '',
|
||||
placeholder: '',
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.selectedDatabase = '';
|
||||
this.placeholder = '';
|
||||
},
|
||||
|
||||
updatePlaceholder() {
|
||||
if (this.selectedDatabase) {
|
||||
const option = document.querySelector('#database-select option[value=\'' + this.selectedDatabase + '\']');
|
||||
if (option) {
|
||||
this.placeholder = option.dataset.inputPlaceholder || '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
submit(formId) {
|
||||
const form = document.getElementById(formId);
|
||||
if (form && form.checkValidity()) {
|
||||
this.isSubmitting = true;
|
||||
form.submit();
|
||||
} else if (form) {
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Add External References</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="generic-set-external-reference-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label" for="database-select">
|
||||
<span class="label-text">
|
||||
Select the Database you want to attach an External Reference for
|
||||
</span>
|
||||
</label>
|
||||
<select
|
||||
id="database-select"
|
||||
name="selected-database"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
x-model="selectedDatabase"
|
||||
@change="updatePlaceholder()"
|
||||
required
|
||||
>
|
||||
<option disabled selected>Select Database</option>
|
||||
<option value="" disabled selected>Select Database</option>
|
||||
{% for entity, databases in meta.external_databases.items %}
|
||||
{% if entity == object_type %}
|
||||
{% for db in databases %}
|
||||
<option
|
||||
id="db-select-{{ db.database.pk }}"
|
||||
data-input-placeholder="{{ db.placeholder }}"
|
||||
value="{{ db.database.id }}"
|
||||
data-input-placeholder="{{ db.placeholder }}"
|
||||
>
|
||||
{{ db.database.name|safe }}
|
||||
</option>
|
||||
`
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<p></p>
|
||||
<div id="input-div" style="display: none">
|
||||
<label for="identifier">The reference</label>
|
||||
<input
|
||||
type="text"
|
||||
id="identifier"
|
||||
name="identifier"
|
||||
class="form-control"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="generic-set-external-reference-modal-form-submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-4" x-show="selectedDatabase" x-cloak>
|
||||
<label class="label" for="identifier">
|
||||
<span class="label-text">The reference</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="identifier"
|
||||
name="identifier"
|
||||
class="input input-bordered w-full"
|
||||
:placeholder="placeholder"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('generic-set-external-reference-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#database-select").on("change", function () {
|
||||
let selected = $(this).val();
|
||||
$("#identifier").attr(
|
||||
"placeholder",
|
||||
$("#db-select-" + selected).data("input-placeholder"),
|
||||
);
|
||||
$("#input-div").show();
|
||||
});
|
||||
|
||||
$("#generic-set-external-reference-modal-form-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#generic-set-external-reference-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,112 +1,142 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
<dialog
|
||||
id="set_scenario_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="set_scenario_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
isLoading: false,
|
||||
loaded: false,
|
||||
scenarios: [],
|
||||
attachedScenarios: [{% for scen in current_object.scenarios.all %}'{{ scen.url }}'{% if not forloop.last %},{% endif %}{% endfor %}],
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
},
|
||||
|
||||
async loadScenarios() {
|
||||
if (this.loaded) return;
|
||||
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const response = await fetch('{% url "package scenario list" meta.current_package.uuid %}');
|
||||
const data = await response.json();
|
||||
this.scenarios = data;
|
||||
this.loaded = true;
|
||||
} catch (error) {
|
||||
console.error('Error loading scenarios:', error);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
isSelected(url) {
|
||||
return this.attachedScenarios.includes(url);
|
||||
},
|
||||
|
||||
submit() {
|
||||
this.isSubmitting = true;
|
||||
const select = document.getElementById('scenario-select');
|
||||
if (select.selectedOptions.length === 0) {
|
||||
// Add hidden empty option to indicate clearing all scenarios
|
||||
const emptyOption = document.createElement('option');
|
||||
emptyOption.value = '';
|
||||
emptyOption.selected = true;
|
||||
select.appendChild(emptyOption);
|
||||
}
|
||||
document.getElementById('set_scenario_modal_form').submit();
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
x-init="$watch('$el.open', value => { if (value) loadScenarios(); })"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">
|
||||
Set Scenarios for {{ current_object.name|safe }}
|
||||
</h4>
|
||||
<div class="modal-box max-w-4xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">
|
||||
Set Scenarios for {{ current_object.name|safe }}
|
||||
</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<!-- Loading indicator -->
|
||||
<div x-show="isLoading" x-cloak class="mb-4 text-center">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
<div class="alert alert-info mt-2">Loading Scenarios...</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="loading_scenario_div" class="text-center"></div>
|
||||
<form
|
||||
id="set_scenario_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="scenario-select">Scenarios</label>
|
||||
|
||||
<form
|
||||
id="set_scenario_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
x-show="!isLoading"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="form-control">
|
||||
<label class="label" for="scenario-select">
|
||||
<span class="label-text">Scenarios</span>
|
||||
</label>
|
||||
<select
|
||||
id="scenario-select"
|
||||
name="selected-scenarios"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
class="select select-bordered h-48 w-full"
|
||||
multiple
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Select Scenarios</option>
|
||||
<option value="" hidden></option>
|
||||
<template x-for="scenario in scenarios" :key="scenario.url">
|
||||
<option
|
||||
:value="scenario.url"
|
||||
:selected="isSelected(scenario.url)"
|
||||
x-text="scenario.name"
|
||||
></option>
|
||||
</template>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="set_scenario_modal_form_submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
<label class="label">
|
||||
<span class="label-text-alt"
|
||||
>Hold Ctrl/Cmd to select multiple scenarios</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit()"
|
||||
:disabled="isSubmitting || isLoading"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# prettier-ignore-start #}
|
||||
<script>
|
||||
|
||||
$(function () {
|
||||
var loaded = false;
|
||||
|
||||
var attachedScenarios = []
|
||||
{% if current_object.scenarios.all %}
|
||||
{% for scen in current_object.scenarios.all %}
|
||||
attachedScenarios.push('{{ scen.url }}')
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
$('#scenario-select').selectpicker();
|
||||
|
||||
$('#set_scenario_modal').on('shown.bs.modal', function () {
|
||||
|
||||
if (!loaded) {
|
||||
makeLoadingGif("#loading_scenario_div", "{% static '/images/wait.gif' %}");
|
||||
$('#loading_scenario_div').append("<p></p><div class='alert alert-info'>Loading Scenarios...</div>");
|
||||
|
||||
$.getJSON("{% url 'package scenario list' meta.current_package.uuid %}").then(function (data) {
|
||||
for(s in data) {
|
||||
scenario = data[s]
|
||||
var selected = attachedScenarios.includes(scenario.url);
|
||||
$('#scenario-select').append(`<option value="${scenario.url}" ${selected ? 'selected' : ''}>${scenario.name}</option>`);
|
||||
}
|
||||
$('#scenario-select').selectpicker('refresh');
|
||||
$("#loading_scenario_div").empty();
|
||||
});
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
$('#set_scenario_modal_form_submit').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
if ($('#scenario-select').val().length == 0) {
|
||||
$('#scenario-select').val("")
|
||||
}
|
||||
$('#set_scenario_modal_form').submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,75 +1,89 @@
|
||||
{% load static %}
|
||||
<!-- Identify Missing Rules -->
|
||||
<div id="identify_missing_rules_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Identify Missing Rules</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<dialog
|
||||
id="identify_missing_rules_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Identify Missing Rules</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
By clicking on Download we'll search the Pathway for Reactions that are
|
||||
not backed by a Rule or which can be assembled by chaining two rules.
|
||||
<form
|
||||
id="identify-missing-rules-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ pathway.url }}"
|
||||
data-remote="true"
|
||||
method="GET"
|
||||
>
|
||||
<label for="rule-package">Select the Rule Package</label>
|
||||
</p>
|
||||
<form
|
||||
id="identify-missing-rules-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ pathway.url }}"
|
||||
method="GET"
|
||||
>
|
||||
<div class="form-control">
|
||||
<label class="label" for="rule-package">
|
||||
<span class="label-text">Select the Rule Package</span>
|
||||
</label>
|
||||
<select
|
||||
id="rule-package"
|
||||
name="rule-package"
|
||||
data-actions-box="true"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
class="select select-bordered w-full"
|
||||
required
|
||||
>
|
||||
<option disabled>Reviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<option disabled>Unreviewed Packages</option>
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<optgroup label="Reviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
<optgroup label="Unreviewed Packages">
|
||||
{% for obj in meta.readable_packages %}
|
||||
{% if not obj.reviewed %}
|
||||
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
</select>
|
||||
<input type="hidden" name="identify-missing-rules" value="true" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="identify-missing-rules-modal-submit"
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="identify-missing-rules" value="true" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="document.getElementById('identify-missing-rules-modal-form').submit(); $el.closest('dialog').close()"
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#identify-missing-rules-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#identify-missing-rules-modal-form").submit();
|
||||
$("#identify_missing_rules_modal").modal("hide");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,118 +1,174 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="manage_api_token_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="manage_api_token_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
newToken: '',
|
||||
tokens: [],
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.newToken = '';
|
||||
},
|
||||
|
||||
async requestToken() {
|
||||
this.isSubmitting = true;
|
||||
const form = document.getElementById('request_api_token_form');
|
||||
const formData = new FormData(form);
|
||||
|
||||
try {
|
||||
const response = await fetch('{{ meta.user.url }}', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
const data = await response.json();
|
||||
this.newToken = data.raw_token;
|
||||
} catch (error) {
|
||||
console.error('Error requesting token:', error);
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
},
|
||||
|
||||
async deleteToken(form) {
|
||||
const formData = new FormData(form);
|
||||
try {
|
||||
await fetch(form.action, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
form.closest('.token-item').remove();
|
||||
} catch (error) {
|
||||
console.error('Error deleting token:', error);
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Manage API Token</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Requesting a Token will invalidate all potential existing tokens. The
|
||||
new token will only be shown once, so ensure to store it in secure
|
||||
place
|
||||
</p>
|
||||
<form
|
||||
id="request_api_token_form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<label for="token-name">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="token-name"
|
||||
class="form-control"
|
||||
name="name"
|
||||
placeholder="Generic Token for {{ meta.user.username }}"
|
||||
/>
|
||||
<label for="valid-for">Valid for (in days)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="valid-for"
|
||||
class="form-control"
|
||||
name="valid-for"
|
||||
value="90"
|
||||
/>
|
||||
<input type="hidden" name="hidden" value="request-api-token" />
|
||||
</p>
|
||||
</form>
|
||||
<div id="new-token">
|
||||
<pre id="new-token-pre"></pre>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Manage API Token</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<p class="mb-4">
|
||||
Requesting a Token will invalidate all potential existing tokens. The
|
||||
new token will only be shown once, so ensure to store it in a secure
|
||||
place.
|
||||
</p>
|
||||
|
||||
<form id="request_api_token_form" accept-charset="UTF-8" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="token-name">
|
||||
<span class="label-text">Name</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="token-name"
|
||||
class="input input-bordered w-full"
|
||||
name="name"
|
||||
placeholder="Generic Token for {{ meta.user.username }}"
|
||||
/>
|
||||
</div>
|
||||
<div id="existing-tokens">
|
||||
{% for t in tokens %}
|
||||
<div class="form-control mb-3">
|
||||
<label class="label" for="valid-for">
|
||||
<span class="label-text">Valid for (in days)</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="valid-for"
|
||||
class="input input-bordered w-full"
|
||||
name="valid-for"
|
||||
value="90"
|
||||
/>
|
||||
</div>
|
||||
<input type="hidden" name="hidden" value="request-api-token" />
|
||||
</form>
|
||||
|
||||
<!-- New Token Display -->
|
||||
<div x-show="newToken" x-cloak class="alert alert-success mb-4">
|
||||
<div class="w-full">
|
||||
<span class="font-bold">New Token:</span>
|
||||
<pre
|
||||
class="mt-2 p-2 bg-base-200 rounded overflow-x-auto"
|
||||
x-text="newToken"
|
||||
></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Existing Tokens -->
|
||||
<div class="space-y-2">
|
||||
{% for t in tokens %}
|
||||
<div class="token-item">
|
||||
<form
|
||||
id="delete-token-{{ forloop.counter0 }}"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.user.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="input-group">
|
||||
<div class="join w-full">
|
||||
<input type="hidden" name="hidden" value="delete" />
|
||||
<input type="hidden" name="token-id" value="{{ t.pk }}" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered join-item w-full"
|
||||
value="{{ t.name|safe }}"
|
||||
disabled
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error join-item"
|
||||
@click="deleteToken($el.closest('form'))"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="manage_api_token_form_submit" class="btn btn-primary" href="#"
|
||||
>Submit</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="requestToken()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Request Token</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Requesting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#new-token").hide();
|
||||
|
||||
$("#manage_api_token_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = $("#request_api_token_form").serialize();
|
||||
$.post("", formData, function (response) {
|
||||
$("#new-token-pre").text(response.raw_token);
|
||||
$("#new-token").show();
|
||||
});
|
||||
});
|
||||
|
||||
// Select all elements that start with 'delete-token-'
|
||||
$("[id^='delete-token-']").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
const formData = $(this).serialize();
|
||||
const form = $(this);
|
||||
$.post(this.action, formData, function (response) {
|
||||
console.log(this);
|
||||
form.remove();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,52 +1,85 @@
|
||||
{% load static %}
|
||||
<!-- Publish a Package -->
|
||||
<div id="publish_package_modal" class="modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Publish Package</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
|
||||
<dialog
|
||||
id="publish_package_modal"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="font-bold text-lg">Publish Package</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<div class="alert alert-info">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="h-6 w-6 shrink-0 stroke-current"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Clicking on Publish will make this Package publicly available!</p>
|
||||
<form
|
||||
id="publish-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_package.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span
|
||||
>Clicking on Publish will make this Package publicly available!</span
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="hidden" value="publish-package" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="publish-package-modal-form-submit"
|
||||
>
|
||||
Publish
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form
|
||||
id="publish-package-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ current_package.url }}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="hidden" value="publish-package" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('publish-package-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Publish</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Publishing...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#publish-package-modal-form-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#publish-package-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,55 +1,72 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="retrain_model_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="retrain_model_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Retrain Model</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="retrain_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_object.url }}"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
<div class="jumbotron">
|
||||
<div class="modal-box max-w-3xl">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Retrain Model</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="retrain_model_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_object.url }}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="alert alert-info mb-4">
|
||||
<span>
|
||||
To reflect changes in the rule or data packages, you can use the
|
||||
"Retrain" button, to let the model reflect the changes without
|
||||
creating a new model. While the model is retraining, it will be
|
||||
unavailable for prediction.
|
||||
</div>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="hidden" value="retrain" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="retrain_model_form_submit" class="btn btn-primary" href="#"
|
||||
>Retrain</a
|
||||
>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<input type="hidden" name="hidden" value="retrain" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('retrain_model_form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Retrain</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Retraining...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
$("#retrain_model_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#retrain_model_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,198 +1,193 @@
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
<dialog
|
||||
id="set_license_modal"
|
||||
role="dialog"
|
||||
aria-labelledby="set_license_modal"
|
||||
aria-hidden="true"
|
||||
class="modal"
|
||||
x-data="{
|
||||
isSubmitting: false,
|
||||
licenseType: '',
|
||||
ccRemix: false,
|
||||
ccNoCom: false,
|
||||
ccAlike: false,
|
||||
|
||||
reset() {
|
||||
this.isSubmitting = false;
|
||||
this.licenseType = '';
|
||||
this.ccRemix = false;
|
||||
this.ccNoCom = false;
|
||||
this.ccAlike = false;
|
||||
},
|
||||
|
||||
get licenseString() {
|
||||
if (this.licenseType !== 'cc') return 'no-license';
|
||||
|
||||
let str = 'by';
|
||||
if (this.ccNoCom) str += '-nc';
|
||||
if (!this.ccRemix) {
|
||||
str += '-nd';
|
||||
} else if (this.ccAlike) {
|
||||
str += '-sa';
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
get licenseUrl() {
|
||||
if (this.licenseType !== 'cc') return '';
|
||||
return 'https://creativecommons.org/licenses/' + this.licenseString + '/4.0/';
|
||||
},
|
||||
|
||||
get licenseImageUrl() {
|
||||
if (this.licenseType !== 'cc') return '';
|
||||
return 'https://licensebuttons.net/l/' + this.licenseString + '/4.0/88x31.png';
|
||||
},
|
||||
|
||||
submit(formId) {
|
||||
const form = document.getElementById(formId);
|
||||
document.getElementById('license').value = this.licenseString;
|
||||
if (form && form.checkValidity()) {
|
||||
this.isSubmitting = true;
|
||||
form.submit();
|
||||
} else if (form) {
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
}"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Set License</h3>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Set License</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<div class="flex gap-4 mb-4">
|
||||
<div class="flex-1">
|
||||
<p>
|
||||
Set the license for all data in this package:
|
||||
<br /><br />
|
||||
(For more information please visit our
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/License"
|
||||
class="link link-primary"
|
||||
>wiki</a
|
||||
>.)
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex-none" x-show="licenseType === 'cc'" x-cloak>
|
||||
<a :href="licenseUrl" target="_blank">
|
||||
<img :src="licenseImageUrl" alt="CC License" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<p>
|
||||
Set the license for all data in this package:
|
||||
<br />
|
||||
<br />
|
||||
(For more information please visit our
|
||||
<a target="#" href="https://wiki.envipath.org/index.php/License"
|
||||
>wiki</a
|
||||
>.)
|
||||
</p>
|
||||
<form
|
||||
id="set_license_form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input
|
||||
type="radio"
|
||||
name="optlicense"
|
||||
class="radio"
|
||||
value="cc"
|
||||
x-model="licenseType"
|
||||
/>
|
||||
<span class="label-text">Creative commons license</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="ml-8 space-y-2" x-show="licenseType === 'cc'" x-cloak>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input type="checkbox" class="checkbox" x-model="ccRemix" />
|
||||
<span class="label-text"
|
||||
>Allow adaptations of your work to be shared</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div id="ccfig"></div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input type="checkbox" class="checkbox" x-model="ccNoCom" />
|
||||
<span class="label-text">Prohibit commercial use</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
x-model="ccAlike"
|
||||
:disabled="!ccRemix"
|
||||
/>
|
||||
<span class="label-text">Share only if others share alike</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
id="set_license_form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="input-group">
|
||||
<div class="radio">
|
||||
<label
|
||||
><input
|
||||
type="radio"
|
||||
name="optlicense"
|
||||
onclick="cc()"
|
||||
id="ccradio"
|
||||
/>Creative commons license</label
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="checkbox">
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
value=""
|
||||
onclick="cc()"
|
||||
id="ccremix"
|
||||
disabled
|
||||
/>Allow adaptations of your work to be shared</label
|
||||
>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
value=""
|
||||
onclick="cc()"
|
||||
id="ccnocom"
|
||||
disabled
|
||||
/>Prohibit commercial use</label
|
||||
>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
value=""
|
||||
onclick="cc()"
|
||||
id="ccalike"
|
||||
disabled
|
||||
/>Share only if others share alike</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label
|
||||
><input
|
||||
type="radio"
|
||||
name="optlicense"
|
||||
onclick="cc()"
|
||||
id="noccradio"
|
||||
/>No creative commons license, contact package owner for license
|
||||
information</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="license" name="license" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="set_license_form_submit" class="btn btn-primary">
|
||||
Submit
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-2">
|
||||
<label class="label cursor-pointer justify-start gap-3">
|
||||
<input
|
||||
type="radio"
|
||||
name="optlicense"
|
||||
class="radio"
|
||||
value="nocc"
|
||||
x-model="licenseType"
|
||||
/>
|
||||
<span class="label-text"
|
||||
>No creative commons license, contact package owner for license
|
||||
information</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="license" name="license" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('set_license_form')"
|
||||
:disabled="isSubmitting || !licenseType"
|
||||
>
|
||||
<span x-show="!isSubmitting">Submit</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Submitting...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function ccstring(ccremix, ccnocom, ccalike) {
|
||||
var ccstring = "by";
|
||||
|
||||
if (ccnocom) {
|
||||
ccstring += "-nc";
|
||||
}
|
||||
|
||||
if (!ccremix) {
|
||||
ccstring += "-nd";
|
||||
} else {
|
||||
if (ccalike) {
|
||||
ccstring += "-sa";
|
||||
}
|
||||
}
|
||||
return ccstring;
|
||||
}
|
||||
|
||||
function cc() {
|
||||
var nocc = $("#noccradio").prop("checked");
|
||||
var iscc = $("#ccradio").prop("checked");
|
||||
|
||||
if (nocc) {
|
||||
$("#ccradio").prop("checked", false);
|
||||
$("#ccremix").prop("checked", false);
|
||||
$("#ccnocom").prop("checked", false);
|
||||
$("#ccalike").prop("checked", false);
|
||||
|
||||
$("#ccremix").prop("disabled", true);
|
||||
$("#ccnocom").prop("disabled", true);
|
||||
$("#ccalike").prop("disabled", true);
|
||||
} else if (iscc) {
|
||||
$("#ccremix").prop("disabled", false);
|
||||
$("#ccnocom").prop("disabled", false);
|
||||
|
||||
if ($("#ccremix").prop("checked")) {
|
||||
$("#ccalike").prop("disabled", false);
|
||||
} else {
|
||||
$("#ccalike").prop("disabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
var remix = $("#ccremix").prop("checked");
|
||||
var nocom = $("#ccnocom").prop("checked");
|
||||
var alike = $("#ccalike").prop("checked");
|
||||
|
||||
if (nocc) {
|
||||
$("#set_license_form_submit").prop("disabled", false);
|
||||
$("#ccfig").empty();
|
||||
$("#license").val("no-license");
|
||||
} else if (iscc) {
|
||||
$("#set_license_form_submit").prop("disabled", false);
|
||||
$("#ccfig").empty();
|
||||
var ccstr = ccstring(remix, nocom, alike);
|
||||
|
||||
var link = `https://creativecommons.org/licenses/${ccstr}/4.0/`;
|
||||
var imageLink = `https://licensebuttons.net/l/${ccstr}/4.0/88x31.png`;
|
||||
|
||||
var img_tpl = `<a href='${link}' target="_blank">
|
||||
<img src='${imageLink}'>
|
||||
</a>`;
|
||||
|
||||
$("#ccfig").append(img_tpl);
|
||||
$("#license").val(ccstr);
|
||||
} else {
|
||||
$("#ccfig").empty();
|
||||
$("#set_license_form_submit").prop("disabled", true);
|
||||
$("#license").val("no-license");
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// Disable by default as nothing is selected
|
||||
|
||||
cc();
|
||||
$("#set_license_form_submit").prop("disabled", true);
|
||||
|
||||
$("#set_license_form_submit").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$("#set_license_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,62 +1,69 @@
|
||||
{% load static %}
|
||||
<!-- Update Scenario Additional Information-->
|
||||
<div
|
||||
|
||||
<dialog
|
||||
id="update_scenario_additional_information_modal"
|
||||
class="modal"
|
||||
tabindex="-1"
|
||||
x-data="modalForm()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3 class="modal-title">Update Additional Information</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="edit-scenario-additional-information-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
{% for widget in update_widgets %}
|
||||
{{ widget|safe }}
|
||||
{% endfor %}
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="set-additional-information"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
id="edit-scenario-additional-information-modal-submit"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-box">
|
||||
<!-- Header -->
|
||||
<h3 class="text-lg font-bold">Update Additional Information</h3>
|
||||
|
||||
<!-- Close button (X) -->
|
||||
<form method="dialog">
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="py-4">
|
||||
<form
|
||||
id="edit-scenario-additional-information-modal-form"
|
||||
accept-charset="UTF-8"
|
||||
action=""
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
{% for widget in update_widgets %}
|
||||
{{ widget|safe }}
|
||||
{% endfor %}
|
||||
<input type="hidden" name="hidden" value="set-additional-information" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="modal-action">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick="this.closest('dialog').close()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="submit('edit-scenario-additional-information-modal-form')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span x-show="!isSubmitting">Update</span>
|
||||
<span
|
||||
x-show="isSubmitting"
|
||||
class="loading loading-spinner loading-sm"
|
||||
></span>
|
||||
<span x-show="isSubmitting">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$("#edit-scenario-additional-information-modal-submit").click(function (e) {
|
||||
e.preventDefault();
|
||||
$("#edit-scenario-additional-information-modal-form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Backdrop -->
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button :disabled="isSubmitting">close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@ -1,178 +0,0 @@
|
||||
{% load static %}
|
||||
<div
|
||||
class="modal fade bs-modal-lg"
|
||||
id="predict_modal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="predict_modal"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Predict a Pathway</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form
|
||||
id="predict_modal_form"
|
||||
accept-charset="UTF-8"
|
||||
action="{{ meta.current_package.url }}/pathway"
|
||||
data-remote="true"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
class="form-control"
|
||||
name="name"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<label for="description">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
class="form-control"
|
||||
name="description"
|
||||
placeholder="Description"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="predict">Predict pathway or build yourself?</label>
|
||||
<div class="radio" id="predict">
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioPredict"
|
||||
value="predict"
|
||||
checked
|
||||
/>Predict pathway
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioIncremental"
|
||||
value="incremental"
|
||||
/>Incremental prediction
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="predict"
|
||||
id="radioBuild"
|
||||
value="build"
|
||||
/>Build pathway
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="predict-modal-smiles">SMILES</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="smiles"
|
||||
placeholder="SMILES"
|
||||
id="predict-modal-smiles"
|
||||
/>
|
||||
<p id="ketcher_container"></p>
|
||||
<div>
|
||||
<iframe
|
||||
id="predict-modal-ketcher"
|
||||
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||
width="100%"
|
||||
height="510"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<label for="prediction-setting">Default Prediction Setting</label>
|
||||
<select
|
||||
id="prediction-setting"
|
||||
name="prediction-setting"
|
||||
class="form-control"
|
||||
data-width="100%"
|
||||
>
|
||||
<option disabled>Select a Setting</option>
|
||||
{% for s in meta.available_settings %}
|
||||
<option
|
||||
value="{{ s.url }}"
|
||||
{% if s.id == meta.user.default_setting.id %}selected{% endif %}
|
||||
>
|
||||
{{ s.name|safe }}{% if s.id == meta.user.default_setting.id %}
|
||||
<i>(User default)</i>
|
||||
{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary pull-left"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" id="predictButton">
|
||||
Predict
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function predictModalketcherToPredictModalTextInput() {
|
||||
$("#predict-modal-smiles").val(this.ketcher.getSmiles());
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#predict-modal-ketcher").on("load", function () {
|
||||
const checkKetcherReady = () => {
|
||||
win = this.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
win.ketcher.editor.event.change.handlers.push({
|
||||
once: false,
|
||||
priority: 0,
|
||||
f: predictModalketcherToPredictModalTextInput,
|
||||
ketcher: win.ketcher,
|
||||
});
|
||||
} else {
|
||||
setTimeout(checkKetcherReady, 100);
|
||||
}
|
||||
};
|
||||
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
$("#predictButton").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
// loading button
|
||||
|
||||
// validation
|
||||
|
||||
// existing pws...
|
||||
|
||||
// submit form
|
||||
$("#predict_modal_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -1,5 +1,10 @@
|
||||
{% load static %}
|
||||
<dialog id="search_modal" class="modal @max-sm:modal-top justify-center">
|
||||
<dialog
|
||||
id="search_modal"
|
||||
class="modal @max-sm:modal-top justify-center"
|
||||
x-data="searchModal()"
|
||||
@close="reset()"
|
||||
>
|
||||
<div class="modal-box h-full w-lvw p-1 sm:h-8/12 sm:w-[85vw] sm:max-w-5xl">
|
||||
<!-- Search Input and Mode Selector -->
|
||||
<div class="form-control mb-4 w-full shrink-0">
|
||||
@ -23,7 +28,9 @@
|
||||
<input
|
||||
type="text"
|
||||
autofocus
|
||||
id="modal_searchbar"
|
||||
x-ref="searchbar"
|
||||
x-model="query"
|
||||
@keydown.enter="performSearch('{{ SERVER_BASE }}')"
|
||||
placeholder="Benfuracarb"
|
||||
class="grow"
|
||||
aria-label="Search"
|
||||
@ -35,12 +42,11 @@
|
||||
<button
|
||||
type="button"
|
||||
tabindex="0"
|
||||
id="modal_mode_button"
|
||||
popovertarget="search_dropdown_menu"
|
||||
style="anchor-name:--1"
|
||||
style="anchor-name: --1"
|
||||
class="btn join-item btn-ghost"
|
||||
>
|
||||
Text
|
||||
<span x-text="searchModeLabel"></span>
|
||||
<svg
|
||||
class="ml-1 h-4 w-4"
|
||||
fill="none"
|
||||
@ -59,13 +65,14 @@
|
||||
tabindex="0"
|
||||
class="dropdown dropdown-end menu bg-base-200 rounded-box w-64 p-2 shadow-lg"
|
||||
popover
|
||||
x-ref="modeDropdown"
|
||||
id="search_dropdown_menu"
|
||||
style="position-anchor:--anchor-2"
|
||||
style="position-anchor: --anchor-2"
|
||||
>
|
||||
<li class="menu-title">Text</li>
|
||||
<li>
|
||||
<a
|
||||
id="modal_dropdown_text"
|
||||
@click.prevent="setSearchMode('text', 'Text')"
|
||||
class="tooltip tooltip-left"
|
||||
data-tip="Search on object names and descriptions"
|
||||
>
|
||||
@ -75,7 +82,7 @@
|
||||
<li class="menu-title">SMILES</li>
|
||||
<li>
|
||||
<a
|
||||
id="modal_dropdown_smiles_default"
|
||||
@click.prevent="setSearchMode('smiles_default', 'Default')"
|
||||
class="tooltip tooltip-left"
|
||||
data-tip="Ignores stereochemistry and charge"
|
||||
>
|
||||
@ -84,7 +91,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
id="modal_dropdown_smiles_canonical"
|
||||
@click.prevent="setSearchMode('smiles_canonical', 'Canonical')"
|
||||
class="tooltip tooltip-left"
|
||||
data-tip="Ignores stereochemistry, preserves charge"
|
||||
>
|
||||
@ -93,7 +100,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
id="modal_dropdown_smiles_exact"
|
||||
@click.prevent="setSearchMode('smiles_exact', 'Exact')"
|
||||
class="tooltip tooltip-left"
|
||||
data-tip="Exact match for stereochemistry and charge"
|
||||
>
|
||||
@ -103,7 +110,7 @@
|
||||
<li class="menu-title">InChI</li>
|
||||
<li>
|
||||
<a
|
||||
id="modal_dropdown_inchikey"
|
||||
@click.prevent="setSearchMode('inchikey', 'InChIKey')"
|
||||
class="tooltip tooltip-left"
|
||||
data-tip="Search by InChIKey"
|
||||
>
|
||||
@ -115,7 +122,7 @@
|
||||
|
||||
<button
|
||||
type="button"
|
||||
id="modal_search_button"
|
||||
@click="performSearch('{{ SERVER_BASE }}')"
|
||||
class="btn btn-xs btn-ghost join-item"
|
||||
>
|
||||
<kbd class="kbd kbd-sm text-base-content/50 p-1">
|
||||
@ -143,18 +150,62 @@
|
||||
<div class="form-control mb-4 shrink-0">
|
||||
<!-- Pills Container -->
|
||||
<div
|
||||
id="modal_package_pills_container"
|
||||
class="border-base-300 m-3 flex min-h-12 flex-wrap items-center gap-2 rounded-lg border-2 border-dashed p-3"
|
||||
>
|
||||
<!-- Pills will be added here dynamically -->
|
||||
<!-- Dynamic Pills -->
|
||||
<template x-for="pkg in selectedPackages" :key="pkg.url">
|
||||
<span class="badge badge-outline gap-2 max-w-xs">
|
||||
<span class="truncate" :title="pkg.name" x-text="pkg.name"></span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 cursor-pointer hover:text-error shrink-0 rotate-45"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
@click="removePackage(pkg.url)"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5v14" />
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<!-- Add Package Button -->
|
||||
<button
|
||||
type="button"
|
||||
popovertarget="package_dropdown_menu"
|
||||
style="anchor-name: --anchor-packages"
|
||||
class="btn btn-sm btn-ghost gap-2 text-base-content/50"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-plus-icon lucide-plus"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5v14" />
|
||||
</svg>
|
||||
Add Package
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Package Dropdown Menu -->
|
||||
<ul
|
||||
class="dropdown dropdown-center menu bg-base-200 rounded-box max-h-96 w-80 overflow-y-auto p-2 shadow-lg"
|
||||
popover
|
||||
x-ref="packageDropdown"
|
||||
id="package_dropdown_menu"
|
||||
style="position-anchor:--anchor-packages"
|
||||
style="position-anchor: --anchor-packages"
|
||||
>
|
||||
{% if unreviewed_packages %}
|
||||
<li class="menu-title">Reviewed Packages</li>
|
||||
@ -164,11 +215,13 @@
|
||||
class="package-option flex items-center justify-between"
|
||||
data-package-url="{{ obj.url }}"
|
||||
data-package-name="{{ obj.name }}"
|
||||
@click.prevent.stop="togglePackage('{{ obj.url }}', '{{ obj.name }}')"
|
||||
>
|
||||
<span>{{ obj.name }}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="package-checkmark hidden h-4 w-4"
|
||||
class="h-4 w-4"
|
||||
:class="isPackageSelected('{{ obj.url }}') ? '' : 'hidden'"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
@ -190,11 +243,13 @@
|
||||
class="package-option flex items-center justify-between"
|
||||
data-package-url="{{ obj.url }}"
|
||||
data-package-name="{{ obj.name }}"
|
||||
@click.prevent.stop="togglePackage('{{ obj.url }}', '{{ obj.name }}')"
|
||||
>
|
||||
<span>{{ obj.name }}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="package-checkmark hidden h-4 w-4"
|
||||
class="h-4 w-4"
|
||||
:class="isPackageSelected('{{ obj.url }}') ? '' : 'hidden'"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
@ -217,11 +272,13 @@
|
||||
class="package-option flex items-center justify-between"
|
||||
data-package-url="{{ obj.url }}"
|
||||
data-package-name="{{ obj.name }}"
|
||||
@click.prevent.stop="togglePackage('{{ obj.url }}', '{{ obj.name }}')"
|
||||
>
|
||||
<span>{{ obj.name }}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="package-checkmark hidden h-4 w-4"
|
||||
class="h-4 w-4"
|
||||
:class="isPackageSelected('{{ obj.url }}') ? '' : 'hidden'"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
@ -241,12 +298,201 @@
|
||||
</div>
|
||||
|
||||
<!-- Loading Indicator -->
|
||||
<div id="search_loading" class="hidden shrink-0 justify-center py-8">
|
||||
<div x-show="isSearching" class="flex shrink-0 justify-center py-8">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
</div>
|
||||
|
||||
<!-- Results Container - scrollable -->
|
||||
<div id="search_results" class="min-h-0 flex-1 overflow-y-auto p-2"></div>
|
||||
<!-- Results Container -->
|
||||
<div class="min-h-0 flex-1 overflow-y-auto p-2">
|
||||
<!-- No packages selected error -->
|
||||
<template x-if="results && results.error === 'no_packages'">
|
||||
<div class="alert alert-info">
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Please select at least one package</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Search error -->
|
||||
<template x-if="error">
|
||||
<div class="alert alert-error">
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span x-text="error"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- No results -->
|
||||
<template x-if="results && !results.error && !hasResults()">
|
||||
<div class="alert alert-warning">
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
<span>No results found</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Results display -->
|
||||
<template x-if="results && !results.error && hasResults()">
|
||||
<div class="mb-2">
|
||||
<div class="text-sm font-semibold text-base-content/70 mb-2">
|
||||
Results
|
||||
</div>
|
||||
|
||||
<!-- Compounds -->
|
||||
<template x-if="results.Compounds && results.Compounds.length > 0">
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
Compounds
|
||||
<span
|
||||
class="badge badge-neutral badge-sm ml-2"
|
||||
x-text="results.Compounds.length"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<template x-for="item in results.Compounds" :key="item.url">
|
||||
<a
|
||||
:href="item.url"
|
||||
class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors"
|
||||
x-text="item.name"
|
||||
></a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Compound Structures -->
|
||||
<template
|
||||
x-if="results['Compound Structures'] && results['Compound Structures'].length > 0"
|
||||
>
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
Compound Structures
|
||||
<span
|
||||
class="badge badge-neutral badge-sm ml-2"
|
||||
x-text="results['Compound Structures'].length"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<template
|
||||
x-for="item in results['Compound Structures']"
|
||||
:key="item.url"
|
||||
>
|
||||
<a
|
||||
:href="item.url"
|
||||
class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors"
|
||||
x-text="item.name"
|
||||
></a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Rules -->
|
||||
<template x-if="results.Rules && results.Rules.length > 0">
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
Rules
|
||||
<span
|
||||
class="badge badge-neutral badge-sm ml-2"
|
||||
x-text="results.Rules.length"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<template x-for="item in results.Rules" :key="item.url">
|
||||
<a
|
||||
:href="item.url"
|
||||
class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors"
|
||||
x-text="item.name"
|
||||
></a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Reactions -->
|
||||
<template x-if="results.Reactions && results.Reactions.length > 0">
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
Reactions
|
||||
<span
|
||||
class="badge badge-neutral badge-sm ml-2"
|
||||
x-text="results.Reactions.length"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<template x-for="item in results.Reactions" :key="item.url">
|
||||
<a
|
||||
:href="item.url"
|
||||
class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors"
|
||||
x-text="item.name"
|
||||
></a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Pathways -->
|
||||
<template x-if="results.Pathways && results.Pathways.length > 0">
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
Pathways
|
||||
<span
|
||||
class="badge badge-neutral badge-sm ml-2"
|
||||
x-text="results.Pathways.length"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<template x-for="item in results.Pathways" :key="item.url">
|
||||
<a
|
||||
:href="item.url"
|
||||
class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors"
|
||||
x-text="item.name"
|
||||
></a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Backdrop to close -->
|
||||
@ -254,433 +500,3 @@
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
// Package Selector Module - Data-driven multiselect package selection
|
||||
const PackageSelector = {
|
||||
// Single source of truth: array of selected packages
|
||||
selectedPackages: [],
|
||||
|
||||
elements: {
|
||||
pillsContainer: null,
|
||||
packageDropdown: null,
|
||||
packageOptions: null,
|
||||
},
|
||||
|
||||
init() {
|
||||
this.cacheElements();
|
||||
this.loadInitialSelection();
|
||||
this.attachEventListeners();
|
||||
this.render();
|
||||
},
|
||||
|
||||
cacheElements() {
|
||||
this.elements.pillsContainer = document.getElementById(
|
||||
"modal_package_pills_container",
|
||||
);
|
||||
this.elements.packageDropdown = document.getElementById(
|
||||
"package_dropdown_menu",
|
||||
);
|
||||
this.elements.packageOptions =
|
||||
document.querySelectorAll(".package-option");
|
||||
},
|
||||
|
||||
loadInitialSelection() {
|
||||
// Load pre-selected packages from server-rendered pills
|
||||
const existingPills =
|
||||
this.elements.pillsContainer.querySelectorAll(".badge");
|
||||
existingPills.forEach((pill) => {
|
||||
this.selectedPackages.push({
|
||||
url: pill.dataset.packageUrl,
|
||||
name: pill.dataset.packageName,
|
||||
});
|
||||
});
|
||||
|
||||
// If no pills found, select all reviewed packages by default
|
||||
if (this.selectedPackages.length === 0) {
|
||||
// Iterate through all menu items and collect reviewed packages
|
||||
const menuItems =
|
||||
this.elements.packageDropdown.querySelectorAll("li");
|
||||
|
||||
for (const item of menuItems) {
|
||||
// Check if this is the "Unreviewed Packages" menu title
|
||||
if (
|
||||
item.classList.contains("menu-title") &&
|
||||
item.textContent.trim() === "Unreviewed Packages"
|
||||
) {
|
||||
break; // Stop processing after this point
|
||||
}
|
||||
|
||||
// Check for package options (only reviewed packages reach here)
|
||||
const packageOption = item.querySelector(".package-option");
|
||||
if (packageOption) {
|
||||
this.selectedPackages.push({
|
||||
url: packageOption.dataset.packageUrl,
|
||||
name: packageOption.dataset.packageName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
attachEventListeners() {
|
||||
// Toggle package selection on dropdown item click
|
||||
this.elements.packageOptions.forEach((option) => {
|
||||
option.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // Prevent dropdown from closing
|
||||
const packageUrl = option.dataset.packageUrl;
|
||||
const packageName = option.dataset.packageName;
|
||||
this.togglePackageSelection(packageUrl, packageName);
|
||||
});
|
||||
});
|
||||
|
||||
// Remove package when X is clicked (using event delegation)
|
||||
this.elements.pillsContainer.addEventListener("click", (e) => {
|
||||
if (
|
||||
e.target.classList.contains("package-remove-btn") ||
|
||||
e.target.closest(".package-remove-btn")
|
||||
) {
|
||||
const pill = e.target.closest(".badge");
|
||||
if (pill) {
|
||||
const packageUrl = pill.dataset.packageUrl;
|
||||
this.removePackage(packageUrl);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
togglePackageSelection(packageUrl, packageName) {
|
||||
const index = this.selectedPackages.findIndex(
|
||||
(pkg) => pkg.url === packageUrl,
|
||||
);
|
||||
|
||||
if (index !== -1) {
|
||||
// Remove from selection
|
||||
this.selectedPackages.splice(index, 1);
|
||||
} else {
|
||||
// Add to selection
|
||||
this.selectedPackages.push({ url: packageUrl, name: packageName });
|
||||
}
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
removePackage(packageUrl) {
|
||||
const index = this.selectedPackages.findIndex(
|
||||
(pkg) => pkg.url === packageUrl,
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.selectedPackages.splice(index, 1);
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
this.renderPills();
|
||||
this.renderAddButton();
|
||||
this.renderCheckmarks();
|
||||
},
|
||||
|
||||
renderPills() {
|
||||
// Clear existing pills and button (except placeholder)
|
||||
const pills = this.elements.pillsContainer.querySelectorAll(".badge");
|
||||
pills.forEach((pill) => pill.remove());
|
||||
|
||||
const existingButton = this.elements.pillsContainer.querySelector(
|
||||
"#modal_package_add_button",
|
||||
);
|
||||
if (existingButton) {
|
||||
existingButton.remove();
|
||||
}
|
||||
|
||||
// Create pills from data
|
||||
this.selectedPackages.forEach((pkg) => {
|
||||
const pill = this.createPillElement(pkg.url, pkg.name);
|
||||
this.elements.pillsContainer.appendChild(pill);
|
||||
});
|
||||
},
|
||||
|
||||
renderAddButton() {
|
||||
// Only render button if there are packages available
|
||||
if (this.elements.packageOptions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.id = "modal_package_add_button";
|
||||
button.setAttribute("popovertarget", "package_dropdown_menu");
|
||||
button.style.cssText = "anchor-name:--anchor-packages";
|
||||
button.className = "btn btn-sm btn-ghost gap-2 text-base-content/50";
|
||||
|
||||
button.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-plus-icon lucide-plus"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
|
||||
Add Package
|
||||
`;
|
||||
|
||||
this.elements.pillsContainer.appendChild(button);
|
||||
},
|
||||
|
||||
createPillElement(packageUrl, packageName) {
|
||||
const pill = document.createElement("span");
|
||||
pill.className = "badge badge-outline gap-2 max-w-xs";
|
||||
pill.dataset.packageUrl = packageUrl;
|
||||
pill.dataset.packageName = packageName;
|
||||
|
||||
pill.innerHTML = `
|
||||
<span class="truncate" title="${packageName}">${packageName}</span>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 cursor-pointer hover:text-error package-remove-btn flex-shrink-0 rotate-45"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M5 12h14"/><path d="M12 5v14"/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
return pill;
|
||||
},
|
||||
|
||||
renderCheckmarks() {
|
||||
// Update all checkmarks based on selected packages
|
||||
this.elements.packageOptions.forEach((option) => {
|
||||
const packageUrl = option.dataset.packageUrl;
|
||||
const isSelected = this.selectedPackages.some(
|
||||
(pkg) => pkg.url === packageUrl,
|
||||
);
|
||||
const checkmark = option.querySelector(".package-checkmark");
|
||||
|
||||
if (checkmark) {
|
||||
checkmark.classList.toggle("hidden", !isSelected);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getSelectedPackages() {
|
||||
return this.selectedPackages.map((pkg) => pkg.url);
|
||||
},
|
||||
};
|
||||
|
||||
// Modal and Search Management
|
||||
const modal = document.getElementById("search_modal");
|
||||
const searchbar = document.getElementById("modal_searchbar");
|
||||
const searchButton = document.getElementById("modal_search_button");
|
||||
const modeButton = document.getElementById("modal_mode_button");
|
||||
const resultsDiv = document.getElementById("search_results");
|
||||
const loadingDiv = document.getElementById("search_loading");
|
||||
|
||||
// MutationObserver to detect when modal opens
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.attributeName === "open" && modal.open) {
|
||||
PackageSelector.render();
|
||||
// Delay focus to allow CSS transitions to complete (modal has 0.3s transition)
|
||||
setTimeout(() => {
|
||||
searchbar.focus();
|
||||
}, 320);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(modal, { attributes: true });
|
||||
|
||||
// Close modal when clicking outside (on the backdrop)
|
||||
// According to DaisyUI docs: https://daisyui.com/components/modal/
|
||||
// The backdrop form with method="dialog" should handle closing automatically when its button is clicked.
|
||||
// We also handle clicks directly on the dialog element (backdrop area) or the backdrop form.
|
||||
modal.addEventListener("click", function (event) {
|
||||
const backdrop = modal.querySelector(".modal-backdrop");
|
||||
const modalBox = modal.querySelector(".modal-box");
|
||||
|
||||
// Close if clicking directly on the dialog element (backdrop area)
|
||||
// or on the backdrop form (but ensure we're not clicking on modal-box content)
|
||||
if (
|
||||
event.target === modal ||
|
||||
(backdrop &&
|
||||
(event.target === backdrop || backdrop.contains(event.target)) &&
|
||||
!modalBox.contains(event.target))
|
||||
) {
|
||||
modal.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Clear results when modal closes
|
||||
modal.addEventListener("close", function () {
|
||||
resultsDiv.innerHTML = "";
|
||||
loadingDiv.classList.add("hidden");
|
||||
searchbar.value = "";
|
||||
});
|
||||
|
||||
// Mode dropdown handlers
|
||||
const dropdownMenu = document.getElementById("search_dropdown_menu");
|
||||
|
||||
const modeButtons = [
|
||||
{ id: "modal_dropdown_text", text: "Text" },
|
||||
{ id: "modal_dropdown_smiles_default", text: "Default" },
|
||||
{ id: "modal_dropdown_smiles_canonical", text: "Canonical" },
|
||||
{ id: "modal_dropdown_smiles_exact", text: "Exact" },
|
||||
{ id: "modal_dropdown_inchikey", text: "InChIKey" },
|
||||
];
|
||||
|
||||
modeButtons.forEach(({ id, text }) => {
|
||||
document.getElementById(id).addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
modeButton.innerHTML =
|
||||
text +
|
||||
` <svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||
</svg>`;
|
||||
// Close dropdown using popover API
|
||||
if (dropdownMenu && typeof dropdownMenu.hidePopover === "function") {
|
||||
dropdownMenu.hidePopover();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize Package Selector
|
||||
PackageSelector.init();
|
||||
|
||||
// Search Response Handler
|
||||
function handleSearchResponse(data) {
|
||||
resultsDiv.innerHTML = "";
|
||||
|
||||
function makeContent(objs) {
|
||||
let links = "";
|
||||
objs.forEach((obj) => {
|
||||
links += `<a href="${obj.url}" class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors">${obj.name}</a>`;
|
||||
});
|
||||
return links;
|
||||
}
|
||||
|
||||
let allEmpty = true;
|
||||
let content = "";
|
||||
|
||||
// Category order for better UX
|
||||
const categoryOrder = [
|
||||
"Compounds",
|
||||
"Compound Structures",
|
||||
"Rules",
|
||||
"Reactions",
|
||||
"Pathways",
|
||||
];
|
||||
|
||||
categoryOrder.forEach((key) => {
|
||||
if (!data[key] || data[key].length < 1) {
|
||||
return;
|
||||
}
|
||||
allEmpty = false;
|
||||
|
||||
content += `
|
||||
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title font-medium">
|
||||
${key} <span class="badge badge-neutral badge-sm ml-2">${data[key].length}</span>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
${makeContent(data[key])}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
if (allEmpty) {
|
||||
resultsDiv.innerHTML = `
|
||||
<div class="alert alert-warning">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||
</svg>
|
||||
<span>No results found</span>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
resultsDiv.innerHTML = `
|
||||
<div class="mb-2">
|
||||
<div class="text-sm font-semibold text-base-content/70 mb-2">Results</div>
|
||||
${content}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Search Execution
|
||||
function performSearch(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const query = searchbar.value.trim();
|
||||
|
||||
if (!query) {
|
||||
console.log("Search phrase empty, won't do search");
|
||||
return;
|
||||
}
|
||||
|
||||
const selPacks = PackageSelector.getSelectedPackages();
|
||||
|
||||
if (selPacks.length < 1) {
|
||||
console.log("No package selected, won't do search");
|
||||
resultsDiv.innerHTML = `
|
||||
<div class="alert alert-info">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>Please select at least one package</span>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = modeButton.textContent.trim().toLowerCase();
|
||||
|
||||
const params = new URLSearchParams();
|
||||
selPacks.forEach((pack) => params.append("packages", pack));
|
||||
params.append("search", query);
|
||||
params.append("mode", mode);
|
||||
|
||||
// Show loading
|
||||
loadingDiv.classList.remove("hidden");
|
||||
resultsDiv.innerHTML = "";
|
||||
|
||||
fetch(`{{ SERVER_BASE }}/search?${params.toString()}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Search request failed");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((result) => {
|
||||
loadingDiv.classList.add("hidden");
|
||||
handleSearchResponse(result);
|
||||
})
|
||||
.catch((error) => {
|
||||
loadingDiv.classList.add("hidden");
|
||||
console.error("Search error:", error);
|
||||
resultsDiv.innerHTML = `
|
||||
<div class="alert alert-error">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>Search failed. Please try again.</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
// Event listeners for search
|
||||
searchButton.addEventListener("click", performSearch);
|
||||
searchbar.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Enter") {
|
||||
performSearch(e);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user