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,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_compound_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_compound_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Compound</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#new_compound_structure_modal"
|
||||
onclick="document.getElementById('new_compound_structure_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Compound Structure</a
|
||||
>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_edge_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_edge_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Edge</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_group_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_group_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Group</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit and meta.enabled_features.MODEL_BUILDING %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_model_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_model_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Model</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_node_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_node_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Node</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,18 +1,23 @@
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_package_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_package_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Package</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#import_package_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('import_package_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-import"></span> Import Package from JSON</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#import_legacy_package_modal"
|
||||
onclick="document.getElementById('import_legacy_package_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-import"></span> Import Package from legacy
|
||||
JSON</a
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_reaction_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_reaction_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Reaction</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_rule_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_rule_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Rule</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span> New Scenario</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#new_setting_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('new_setting_modal').showModal(); return false;"
|
||||
>
|
||||
<span class="glyphicon glyphicon-plus"></span>New Setting</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,42 +1,59 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_compound_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_compound_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Compound</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#add_structure_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('add_structure_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Add Structure</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#generic_set_external_reference_modal"
|
||||
onclick="document.getElementById('generic_set_external_reference_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set External Reference</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_copy_object_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('generic_copy_object_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-duplicate"></i> Copy</a
|
||||
>
|
||||
</li>
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Compound</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -2,33 +2,40 @@
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#edit_compound_structure_modal"
|
||||
onclick="document.getElementById('edit_compound_structure_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Compound Structure</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#generic_set_external_reference_modal"
|
||||
onclick="document.getElementById('generic_set_external_reference_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set External Reference</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Compound Structure</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,16 +1,25 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Edge</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_group_member_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_group_member_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Add/Remove Member</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Group</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,21 +1,33 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_model_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_model_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Model</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#evaluate_model_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('evaluate_model_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-ok"></i> Evaluate Model</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#retrain_model_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('retrain_model_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-repeat"></i> Retrain Model</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Model</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,21 +1,33 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_node_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_node_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Node</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Node</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,35 +1,49 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_package_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_package_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Package</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#edit_package_permissions_modal"
|
||||
onclick="document.getElementById('edit_package_permissions_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-user"></i> Edit Permissions</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#publish_package_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('publish_package_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-bullhorn"></i> Publish Package</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#export_package_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('export_package_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-bullhorn"></i> Export Package as JSON</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_license_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_license_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-duplicate"></i> License</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Package</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,26 +1,34 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#add_pathway_node_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('add_pathway_node_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Add Compound</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#add_pathway_edge_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('add_pathway_edge_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Add Reaction</a
|
||||
>
|
||||
</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_copy_object_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('generic_copy_object_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-duplicate"></i> Copy</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#download_pathway_csv_modal"
|
||||
onclick="document.getElementById('download_pathway_csv_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-floppy-save"></i> Download Pathway as CSV</a
|
||||
>
|
||||
@ -28,8 +36,7 @@
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#download_pathway_image_modal"
|
||||
onclick="document.getElementById('download_pathway_image_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-floppy-save"></i> Download Pathway as Image</a
|
||||
>
|
||||
@ -38,8 +45,7 @@
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#identify_missing_rules_modal"
|
||||
onclick="document.getElementById('identify_missing_rules_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-question-sign"></i> Identify Missing
|
||||
Rules</a
|
||||
@ -47,30 +53,34 @@
|
||||
</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#edit_pathway_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('edit_pathway_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Pathway</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
{# <li>#}
|
||||
{# <a class="button" data-toggle="modal" data-target="#add_pathway_edge_modal">#}
|
||||
{# <i class="glyphicon glyphicon-plus"></i> Calculate Compound Properties</a>#}
|
||||
{# </li>#}
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#delete_pathway_node_modal"
|
||||
onclick="document.getElementById('delete_pathway_node_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Compound</a
|
||||
>
|
||||
@ -78,14 +88,16 @@
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#delete_pathway_edge_modal"
|
||||
onclick="document.getElementById('delete_pathway_edge_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Reaction</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Pathway</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,37 +1,51 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_reaction_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_reaction_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Reaction</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#generic_set_external_reference_modal"
|
||||
onclick="document.getElementById('generic_set_external_reference_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set External Reference</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_copy_object_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('generic_copy_object_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-duplicate"></i> Copy</a
|
||||
>
|
||||
</li>
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Reaction</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,28 +1,43 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_rule_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_rule_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Edit Rule</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_aliases_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_aliases_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Aliases</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#set_scenario_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('set_scenario_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> Set Scenarios</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_copy_object_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('generic_copy_object_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-duplicate"></i> Copy</a
|
||||
>
|
||||
</li>
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Rule</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#add_additional_information_modal"
|
||||
onclick="document.getElementById('add_additional_information_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Add Additional Information</a
|
||||
>
|
||||
@ -11,14 +10,16 @@
|
||||
<li>
|
||||
<a
|
||||
class="button"
|
||||
data-toggle="modal"
|
||||
data-target="#update_scenario_additional_information_modal"
|
||||
onclick="document.getElementById('update_scenario_additional_information_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Set Additional Information</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Scenario</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
{% if meta.can_edit %}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_user_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_user_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-edit"></i> Update</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#edit_password_modal">
|
||||
<a
|
||||
role="button"
|
||||
onclick="document.getElementById('edit_password_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-lock"></i> Update Password</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
data-target="#new_prediction_setting_modal"
|
||||
onclick="document.getElementById('new_prediction_setting_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-plus"></i> New Prediction Setting</a
|
||||
>
|
||||
@ -23,7 +28,10 @@
|
||||
{# <i class="glyphicon glyphicon-console"></i> Manage API Token</a>#}
|
||||
{# </li>#}
|
||||
<li>
|
||||
<a role="button" data-toggle="modal" data-target="#generic_delete_modal">
|
||||
<a
|
||||
class="button"
|
||||
onclick="document.getElementById('generic_delete_modal').showModal(); return false;"
|
||||
>
|
||||
<i class="glyphicon glyphicon-trash"></i> Delete Account</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@ -1,49 +1,33 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% load envipytags %}
|
||||
{% block content %}
|
||||
<div class="panel-group" id="reviewListAccordion">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
Jobs
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>Job Logs Desc</p>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-2xl">User Prediction Jobs</h2>
|
||||
<p class="mt-2">Job Logs Desc</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="job-accordion-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#job-accordion"
|
||||
href="#jobs"
|
||||
>
|
||||
Jobs
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="jobs" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item" id="job-content">
|
||||
<table class="table-bordered table-hover table">
|
||||
<tr style="background-color: rgba(0, 0, 0, 0.08);">
|
||||
{% if meta.user.is_superuser %}
|
||||
<th scope="col">User</th>
|
||||
{% endif %}
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Queued</th>
|
||||
<th scope="col">Done</th>
|
||||
<th scope="col">Result</th>
|
||||
</tr>
|
||||
<!-- Jobs -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Recent Jobs</div>
|
||||
<div class="collapse-content" id="job-content">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table-zebra table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Queued</th>
|
||||
<th>Done</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for job in jobs %}
|
||||
<tr>
|
||||
@ -58,7 +42,11 @@
|
||||
<td>{{ job.created }}</td>
|
||||
<td>{{ job.done_at }}</td>
|
||||
{% if job.task_result and job.task_result|is_url == True %}
|
||||
<td><a href="{{ job.task_result }}">Result</a></td>
|
||||
<td>
|
||||
<a href="{{ job.task_result }}" class="link link-primary"
|
||||
>Result</a
|
||||
>
|
||||
</td>
|
||||
{% elif job.task_result %}
|
||||
<td>{{ job.task_result|slice:"40" }}...</td>
|
||||
{% else %}
|
||||
@ -70,19 +58,31 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Unreviewable objects such as User / Group / Setting -->
|
||||
<ul class="list-group">
|
||||
{% for obj in objects %}
|
||||
{% if object_type == 'user' %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.username }}</a
|
||||
>
|
||||
{% else %}
|
||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if objects %}
|
||||
<!-- Unreviewable objects such as User / Group / Setting -->
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for obj in objects %}
|
||||
{% if object_type == 'user' %}
|
||||
<li>
|
||||
<a href="{{ obj.url }}" class="hover:bg-base-300"
|
||||
>{{ obj.username }}</a
|
||||
>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ obj.url }}" class="hover:bg-base-300"
|
||||
>{{ obj.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,28 +1,32 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
|
||||
{% if object_type != 'package' %}
|
||||
<div>
|
||||
<div id="load-all-error" style="display: none;">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<span
|
||||
class="glyphicon glyphicon-exclamation-sign"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<span class="sr-only">Error:</span>
|
||||
Getting objects failed!
|
||||
</div>
|
||||
</div>
|
||||
{# Serialize objects data for Alpine pagination #}
|
||||
{# prettier-ignore-start #}
|
||||
{# FIXME: This is a hack to get the objects data into the JavaScript code. #}
|
||||
<script>
|
||||
window.reviewedObjects = [
|
||||
{% for obj in reviewed_objects %}
|
||||
{ "name": "{{ obj.name|escapejs }}", "url": "{{ obj.url }}" }{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
];
|
||||
window.unreviewedObjects = [
|
||||
{% for obj in unreviewed_objects %}
|
||||
{ "name": "{{ obj.name|escapejs }}", "url": "{{ obj.url }}" }{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
];
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
|
||||
{% if object_type != 'package' %}
|
||||
<div class="px-8 py-4">
|
||||
<input
|
||||
type="text"
|
||||
id="object-search"
|
||||
class="form-control"
|
||||
class="input input-bordered hidden w-full max-w-xs"
|
||||
placeholder="Search by name"
|
||||
style="display: none;"
|
||||
/>
|
||||
<p></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@ -56,423 +60,474 @@
|
||||
{% endif %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="reviewListAccordion">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{% if object_type == 'package' %}
|
||||
Packages
|
||||
{% elif object_type == 'compound' %}
|
||||
Compounds
|
||||
{% elif object_type == 'structure' %}
|
||||
Compound structures
|
||||
{% elif object_type == 'rule' %}
|
||||
Rules
|
||||
{% elif object_type == 'reaction' %}
|
||||
Reactions
|
||||
{% elif object_type == 'pathway' %}
|
||||
Pathways
|
||||
{% elif object_type == 'node' %}
|
||||
Nodes
|
||||
{% elif object_type == 'edge' %}
|
||||
Edges
|
||||
{% elif object_type == 'scenario' %}
|
||||
Scenarios
|
||||
{% elif object_type == 'model' %}
|
||||
Model
|
||||
{% elif object_type == 'setting' %}
|
||||
Settings
|
||||
{% elif object_type == 'user' %}
|
||||
Users
|
||||
{% elif object_type == 'group' %}
|
||||
Groups
|
||||
{% endif %}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% if object_type == 'package' %}
|
||||
{% include "actions/collections/package.html" %}
|
||||
{% elif object_type == 'compound' %}
|
||||
{% include "actions/collections/compound.html" %}
|
||||
{% elif object_type == 'structure' %}
|
||||
{% include "actions/collections/compound_structure.html" %}
|
||||
{% elif object_type == 'rule' %}
|
||||
{% include "actions/collections/rule.html" %}
|
||||
{% elif object_type == 'reaction' %}
|
||||
{% include "actions/collections/reaction.html" %}
|
||||
{% elif object_type == 'setting' %}
|
||||
{% include "actions/collections/setting.html" %}
|
||||
{% elif object_type == 'scenario' %}
|
||||
{% include "actions/collections/scenario.html" %}
|
||||
{% elif object_type == 'model' %}
|
||||
{% include "actions/collections/model.html" %}
|
||||
{% elif object_type == 'pathway' %}
|
||||
{% include "actions/collections/pathway.html" %}
|
||||
{% elif object_type == 'node' %}
|
||||
{% include "actions/collections/node.html" %}
|
||||
{% elif object_type == 'edge' %}
|
||||
{% include "actions/collections/edge.html" %}
|
||||
{% elif object_type == 'group' %}
|
||||
{% include "actions/collections/group.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
<div class="px-8 py-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body px-0 py-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">
|
||||
{% if object_type == 'package' %}
|
||||
Packages
|
||||
{% elif object_type == 'compound' %}
|
||||
Compounds
|
||||
{% elif object_type == 'structure' %}
|
||||
Compound structures
|
||||
{% elif object_type == 'rule' %}
|
||||
Rules
|
||||
{% elif object_type == 'reaction' %}
|
||||
Reactions
|
||||
{% elif object_type == 'pathway' %}
|
||||
Pathways
|
||||
{% elif object_type == 'node' %}
|
||||
Nodes
|
||||
{% elif object_type == 'edge' %}
|
||||
Edges
|
||||
{% elif object_type == 'scenario' %}
|
||||
Scenarios
|
||||
{% elif object_type == 'model' %}
|
||||
Model
|
||||
{% elif object_type == 'setting' %}
|
||||
Settings
|
||||
{% elif object_type == 'user' %}
|
||||
Users
|
||||
{% elif object_type == 'group' %}
|
||||
Groups
|
||||
{% endif %}
|
||||
</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% if object_type == 'package' %}
|
||||
{% include "actions/collections/package.html" %}
|
||||
{% elif object_type == 'compound' %}
|
||||
{% include "actions/collections/compound.html" %}
|
||||
{% elif object_type == 'structure' %}
|
||||
{% include "actions/collections/compound_structure.html" %}
|
||||
{% elif object_type == 'rule' %}
|
||||
{% include "actions/collections/rule.html" %}
|
||||
{% elif object_type == 'reaction' %}
|
||||
{% include "actions/collections/reaction.html" %}
|
||||
{% elif object_type == 'setting' %}
|
||||
{% include "actions/collections/setting.html" %}
|
||||
{% elif object_type == 'scenario' %}
|
||||
{% include "actions/collections/scenario.html" %}
|
||||
{% elif object_type == 'model' %}
|
||||
{% include "actions/collections/model.html" %}
|
||||
{% elif object_type == 'pathway' %}
|
||||
{% include "actions/collections/pathway.html" %}
|
||||
{% elif object_type == 'node' %}
|
||||
{% include "actions/collections/node.html" %}
|
||||
{% elif object_type == 'edge' %}
|
||||
{% include "actions/collections/edge.html" %}
|
||||
{% elif object_type == 'group' %}
|
||||
{% include "actions/collections/group.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- Set Text above links -->
|
||||
{% if object_type == 'package' %}
|
||||
<p>
|
||||
A package contains pathways, rules, etc. and can reflect specific
|
||||
experimental conditions.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'compound' %}
|
||||
<p>
|
||||
A compound stores the structure of a molecule and can include
|
||||
meta-information.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/compounds"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'structure' %}
|
||||
<p>
|
||||
The structures stored in this compound
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/compounds"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'rule' %}
|
||||
<p>
|
||||
A rule describes a biotransformation reaction template that is
|
||||
defined as SMIRKS.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/Rules"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'reaction' %}
|
||||
<p>
|
||||
A reaction is a specific biotransformation from educt compounds to
|
||||
product compounds.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/reactions"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'pathway' %}
|
||||
<p>
|
||||
A pathway displays the (predicted) biodegradation of a compound as
|
||||
graph.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/pathways"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'node' %}
|
||||
<p>
|
||||
Nodes represent the (predicted) compounds in a graph.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/nodes"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'edge' %}
|
||||
<p>
|
||||
Edges represent the links between Nodes in a graph
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/edges"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'scenario' %}
|
||||
<p>
|
||||
A scenario contains meta-information that can be attached to other
|
||||
data (compounds, rules, ..).
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/scenarios"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'model' %}
|
||||
<p>
|
||||
A model applies machine learning to limit the combinatorial
|
||||
explosion.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/relative_reasoning"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'setting' %}
|
||||
<p>
|
||||
A setting includes configuration parameters for pathway predictions.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/settings"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'user' %}
|
||||
<p>
|
||||
Register now to create own packages and to submit and manage your
|
||||
data.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/users"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'group' %}
|
||||
<p>
|
||||
Users can team up in groups to share packages.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/groups"
|
||||
role="button"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<!-- If theres nothing to show extend the text above -->
|
||||
{% if reviewed_objects and unreviewed_objects %}
|
||||
{% if reviewed_objects|length == 0 and unreviewed_objects|length == 0 %}
|
||||
<div class="mt-2">
|
||||
<!-- Set Text above links -->
|
||||
{% if object_type == 'package' %}
|
||||
<p>
|
||||
Nothing found. There are two possible reasons: <br /><br />1.
|
||||
There is no content yet.<br />2. You have no reading
|
||||
permissions.<br /><br />Please be sure you have at least reading
|
||||
permissions.
|
||||
A package contains pathways, rules, etc. and can reflect specific
|
||||
experimental conditions.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'compound' %}
|
||||
<p>
|
||||
A compound stores the structure of a molecule and can include
|
||||
meta-information.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/compounds"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'structure' %}
|
||||
<p>
|
||||
The structures stored in this compound
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/compounds"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'rule' %}
|
||||
<p>
|
||||
A rule describes a biotransformation reaction template that is
|
||||
defined as SMIRKS.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/Rules"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'reaction' %}
|
||||
<p>
|
||||
A reaction is a specific biotransformation from educt compounds to
|
||||
product compounds.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/reactions"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'pathway' %}
|
||||
<p>
|
||||
A pathway displays the (predicted) biodegradation of a compound as
|
||||
graph.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/pathways"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'node' %}
|
||||
<p>
|
||||
Nodes represent the (predicted) compounds in a graph.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/nodes"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'edge' %}
|
||||
<p>
|
||||
Edges represent the links between Nodes in a graph
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/edges"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'scenario' %}
|
||||
<p>
|
||||
A scenario contains meta-information that can be attached to other
|
||||
data (compounds, rules, ..).
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/scenarios"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'model' %}
|
||||
<p>
|
||||
A model applies machine learning to limit the combinatorial
|
||||
explosion.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/relative_reasoning"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'setting' %}
|
||||
<p>
|
||||
A setting includes configuration parameters for pathway
|
||||
predictions.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/settings"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'user' %}
|
||||
<p>
|
||||
Register now to create own packages and to submit and manage your
|
||||
data.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/users"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% elif object_type == 'group' %}
|
||||
<p>
|
||||
Users can team up in groups to share packages.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/groups"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- If theres nothing to show extend the text above -->
|
||||
{% if reviewed_objects and unreviewed_objects %}
|
||||
{% if reviewed_objects|length == 0 and unreviewed_objects|length == 0 %}
|
||||
<p class="mt-4">
|
||||
Nothing found. There are two possible reasons: <br /><br />1.
|
||||
There is no content yet.<br />2. You have no reading
|
||||
permissions.<br /><br />Please be sure you have at least reading
|
||||
permissions.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lists Container - Full Width with Reviewed on Right -->
|
||||
<div class="w-full">
|
||||
{% if reviewed_objects %}
|
||||
{% if reviewed_objects|length > 0 %}
|
||||
<!-- Reviewed -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
class="collapse-arrow bg-base-200 collapse order-2 w-full"
|
||||
x-data="paginatedList(window.reviewedObjects || [], { isReviewed: true, instanceId: 'reviewed' })"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="ReviewedLink"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reviewListAccordion"
|
||||
href="#Reviewed"
|
||||
>Reviewed</a
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Reviewed
|
||||
<span
|
||||
class="badge badge-sm badge-neutral ml-2"
|
||||
x-text="totalItems"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content w-full">
|
||||
<ul class="menu bg-base-100 rounded-box w-full">
|
||||
<template x-for="obj in paginatedItems" :key="obj.url">
|
||||
<li>
|
||||
<a :href="obj.url" class="hover:bg-base-200">
|
||||
<span x-text="obj.name"></span>
|
||||
<span
|
||||
class="tooltip tooltip-left ml-auto"
|
||||
data-tip="Reviewed"
|
||||
>
|
||||
<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-star"
|
||||
>
|
||||
<polygon
|
||||
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<!-- Pagination Controls -->
|
||||
<div
|
||||
x-show="totalPages > 1"
|
||||
class="mt-4 flex items-center justify-between px-2"
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="Reviewed" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item" id="ReviewedContent">
|
||||
{% if object_type == 'package' %}
|
||||
{% for obj in reviewed_objects %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.name|safe }}
|
||||
<span
|
||||
class="glyphicon glyphicon-star"
|
||||
aria-hidden="true"
|
||||
style="float:right"
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
title=""
|
||||
data-original-title="Reviewed"
|
||||
>
|
||||
</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for obj in reviewed_objects|slice:":50" %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.name|safe }}{# <i>({{ obj.package.name }})</i> #}
|
||||
<span
|
||||
class="glyphicon glyphicon-star"
|
||||
aria-hidden="true"
|
||||
style="float:right"
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
title=""
|
||||
data-original-title="Reviewed"
|
||||
>
|
||||
</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<span class="text-base-content/70 text-sm">
|
||||
Showing <span x-text="showingStart"></span>-<span
|
||||
x-text="showingEnd"
|
||||
></span>
|
||||
of <span x-text="totalItems"></span>
|
||||
</span>
|
||||
<div class="join">
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:disabled="currentPage === 1"
|
||||
@click="prevPage()"
|
||||
>
|
||||
«
|
||||
</button>
|
||||
<template x-for="item in pageNumbers" :key="item.key">
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:class="{ 'btn-active': item.page === currentPage }"
|
||||
:disabled="item.isEllipsis"
|
||||
@click="!item.isEllipsis && goToPage(item.page)"
|
||||
x-text="item.page"
|
||||
></button>
|
||||
</template>
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:disabled="currentPage === totalPages"
|
||||
@click="nextPage()"
|
||||
>
|
||||
»
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if unreviewed_objects %}
|
||||
<!-- Unreviewed -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
class="collapse-arrow bg-base-200 collapse order-1 w-full"
|
||||
x-data="paginatedList(window.unreviewedObjects || [], { isReviewed: false, instanceId: 'unreviewed' })"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="UnreviewedLink"
|
||||
data-toggle="collapse"
|
||||
data-parent="#unReviewListAccordion"
|
||||
href="#Unreviewed"
|
||||
>Unreviewed</a
|
||||
<input
|
||||
type="checkbox"
|
||||
{% if reviewed_objects|length == 0 or object_type == 'package' %}checked{% endif %}
|
||||
/>
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Unreviewed
|
||||
<span
|
||||
class="badge badge-sm badge-neutral ml-2"
|
||||
x-text="totalItems"
|
||||
></span>
|
||||
</div>
|
||||
<div class="collapse-content w-full">
|
||||
<ul class="menu bg-base-100 rounded-box w-full">
|
||||
<template x-for="obj in paginatedItems" :key="obj.url">
|
||||
<li>
|
||||
<a
|
||||
:href="obj.url"
|
||||
class="hover:bg-base-200"
|
||||
x-text="obj.name"
|
||||
></a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<!-- Pagination Controls -->
|
||||
<div
|
||||
x-show="totalPages > 1"
|
||||
class="mt-4 flex items-center justify-between px-2"
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="Unreviewed"
|
||||
class="panel-collapse {% if reviewed_objects|length == 0 or object_type == 'package' %}in{% endif %} collapse"
|
||||
>
|
||||
<div class="panel-body list-group-item" id="UnreviewedContent">
|
||||
{% if object_type == 'package' %}
|
||||
{% for obj in unreviewed_objects %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.name|safe }}</a
|
||||
<span class="text-base-content/70 text-sm">
|
||||
Showing <span x-text="showingStart"></span>-<span
|
||||
x-text="showingEnd"
|
||||
></span>
|
||||
of <span x-text="totalItems"></span>
|
||||
</span>
|
||||
<div class="join">
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:disabled="currentPage === 1"
|
||||
@click="prevPage()"
|
||||
>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for obj in unreviewed_objects|slice:":50" %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.name|safe }}</a
|
||||
«
|
||||
</button>
|
||||
<template x-for="item in pageNumbers" :key="item.key">
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:class="{ 'btn-active': item.page === currentPage }"
|
||||
:disabled="item.isEllipsis"
|
||||
@click="!item.isEllipsis && goToPage(item.page)"
|
||||
x-text="item.page"
|
||||
></button>
|
||||
</template>
|
||||
<button
|
||||
class="join-item btn btn-sm"
|
||||
:disabled="currentPage === totalPages"
|
||||
@click="nextPage()"
|
||||
>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
»
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if objects %}
|
||||
<!-- Unreviewable objects such as User / Group / Setting -->
|
||||
<ul class="list-group">
|
||||
{% for obj in objects %}
|
||||
{% if object_type == 'user' %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.username|safe }}</a
|
||||
>
|
||||
{% else %}
|
||||
<a class="list-group-item" href="{{ obj.url }}"
|
||||
>{{ obj.name|safe }}</a
|
||||
>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<style>
|
||||
.spinner-widget {
|
||||
position: fixed; /* stays in place on scroll */
|
||||
bottom: 20px; /* distance from bottom */
|
||||
right: 20px; /* distance from right */
|
||||
z-index: 9999; /* above most elements */
|
||||
width: 60px; /* adjust to gif size */
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.spinner-widget img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="load-all-loading" class="spinner-widget" style="display: none">
|
||||
<img
|
||||
id="loading-gif"
|
||||
src="{% static '/images/wait.gif' %}"
|
||||
alt="Loading..."
|
||||
/>
|
||||
</div>
|
||||
{% if objects %}
|
||||
<!-- Unreviewable objects such as User / Group / Setting -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for obj in objects %}
|
||||
{% if object_type == 'user' %}
|
||||
<li>
|
||||
<a href="{{ obj.url }}" class="hover:bg-base-300"
|
||||
>{{ obj.username }}</a
|
||||
>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ obj.url }}" class="hover:bg-base-300"
|
||||
>{{ obj.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{# prettier-ignore-start #}
|
||||
<script>
|
||||
$(function () {
|
||||
|
||||
$('#object-search').show();
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Show actions button if there are actions
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
|
||||
{% if object_type != 'package' and object_type != 'user' and object_type != 'group' %}
|
||||
{% if reviewed_objects|length > 50 or unreviewed_objects|length > 50 %}
|
||||
$('#load-all-loading').show()
|
||||
|
||||
setTimeout(function () {
|
||||
$('#load-all-error').hide();
|
||||
|
||||
$.getJSON('?all=true', function (resp) {
|
||||
$('#ReviewedContent').empty();
|
||||
$('#UnreviewedContent').empty();
|
||||
|
||||
for (o in resp.objects) {
|
||||
obj = resp.objects[o];
|
||||
if (obj.reviewed) {
|
||||
$('#ReviewedContent').append('<a class="list-group-item" href="' + obj.url + '">' + obj.name + ' <span class="glyphicon glyphicon-star" aria-hidden="true" style="float:right" data-toggle="tooltip" data-placement="top" title="" data-original-title="Reviewed"></span></a>');
|
||||
} else {
|
||||
$('#UnreviewedContent').append('<a class="list-group-item" href="' + obj.url + '">' + obj.name + '</a>');
|
||||
}
|
||||
}
|
||||
|
||||
$('#load-all-loading').hide();
|
||||
$('#load-remaining').hide();
|
||||
}).fail(function (resp) {
|
||||
$('#load-all-loading').hide();
|
||||
$('#load-all-error').show();
|
||||
});
|
||||
|
||||
}, 2500);
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
$('#modal-form-delete-submit').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#modal-form-delete').submit();
|
||||
// Show search input and connect to Alpine pagination
|
||||
const objectSearch = document.getElementById("object-search");
|
||||
if (objectSearch) {
|
||||
objectSearch.classList.remove("hidden");
|
||||
objectSearch.addEventListener("input", function () {
|
||||
const query = this.value;
|
||||
// Dispatch search to all paginatedList components
|
||||
document
|
||||
.querySelectorAll('[x-data*="paginatedList"]')
|
||||
.forEach((el) => {
|
||||
if (el._x_dataStack && el._x_dataStack[0]) {
|
||||
el._x_dataStack[0].search(query);
|
||||
}
|
||||
});
|
||||
|
||||
$('#object-search').on('keyup', function () {
|
||||
let query = $(this).val().toLowerCase();
|
||||
$('a.list-group-item').each(function () {
|
||||
let text = $(this).text().toLowerCase();
|
||||
$(this).toggle(text.indexOf(query) !== -1);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
}
|
||||
|
||||
// Delete form submit handler
|
||||
const deleteSubmit = document.getElementById("modal-form-delete-submit");
|
||||
const deleteForm = document.getElementById("modal-form-delete");
|
||||
if (deleteSubmit && deleteForm) {
|
||||
deleteSubmit.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
deleteForm.submit();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,18 +1,77 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="alert alert-error" role="alert">
|
||||
<h4 class="alert-heading">Bad Request!</h4>
|
||||
<p>Lorem</p>
|
||||
<hr />
|
||||
<p class="mb-0">
|
||||
You can find out more about permissions in our
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
role="button"
|
||||
>Wiki >></a
|
||||
>
|
||||
</p>
|
||||
<div class="flex min-h-[60vh] flex-col items-center justify-center p-8">
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="alert alert-error mb-6 shadow-lg">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-8 w-8 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
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>
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg font-bold">Bad Request</h3>
|
||||
<p class="text-sm">The request you sent was invalid or malformed.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title mb-4 text-2xl">What happened?</h2>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
The server couldn't process your request because it contains invalid
|
||||
data or parameters.
|
||||
</p>
|
||||
<div class="card-actions mt-6 justify-end">
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
<a
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
target="_blank"
|
||||
class="btn btn-outline"
|
||||
>
|
||||
Learn More
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="ml-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,18 +1,80 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="alert alert-error" role="alert">
|
||||
<h4 class="alert-heading">Access Denied!</h4>
|
||||
<p>Access to X denied.</p>
|
||||
<hr />
|
||||
<p class="mb-0">
|
||||
You can find out more about permissions in our
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
role="button"
|
||||
>Wiki >></a
|
||||
>
|
||||
</p>
|
||||
<div class="flex min-h-[60vh] flex-col items-center justify-center p-8">
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="alert alert-warning mb-6 shadow-lg">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-8 w-8 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
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>
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg font-bold">Access Denied</h3>
|
||||
<p class="text-sm">
|
||||
You don't have permission to access this resource.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title mb-4 text-2xl">Permission Required</h2>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
You need the appropriate permissions to access this content. If you
|
||||
believe this is an error, please contact the package owner or
|
||||
administrator.
|
||||
</p>
|
||||
<div class="card-actions mt-6 justify-end">
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
<a
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
target="_blank"
|
||||
class="btn btn-outline"
|
||||
>
|
||||
Learn More
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="ml-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,18 +1,77 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="alert alert-error" role="alert">
|
||||
<h4 class="alert-heading">Not Found!</h4>
|
||||
<p>Does not exist</p>
|
||||
<hr />
|
||||
<p class="mb-0">
|
||||
You can find out more about permissions in our
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
role="button"
|
||||
>Wiki >></a
|
||||
>
|
||||
</p>
|
||||
<div class="flex min-h-[60vh] flex-col items-center justify-center p-8">
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="alert alert-info mb-6 shadow-lg">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-8 w-8 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
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>
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg font-bold">Page Not Found</h3>
|
||||
<p class="text-sm">The page you're looking for doesn't exist.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title mb-4 text-2xl">404 Error</h2>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
The page or resource you requested could not be found. It may have
|
||||
been moved, deleted, or the URL might be incorrect.
|
||||
</p>
|
||||
<div class="card-actions mt-6 justify-end">
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
<a
|
||||
href="https://wiki.envipath.org/index.php/packages"
|
||||
target="_blank"
|
||||
class="btn btn-outline"
|
||||
>
|
||||
Learn More
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="ml-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,9 +1,76 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h4 class="alert-heading">{{ error_message }}</h4>
|
||||
<hr />
|
||||
<p class="mb-0">{{ error_detail }}</p>
|
||||
<div class="flex min-h-[60vh] flex-col items-center justify-center p-8">
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="alert alert-error mb-6 shadow-lg">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-8 w-8 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg font-bold">
|
||||
{{ error_message|default:"An Error Occurred" }}
|
||||
</h3>
|
||||
<p class="text-sm">
|
||||
{{ error_detail|default:"Something went wrong. Please try again later." }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title mb-4 text-2xl">Oops! Something went wrong</h2>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
{{ error_description|default:"We encountered an unexpected error while processing your request. Our team has been notified and is working to resolve the issue." }}
|
||||
</p>
|
||||
<div class="card-actions mt-6 justify-end">
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
<button onclick="window.history.back()" class="btn btn-outline">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 19l-7-7m0 0l7-7m-7 7h18"
|
||||
/>
|
||||
</svg>
|
||||
Go Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,11 +1,81 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h4 class="alert-heading">Your account has not been activated yet!</h4>
|
||||
<p>
|
||||
Your account has not been activated yet. If you have questions
|
||||
<a href="mailto:admin@envipath.org">contact us.</a>
|
||||
</p>
|
||||
<div class="flex min-h-[60vh] flex-col items-center justify-center p-8">
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="alert alert-warning mb-6 shadow-lg">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-8 w-8 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
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>
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-lg font-bold">Account Not Activated</h3>
|
||||
<p class="text-sm">Your account is pending activation.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title mb-4 text-2xl">Account Activation Required</h2>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
Your account has not been activated yet. An administrator needs to
|
||||
approve your account before you can access all features. This
|
||||
process typically takes 24-48 hours.
|
||||
</p>
|
||||
<div class="divider"></div>
|
||||
<p class="text-base-content/70 mb-4">
|
||||
If you have questions or believe this is an error, please
|
||||
<a href="mailto:admin@envipath.org" class="link link-primary"
|
||||
>contact us</a
|
||||
>.
|
||||
</p>
|
||||
<div class="card-actions mt-6 justify-end">
|
||||
<a href="/" class="btn btn-primary">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
<a href="mailto:admin@envipath.org" class="btn btn-outline">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Contact Admin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -228,15 +228,7 @@
|
||||
>Documentation Wiki</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
id="citeButton"
|
||||
data-toggle="modal"
|
||||
data-target="#citemodal"
|
||||
>How to cite enviPath</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li class="divider"></li>
|
||||
<li><a>Version: {{ meta.version }}</a></li>
|
||||
</ul>
|
||||
@ -408,10 +400,5 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% block modals %}
|
||||
{% include "modals/cite_modal.html" %}
|
||||
{% include "modals/predict_modal.html" %}
|
||||
{% include "modals/batch_predict_modal.html" %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -21,8 +21,14 @@
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
{# jQuery - Keep for compatibility with existing JS #}
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
{# Alpine.js - For reactive components #}
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"
|
||||
></script>
|
||||
<script src="{% static 'js/alpine/index.js' %}"></script>
|
||||
<script src="{% static 'js/alpine/search.js' %}"></script>
|
||||
<script src="{% static 'js/alpine/pagination.js' %}"></script>
|
||||
|
||||
{# Font Awesome #}
|
||||
<link
|
||||
@ -35,21 +41,10 @@
|
||||
|
||||
<script>
|
||||
const csrftoken = document.querySelector("[name=csrf-token]").content;
|
||||
|
||||
// Setup CSRF header for all jQuery AJAX requests
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr, settings) {
|
||||
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
|
||||
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
{# General EP JS #}
|
||||
<script src="{% static 'js/pps.js' %}"></script>
|
||||
{# Modal Steps for Stepwise Modal Wizards #}
|
||||
<script src="{% static 'js/jquery-bootstrap-modal-steps.js' %}"></script>
|
||||
|
||||
{% if not debug %}
|
||||
<!-- Matomo -->
|
||||
@ -171,10 +166,11 @@
|
||||
{% endblock %}
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
// Hide actionsbutton if there's no action defined
|
||||
if ($("#actionsButton ul").children().length > 0) {
|
||||
$("#actionsButton").show();
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Show actions button if there are actions defined
|
||||
const actionsButtonUl = document.querySelector("#actionsButton ul");
|
||||
if (actionsButtonUl && actionsButtonUl.children.length > 0) {
|
||||
document.getElementById("actionsButton").style.display = "";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,140 +1,267 @@
|
||||
{% load static %}
|
||||
{# Modern DaisyUI Navbar #}
|
||||
<div class="navbar x-50 bg-neutral-50 text-neutral-950 shadow-lg">
|
||||
<div class="navbar-start">
|
||||
<a href="{{ meta.server_url }}" class="btn btn-ghost text-xl normal-case">
|
||||
<svg class="fill-base-content h-8" viewBox="0 0 104 26" role="img">
|
||||
<use href="{% static "/images/logo-name.svg" %}#ep-logo-name" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if not public_mode %}
|
||||
<div class="navbar-center hidden lg:flex">
|
||||
<a
|
||||
href="{{ meta.server_url }}/predict"
|
||||
role="button"
|
||||
class="btn btn-ghost"
|
||||
id="predictLink"
|
||||
>Predict</a
|
||||
>
|
||||
<!-- <li><a href="{{ meta.server_url }}/package" id="packageLink">Package</a></li> -->
|
||||
<!--<li><a href="{{ meta.server_url }}/browse" id="browseLink">Browse</a></li>-->
|
||||
<div class="dropdown dropdown-center">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost">Browse</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm"
|
||||
{# Modern DaisyUI Navbar with Mobile Drawer Menu #}
|
||||
<div class="drawer drawer-mobile">
|
||||
<input id="drawer-toggle" type="checkbox" class="drawer-toggle" />
|
||||
<div class="drawer-content flex flex-col">
|
||||
{# Navbar #}
|
||||
<div class="navbar x-50 bg-neutral-50 text-neutral-950 shadow-lg">
|
||||
<div class="navbar-start">
|
||||
{# Hamburger menu button - visible on mobile, hidden on desktop #}
|
||||
{% if not public_mode %}
|
||||
<label
|
||||
for="drawer-toggle"
|
||||
class="btn btn-square btn-ghost drawer-button lg:hidden"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="inline-block h-5 w-5 stroke-current"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
></path>
|
||||
</svg>
|
||||
</label>
|
||||
{% endif %}
|
||||
<a
|
||||
href="{{ meta.server_url }}"
|
||||
class="btn btn-ghost text-xl normal-case"
|
||||
>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/package" id="packageLink">Package</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/pathway" id="pathwayLink">Pathway</a>
|
||||
</li>
|
||||
<li><a href="{{ meta.server_url }}/rule" id="ruleLink">Rule</a></li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/compound" id="compoundLink"
|
||||
>Compound</a
|
||||
<svg class="fill-base-content h-8" viewBox="0 0 104 26" role="img">
|
||||
<use href="{% static "/images/logo-name.svg" %}#ep-logo-name" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if not public_mode %}
|
||||
{# Desktop menu - hidden on mobile, visible on desktop #}
|
||||
<div class="navbar-center hidden lg:flex">
|
||||
<a
|
||||
href="{{ meta.server_url }}/predict"
|
||||
role="button"
|
||||
class="btn btn-ghost"
|
||||
id="predictLink"
|
||||
>Predict</a
|
||||
>
|
||||
<div class="dropdown dropdown-center">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost">Browse</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm"
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/reaction" id="reactionLink"
|
||||
>Reaction</a
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/package" id="packageLink"
|
||||
>Package</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/pathway" id="pathwayLink"
|
||||
>Pathway</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/rule" id="ruleLink">Rule</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/compound" id="compoundLink"
|
||||
>Compound</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/reaction" id="reactionLink"
|
||||
>Reaction</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="{{ meta.server_url }}/model"
|
||||
id="relative-reasoningLink"
|
||||
>Model</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/scenario" id="scenarioLink"
|
||||
>Scenario</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="navbar-end">
|
||||
{% if not public_mode %}
|
||||
<a id="search-trigger" role="button" class="cursor-pointer">
|
||||
<div
|
||||
class="badge badge-dash bg-base-200 text-base-content/50 m-1 flex items-center space-x-1 p-2"
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/model" id="relative-reasoningLink"
|
||||
>Model</a
|
||||
<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-search-icon lucide-search"
|
||||
>
|
||||
<path d="m21 21-4.34-4.34" />
|
||||
<circle cx="11" cy="11" r="8" />
|
||||
</svg>
|
||||
<span id="search-shortcut">⌘K</span>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if meta.user.username == 'anonymous' or public_mode %}
|
||||
<a href="{% url 'login' %}" id="loginButton" class="p-2">Login</a>
|
||||
{% else %}
|
||||
<div class="dropdown dropdown-end">
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="btn btn-ghost btn-circle m-1"
|
||||
id="loggedInButton"
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/scenario" id="scenarioLink"
|
||||
>Scenario</a
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-circle-user-icon lucide-circle-user"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
<path d="M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662" />
|
||||
</svg>
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2 shadow-sm"
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<li>
|
||||
<a href="{{ meta.user.url }}" id="accountbutton">Settings</a>
|
||||
</li>
|
||||
<li>
|
||||
<form
|
||||
id="logoutForm"
|
||||
action="{% url 'logout' %}"
|
||||
method="post"
|
||||
style="display: none;"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="logout" value="true" />
|
||||
</form>
|
||||
<a
|
||||
href="#"
|
||||
id="logoutButton"
|
||||
onclick="event.preventDefault(); document.getElementById('logoutForm').submit();"
|
||||
>Logout</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="navbar-end">
|
||||
{% if not public_mode %}
|
||||
<a id="search-trigger" role="button" class="cursor-pointer">
|
||||
<div
|
||||
class="badge badge-dash bg-base-200 text-base-content/50 m-1 flex items-center space-x-1 p-2"
|
||||
>
|
||||
<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-search-icon lucide-search"
|
||||
</div>
|
||||
{# Mobile drawer menu - slides in from the left #}
|
||||
<div class="drawer-side">
|
||||
<label for="drawer-toggle" class="drawer-overlay"></label>
|
||||
<ul class="menu min-h-full w-80 bg-base-200 p-4 text-base-content">
|
||||
{# Drawer header with close button #}
|
||||
<li class="mb-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-bold text-lg">Menu</span>
|
||||
<label
|
||||
for="drawer-toggle"
|
||||
class="btn btn-sm btn-circle btn-ghost"
|
||||
aria-label="Close menu"
|
||||
>
|
||||
<path d="m21 21-4.34-4.34" />
|
||||
<circle cx="11" cy="11" r="8" />
|
||||
</svg>
|
||||
<span id="search-shortcut">⌘K</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if meta.user.username == 'anonymous' or public_mode %}
|
||||
<a href="{% url 'login' %}" id="loginButton" class="p-2">Login</a>
|
||||
{% else %}
|
||||
<div class="dropdown dropdown-end">
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="btn btn-ghost btn-circle m-1"
|
||||
id="loggedInButton"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-circle-user-icon lucide-circle-user"
|
||||
</li>
|
||||
{% if not public_mode %}
|
||||
{# Predict link #}
|
||||
<li>
|
||||
<a
|
||||
href="{{ meta.server_url }}/predict"
|
||||
class="text-lg"
|
||||
id="predictLinkMobile"
|
||||
>Predict</a
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
<path d="M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662" />
|
||||
</svg>
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2 shadow-sm"
|
||||
>
|
||||
<li><a href="{{ meta.user.url }}" id="accountbutton">Settings</a></li>
|
||||
<li>
|
||||
<form
|
||||
id="logoutForm"
|
||||
action="{% url 'logout' %}"
|
||||
method="post"
|
||||
style="display: none;"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="logout" value="true" />
|
||||
</form>
|
||||
<a
|
||||
href="#"
|
||||
id="logoutButton"
|
||||
onclick="event.preventDefault(); document.getElementById('logoutForm').submit();"
|
||||
>Logout</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{# Browse menu with submenu #}
|
||||
<li>
|
||||
<details>
|
||||
<summary class="text-lg">Browse</summary>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/package" id="packageLinkMobile"
|
||||
>Package</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/pathway" id="pathwayLinkMobile"
|
||||
>Pathway</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/rule" id="ruleLinkMobile"
|
||||
>Rule</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/compound" id="compoundLinkMobile"
|
||||
>Compound</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/reaction" id="reactionLinkMobile"
|
||||
>Reaction</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="{{ meta.server_url }}/model"
|
||||
id="relative-reasoningLinkMobile"
|
||||
>Model</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ meta.server_url }}/scenario" id="scenarioLinkMobile"
|
||||
>Scenario</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
>
|
||||
<div class="hero-overlay"></div>
|
||||
<!-- Predict Pathway text over the image -->
|
||||
<div class="absolute bottom-40 left-1/8 z-10 -translate-x-8">
|
||||
<div class="absolute bottom-40 left-1/8 -translate-x-8">
|
||||
<h2 class="text-base-100 text-left text-3xl text-shadow-lg">
|
||||
Predict Your Pathway
|
||||
</h2>
|
||||
@ -20,16 +20,68 @@
|
||||
<div class="bg-base-200 mx-auto max-w-5xl shadow-md">
|
||||
<!-- Predict Pathway Section -->
|
||||
<div
|
||||
class="relative z-20 mx-auto -mt-32 mb-10 w-full flex-col lg:flex-row-reverse"
|
||||
class="relative mx-auto -mt-32 mb-10 w-full flex-col lg:flex-row-reverse"
|
||||
>
|
||||
<div
|
||||
class="card bg-base-100 mx-auto w-3/4 shrink-0 shadow-xl transition-all duration-300 ease-in-out"
|
||||
x-data="{
|
||||
drawMode: false,
|
||||
smiles: '',
|
||||
loadExample(smilesStr, linkEl) {
|
||||
if (this.drawMode && window.indexKetcher && window.indexKetcher.setMolecule) {
|
||||
window.indexKetcher.setMolecule(smilesStr);
|
||||
} else {
|
||||
this.smiles = smilesStr;
|
||||
}
|
||||
const original = linkEl.textContent;
|
||||
linkEl.textContent = 'loaded!';
|
||||
setTimeout(() => linkEl.textContent = original, 1000);
|
||||
},
|
||||
syncFromKetcher() {
|
||||
const ketcher = getKetcherInstance('index-ketcher');
|
||||
if (ketcher && ketcher.getSmiles) {
|
||||
try {
|
||||
const s = ketcher.getSmiles();
|
||||
if (s && s.trim()) this.smiles = s;
|
||||
} catch (err) {
|
||||
console.error('Failed to sync from Ketcher:', err);
|
||||
}
|
||||
}
|
||||
},
|
||||
submitForm() {
|
||||
let finalSmiles = '';
|
||||
if (this.drawMode) {
|
||||
const ketcher = getKetcherInstance('index-ketcher');
|
||||
if (ketcher && ketcher.getSmiles) {
|
||||
try {
|
||||
finalSmiles = ketcher.getSmiles().trim();
|
||||
} catch (err) {
|
||||
console.error('Failed to get SMILES from Ketcher:', err);
|
||||
alert('Unable to extract structure. Please try again or switch to SMILES input.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
alert('The drawing editor is still loading. Please wait and try again.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
finalSmiles = this.smiles.trim();
|
||||
}
|
||||
if (!finalSmiles) {
|
||||
alert('Please enter a SMILES string or draw a structure.');
|
||||
return;
|
||||
}
|
||||
document.getElementById('index-form-smiles').value = finalSmiles;
|
||||
document.getElementById('index-form').submit();
|
||||
}
|
||||
}"
|
||||
x-init="$watch('drawMode', value => { if (!value) syncFromKetcher(); })"
|
||||
>
|
||||
<div class="card-body">
|
||||
<div class="my-4 ml-8 flex h-fit flex-row items-center justify-start">
|
||||
<div class="flex items-center gap-1">
|
||||
<label class="swap btn btn-ghost btn-sm p-1" title="Input Mode">
|
||||
<input type="checkbox" />
|
||||
<input type="checkbox" x-model="drawMode" />
|
||||
<span class="swap-on flex items-center gap-1">
|
||||
<div
|
||||
class="bg-neutral/50 text-neutral-content flex items-center justify-center rounded-full p-1"
|
||||
@ -82,16 +134,24 @@
|
||||
|
||||
<fieldset
|
||||
class="fieldset overflow-hidden transition-all duration-300 ease-in-out"
|
||||
:class="drawMode ? 'p-4' : 'p-8'"
|
||||
>
|
||||
<form
|
||||
id="index-form"
|
||||
action="{{ meta.current_package.url }}/pathway"
|
||||
method="POST"
|
||||
@submit.prevent="submitForm()"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<div
|
||||
id="text-input-container"
|
||||
class="scale-100 transform opacity-100 transition-all duration-300 ease-in-out"
|
||||
x-show="!drawMode"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-300"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
>
|
||||
<div class="join mx-auto w-full">
|
||||
<input
|
||||
@ -99,6 +159,7 @@
|
||||
id="index-form-text-input"
|
||||
placeholder="canonical SMILES string"
|
||||
class="input input-md join-item grow"
|
||||
x-model="smiles"
|
||||
/>
|
||||
<button class="btn btn-neutral join-item">Predict!</button>
|
||||
</div>
|
||||
@ -107,15 +168,15 @@
|
||||
<a
|
||||
href="#"
|
||||
class="example-link hover:text-primary cursor-pointer"
|
||||
data-smiles="CN1C=NC2=C1C(=O)N(C(=O)N2C)C"
|
||||
title="load example"
|
||||
@click.prevent="loadExample('CN1C=NC2=C1C(=O)N(C(=O)N2C)C', $el)"
|
||||
>Caffeine</a
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="example-link hover:text-primary cursor-pointer"
|
||||
data-smiles="CC(C)CC1=CC=C(C=C1)C(C)C(=O)O"
|
||||
title="load example"
|
||||
@click.prevent="loadExample('CC(C)CC1=CC=C(C=C1)C(C)C(=O)O', $el)"
|
||||
>Ibuprofen</a
|
||||
>
|
||||
</div>
|
||||
@ -128,7 +189,14 @@
|
||||
</div>
|
||||
<div
|
||||
id="ketcher-container"
|
||||
class="hidden w-full scale-95 transform opacity-0 transition-all duration-300 ease-in-out"
|
||||
x-show="drawMode"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-300"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
class="w-full"
|
||||
>
|
||||
<iframe
|
||||
id="index-ketcher"
|
||||
@ -337,166 +405,20 @@
|
||||
// Make render function globally available
|
||||
window.renderDiscourseTopics = renderDiscourseTopics;
|
||||
|
||||
// Toggle functionality with smooth animations
|
||||
function toggleInputMode() {
|
||||
const toggle = $('input[type="checkbox"]');
|
||||
const textContainer = $("#text-input-container");
|
||||
const ketcherContainer = $("#ketcher-container");
|
||||
const formCard = $(".card");
|
||||
const fieldset = $(".fieldset");
|
||||
|
||||
if (toggle.is(":checked")) {
|
||||
// Draw mode - show Ketcher, hide text input
|
||||
textContainer.addClass("opacity-0 transform scale-95");
|
||||
textContainer.removeClass("opacity-100 transform scale-100");
|
||||
|
||||
// Adjust fieldset padding for Ketcher mode - reduce padding and make more compact
|
||||
fieldset.removeClass("p-8");
|
||||
fieldset.addClass("p-4");
|
||||
|
||||
// Wait for fade out to complete, then hide and show new content
|
||||
setTimeout(() => {
|
||||
textContainer.addClass("hidden");
|
||||
ketcherContainer.removeClass("hidden opacity-0 transform scale-95");
|
||||
ketcherContainer.addClass("opacity-100 transform scale-100");
|
||||
|
||||
// Force re-evaluation of iframe size
|
||||
const iframe = document.getElementById("index-ketcher");
|
||||
if (iframe) {
|
||||
iframe.style.height = "400px";
|
||||
}
|
||||
}, 300);
|
||||
} else {
|
||||
// SMILES mode - show text input, hide Ketcher
|
||||
ketcherContainer.addClass("opacity-0 transform scale-95");
|
||||
ketcherContainer.removeClass("opacity-100 transform scale-100");
|
||||
|
||||
// Restore fieldset padding for text input mode
|
||||
fieldset.removeClass("p-4");
|
||||
fieldset.addClass("p-8");
|
||||
|
||||
// Wait for fade out to complete, then hide and show new content
|
||||
setTimeout(() => {
|
||||
ketcherContainer.addClass("hidden");
|
||||
textContainer.removeClass("hidden opacity-0 transform scale-95");
|
||||
textContainer.addClass("opacity-100 transform scale-100");
|
||||
}, 300);
|
||||
|
||||
// Transfer SMILES from Ketcher to text input if available
|
||||
const ketcher = getKetcherInstance("index-ketcher");
|
||||
if (ketcher && ketcher.getSmiles) {
|
||||
try {
|
||||
const smiles = ketcher.getSmiles();
|
||||
if (smiles && smiles.trim() !== "") {
|
||||
$("#index-form-text-input").val(smiles);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to sync Ketcher to text input:", err);
|
||||
// Non-critical error, just log it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ketcher integration
|
||||
function indexKetcherToTextInput() {
|
||||
$("#index-form-smiles").val(this.ketcher.getSmiles());
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// Initialize fieldset with proper padding
|
||||
$(".fieldset").addClass("p-8");
|
||||
|
||||
// Toggle event listener
|
||||
$('input[type="checkbox"]').on("change", toggleInputMode);
|
||||
|
||||
// Ketcher iframe load handler
|
||||
$("#index-ketcher").on("load", function () {
|
||||
// Ketcher iframe load handler - set up change event to sync SMILES
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const indexKetcher = document.getElementById("index-ketcher");
|
||||
indexKetcher.addEventListener("load", function () {
|
||||
const checkKetcherReady = () => {
|
||||
const win = this.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
window.indexKetcher = win.ketcher;
|
||||
win.ketcher.editor.event.change.handlers.push({
|
||||
once: false,
|
||||
priority: 0,
|
||||
f: indexKetcherToTextInput,
|
||||
ketcher: win.ketcher,
|
||||
});
|
||||
} else {
|
||||
setTimeout(checkKetcherReady, 100);
|
||||
}
|
||||
};
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
// Handle example link clicks
|
||||
$(".example-link").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
const smiles = $(this).data("smiles");
|
||||
const title = $(this).attr("title");
|
||||
|
||||
// Check if we're in Ketcher mode or text input mode
|
||||
if ($('input[type="checkbox"]').is(":checked")) {
|
||||
// In Ketcher mode - set the SMILES in Ketcher
|
||||
if (window.indexKetcher && window.indexKetcher.setMolecule) {
|
||||
window.indexKetcher.setMolecule(smiles);
|
||||
}
|
||||
} else {
|
||||
// In text input mode - set the SMILES in the text input
|
||||
$("#index-form-text-input").val(smiles);
|
||||
}
|
||||
|
||||
// Show a brief feedback
|
||||
const originalText = $(this).text();
|
||||
$(this).text(`loaded!`);
|
||||
setTimeout(() => {
|
||||
$(this).text(originalText);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Handle form submission on Enter
|
||||
$("#index-form").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var textSmiles = "";
|
||||
|
||||
// Check if we're in Ketcher mode and extract SMILES
|
||||
if ($('input[type="checkbox"]').is(":checked")) {
|
||||
// Use the robust getter function
|
||||
const ketcher = getKetcherInstance("index-ketcher");
|
||||
if (ketcher && ketcher.getSmiles) {
|
||||
try {
|
||||
textSmiles = ketcher.getSmiles().trim();
|
||||
} catch (err) {
|
||||
console.error("Failed to get SMILES from Ketcher:", err);
|
||||
alert(
|
||||
"Unable to extract structure from the drawing editor. Please try again or switch to SMILES input mode.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
console.warn("Ketcher not available, possibly still loading");
|
||||
alert(
|
||||
"The drawing editor is still loading. Please wait a moment and try again.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
textSmiles = $("#index-form-text-input").val().trim();
|
||||
}
|
||||
|
||||
if (textSmiles === "") {
|
||||
alert("Please enter a SMILES string or draw a structure.");
|
||||
return;
|
||||
}
|
||||
|
||||
$("#index-form-smiles").val(textSmiles);
|
||||
$("#index-form").attr("action", currentPackage + "/pathway");
|
||||
$("#index-form").attr("method", "POST");
|
||||
this.submit();
|
||||
});
|
||||
|
||||
// Discourse topics are now loaded automatically by discourse-api.js
|
||||
});
|
||||
</script>
|
||||
{% endblock main_content %}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -10,171 +10,146 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="rule-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ rule.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/rule.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ rule.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/rule.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">{{ rule.description|safe }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if rule.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in rule.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ rule.description|safe }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if rule.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in rule.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Reaction Patterns -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-reaction-patterns-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-reaction-patterns"
|
||||
>Reaction Patterns</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-reaction-patterns" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Reaction Patterns -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reaction Patterns</div>
|
||||
<div class="collapse-content">
|
||||
<div class="space-y-4">
|
||||
{% for r in rule.srs %}
|
||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
||||
<div align="center">
|
||||
<p>{{ r.as_svg|safe }}</p>
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<a href="{{ r.url }}" class="link link-primary font-semibold"
|
||||
>{{ r.name }}</a
|
||||
>
|
||||
<div class="mt-2 flex justify-center">{{ r.as_svg|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scenarios -->
|
||||
{% if rule.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Scenarios -->
|
||||
{% if rule.scenarios.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in rule.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if rule.enzymelinks %}
|
||||
<!-- EC Numbers -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-ec-numbers-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-ec-numbers"
|
||||
>EC Numbers</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-ec-numbers" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% if rule.enzymelinks %}
|
||||
<!-- EC Numbers -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">EC Numbers</div>
|
||||
<div class="collapse-content">
|
||||
<div class="space-y-2">
|
||||
{% for k, v in rule.get_grouped_enzymelinks.items %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="{{ k|slugify }}_Link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#{{ k|slugify }}_Accordion"
|
||||
href="#{{ k|slugify }}"
|
||||
>
|
||||
{{ k }}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{ k|slugify }}" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for enzyme in v %}
|
||||
<a class="list-group-item" href="{{ enzyme.url }}">
|
||||
{{ enzyme.ec_number }}
|
||||
<div style="position:absolute;bottom:10px;left:100px;">
|
||||
{{ enzyme.name }}
|
||||
</div>
|
||||
<div style="float:right;">
|
||||
{{ enzyme.linking_method }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">{{ k }}</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for enzyme in v %}
|
||||
<li>
|
||||
<a href="{{ enzyme.url }}" class="hover:bg-base-300">
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<span>{{ enzyme.ec_number }}</span>
|
||||
<span class="text-sm opacity-70"
|
||||
>{{ enzyme.linking_method }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="text-sm opacity-60">
|
||||
{{ enzyme.name }}
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -12,360 +12,261 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="compound-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ compound.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/compound.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ compound.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/compound.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<p class="mt-2">
|
||||
The structures stored in this compound can be found at
|
||||
<a target="_blank" href="{{ compound.url }}/structure" role="button"
|
||||
<a
|
||||
target="_blank"
|
||||
href="{{ compound.url }}/structure"
|
||||
class="link link-primary"
|
||||
>Compound structures >></a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if compound.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% if compound.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in compound.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-desc-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-desc"
|
||||
>Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-desc" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ compound.description|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ compound.description }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Image -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">
|
||||
{{ compound.default_structure.as_svg|safe }}
|
||||
</div>
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">
|
||||
{{ compound.default_structure.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMILES -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-smiles-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-smiles"
|
||||
>SMILES Representation</a
|
||||
>
|
||||
</h4>
|
||||
<!-- SMILES Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMILES Representation
|
||||
</div>
|
||||
<div id="compound-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ compound.default_structure.smiles }}
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
{{ compound.default_structure.smiles }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Canonical SMILES -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-canonical-smiles-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-canonical-smiles"
|
||||
>Canonical SMILES Representation</a
|
||||
>
|
||||
</h4>
|
||||
<!-- Canonical SMILES Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Canonical SMILES Representation
|
||||
</div>
|
||||
<div id="compound-canonical-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ compound.default_structure.canonical_smiles }}
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
{{ compound.default_structure.canonical_smiles }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- InChiKey -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-inchi-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-inchi"
|
||||
>InChIKey</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-inchi" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ compound.default_structure.inchikey }}
|
||||
</div>
|
||||
<!-- InChIKey -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">InChIKey</div>
|
||||
<div class="collapse-content">
|
||||
{{ compound.default_structure.inchikey }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reactions -->
|
||||
{% if compound.related_reactions %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-reaction-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-reaction"
|
||||
>Reactions</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-reaction" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Reactions -->
|
||||
{% if compound.related_reactions %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reactions</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in compound.related_reactions %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }} <i>({{ r.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Pathways -->
|
||||
{% if compound.related_pathways %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-pathway-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-pathway"
|
||||
>Pathways</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-pathway" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Pathways -->
|
||||
{% if compound.related_pathways %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Pathways</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in compound.related_pathways %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }} <i>({{ r.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Scenarios -->
|
||||
{% if compound.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Scenarios -->
|
||||
{% if compound.scenarios.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in compound.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- External Identifiers -->
|
||||
{% if compound.get_external_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-external-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-detail"
|
||||
href="#compound-external-identifier"
|
||||
>External Identifier</a
|
||||
>
|
||||
</h4>
|
||||
<!-- External Identifiers -->
|
||||
{% if compound.get_external_identifiers %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
External Identifier
|
||||
</div>
|
||||
<div
|
||||
id="compound-external-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
<div class="panel-body list-group-item">
|
||||
<div class="collapse-content">
|
||||
<div class="space-y-2">
|
||||
{% if compound.get_pubchem_compound_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-pubchem-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-external-identifier"
|
||||
href="#compound-pubchem-identifier"
|
||||
>PubChem Compound Identifier</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="compound-pubchem-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
{% for eid in compound.get_pubchem_compound_identifiers %}
|
||||
<a class="list-group-item" href="{{ eid.external_url }}"
|
||||
>CID{{ eid.identifier_value }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">
|
||||
PubChem Compound Identifier
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for eid in compound.get_pubchem_compound_identifiers %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ eid.external_url }}"
|
||||
class="hover:bg-base-300"
|
||||
>CID{{ eid.identifier_value }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if compound.get_pubchem_substance_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-pubchem-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-external-identifier"
|
||||
href="#compound-pubchem-identifier"
|
||||
>PubChem Substance Identifier</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="compound-pubchem-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
{% for eid in compound.get_pubchem_substance_identifiers %}
|
||||
<a class="list-group-item" href="{{ eid.external_url }}"
|
||||
>SID{{ eid.identifier_value }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">
|
||||
PubChem Substance Identifier
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for eid in compound.get_pubchem_substance_identifiers %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ eid.external_url }}"
|
||||
class="hover:bg-base-300"
|
||||
>SID{{ eid.identifier_value }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if compound.get_chebi_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-chebi-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-external-identifier"
|
||||
href="#compound-chebi-identifier"
|
||||
>ChEBI Identifier</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="compound-chebi-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
{% for eid in compound.get_chebi_identifiers %}
|
||||
<a class="list-group-item" href="{{ eid.external_url }}"
|
||||
>CHEBI:{{ eid.identifier_value }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">
|
||||
ChEBI Identifier
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for eid in compound.get_chebi_identifiers %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ eid.external_url }}"
|
||||
class="hover:bg-base-300"
|
||||
>CHEBI:{{ eid.identifier_value }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -10,141 +10,109 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="compound-structure-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ compound_structure.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/compound_structure.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ compound_structure.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/compound_structure.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">{{ compound_structure.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">
|
||||
{{ compound_structure.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMILES Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMILES Representation
|
||||
</div>
|
||||
<div class="collapse-content">{{ compound_structure.smiles }}</div>
|
||||
</div>
|
||||
|
||||
{% if compound_structure.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in compound_structure.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ compound_structure.description|safe }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Image -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-structure-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-structure-detail"
|
||||
href="#compound-structure-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-structure-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">
|
||||
{{ compound_structure.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMILES -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-structure-smiles-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-structure-detail"
|
||||
href="#compound-structure-smiles"
|
||||
>SMILES Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-structure-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ compound_structure.smiles }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if compound_structure.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-structure-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-structure-detail"
|
||||
href="#compound-structure-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="compound-structure-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in compound_structure.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if compound_structure.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="compound-structure-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#compound-structure-detail"
|
||||
href="#compound-structure-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="compound-structure-scenario"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
<div class="panel-body list-group-item">
|
||||
{% if compound_structure.scenarios.all %}
|
||||
<!-- Scenarios -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in compound_structure.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Reactions -->
|
||||
|
||||
<!-- Pathways -->
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -9,214 +9,165 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="edge-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ edge.edge_label.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/edge.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ edge.edge_label.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/edge.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ edge.description }}</div>
|
||||
</div>
|
||||
|
||||
{% if edge.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in edge.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-desc-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-desc"
|
||||
>Description</a
|
||||
>
|
||||
</h4>
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">{{ edge.edge_label.as_svg|safe }}</div>
|
||||
</div>
|
||||
<div id="edge-desc" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ edge.description|safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if edge.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in edge.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Image -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">
|
||||
{{ edge.edge_label.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reaction Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-description-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-description-detail"
|
||||
href="#edge-description-smiles"
|
||||
>Reaction Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-description-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for educt in edge.start_nodes.all %}
|
||||
<a class="btn btn-default" href="{{ educt.url }}"
|
||||
>{{ educt.name|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<span
|
||||
class="glyphicon glyphicon-arrow-right"
|
||||
style="margin-left:5em;margin-right:5em;"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
{% for product in edge.end_nodes.all %}
|
||||
<a class="btn btn-default" href="{{ product.url }}"
|
||||
>{{ product.name|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMIRKS -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-smirks-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-smirks"
|
||||
>SMIRKS Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-smirks" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ edge.edge_label.smirks }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if edge.edge_label.rules.all %}
|
||||
<!-- Rules -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-rules-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-rules"
|
||||
>Rules</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-rules" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for r in edge.edge_label.rules.all %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if edge.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="edge-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#edge-detail"
|
||||
href="#edge-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="edge-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for s in edge.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Reaction Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reaction Description</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex flex-wrap items-center justify-center gap-4">
|
||||
{% for educt in edge.start_nodes.all %}
|
||||
<a href="{{ educt.url }}" class="btn btn-outline btn-sm"
|
||||
>{{ educt.name }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-arrow-right"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="m12 5 7 7-7 7" />
|
||||
</svg>
|
||||
{% for product in edge.end_nodes.all %}
|
||||
<a href="{{ product.url }}" class="btn btn-outline btn-sm"
|
||||
>{{ product.name }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMIRKS Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMIRKS Representation
|
||||
</div>
|
||||
<div class="collapse-content">{{ edge.edge_label.smirks }}</div>
|
||||
</div>
|
||||
|
||||
{% if edge.edge_label.rules.all %}
|
||||
<!-- Rules -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Rules</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in edge.edge_label.rules.all %}
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200">{{ r.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if edge.scenarios.all %}
|
||||
<!-- Scenarios -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in edge.scenarios.all %}
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,163 +1,109 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel-group" id="enzyme-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ enzymelink.ec_number }}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-2xl">{{ enzymelink.ec_number }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Name -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-name-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-name"
|
||||
>Enzyme Name</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-name" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">{{ enzymelink.name }}</div>
|
||||
</div>
|
||||
<!-- Enzyme Name -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Enzyme Name</div>
|
||||
<div class="collapse-content">{{ enzymelink.name }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Linking Method -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-linking-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-linking"
|
||||
>Linking Method</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-linking" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ enzymelink.linking_method }}. <a
|
||||
href="https://wiki.envipath.org/index.php/Rules#EnzymeLinks"
|
||||
target="#"
|
||||
>Learn more >></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if enzymelink.kegg_reaction_links %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
<!-- Linking Method -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Linking Method</div>
|
||||
<div class="collapse-content">
|
||||
{{ enzymelink.linking_method }}. <a
|
||||
href="https://wiki.envipath.org/index.php/Rules#EnzymeLinks"
|
||||
target="_blank"
|
||||
class="link link-primary"
|
||||
>Learn more >></a
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-evidence-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-evidence"
|
||||
>Linking Evidence</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-evidence" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if enzymelink.kegg_reaction_links %}
|
||||
<!-- Linking Evidence -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Linking Evidence</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for kl in enzymelink.kegg_reaction_links %}
|
||||
<a class="list-group-item" href="{{ kl.external_url }}"
|
||||
>{{ kl.identifier_value }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ kl.external_url }}" class="hover:bg-base-200"
|
||||
>{{ kl.identifier_value }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if enzymelink.reaction_evidence.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-reaction-evidence-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-reaction-evidence"
|
||||
>Linking Evidence - enviPath Reactions</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-reaction-evidence" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for r in enzymelink.reaction_evidence.all %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if enzymelink.edge_evidence.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-edge-evidence-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-edge-evidence"
|
||||
>Linking Evidence - enviPath Pathways</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-edge-evidence" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for e in enzymelink.edge_evidence.all %}
|
||||
<a class="list-group-item" href="{{ e.pathway.url }}"
|
||||
>{{ e.pathway.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- External DB Reference -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="enzyme-external-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#enzyme-detail"
|
||||
href="#enzyme-external-identifier"
|
||||
>External DB References</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="enzyme-external-identifier" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<a
|
||||
class="list-group-item"
|
||||
href="http://www.brenda-enzymes.org/enzyme.php?ecno={{ enzymelink.ec_number }}"
|
||||
target="_blank"
|
||||
>
|
||||
Brenda entry for {{ enzymelink.ec_number }}</a
|
||||
>
|
||||
{% endif %}
|
||||
|
||||
{% if enzymelink.reaction_evidence.all %}
|
||||
<!-- Linking Evidence - enviPath Reactions -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Linking Evidence - enviPath Reactions
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in enzymelink.reaction_evidence.all %}
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if enzymelink.edge_evidence.all %}
|
||||
<!-- Linking Evidence - enviPath Pathways -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Linking Evidence - enviPath Pathways
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for e in enzymelink.edge_evidence.all %}
|
||||
<li>
|
||||
<a href="{{ e.pathway.url }}" class="hover:bg-base-200"
|
||||
>{{ e.pathway.name }} <i>({{ e.pathway.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- External DB References -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
External DB References
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<a
|
||||
href="http://www.brenda-enzymes.org/enzyme.php?ecno={{ enzymelink.ec_number }}"
|
||||
target="_blank"
|
||||
class="link link-primary"
|
||||
>Brenda entry for {{ enzymelink.ec_number }}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -8,84 +8,92 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="package-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ group.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/group.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ group.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/group.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ group.description|safe }}</p>
|
||||
<p class="mt-2">{{ group.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
id="member-panel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
class="panel-heading"
|
||||
>
|
||||
Members
|
||||
<!-- Members -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title mb-4 text-xl">Members</h3>
|
||||
<p class="mb-4">List of members of this group</p>
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for um in group.user_member.all %}
|
||||
<li>
|
||||
<a href="{{ um.url }}" class="hover:bg-base-300"
|
||||
>{{ um.username }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% for gm in group.group_member.all %}
|
||||
<li>
|
||||
<a href="{{ gm.url }}" class="hover:bg-base-300">{{ gm.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>List of members of this group</p>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{% for um in group.user_member.all %}
|
||||
<a class="list-group-item" href="{{ um.url }}"
|
||||
>{{ um.username|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
{% for gm in group.group_member.all %}
|
||||
<a class="list-group-item" href="{{ gm.url }}">{{ gm.name|safe }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
id="package-panel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
class="panel-heading"
|
||||
>
|
||||
Packages
|
||||
<!-- Packages -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title mb-4 text-xl">Packages</h3>
|
||||
<p class="mb-4">Packages where this group has access to</p>
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for p in packages %}
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-300">{{ p.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>Packages where this group has access to</p>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{% for p in packages %}
|
||||
<a class="list-group-item" href="{{ p.url }}">{{ p.name|safe }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% load envipytags %}
|
||||
{% block content %}
|
||||
@ -18,509 +18,458 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<div class="panel-group" id="model-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ model.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/model.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ model.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/model.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">{{ model.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning' %}
|
||||
<!-- Rule Packages -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Rule Packages</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box w-full">
|
||||
{% for p in model.rule_packages.all %}
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-200">{{ p.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ model.description|safe }}</p>
|
||||
</div>
|
||||
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning' %}
|
||||
<!-- Rule Packages -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-package-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#rule-package"
|
||||
>Rule Packages</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-package" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for p in model.rule_packages.all %}
|
||||
<a class="list-group-item" href="{{ p.url }}"
|
||||
>{{ p.name|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Reaction Packages -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-package-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#reaction-package"
|
||||
>Data Packages</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-package" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Reaction Packages -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reaction Packages</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box w-full">
|
||||
{% for p in model.data_packages.all %}
|
||||
<a class="list-group-item" href="{{ p.url }}"
|
||||
>{{ p.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-200">{{ p.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% if model.eval_packages.all|length > 0 %}
|
||||
<!-- Eval Packages -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="eval-package-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#eval-package"
|
||||
>Evaluation Packages</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="eval-package" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
</div>
|
||||
{% if model.eval_packages.all|length > 0 %}
|
||||
<!-- Eval Packages -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Eval Packages</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box w-full">
|
||||
{% for p in model.eval_packages.all %}
|
||||
<a class="list-group-item" href="{{ p.url }}"
|
||||
>{{ p.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-200"
|
||||
>{{ p.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Model Status -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="model-status-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#model-status"
|
||||
>Model Status</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="model-status" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">{{ model.status }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if model.ready_for_prediction %}
|
||||
<!-- Predict Panel -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="predict-smiles-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#predict-smiles"
|
||||
>Predict</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="predict-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div class="input-group">
|
||||
<!-- Model Status -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Model Status</div>
|
||||
<div class="collapse-content">{{ model.status }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if model.ready_for_prediction %}
|
||||
<!-- Predict Panel -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Predict</div>
|
||||
<div class="collapse-content">
|
||||
<div class="form-control">
|
||||
<div class="join w-full">
|
||||
<input
|
||||
id="smiles-to-predict"
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered join-item grow"
|
||||
placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C"
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
class="btn btn-default"
|
||||
type="submit"
|
||||
id="predict-button"
|
||||
>
|
||||
Predict!
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="btn btn-primary join-item"
|
||||
type="button"
|
||||
id="predict-button"
|
||||
>
|
||||
Predict!
|
||||
</button>
|
||||
</div>
|
||||
<div id="predictLoading"></div>
|
||||
<div id="predictResultTable"></div>
|
||||
</div>
|
||||
<div id="predictLoading" class="mt-2"></div>
|
||||
<div id="predictResultTable" class="mt-4"></div>
|
||||
</div>
|
||||
<!-- End Predict Panel -->
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if model.ready_for_prediction and model.app_domain %}
|
||||
<!-- App Domain -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="app-domain-assessment-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#app-domain-assessment"
|
||||
>Applicability Domain Assessment</a
|
||||
>
|
||||
</h4>
|
||||
{% if model.ready_for_prediction and model.app_domain %}
|
||||
<!-- App Domain -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Applicability Domain Assessment
|
||||
</div>
|
||||
<div id="app-domain-assessment" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div class="input-group">
|
||||
<div class="collapse-content">
|
||||
<div class="form-control">
|
||||
<div class="join w-full">
|
||||
<input
|
||||
id="smiles-to-assess"
|
||||
type="text"
|
||||
class="form-control"
|
||||
class="input input-bordered join-item grow"
|
||||
placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C"
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
class="btn btn-default"
|
||||
type="submit"
|
||||
id="assess-button"
|
||||
>
|
||||
Assess!
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div id="appDomainLoading"></div>
|
||||
<div id="appDomainAssessmentResultTable"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End App Domain -->
|
||||
{% endif %}
|
||||
|
||||
{% if model.model_status == 'FINISHED' %}
|
||||
<!-- Single Gen Curve Panel -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="sg-curve-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#model-detail"
|
||||
href="#sg-curve"
|
||||
>Precision Recall Curve</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="sg-curve" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Center container contents -->
|
||||
<div
|
||||
class="container"
|
||||
style="display: flex;justify-content: center;"
|
||||
>
|
||||
<div id="sg-curve-plotdiv" class="chart">
|
||||
<div id="sg-chart"></div>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary join-item"
|
||||
type="button"
|
||||
id="assess-button"
|
||||
>
|
||||
Assess!
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="appDomainLoading" class="mt-2"></div>
|
||||
<div id="appDomainAssessmentResultTable" class="mt-4"></div>
|
||||
</div>
|
||||
{# prettier-ignore-start #}
|
||||
<script>
|
||||
$(function () {
|
||||
if (!($('#sg-chart').length > 0)) {
|
||||
return;
|
||||
}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
var x = ['Recall'];
|
||||
var y = ['Precision'];
|
||||
var thres = ['threshold'];
|
||||
|
||||
// Compare function for the given array
|
||||
function compare(a, b) {
|
||||
if (a.threshold < b.threshold)
|
||||
return -1;
|
||||
else if (a.threshold > b.threshold)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getIndexForValue(data, val, val_name) {
|
||||
for (var idx in data) {
|
||||
if (data[idx][val_name] == val) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
var data = {{ model.pr_curve|safe }}
|
||||
var dataLength = Object.keys(data).length;
|
||||
data.sort(compare);
|
||||
|
||||
for (var idx in data) {
|
||||
var d = data[idx];
|
||||
x.push(d.recall);
|
||||
y.push(d.precision);
|
||||
thres.push(d.threshold);
|
||||
}
|
||||
var chart = c3.generate({
|
||||
bindto: '#sg-chart',
|
||||
data: {
|
||||
onclick: function (d, e) {
|
||||
var idx = d.index;
|
||||
var thresh = data[dataLength - idx - 1].threshold;
|
||||
|
||||
//onclick(thresh)
|
||||
|
||||
},
|
||||
x: 'Recall',
|
||||
y: 'Precision',
|
||||
columns: [
|
||||
x,
|
||||
y,
|
||||
//thres
|
||||
]
|
||||
},
|
||||
size: {
|
||||
height: 400, // TODO: Make variable to current modal width
|
||||
width: 480
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
max: 1,
|
||||
min: 0,
|
||||
label: 'Recall',
|
||||
padding: 0,
|
||||
tick: {
|
||||
fit: true,
|
||||
values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
|
||||
}
|
||||
},
|
||||
y: {
|
||||
max: 1,
|
||||
min: 0,
|
||||
label: 'Precision',
|
||||
padding: 0,
|
||||
tick: {
|
||||
fit: true,
|
||||
values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
|
||||
}
|
||||
}
|
||||
},
|
||||
point: {
|
||||
r: 4
|
||||
},
|
||||
tooltip: {
|
||||
format: {
|
||||
title: function (recall) {
|
||||
idx = getIndexForValue(data, recall, "recall");
|
||||
if (idx != -1) {
|
||||
return "Threshold: " + data[idx].threshold;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
value: function (precision, ratio, id) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
enabled: true
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
<!-- End Single Gen Curve Panel -->
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if model.model_status == 'FINISHED' %}
|
||||
<!-- Single Gen Curve Panel -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Precision Recall Curve
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">
|
||||
<div id="sg-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function handlePredictionResponse(data) {
|
||||
res = "<table class='table table-striped'>";
|
||||
res += "<thead>";
|
||||
res += "<th scope='col'>#</th>";
|
||||
{# prettier-ignore-start #}
|
||||
{# FIXME: This is a hack to get the precision recall curve data into the JavaScript code. #}
|
||||
<script>
|
||||
function handlePredictionResponse(data) {
|
||||
let res = "<table class='table table-zebra'>"
|
||||
res += "<thead>"
|
||||
res += "<th scope='col'>#</th>"
|
||||
|
||||
columns = ["products", "image", "probability", "btrule"];
|
||||
const columns = ['products', 'image', 'probability', 'btrule']
|
||||
|
||||
for (col in columns) {
|
||||
res += "<th scope='col'>" + columns[col] + "</th>";
|
||||
}
|
||||
|
||||
res += "</thead>";
|
||||
res += "<tbody>";
|
||||
var cnt = 1;
|
||||
for (transformation in data) {
|
||||
res += "<tr>";
|
||||
res += "<th scope='row'>" + cnt + "</th>";
|
||||
res +=
|
||||
"<th scope='row'>" +
|
||||
data[transformation]["products"][0].join(", ") +
|
||||
"</th>";
|
||||
res +=
|
||||
"<th scope='row'>" +
|
||||
"<img width='400' src='{% url 'depict' %}?smiles=" +
|
||||
encodeURIComponent(data[transformation]["products"][0].join(".")) +
|
||||
"'></th>";
|
||||
res +=
|
||||
"<th scope='row'>" +
|
||||
data[transformation]["probability"].toFixed(3) +
|
||||
"</th>";
|
||||
if (data[transformation]["btrule"] != null) {
|
||||
res +=
|
||||
"<th scope='row'>" +
|
||||
"<a href='" +
|
||||
data[transformation]["btrule"]["url"] +
|
||||
"'>" +
|
||||
data[transformation]["btrule"]["name"] +
|
||||
"</a>" +
|
||||
"</th>";
|
||||
} else {
|
||||
res += "<th scope='row'>N/A</th>";
|
||||
}
|
||||
res += "</tr>";
|
||||
cnt += 1;
|
||||
}
|
||||
|
||||
res += "</tbody>";
|
||||
res += "</table>";
|
||||
$("#predictResultTable").append(res);
|
||||
}
|
||||
|
||||
function clear(divid) {
|
||||
$("#" + divid).removeClass("alert alert-danger");
|
||||
$("#" + divid).empty();
|
||||
}
|
||||
|
||||
if ($("#predict-button").length > 0) {
|
||||
$("#predict-button").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
clear("predictResultTable");
|
||||
|
||||
data = {
|
||||
smiles: $("#smiles-to-predict").val(),
|
||||
classify: "ILikeCats!",
|
||||
};
|
||||
|
||||
if (data["smiles"].trim() === "") {
|
||||
$("#predictResultTable").addClass("alert alert-danger");
|
||||
$("#predictResultTable").append(
|
||||
"Please enter a SMILES string to predict!",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
makeLoadingGif("#predictLoading", "{% static '/images/wait.gif' %}");
|
||||
$.ajax({
|
||||
type: "get",
|
||||
data: data,
|
||||
url: "",
|
||||
success: function (data, textStatus) {
|
||||
try {
|
||||
$("#predictLoading").empty();
|
||||
handlePredictionResponse(data);
|
||||
} catch (error) {
|
||||
$("#predictLoading").empty();
|
||||
$("#predictResultTable").addClass("alert alert-danger");
|
||||
$("#predictResultTable").append(
|
||||
"Error while processing response :/",
|
||||
);
|
||||
for (const col of columns) {
|
||||
res += "<th scope='col'>" + col + "</th>"
|
||||
}
|
||||
res += "</thead>"
|
||||
res += "<tbody>"
|
||||
let cnt = 1;
|
||||
for (const transformation in data) {
|
||||
res += "<tr>"
|
||||
res += "<th scope='row'>" + cnt + "</th>"
|
||||
res += "<th scope='row'>" + data[transformation]['products'][0].join(', ') + "</th>"
|
||||
res += "<th scope='row'>" + "<img width='400' src='{% url 'depict' %}?smiles=" + encodeURIComponent(data[transformation]['products'][0].join('.')) + "'></th>"
|
||||
res += "<th scope='row'>" + data[transformation]['probability'].toFixed(3) + "</th>"
|
||||
if (data[transformation]['btrule'] != null) {
|
||||
res += "<th scope='row'>" + "<a href='" + data[transformation]['btrule']['url'] + "' class='link link-primary'>" + data[transformation]['btrule']['name'] + "</a>" + "</th>"
|
||||
} else {
|
||||
res += "<th scope='row'>N/A</th>"
|
||||
}
|
||||
res += "</tr>"
|
||||
cnt += 1;
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown, x) {
|
||||
$("#predictLoading").empty();
|
||||
$("#predictResultTable").addClass("alert alert-danger");
|
||||
$("#predictResultTable").append(jqXHR.responseJSON.error);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if ($("#assess-button").length > 0) {
|
||||
$("#assess-button").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
clear("appDomainAssessmentResultTable");
|
||||
|
||||
data = {
|
||||
smiles: $("#smiles-to-assess").val(),
|
||||
"app-domain-assessment": "ILikeCats!",
|
||||
};
|
||||
|
||||
if (data["smiles"].trim() === "") {
|
||||
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
||||
$("#appDomainAssessmentResultTable").append(
|
||||
"Please enter a SMILES string to predict!",
|
||||
);
|
||||
return;
|
||||
res += "</tbody>"
|
||||
res += "</table>"
|
||||
const resultTable = document.getElementById("predictResultTable");
|
||||
if (resultTable) {
|
||||
resultTable.innerHTML = res;
|
||||
}
|
||||
}
|
||||
|
||||
makeLoadingGif("#appDomainLoading", "{% static '/images/wait.gif' %}");
|
||||
$.ajax({
|
||||
type: "get",
|
||||
data: data,
|
||||
url: "",
|
||||
success: function (data, textStatus) {
|
||||
try {
|
||||
$("#appDomainLoading").empty();
|
||||
handleAssessmentResponse("{% url 'depict' %}", data);
|
||||
console.log(data);
|
||||
} catch (error) {
|
||||
$("#appDomainLoading").empty();
|
||||
$("#appDomainAssessmentResultTable").addClass(
|
||||
"alert alert-danger",
|
||||
);
|
||||
$("#appDomainAssessmentResultTable").append(
|
||||
"Error while processing response :/",
|
||||
);
|
||||
function clear(divid) {
|
||||
const element = document.getElementById(divid);
|
||||
if (element) {
|
||||
element.classList.remove("alert", "alert-error");
|
||||
element.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
function makeLoadingGif(selector, gifPath) {
|
||||
const element = document.querySelector(selector);
|
||||
if (element) {
|
||||
element.innerHTML = '<img src="' + gifPath + '" alt="Loading...">';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Show actions button if there are actions
|
||||
const actionsButton = document.getElementById('actionsButton');
|
||||
const actionsList = actionsButton?.querySelector('ul');
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove('hidden');
|
||||
}
|
||||
|
||||
{% if model.model_status == 'FINISHED' %}
|
||||
// Precision Recall Curve
|
||||
const sgChart = document.getElementById('sg-chart');
|
||||
if (sgChart) {
|
||||
const x = ['Recall'];
|
||||
const y = ['Precision'];
|
||||
const thres = ['threshold'];
|
||||
|
||||
function compare(a, b) {
|
||||
if (a.threshold < b.threshold)
|
||||
return -1;
|
||||
else if (a.threshold > b.threshold)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getIndexForValue(data, val, val_name) {
|
||||
for (const idx in data) {
|
||||
if (data[idx][val_name] == val) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
var data = {{ model.pr_curve|safe }};
|
||||
if (!data || data.length === 0) {
|
||||
console.warn('PR curve data is empty');
|
||||
return;
|
||||
}
|
||||
const dataLength = data.length;
|
||||
data.sort(compare);
|
||||
|
||||
for (const idx in data) {
|
||||
const d = data[idx];
|
||||
x.push(d.recall);
|
||||
y.push(d.precision);
|
||||
thres.push(d.threshold);
|
||||
}
|
||||
const chart = c3.generate({
|
||||
bindto: '#sg-chart',
|
||||
data: {
|
||||
onclick: function (d, e) {
|
||||
const idx = d.index;
|
||||
const thresh = data[dataLength - idx - 1].threshold;
|
||||
},
|
||||
x: 'Recall',
|
||||
y: 'Precision',
|
||||
columns: [
|
||||
x,
|
||||
y,
|
||||
]
|
||||
},
|
||||
size: {
|
||||
height: 400,
|
||||
width: 480
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
max: 1,
|
||||
min: 0,
|
||||
label: 'Recall',
|
||||
padding: 0,
|
||||
tick: {
|
||||
fit: true,
|
||||
values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
|
||||
}
|
||||
},
|
||||
y: {
|
||||
max: 1,
|
||||
min: 0,
|
||||
label: 'Precision',
|
||||
padding: 0,
|
||||
tick: {
|
||||
fit: true,
|
||||
values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
|
||||
}
|
||||
}
|
||||
},
|
||||
point: {
|
||||
r: 4
|
||||
},
|
||||
tooltip: {
|
||||
format: {
|
||||
title: function (recall) {
|
||||
const idx = getIndexForValue(data, recall, "recall");
|
||||
if (idx != -1) {
|
||||
return "Threshold: " + data[idx].threshold;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
value: function (precision, ratio, id) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
enabled: true
|
||||
}
|
||||
});
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
// Predict button handler
|
||||
const predictButton = document.getElementById('predict-button');
|
||||
if (predictButton) {
|
||||
predictButton.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
clear("predictResultTable");
|
||||
|
||||
const smilesInput = document.getElementById('smiles-to-predict');
|
||||
const smiles = smilesInput ? smilesInput.value.trim() : '';
|
||||
|
||||
if (smiles === "") {
|
||||
const resultTable = document.getElementById("predictResultTable");
|
||||
if (resultTable) {
|
||||
resultTable.classList.add("alert", "alert-error");
|
||||
resultTable.innerHTML = "Please enter a SMILES string to predict!";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
makeLoadingGif("#predictLoading", "{% static '/images/wait.gif' %}");
|
||||
|
||||
const params = new URLSearchParams({
|
||||
smiles: smiles,
|
||||
classify: "ILikeCats!"
|
||||
});
|
||||
|
||||
fetch('?' + params.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-CSRFToken': document.querySelector('[name=csrf-token]').content
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(err => { throw err; });
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
const loadingEl = document.getElementById("predictLoading");
|
||||
if (loadingEl) loadingEl.innerHTML = "";
|
||||
handlePredictionResponse(data);
|
||||
})
|
||||
.catch(error => {
|
||||
const loadingEl = document.getElementById("predictLoading");
|
||||
if (loadingEl) loadingEl.innerHTML = "";
|
||||
const resultTable = document.getElementById("predictResultTable");
|
||||
if (resultTable) {
|
||||
resultTable.classList.add("alert", "alert-error");
|
||||
resultTable.innerHTML = error.error || "Error while processing response :/";
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Assess button handler
|
||||
const assessButton = document.getElementById('assess-button');
|
||||
if (assessButton) {
|
||||
assessButton.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
clear("appDomainAssessmentResultTable");
|
||||
|
||||
const smilesInput = document.getElementById('smiles-to-assess');
|
||||
const smiles = smilesInput ? smilesInput.value.trim() : '';
|
||||
|
||||
if (smiles === "") {
|
||||
const resultTable = document.getElementById("appDomainAssessmentResultTable");
|
||||
if (resultTable) {
|
||||
resultTable.classList.add("alert", "alert-error");
|
||||
resultTable.innerHTML = "Please enter a SMILES string to predict!";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
makeLoadingGif("#appDomainLoading", "{% static '/images/wait.gif' %}");
|
||||
|
||||
const params = new URLSearchParams({
|
||||
smiles: smiles,
|
||||
"app-domain-assessment": "ILikeCats!"
|
||||
});
|
||||
|
||||
fetch('?' + params.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-CSRFToken': document.querySelector('[name=csrf-token]').content
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(err => { throw err; });
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
const loadingEl = document.getElementById("appDomainLoading");
|
||||
if (loadingEl) loadingEl.innerHTML = "";
|
||||
if (typeof handleAssessmentResponse === 'function') {
|
||||
handleAssessmentResponse("{% url 'depict' %}", data);
|
||||
}
|
||||
console.log(data);
|
||||
})
|
||||
.catch(error => {
|
||||
const loadingEl = document.getElementById("appDomainLoading");
|
||||
if (loadingEl) loadingEl.innerHTML = "";
|
||||
const resultTable = document.getElementById("appDomainAssessmentResultTable");
|
||||
if (resultTable) {
|
||||
resultTable.classList.add("alert", "alert-error");
|
||||
resultTable.innerHTML = error.error || "Error while processing response :/";
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
$("#appDomainLoading").empty();
|
||||
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
||||
$("#appDomainAssessmentResultTable").append(
|
||||
jqXHR.responseJSON.error,
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -9,167 +9,135 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="node-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ node.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/node.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ node.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/node.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">
|
||||
The underlying structure can be found
|
||||
<a href="{{ node.default_node_label.url }}" class="link link-primary"
|
||||
>here</a
|
||||
>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ node.description }}</div>
|
||||
</div>
|
||||
|
||||
{% if node.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in node.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
The underlying structure can be found
|
||||
<a href="{{ node.default_node_label.url }}">here</a>.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="node-desc-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#node-detail"
|
||||
href="#node-desc"
|
||||
>Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="node-desc" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ node.description|safe }}
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">
|
||||
{{ node.default_node_label.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if node.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="node-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#node-detail"
|
||||
href="#node-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="node-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in node.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Image -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="node-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#node-detail"
|
||||
href="#node-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="node-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">
|
||||
{{ node.default_node_label.as_svg|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMILES -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="node-smiles-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#node-detail"
|
||||
href="#node-smiles"
|
||||
>SMILES Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="node-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ node.default_node_label.smiles }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if node.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="node-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#node-detail"
|
||||
href="#node-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="node-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for s in node.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if app_domain_assessment_data %}
|
||||
<div id="appDomainAssessmentResultTable"></div>
|
||||
{# prettier-ignore-start #}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
handleAssessmentResponse("{% url 'depict' %}", {{ app_domain_assessment_data|safe }})
|
||||
})
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- SMILES Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMILES Representation
|
||||
</div>
|
||||
<div class="collapse-content">{{ node.default_node_label.smiles }}</div>
|
||||
</div>
|
||||
|
||||
{% if node.scenarios.all %}
|
||||
<!-- Scenarios -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in node.scenarios.all %}
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if app_domain_assessment_data %}
|
||||
<div id="appDomainAssessmentResultTable"></div>
|
||||
{# prettier-ignore-start #}
|
||||
{# FIXME: This is a hack to get the app domain assessment data into the JavaScript code. #}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof handleAssessmentResponse === 'function') {
|
||||
handleAssessmentResponse("{% url 'depict' %}", {{ app_domain_assessment_data|safe }});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{# prettier-ignore-end #}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -11,69 +11,87 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="package-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ package.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/package.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ package.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/package.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">{{ package.description|safe }}</p>
|
||||
<ul class="menu bg-base-200 rounded-box mt-4 w-full">
|
||||
<li>
|
||||
<a href="{{ package.url }}/pathway" class="hover:bg-base-300"
|
||||
>Pathways ({{ package.pathways.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ package.url }}/rule" class="hover:bg-base-300"
|
||||
>Rules ({{ package.rules.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ package.url }}/compound" class="hover:bg-base-300"
|
||||
>Compounds ({{ package.compounds.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ package.url }}/reaction" class="hover:bg-base-300"
|
||||
>Reactions ({{ package.reactions.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ package.url }}/model" class="hover:bg-base-300"
|
||||
>Models ({{ package.models.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ package.url }}/scenario" class="hover:bg-base-300"
|
||||
>Scenarios ({{ package.scenarios.count }})</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ package.description|safe }}</p>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/pathway"
|
||||
>Pathways ({{ package.pathways.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/rule">Rules ({{ package.rules.count }})</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/compound"
|
||||
>Compounds ({{ package.compounds.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/reaction"
|
||||
>Reactions ({{ package.reactions.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/model"
|
||||
>Models ({{ package.models.count }})</a
|
||||
>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a href="{{ package.url }}/scenario"
|
||||
>Scenarios ({{ package.scenarios.count }})</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
@ -7,6 +7,7 @@
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#pwsvg {
|
||||
@ -18,6 +19,7 @@
|
||||
.link {
|
||||
stroke: #999;
|
||||
stroke-opacity: 0.6;
|
||||
/* marker-end: url(#arrow); */
|
||||
}
|
||||
|
||||
.link_no_arrow {
|
||||
@ -63,15 +65,6 @@
|
||||
stroke: red;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
background: lightgrey;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
visibility: hidden;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
<script src="{% static 'js/pw.js' %}"></script>
|
||||
|
||||
@ -90,141 +83,217 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<p></p>
|
||||
<div id="pwcontent">
|
||||
<div class="panel-group" id="pwAccordion">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ pathway.name|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="vizLink"
|
||||
data-toggle="collapse"
|
||||
data-parent="#pwAccordion"
|
||||
href="#viz"
|
||||
>
|
||||
Graphical Representation
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="viz" class="panel-collapse in collapse">
|
||||
<nav role="navigation" class="navbar navbar-default" style="margin: 0;">
|
||||
<div class="navbar-header"></div>
|
||||
<div id="editbarCollapse" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown requiresWritePerm">
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="glyphicon glyphicon-edit"></span>
|
||||
Edit
|
||||
<span class="caret"></span
|
||||
></a>
|
||||
<ul id="editingList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/pathway.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</li>
|
||||
{% if pathway.setting.model.app_domain %}
|
||||
<li class="dropdown">
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="glyphicon glyphicon-eye-open"></span>
|
||||
View
|
||||
<span class="caret"></span
|
||||
></a>
|
||||
<ul id="editingList" class="dropdown-menu">
|
||||
<li>
|
||||
<a class="button" id="app-domain-toggle-button">
|
||||
<i
|
||||
id="app-domain-toggle-button"
|
||||
class="glyphicon glyphicon-eye-open"
|
||||
></i>
|
||||
App Domain View</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a
|
||||
role="button"
|
||||
data-toggle="modal"
|
||||
onclick="goFullscreen('vizdiv')"
|
||||
>
|
||||
<span class="glyphicon glyphicon-fullscreen"></span>
|
||||
Fullscreen
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{% if pathway.completed %}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default navbar-btn"
|
||||
data-toggle="popover"
|
||||
id="status"
|
||||
data-original-title=""
|
||||
title=""
|
||||
data-content="Pathway prediction complete."
|
||||
>
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
{% elif pathway.failed %}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default navbar-btn"
|
||||
data-toggle="popover"
|
||||
id="status"
|
||||
data-original-title=""
|
||||
title=""
|
||||
data-content="Pathway prediction failed."
|
||||
>
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
</button>
|
||||
{% else %}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default navbar-btn"
|
||||
data-toggle="popover"
|
||||
id="status"
|
||||
data-original-title=""
|
||||
title=""
|
||||
data-content="Pathway prediction running."
|
||||
>
|
||||
<img height="20" src="{% static '/images/wait.gif' %}" />
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
</li>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ pathway.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/pathway.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Graphical Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Graphical Representation
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<div class="bg-base-100 mb-2 rounded-lg p-2">
|
||||
<div class="navbar bg-base-100 rounded-lg">
|
||||
<div class="flex-1">
|
||||
{% if meta.can_edit %}
|
||||
<div class="dropdown">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-edit"
|
||||
>
|
||||
<path
|
||||
d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
|
||||
/>
|
||||
<path
|
||||
d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
|
||||
/>
|
||||
</svg>
|
||||
Edit
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% include "actions/objects/pathway.html" %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if pathway.setting.model.app_domain %}
|
||||
<div class="dropdown">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-eye"
|
||||
>
|
||||
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
</svg>
|
||||
View
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
<li>
|
||||
<a id="app-domain-toggle-button" class="cursor-pointer">
|
||||
<svg
|
||||
id="app-domain-icon"
|
||||
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-eye"
|
||||
>
|
||||
<path
|
||||
d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"
|
||||
/>
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
</svg>
|
||||
App Domain View
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="flex-none gap-2">
|
||||
<button
|
||||
class="btn btn-ghost btn-sm"
|
||||
onclick="goFullscreen('vizdiv')"
|
||||
>
|
||||
<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-maximize"
|
||||
>
|
||||
<path
|
||||
d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"
|
||||
/>
|
||||
</svg>
|
||||
Fullscreen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="vizdiv">
|
||||
{% if pathway.completed %}
|
||||
<div class="tooltip tooltip-bottom absolute top-4 right-4 z-10">
|
||||
<div class="tooltip-content">Pathway prediction complete.</div>
|
||||
<div id="status" class="flex items-center">
|
||||
<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-check"
|
||||
>
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
{% elif pathway.failed %}
|
||||
<div class="tooltip tooltip-bottom absolute top-4 right-4 z-10">
|
||||
<div class="tooltip-content">Pathway prediction failed.</div>
|
||||
<div id="status" class="flex items-center">
|
||||
<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-x"
|
||||
>
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="M6 6l12 12" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="tooltip tooltip-bottom absolute top-4 right-4 z-10">
|
||||
<div class="tooltip-content">Pathway prediction running.</div>
|
||||
<div id="status" class="flex items-center">
|
||||
<div
|
||||
id="status-loading-spinner"
|
||||
style="width: 20px; height: 20px;"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<svg id="pwsvg">
|
||||
<defs>
|
||||
<marker
|
||||
@ -266,184 +335,137 @@
|
||||
</defs>
|
||||
<g id="zoomable"></g>
|
||||
</svg>
|
||||
<div id="tooltip" class="tooltip"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="DescriptionLink"
|
||||
data-toggle="collapse"
|
||||
data-parent="#pathwayAccordion"
|
||||
href="#Description"
|
||||
>Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="Description" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item" id="DescriptionContent">
|
||||
{{ pathway.description | safe }}
|
||||
<div id="tooltip" class="tooltip-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if pathway.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="pathway-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#pathway-detail"
|
||||
href="#pathway-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="pathway-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">
|
||||
<div id="DescriptionContent">{{ pathway.description | safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if pathway.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in pathway.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if pathway.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="pathway-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#pathway-detail"
|
||||
href="#pathway-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="pathway-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% if pathway.scenarios.all %}
|
||||
<!-- Scenarios -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in pathway.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200">
|
||||
{{ s.name }}
|
||||
<span class="text-sm opacity-70">({{ s.package.name }})</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if pathway.setting %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="pathwaySettingLink"
|
||||
data-toggle="collapse"
|
||||
data-parent="#pathwayAccordion"
|
||||
href="#pathwaySetting"
|
||||
>Setting</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="pathwaySetting" class="panel-collapse collapse">
|
||||
<div class="panel-body list-group-item" id="pathwaySettingContent">
|
||||
<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>
|
||||
</tr>
|
||||
{% if pathway.setting %}
|
||||
<!-- Setting -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Setting</div>
|
||||
<div class="collapse-content">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table-zebra table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if pathway.setting.model %}
|
||||
<tr>
|
||||
<td width="20%">Model</td>
|
||||
<td width="80%">
|
||||
<table
|
||||
width="100%"
|
||||
class="table-bordered table-hover table"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<li class="list-group-item">
|
||||
<a href="{{ pathway.setting.model.url }}">
|
||||
{{ pathway.setting.model.name|safe }}
|
||||
</a>
|
||||
</li>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="20%">Model Parameter</th>
|
||||
<th width="80%">Parameter Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%">Threshold</td>
|
||||
<td width="80%">
|
||||
{{ pathway.setting.model_threshold }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<td>Model</td>
|
||||
<td>
|
||||
<div class="space-y-2">
|
||||
<div>
|
||||
<a
|
||||
href="{{ pathway.setting.model.url }}"
|
||||
class="link link-primary"
|
||||
>
|
||||
{{ pathway.setting.model.name }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table-xs table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Model Parameter</th>
|
||||
<th>Parameter Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Threshold</td>
|
||||
<td>{{ pathway.setting.model_threshold }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if pathway.setting.rule_packages.all %}
|
||||
<tr>
|
||||
<td width="20%">Rule Packages</td>
|
||||
<td width="80%">
|
||||
<table
|
||||
width="100%"
|
||||
class="table-bordered table-hover table"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% for p in pathway.setting.rule_packages.all %}
|
||||
<li class="list-group-item">
|
||||
<a href="{{ p.url }}"> {{ p.name|safe }} </a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<td>Rule Packages</td>
|
||||
<td>
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for p in pathway.setting.rule_packages.all %}
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-200"
|
||||
>{{ p.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Nodes</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ pathway.setting.max_nodes }}</p>
|
||||
</td>
|
||||
<td>Max Nodes</td>
|
||||
<td>{{ pathway.setting.max_nodes }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Depth</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ pathway.setting.max_depth }}</p>
|
||||
</td>
|
||||
<td>Max Depth</td>
|
||||
<td>{{ pathway.setting.max_depth }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{# prettier-ignore-start #}
|
||||
{# FIXME: This is a hack to get the pathway data into the JavaScript code. #}
|
||||
|
||||
<script>
|
||||
// Global switch for app domain view
|
||||
var appDomainViewEnabled = false;
|
||||
@ -461,15 +483,17 @@
|
||||
return text.replace(/\[\s*(http[^\]|]+)\s*\|\s*([^\]]+)\s*\]/g, '<a target="parent" href="$1">$2</a>');
|
||||
}
|
||||
|
||||
pathway = {{ pathway.d3_json | safe }};
|
||||
|
||||
$(function () {
|
||||
var pathway = {{ pathway.d3_json | safe }};
|
||||
|
||||
$('#status').popover({
|
||||
trigger: 'manual',
|
||||
placement: 'bottom',
|
||||
html: true
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize loading spinner if pathway is running
|
||||
if (pathway.status === 'running') {
|
||||
const spinnerContainer = document.getElementById('status-loading-spinner');
|
||||
if (spinnerContainer) {
|
||||
showLoadingSpinner(spinnerContainer);
|
||||
}
|
||||
}
|
||||
|
||||
// If prediction is still running, regularly check status
|
||||
if (pathway.status === 'running') {
|
||||
@ -481,29 +505,32 @@
|
||||
const data = await response.json();
|
||||
|
||||
if (data.modified > last_modified) {
|
||||
var msg = 'Prediction '
|
||||
var btn = '<button type="button" onclick="location.reload()" class="btn btn-primary" id="reloadBtn">Reload page</button>'
|
||||
var msg = 'Prediction ';
|
||||
var btn = '<button type="button" onclick="location.reload()" class="btn btn-primary btn-sm mt-2" id="reloadBtn">Reload page</button>';
|
||||
|
||||
if (data.status === "running") {
|
||||
msg += 'is still running. But the Pathway was updated.<br>' + btn;
|
||||
|
||||
} else if (data.status === "completed") {
|
||||
msg += 'is completed. Reload the page to see the updated Pathway.<br>' + btn;
|
||||
} else if (data.status === "failed") {
|
||||
msg += 'failed. Reload the page to see the current shape<br>' + btn;
|
||||
msg += 'failed. Reload the page to see the current shape.<br>' + btn;
|
||||
}
|
||||
|
||||
$('#status').attr(
|
||||
'data-content', msg
|
||||
).popover('show');
|
||||
showStatusPopover(msg);
|
||||
}
|
||||
|
||||
if (data.status === "completed" || data.status === "failed") {
|
||||
$('#status img').remove();
|
||||
const statusBtn = document.getElementById('status');
|
||||
const tooltipContent = statusBtn.parentElement.querySelector('.tooltip-content');
|
||||
const spinner = statusBtn.querySelector('#status-loading-spinner');
|
||||
if (spinner) spinner.remove();
|
||||
|
||||
if (data.status === "completed") {
|
||||
$('#status').append('<span class="glyphicon glyphicon-ok"></span>')
|
||||
statusBtn.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-check"><path d="M20 6 9 17l-5-5"/></svg>`;
|
||||
tooltipContent.textContent = 'Pathway prediction complete.';
|
||||
} else {
|
||||
$('#status').append('<span class="glyphicon glyphicon-remove"></span>')
|
||||
statusBtn.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-x"><path d="M18 6 6 18"/><path d="M6 6l12 12"/></svg>`;
|
||||
tooltipContent.textContent = 'Pathway prediction failed.';
|
||||
}
|
||||
clearInterval(pollInterval);
|
||||
}
|
||||
@ -515,54 +542,68 @@
|
||||
}
|
||||
|
||||
draw(pathway, 'vizdiv');
|
||||
// TODO fix somewhere else...
|
||||
var newDesc = transformReferences($('#DescriptionContent')[0].innerText);
|
||||
$('#DescriptionContent').html(newDesc);
|
||||
|
||||
// Transform references in description
|
||||
const descContent = document.getElementById('DescriptionContent');
|
||||
if (descContent) {
|
||||
const newDesc = transformReferences(descContent.innerText);
|
||||
descContent.innerHTML = newDesc;
|
||||
}
|
||||
|
||||
$('#app-domain-toggle-button').on('click', function () {
|
||||
// glyphicon glyphicon-eye-close
|
||||
// glyphicon glyphicon-eye-open
|
||||
appDomainViewEnabled = !appDomainViewEnabled;
|
||||
// App domain toggle
|
||||
const appDomainBtn = document.getElementById('app-domain-toggle-button');
|
||||
if (appDomainBtn) {
|
||||
appDomainBtn.addEventListener('click', function() {
|
||||
appDomainViewEnabled = !appDomainViewEnabled;
|
||||
const icon = document.getElementById('app-domain-icon');
|
||||
|
||||
if (appDomainViewEnabled) {
|
||||
$('#app-domain-toggle-button > i').removeClass('glyphicon-eye-open');
|
||||
$('#app-domain-toggle-button > i').addClass('glyphicon-eye-close');
|
||||
nodes.forEach((x) => {
|
||||
if(x.app_domain) {
|
||||
if (x.app_domain.inside_app_domain) {
|
||||
d3.select(x.el).select("circle").classed("inside_app_domain", true);
|
||||
} else {
|
||||
d3.select(x.el).select("circle").classed("outside_app_domain", true);
|
||||
if (appDomainViewEnabled) {
|
||||
// Change to eye-off icon
|
||||
icon.innerHTML = '<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>';
|
||||
|
||||
nodes.forEach((x) => {
|
||||
if(x.app_domain) {
|
||||
if (x.app_domain.inside_app_domain) {
|
||||
d3.select(x.el).select("circle").classed("inside_app_domain", true);
|
||||
} else {
|
||||
d3.select(x.el).select("circle").classed("outside_app_domain", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
links.forEach((x) => {
|
||||
if(x.app_domain) {
|
||||
if (x.app_domain.passes_app_domain) {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_passes_app_domain)");
|
||||
d3.select(x.el).classed("passes_app_domain", true);
|
||||
} else {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_fails_app_domain)");
|
||||
d3.select(x.el).classed("fails_app_domain", true);
|
||||
});
|
||||
links.forEach((x) => {
|
||||
if(x.app_domain) {
|
||||
if (x.app_domain.passes_app_domain) {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_passes_app_domain)");
|
||||
d3.select(x.el).classed("passes_app_domain", true);
|
||||
} else {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_fails_app_domain)");
|
||||
d3.select(x.el).classed("fails_app_domain", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$('#app-domain-toggle-button > i').removeClass('glyphicon-eye-close');
|
||||
$('#app-domain-toggle-button > i').addClass('glyphicon-eye-open');
|
||||
nodes.forEach((x) => {
|
||||
d3.select(x.el).select("circle").classed("inside_app_domain", false);
|
||||
d3.select(x.el).select("circle").classed("outside_app_domain", false);
|
||||
});
|
||||
links.forEach((x) => {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow)");
|
||||
d3.select(x.el).classed("passes_app_domain", false);
|
||||
d3.select(x.el).classed("fails_app_domain", false);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// Change back to eye icon
|
||||
icon.innerHTML = '<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>';
|
||||
|
||||
nodes.forEach((x) => {
|
||||
d3.select(x.el).select("circle").classed("inside_app_domain", false);
|
||||
d3.select(x.el).select("circle").classed("outside_app_domain", false);
|
||||
});
|
||||
links.forEach((x) => {
|
||||
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow)");
|
||||
d3.select(x.el).classed("passes_app_domain", false);
|
||||
d3.select(x.el).classed("fails_app_domain", false);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Show actions button if there are actions
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -11,343 +11,257 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="reaction-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ reaction.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/reaction.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ reaction.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/reaction.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Description</div>
|
||||
<div class="collapse-content">{{ reaction.description }}</div>
|
||||
</div>
|
||||
|
||||
{% if reaction.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in reaction.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-desc-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-desc"
|
||||
>Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-desc" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{{ reaction.description|safe }}
|
||||
</div>
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">{{ reaction.as_svg|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if reaction.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in reaction.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Image -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">{{ reaction.as_svg|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reaction Description -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-description-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-description-detail"
|
||||
href="#reaction-description-smiles"
|
||||
>Reaction Description</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-description-smiles" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Reaction Description -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reaction Description</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex flex-wrap items-center justify-center gap-4">
|
||||
{% for educt in reaction.educts.all %}
|
||||
<a class="btn btn-default" href="{{ educt.url }}"
|
||||
>{{ educt.name|safe }}</a
|
||||
<a href="{{ educt.url }}" class="btn btn-outline btn-sm"
|
||||
>{{ educt.name }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<span
|
||||
class="glyphicon glyphicon-arrow-right"
|
||||
style="margin-left:5em;margin-right:5em;"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
{% for product in reaction.products.all %}
|
||||
<a class="btn btn-default" href="{{ product.url }}"
|
||||
>{{ product.name|safe }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMIRKS -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-smirks-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-smirks"
|
||||
>SMIRKS Representation</a
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-arrow-right"
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-smirks" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">{{ reaction.smirks }}</div>
|
||||
</div>
|
||||
|
||||
{% if reaction.rules.all %}
|
||||
<!-- Rules -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-rules-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-rules"
|
||||
>Rules</a
|
||||
<path d="M5 12h14" />
|
||||
<path d="m12 5 7 7-7 7" />
|
||||
</svg>
|
||||
{% for product in reaction.products.all %}
|
||||
<a href="{{ product.url }}" class="btn btn-outline btn-sm"
|
||||
>{{ product.name }}</a
|
||||
>
|
||||
</h4>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div id="reaction-rules" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMIRKS Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMIRKS Representation
|
||||
</div>
|
||||
<div class="collapse-content">{{ reaction.smirks }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Rules -->
|
||||
{% if reaction.rules.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Rules</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in reaction.rules.all %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200">{{ r.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if reaction.get_related_enzymes %}
|
||||
<!-- EC Numbers -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-ec-numbers-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-ec-numbers"
|
||||
>EC Numbers</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-ec-numbers" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- EC Numbers -->
|
||||
{% if reaction.get_related_enzymes %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">EC Numbers</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for e in reaction.get_related_enzymes %}
|
||||
<a
|
||||
class="list-group-item"
|
||||
href="http://www.brenda-enzymes.org/enzyme.php?ecno={{ e.ec_number }}"
|
||||
>{{ e.name }}</a
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
href="http://www.brenda-enzymes.org/enzyme.php?ecno={{ e.ec_number }}"
|
||||
class="hover:bg-base-200"
|
||||
>{{ e.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if reaction.related_pathways %}
|
||||
<!-- Pathways -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-pathway-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-pathway"
|
||||
>Pathways</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-pathway" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Pathways -->
|
||||
{% if reaction.related_pathways %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Pathways</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in reaction.related_pathways %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if reaction.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="reaction-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Scenarios -->
|
||||
{% if reaction.scenarios.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in reaction.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200"
|
||||
>{{ s.name }} <i>({{ s.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- External Identifiers -->
|
||||
{% if reaction.get_external_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-external-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-detail"
|
||||
href="#reaction-external-identifier"
|
||||
>External Identifier</a
|
||||
>
|
||||
</h4>
|
||||
<!-- External Identifiers -->
|
||||
{% if reaction.get_external_identifiers %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
External Identifier
|
||||
</div>
|
||||
<div
|
||||
id="reaction-external-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
<div class="panel-body list-group-item">
|
||||
<div class="collapse-content">
|
||||
<div class="space-y-2">
|
||||
{% if reaction.get_rhea_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-rhea-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-external-identifier"
|
||||
href="#reaction-rhea-identifier"
|
||||
>Rhea</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="reaction-rhea-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
{% for eid in reaction.get_rhea_identifiers %}
|
||||
<a class="list-group-item" href="{{ eid.external_url }}"
|
||||
>{{ eid.identifier_value }}</a
|
||||
>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">Rhea</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for eid in reaction.get_rhea_identifiers %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ eid.external_url }}"
|
||||
class="hover:bg-base-300"
|
||||
>{{ eid.identifier_value }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if reaction.get_uniprot_identifiers %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="reaction-uniprot-identifier-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#reaction-external-identifier"
|
||||
href="#reaction-uniprot-identifier"
|
||||
>UniProt</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="reaction-uniprot-identifier"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
{% for eid in reaction.get_uniprot_identifiers %}
|
||||
<a class="list-group-item" href="{{ eid.external_url }}"
|
||||
>10 SwissProt entries ({{ eid.identifier_value }})</a
|
||||
>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">UniProt</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for eid in reaction.get_uniprot_identifiers %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ eid.external_url }}"
|
||||
class="hover:bg-base-300"
|
||||
>10 SwissProt entries ({{ eid.identifier_value }})</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -7,115 +7,169 @@
|
||||
{% include "modals/objects/update_scenario_additional_information_modal.html" %}
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
<div class="panel-group" id="scenario-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ scenario.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/scenario.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ scenario.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/scenario.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title mb-2 text-lg">Description</h3>
|
||||
<p>{{ scenario.description }}</p>
|
||||
<p class="mt-2"><strong>Type:</strong> {{ scenario.scenario_type }}</p>
|
||||
<p><strong>Reported:</strong> {{ scenario.scenario_date }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Additional Information Table -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title mb-4 text-lg">Additional Information</h3>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table-zebra table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Property</th>
|
||||
<th>Value</th>
|
||||
<th>Unit</th>
|
||||
{% if meta.can_edit %}
|
||||
<th>Remove</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ai in scenario.get_additional_information %}
|
||||
<tr>
|
||||
<td>{{ ai.property_name|safe }}</td>
|
||||
<td>{{ ai.property_data|safe }}</td>
|
||||
<td>{{ ai.property_unit|safe }}</td>
|
||||
{% if meta.can_edit %}
|
||||
<td>
|
||||
<form
|
||||
action="{% url 'package scenario detail' scenario.package.uuid scenario.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input
|
||||
type="hidden"
|
||||
name="uuid"
|
||||
value="{{ ai.uuid }}"
|
||||
/>
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="delete-additional-information"
|
||||
/>
|
||||
<button type="submit" class="btn btn-sm btn-ghost">
|
||||
<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-minus"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if meta.can_edit %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Delete all</td>
|
||||
<td>
|
||||
<form
|
||||
action="{% url 'package scenario detail' scenario.package.uuid scenario.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="delete-all-additional-information"
|
||||
/>
|
||||
<button type="submit" class="btn btn-sm btn-ghost">
|
||||
<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-trash"
|
||||
>
|
||||
<path d="M3 6h18" />
|
||||
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
||||
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Description</div>
|
||||
<div class="panel-body">
|
||||
{{ scenario.description|safe }}
|
||||
<br />
|
||||
{{ scenario.scenario_type }}
|
||||
<br />
|
||||
Reported {{ scenario.scenario_date }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
id="scenario-table"
|
||||
class="table-bordered table-striped table-hover table"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Property</th>
|
||||
<th>Value</th>
|
||||
<th>Unit</th>
|
||||
{% if meta.can_edit %}
|
||||
<th>Remove</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
{% for ai in scenario.get_additional_information %}
|
||||
<tr>
|
||||
<td>{{ ai.property_name|safe }}</td>
|
||||
<td>{{ ai.property_data|safe }}</td>
|
||||
<td>{{ ai.property_unit|safe }}</td>
|
||||
{% if meta.can_edit %}
|
||||
<td>
|
||||
<form
|
||||
action="{% url 'package scenario detail' scenario.package.uuid scenario.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="uuid" value="{{ ai.uuid }}" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="delete-additional-information"
|
||||
/>
|
||||
<button type="submit" class="btn">
|
||||
<span class="glyphicon glyphicon-minus"></span>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if meta.can_edit %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Delete all</td>
|
||||
<td>
|
||||
<form
|
||||
action="{% url 'package scenario detail' scenario.package.uuid scenario.uuid %}"
|
||||
method="post"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input
|
||||
type="hidden"
|
||||
name="hidden"
|
||||
value="delete-all-additional-information"
|
||||
/>
|
||||
<button type="submit" class="btn">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -10,359 +10,243 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="rule-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ rule.name|safe }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/rule.html" %}
|
||||
{% endblock %}
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ rule.name }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/rule.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2">{{ rule.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if rule.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Aliases</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for alias in rule.aliases %}
|
||||
<li><a class="hover:bg-base-200">{{ alias }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{ rule.description|safe }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if rule.aliases %}
|
||||
<!-- Aliases -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-aliases-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-aliases"
|
||||
>Aliases</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-aliases" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for alias in rule.aliases %}
|
||||
<a class="list-group-item">{{ alias }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Image Representation -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Image Representation</div>
|
||||
<div class="collapse-content">
|
||||
<div class="flex justify-center">{{ rule.as_svg|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Representation -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-image-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-image"
|
||||
>Image Representation</a
|
||||
>
|
||||
</h4>
|
||||
<!-- SMIRKS -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
SMIRKS Representation
|
||||
</div>
|
||||
<div id="rule-image" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div id="image-div" align="center">{{ rule.as_svg|safe }}</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<p>{{ rule.smirks }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMIRKS -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-smirks-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-smirks"
|
||||
>SMIRKS Representation</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-smirks" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<p>{{ rule.smirks }}</p>
|
||||
</div>
|
||||
<!-- Reactants SMARTS -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Reactant SMARTS</div>
|
||||
<div class="collapse-content">
|
||||
<p>{{ rule.reactants_smarts }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reactants SMARTS -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-reactants-smarts-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-reactants-smarts"
|
||||
>Reactant SMARTS</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-reactants-smarts" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<p>{{ rule.reactants_smarts }}</p>
|
||||
<!-- Reactant Filter SMARTS -->
|
||||
{% if rule.reactant_filter_smarts %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Reactant Filter SMARTS
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<p>{{ rule.reactant_filter_smarts }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Reactant Filter SMARTS -->
|
||||
{% if rule.reactant_filter_smarts %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-reactant-filter-smarts-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-reactant-filter-smarts"
|
||||
>Reactant Filter SMARTS</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
id="rule-reactant-filter-smarts"
|
||||
class="panel-collapse in collapse"
|
||||
>
|
||||
<div class="panel-body list-group-item">
|
||||
<p>{{ rule.reactant_filter_smarts }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Products SMARTS -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-products-smarts-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-products-smarts"
|
||||
>Reactant SMARTS</a
|
||||
>
|
||||
</h4>
|
||||
<!-- Products SMARTS -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Products SMARTS</div>
|
||||
<div class="collapse-content">
|
||||
<p>{{ rule.products_smarts }}</p>
|
||||
</div>
|
||||
<div id="rule-products-smarts" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<p>{{ rule.products_smarts }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Product Filter SMARTS -->
|
||||
{% if rule.product_filter_smarts %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Product Filter SMARTS
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<p>{{ rule.product_filter_smarts }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Product Filter SMARTS -->
|
||||
{% if rule.product_filter_smarts %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-product-filter-smarts-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-product-filter-smarts"
|
||||
>Product Filter SMARTS</a
|
||||
>
|
||||
</h4>
|
||||
<!-- Included in Composite Rules -->
|
||||
{% if rule.parallelrule_set.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Included in Composite Rules
|
||||
</div>
|
||||
<div id="rule-product-filter-smarts" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<p>{{ rule.product_filter_smarts }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Included in Composite Rules -->
|
||||
{% if rule.parallelrule_set.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-composite-rule-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-composite-rule"
|
||||
>Included in Composite Rules</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-composite-rule" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for cr in rule.parallelrule_set.all %}
|
||||
<a class="list-group-item" href="{{ cr.url }}"
|
||||
>{{ cr.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ cr.url }}" class="hover:bg-base-200"
|
||||
>{{ cr.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Scenarios -->
|
||||
{% if rule.scenarios.all %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-scenario-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-scenario"
|
||||
>Scenarios</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-scenario" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Scenarios -->
|
||||
{% if rule.scenarios.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for s in rule.scenarios.all %}
|
||||
<a class="list-group-item" href="{{ s.url }}"
|
||||
>{{ s.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ s.url }}" class="hover:bg-base-200">{{ s.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Reactions -->
|
||||
{% if rule.related_reactions %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-reaction-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-reaction"
|
||||
>Reactions</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-reaction" class="panel-collapse collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Reactions -->
|
||||
{% if rule.related_reactions %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Reactions</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in rule.related_reactions %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200">{{ r.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Pathways -->
|
||||
{% if rule.related_pathways %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-pathway-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-pathway"
|
||||
>Pathways</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-pathway" class="panel-collapse collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<!-- Pathways -->
|
||||
{% if rule.related_pathways %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Pathways</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in rule.related_pathways %}
|
||||
<a class="list-group-item" href="{{ r.url }}"
|
||||
>{{ r.name|safe }}</a
|
||||
>
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200">{{ r.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if rule.enzymelinks %}
|
||||
<!-- EC Numbers -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="rule-ec-numbers-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#rule-detail"
|
||||
href="#rule-ec-numbers"
|
||||
>EC Numbers</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="rule-ec-numbers" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% if rule.enzymelinks %}
|
||||
<!-- EC Numbers -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">EC Numbers</div>
|
||||
<div class="collapse-content">
|
||||
<div class="space-y-2">
|
||||
{% for k, v in rule.get_grouped_enzymelinks.items %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="{{ k|slugify }}_Link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#{{ k|slugify }}_Accordion"
|
||||
href="#{{ k|slugify }}"
|
||||
>
|
||||
{{ k }}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{ k|slugify }}" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for enzyme in v %}
|
||||
<a class="list-group-item" href="{{ enzyme.url }}">
|
||||
{{ enzyme.ec_number }}
|
||||
<div style="position:absolute;bottom:10px;left:100px;">
|
||||
{{ enzyme.name }}
|
||||
</div>
|
||||
<div style="float:right;">
|
||||
{{ enzyme.linking_method }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-lg font-medium">{{ k }}</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for enzyme in v %}
|
||||
<li>
|
||||
<a href="{{ enzyme.url }}" class="hover:bg-base-300">
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<span>{{ enzyme.ec_number }}</span>
|
||||
<span class="text-sm opacity-70"
|
||||
>{{ enzyme.linking_method }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="text-sm opacity-60">
|
||||
{{ enzyme.name }}
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "framework.html" %}
|
||||
{% extends "framework_modern.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -10,187 +10,161 @@
|
||||
{% include "modals/objects/generic_delete_modal.html" %}
|
||||
{% endblock action_modals %}
|
||||
|
||||
<div class="panel-group" id="user-detail">
|
||||
<div class="panel panel-default">
|
||||
<div
|
||||
class="panel-heading"
|
||||
id="headingPanel"
|
||||
style="font-size:2rem;height: 46px"
|
||||
>
|
||||
{{ user.username }}
|
||||
<div
|
||||
id="actionsButton"
|
||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||
class="dropdown"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||
<span class="caret"></span><span style="padding-right:1em"></span
|
||||
></a>
|
||||
<ul id="actionsList" class="dropdown-menu">
|
||||
{% block actions %}
|
||||
{% include "actions/objects/user.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
<div class="space-y-2 p-4">
|
||||
<!-- Header Section -->
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="card-title text-2xl">{{ user.username }}</h2>
|
||||
<div id="actionsButton" class="dropdown dropdown-end hidden">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||
<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-wrench"
|
||||
>
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
Actions
|
||||
</div>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||
>
|
||||
{% block actions %}
|
||||
{% include "actions/objects/user.html" %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<p class="mt-2">
|
||||
On this page you can modify your account or set preferences such as
|
||||
prediction settings.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Default Package -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="default-package-link"
|
||||
data-toggle="collapse"
|
||||
data-parent="#user-detail"
|
||||
href="#default-package"
|
||||
>Default Package</a
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Default Package</div>
|
||||
<div class="collapse-content">
|
||||
<a href="{{ user.default_package.url }}" class="link link-primary"
|
||||
>{{ user.default_package.name }}</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="default-package" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
<li class="list-group-item">
|
||||
<a href="{{ user.default_package.url }}">
|
||||
{{ user.default_package.name|safe }}</a
|
||||
>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Groups -->
|
||||
{% if meta.available_groups|length > 0 %}
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="group-links"
|
||||
data-toggle="collapse"
|
||||
data-parent="#user-detail"
|
||||
href="#groups"
|
||||
>Groups</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="groups" class="panel-collapse in collapse">
|
||||
<div class="panel-body list-group-item">
|
||||
{% for g in meta.available_groups %}
|
||||
<li class="list-group-item">
|
||||
<a href="{{ g.url }}"> {{ g.name|safe }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">Groups</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for g in meta.available_groups %}
|
||||
<li>
|
||||
<a href="{{ g.url }}" class="hover:bg-base-200">{{ g.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Current Prediction Settings -->
|
||||
<div
|
||||
class="panel panel-default panel-heading list-group-item"
|
||||
style="background-color:silver"
|
||||
>
|
||||
<h4 class="panel-title">
|
||||
<a
|
||||
id="current-prediction-setting-links"
|
||||
data-toggle="collapse"
|
||||
data-parent="#user-detail"
|
||||
href="#current-prediction-setting"
|
||||
>Current Prediction Setting</a
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="current-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>
|
||||
</tr>
|
||||
<tbody>
|
||||
{% if user.default_setting.model %}
|
||||
<!-- Current Prediction Setting -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
Current Prediction Setting
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table-zebra table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="20%">Model</td>
|
||||
<td width="80%">
|
||||
<table width="100%" class="table-bordered table-hover table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<li class="list-group-item">
|
||||
<a href="{{ user.default_setting.model.url }}">
|
||||
{{ user.default_setting.model.name|safe }}
|
||||
</a>
|
||||
</li>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="20%">Model Parameter</th>
|
||||
<th width="80%">Parameter Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%">Threshold</td>
|
||||
<td width="80%">
|
||||
{{ user.default_setting.model_threshold }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if user.default_setting.rule_packages.all %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if user.default_setting.model %}
|
||||
<tr>
|
||||
<td>Model</td>
|
||||
<td>
|
||||
<div class="space-y-2">
|
||||
<a
|
||||
href="{{ user.default_setting.model.url }}"
|
||||
class="link link-primary"
|
||||
>
|
||||
{{ user.default_setting.model.name }}
|
||||
</a>
|
||||
<table class="table-xs table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Model Parameter</th>
|
||||
<th>Parameter Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Threshold</td>
|
||||
<td>{{ user.default_setting.model_threshold }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if user.default_setting.rule_packages.all %}
|
||||
<tr>
|
||||
<td>Rule Packages</td>
|
||||
<td>
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
{% for p in user.default_setting.rule_packages.all %}
|
||||
<li>
|
||||
<a href="{{ p.url }}" class="hover:bg-base-300"
|
||||
>{{ p.name }}</a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td width="20%">Rule Packages</td>
|
||||
<td width="80%">
|
||||
<table width="100%" class="table-bordered table-hover table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% for p in user.default_setting.rule_packages.all %}
|
||||
<li class="list-group-item">
|
||||
<a href="{{ p.url }}"> {{ p.name|safe }} </a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td>Max Nodes</td>
|
||||
<td>{{ user.default_setting.max_nodes }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Nodes</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ user.default_setting.max_nodes }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Max Depth</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>{{ user.default_setting.max_depth }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<tr>
|
||||
<td>Max Depth</td>
|
||||
<td>{{ user.default_setting.max_depth }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show actions button if there are actions
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
@ -158,11 +158,12 @@
|
||||
}
|
||||
|
||||
function predictKetcherToTextInput() {
|
||||
$("#predict-smiles").val(this.ketcher.getSmiles());
|
||||
document.getElementById("predict-smiles").value = this.ketcher.getSmiles();
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#predict-ketcher").on("load", function () {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const predictKetcher = document.getElementById("predict-ketcher");
|
||||
predictKetcher.addEventListener("load", function () {
|
||||
const checkKetcherReady = () => {
|
||||
const win = this.contentWindow;
|
||||
if (win.ketcher && "editor" in win.ketcher) {
|
||||
@ -181,14 +182,16 @@
|
||||
checkKetcherReady();
|
||||
});
|
||||
|
||||
$("#predict-submit-button").on("click", function (e) {
|
||||
const submitButton = document.getElementById("predict-submit-button");
|
||||
submitButton.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
const button = $(this);
|
||||
button.prop("disabled", true);
|
||||
button.text("Predicting...");
|
||||
const button = this;
|
||||
button.disabled = true;
|
||||
button.textContent = "Predicting...";
|
||||
|
||||
// Get SMILES from either input or Ketcher
|
||||
let smiles = $("#predict-smiles").val().trim();
|
||||
const smilesInput = document.getElementById("predict-smiles");
|
||||
let smiles = smilesInput.value.trim();
|
||||
|
||||
// If SMILES input is empty, try to get from Ketcher
|
||||
if (!smiles) {
|
||||
@ -197,13 +200,13 @@
|
||||
try {
|
||||
smiles = ketcher.getSmiles().trim();
|
||||
if (smiles) {
|
||||
$("#predict-smiles").val(smiles);
|
||||
smilesInput.value = smiles;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to get SMILES from Ketcher:", err);
|
||||
alert("Unable to extract structure from the drawing editor. Please enter a SMILES string instead.");
|
||||
button.prop("disabled", false);
|
||||
button.text("Predict");
|
||||
button.disabled = false;
|
||||
button.textContent = "Predict";
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -212,13 +215,13 @@
|
||||
// Basic validation
|
||||
if (!smiles) {
|
||||
alert("Please enter a SMILES string or draw a structure.");
|
||||
button.prop("disabled", false);
|
||||
button.text("Predict");
|
||||
button.disabled = false;
|
||||
button.textContent = "Predict";
|
||||
return;
|
||||
}
|
||||
|
||||
// Submit form
|
||||
$("#predict_form").submit();
|
||||
document.getElementById("predict_form").submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user