diff --git a/client/models/model.js b/client/models/model.js
index b8b59ab441..139c9647a5 100644
--- a/client/models/model.js
+++ b/client/models/model.js
@@ -91,12 +91,12 @@ module.exports = Model.extend({
this.rules.on('add change remove', this.updateValid, this);
},
validateModel: function () {
- if(!this.species.validateCollection()) return false;
+ if(!this.species.validateCollection(this.is_spatial)) return false;
if(!this.parameters.validateCollection()) return false;
if(!this.reactions.validateCollection()) return false;
if(!this.eventsCollection.validateCollection()) return false;
if(!this.rules.validateCollection()) return false;
- if(this.reactions.length <= 0 && this.eventsCollection.length <= 0 && this.rules.length <= 0) {
+ if(!this.is_spatial && this.reactions.length <= 0 && this.eventsCollection.length <= 0 && this.rules.length <= 0) {
this.error = {"type":"process"}
return false;
}
diff --git a/client/models/species.js b/client/models/species.js
index 5ba9377b71..b9ee6dc508 100644
--- a/client/models/species.js
+++ b/client/models/species.js
@@ -55,8 +55,8 @@ module.exports = Collection.extend({
this.remove(specie);
this.parent.updateValid()
},
- validateCollection: function () {
- if(this.length <= 0) {
+ validateCollection: function (isSpatial) {
+ if(this.length <= 0 && !isSpatial) {
this.parent.error = {'type':'species'}
return false;
}
diff --git a/client/models/timespan-settings.js b/client/models/timespan-settings.js
index 98ab1d7879..b467a2b125 100644
--- a/client/models/timespan-settings.js
+++ b/client/models/timespan-settings.js
@@ -22,7 +22,8 @@ var State = require('ampersand-state');
module.exports = State.extend({
props: {
endSim: 'any',
- timeStep: 'any'
+ timeStep: 'any',
+ timestepSize: 'number'
},
initialize: function (attrs, options) {
State.prototype.initialize.apply(this, arguments)
diff --git a/client/pages/model-editor.js b/client/pages/model-editor.js
index ce70b0177e..b3b8160138 100644
--- a/client/pages/model-editor.js
+++ b/client/pages/model-editor.js
@@ -23,23 +23,19 @@ let path = require('path');
var app = require('../app');
var modals = require('../modals');
var tests = require('../views/tests');
+let Tooltips = require("../tooltips");
//views
var PageView = require('../pages/base');
var InputView = require('../views/input');
var DomainViewer = require('../views/domain-viewer');
var SpeciesEditorView = require('../views/species-editor');
-var SpeciesViewer = require('../views/species-viewer');
var InitialConditionsEditorView = require('../views/initial-conditions-editor');
var InitialConditionsViewer = require('../views/initial-conditions-viewer');
var ParametersEditorView = require('../views/parameters-editor');
-var ParameterViewer = require('../views/parameters-viewer');
var ParticleViewer = require('../views/view-particle');
var ReactionsEditorView = require('../views/reactions-editor');
-var ReactionsViewer = require('../views/reactions-viewer');
var EventsEditorView = require('../views/events-editor');
-var EventsViewer = require('../views/events-viewer');
var RulesEditorView = require('../views/rules-editor');
-var RulesViewer = require('../views/rules-viewer');
var SBMLComponentView = require('../views/sbml-component-editor');
var TimespanSettingsView = require('../views/timespan-settings');
var ModelStateButtonsView = require('../views/model-state-buttons');
@@ -55,9 +51,13 @@ import initPage from './page.js';
let ModelEditor = PageView.extend({
template: template,
events: {
+ 'change [data-hook=all-continuous]' : 'setDefaultMode',
+ 'change [data-hook=all-discrete]' : 'setDefaultMode',
+ 'change [data-hook=advanced]' : 'setDefaultMode',
'click [data-hook=edit-model-help]' : function () {
let modal = $(modals.operationInfoModalHtml('model-editor')).modal();
},
+ 'change [data-hook=edit-volume]' : 'updateVolumeViewer',
'click [data-hook=collapse-me-advanced-section]' : 'changeCollapseButtonText',
'click [data-hook=project-breadcrumb-link]' : 'handleProjectBreadcrumbClick',
'click [data-hook=toggle-preview-plot]' : 'togglePreviewPlot',
@@ -67,6 +67,7 @@ let ModelEditor = PageView.extend({
},
initialize: function (attrs, options) {
PageView.prototype.initialize.apply(this, arguments);
+ this.tooltips = Tooltips.modelEditor
var self = this;
let urlParams = new URLSearchParams(window.location.search)
var directory = urlParams.get('path');
@@ -219,6 +220,12 @@ let ModelEditor = PageView.extend({
}
},
renderSubviews: function () {
+ if(this.model.defaultMode === "" && !this.model.is_spatial){
+ this.getInitialDefaultMode();
+ }else{
+ let dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}
+ $(this.queryByHook(dataHooks[this.model.defaultMode])).prop('checked', true)
+ }
this.modelSettings = new TimespanSettingsView({
parent: this,
model: this.model.modelSettings,
@@ -232,6 +239,7 @@ let ModelEditor = PageView.extend({
app.registerRenderSubview(this, this.modelSettings, 'model-settings-container');
app.registerRenderSubview(this, this.modelStateButtons, 'model-state-buttons-container');
if(this.model.is_spatial) {
+ $(this.queryByHook("advaced-model-mode")).css("display", "none");
$(this.queryByHook("model-editor-advanced-container")).css("display", "none");
$(this.queryByHook("spatial-beta-message")).css("display", "block");
this.renderDomainViewer();
@@ -243,8 +251,7 @@ let ModelEditor = PageView.extend({
this.renderRulesView();
if(this.model.functionDefinitions.length) {
var sbmlComponentView = new SBMLComponentView({
- functionDefinitions: this.model.functionDefinitions,
- viewModel: false
+ functionDefinitions: this.model.functionDefinitions
});
app.registerRenderSubview(this, sbmlComponentView, 'sbml-component-container');
}
@@ -288,15 +295,15 @@ let ModelEditor = PageView.extend({
app.registerRenderSubview(this, this.domainViewer, 'domain-viewer-container');
}
},
- renderSpeciesView: function (mode="edit") {
+ renderSpeciesView: function () {
if(this.speciesEditor) {
this.speciesEditor.remove()
}
- if(mode === "edit") {
- this.speciesEditor = new SpeciesEditorView({collection: this.model.species});
- }else{
- this.speciesEditor = new SpeciesViewer({collection: this.model.species});
- }
+ this.speciesEditor = new SpeciesEditorView({
+ collection: this.model.species,
+ spatial: this.model.is_spatial,
+ defaultMode: this.model.defaultMode
+ });
app.registerRenderSubview(this, this.speciesEditor, 'species-editor-container');
},
renderInitialConditions: function (mode="edit", opened=false) {
@@ -315,48 +322,32 @@ let ModelEditor = PageView.extend({
}
app.registerRenderSubview(this, this.initialConditionsEditor, 'initial-conditions-editor-container');
},
- renderParametersView: function (mode="edit", opened=false) {
+ renderParametersView: function () {
if(this.parametersEditor) {
this.parametersEditor.remove()
}
- if(mode === "edit") {
- this.parametersEditor = new ParametersEditorView({collection: this.model.parameters, opened: opened});
- }else{
- this.parametersEditor = new ParameterViewer({collection: this.model.parameters});
- }
+ this.parametersEditor = new ParametersEditorView({collection: this.model.parameters});
app.registerRenderSubview(this, this.parametersEditor, 'parameters-editor-container');
},
- renderReactionsView: function (mode="edit", opened=false) {
+ renderReactionsView: function () {
if(this.reactionsEditor) {
this.reactionsEditor.remove()
}
- if(mode === "edit") {
- this.reactionsEditor = new ReactionsEditorView({collection: this.model.reactions, opened: opened});
- }else{
- this.reactionsEditor = new ReactionsViewer({collection: this.model.reactions});
- }
+ this.reactionsEditor = new ReactionsEditorView({collection: this.model.reactions});
app.registerRenderSubview(this, this.reactionsEditor, 'reactions-editor-container');
},
- renderEventsView: function (mode="edit", opened=false) {
+ renderEventsView: function () {
if(this.eventsEditor){
this.eventsEditor.remove();
}
- if(mode === "edit") {
- this.eventsEditor = new EventsEditorView({collection: this.model.eventsCollection, opened: opened});
- }else{
- this.eventsEditor = new EventsViewer({collection: this.model.eventsCollection});
- }
+ this.eventsEditor = new EventsEditorView({collection: this.model.eventsCollection});
app.registerRenderSubview(this, this.eventsEditor, 'events-editor-container');
},
- renderRulesView: function (mode="edit", opened=false) {
+ renderRulesView: function () {
if(this.rulesEditor){
this.rulesEditor.remove();
}
- if(mode === "edit") {
- this.rulesEditor = new RulesEditorView({collection: this.model.rules, opened: opened});
- }else{
- this.rulesEditor = new RulesViewer({collection: this.model.rules})
- }
+ this.rulesEditor = new RulesEditorView({collection: this.model.rules});
app.registerRenderSubview(this, this.rulesEditor, 'rules-editor-container');
},
renderSystemVolumeView: function () {
@@ -373,10 +364,11 @@ let ModelEditor = PageView.extend({
valueType: 'number',
value: this.model.volume,
});
- app.registerRenderSubview(this, this.systemVolumeView, 'volume')
+ app.registerRenderSubview(this, this.systemVolumeView, 'edit-volume')
if(this.model.defaultMode === "continuous") {
$(this.queryByHook("system-volume-container")).collapse("hide")
}
+ $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume)
},
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
@@ -430,6 +422,66 @@ let ModelEditor = PageView.extend({
clickDownloadPNGButton: function (e) {
let pngButton = $('div[data-hook=preview-plot-container] a[data-title*="Download plot as a png"]')[0]
pngButton.click()
+ },
+ getInitialDefaultMode: function () {
+ var self = this;
+ if(document.querySelector('#defaultModeModal')) {
+ document.querySelector('#defaultModeModal').remove();
+ }
+ let modal = $(modals.renderDefaultModeModalHtml()).modal();
+ let continuous = document.querySelector('#defaultModeModal .concentration-btn');
+ let discrete = document.querySelector('#defaultModeModal .population-btn');
+ let dynamic = document.querySelector('#defaultModeModal .hybrid-btn');
+ continuous.addEventListener('click', function (e) {
+ self.setInitialDefaultMode(modal, "continuous");
+ });
+ discrete.addEventListener('click', function (e) {
+ self.setInitialDefaultMode(modal, "discrete");
+ });
+ dynamic.addEventListener('click', function (e) {
+ self.setInitialDefaultMode(modal, "dynamic");
+ });
+ },
+ setAllSpeciesModes: function (prevMode) {
+ let self = this;
+ this.model.species.forEach(function (specie) {
+ specie.mode = self.model.defaultMode;
+ self.model.species.trigger('update-species', specie.compID, specie, false, true);
+ });
+ let switchToDynamic = (!Boolean(prevMode) || prevMode !== "dynamic") && this.model.defaultMode === "dynamic";
+ let switchFromDynamic = Boolean(prevMode) && prevMode === "dynamic" && this.model.defaultMode !== "dynamic";
+ if(switchToDynamic || switchFromDynamic) {
+ this.speciesEditor.renderEditSpeciesView();
+ this.speciesEditor.renderViewSpeciesView();
+ }
+ },
+ setDefaultMode: function (e) {
+ let prevMode = this.model.defaultMode;
+ this.model.defaultMode = e.target.dataset.name;
+ this.speciesEditor.defaultMode = e.target.dataset.name;
+ this.setAllSpeciesModes(prevMode);
+ this.toggleVolumeContainer();
+ },
+ setInitialDefaultMode: function (modal, mode) {
+ var dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'};
+ modal.modal('hide');
+ $(this.queryByHook(dataHooks[mode])).prop('checked', true);
+ this.model.defaultMode = mode;
+ this.speciesEditor.defaultMode = mode;
+ this.setAllSpeciesModes();
+ this.toggleVolumeContainer();
+ },
+ toggleVolumeContainer: function () {
+ if(!this.model.is_spatial) {
+ if(this.model.defaultMode === "continuous") {
+ $(this.queryByHook("system-volume-container")).collapse("hide");
+ }else{
+ $(this.queryByHook("system-volume-container")).collapse("show");
+ }
+ }
+ },
+ updateVolumeViewer: function (e) {
+ $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume)
}
});
diff --git a/client/styles/styles.css b/client/styles/styles.css
index 29403e2122..e5b21c765d 100644
--- a/client/styles/styles.css
+++ b/client/styles/styles.css
@@ -293,6 +293,11 @@ input[type="file"]::-ms-browse {
display: inline-block;
}
+.reaction-list-summary {
+ width: auto !important;
+ text-align: center;
+}
+
.container-part {
max-width: none;
}
diff --git a/client/templates/includes/editAdvancedSpecie.pug b/client/templates/includes/editAdvancedSpecie.pug
deleted file mode 100644
index e341430071..0000000000
--- a/client/templates/includes/editAdvancedSpecie.pug
+++ /dev/null
@@ -1,19 +0,0 @@
-tr
-
- td.name: div(data-hook="specie-name")=this.model.name
-
- td: div(data-hook="specie-mode")
-
- td
- div.switching
- input(type="radio", name=this.model.name + "-switch-method", data-hook="switching-tol")
- | Switching Tolerance
-
- div.switching
- input(type="radio", name=this.model.name + "-switch-method", data-hook="switching-min")
- | Minimum Value for Switching (number of molecules)
-
- td
- div(data-hook="switching-tolerance")
-
- div(data-hook="switching-threshold")
\ No newline at end of file
diff --git a/client/templates/includes/editEventAssignment.pug b/client/templates/includes/editEventAssignment.pug
index 00c9294936..ecc8b48dda 100644
--- a/client/templates/includes/editEventAssignment.pug
+++ b/client/templates/includes/editEventAssignment.pug
@@ -1,7 +1,18 @@
-tr
+div.mx-1
- td: div(data-hook="event-assignment-variable")
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td: div(data-hook="event-assignment-Expression")
+ div.row
- td: button.btn.btn-outline-secondary(data-hook="remove") X
\ No newline at end of file
+ div.col-sm-3
+
+ div.pl-2(data-hook="event-assignment-variable")
+
+ div.col-sm-7
+
+ div(data-hook="event-assignment-expression")
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary(data-hook="remove") X
diff --git a/client/templates/includes/editFunctionDefinition.pug b/client/templates/includes/editFunctionDefinition.pug
index 1e9f7f5a54..74866ea363 100644
--- a/client/templates/includes/editFunctionDefinition.pug
+++ b/client/templates/includes/editFunctionDefinition.pug
@@ -1,13 +1,20 @@
-tr
+div.mx-1
- td=this.model.signature
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- th
+ div.row
- div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.col-sm-8
+
+ div.pl-2=this.model.signature
+
+ div.col-sm-2
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
- if(!this.parent.viewMode)
button.btn.btn-outline-secondary.btn-sm(data-hook="edit-annotation-btn") Edit
-
- if(!this.parent.viewMode)
- td: button.btn.btn-outline-secondary(data-hook="remove") X
\ No newline at end of file
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary(data-hook="remove") X
diff --git a/client/templates/includes/editParameter.pug b/client/templates/includes/editParameter.pug
new file mode 100644
index 0000000000..87c84fa80e
--- /dev/null
+++ b/client/templates/includes/editParameter.pug
@@ -0,0 +1,24 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-3
+
+ div.pl-2(data-hook="input-name-container")
+
+ div.col-sm-5
+
+ div(data-hook="input-value-container")
+
+ div.col-sm-2
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
diff --git a/client/templates/includes/editReactionVar.pug b/client/templates/includes/editReactionVar.pug
deleted file mode 100644
index 8d416852be..0000000000
--- a/client/templates/includes/editReactionVar.pug
+++ /dev/null
@@ -1,12 +0,0 @@
-tr
- td.name: div(data-hook="input-name-container")
-
- td: div(data-hook="input-value-container")
-
- td
-
- div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
-
- button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
-
- td: button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
\ No newline at end of file
diff --git a/client/templates/includes/editRule.pug b/client/templates/includes/editRule.pug
index 30c7547445..cdbb34eaeb 100644
--- a/client/templates/includes/editRule.pug
+++ b/client/templates/includes/editRule.pug
@@ -1,17 +1,32 @@
-tr
+div.mx-1
- td.name: div(data-hook="rule-name")
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td: div(data-hook="rule-type")
+ div.row
- td: div(data-hook="rule-variable")
+ div.col-sm-2
- td: div(data-hook="rule-expression")
+ div.pl-2(data-hook="rule-name")
- td
+ div.col-sm-2
- div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div(data-hook="rule-type")
- button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+ div.col-sm-2
- td: button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
\ No newline at end of file
+ div(data-hook="rule-variable")
+
+ div.col-sm-2
+
+ div(data-hook="rule-expression")
+
+ div.col-sm-2
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
diff --git a/client/templates/includes/editSpatialSpecie.pug b/client/templates/includes/editSpatialSpecie.pug
deleted file mode 100644
index 44aefb3757..0000000000
--- a/client/templates/includes/editSpatialSpecie.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-tr
-
- td.name: div(data-hook="input-name-container")
-
- td: div(data-hook="input-diffusion-coeff-container")
-
- td: div.row(data-hook="species-types")
-
- td: button.btn.btn-outline-secondary(data-hook="remove") X
\ No newline at end of file
diff --git a/client/templates/includes/editSpatialSpecies.pug b/client/templates/includes/editSpatialSpecies.pug
new file mode 100644
index 0000000000..ae78da2e75
--- /dev/null
+++ b/client/templates/includes/editSpatialSpecies.pug
@@ -0,0 +1,28 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-2
+
+ div.pl-2(data-hook="input-name-container")
+
+ div.col-sm-2
+
+ div(data-hook="input-value-container")
+
+ div.col-sm-4
+
+ div.row(data-hook="species-types")
+
+ div.col-sm-2
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
diff --git a/client/templates/includes/editSpecies.pug b/client/templates/includes/editSpecies.pug
new file mode 100644
index 0000000000..3c1ad72082
--- /dev/null
+++ b/client/templates/includes/editSpecies.pug
@@ -0,0 +1,70 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-3
+
+ div.pl-2(data-hook="input-name-container")
+
+ div.col-sm-5
+
+ div(data-hook="input-value-container")
+
+ div.col-sm-2
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-sm-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
+
+ div.mx-1.pl-2(data-hook="advanced-species")
+
+ div.align-items-baseline
+
+ h6.inline Advanced
+
+ button.btn.btn-outline-collapse.mb-2(data-toggle="collapse" data-target="#collapse-species-advanced" + this.model.collection.indexOf(this.model) data-hook="collapse-advanced") +
+
+ div.collapse(id="collapse-species-advanced" + this.model.collection.indexOf(this.model))
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ h6.inline Mode
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.tooltips.mode)
+
+ div.col-sm-9
+
+ h6.inline Switching Settings (Hybrid Only)
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.tooltips.switchValue)
+
+ div.row.mt-3
+
+ div.col-sm-3(data-hook="specie-mode")
+
+ div.col-sm-4
+
+ div.switching
+ input(type="radio", name=this.model.name + "-switch-method", data-hook="switching-tol")
+ | Switching Tolerance
+
+ div.switching
+ input(type="radio", name=this.model.name + "-switch-method", data-hook="switching-min")
+ | Minimum Value for Switching (number of molecules)
+
+ div.col-sm-5
+
+ div(data-hook="switching-tolerance")
+
+ div(data-hook="switching-threshold")
diff --git a/client/templates/includes/eventAssignmentsEditor.pug b/client/templates/includes/eventAssignmentsEditor.pug
index 022cef0cd7..f32e4cf6da 100644
--- a/client/templates/includes/eventAssignmentsEditor.pug
+++ b/client/templates/includes/eventAssignmentsEditor.pug
@@ -1,26 +1,55 @@
-div
+div#event-assignments-editor
- table.table
+ div(data-hook="event-assignments-header")
- thead
+ h5.inline.mr-3
- tr
+ div
+
+ div.inline Assignments
- th(scope="col")
- div
- div.inline Target
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.assignments)
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.parent.tooltips.variable)
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-event-assignments" data-hook="collapse-assignments") -
- th(scope="col")
- div
- div.inline Expression
+ div
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.parent.tooltips.assignmentExpression)
+ div.collapse.show.tab-content(id="collapse-event-assignments" data-hook="event-assignments-list-container")
- th(scope="col") Remove
+ div.tab-pane.active(id="edit-event-assignments" data-hook="edit-event-assignments")
- tbody(data-hook="event-assignments-container")
+ hr
- button.btn.btn-outline-primary.box-shadow(data-hook="add-event-assignment", type="button")
- | Add Assignment
\ No newline at end of file
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ div.inline Target
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.variable)
+
+ div.col-sm-7
+
+ h6.inline Expression
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.assignmentExpression)
+
+ div.col-sm-2
+
+ h6 Remove
+
+ div.my-3(data-hook="edit-event-assignments-container")
+
+ button.btn.btn-outline-primary.box-shadow(data-hook="add-event-assignment", type="button") Add Assignment
+
+ div.tab-pane(id="view-event-assignments" data-hook="view-event-assignments")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3 Target
+
+ div.col-sm-7 Expression
+
+ div.my-3(data-hook="view-event-assignments-container")
diff --git a/client/templates/includes/eventAssignmentsViewer.pug b/client/templates/includes/eventAssignmentsViewer.pug
deleted file mode 100644
index 4a3aa846c8..0000000000
--- a/client/templates/includes/eventAssignmentsViewer.pug
+++ /dev/null
@@ -1,11 +0,0 @@
-table.table
-
- thead
-
- tr
-
- th(scope="col") Target
-
- th(scope="col") Expression
-
- tbody(data-hook="view-event-assignments-list")
\ No newline at end of file
diff --git a/client/templates/includes/eventDetails.pug b/client/templates/includes/eventDetails.pug
index 6ccdb91b55..c473f51381 100644
--- a/client/templates/includes/eventDetails.pug
+++ b/client/templates/includes/eventDetails.pug
@@ -1,14 +1,18 @@
div(data-hook="event-details")
- div
+ div.row
- span(for="event-trigger-expression") Trigger Expression:
+ div
+
+ span(for="event-trigger-expression") Trigger Expression:
div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.tooltips.triggerExpression)
- div.col-md-8.inline(id="event-trigger-expression" data-hook="event-trigger-expression")
+ div.col-md-8(id="event-trigger-expression" data-hook="event-trigger-expression")
- div
+ div(data-hook="event-assignments")
+
+ div.my-1
h6.inline Advanced
button.btn.btn-outline-collapse(data-toggle='collapse', data-target='#advanced-events', data-hook='advanced-event-button') +
@@ -27,7 +31,7 @@ div(data-hook="event-details")
div.col-md-6
- span(for="event-trigger-expression") Prioirty:
+ span(for="event-trigger-expression") Priority:
div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.tooltips.priority)
@@ -61,18 +65,10 @@ div(data-hook="event-details")
div.horizontal-space.inline
- input(type="radio", name="use-values-from" data-hook="trigger-time" data-name="trigger")
+ input(type="radio", name="edit-use-values-from" data-hook="edit-trigger-time" data-name="trigger")
| Trigger Time
div.horizontal-space.inline
- input(type="radio", name="use-values-from" data-hook="assignment-time" data-name="assignment")
+ input(type="radio", name="edit-use-values-from" data-hook="edit-assignment-time" data-name="assignment")
| Assignment Time
-
- h5.inline
- div
- div.inline Assignments
-
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.parent.tooltips.assignments)
-
- div(data-hook="event-assignments")
\ No newline at end of file
diff --git a/client/templates/includes/eventListings.pug b/client/templates/includes/eventListings.pug
index c1d7a49696..f67a2ecc19 100644
--- a/client/templates/includes/eventListings.pug
+++ b/client/templates/includes/eventListings.pug
@@ -1,13 +1,22 @@
-tr
+div.mx-1
- td: input(type="radio", data-hook="select", name="event-select")
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td.name: div(data-hook="event-name-container")
+ div.row.align-items-baseline
- td
+ div.col-md-2
- div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.pl-3: input(type="radio", data-hook="select", name="event-select")
- button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+ div.col-md-5(data-hook="event-name-container")
- td: button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
\ No newline at end of file
+ div.col-md-3
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-md-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
diff --git a/client/templates/includes/eventsEditor.pug b/client/templates/includes/eventsEditor.pug
index 41f5845440..0828d3d9ee 100644
--- a/client/templates/includes/eventsEditor.pug
+++ b/client/templates/includes/eventsEditor.pug
@@ -1,45 +1,90 @@
-div#events.card.card-body
+div#events.card
- div
+ div.card-header.pb-0
- h3.inline Events
+ h3.inline.mr-3 Events
+
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="events-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="events-edit-tab" data-toggle="tab" href="#edit-events") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="events-view-tab" data-toggle="tab" href="#view-events") View
button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#events-container", data-hook="collapse") +
- div.collapse(id="events-container", data-hook="events")
+ div.card-body
+
+ p.mb-0
+ | A discontinuous action triggered by the state of the system.
+
+ div.collapse.tab-content(id="events-container", data-hook="events")
+
+ div.tab-pane.active(id="edit-events" data-hook="edit-events")
+
+ div.row.mb-3.align-items-baseline
+
+ div.col-md-6.container-part
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-md-2
+
+ h6 Edit
+
+ div.col-md-5
+
+ h6.inline Name
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+
+ div.col-md-3
+
+ h6.inline Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-md-2
+
+ h6 Remove
+
+ div.mt-3(data-hook="edit-event-listing-container")
+
+ div.col-md-6.container-part(data-hook="event-details-container")
- div.row
+ button.btn.btn-outline-primary.box-shadow(data-hook="add-event") Add Event
- div.col-md-6.container-part
- p
- | A discontinuous action triggered by the state of the system.
+ div.tab-pane(id="view-events" data-hook="view-events")
- table.table
+ hr
- thead
+ div.mx-1.row.head
- tr
+ div.col-sm-2
- th(scope="col") Edit
+ h6 Name
- th(scope="col")
- div
- div.inline Name
+ div.col-sm-2
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+ h6 Trigger
- th(scope="col")
- div
- div.inline Annotation
+ div.col-sm-4
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+ h6 Assignments
- th(scope="col") Remove
+ div.col-sm-2
- tbody(data-hook="event-listing-container")
+ h6 Advanced
- div.col-md-6.container-part(data-hook="event-details-container")
+ div.col-sm-2(data-hook="events-annotation-header")
- button.btn.btn-outline-primary.box-shadow(data-hook="add-event") Add Event
+ h6 Annotation
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-events") Save Events
+ div.mt-3(data-hook="view-event-listing-container")
diff --git a/client/templates/includes/eventsViewer.pug b/client/templates/includes/eventsViewer.pug
deleted file mode 100644
index bf9bed0f61..0000000000
--- a/client/templates/includes/eventsViewer.pug
+++ /dev/null
@@ -1,30 +0,0 @@
-div#events-viewer.card.card-body
-
- div
-
- h3.inline Events
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-model-events-viewer", data-hook="collapse") -
-
- div.row.collapse(class="show", id="collapse-model-events-viewer")
-
- table.table
-
- thead
-
- tr
-
- th(scope="col") Name
-
- th(scope="col") Trigger
-
- th(scope="col") Assignments
-
- th(scope="col") Advanced
-
- if this.containsMdlWithAnn
- th.col-md-3-view(scope="col") Annotation
-
- tbody(data-hook="view-events-container")
-
- if this.collection.parent.for === "edit"
- button.btn.btn-outline-primary.box-shadow(data-hook="edit-events") Edit Events
diff --git a/client/templates/includes/parametersEditor.pug b/client/templates/includes/parametersEditor.pug
index 707ada2a8b..5d2c5af0d6 100644
--- a/client/templates/includes/parametersEditor.pug
+++ b/client/templates/includes/parametersEditor.pug
@@ -1,43 +1,73 @@
-div#parameters-editor.card.card-body
+div#parameters-editor.card
- div
+ div.card-header.pb-0
- h3.inline Parameters
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-parameters", data-hook="collapse") +
+ h3.inline.mr-3 Parameters
- div.collapse(id="collapse-parameters" data-hook="parameters-list-container")
- p
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="parameter-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="parameters-edit-tab" data-toggle="tab" href="#edit-parameters") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="parameters-view-tab" data-toggle="tab" href="#view-parameters") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-parameters" data-hook="collapse") +
+
+ div.card-body
+ p.mb-0
| Constant values that represents an inherent properties of the system. Used to set the rate of a Reaction.
- table.table
- thead
- tr
- th(scope="col")
- div
- div.inline Name
+ div.collapse.tab-content(id="collapse-parameters" data-hook="parameters-list-container")
+
+ div.tab-pane.active(id="edit-parameters" data-hook="edit-parameters")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ h6.inline Name
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+
+ div.col-sm-5
+
+ h6.inline Value
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.expression)
+
+ div.col-sm-2
+
+ h6.inline Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-sm-2
+
+ h6.inline Remove
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.remove)
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+ div.my-3(data-hook="edit-parameter-list")
- th(scope="col")
- div
- div.inline Value
+ button.btn.btn-outline-primary.box-shadow(data-hook="add-parameter") Add Parameter
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.expression)
+ div.tab-pane(id="view-parameters" data-hook="view-parameters")
- th(scope="col")
- div
- div.inline Annotation
+ hr
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+ div.mx-1.row.head.align-items-baseline
- th(scope="col")
- div
- div.inline Remove
+ div.col-sm-3: h6 Name
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.remove)
-
- tbody(data-hook="parameter-list")
+ div.col-sm-7: h6 Value
- button.btn.btn-outline-primary.box-shadow(data-hook="add-parameter") Add Parameter
+ div.col-sm-2(data-hook="parameters-annotation-header"): h6 Annotation
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-parameters") Save Parameters
+ div.mt-3(data-hook="view-parameter-list")
diff --git a/client/templates/includes/parametersViewer.pug b/client/templates/includes/parametersViewer.pug
deleted file mode 100644
index b579141fb2..0000000000
--- a/client/templates/includes/parametersViewer.pug
+++ /dev/null
@@ -1,21 +0,0 @@
-div#parameters-viewer.card.card-body
-
- div
-
- h3.inline Parameters
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-parameters", data-hook="collapse") -
-
- div.collapse(class="show", id="collapse-parameters")
-
- table.table
- thead
- tr
- th.col-md-3-view(scope="col") Name
- th.col-md-9-view(scope="col") Value
- if this.containsMdlWithAnn
- th.col-md-3-view(scope="col") Annotation
-
- tbody(data-hook="parameter-list")
-
- if this.collection.parent.for === "edit"
- button.btn.btn-outline-primary.box-shadow(data-hook="edit-parameters") Edit Parameters
diff --git a/client/templates/includes/reactionListing.pug b/client/templates/includes/reactionListing.pug
index bed0ba53e5..3b7ea5cae3 100644
--- a/client/templates/includes/reactionListing.pug
+++ b/client/templates/includes/reactionListing.pug
@@ -1,14 +1,24 @@
-tr
- td: input(type="radio", data-hook="select", name="reaction-select")
-
- td.name: div(data-hook="input-name-container")
-
- td: div(data-hook="summary", style="width: auto !important")
-
- td
+div.mx-1
- div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+ div.row.align-items-baseline
- td: button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
\ No newline at end of file
+ div.col-md-2
+
+ div.pl-3: input(type="radio" data-hook="select" name="reaction-select")
+
+ div.col-md-2(data-hook="input-name-container")
+
+ div.col-md-3.reaction-list-summary(data-hook="summary")
+
+ div.col-md-3
+
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+
+ button.btn.btn-outline-secondary.btn-sm.box-shadow(data-hook="edit-annotation-btn") Edit
+
+ div.col-md-2
+
+ button.btn.btn-outline-secondary.box-shadow(data-hook="remove") X
diff --git a/client/templates/includes/reactionsEditor.pug b/client/templates/includes/reactionsEditor.pug
index b27791913b..c3b6e5b7ef 100644
--- a/client/templates/includes/reactionsEditor.pug
+++ b/client/templates/includes/reactionsEditor.pug
@@ -1,78 +1,117 @@
-div#reactions-editor.card.card-body
+div#reactions-editor.card
- div
+ div.card-header.pb-0
- h3.inline
- div
- div.inline Reactions
+ h3.inline.mr-3 Reactions
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-reaction", data-hook="collapse") +
+ div.inline.mr-3
- div.collapse(id="collapse-reaction" data-hook="reactions-list-container")
+ ul.nav.nav-tabs.card-header-tabs(id="reactions-tabs")
- p
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="reactions-edit-tab" data-toggle="tab" href="#edit-reactions") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="reactions-view-tab" data-toggle="tab" href="#view-reactions") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-reaction" data-hook="collapse") +
+
+ div.card-body
+
+ p.mb-0
| A process that transforms a set of Variables (reactants) into a set of Variables (products) at a rate set by a Parameter. Select from the given reaction templates, or use the custom types. The symbol represents null or empty set.
- div.row
- div.col-md-7.container-part: table.table
- thead: tr
- th(scope="col") Edit
- th(scope="col")
- div
- div.inline Name
+ div.collapse.tab-content(id="collapse-reaction" data-hook="reactions-list-container")
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
-
- th(scope="col") Summary
- th(scope="col")
- div
- div.inline Annotation
+ div.tab-pane.active(id="edit-reactions" data-hook="edit-reactions")
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+ div.row.mb-3
+
+ div.col-md-7.container-part
+
+ hr
- th(scope="col") Remove
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-md-2: h6.align-bottom Edit
+
+ div.col-md-2
- tbody(data-hook="reaction-list")
+ h6.inline Name
- div.col-md-5.container-part(data-hook="reaction-details-container")
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
- div(data-hook="massaction-message"): p.text-info To add a mass action reaction the model must have at least one parameter
-
- div(data-hook="process-component-error"): p.text-danger A model must have at least one reaction, event, or rule
-
- div.dropdown.inline
-
- button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addReactionBtn(
- data-hook="add-reaction-full",
- data-toggle="dropdown",
- aria-haspopup="true",
- aria-expanded="false",
- type="button"
- ) Add Reaction
-
- ul.dropdown-menu(aria-labelledby="addReactionBtn")
- li.dropdown-item(data-hook="creation") Creation Reaction
- li.dropdown-item(data-hook="destruction") Destruction Reaction
- li.dropdown-item(data-hook="change") Transformation Reaction
- li.dropdown-item(data-hook="dimerization") Dimerization Reaction
- li.dropdown-item(data-hook="merge") Merge Reaction
- li.dropdown-item(data-hook="split") Split Reaction
- li.dropdown-item(data-hook="four") Four Reaction
- li.dropdown-divider
- li.dropdown-item(data-hook="custom-massaction") Custom mass action
- li.dropdown-item(data-hook="custom-propensity") Custom propensity
-
- div.dropdown.inline
-
- button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addReactionBtn(
- data-hook="add-reaction-partial",
- data-toggle="dropdown",
- aria-haspopup="true",
- aria-expanded="false",
- type="button"
- ) Add Reaction
-
- ul.dropdown-menu(aria-labelledby="addReactionBtn")
- li.dropdown-item(data-hook="custom-propensity") Custom propensity
-
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-reactions") Save Reactions
+ div.col-md-3: h6 Summary
+
+ div.col-md-3
+
+ div.inline
+
+ h6 Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-md-2: h6 Remove
+
+ div.mt-3(data-hook="edit-reaction-list")
+
+ div.col-md-5.container-part(data-hook="reaction-details-container")
+
+ div(data-hook="massaction-message"): p.text-info To add a mass action reaction the model must have at least one parameter
+
+ div.component-valid(data-hook="process-component-error"): p.text-danger A model must have at least one reaction, event, or rule
+
+ div.dropdown.inline
+
+ button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addReactionBtn(
+ data-hook="add-reaction-full",
+ data-toggle="dropdown",
+ aria-haspopup="true",
+ aria-expanded="false",
+ type="button"
+ ) Add Reaction
+
+ ul.dropdown-menu(aria-labelledby="addReactionBtn")
+ li.dropdown-item(data-hook="creation") Creation Reaction
+ li.dropdown-item(data-hook="destruction") Destruction Reaction
+ li.dropdown-item(data-hook="change") Transformation Reaction
+ li.dropdown-item(data-hook="dimerization") Dimerization Reaction
+ li.dropdown-item(data-hook="merge") Merge Reaction
+ li.dropdown-item(data-hook="split") Split Reaction
+ li.dropdown-item(data-hook="four") Four Reaction
+ li.dropdown-divider
+ li.dropdown-item(data-hook="custom-massaction") Custom mass action
+ li.dropdown-item(data-hook="custom-propensity") Custom propensity
+
+ div.dropdown.inline
+
+ button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addReactionBtn(
+ data-hook="add-reaction-partial",
+ data-toggle="dropdown",
+ aria-haspopup="true",
+ aria-expanded="false",
+ type="button"
+ ) Add Reaction
+
+ ul.dropdown-menu(aria-labelledby="addReactionBtn")
+ li.dropdown-item(data-hook="custom-propensity") Custom propensity
+
+ div.tab-pane(id="view-reactions" data-hook="view-reactions")
+
+ hr
+
+ div.mx-1.row.head
+
+ div.col-md-2: h6 Name
+
+ div.col-md-3: h6 Summary
+
+ div.col-md-3: h6 Rate/Propensity
+
+ div.col-md-2(data-hook="reaction-types-header"): h6 Active in Types
+
+ div.col-md-2(data-hook="reaction-annotation-header"): h6 Annotation
+
+ div.mt-3(data-hook="view-reaction-list")
diff --git a/client/templates/includes/reactionsViewer.pug b/client/templates/includes/reactionsViewer.pug
deleted file mode 100644
index 2ad0a5bb15..0000000000
--- a/client/templates/includes/reactionsViewer.pug
+++ /dev/null
@@ -1,24 +0,0 @@
-div#reactions-viewer.card.card-body
-
- div
-
- h3.inline Reactions
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-reactions", data-hook="collapse") -
-
- div.collapse(class="show", id="collapse-reactions")
-
- table.table
- thead
- tr
- th.col-md-3-view(scope="col") Name
- th.col-md-3-view(scope="col") Summary
- th.col-md-6-view(scope="col") Rate/Propensity
- if this.collection.parent.is_spatial
- th.col-md-3-view(scope="col") Active in Types
- if this.containsMdlWithAnn
- th.col-md-3-view(scope="col") Annotation
-
- tbody(data-hook="reaction-list")
-
- if this.collection.parent.for === "edit"
- button.btn.btn-outline-primary.box-shadow(data-hook="edit-reactions") Edit Reactions
diff --git a/client/templates/includes/ruleEditor.pug b/client/templates/includes/ruleEditor.pug
index 7065291d4e..97cfd2c051 100644
--- a/client/templates/includes/ruleEditor.pug
+++ b/client/templates/includes/ruleEditor.pug
@@ -1,67 +1,109 @@
-div#rules-editor.card.card-body
+div#rules-editor.card
- div
+ div.card-header.pb-0
- h3.inline Rules
+ h3.inline.mr-3 Rules
+
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="rules-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="rules-edit-tab" data-toggle="tab" href="#edit-rules") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="rules-view-tab" data-toggle="tab" href="#view-rules") View
button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-rules", data-hook="collapse") +
- div.collapse(id="collapse-rules" data-hook="rules-list-container")
- p
+ div.card-body
+ p.mb-0
| Equations that determine the value (assignment rule) or rates of change (rate rule) of Variables or Parameter.
- table.table
+ div.collapse.tab-content(id="collapse-rules" data-hook="rules-list-container")
+
+ div.tab-pane.active(id="edit-rules" data-hook="edit-rules")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-2
+
+ h6.inline Name
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+
+ div.col-sm-2
+
+ h6.inline Type
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.type)
+
+ div.col-sm-2
+
+ h6.inline Target
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.variable)
+
+ div.col-sm-2
+
+ h6.inline Formula
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.expression)
+
+ div.col-sm-2
+
+ h6.inline Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-sm-2
+
+ h6 Remove
- thead
+ div.my-3(data-hook="edit-rule-list-container")
- tr
+ div.dropdown
- th(scope="col")
- div
- div.inline Name
+ button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addRuleBtn(
+ data-hook="add-rule",
+ data-toggle="dropdown",
+ aria-haspopup="true",
+ aria-expanded="false",
+ type="button"
+ ) Add Rule
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+ ul.dropdown-menu(aria-labelledby="addRuleBtn")
+ li.dropdown-item(data-hook="rate-rule" data-name="Rate Rule") Rate Rule
+ li.dropdown-item(data-hook="assignment-rule" data-name="Assignment Rule") Assignment Rule
- th(scope="col")
- div
- div.inline Type
+ div.tab-pane(id="view-rules" data-hook="view-rules")
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.type)
+ hr
- th(scope="col")
- div
- div.inline Target
+ div.mx-1.row.head.align-items-baseline
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.variable)
+ div.col-sm-2
- th(scope="col")
- div
- div.inline Formula
+ h6.inline Name
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.expression)
+ div.col-sm-2
- th(scope="col")
- div
- div.inline Annotation
+ h6.inline Type
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+ div.col-sm-2
- th(scope="col") Remove
+ h6.inline Target
- tbody(data-hook="rule-list-container")
+ div.col-sm-4
- div.dropdown.inline
+ h6.inline Formula
- button.btn.btn-outline-primary.dropdown-toggle.box-shadow#addRuleBtn(
- data-hook="add-rule",
- data-toggle="dropdown",
- aria-haspopup="true",
- aria-expanded="false",
- type="button"
- ) Add Rule
+ div.col-sm-2(data-hook="rules-annotation-header")
- ul.dropdown-menu(aria-labelledby="addRuleBtn")
- li.dropdown-item(data-hook="rate-rule" data-name="Rate Rule") Rate Rule
- li.dropdown-item(data-hook="assignment-rule" data-name="Assignment Rule") Assignment Rule
+ h6.inline Annotation
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-rules") Save Rules
+ div.mt-3(data-hook="view-rules-list-container")
diff --git a/client/templates/includes/rulesViewer.pug b/client/templates/includes/rulesViewer.pug
deleted file mode 100644
index 1451df8482..0000000000
--- a/client/templates/includes/rulesViewer.pug
+++ /dev/null
@@ -1,23 +0,0 @@
-div#rules-viewer.card.card-body
-
- div
-
- h3.inline Rules
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-rules", data-hook="collapse") -
-
- div.collapse(class="show", id="collapse-rules")
-
- table.table
- thead
- tr
- th.col-md-3-view(scope="col") Name
- th.col-md-3-view(scope="col") Type
- th.col-md-3-view(scope="col") Target
- th.col-md-3-view(scope="col") Formula
- if this.containsMdlWithAnn
- th.col-md-3-view(scope="col") Annotation
-
- tbody(data-hook="rules-list")
-
- if this.collection.parent.for === "edit"
- button.btn.btn-outline-primary.box-shadow(data-hook="edit-rules") Edit Rules
diff --git a/client/templates/includes/sbmlComponentEditor.pug b/client/templates/includes/sbmlComponentEditor.pug
index 7d4ec4423d..84ac3d3fb5 100644
--- a/client/templates/includes/sbmlComponentEditor.pug
+++ b/client/templates/includes/sbmlComponentEditor.pug
@@ -1,34 +1,75 @@
-div#sbml-components.card.card-body
+div#sbml-components.card
- div
+ div.card-header.pb-0
h3.inline SBML Components
+
button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-sbml-component", data-hook="collapse") +
div.collapse(id="collapse-sbml-component")
- div
+ div.card-body
+
+ div#function-definitions.card
+
+ div.card-header.pb-0
+
+ h5.inline.mr-3 Function Definitions
+
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="function-definitions-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="function-definitions-edit-tab" data-toggle="tab" href="#edit-function-definitions") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="function-definitions-view-tab" data-toggle="tab" href="#view-function-definitions") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-function-definitions" data-hook="collapse-function-definitions") -
+
+ div.card-body
+ p.mb-0
+ | Object representation defining an evaluable function to be used during simulation.
+
+ div.collapse.tab-content(class="show" id="collapse-function-definitions")
+
+ div.tab-pane.active(id="edit-function-definitions" data-hook="edit-function-definitions")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-8
+
+ h6 Signature
+
+ div.col-sm-2
+
+ h6.inline Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-sm-2
+
+ h6 Remove
+
+ div.my-3(data-hook="edit-function-definition-list")
+
+ div.tab-pane(id="view-function-definitions" data-hook="view-function-definitions")
- h5.inline Function Definitions
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-function-definitions", data-hook="collapse-function-definitions") -
+ hr
- div.collapse(class="show", id="collapse-function-definitions")
+ div.mx-1.row.head.align-items-baseline
- table.table
+ div.col-sm-10
- thead
-
- tr
-
- th(scope="col") Signature
+ h6 Signature
- th(scope="col")
- div
- div.inline Annotation
+ div.col-sm-2(data-hook="function-definition-annotation-header")
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+ h6.inline Annotation
- if(!this.viewMode)
- th(scope="col") Remove
-
- tbody(data-hook="function-definition-list")
\ No newline at end of file
+ div.my-3(data-hook="view-function-definition-list")
diff --git a/client/templates/includes/spatialSpeciesEditor.pug b/client/templates/includes/spatialSpeciesEditor.pug
index 4adc51dfcb..ae24b9fc88 100644
--- a/client/templates/includes/spatialSpeciesEditor.pug
+++ b/client/templates/includes/spatialSpeciesEditor.pug
@@ -1,45 +1,85 @@
-div#species-editor.card.card-body
+div#species-editor.card
- div
+ div.card-header.pb-0
- h3.inline Variables
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-species", data-hook="collapse") -
+ h3.inline.mr-3 Variables
- div.collapse(class="show", id="collapse-species")
+ div.inline.mr-3
- p
+ ul.nav.nav-tabs.card-header-tabs(id="species-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="species-edit-tab" data-toggle="tab" href="#edit-species") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="species-view-tab" data-toggle="tab" href="#view-species") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-species" data-hook="collapse") -
+
+ div.card-body
+ p.mb-0
| Time varying quantities of interest; e.g.: concentrations, populations, or counts of biochemical species, epidemological compartments, chemicals, proteins, or molecules.
- table.table
- thead
- tr
- th(scope="col") Name
- th(scope="col") Diffusion Constant
- th(scope="col") Restricted to Types:
- th(scope="col") Remove
-
- tbody(data-hook="specie-list")
+ div.collapse.tab-content(class="show" id="collapse-species" data-hook="species-list-container")
+
+ div.tab-pane.active(id="edit-species" data-hook="edit-species")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-2
+
+ h6.inline Name
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+
+ div.col-sm-2
+
+ h6.inline Diffusion Constant
+
+ div.col-sm-4
+
+ h6.inline Restricted to Types:
+
+ div.col-sm-2
+
+ h6.inline Annotation
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
+
+ div.col-sm-2
+
+ h6.inline Remove
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.remove)
+
+ div.my-3(data-hook="edit-specie-list")
+
+ button.btn.btn-outline-primary.box-shadow(data-hook="add-species") Add Variable
+
+ div.tab-pane(id="view-species" data-hook="view-species")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-2
+
+ h6.inline Name
- table.table
- thead
- tr
- th(scope="col", colspan="3")
+ div.col-sm-2
- div
+ h6.inline Diffusion Constant
- div.inline Model Mode
+ div.col-sm-6
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.spatialSpeciesMode)
+ h6.inline Restricted to Types:
- tbody
- tr
- td
- input(type="radio", name="species-mode", data-hook="all-continuous", data-name="continuous")
- | Concentration
- td
- input(type="radio", name="species-mode", data-hook="all-discrete", data-name="discrete")
- | Population
+ div.col-sm-2(data-hook="species-annotation-header")
- button.btn.btn-outline-primary.box-shadow(data-hook="add-species") Add Variable
+ h6.inline Annotation
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-species") Save Variables
\ No newline at end of file
+ div.my-3(data-hook="view-specie-list")
diff --git a/client/templates/includes/speciesEditor.pug b/client/templates/includes/speciesEditor.pug
index 9162e167f8..0c0ae48995 100644
--- a/client/templates/includes/speciesEditor.pug
+++ b/client/templates/includes/speciesEditor.pug
@@ -1,92 +1,89 @@
-div#species-editor.card.card-body
+div#species-editor.card
- div
+ div.card-header.pb-0
- h3.inline Variables
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-species", data-hook="collapse") -
+ h3.inline.mr-3 Variables
- div.collapse(class="show", id="collapse-species" data-hook="species-list-container")
- p
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="species-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="species-edit-tab" data-toggle="tab" href="#edit-species") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="species-view-tab" data-toggle="tab" href="#view-species") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-species" data-hook="collapse") -
+
+ div.card-body
+ p.mb-0
| Time varying quantities of interest; e.g.: concentrations, populations, or counts of biochemical species, epidemological compartments, chemicals, proteins, or molecules.
- table.table
- thead
- tr
- th(scope="col")
- div
- div.inline Name
+ div.collapse.tab-content(class="show" id="collapse-species" data-hook="species-list-container")
+
+ div.tab-pane.active(id="edit-species" data-hook="edit-species")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ h6.inline Name
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+
+ div.col-sm-5
+
+ h6.inline Initial Condition
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.initialValue)
+
+ div.col-sm-2
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.name)
+ h6.inline Annotation
- th(scope="col")
- div
- div.inline Initial Condition
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.initialValue)
+ div.col-sm-2
- th(scope="col")
- div
- div.inline Annotation
+ h6.inline Remove
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.annotation)
-
- th(scope="col")
- div
- div.inline Remove
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.remove)
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.remove)
-
- tbody(data-hook="specie-list")
+ div.my-3(data-hook="edit-specie-list")
- table.table
- thead
- tr
- th(scope="col", colspan="3")
+ div(data-hook="species-collection-error"): p.text-danger A model must have at least one variable
- div
+ button.btn.btn-outline-primary.box-shadow(data-hook="add-species") Add Variable
- div.inline Variable Mode
+ div.tab-pane(id="view-species" data-hook="view-species")
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.speciesMode)
+ hr
- tbody
- tr
- td
- input(type="radio", name="species-mode", data-hook="all-continuous", data-name="continuous")
- | Concentration
- td
- input(type="radio", name="species-mode", data-hook="all-discrete", data-name="discrete")
- | Population
- td
- input(type="radio", name="species-mode", data-hook="advanced", data-name="dynamic")
- | Hybrid Concentration/Population
-
- div.collapse(data-hook="advanced-species")
+ div.mx-1.row.head.align-items-baseline
- table.table
+ div.col-sm-2
- thead
+ h6.inline Name
- tr
+ div.col-sm-2
- th(scope="col") Name
+ h6.inline Initial Condition
- th(scope="col")
- div
- div.inline Mode
+ div.col-sm-2
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.mode)
-
- th(scope="col" colspan="2")
- div
- div.inline Switching Settings (Hybrid Only)
+ h6.inline Mode
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.switchValue)
+ div.col-sm-4(data-hook="species-switching-header")
- tbody(data-hook="edit-species-mode")
+ h6.inline Switch Tolerance/Minimum Value for Switching
- div(data-hook="species-collection-error"): p.text-danger A model must have at least one variable
+ div.col-sm-2(data-hook="species-annotation-header")
- button.btn.btn-outline-primary.box-shadow(data-hook="add-species") Add Variable
+ h6.inline Annotation
- button.btn.btn-outline-primary.box-shadow.ml-2(data-hook="save-species") Save Variables
+ div.my-3(data-hook="view-specie-list")
diff --git a/client/templates/includes/speciesViewer.pug b/client/templates/includes/speciesViewer.pug
deleted file mode 100644
index f2ad8b30e9..0000000000
--- a/client/templates/includes/speciesViewer.pug
+++ /dev/null
@@ -1,28 +0,0 @@
-div#species-viewer.card.card-body
-
- div
-
- h3.inline Variables
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-species", data-hook="collapse") -
-
- div.collapse(class="show", id="collapse-species")
-
- table.table
- thead
- tr
- th.col-md-3-view(scope="col") Name
- if this.collection.parent.is_spatial
- th.col-md-3-view(scope="col") Diffusion Constant
- th.col-md-3-view(scope="col") Restricted to Types:
- else
- th.col-md-3-view(scope="col") Initial Condition
- th.col-md-3-view(scope="col") Mode
- if this.collection.parent.defaultMode === "dynamic"
- th.col-md-3-view(scope="col") Switch Tolerance/Minimum Value for Switching
- if this.containsMdlWithAnn
- th.col-md-3-view(scope="col") Annotation
-
- tbody(data-hook="specie-list")
-
- if this.collection.parent.for === "edit"
- button.btn.btn-outline-primary.box-shadow(data-hook="edit-species") Edit Variables
diff --git a/client/templates/includes/timespanSettings.pug b/client/templates/includes/timespanSettings.pug
index 35e7ad3b88..34401ab4e3 100644
--- a/client/templates/includes/timespanSettings.pug
+++ b/client/templates/includes/timespanSettings.pug
@@ -1,33 +1,113 @@
-div#preview-settings.card.card-body
+div#preview-settings.card
- div
+ div.card-header.pb-0
- h3.inline Timespan
+ h3.inline.mr-3 Timespan
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-preview-settings", data-hook="collapse") -
+ div.inline.mr-3
- div.collapse(class="show", id="collapse-preview-settings" data-hook="timespan-container")
+ ul.nav.nav-tabs.card-header-tabs(id="timespan-tabs")
- p Timespan settings are used for the preview and all workflows created using this model.
+ li.nav-item
- table.table
+ a.nav-link.tab.active(data-hook="timespan-edit-tab" data-toggle="tab" href="#edit-timespan") Edit
- thead
+ li.nav-item
- tr
+ a.nav-link.tab(data-hook="timespan-view-tab" data-toggle="tab" href="#view-timespan") View
- th(scope="col") Simulation Time
+ button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-preview-settings" data-hook="collapse") -
- th(scope="col")
- div
- div.inline Sample Frequency
+ div.card-body
- div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.timeUnits)
+ p.mb-0
+ | Timespan settings are used for the preview and all workflows created using this model.
- tbody
+ div.collapse.tab-content(class="show" id="collapse-preview-settings" data-hook="timespan-container")
- tr
+ div.tab-pane.active(id="edit-timespan" data-hook="edit-timespan")
- td: div(data-hook="preview-time")
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ h6 Simulation Time
+
+ div.col-sm-3
+
+ h6.inline Sample Frequency
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.timeUnits)
+
+ div.col-sm-6
+
+ if this.parent.model.is_spatial
+ h6 Timestep Size
+
+ div.mx-1.my-3.row
+
+ div.col-sm-3(data-hook="preview-time")
+
+ div.col-sm-3(data-hook="time-units")
+
+ div.col-sm-6
+
+ if this.parent.model.is_spatial
+ div
+
+ div.row
+
+ div.col-sm-3
+
+ span.inline 1e-5
+
+ div.col-sm-8
+
+ span.mr-2.inline Current Value:
+
+ div.inline(data-hook="timestep-size-value")
+
+ div.col-sm-1.d-flex.justify-content-end
+
+ span.inline 1
+
+ input.custom-range(
+ type="range"
+ min="1e-5"
+ max="1"
+ step="1e-5"
+ value=this.model.timestepSize
+ data-hook="timestep-size-slider"
+ )
+
+ div.tab-pane(id="view-timespan" data-hook="view-timespan")
+
+ hr
+
+ div.mx-1.row.head.align-items-baseline
+
+ div.col-sm-3
+
+ h6 Simulation Time
+
+ div.col-sm-3
+
+ h6 Sample Frequency
+
+ div.col-sm-3
+
+ if this.parent.model.is_spatial
+ h6 Timestep Size
+
+ div.mx-1.my-3.row
+
+ div.col-sm-3(data-hook="view-end-sim")="0 to " + this.model.endSim
+
+ div.col-sm-3(data-hook="view-time-step")=this.model.timeStep
+
+ if this.parent.model.is_spatial
+ div.col-sm-6(data-hook="view-timestep-size")=this.model.timestepSize
+
- td: div(data-hook="time-units")
diff --git a/client/templates/includes/viewEventAssignment.pug b/client/templates/includes/viewEventAssignment.pug
new file mode 100644
index 0000000000..dc2a1867fc
--- /dev/null
+++ b/client/templates/includes/viewEventAssignment.pug
@@ -0,0 +1,14 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-3
+
+ div.pl-2=this.model.variable.name
+
+ div.col-sm-7
+
+ div=this.model.expression
diff --git a/client/templates/includes/viewEventAssignments.pug b/client/templates/includes/viewEventAssignments.pug
deleted file mode 100644
index 6d9f62e879..0000000000
--- a/client/templates/includes/viewEventAssignments.pug
+++ /dev/null
@@ -1,5 +0,0 @@
-tr
-
- td=this.model.variable.name
-
- td=this.model.expression
\ No newline at end of file
diff --git a/client/templates/includes/viewEvents.pug b/client/templates/includes/viewEvents.pug
index a26dfb151f..ef20893766 100644
--- a/client/templates/includes/viewEvents.pug
+++ b/client/templates/includes/viewEvents.pug
@@ -1,45 +1,51 @@
-tr
+div.mx-1
- td: div.name=this.model.name
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td=this.model.triggerExpression
+ div.row
- td: div(data-hook="assignment-viewer")
+ div.col-sm-2
- td
+ div.pl-2=this.model.name
- div="Delay: "+this.delay
+ div.col-sm-2=this.model.triggerExpression
- div="Priority: "+this.model.priority
+ div.col-sm-4(data-hook="assignment-viewer")
- div
+ div.col-sm-2
- span.checkbox(for="initial-value") Initial Value:
+ div="Delay: "+this.delay
- input(type="checkbox", id="initial-value", data-hook="event-trigger-init-value" disabled)
+ div="Priority: "+this.model.priority
- div
+ div
- span.checkbox(for="persistent") Persistent:
+ span.checkbox(for="initial-value") Initial Value:
- input(type="checkbox", id="persistent", data-hook="event-trigger-persistent" disabled)
+ input(type="checkbox", id="initial-value", data-hook="event-trigger-init-value" disabled)
- div.event-adv-header Use Values From
+ div
- div
+ span.checkbox(for="persistent") Persistent:
- input(type="radio", id="trigger-time", name="use-values-from" data-hook="trigger-time" disabled)
+ input(type="checkbox", id="persistent", data-hook="event-trigger-persistent" disabled)
- span.inline.horizontal-space(for="trigger-time") Trigger Time
+ div.event-adv-header Use Values From
- div
+ div
- input(type="radio", id="assignment-time", name="use-values-from" data-hook="assignment-time" disabled)
+ input(type="radio", id="trigger-time", name="view-use-values-from" data-hook="view-trigger-time" disabled)
- span.inline.horizontal-space(for="assignment-time") Assignment Time
+ span.inline.horizontal-space(for="trigger-time") Trigger Time
- if this.model.annotation
- td: div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div
- if this.parent.containsMdlWithAnn && !this.model.annotation
- td: div
+ input(type="radio", id="assignment-time", name="view-use-values-from" data-hook="view-assignment-time" disabled)
+
+ span.inline.horizontal-space(for="assignment-time") Assignment Time
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/includes/viewFunctionDefinition.pug b/client/templates/includes/viewFunctionDefinition.pug
new file mode 100644
index 0000000000..cdfc4ac78a
--- /dev/null
+++ b/client/templates/includes/viewFunctionDefinition.pug
@@ -0,0 +1,15 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-10
+
+ div.pl-2=this.model.signature
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/includes/viewParameters.pug b/client/templates/includes/viewParameters.pug
index a4cae60444..6e338ecbea 100644
--- a/client/templates/includes/viewParameters.pug
+++ b/client/templates/includes/viewParameters.pug
@@ -1,10 +1,19 @@
-tr
- td=this.model.name
+div.mx-1
- td=this.model.expression
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- if this.model.annotation
- td: div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.row
- if this.parent.containsMdlWithAnn && !this.model.annotation
- td: div
+ div.col-sm-3
+
+ div.pl-2=this.model.name
+
+ div.col-sm-7
+
+ div=this.model.expression
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/includes/viewReactions.pug b/client/templates/includes/viewReactions.pug
index 582e48dae1..21be6b3275 100644
--- a/client/templates/includes/viewReactions.pug
+++ b/client/templates/includes/viewReactions.pug
@@ -1,15 +1,24 @@
-tr
- td=this.model.name
+div.mx-1
- td: div(data-hook="summary")
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td=this.rate
+ div.row.align-items-baseline
- if this.model.collection.parent.is_spatial
- td: div=this.types.join(', ')
+ div.col-md-2
- if this.model.annotation
- td: div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.pl-2=this.model.name
- if this.parent.containsMdlWithAnn && !this.model.annotation
- td: div
+ div.col-md-3(data-hook="summary")
+
+ div.col-md-3=this.rate
+
+ if this.model.collection.parent.is_spatial
+ div.col-md-2(data-hook="reaction-types")
+
+ div=this.types.join(', ')
+
+ div.col-md-2(data-hook="reaction-annotation-header")
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation)
diff --git a/client/templates/includes/viewRules.pug b/client/templates/includes/viewRules.pug
index f4b039523b..30bacfe4dd 100644
--- a/client/templates/includes/viewRules.pug
+++ b/client/templates/includes/viewRules.pug
@@ -1,14 +1,19 @@
-tr
- td=this.model.name
+div.mx-1
- td=this.model.type
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td=this.model.variable.name
+ div.row
- td=this.model.expression
+ div.col-sm-2=this.model.name
- if this.model.annotation
- td: div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.col-sm-2=this.model.type
- if this.parent.containsMdlWithAnn && !this.model.annotation
- td: div
+ div.col-sm-2=this.model.variable.name
+
+ div.col-sm-4=this.model.expression
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/includes/viewSpatialSpecies.pug b/client/templates/includes/viewSpatialSpecies.pug
new file mode 100644
index 0000000000..4af4396fa9
--- /dev/null
+++ b/client/templates/includes/viewSpatialSpecies.pug
@@ -0,0 +1,23 @@
+div.mx-1
+
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
+
+ div.row
+
+ div.col-sm-2
+
+ div.pl-2=this.model.name
+
+ div.col-sm-2
+
+ div=this.model.diffusionConst
+
+ div.col-sm-6
+
+ div=this.types.join(", ")
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/includes/viewSpecies.pug b/client/templates/includes/viewSpecies.pug
index e5ab763ec9..a792c44923 100644
--- a/client/templates/includes/viewSpecies.pug
+++ b/client/templates/includes/viewSpecies.pug
@@ -1,21 +1,27 @@
-tr
- td=this.model.name
+div.mx-1
- if this.model.collection.parent.is_spatial
- td=this.model.diffusionConst
+ if(this.model.collection.indexOf(this.model) !== 0)
+ hr
- td=this.types.join(", ")
- else
- td=this.model.value
+ div.row
- td=this.model.mode
+ div.col-sm-2
- if this.model.collection.parent.defaultMode === 'dynamic'
- td=this.switchingValWithLabel
+ div.pl-2=this.model.name
- if this.model.annotation
- td: div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
+ div.col-sm-2
- if this.parent.containsMdlWithAnn && !this.model.annotation
- td: div
-
\ No newline at end of file
+ div=this.model.value
+
+ div.col-sm-2
+
+ div=this.model.mode
+
+ if this.model.mode === "dynamic"
+ div.col-sm-4
+ div=this.switchingValWithLabel
+
+ div.col-sm-2
+
+ if this.model.annotation
+ div.tooltip-icon-large(data-hook="annotation-tooltip" data-html="true" data-toggle="tooltip" title=this.model.annotation || "Click 'Add' to add an annotation")
diff --git a/client/templates/pages/modelEditor.pug b/client/templates/pages/modelEditor.pug
index eeb3660d85..31cf797e9d 100644
--- a/client/templates/pages/modelEditor.pug
+++ b/client/templates/pages/modelEditor.pug
@@ -26,6 +26,26 @@ section.page
ol.breadcrumb
li.breadcrumb-item.active(aria-current="page")=this.model.name
+ div.card
+
+ div.card-header.pb-0
+
+ h3.inline Model Mode
+
+ div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.modelMode)
+
+ div.card-body
+ div.row
+ div.col-sm-4
+ input.mr-2(type="radio" name="default-mode" data-hook="all-continuous" data-name="continuous")
+ span Concentration
+ div.col-sm-4
+ input.mr-2(type="radio" name="default-mode" data-hook="all-discrete" data-name="discrete")
+ span Population
+ div.col-sm-4(data-hook="advaced-model-mode")
+ input.mr-2(type="radio" name="default-mode" data-hook="advanced" data-name="dynamic")
+ span Hybrid Concentration/Population
+
div(data-hook="domain-viewer-container")
div(data-hook="species-editor-container")
@@ -36,9 +56,9 @@ section.page
div(data-hook="reactions-editor-container")
- div.card.card-body(data-hook="model-editor-advanced-container")
+ div.card(data-hook="model-editor-advanced-container")
- div
+ div.card-header.pb-0
h3.inline Advanced
@@ -46,26 +66,52 @@ section.page
div.collapse(id="me-advanced-section", data-hook="me-advanced-section")
- div(data-hook="events-editor-container")
+ div.card-body
- div(data-hook="rules-editor-container")
+ div(data-hook="events-editor-container")
- div(data-hook="sbml-component-container")
+ div(data-hook="rules-editor-container")
- div.card.card-body.collapse.show(data-hook="system-volume-container")
+ div(data-hook="sbml-component-container")
- div
+ div.card.collapse.show(data-hook="system-volume-container")
- h3.inline System Volume
- button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-system-volume", data-hook="collapse-system-volume") +
+ div.card-header.pb-0
- div.collapse(id="collapse-system-volume" data-hook="system-volume-section")
-
- p System volume affects custom propensities or stochastic reactions with two reactants. The volume sets the implicit parameter 'vol' which can be used in custom propensity functions. A single well-mixed volume is assumed. Compartments are not currently supported.
+ h3.inline.mr-3 System Volume
+
+ div.inline.mr-3
+
+ ul.nav.nav-tabs.card-header-tabs(id="volume-tabs")
+
+ li.nav-item
+
+ a.nav-link.tab.active(data-hook="volume-edit-tab" data-toggle="tab" href="#edit-system-volume") Edit
+
+ li.nav-item
+
+ a.nav-link.tab(data-hook="volume-view-tab" data-toggle="tab" href="#view-system-volume") View
+
+ button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-system-volume", data-hook="collapse-system-volume") +
+
+ div.card-body
+
+ p.mb-0
+ | System volume affects custom propensities or stochastic reactions with two reactants. The volume sets the implicit parameter 'vol' which can be used in custom propensity functions. A single well-mixed volume is assumed. Compartments are not currently supported. In most cases this should not be changed. please review your model requirements carefully before changing this property.
+
+ div.collapse.tab-content(id="collapse-system-volume" data-hook="system-volume-section")
+
+ div.tab-pane.active(id="edit-system-volume" data-hook="edit-system-volume")
+
+ hr
+
+ div(data-hook="edit-volume")
+
+ div.tab-pane(id="view-system-volume" data-hook="view-system-volume")
- hr
+ hr
- div(data-hook="volume")
+ div(data-hook="view-volume")
div(data-hook="model-settings-container")
diff --git a/client/tooltips.js b/client/tooltips.js
index 4c426230a2..42e8c77241 100644
--- a/client/tooltips.js
+++ b/client/tooltips.js
@@ -17,6 +17,13 @@ along with this program. If not, see .
*/
module.exports = {
+ modelEditor: {
+ modelMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+
+ "using discrete (integer count) values.
Hybrid Concentration/Population - Allows a variables to be represented using continuous and/or discrete values.",
+
+ spatialModelMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+
+ "using discrete (integer count) values."
+ },
speciesEditor: {
name: "Unique identifier for Variable. Cannot share a name with other model components.",
@@ -26,12 +33,6 @@ module.exports = {
remove: "A variables may only be removed if it is not a part of any reaction, event assignment, or rule.",
- speciesMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+
- "using discrete (integer count) values.
Hybrid Concentration/Population - Allows a variables to be represented using continuous and/or discrete values.",
-
- spatialSpeciesMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+
- "using discrete (integer count) values.",
-
mode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+
"using discrete (integer count) values.
Hybrid Concentration/Population - Allows a variables to be represented using continuous and/or discrete values.",
diff --git a/client/views/component-types.js b/client/views/component-types.js
index d5856b2693..212ef27413 100644
--- a/client/views/component-types.js
+++ b/client/views/component-types.js
@@ -46,5 +46,8 @@ module.exports = View.extend({
let index = this.parent.model.types.indexOf(typeID);
this.parent.model.types.splice(index, 1);
}
+ if(this.parent.modelType === "species") {
+ this.parent.model.trigger('change');
+ }
}
});
\ No newline at end of file
diff --git a/client/views/edit-advanced-specie.js b/client/views/edit-advanced-specie.js
deleted file mode 100644
index 33c6ac446a..0000000000
--- a/client/views/edit-advanced-specie.js
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-var tests = require('./tests');
-//views
-var View = require('ampersand-view');
-var SelectView = require('ampersand-select-view');
-var InputView = require('./input');
-//templates
-var template = require('../templates/includes/editAdvancedSpecie.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'change [data-hook=switching-tol]' : 'setSwitchingType',
- 'change [data-hook=switching-min]' : 'setSwitchingType',
- 'change [data-hook=specie-mode]' : 'setSpeciesMode',
- },
- initialize: function () {
- View.prototype.initialize.apply(this, arguments);
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- var optionDict = {"continuous":"Concentration", "discrete":"Population", "dynamic":"Hybrid Concentration/Population"}
- var modeSelectView = new SelectView({
- label: '',
- name: 'mode',
- required: true,
- idAttributes: 'cid',
- options: ['Concentration','Population','Hybrid Concentration/Population'],
- value: optionDict[this.model.mode],
- });
- app.registerRenderSubview(this, modeSelectView, "specie-mode")
- if(this.model.isSwitchTol){
- $(this.queryByHook('switching-tol')).prop('checked', true);
- }else{
- $(this.queryByHook('switching-min')).prop('checked', true);
- }
- this.toggleSwitchingSettings();
- this.updateInputValidation();
- },
- update: function () {
- },
- updateValid: function () {
- },
- setSpeciesMode: function (e) {
- var value = e.target.selectedOptions.item(0).text
- var modeDict = {"Concentration":"continuous","Population":"discrete","Hybrid Concentration/Population":"dynamic"}
- this.model.mode = modeDict[value]
- this.model.collection.trigger('update-species', this.model.compID, this.model, false, false);
- this.updateInputValidation();
- this.toggleSwitchingSettings();
- },
- setSwitchingType: function (e) {
- this.model.isSwitchTol = $(this.queryByHook('switching-tol')).is(":checked");
- this.updateInputValidation();
- this.toggleSwitchingSettingsInput();
- },
- updateInputValidation: function () {
- // Update validation requirements and re-run tests for inputSwitchTol.
- // This removes error reporting not using switching tolerance
- let shouldValidateTol = this.model.mode === "dynamic" && this.model.isSwitchTol
- this.inputSwitchTol.required = shouldValidateTol;
- this.inputSwitchTol.tests = shouldValidateTol ? tests.valueTests : []
- this.inputSwitchTol.runTests()
- // Update validation requirements and re-run tests for inputSwitchMin.
- // This removes error reporting when not using minimum value for switching.
- let shouldValidateMin = this.model.mode === "dynamic" && !this.model.isSwitchTol
- this.inputSwitchMin.required = shouldValidateMin;
- this.inputSwitchMin.tests = shouldValidateMin ? tests.valueTests : []
- this.inputSwitchMin.runTests()
- // Add/Remove 'input-invalid' class from inputSwitchTol and inputSwitchMin based on whether
- // the user is using switching tolerance or minimum value for switching
- let tolInput = $(this.queryByHook('switching-tolerance')).find('input')[0]
- let minInput = $(this.queryByHook('switching-threshold')).find('input')[0]
- if(this.model.mode !== "dynamic") {
- $(tolInput).removeClass('input-invalid')
- $(minInput).removeClass('input-invalid')
- }else if(this.model.isSwitchTol){
- $(minInput).removeClass('input-invalid')
- if(this.model.switchTol === "" || isNaN(this.model.switchTol)){
- $(tolInput).addClass('input-invalid')
- }
- }else{
- $(tolInput).removeClass('input-invalid')
- if(this.model.switchMin === "" || isNaN(this.model.switchMin)){
- $(minInput).addClass('input-invalid')
- }
- }
- },
- toggleSwitchingSettingsInput: function () {
- if(this.model.isSwitchTol){
- $(this.queryByHook('switching-threshold')).find('input').prop('disabled', true);
- $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', false);
- }else{
- $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', true);
- $(this.queryByHook('switching-threshold')).find('input').prop('disabled', false);
- }
- },
- toggleSwitchingSettings: function () {
- if(this.model.mode === "dynamic"){
- $(this.queryByHook('switching-tol')).prop('disabled', false);
- $(this.queryByHook('switching-min')).prop('disabled', false);
- this.toggleSwitchingSettingsInput();
- }else{
- $(this.queryByHook('switching-tol')).prop('disabled', true);
- $(this.queryByHook('switching-min')).prop('disabled', true);
- $(this.queryByHook('switching-threshold')).find('input').prop('disabled', true);
- $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', true);
- }
- },
- subviews: {
- inputSwitchTol: {
- hook: 'switching-tolerance',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'switching-tolerance',
- label: '',
- tests: tests.valueTests,
- modelKey: 'switchTol',
- valueType: 'number',
- value: this.model.switchTol,
- });
- },
- },
- inputSwitchMin: {
- hook: 'switching-threshold',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'switching-threshold',
- label: '',
- tests: tests.valueTests,
- modelKey: 'switchMin',
- valueType: 'number',
- value: this.model.switchMin,
- });
- },
- },
- },
-});
\ No newline at end of file
diff --git a/client/views/edit-event-assignment.js b/client/views/edit-event-assignment.js
index 72c4b268d3..8e48f4931f 100644
--- a/client/views/edit-event-assignment.js
+++ b/client/views/edit-event-assignment.js
@@ -24,31 +24,22 @@ var View = require('ampersand-view');
var InputView = require('./input');
var SelectView = require('ampersand-select-view');
//templates
-var template = require('../templates/includes/editEventAssignment.pug');
+var editTemplate = require('../templates/includes/editEventAssignment.pug');
+var viewTemplate = require('../templates/includes/viewEventAssignment.pug');
module.exports = View.extend({
- template: template,
events: {
'click [data-hook=remove]' : 'removeAssignment',
'change [data-hook=event-assignment-variable]' : 'selectAssignmentVariable',
+ 'change [data-hook=event-assignment-expression]' : 'updateViewer'
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
},
render: function () {
+ this.template = this.viewMode ? viewTemplate : editTemplate;
View.prototype.render.apply(this, arguments);
- var options = this.getOptions();
- var variableSelectView = new SelectView({
- label: '',
- name: 'variable',
- required: true,
- idAttributes: 'cid',
- options: options,
- value: this.model.variable.name,
- });
- app.registerRenderSubview(this, variableSelectView, 'event-assignment-variable');
- var inputField = this.queryByHook('event-assignment-Expression').children[0].children[1];
- $(inputField).attr("placeholder", "---No Expression Entered---");
},
update: function () {
},
@@ -62,44 +53,66 @@ module.exports = View.extend({
getOptions: function () {
var species = this.model.collection.parent.collection.parent.species;
var parameters = this.model.collection.parent.collection.parent.parameters;
- var speciesNames = species.map(function (specie) { return specie.name });
- var parameterNames = parameters.map(function (parameter) { return parameter.name });
- return speciesNames.concat(parameterNames);
+ var specs = species.map(function (specie) {
+ return [specie.compID, specie.name]
+ });
+ var params = parameters.map(function (parameter) {
+ return [parameter.compID, parameter.name]
+ });
+ let options = [{groupName: "Variables", options: specs},
+ {groupName: "Parameters", options: params}]
+ return options;
},
selectAssignmentVariable: function (e) {
var species = this.model.collection.parent.collection.parent.species;
var parameters = this.model.collection.parent.collection.parent.parameters;
- var val = e.target.selectedOptions.item(0).text;
+ var val = Number(e.target.value);
var eventVar = species.filter(function (specie) {
- if(specie.name === val) {
+ if(specie.compID === val) {
return specie;
}
});
if(!eventVar.length) {
eventVar = parameters.filter(function (parameter) {
- if(parameter.name === val) {
+ if(parameter.compID === val) {
return parameter;
}
});
}
this.model.variable = eventVar[0];
+ this.updateViewer();
this.model.collection.parent.collection.trigger('change');
},
+ updateViewer: function () {
+ this.model.collection.parent.trigger('change');
+ },
subviews: {
inputAssignmentExpression: {
- hook: 'event-assignment-Expression',
+ hook: 'event-assignment-expression',
prepareView: function (el) {
return new InputView({
parent: this,
required: true,
name: 'event-assignment-expression',
- label: '',
- tests: '',
+ placeholder: "---No Expression Entered---",
modelKey: 'expression',
valueType: 'string',
value: this.model.expression,
});
},
},
+ variableSelectView: {
+ hook: 'event-assignment-variable',
+ prepareView: function (el) {
+ let options = this.getOptions();
+ return new SelectView({
+ name: 'variable',
+ required: true,
+ idAttributes: 'cid',
+ groupOptions: options,
+ value: this.model.variable.compID,
+ });
+ }
+ }
},
});
\ No newline at end of file
diff --git a/client/views/edit-function-definition.js b/client/views/edit-function-definition.js
index 61a3261b45..bb7146befb 100644
--- a/client/views/edit-function-definition.js
+++ b/client/views/edit-function-definition.js
@@ -22,18 +22,20 @@ var modals = require('../modals');
//views
var View = require('ampersand-view');
//templates
-var template = require('../templates/includes/editFunctionDefinition.pug');
+var editTemplate = require('../templates/includes/editFunctionDefinition.pug');
+let viewTemplate = require('../templates/includes/viewFunctionDefinition.pug');
module.exports = View.extend({
- template: template,
events: {
'click [data-hook=remove]' : 'removeFunctionDefinition',
'click [data-hook=edit-annotation-btn]' : 'editAnnotation',
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
},
render: function () {
+ this.template = this.viewMode ? viewTemplate : editTemplate;
View.prototype.render.apply(this, arguments);
$(document).on('hide.bs.modal', '.modal', function (e) {
e.target.remove()
@@ -57,7 +59,7 @@ module.exports = View.extend({
});
okBtn.addEventListener('click', function (e) {
self.model.annotation = input.value.trim();
- self.parent.renderEdirFunctionDefinitionView();
+ self.parent.renderEditFunctionDefinitionView();
modal.modal('hide');
});
},
diff --git a/client/views/edit-parameter.js b/client/views/edit-parameter.js
index ff96685435..e8b342f24c 100644
--- a/client/views/edit-parameter.js
+++ b/client/views/edit-parameter.js
@@ -17,6 +17,7 @@ along with this program. If not, see .
*/
var $ = require('jquery');
+let _ = require('underscore');
//support files
var tests = require('./tests');
var modals = require('../modals')
@@ -24,10 +25,10 @@ var modals = require('../modals')
var View = require('ampersand-view');
var InputView = require('./input');
//templates
-var template = require('../templates/includes/editReactionVar.pug');
+var editTemplate = require('../templates/includes/editParameter.pug');
+let viewTemplate = require('../templates/includes/viewParameters.pug');
module.exports = View.extend({
- template: template,
bindings: {
'model.inUse': {
hook: 'remove',
@@ -43,9 +44,14 @@ module.exports = View.extend({
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
this.previousName = this.model.name
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
},
render: function () {
+ this.template = this.viewMode ? viewTemplate : editTemplate;
View.prototype.render.apply(this, arguments);
+ if(!this.viewMode){
+ this.model.on('change', _.bind(this.updateViewer, this))
+ }
$(document).on('shown.bs.modal', function (e) {
$('[autofocus]', e.target).focus();
});
@@ -96,6 +102,9 @@ module.exports = View.extend({
this.model.collection.trigger('remove')
}
},
+ updateViewer: function () {
+ this.parent.renderViewParameter()
+ },
subviews: {
inputName: {
hook: 'input-name-container',
diff --git a/client/views/edit-rule.js b/client/views/edit-rule.js
index 9c54a25471..de9884510f 100644
--- a/client/views/edit-rule.js
+++ b/client/views/edit-rule.js
@@ -17,6 +17,7 @@ along with this program. If not, see .
*/
var $ = require('jquery');
+let _ = require('underscore');
//support files
let app = require('../app');
var tests = require('./tests');
@@ -26,43 +27,26 @@ var View = require('ampersand-view');
var InputView = require('./input');
var SelectView = require('ampersand-select-view');
//templates
-var template = require('../templates/includes/editRule.pug');
+var editTemplate = require('../templates/includes/editRule.pug');
+let viewTemplate = require('../templates/includes/viewRules.pug');
module.exports = View.extend({
- template: template,
events: {
'change [data-hook=rule-type]' : 'selectRuleType',
'change [data-hook=rule-variable]' : 'selectRuleVariable',
'click [data-hook=edit-annotation-btn]' : 'editAnnotation',
'click [data-hook=remove]' : 'removeRule',
},
- initiailize: function (attrs, options) {
- View.prototype.initiailize.apply(this, arguments);
+ initialize: function (attrs, options) {
+ View.prototype.initialize.apply(this, arguments);
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
},
render: function () {
- this.renderWithTemplate();
- var inputField = this.queryByHook('rule-expression').children[0].children[1];
- $(inputField).attr("placeholder", "---No Expression Entered---");
- var varOptions = this.getOptions();
- var typeOptions = ['Rate Rule', 'Assignment Rule']
- var typeSelectView = new SelectView({
- label: '',
- name: 'type',
- required: true,
- idAttributes: 'cid',
- options: typeOptions,
- value: this.model.type,
- });
- var variableSelectView = new SelectView({
- label: '',
- name: 'variable',
- required: true,
- idAttributes: 'cid',
- options: varOptions,
- value: this.model.variable.name,
- });
- app.registerRenderSubview(this, typeSelectView, "rule-type");
- app.registerRenderSubview(this, variableSelectView, 'rule-variable');
+ this.template = this.viewMode ? viewTemplate : editTemplate;
+ View.prototype.render.apply(this, arguments);
+ if(!this.viewMode){
+ this.model.on('change', _.bind(this.updateViewer, this))
+ }
$(document).on('shown.bs.modal', function (e) {
$('[autofocus]', e.target).focus();
});
@@ -95,33 +79,38 @@ module.exports = View.extend({
});
okBtn.addEventListener('click', function (e) {
self.model.annotation = input.value.trim();
- self.parent.renderRules();
+ self.parent.renderEditRules();
modal.modal('hide');
});
},
getOptions: function () {
var species = this.model.collection.parent.species;
var parameters = this.model.collection.parent.parameters;
- var speciesNames = species.map(function (specie) { return specie.name });
- var parameterNames = parameters.map(function (parameter) { return parameter.name });
- return speciesNames.concat(parameterNames);
+ var specs = species.map(function (specie) {
+ return [specie.compID, specie.name];
+ });
+ var params = parameters.map(function (parameter) {
+ return [parameter.compID, parameter.name];
+ });
+ let options = [{groupName: "Variables", options: specs},
+ {groupName: "Parameters", options: params}];
+ return options;
},
selectRuleType: function (e) {
- var type = e.target.selectedOptions.item(0).text;
- this.model.type = type;
+ this.model.type = e.target.value;
},
selectRuleVariable: function (e) {
var species = this.model.collection.parent.species;
var parameters = this.model.collection.parent.parameters;
- var val = e.target.selectedOptions.item(0).text;
+ var compID = Number(e.target.value);
var ruleVar = species.filter(function (specie) {
- if(specie.name === val) {
+ if(specie.compID === compID) {
return specie;
}
});
if(!ruleVar.length) {
ruleVar = parameters.filter(function (parameter) {
- if(parameter.name === val) {
+ if(parameter.compID === compID) {
return parameter;
}
});
@@ -131,6 +120,9 @@ module.exports = View.extend({
removeRule: function () {
this.model.collection.removeRule(this.model);
},
+ updateViewer: function () {
+ this.parent.renderViewRules();
+ },
subviews: {
inputName: {
hook: 'rule-name',
@@ -145,7 +137,33 @@ module.exports = View.extend({
valueType: 'string',
value: this.model.name,
});
- },
+ }
+ },
+ selectType: {
+ hook: 'rule-type',
+ prepareView: function (el) {
+ let options = ['Rate Rule', 'Assignment Rule'];
+ return new SelectView({
+ name: 'type',
+ required: true,
+ idAttributes: 'cid',
+ options: options,
+ value: this.model.type,
+ });
+ }
+ },
+ selectTarget: {
+ hook: 'rule-variable',
+ prepareView: function(el) {
+ let options = this.getOptions();
+ return new SelectView({
+ name: 'variable',
+ required: true,
+ idAttributes: 'cid',
+ groupOptions: options,
+ value: this.model.variable.compID,
+ });
+ }
},
inputRule: {
hook: 'rule-expression',
@@ -154,14 +172,12 @@ module.exports = View.extend({
parent: this,
required: true,
name: 'rule-expression',
- label: '',
- tests: '',
modelKey: 'expression',
valueType: 'string',
value: this.model.expression,
placeholder: "--No Formula Entered--"
});
- },
- },
- },
+ }
+ }
+ }
});
\ No newline at end of file
diff --git a/client/views/edit-spatial-specie.js b/client/views/edit-spatial-specie.js
deleted file mode 100644
index 7a685800b6..0000000000
--- a/client/views/edit-spatial-specie.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var tests = require('./tests');
-var _ = require('underscore');
-//views
-var View = require('ampersand-view');
-var InputView = require('./input');
-var TypesView = require('./component-types');
-//templates
-var template = require('../templates/includes/editSpatialSpecie.pug');
-
-module.exports = View.extend({
- template: template,
- bindings: {
- 'model.inUse': {
- hook: 'remove',
- type: 'booleanAttribute',
- name: 'disabled',
- },
- },
- events: {
- 'click [data-hook=remove]' : 'removeSpecie',
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.baseModel = this.model.collection.parent;
- this.modelType = "species";
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderTypes();
- },
- update: function () {
- },
- updateValid: function () {
- },
- removeSpecie: function () {
- this.remove();
- this.collection.removeSpecie(this.model);
- },
- renderTypes: function () {
- if(this.typesView) {
- this.typesView.remove();
- }
- this.typesView = this.renderCollection(
- this.baseModel.domain.types,
- TypesView,
- this.queryByHook("species-types"),
- {"filter": function (model) {
- return model.typeID != 0;
- }}
- );
- },
- subviews: {
- inputName: {
- hook: 'input-name-container',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'name',
- label: '',
- tests: tests.nameTests,
- modelKey: 'name',
- valueType: 'string',
- value: this.model.name,
- });
- },
- },
- inputValue: {
- hook: 'input-diffusion-coeff-container',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'diffusion coeff',
- label: '',
- tests: tests.valueTests,
- modelKey: 'diffusionConst',
- valueType: 'number',
- value: this.model.diffusionConst,
- });
- },
- },
- },
-});
\ No newline at end of file
diff --git a/client/views/edit-specie.js b/client/views/edit-specie.js
deleted file mode 100644
index b920f7c952..0000000000
--- a/client/views/edit-specie.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-var tests = require('./tests');
-var modals = require('../modals');
-//views
-var View = require('ampersand-view');
-var InputView = require('./input');
-//templates
-var template = require('../templates/includes/editReactionVar.pug');
-
-module.exports = View.extend({
- template: template,
- bindings: {
- 'model.inUse': {
- hook: 'remove',
- type: 'booleanAttribute',
- name: 'disabled',
- },
- },
- events: {
- 'click [data-hook=edit-annotation-btn]' : 'editAnnotation',
- 'click [data-hook=remove]' : 'removeSpecie',
- 'change [data-hook=input-name-container]' : 'setSpeciesName',
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.previousName = this.model.name
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- $(document).on('shown.bs.modal', function (e) {
- $('[autofocus]', e.target).focus();
- });
- $(document).on('hide.bs.modal', '.modal', function (e) {
- e.target.remove()
- });
- if(!this.model.annotation){
- $(this.queryByHook('edit-annotation-btn')).text('Add')
- }
- },
- update: function () {
- },
- updateValid: function (e) {
- },
- removeSpecie: function () {
- this.remove();
- this.collection.removeSpecie(this.model);
- this.parent.toggleSpeciesCollectionError();
- },
- setSpeciesName: function (e) {
- if(!e.target.value.trim()) {
- this.model.name = this.previousName;
- this.parent.renderEditSpeciesView();
- }else{
- this.previousName = this.model.name;
- this.model.collection.trigger('update-species', this.model.compID, this.model, true, false);
- this.model.collection.trigger('remove');
- }
- },
- editAnnotation: function () {
- var self = this;
- var name = this.model.name;
- var annotation = this.model.annotation;
- if(document.querySelector('#speciesAnnotationModal')) {
- document.querySelector('#speciesAnnotationModal').remove();
- }
- let modal = $(modals.annotationModalHtml("species", name, annotation)).modal();
- let okBtn = document.querySelector('#speciesAnnotationModal .ok-model-btn');
- let input = document.querySelector('#speciesAnnotationModal #speciesAnnotationInput');
- input.addEventListener("keyup", function (event) {
- if(event.keyCode === 13){
- event.preventDefault();
- okBtn.click();
- }
- });
- okBtn.addEventListener('click', function (e) {
- self.model.annotation = input.value.trim();
- self.parent.renderEditSpeciesView();
- modal.modal('hide');
- });
- },
- subviews: {
- inputName: {
- hook: 'input-name-container',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'name',
- label: '',
- tests: tests.nameTests,
- modelKey: 'name',
- valueType: 'string',
- value: this.model.name,
- });
- },
- },
- inputValue: {
- hook: 'input-value-container',
- prepareView: function (el) {
- return new InputView({
- parent: this,
- required: true,
- name: 'value',
- label: '',
- tests: tests.valueTests,
- modelKey: 'value',
- valueType: 'number',
- value: this.model.value,
- });
- },
- },
- },
-});
\ No newline at end of file
diff --git a/client/views/edit-species.js b/client/views/edit-species.js
new file mode 100644
index 0000000000..2aad005f6c
--- /dev/null
+++ b/client/views/edit-species.js
@@ -0,0 +1,304 @@
+/*
+StochSS is a platform for simulating biochemical systems
+Copyright (C) 2019-2020 StochSS developers.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+let $ = require('jquery');
+let _ = require('underscore');
+//support files
+let app = require('../app');
+let tests = require('./tests');
+let modals = require('../modals');
+//views
+let InputView = require('./input');
+let View = require('ampersand-view');
+let TypesView = require('./component-types');
+let SelectView = require('ampersand-select-view');
+//templates
+let editTemplate = require('../templates/includes/editSpecies.pug');
+let editSpatialTemplate = require('../templates/includes/editSpatialSpecies.pug');
+let viewTemplate = require('../templates/includes/viewSpecies.pug');
+let viewSpatialTemplate = require('../templates/includes/viewSpatialSpecies.pug');
+
+module.exports = View.extend({
+ bindings: {
+ 'model.inUse': {
+ hook: 'remove',
+ type: 'booleanAttribute',
+ name: 'disabled',
+ },
+ },
+ events: {
+ 'change [data-hook=input-name-container]' : 'setSpeciesName',
+ 'change [data-hook=specie-mode]' : 'setSpeciesMode',
+ 'change [data-hook=switching-tol]' : 'setSwitchingType',
+ 'change [data-hook=switching-min]' : 'setSwitchingType',
+ 'click [data-hook=edit-annotation-btn]' : 'editAnnotation',
+ 'click [data-hook=remove]' : 'removeSpecie',
+ 'click [data-hook=collapse-advanced]' : 'changeCollapseButtonText'
+ },
+ initialize: function (attrs, options) {
+ View.prototype.initialize.apply(this, arguments);
+ this.modelType = "species";
+ this.previousName = this.model.name;
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
+ if(this.viewMode && this.parent.spatial) {
+ let self = this;
+ this.types = [];
+ if(this.model.types) {
+ this.model.types.forEach(function (index) {
+ let type = self.model.collection.parent.domain.types.get(index, "typeID");
+ self.types.push(type.name);
+ });
+ }
+ }
+ if(this.model.mode === null && this.parent.defaultMode !== "") {
+ this.model.mode = this.parent.defaultMode;
+ }
+ this.switchingValWithLabel = this.model.isSwitchTol ?
+ "Switching Tolerance: " + this.model.switchTol :
+ "Minimum Value For Switching: " + this.model.switchMin;
+ },
+ render: function () {
+ if(this.parent.spatial){
+ this.template = this.viewMode ? viewSpatialTemplate : editSpatialTemplate;
+ }else{
+ this.template = this.viewMode ? viewTemplate : editTemplate;
+ }
+ View.prototype.render.apply(this, arguments);
+ $(document).on('shown.bs.modal', function (e) {
+ $('[autofocus]', e.target).focus();
+ });
+ $(document).on('hide.bs.modal', '.modal', function (e) {
+ e.target.remove();
+ });
+ if(!this.model.annotation){
+ $(this.queryByHook('edit-annotation-btn')).text('Add');
+ }
+ if(this.parent.defaultMode !== "dynamic") {
+ $(this.queryByHook("advanced-species")).css("display", "none");
+ }else{
+ $(this.queryByHook("advanced-species")).css("display", "block");
+ }
+ if(this.model.isSwitchTol){
+ $(this.queryByHook('switching-tol')).prop('checked', true);
+ }else{
+ $(this.queryByHook('switching-min')).prop('checked', true);
+ }
+ this.toggleSwitchingSettings();
+ this.updateInputValidation();
+ if(!this.viewMode){
+ this.model.on('change', _.bind(this.updateViewer, this));
+ if(this.parent.spatial) {
+ this.renderTypes();
+ }
+ }
+ },
+ changeCollapseButtonText: function (e) {
+ app.changeCollapseButtonText(this, e);
+ },
+ editAnnotation: function () {
+ let self = this;
+ let name = this.model.name;
+ let annotation = this.model.annotation;
+ if(document.querySelector('#speciesAnnotationModal')) {
+ document.querySelector('#speciesAnnotationModal').remove();
+ }
+ let modal = $(modals.annotationModalHtml("species", name, annotation)).modal();
+ let okBtn = document.querySelector('#speciesAnnotationModal .ok-model-btn');
+ let input = document.querySelector('#speciesAnnotationModal #speciesAnnotationInput');
+ input.addEventListener("keyup", function (event) {
+ if(event.keyCode === 13){
+ event.preventDefault();
+ okBtn.click();
+ }
+ });
+ okBtn.addEventListener('click', function (e) {
+ self.model.annotation = input.value.trim();
+ self.parent.renderEditSpeciesView();
+ modal.modal('hide');
+ });
+ },
+ removeSpecie: function () {
+ this.remove();
+ this.collection.removeSpecie(this.model);
+ this.parent.toggleSpeciesCollectionError();
+ },
+ renderTypes: function () {
+ if(this.typesView) {
+ this.typesView.remove();
+ }
+ this.typesView = this.renderCollection(
+ this.model.collection.parent.domain.types,
+ TypesView,
+ this.queryByHook("species-types"),
+ {"filter": function (model) {
+ return model.typeID != 0;
+ }}
+ );
+ },
+ setSpeciesMode: function (e) {
+ this.model.mode = e.target.value;
+ this.model.collection.trigger('update-species', this.model.compID, this.model, false, false);
+ this.updateInputValidation();
+ this.toggleSwitchingSettings();
+ },
+ setSpeciesName: function (e) {
+ if(!e.target.value.trim()) {
+ this.model.name = this.previousName;
+ this.parent.renderEditSpeciesView();
+ }else{
+ this.previousName = this.model.name;
+ this.model.collection.trigger('update-species', this.model.compID, this.model, true, false);
+ }
+ },
+ setSwitchingType: function (e) {
+ this.model.isSwitchTol = $(this.queryByHook('switching-tol')).is(":checked");
+ this.updateInputValidation();
+ this.toggleSwitchingSettingsInput();
+ },
+ toggleSwitchingSettings: function () {
+ if(this.model.mode === "dynamic"){
+ $(this.queryByHook('switching-tol')).prop('disabled', false);
+ $(this.queryByHook('switching-min')).prop('disabled', false);
+ this.toggleSwitchingSettingsInput();
+ }else{
+ $(this.queryByHook('switching-tol')).prop('disabled', true);
+ $(this.queryByHook('switching-min')).prop('disabled', true);
+ $(this.queryByHook('switching-threshold')).find('input').prop('disabled', true);
+ $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', true);
+ }
+ },
+ toggleSwitchingSettingsInput: function () {
+ if(this.model.isSwitchTol){
+ $(this.queryByHook('switching-threshold')).find('input').prop('disabled', true);
+ $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', false);
+ }else{
+ $(this.queryByHook('switching-tolerance')).find('input').prop('disabled', true);
+ $(this.queryByHook('switching-threshold')).find('input').prop('disabled', false);
+ }
+ },
+ update: function () {},
+ updateInputValidation: function () {
+ if(this.viewMode || this.parent.spatial) {return}
+ // Update validation requirements and re-run tests for inputSwitchTol.
+ // This removes error reporting not using switching tolerance
+ let shouldValidateTol = this.model.mode === "dynamic" && this.model.isSwitchTol
+ this.inputSwitchTol.required = shouldValidateTol;
+ this.inputSwitchTol.tests = shouldValidateTol ? tests.valueTests : []
+ this.inputSwitchTol.runTests()
+ // Update validation requirements and re-run tests for inputSwitchMin.
+ // This removes error reporting when not using minimum value for switching.
+ let shouldValidateMin = this.model.mode === "dynamic" && !this.model.isSwitchTol
+ this.inputSwitchMin.required = shouldValidateMin;
+ this.inputSwitchMin.tests = shouldValidateMin ? tests.valueTests : []
+ this.inputSwitchMin.runTests()
+ // Add/Remove 'input-invalid' class from inputSwitchTol and inputSwitchMin based on whether
+ // the user is using switching tolerance or minimum value for switching
+ let tolInput = $(this.queryByHook('switching-tolerance')).find('input')[0]
+ let minInput = $(this.queryByHook('switching-threshold')).find('input')[0]
+ if(this.model.mode !== "dynamic") {
+ $(tolInput).removeClass('input-invalid')
+ $(minInput).removeClass('input-invalid')
+ }else if(this.model.isSwitchTol){
+ $(minInput).removeClass('input-invalid')
+ if(this.model.switchTol === "" || isNaN(this.model.switchTol)){
+ $(tolInput).addClass('input-invalid')
+ }
+ }else{
+ $(tolInput).removeClass('input-invalid')
+ if(this.model.switchMin === "" || isNaN(this.model.switchMin)){
+ $(minInput).addClass('input-invalid')
+ }
+ }
+ },
+ updateValid: function (e) {},
+ updateViewer: function () {
+ this.parent.renderViewSpeciesView()
+ },
+ subviews: {
+ inputName: {
+ hook: 'input-name-container',
+ prepareView: function (el) {
+ return new InputView({
+ parent: this,
+ required: true,
+ name: 'name',
+ tests: tests.nameTests,
+ modelKey: 'name',
+ valueType: 'string',
+ value: this.model.name,
+ });
+ }
+ },
+ inputValue: {
+ hook: 'input-value-container',
+ prepareView: function (el) {
+ return new InputView({
+ parent: this,
+ required: true,
+ name: this.parent.spatial ? 'diffusion constant' : 'value',
+ tests: tests.valueTests,
+ modelKey: this.parent.spatial ? 'diffusionConst' : 'value',
+ valueType: 'number',
+ value: this.parent.spatial ? this.model.diffusionConst : this.model.value,
+ });
+ }
+ },
+ selectMode: {
+ hook: 'specie-mode',
+ prepareView: function (el) {
+ options = [['continuous', 'Concentration'], ['discrete', 'Population'],
+ ['dynamic', 'Hybrid Concentration/Population']]
+ return new SelectView({
+ name: 'mode',
+ required: true,
+ idAttributes: 'cid',
+ options: options,
+ value: this.model.mode,
+ });
+ }
+ },
+ inputSwitchTol: {
+ hook: 'switching-tolerance',
+ prepareView: function (el) {
+ return new InputView({
+ parent: this,
+ required: true,
+ name: 'switching-tolerance',
+ tests: tests.valueTests,
+ modelKey: 'switchTol',
+ valueType: 'number',
+ value: this.model.switchTol,
+ });
+ }
+ },
+ inputSwitchMin: {
+ hook: 'switching-threshold',
+ prepareView: function (el) {
+ return new InputView({
+ parent: this,
+ required: true,
+ name: 'switching-threshold',
+ tests: tests.valueTests,
+ modelKey: 'switchMin',
+ valueType: 'number',
+ value: this.model.switchMin,
+ });
+ }
+ }
+ }
+});
diff --git a/client/views/event-assignments-editor.js b/client/views/event-assignments-editor.js
index 917820a137..7f790869f5 100644
--- a/client/views/event-assignments-editor.js
+++ b/client/views/event-assignments-editor.js
@@ -16,6 +16,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+let $ = require('jquery');
+//support files
+let app = require('../app');
//views
var View = require('ampersand-view');
var EditEventAssignment = require('./edit-event-assignment');
@@ -25,25 +28,56 @@ var template = require('../templates/includes/eventAssignmentsEditor.pug');
module.exports = View.extend({
template: template,
events: {
- 'click [data-hook=add-event-assignment]' : 'addAssignment',
+ 'click [data-hook=collapse-assignments]' : 'changeCollapseButtonText',
+ 'click [data-hook=add-event-assignment]' : 'addAssignment'
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
+ this.tooltips = attrs.tooltips;
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderCollection(
+ if(this.readOnly) {
+ $(this.queryByHook('edit-event-assignments')).removeClass('active');
+ $(this.queryByHook('view-event-assignments')).addClass('active');
+ $(this.queryByHook('event-assignments-header')).css("display", "none");
+ this.renderViewEventAssignment();
+ }else{
+ this.renderEditEventAssignment();
+ }
+ },
+ addAssignment: function () {
+ this.collection.addEventAssignment();
+ this.collection.parent.collection.trigger('change')
+ },
+ changeCollapseButtonText: function (e) {
+ app.changeCollapseButtonText(this, e);
+ },
+ renderEditEventAssignment: function () {
+ if(this.editEventAssignments) {
+ this.editEventAssignments.remove();
+ }
+ this.editEventAssignments = this.renderCollection(
this.collection,
EditEventAssignment,
- this.queryByHook('event-assignments-container')
+ this.queryByHook('edit-event-assignments-container')
+ );
+ },
+ renderViewEventAssignment: function () {
+ if(this.viewEventAssignments) {
+ this.viewEventAssignments.remove();
+ }
+ let options = {viewOptions: {viewMode: true}}
+ this.viewEventAssignments = this.renderCollection(
+ this.collection,
+ EditEventAssignment,
+ this.queryByHook('view-event-assignments-container'),
+ options
);
},
update: function () {
},
updateValid: function () {
- },
- addAssignment: function () {
- this.collection.addEventAssignment();
- this.collection.parent.collection.trigger('change')
- },
+ }
})
\ No newline at end of file
diff --git a/client/views/event-assignments-viewer.js b/client/views/event-assignments-viewer.js
deleted file mode 100644
index ee3551a067..0000000000
--- a/client/views/event-assignments-viewer.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-//views
-var View = require('ampersand-view');
-var ViewAssignments = require('./view-event-assignments');
-//templates
-var template = require('../templates/includes/eventAssignmentsViewer.pug');
-
-module.exports = View.extend({
- template: template,
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewAssignments, 'view-event-assignments-list');
- },
-});
\ No newline at end of file
diff --git a/client/views/event-details.js b/client/views/event-details.js
index 3d64cdb23d..b0cc2aca09 100644
--- a/client/views/event-details.js
+++ b/client/views/event-details.js
@@ -44,8 +44,8 @@ module.exports = View.extend({
events: {
'change [data-hook=event-trigger-init-value]' : 'setTriggerInitialValue',
'change [data-hook=event-trigger-persistent]' : 'setTriggerPersistent',
- 'change [data-hook=trigger-time]' : 'setUseValuesFromTriggerTime',
- 'change [data-hook=assignment-time]' : 'setUseValuesFromTriggerTime',
+ 'change [data-hook=edit-trigger-time]' : 'setUseValuesFromTriggerTime',
+ 'change [data-hook=edit-assignment-time]' : 'setUseValuesFromTriggerTime',
'click [data-hook=advanced-event-button]' : 'changeCollapseButtonText',
},
initialize: function (attrs, options) {
@@ -54,16 +54,12 @@ module.exports = View.extend({
render: function () {
View.prototype.render.apply(this, arguments);
this.renderEventAssignments();
- var triggerExpressionField = this.queryByHook('event-trigger-expression').children[0].children[1];
- $(triggerExpressionField).attr("placeholder", "---No Expression Entered---");
- var delayField = this.queryByHook('event-delay').children[0].children[1];
- $(delayField).attr("placeholder", "---No Expression Entered---");
if(this.model.useValuesFromTriggerTime){
- $(this.queryByHook('trigger-time')).prop('checked', true)
+ $(this.queryByHook('edit-trigger-time')).prop('checked', true)
}else{
- $(this.queryByHook('assignment-time')).prop('checked', true)
+ $(this.queryByHook('edit-assignment-time')).prop('checked', true)
}
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
@@ -81,6 +77,7 @@ module.exports = View.extend({
}
this.eventAssignmentsView = new EventAssignment({
collection: this.model.eventAssignments,
+ tooltips: this.parent.tooltips
});
app.registerRenderSubview(this, this.eventAssignmentsView, 'event-assignments');
},
@@ -111,8 +108,7 @@ module.exports = View.extend({
parent: this,
required: false,
name: 'delay',
- label: '',
- tests: '',
+ placeholder: '---No Expression Entered---',
modelKey: 'delay',
valueType: 'string',
value: this.model.delay,
@@ -126,8 +122,6 @@ module.exports = View.extend({
parent: this,
required: true,
name: 'priority',
- label: '',
- tests: '',
modelKey: 'priority',
valueType: 'string',
value: this.model.priority,
@@ -141,8 +135,7 @@ module.exports = View.extend({
parent: this,
required: true,
name: 'trigger-expression',
- label: '',
- tests: '',
+ placeholder: '---No Expression Entered---',
modelKey: 'triggerExpression',
valueType: 'string',
value: this.model.triggerExpression,
diff --git a/client/views/event-listings.js b/client/views/event-listings.js
index 2f248816f7..658828a165 100644
--- a/client/views/event-listings.js
+++ b/client/views/event-listings.js
@@ -17,52 +17,36 @@ along with this program. If not, see .
*/
var $ = require('jquery');
+let _ = require('underscore');
//support files
+let app = require('../app');
var tests = require('./tests');
var modals = require('../modals');
//views
var View = require('ampersand-view');
var InputView = require('./input');
+var EventAssignment = require('./event-assignments-editor');
//templates
-var template = require('../templates/includes/eventListings.pug');
-
-let eventAnnotationModalHtml = (eventName, annotation) => {
- return `
-
-
-
-
-
- Annotation:
-
-
-
-
-
-
- `
-}
+var editTemplate = require('../templates/includes/eventListings.pug');
+let viewTemplate = require('../templates/includes/viewEvents.pug');
module.exports = View.extend({
- template: template,
bindings: {
- 'model.name' : {
- type: 'value',
- hook: 'input-name-container'
- },
'model.selected' : {
type: function (el, value, previousValue) {
el.checked = value;
},
hook: 'select'
+ },
+ 'model.initialValue': {
+ hook: 'event-trigger-init-value',
+ type: 'booleanAttribute',
+ name: 'checked',
+ },
+ 'model.persistent': {
+ hook: 'event-trigger-persistent',
+ type: 'booleanAttribute',
+ name: 'checked',
}
},
events: {
@@ -72,8 +56,15 @@ module.exports = View.extend({
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
+ if(this.viewMode) {
+ this.delay = this.model.delay === "" ? "None" : this.model.delay;
+ }else{
+ this.model.on("change", _.bind(this.updateViewer, this));
+ }
},
render: function () {
+ this.template = this.viewMode ? viewTemplate : editTemplate;
View.prototype.render.apply(this, arguments);
$(document).on('shown.bs.modal', function (e) {
$('[autofocus]', e.target).focus();
@@ -82,7 +73,15 @@ module.exports = View.extend({
e.target.remove()
});
if(!this.model.annotation){
- $(this.queryByHook('edit-annotation-btn')).text('Add')
+ $(this.queryByHook('edit-annotation-btn')).text('Add');
+ }
+ if(this.viewMode) {
+ this.renderViewEventAssignments();
+ if(this.model.useValuesFromTriggerTime) {
+ $(this.queryByHook("view-trigger-time")).prop('checked', true);
+ }else{
+ $(this.queryByHook("view-assignment-time")).prop('checked', true);
+ }
}
},
update: function () {
@@ -110,7 +109,7 @@ module.exports = View.extend({
});
okBtn.addEventListener('click', function (e) {
self.model.annotation = input.value.trim();
- self.parent.renderEventListingsView();
+ self.parent.renderEditEventListingsView();
modal.modal('hide');
});
},
@@ -118,6 +117,20 @@ module.exports = View.extend({
this.remove();
this.collection.removeEvent(this.model);
},
+ renderViewEventAssignments: function () {
+ if(this.viewEventAssignmentsView){
+ this.viewEventAssignmentsView.remove()
+ }
+ this.viewEventAssignmentsView = new EventAssignment({
+ collection: this.model.eventAssignments,
+ tooltips: this.parent.tooltips,
+ readOnly: true
+ });
+ app.registerRenderSubview(this, this.viewEventAssignmentsView, 'assignment-viewer');
+ },
+ updateViewer: function () {
+ this.parent.renderViewEventListingView();
+ },
subviews: {
inputName: {
hook: 'event-name-container',
diff --git a/client/views/events-editor.js b/client/views/events-editor.js
index 73bfbcca24..189c16fad5 100644
--- a/client/views/events-editor.js
+++ b/client/views/events-editor.js
@@ -37,54 +37,89 @@ module.exports = View.extend({
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
this.tooltips = Tooltips.eventsEditor
- this.opened = attrs.opened
- this.collection.on("select", function (event) {
- this.setSelectedEvent(event);
- this.setDetailsView(event);
- }, this);
- this.collection.on("remove", function (event) {
- // Select the last event by default
- // But only if there are other events other than the one we're removing
- if (event.detailsView)
- event.detailsView.remove();
- this.collection.removeEvent(event);
- if (this.collection.length) {
- var selected = this.collection.at(this.collection.length-1);
- this.collection.trigger("select", selected);
- }
- }, this);
- this.collection.parent.species.on('add remove', this.toggleAddEventButton, this);
- this.collection.parent.parameters.on('add remove', this.toggleAddEventButton, this);
+ if(!this.readOnly) {
+ this.collection.on("select", function (event) {
+ this.setSelectedEvent(event);
+ this.setDetailsView(event);
+ }, this);
+ this.collection.on("remove", function (event) {
+ // Select the last event by default
+ // But only if there are other events other than the one we're removing
+ if (event.detailsView)
+ event.detailsView.remove();
+ this.collection.removeEvent(event);
+ if (this.collection.length) {
+ var selected = this.collection.at(this.collection.length-1);
+ this.collection.trigger("select", selected);
+ }
+ }, this);
+ this.collection.parent.species.on('add remove', this.toggleAddEventButton, this);
+ this.collection.parent.parameters.on('add remove', this.toggleAddEventButton, this);
+ }
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderEventListingsView();
- this.detailsContainer = this.queryByHook('event-details-container');
- this.detailsViewSwitcher = new ViewSwitcher({
- el: this.detailsContainer,
- });
- if (this.collection.length) {
- this.setSelectedEvent(this.collection.at(0));
- this.collection.trigger("select", this.selectedEvent);
- }
- this.toggleAddEventButton()
- if(this.opened) {
- this.openEventsContainer();
+ if(this.readOnly) {
+ $(this.queryByHook('events-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('events-view-tab')).tab('show');
+ $(this.queryByHook('edit-events')).removeClass('active');
+ $(this.queryByHook('view-events')).addClass('active');
+ }else {
+ this.renderEditEventListingsView();
+ this.detailsContainer = this.queryByHook('event-details-container');
+ this.detailsViewSwitcher = new ViewSwitcher({
+ el: this.detailsContainer,
+ });
+ if(this.collection.length) {
+ this.setSelectedEvent(this.collection.at(0));
+ this.collection.trigger("select", this.selectedEvent);
+ }
+ this.toggleAddEventButton()
}
+ this.renderViewEventListingView();
},
update: function () {
},
updateValid: function () {
},
- renderEventListingsView: function () {
- if(this.eventListingsView){
- this.eventListingsView.remove();
+ renderEditEventListingsView: function () {
+ if(this.editEventListingsView){
+ this.editEventListingsView.remove();
+ }
+ this.editEventListingsView = this.renderCollection(
+ this.collection,
+ EventListings,
+ this.queryByHook('edit-event-listing-container')
+ );
+ $(document).ready(function () {
+ $('[data-toggle="tooltip"]').tooltip();
+ $('[data-toggle="tooltip"]').click(function () {
+ $('[data-toggle="tooltip"]').tooltip("hide");
+ });
+ });
+ },
+ renderViewEventListingView: function () {
+ if(this.viewEventListingsView) {
+ this.viewEventListingsView.remove();
}
- this.eventListingsView = this.renderCollection(
+ this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("events-annotation-header")).css("display", "none");
+ }else{
+ $(this.queryByHook("events-annotation-header")).css("display", "block");
+ }
+ let options = {viewOptions: {parent: this, viewMode: true}};
+ this.viewEventListingsView = this.renderCollection(
this.collection,
EventListings,
- this.queryByHook('event-listing-container')
+ this.queryByHook('view-event-listing-container'),
+ options
);
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
@@ -134,11 +169,6 @@ module.exports = View.extend({
this.parent.modelStateButtons.clickSaveHandler(e);
this.parent.renderEventsView(mode="view");
},
- openEventsContainer: function () {
- $(this.queryByHook('events')).collapse('show');
- let collapseBtn = $(this.queryByHook('collapse'))
- collapseBtn.trigger('click')
- },
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
},
diff --git a/client/views/events-viewer.js b/client/views/events-viewer.js
deleted file mode 100644
index fd5326b366..0000000000
--- a/client/views/events-viewer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var ViewEvent = require('./view-events');
-//templates
-var template = require('../templates/includes/eventsViewer.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'click [data-hook=collapse]' : 'changeCollapseButtonText',
- 'click [data-hook=edit-events]' : 'switchToEditMode'
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewEvent, this.queryByHook('view-events-container'))
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip();
- $('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
- });
- },
- switchToEditMode: function (e) {
- this.parent.renderEventsView("edit", true);
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
- },
-});
\ No newline at end of file
diff --git a/client/views/model-viewer.js b/client/views/model-viewer.js
index d35fe7885a..b1563030d3 100644
--- a/client/views/model-viewer.js
+++ b/client/views/model-viewer.js
@@ -20,11 +20,11 @@ along with this program. If not, see .
let app = require('../app');
//views
let View = require('ampersand-view');
-let RulesViewer = require('./rules-viewer');
-let EventsViewer = require('./events-viewer');
-let SpeciesViewer = require('./species-viewer');
-let ReactionsViewer = require('./reactions-viewer');
-let ParametersViewer = require('./parameters-viewer');
+let EventsViewer = require('./events-editor');
+let RulesViewer = require('./rules-editor');
+let SpeciesViewer = require('./species-editor');
+let ReactionsViewer = require('./reactions-editor');
+let ParametersViewer = require('./parameters-editor');
let SBMLComponentsView = require('./sbml-component-editor');
//templates
let template = require('../templates/includes/modelViewer.pug');
@@ -48,38 +48,45 @@ module.exports = View.extend({
},
renderEventsView: function () {
let eventsViewer = new EventsViewer({
- collection: this.model.eventsCollection
+ collection: this.model.eventsCollection,
+ readOnly: true
});
app.registerRenderSubview(this, eventsViewer, "events-viewer-container");
},
renderParametersView: function () {
let parametersViewer = new ParametersViewer({
- collection: this.model.parameters
+ collection: this.model.parameters,
+ readOnly: true
});
app.registerRenderSubview(this, parametersViewer, "parameters-viewer-container");
},
renderReactionsView: function () {
let reactionsViewer = new ReactionsViewer({
- collection: this.model.reactions
+ collection: this.model.reactions,
+ readOnly: true
});
app.registerRenderSubview(this, reactionsViewer, "reactions-viewer-container");
},
renderRulesView: function () {
let rulesViewer = new RulesViewer({
- collection: this.model.rules
+ collection: this.model.rules,
+ readOnly: true
});
app.registerRenderSubview(this, rulesViewer, "rules-viewer-container");
},
renderSBMLComponentsView: function () {
let sbmlComponentsView = new SBMLComponentsView({
functionDefinitions: this.model.functionDefinitions,
- viewMode: true
+ readOnly: true
});
app.registerRenderSubview(this, sbmlComponentsView, "sbml-components-viewer-container");
},
renderSpeciesView: function () {
let speciesViewer = new SpeciesViewer({
- collection: this.model.species
+ collection: this.model.species,
+ spatial: this.model.is_spatial,
+ defaultMode: this.model.defaultMode,
+ readOnly: true
});
app.registerRenderSubview(this, speciesViewer, "species-viewer-container");
},
diff --git a/client/views/parameters-editor.js b/client/views/parameters-editor.js
index c8e69b06b5..aa72c100c5 100644
--- a/client/views/parameters-editor.js
+++ b/client/views/parameters-editor.js
@@ -30,14 +30,13 @@ module.exports = View.extend({
template: template,
events: {
'click [data-hook=add-parameter]' : 'addParameter',
- 'click [data-hook=save-parameters]' : 'switchToViewMode',
'click [data-hook=collapse]' : 'changeCollapseButtonText',
},
initialize: function (attrs, options) {
var self = this;
View.prototype.initialize.apply(this, arguments);
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
this.tooltips = Tooltips.parametersEditor
- this.opened = attrs.opened
this.collection.on('update-parameters', function (compID, parameter) {
self.collection.parent.reactions.map(function (reaction) {
if(reaction.rate && reaction.rate.compID === compID){
@@ -63,10 +62,19 @@ module.exports = View.extend({
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderEditParameter();
- if(this.opened) {
- this.openParametersContainer();
+ if(this.readOnly) {
+ $(this.queryByHook('parameters-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('parameters-view-tab')).tab('show');
+ $(this.queryByHook('edit-parameters')).removeClass('active');
+ $(this.queryByHook('view-parameters')).addClass('active');
+ }else{
+ this.renderEditParameter();
}
+ this.renderViewParameter();
},
update: function () {
},
@@ -79,15 +87,33 @@ module.exports = View.extend({
this.editParameterView = this.renderCollection(
this.collection,
EditParameterView,
- this.queryByHook('parameter-list')
+ this.queryByHook('edit-parameter-list')
);
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
});
});
},
+ renderViewParameter: function () {
+ if(this.viewParameterView) {
+ this.viewParameterView.remove();
+ }
+ this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("parameters-annotation-header")).css("display", "none");
+ }else{
+ $(this.queryByHook("parameters-annotation-header")).css("display", "block");
+ }
+ let options = {viewOptions: {viewMode: true}};
+ this.viewParameterView = this.renderCollection(
+ this.collection,
+ EditParameterView,
+ this.queryByHook('view-parameter-list'),
+ options
+ );
+ },
addParameter: function () {
this.collection.addParameter();
$(document).ready(function () {
@@ -98,15 +124,6 @@ module.exports = View.extend({
});
});
},
- switchToViewMode: function (e) {
- this.parent.modelStateButtons.clickSaveHandler(e);
- this.parent.renderParametersView(mode="view");
- },
- openParametersContainer: function () {
- $(this.queryByHook('parameters-list-container')).collapse('show');
- let collapseBtn = $(this.queryByHook('collapse'))
- collapseBtn.trigger('click')
- },
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
},
diff --git a/client/views/parameters-viewer.js b/client/views/parameters-viewer.js
deleted file mode 100644
index e58ba726fd..0000000000
--- a/client/views/parameters-viewer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var ViewParameter = require('./view-parameter');
-//templates
-var template = require('../templates/includes/parametersViewer.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'click [data-hook=collapse]' : 'changeCollapseButtonText',
- 'click [data-hook=edit-parameters]' : 'switchToEditMode'
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewParameter, this.queryByHook('parameter-list'))
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip();
- $('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
- });
- },
- switchToEditMode: function (e) {
- this.parent.renderParametersView("edit", true);
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
- },
-});
\ No newline at end of file
diff --git a/client/views/reaction-details.js b/client/views/reaction-details.js
index 36e1949844..aa074e024b 100644
--- a/client/views/reaction-details.js
+++ b/client/views/reaction-details.js
@@ -182,6 +182,7 @@ module.exports = View.extend({
var val = e.target.selectedOptions.item(0).text;
var param = this.getRateFromParameters(val);
this.model.rate = param || this.model.rate;
+ this.model.trigger("change");
this.model.collection.trigger("change");
}
},
diff --git a/client/views/reaction-listing.js b/client/views/reaction-listing.js
index 864c24a43d..6de8a56d3e 100644
--- a/client/views/reaction-listing.js
+++ b/client/views/reaction-listing.js
@@ -18,6 +18,7 @@ along with this program. If not, see .
var $ = require('jquery');
var katex = require('katex');
+let _ = require('underscore');
//support files
var tests = require('./tests');
var modals = require('../modals');
@@ -25,10 +26,10 @@ var modals = require('../modals');
var View = require('ampersand-view');
var InputView = require('./input');
//templates
-var template = require('../templates/includes/reactionListing.pug');
+var editTemplate = require('../templates/includes/reactionListing.pug');
+let viewTemplate = require('../templates/includes/viewReactions.pug');
module.exports = View.extend({
- template: template,
bindings: {
'model.name' : {
type: 'value',
@@ -58,8 +59,23 @@ module.exports = View.extend({
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.viewMode = attrs.viewMode ? attrs.viewMode : false;
+ if(this.viewMode) {
+ this.rate = this.model.reactionType === "custom-propensity" ? this.model.propensity : this.model.rate.name;
+ this.types = [];
+ let self = this;
+ if(this.model.types) {
+ this.model.types.forEach(function (index) {
+ let type = self.model.collection.parent.domain.types.get(index, "typeID");
+ self.types.push(type.name)
+ });
+ }
+ }else{
+ this.model.on('change', _.bind(this.updateViewer, this));
+ }
},
render: function () {
+ this.template = this.viewMode ? viewTemplate : editTemplate;
View.prototype.render.apply(this, arguments);
$(document).on('shown.bs.modal', function (e) {
$('[autofocus]', e.target).focus();
@@ -100,10 +116,13 @@ module.exports = View.extend({
});
okBtn.addEventListener('click', function (e) {
self.model.annotation = input.value.trim();
- self.parent.renderReactionListingView();
+ self.parent.renderEditReactionListingView();
modal.modal('hide');
});
},
+ updateViewer: function () {
+ this.parent.renderViewReactionView();
+ },
subviews: {
inputName: {
hook: 'input-name-container',
diff --git a/client/views/reactions-editor.js b/client/views/reactions-editor.js
index c54ef00484..dc9b56ed77 100644
--- a/client/views/reactions-editor.js
+++ b/client/views/reactions-editor.js
@@ -45,69 +45,83 @@ module.exports = View.extend({
'click [data-hook=four]' : 'handleAddReactionClick',
'click [data-hook=custom-massaction]' : 'handleAddReactionClick',
'click [data-hook=custom-propensity]' : 'handleAddReactionClick',
- 'click [data-hook=save-reactions]' : 'switchToViewMode',
'click [data-hook=collapse]' : 'changeCollapseButtonText'
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
this.tooltips = Tooltips.reactionsEditor
- this.opened = attrs.opened
- this.collection.on("select", function (reaction) {
- this.setSelectedReaction(reaction);
- this.setDetailsView(reaction);
- }, this);
- this.collection.on("remove", function (reaction) {
- // Select the last reaction by default
- // But only if there are other reactions other than the one we're removing
- if (reaction.detailsView)
- reaction.detailsView.remove();
- this.collection.removeReaction(reaction);
- if (this.collection.length) {
- var selected = this.collection.at(this.collection.length-1);
- this.collection.trigger("select", selected);
- }
- }, this);
- this.collection.parent.species.on('add remove', this.toggleAddReactionButton, this);
- this.collection.parent.parameters.on('add remove', this.toggleReactionTypes, this);
- this.collection.parent.on('change', this.toggleProcessError, this)
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
+ if(!this.readOnly) {
+ this.collection.on("select", function (reaction) {
+ this.setSelectedReaction(reaction);
+ this.setDetailsView(reaction);
+ }, this);
+ this.collection.on("remove", function (reaction) {
+ // Select the last reaction by default
+ // But only if there are other reactions other than the one we're removing
+ if (reaction.detailsView)
+ reaction.detailsView.remove();
+ this.collection.removeReaction(reaction);
+ if (this.collection.length) {
+ var selected = this.collection.at(this.collection.length-1);
+ this.collection.trigger("select", selected);
+ }
+ }, this);
+ this.collection.parent.species.on('add remove', this.toggleAddReactionButton, this);
+ this.collection.parent.parameters.on('add remove', this.toggleReactionTypes, this);
+ this.collection.parent.on('change', this.toggleProcessError, this)
+ }
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderReactionListingView();
- this.detailsContainer = this.queryByHook('reaction-details-container');
- this.detailsViewSwitcher = new ViewSwitcher({
- el: this.detailsContainer,
- });
- if (this.collection.length) {
- this.setSelectedReaction(this.collection.at(0));
- this.collection.trigger("select", this.selectedReaction);
- }
- this.collection.trigger("change");
- this.toggleAddReactionButton();
- if(this.collection.parent.parameters.length > 0){
- $(this.queryByHook('add-reaction-partial')).prop('hidden', true);
- }
- else{
- $(this.queryByHook('add-reaction-full')).prop('hidden', true);
- }
- this.renderReactionTypes();
- katex.render("\\emptyset", this.queryByHook('emptyset'), {
- displayMode: false,
- output: 'html',
- });
- if(this.opened) {
- this.openReactionsContainer();
+ if(this.readOnly) {
+ this.renderViewReactionView()
+ $(this.queryByHook('reactions-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('reactions-view-tab')).tab('show');
+ $(this.queryByHook('edit-reactions')).removeClass('active');
+ $(this.queryByHook('view-reactions')).addClass('active');
+ }else{
+ this.renderReactionListingViews();
+ this.detailsContainer = this.queryByHook('reaction-details-container');
+ this.detailsViewSwitcher = new ViewSwitcher({
+ el: this.detailsContainer,
+ });
+ if (this.collection.length) {
+ this.setSelectedReaction(this.collection.at(0));
+ this.collection.trigger("select", this.selectedReaction);
+ }
+ this.collection.trigger("change");
+ this.toggleAddReactionButton();
+ if(this.collection.parent.parameters.length > 0){
+ $(this.queryByHook('add-reaction-partial')).prop('hidden', true);
+ }
+ else{
+ $(this.queryByHook('add-reaction-full')).prop('hidden', true);
+ }
+ this.renderReactionTypes();
+ katex.render("\\emptyset", this.queryByHook('emptyset'), {
+ displayMode: false,
+ output: 'html',
+ });
+ this.toggleProcessError()
+ $(this.queryByHook('massaction-message')).prop('hidden', this.collection.parent.parameters.length > 0);
}
- this.toggleProcessError()
- $(this.queryByHook('massaction-message')).prop('hidden', this.collection.parent.parameters.length > 0);
},
update: function () {
},
updateValid: function () {
},
- renderReactionListingView: function () {
- if(this.reactionListingView){
- this.reactionListingView.remove();
+ renderReactionListingViews: function () {
+ this.renderEditReactionListingView();
+ this.renderViewReactionView();
+ },
+ renderEditReactionListingView: function () {
+ if(this.editReactionListingView){
+ this.editReactionListingView.remove();
}
if(this.collection.parent.parameters.length <= 0) {
for(var i = 0; i < this.collection.length; i++) {
@@ -116,10 +130,10 @@ module.exports = View.extend({
}
}
}
- this.reactionListingView = this.renderCollection(
+ this.editReactionListingView = this.renderCollection(
this.collection,
ReactionListingView,
- this.queryByHook('reaction-list')
+ this.queryByHook('edit-reaction-list')
);
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
@@ -128,6 +142,27 @@ module.exports = View.extend({
});
});
},
+ renderViewReactionView: function () {
+ if(this.viewReactionListingView){
+ this.viewReactionListingView.remove();
+ }
+ if(!this.collection.parent.is_spatial){
+ $(this.queryByHook("reaction-types-header")).css("display", "none");
+ }
+ this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("reaction-annotation-header")).css("display", "none");
+ }else{
+ $(this.queryByHook("reaction-annotation-header")).css("display", "block");
+ }
+ let options = {viewOptions: {viewMode: true, hasAnnotations: this.containsMdlWithAnn}}
+ this.viewReactionListingView = this.renderCollection(
+ this.collection,
+ ReactionListingView,
+ this.queryByHook('view-reaction-list'),
+ options
+ );
+ },
toggleAddReactionButton: function () {
$(this.queryByHook('add-reaction-full')).prop('disabled', (this.collection.parent.species.length <= 0));
$(this.queryByHook('add-reaction-partial')).prop('disabled', (this.collection.parent.species.length <= 0));
@@ -186,10 +221,6 @@ module.exports = View.extend({
detailsView.parent = this;
return detailsView
},
- switchToViewMode: function (e) {
- this.parent.modelStateButtons.clickSaveHandler(e);
- this.parent.renderReactionsView(mode="view");
- },
openReactionsContainer: function () {
$(this.queryByHook('reactions-list-container')).collapse('show');
let collapseBtn = $(this.queryByHook('collapse'))
@@ -206,8 +237,9 @@ module.exports = View.extend({
return ReactionTypes[type].label
},
toggleProcessError: function () {
- let errorMsg = $(this.queryByHook('process-component-error'))
let model = this.collection.parent
+ if(model.is_spatial) {return};
+ let errorMsg = $(this.queryByHook('process-component-error'))
if(this.collection.length <= 0 && model.eventsCollection.length <= 0 && model.rules.length <= 0) {
errorMsg.addClass('component-invalid')
errorMsg.removeClass('component-valid')
diff --git a/client/views/reactions-viewer.js b/client/views/reactions-viewer.js
deleted file mode 100644
index ee31d9b390..0000000000
--- a/client/views/reactions-viewer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var ViewReactions = require('./view-reactions');
-//templates
-var template = require('../templates/includes/reactionsViewer.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'click [data-hook=collapse]' : 'changeCollapseButtonText',
- 'click [data-hook=edit-reactions]' : 'switchToEditMode'
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewReactions, this.queryByHook('reaction-list'))
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip();
- $('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
- });
- },
- switchToEditMode: function (e) {
- this.parent.renderReactionsView("edit", true);
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
- },
-});
\ No newline at end of file
diff --git a/client/views/rules-editor.js b/client/views/rules-editor.js
index fdba4cb842..6c0145acad 100644
--- a/client/views/rules-editor.js
+++ b/client/views/rules-editor.js
@@ -31,38 +31,70 @@ module.exports = View.extend({
events: {
'click [data-hook=rate-rule]' : 'addRule',
'click [data-hook=assignment-rule]' : 'addRule',
- 'click [data-hook=save-rules]' : 'switchToViewMode',
'click [data-hook=collapse]' : 'changeCollapseButtonText',
},
- initialize: function (args) {
+ initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
this.collection.parent.species.on('add remove', this.toggleAddRuleButton, this);
this.collection.parent.parameters.on('add remove', this.toggleAddRuleButton, this);
this.tooltips = Tooltips.rulesEditor
- this.opened = args.opened
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderRules();
- this.toggleAddRuleButton()
- if(this.opened) {
- this.openRulesContainer();
+ if(this.readOnly) {
+ $(this.queryByHook('rules-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('rules-view-tab')).tab('show');
+ $(this.queryByHook('edit-rules')).removeClass('active');
+ $(this.queryByHook('view-rules')).addClass('active');
+ }else {
+ this.renderEditRules();
+ this.toggleAddRuleButton();
}
+ this.renderViewRules();
},
update: function () {
},
updateValid: function () {
},
- renderRules: function () {
+ renderEditRules: function () {
if(this.rulesView) {
this.rulesView.remove();
}
this.rulesView = this.renderCollection(
this.collection,
RuleView,
- this.queryByHook('rule-list-container')
+ this.queryByHook('edit-rule-list-container')
+ );
+ $(function () {
+ $('[data-toggle="tooltip"]').tooltip();
+ $('[data-toggle="tooltip"]').click(function () {
+ $('[data-toggle="tooltip"]').tooltip("hide");
+ });
+ });
+ },
+ renderViewRules: function () {
+ if(this.viewRulesView) {
+ this.viewRulesView.remove();
+ }
+ this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("rules-annotation-header")).css("display", "none");
+ }else{
+ $(this.queryByHook("rules-annotation-header")).css("display", "block");
+ }
+ let options = {viewOptions: {viewMode: true}};
+ this.viewRulesView = this.renderCollection(
+ this.collection,
+ RuleView,
+ this.queryByHook('view-rules-list-container'),
+ options
);
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
@@ -70,7 +102,7 @@ module.exports = View.extend({
});
},
toggleAddRuleButton: function () {
- this.renderRules();
+ this.renderEditRules();
var numSpecies = this.collection.parent.species.length;
var numParameters = this.collection.parent.parameters.length;
var disabled = numSpecies <= 0 && numParameters <= 0
@@ -79,7 +111,7 @@ module.exports = View.extend({
addRule: function (e) {
var type = e.target.dataset.name
this.collection.addRule(type);
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
@@ -87,15 +119,6 @@ module.exports = View.extend({
});
});
},
- switchToViewMode: function (e) {
- this.parent.modelStateButtons.clickSaveHandler(e);
- this.parent.renderRulesView(mode="view");
- },
- openRulesContainer: function () {
- $(this.queryByHook('rules-list-container')).collapse('show');
- let collapseBtn = $(this.queryByHook('collapse'))
- collapseBtn.trigger('click')
- },
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
},
diff --git a/client/views/rules-viewer.js b/client/views/rules-viewer.js
deleted file mode 100644
index a8fce201da..0000000000
--- a/client/views/rules-viewer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var ViewRules = require('./view-rules');
-//templates
-var template = require('../templates/includes/rulesViewer.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'click [data-hook=collapse]' : 'changeCollapseButtonText',
- 'click [data-hook=edit-rules]' : 'switchToEditMode'
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewRules, this.queryByHook('rules-list'))
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip();
- $('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
- });
- },
- switchToEditMode: function (e) {
- this.parent.renderRulesView("edit", true);
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
- },
-});
\ No newline at end of file
diff --git a/client/views/sbml-component-editor.js b/client/views/sbml-component-editor.js
index 565b097bc4..e7f58940ab 100644
--- a/client/views/sbml-component-editor.js
+++ b/client/views/sbml-component-editor.js
@@ -36,22 +36,58 @@ module.exports = View.extend({
View.prototype.initialize.apply(this, arguments);
this.tooltips = Tooltips.sbmlComponentsEditor
this.functionDefinitions = attrs.functionDefinitions;
- this.viewMode = attrs.viewMode;
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
},
render: function () {
View.prototype.render.apply(this, arguments);
- this.renderEdirFunctionDefinitionView();
+ if(this.readOnly) {
+ $(this.queryByHook('function-definitions-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('function-definitions-view-tab')).tab('show');
+ $(this.queryByHook('edit-function-definitions')).removeClass('active');
+ $(this.queryByHook('view-function-definitions')).addClass('active');
+ }else {
+ this.renderEditFunctionDefinitionView();
+ }
+ this.renderViewFunctionDefinitionView();
},
- renderEdirFunctionDefinitionView: function () {
+ renderEditFunctionDefinitionView: function () {
if(this.editFunctionDefinitionView){
this.editFunctionDefinitionView.remove();
}
this.editFunctionDefinitionView = this.renderCollection(
this.functionDefinitions,
EditFunctionDefinition,
- this.queryByHook('function-definition-list')
+ this.queryByHook('edit-function-definition-list')
+ );
+ $(function () {
+ $('[data-toggle="tooltip"]').tooltip();
+ $('[data-toggle="tooltip"]').click(function () {
+ $('[data-toggle="tooltip"]').tooltip("hide");
+ });
+ });
+ },
+ renderViewFunctionDefinitionView: function () {
+ if(this.viewFunctionDefinitionView) {
+ this.viewFunctionDefinitionView.remove();
+ }
+ let options = {viewOptions: {viewMode: true}};
+ this.containsMdlWithAnn = this.functionDefinitions.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("function-definition-annotation-header")).css("display", "none");
+ }else{
+ $(this.queryByHook("function-definition-annotation-header")).css("display", "block");
+ }
+ this.viewFunctionDefinitionView = this.renderCollection(
+ this.functionDefinitions,
+ EditFunctionDefinition,
+ this.queryByHook('view-function-definition-list'),
+ options
);
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
diff --git a/client/views/species-editor.js b/client/views/species-editor.js
index e604138e74..6eb3a6b445 100644
--- a/client/views/species-editor.js
+++ b/client/views/species-editor.js
@@ -16,54 +16,53 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-var $ = require('jquery');
+let $ = require('jquery');
//support files
let app = require('../app');
-var modals = require('../modals');
-var Tooltips = require('../tooltips');
+let Tooltips = require('../tooltips');
//views
-var View = require('ampersand-view');
-var EditNonspatialSpecieView = require('./edit-specie');
-var EditSpatialSpecieView = require('./edit-spatial-specie');
-var EditAdvancedSpecie = require('./edit-advanced-specie');
+let View = require('ampersand-view');
+let SpecieView = require('./edit-species');
//templates
-var nonspatialSpecieTemplate = require('../templates/includes/speciesEditor.pug');
-var spatialSpecieTemplate = require('../templates/includes/spatialSpeciesEditor.pug');
+let speciesTemplate = require('../templates/includes/speciesEditor.pug');
+let spatialSpeciesTemplate = require('../templates/includes/spatialSpeciesEditor.pug');
module.exports = View.extend({
events: {
- 'change [data-hook=all-continuous]' : 'getDefaultSpeciesMode',
- 'change [data-hook=all-discrete]' : 'getDefaultSpeciesMode',
- 'change [data-hook=advanced]' : 'getDefaultSpeciesMode',
- 'click [data-hook=add-species]' : 'handleAddSpeciesClick',
- 'click [data-hook=save-species]' : 'switchToViewMode',
'click [data-hook=collapse]' : 'changeCollapseButtonText',
+ 'click [data-hook=add-species]' : 'handleAddSpeciesClick'
},
initialize: function (attrs, options) {
- var self = this;
View.prototype.initialize.apply(this, arguments);
- this.baseModel = this.collection.parent;
- this.tooltips = Tooltips.speciesEditor
+ this.spatial = attrs.spatial
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
+ this.template = this.spatial ? spatialSpeciesTemplate : speciesTemplate;
+ this.tooltips = Tooltips.speciesEditor;
+ this.defaultMode = attrs.defaultMode;
+ let self = this
this.collection.on('update-species', function (compID, specie, isNameUpdate, isDefaultMode) {
- self.collection.parent.reactions.map(function (reaction) {
- reaction.reactants.map(function (reactant) {
+ self.collection.parent.reactions.forEach(function (reaction) {
+ reaction.reactants.forEach(function (reactant) {
if(reactant.specie.compID === compID) {
reactant.specie = specie;
}
});
- reaction.products.map(function (product) {
+ reaction.products.forEach(function (product) {
if(product.specie.compID === compID) {
product.specie = specie;
}
});
if(isNameUpdate) {
reaction.buildSummary();
+ if(reaction.selected) {
+ self.parent.reactionsEditor.setDetailsView(reaction);
+ }
}else if(!isDefaultMode || specie.compID === self.collection.models[self.collection.length-1].compID){
reaction.checkModes();
}
});
- self.collection.parent.eventsCollection.map(function (event) {
- event.eventAssignments.map(function (assignment) {
+ self.collection.parent.eventsCollection.forEach(function (event) {
+ event.eventAssignments.forEach(function (assignment) {
if(assignment.variable.compID === compID) {
assignment.variable = specie;
}
@@ -72,138 +71,105 @@ module.exports = View.extend({
event.detailsView.renderEventAssignments();
}
});
- self.collection.parent.rules.map(function (rule) {
+ self.collection.parent.rules.forEach(function (rule) {
if(rule.variable.compID === compID) {
rule.variable = specie;
}
});
if(isNameUpdate) {
- self.renderSpeciesAdvancedView();
self.parent.renderRulesView();
}
});
},
render: function () {
- this.template = this.parent.model.is_spatial ? spatialSpecieTemplate : nonspatialSpecieTemplate;
View.prototype.render.apply(this, arguments);
- var defaultMode = this.collection.parent.defaultMode;
- if(defaultMode === "" && !this.collection.parent.is_spatial){
- this.getInitialDefaultSpeciesMode();
+ if(this.readOnly) {
+ $(this.queryByHook('species-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('species-view-tab')).tab('show');
+ $(this.queryByHook('edit-species')).removeClass('active');
+ $(this.queryByHook('view-species')).addClass('active');
}else{
- var dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}
- $(this.queryByHook(dataHooks[this.collection.parent.defaultMode])).prop('checked', true)
- if(defaultMode === "dynamic"){
- $(this.queryByHook('advanced-species')).collapse('show');
- }
+ this.toggleSpeciesCollectionError();
+ this.renderEditSpeciesView();
}
- this.renderEditSpeciesView();
- this.renderSpeciesAdvancedView();
- this.toggleSpeciesCollectionError();
+ this.renderViewSpeciesView();
},
- update: function () {
- },
- updateValid: function (e) {
- },
- getInitialDefaultSpeciesMode: function () {
- var self = this;
- if(document.querySelector('#defaultModeModal')) {
- document.querySelector('#defaultModeModal').remove()
+ addSpecies: function () {
+ if(this.parent.model.domain.types) {
+ var types = this.parent.model.domain.types.map(function (type) {
+ return type.typeID;
+ });
+ types.shift()
+ }else{
+ var types = []
}
- let modal = $(modals.renderDefaultModeModalHtml()).modal();
- let continuous = document.querySelector('#defaultModeModal .concentration-btn');
- let discrete = document.querySelector('#defaultModeModal .population-btn');
- let dynamic = document.querySelector('#defaultModeModal .hybrid-btn');
- continuous.addEventListener('click', function (e) {
- self.setInitialDefaultMode(modal, "continuous");
- });
- discrete.addEventListener('click', function (e) {
- self.setInitialDefaultMode(modal, "discrete");
- });
- dynamic.addEventListener('click', function (e) {
- self.setInitialDefaultMode(modal, "dynamic");
+ this.collection.addSpecie(types);
+ this.toggleSpeciesCollectionError()
+ $(function () {
+ $('[data-toggle="tooltip"]').tooltip();
+ $('[data-toggle="tooltip"]').click(function () {
+ $('[data-toggle="tooltip"]').tooltip("hide");
+
+ });
});
},
- setInitialDefaultMode: function (modal, mode) {
- var dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}
- modal.modal('hide')
- $(this.queryByHook(dataHooks[mode])).prop('checked', true)
- this.setAllSpeciesModes(mode)
- },
- getDefaultSpeciesMode: function (e) {
- var self = this;
- this.setAllSpeciesModes(e.target.dataset.name, function (specie) {
- self.collection.trigger('update-species', specie.compID, specie, false, true)
- });
+ changeCollapseButtonText: function (e) {
+ app.changeCollapseButtonText(this, e);
},
- setAllSpeciesModes: function (defaultMode, cb) {
- this.collection.parent.defaultMode = defaultMode;
- if(!this.collection.parent.is_spatial) {
- if(defaultMode === "continuous") {
- $(this.parent.queryByHook("system-volume-container")).collapse("hide")
- }else{
- $(this.parent.queryByHook("system-volume-container")).collapse("show")
- }
- this.collection.map(function (specie) {
- specie.mode = defaultMode
- cb(specie)
- });
- if(defaultMode === "dynamic"){
- this.renderSpeciesAdvancedView()
- $(this.queryByHook('advanced-species')).collapse('show');
- }
- else{
- this.speciesAdvancedView.views[0].updateInputValidation()
- $(this.queryByHook('advanced-species')).collapse('hide');
- }
+ handleAddSpeciesClick: function (e) {
+ let self = this;
+ let defaultMode = this.collection.parent.defaultMode;
+ if(defaultMode === "" && !this.collection.parent.is_spatial){
+ this.parent.getInitialDefaultMode();
+ }else{
+ this.addSpecies();
}
},
renderEditSpeciesView: function () {
if(this.editSpeciesView){
this.editSpeciesView.remove();
}
- var editSpecieView = !this.collection.parent.is_spatial ? EditNonspatialSpecieView : EditSpatialSpecieView;
+ let options = {viewOptions: {parent: this}};
this.editSpeciesView = this.renderCollection(
this.collection,
- editSpecieView,
- this.queryByHook('specie-list')
+ SpecieView,
+ this.queryByHook('edit-specie-list')
);
- $(document).ready(function () {
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
+ $('[data-toggle="tooltip"]').tooltip("hide");
+
+ });
});
},
- renderSpeciesAdvancedView: function () {
- if(this.collection.parent.is_spatial) {
- return
- }
- if(this.speciesAdvancedView) {
- this.speciesAdvancedView.remove()
+ renderViewSpeciesView: function () {
+ if(this.viewSpeciesView){
+ this.viewSpeciesView.remove();
}
- this.speciesAdvancedView = this.renderCollection(this.collection, EditAdvancedSpecie, this.queryByHook('edit-species-mode'));
- },
- handleAddSpeciesClick: function (e) {
- var self = this;
- var defaultMode = this.collection.parent.defaultMode;
- if(defaultMode === "" && !this.collection.parent.is_spatial){
- this.getInitialDefaultSpeciesMode();
+ if(this.defaultMode !== "dynamic") {
+ $(this.queryByHook("species-switching-header")).css("display", "none");
}else{
- this.addSpecies();
+ $(this.queryByHook("species-switching-header")).css("display", "block");
}
- },
- addSpecies: function () {
- if(this.parent.model.domain.types) {
- var types = this.parent.model.domain.types.map(function (type) {
- return type.typeID;
- });
- types.shift()
+ this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0;
+ if(!this.containsMdlWithAnn) {
+ $(this.queryByHook("species-annotation-header")).css("display", "none");
}else{
- var types = []
+ $(this.queryByHook("species-annotation-header")).css("display", "block");
}
- this.collection.addSpecie(types);
- this.toggleSpeciesCollectionError()
- $(document).ready(function () {
+ let options = {viewOptions: {parent: this, viewMode: true}};
+ this.viewSpeciesView = this.renderCollection(
+ this.collection,
+ SpecieView,
+ this.queryByHook('view-specie-list'),
+ options
+ );
+ $(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");
@@ -212,6 +178,7 @@ module.exports = View.extend({
});
},
toggleSpeciesCollectionError: function () {
+ if(this.spatial) {return};
let errorMsg = $(this.queryByHook('species-collection-error'))
if(this.collection.length <= 0) {
errorMsg.addClass('component-invalid')
@@ -220,12 +187,5 @@ module.exports = View.extend({
errorMsg.addClass('component-valid')
errorMsg.removeClass('component-invalid')
}
- },
- switchToViewMode: function (e) {
- this.parent.modelStateButtons.clickSaveHandler(e);
- this.parent.renderSpeciesView(mode="view");
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
}
-});
\ No newline at end of file
+});
diff --git a/client/views/species-viewer.js b/client/views/species-viewer.js
deleted file mode 100644
index 7087d36bca..0000000000
--- a/client/views/species-viewer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var ViewSpecie = require('./view-specie');
-//templates
-var template = require('../templates/includes/speciesViewer.pug');
-
-module.exports = View.extend({
- template: template,
- events: {
- 'click [data-hook=collapse]' : 'changeCollapseButtonText',
- 'click [data-hook=edit-species]' : 'switchToEditMode'
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- this.renderCollection(this.collection, ViewSpecie, this.queryByHook('specie-list'))
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip();
- $('[data-toggle="tooltip"]').click(function () {
- $('[data-toggle="tooltip"]').tooltip("hide");
- });
- });
- },
- switchToEditMode: function (e) {
- this.parent.renderSpeciesView();
- },
- changeCollapseButtonText: function (e) {
- app.changeCollapseButtonText(this, e);
- },
-});
\ No newline at end of file
diff --git a/client/views/timespan-settings.js b/client/views/timespan-settings.js
index 22b8cd3fbf..fa5f87cb4b 100644
--- a/client/views/timespan-settings.js
+++ b/client/views/timespan-settings.js
@@ -31,15 +31,29 @@ module.exports = View.extend({
template: template,
events: {
'click [data-hook=collapse]' : 'changeCollapseButtonText',
- },
- bindings: {
+ 'input [data-hook=timestep-size-slider]' : 'viewTimestepValue',
+ 'change [data-hook=preview-time]' : 'updateViewer',
+ 'change [data-hook=time-units]' : 'updateViewer',
+ 'change [data-hook=timestep-size-slider]' : 'setTimestepSize'
},
initialize: function (attrs, options) {
View.prototype.initialize.apply(this, arguments);
+ this.readOnly = attrs.readOnly ? attrs.readOnly : false;
this.tooltips = Tooltips.modelSettings
},
render: function () {
View.prototype.render.apply(this, arguments);
+ if(this.readOnly) {
+ $(this.queryByHook('timespan-edit-tab')).addClass("disabled");
+ $(".nav .disabled>a").on("click", function(e) {
+ e.preventDefault();
+ return false;
+ });
+ $(this.queryByHook('timespan-view-tab')).tab('show');
+ $(this.queryByHook('edit-timespan')).removeClass('active');
+ $(this.queryByHook('view-timespan')).addClass('active');
+ }
+ $(this.queryByHook("timestep-size-value")).html(this.model.timestepSize);
},
update: function (e) {
},
@@ -49,6 +63,18 @@ module.exports = View.extend({
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
},
+ setTimestepSize: function (e) {
+ this.model.timestepSize = Number(e.target.value);
+ $(this.queryByHook("view-timestep-size")).html(this.model.timestepSize);
+ },
+ updateViewer: function (e) {
+ $(this.queryByHook("view-end-sim")).html("0 to " + this.model.endSim);
+ $(this.queryByHook("view-time-step")).html(this.model.timeStep);
+ },
+ viewTimestepValue: function (e) {
+ let value = e.target.value;
+ $(this.queryByHook("timestep-size-value")).html(value);
+ },
subviews: {
inputSimEnd: {
hook: 'preview-time',
diff --git a/client/views/view-event-assignments.js b/client/views/view-event-assignments.js
deleted file mode 100644
index 709bab1ce8..0000000000
--- a/client/views/view-event-assignments.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-//views
-var View = require('ampersand-view');
-//templates
-var template = require('../templates/includes/viewEventAssignments.pug');
-
-module.exports = View.extend({
- template: template,
-});
\ No newline at end of file
diff --git a/client/views/view-events.js b/client/views/view-events.js
deleted file mode 100644
index 0b04864060..0000000000
--- a/client/views/view-events.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var $ = require('jquery');
-//support files
-let app = require('../app');
-//views
-var View = require('ampersand-view');
-var AssignmentsViewer = require('./event-assignments-viewer');
-//templates
-var template = require('../templates/includes/viewEvents.pug');
-
-module.exports = View.extend({
- template: template,
- bindings: {
- 'model.initialValue': {
- hook: 'event-trigger-init-value',
- type: 'booleanAttribute',
- name: 'checked',
- },
- 'model.persistent': {
- hook: 'event-trigger-persistent',
- type: 'booleanAttribute',
- name: 'checked',
- }
- },
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- this.delay = this.model.delay === "" ? "None" : this.model.delay
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- var assignmentsViewer = new AssignmentsViewer({
- collection: this.model.eventAssignments
- });
- app.registerRenderSubview(this, assignmentsViewer, 'assignment-viewer');
- if(this.model.useValuesFromTriggerTime) {
- $(this.queryByHook("trigger-time")).prop('checked', true)
- }else{
- $(this.queryByHook("assignment-time")).prop('checked', true)
- }
- }
-});
\ No newline at end of file
diff --git a/client/views/view-parameter.js b/client/views/view-parameter.js
deleted file mode 100644
index a5ba33c0a4..0000000000
--- a/client/views/view-parameter.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-//views
-var View = require('ampersand-view');
-//templates
-var template = require('../templates/includes/viewParameters.pug');
-
-module.exports = View.extend({
- template: template,
-});
\ No newline at end of file
diff --git a/client/views/view-reactions.js b/client/views/view-reactions.js
deleted file mode 100644
index be5a565ab5..0000000000
--- a/client/views/view-reactions.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-var katex = require('katex');
-//views
-var View = require('ampersand-view');
-//templates
-var template = require('../templates/includes/viewReactions.pug');
-
-module.exports = View.extend({
- template: template,
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- let self = this;
- this.types = [];
- if(this.model.types) {
- this.model.types.forEach(function (index) {
- let type = self.model.collection.parent.domain.types.get(index, "typeID");
- self.types.push(type.name)
- });
- }
- this.rate = this.model.reactionType === "custom-propensity" ?
- this.model.propensity : this.model.rate.name
- },
- render: function () {
- View.prototype.render.apply(this, arguments);
- katex.render(this.model.summary, this.queryByHook('summary'), {
- displayMode: false,
- output: 'html',
- throwOnError: false
- });
- },
-});
\ No newline at end of file
diff --git a/client/views/view-rules.js b/client/views/view-rules.js
deleted file mode 100644
index c4939f45d4..0000000000
--- a/client/views/view-rules.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-//views
-var View = require('ampersand-view');
-//templates
-var template = require('../templates/includes/viewRules.pug');
-
-module.exports = View.extend({
- template: template,
-});
\ No newline at end of file
diff --git a/client/views/view-specie.js b/client/views/view-specie.js
deleted file mode 100644
index f0a5ee22be..0000000000
--- a/client/views/view-specie.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-StochSS is a platform for simulating biochemical systems
-Copyright (C) 2019-2020 StochSS developers.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-//views
-var View = require('ampersand-view');
-//templates
-var template = require('../templates/includes/viewSpecies.pug');
-
-module.exports = View.extend({
- template: template,
- initialize: function (attrs, options) {
- View.prototype.initialize.apply(this, arguments);
- let self = this;
- this.types = [];
- if(this.model.types) {
- this.model.types.forEach(function (index) {
- let type = self.model.collection.parent.domain.types.get(index, "typeID");
- self.types.push(type.name)
- });
- }
- this.switchingValWithLabel = this.model.isSwitchTol ?
- "Switching Tolerance: " + this.model.switchTol :
- "Minimum Value For Switching: " + this.model.switchMin
- },
-});
\ No newline at end of file
diff --git a/stochss/handlers/models.py b/stochss/handlers/models.py
index a55a29a947..b4a4a62755 100644
--- a/stochss/handlers/models.py
+++ b/stochss/handlers/models.py
@@ -215,7 +215,8 @@ async def get(self):
exec_cmd = ['/stochss/stochss/handlers/util/scripts/run_preview.py',
f'{path}', f'{outfile}']
if species is not None:
- exec_cmd.append(f"{species}")
+ exec_cmd.insert(1, "--species")
+ exec_cmd.insert(2, f"{species}")
log.debug("Script commands for running a preview: %s", exec_cmd)
subprocess.Popen(exec_cmd)
resp['Running'] = True
diff --git a/stochss/handlers/util/ensemble_simulation.py b/stochss/handlers/util/ensemble_simulation.py
index 925922e2c2..2b220e21fb 100644
--- a/stochss/handlers/util/ensemble_simulation.py
+++ b/stochss/handlers/util/ensemble_simulation.py
@@ -119,7 +119,7 @@ def __update_timespan(self):
if "endSim" in keys and "timeStep" in keys:
end = self.settings['timespanSettings']['endSim']
step_size = self.settings['timespanSettings']['timeStep']
- self.g_model.timespan(numpy.arange(0, end, step_size))
+ self.g_model.timespan(numpy.arange(0, end + step_size, step_size))
def run(self, preview=False, verbose=True):
diff --git a/stochss/handlers/util/parameter_sweep.py b/stochss/handlers/util/parameter_sweep.py
index 20635e18f6..d1a4a909c2 100644
--- a/stochss/handlers/util/parameter_sweep.py
+++ b/stochss/handlers/util/parameter_sweep.py
@@ -197,7 +197,7 @@ def configure(self):
if "endSim" in keys and "timeStep" in keys:
end = self.settings['timespanSettings']['endSim']
step_size = self.settings['timespanSettings']['timeStep']
- self.g_model.timespan(numpy.arange(0, end, step_size))
+ self.g_model.timespan(numpy.arange(0, end + step_size, step_size))
kwargs = {"model":self.g_model, "settings":run_settings}
parameters = []
for param in self.settings['parameterSweepSettings']['parameters']:
diff --git a/stochss/handlers/util/stochss_model.py b/stochss/handlers/util/stochss_model.py
index be448194b1..6b617b2385 100644
--- a/stochss/handlers/util/stochss_model.py
+++ b/stochss/handlers/util/stochss_model.py
@@ -134,7 +134,7 @@ def __convert_model_settings(self):
try:
end = self.model['modelSettings']['endSim']
step_size = self.model['modelSettings']['timeStep']
- return numpy.arange(0, end, step_size)
+ return numpy.arange(0, end + step_size, step_size)
except KeyError as err:
message = "Model settings are not properly formatted or "
message += f"are referenced incorrectly: {str(err)}"
@@ -380,6 +380,8 @@ def convert_to_spatial(self):
if self.model is None:
model = self.load()
model['is_spatial'] = True
+ if "timestepSize" not in self.model['modelSettings'].keys():
+ self.model['modelSettings']['timestepSize'] = self.model['modelSettings']['timeStep']
if "domain" not in model.keys():
model['domain'] = self.get_model_template()['domain']
for species in model['species']:
diff --git a/stochss/handlers/util/stochss_notebook.py b/stochss/handlers/util/stochss_notebook.py
index 2a02836cd8..41840f149e 100644
--- a/stochss/handlers/util/stochss_notebook.py
+++ b/stochss/handlers/util/stochss_notebook.py
@@ -265,7 +265,6 @@ def __create_model_cell(self):
self.__create_initial_condition_strings(model=model, pad=pad)
self.__create_parameter_strings(model=model, pad=pad)
self.__create_reaction_strings(model=model, pad=pad)
- self.__create_tspan_string(model=model, pad=pad)
else:
model = [f"class {self.__get_class_name()}(Model):",
" def __init__(self, parameter_values=None):",
@@ -277,7 +276,7 @@ def __create_model_cell(self):
self.__create_event_strings(model=model, pad=pad)
self.__create_rules_strings(model=model, pad=pad)
self.__create_function_definition_strings(model=model, pad=pad)
- self.__create_tspan_string(model=model, pad=pad)
+ self.__create_tspan_string(model=model, pad=pad)
return nbf.new_code_cell("\n".join(model))
def __create_parameter_strings(self, model, pad):
@@ -770,13 +769,14 @@ def __create_stoich_spec_string(self, stoich_species):
def __create_tspan_string(self, model, pad):
end = self.s_model['modelSettings']['endSim']
- step = self.s_model['modelSettings']['timeStep']
+ output_freq = self.s_model['modelSettings']['timeStep']
+ step_size = self.s_model['modelSettings']['timestepSize']
tspan = ["", f"{pad}# Timespan"]
- ts_str = f'{pad}self.timespan(np.arange(0, {end}, {step})'
if self.s_model['is_spatial']:
- ts_str += f", timestep_size={step})"
+ ts_str = f'{pad}self.timespan(np.arange(0, {end + step_size}, {output_freq})'
+ ts_str += f", timestep_size={step_size})"
else:
- ts_str += ")"
+ ts_str = f'{pad}self.timespan(np.arange(0, {end + output_freq}, {output_freq}))'
tspan.append(ts_str)
model.extend(tspan)
diff --git a/stochss/handlers/util/stochss_spatial_model.py b/stochss/handlers/util/stochss_spatial_model.py
index e0f444ca0e..b667f7b020 100644
--- a/stochss/handlers/util/stochss_spatial_model.py
+++ b/stochss/handlers/util/stochss_spatial_model.py
@@ -169,8 +169,9 @@ def __convert_initial_conditions(self, model):
def __convert_model_settings(self, model):
try:
end = self.model['modelSettings']['endSim']
- step_size = self.model['modelSettings']['timeStep']
- tspan = numpy.arange(0, end, step_size)
+ output_freq = self.model['modelSettings']['timeStep']
+ step_size = self.model['modelSettings']['timestepSize']
+ tspan = numpy.arange(0, end + step_size, output_freq)
model.timespan(tspan, timestep_size=step_size)
except KeyError as err:
message = "Spatial model settings are not properly formatted or "
@@ -525,6 +526,8 @@ def load(self):
self.model['name'] = self.get_name()
if not self.model['defaultMode']:
self.model['defaultMode'] = "discrete"
+ if "timestepSize" not in self.model['modelSettings'].keys():
+ self.model['modelSettings']['timestepSize'] = self.model['modelSettings']['timeStep']
if "domain" not in self.model.keys() or len(self.model['domain'].keys()) < 6:
self.model['domain'] = self.get_model_template()['domain']
elif "static" not in self.model['domain'].keys():
diff --git a/stochss_templates/nonSpatialModelTemplate.json b/stochss_templates/nonSpatialModelTemplate.json
index 248896e2cc..514f8cd8a6 100644
--- a/stochss_templates/nonSpatialModelTemplate.json
+++ b/stochss_templates/nonSpatialModelTemplate.json
@@ -6,7 +6,8 @@
"volume": 1,
"modelSettings": {
"endSim": 20,
- "timeStep": 0.05
+ "timeStep": 0.05,
+ "timestepSize": 1e-5
},
"domain": {
"size": null,
diff --git a/stochss_templates/workflowSettingsTemplate.json b/stochss_templates/workflowSettingsTemplate.json
index 85bfd2de1a..b1a402f656 100644
--- a/stochss_templates/workflowSettingsTemplate.json
+++ b/stochss_templates/workflowSettingsTemplate.json
@@ -19,6 +19,7 @@
},
"timespanSettings": {
"endSim": 20,
- "timeStep": 0.05
+ "timeStep": 0.05,
+ "timestepSize": 1e-5
}
}
\ No newline at end of file