Skip to content

Commit

Permalink
Merge pull request #1446 from StochSS/develop
Browse files Browse the repository at this point in the history
2.5.2 Release
  • Loading branch information
briandrawert authored May 2, 2023
2 parents f5224a4 + 1f265b6 commit f4b1f9f
Show file tree
Hide file tree
Showing 83 changed files with 5,473 additions and 658 deletions.
2 changes: 1 addition & 1 deletion __version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# @website https://github.com/stochss/stochss
# =============================================================================

__version__ = '2.5.1'
__version__ = '2.5.2'
__title__ = 'StochSS'
__description__ = 'StochSS is an integrated development environment (IDE) \
for simulation of biochemical networks.'
Expand Down
204 changes: 106 additions & 98 deletions client/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,6 @@ let changeCollapseButtonText = (view, e) => {
text === '+' ? collapseBtn.text('-') : collapseBtn.text('+');
}
}
let copyToClipboard = (text, success, error) => {
fullURL = window.location.protocol + '//' + window.location.hostname + text;
if (window.clipboardData && window.clipboardData.setData) {
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
return window.clipboardData.setData("Text", fullURL);
}
else {
navigator.clipboard.writeText(fullURL).then(success, error);
}
}
let documentSetup = () => {
tooltipSetup();
$(document).on('shown.bs.modal', (e) => {
$('[autofocus]', e.target).focus();
});
$(document).on('hide.bs.modal', '.modal', (e) => {
e.target.remove();
});
}
let getApiPath = () => path.join(getBasePath(), apiPrefix);
let getBasePath = () => {
try {
Expand Down Expand Up @@ -133,6 +114,112 @@ let getXHR = (endpoint, {
error(exception, response, body);
}
}

let validateName = (input, {rename=false, saveAs=true}={}) => {
var error = "";
if(input.endsWith('/')) {
error = 'forward';
}
var invalidChars = "`~!@#$%^&*=+[{]}\"|:;'<,>?\\";
if(rename || !saveAs) {
invalidChars += "/";
}
for(var i = 0; i < input.length; i++) {
if(invalidChars.includes(input.charAt(i))) {
error = error === "" || error === "special" ? "special" : "both";
}
}
return error;
}

let newWorkflow = (parent, mdlPath, isSpatial, type) => {
if(document.querySelector('#newWorkflowModal')) {
document.querySelector('#newWorkflowModal').remove()
}
let typeCodes = {
"Ensemble Simulation": "_ES",
"Spatial Ensemble Simulation": "_SES",
"Parameter Sweep": "_PS",
"Model Inference": "_MI"
}
let ext = isSpatial ? /.smdl/g : /.mdl/g
let typeCode = typeCodes[type];
let name = mdlPath.split('/').pop().replace(ext, typeCode)
let modal = $(modals.createWorkflowHtml(name, type)).modal();
let okBtn = document.querySelector('#newWorkflowModal .ok-model-btn');
let input = document.querySelector('#newWorkflowModal #workflowNameInput');
okBtn.disabled = false;
input.addEventListener("keyup", (event) => {
if(event.keyCode === 13){
event.preventDefault();
okBtn.click();
}
});
input.addEventListener("input", (e) => {
let endErrMsg = document.querySelector('#newWorkflowModal #workflowNameInputEndCharError')
let charErrMsg = document.querySelector('#newWorkflowModal #workflowNameInputSpecCharError')
let error = validateName(input.value)
okBtn.disabled = error !== "" || input.value.trim() === ""
charErrMsg.style.display = error === "both" || error === "special" ? "block" : "none"
endErrMsg.style.display = error === "both" || error === "forward" ? "block" : "none"
});
okBtn.addEventListener('click', (e) => {
modal.modal("hide");
let wkflFile = `${input.value.trim()}.wkfl`;
if(mdlPath.includes(".proj") && !mdlPath.includes(".wkgp")){
var wkflPath = path.join(path.dirname(mdlPath), "WorkflowGroup1.wkgp", wkflFile);
}else{
var wkflPath = path.join(path.dirname(mdlPath), wkflFile);
}
let queryString = `?path=${wkflPath}&model=${mdlPath}&type=${type}`;
let endpoint = path.join(getApiPath(), "workflow/new") + queryString;
getXHR(endpoint, {
success: (err, response, body) => {
window.location.href = `${path.join(getBasePath(), "stochss/workflow/edit")}?path=${body.path}`;
}
});
});
}

tooltipSetup = () => {
$(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').on('click ', function () {
$('[data-toggle="tooltip"]').tooltip("hide");
});
});
}

documentSetup = () => {
tooltipSetup();
$(document).on('shown.bs.modal', function (e) {
$('[autofocus]', e.target).focus();
});
$(document).on('hide.bs.modal', '.modal', function (e) {
e.target.remove();
});
}

copyToClipboard = (text, success, error) => {
fullURL = window.location.protocol + '//' + window.location.hostname + text;
if (window.clipboardData && window.clipboardData.setData) {
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
return window.clipboardData.setData("Text", fullURL);
}
else {
navigator.clipboard.writeText(fullURL).then(success, error)
}
}

let switchToEditTab = (view, section) => {
let elementID = Boolean(view.model && view.model.elementID) ? view.model.elementID + "-" : "";
if($(view.queryByHook(elementID + 'view-' + section)).hasClass('active')) {
$(view.queryByHook(elementID + section + '-edit-tab')).tab('show');
$(view.queryByHook(elementID + 'edit-' + section)).addClass('active');
$(view.queryByHook(elementID + 'view-' + section)).removeClass('active');
}
}

let maintenance = (view) => {
getXHR("stochss/api/message", {
always: (err, response, body) => {
Expand Down Expand Up @@ -186,53 +273,6 @@ let maintenance = (view) => {
}
});
}
let newWorkflow = (parent, mdlPath, isSpatial, type) => {
if(document.querySelector('#newWorkflowModal')) {
document.querySelector('#newWorkflowModal').remove();
}
let typeCodes = {
"Ensemble Simulation": "_ES",
"Spatial Ensemble Simulation": "_SES",
"Parameter Sweep": "_PS"
}
let ext = isSpatial ? /.smdl/g : /.mdl/g;
let typeCode = typeCodes[type];
let name = mdlPath.split('/').pop().replace(ext, typeCode);
let modal = $(modals.createWorkflowHtml(name, type)).modal();
let okBtn = document.querySelector('#newWorkflowModal .ok-model-btn');
let input = document.querySelector('#newWorkflowModal #workflowNameInput');
okBtn.disabled = false;
input.addEventListener("keyup", (event) => {
if(event.keyCode === 13){
event.preventDefault();
okBtn.click();
}
});
input.addEventListener("input", (e) => {
let endErrMsg = document.querySelector('#newWorkflowModal #workflowNameInputEndCharError');
let charErrMsg = document.querySelector('#newWorkflowModal #workflowNameInputSpecCharError');
let error = validateName(input.value);
okBtn.disabled = error !== "" || input.value.trim() === "";
charErrMsg.style.display = error === "both" || error === "special" ? "block" : "none";
endErrMsg.style.display = error === "both" || error === "forward" ? "block" : "none";
});
okBtn.addEventListener('click', (e) => {
modal.modal("hide");
let wkflFile = `${input.value.trim()}.wkfl`;
if(mdlPath.includes(".proj") && !mdlPath.includes(".wkgp")){
var wkflPath = path.join(path.dirname(mdlPath), "WorkflowGroup1.wkgp", wkflFile);
}else{
var wkflPath = path.join(path.dirname(mdlPath), wkflFile);
}
let queryString = `?path=${wkflPath}&model=${mdlPath}&type=${type}`;
let endpoint = path.join(getApiPath(), "workflow/new") + queryString;
getXHR(endpoint, {
success: (err, response, body) => {
window.location.href = `${path.join(getBasePath(), "stochss/workflow/edit")}?path=${body.path}`;
}
});
});
}
let postXHR = (endpoint, data, {
always = function (err, response, body) {}, success = function (err, response, body) {},
error = function (err, response, body) {}}={}, isJSON) => {
Expand All @@ -258,38 +298,6 @@ let registerRenderSubview = (parent, view, hook) => {
parent.registerSubview(view);
parent.renderSubview(view, parent.queryByHook(hook));
}
let switchToEditTab = (view, section) => {
let elementID = Boolean(view.model && view.model.elementID) ? view.model.elementID + "-" : "";
if($(view.queryByHook(elementID + 'view-' + section)).hasClass('active')) {
$(view.queryByHook(elementID + section + '-edit-tab')).tab('show');
$(view.queryByHook(elementID + 'edit-' + section)).addClass('active');
$(view.queryByHook(elementID + 'view-' + section)).removeClass('active');
}
}
let tooltipSetup = () => {
$(() => {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').on('click ', () => {
$('[data-toggle="tooltip"]').tooltip("hide");
});
});
}
let validateName = (input, {rename=false, saveAs=true}={}) => {
var error = "";
if(input.endsWith('/')) {
error = 'forward';
}
var invalidChars = "`~!@#$%^&*=+[{]}\"|:;'<,>?\\";
if(rename || !saveAs) {
invalidChars += "/";
}
for(var i = 0; i < input.length; i++) {
if(invalidChars.includes(input.charAt(i))) {
error = error === "" || error === "special" ? "special" : "both";
}
}
return error;
}

module.exports = {
changeCollapseButtonText: changeCollapseButtonText,
Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/templates/actionsView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ div#domain-actions-editor.card

a.nav-link.tab(data-hook="actions-view-tab" data-toggle="tab" href="#view-actions") View

button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-actions" data-hook="collapse") +
button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-actions" data-hook="collapse-actions") +

div.card-body

Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/templates/shapesView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ div#domain-geometries-editor.card

a.nav-link.tab(data-hook="shapes-view-tab" data-toggle="tab" href="#view-shapes") View

button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-shapes" data-hook="collapse") +
button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-shapes" data-hook="collapse-shapes") +

div.card-body
p.mb-0
Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/templates/transformationsView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ div#domain-transformation-editor.card

a.nav-link.tab(data-hook="transformations-view-tab" data-toggle="tab" href="#view-transformations") View

button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-transformations" data-hook="collapse") +
button.btn.btn-outline-collapse.inline(data-toggle="collapse" data-target="#collapse-transformations" data-hook="collapse-transformations") +

div.card-body

Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/views/actions-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let template = require('../templates/actionsView.pug');
module.exports = View.extend({
template: template,
events: {
'click [data-hook=collapse]' : 'changeCollapseButtonText',
'click [data-hook=collapse-actions]' : 'changeCollapseButtonText',
'click [data-hook=fill-action]' : 'addAction',
'click [data-hook=set-action]' : 'addAction',
'click [data-hook=remove-action]' : 'addAction',
Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/views/shapes-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let template = require('../templates/shapesView.pug');
module.exports = View.extend({
template: template,
events: {
'click [data-hook=collapse]' : 'changeCollapseButtonText',
'click [data-hook=collapse-shapes]' : 'changeCollapseButtonText',
'click [data-hook=cartesian-lattice]' : 'addShape',
'click [data-hook=spherical-lattice]' : 'addShape',
'click [data-hook=cylindrical-lattice]' : 'addShape'
Expand Down
2 changes: 1 addition & 1 deletion client/domain-view/views/transformations-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let template = require('../templates/transformationsView.pug');
module.exports = View.extend({
template: template,
events: {
'click [data-hook=collapse]' : 'changeCollapseButtonText',
'click [data-hook=collapse-transformations]' : 'changeCollapseButtonText',
'click [data-hook=translate-transformation]' : 'addTransformation',
'click [data-hook=rotate-transformation]' : 'addTransformation',
'click [data-hook=reflect-transformation]' : 'addTransformation',
Expand Down
25 changes: 14 additions & 11 deletions client/domain-view/views/types-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ module.exports = View.extend({
changeCollapseButtonText: function (e) {
app.changeCollapseButtonText(this, e);
},
getParticleCounts: function (particles) {
let particleCounts = {};
particles.forEach((particle) => {
if(particleCounts[particle.type]) {
particleCounts[particle.type] += 1;
}else{
particleCounts[particle.type] = 1;
}
});
this.collection.forEach((type) => {
type.numParticles = particleCounts[type.typeID] ? particleCounts[type.typeID] : 0;
});
},
handleAddDomainType: function () {
let name = this.collection.addType();
this.collection.parent.trigger('update-particle-type-options', {currName: name});
Expand Down Expand Up @@ -135,17 +148,7 @@ module.exports = View.extend({
});
},
updateParticleCounts: function (particles) {
let particleCounts = {};
particles.forEach((particle) => {
if(particleCounts[particle.type]) {
particleCounts[particle.type] += 1;
}else{
particleCounts[particle.type] = 1;
}
});
this.collection.forEach((type) => {
type.numParticles = particleCounts[type.typeID] ? particleCounts[type.typeID] : 0;
});
this.getParticleCounts(particles);
$(this.queryByHook('unassigned-type-count')).text(this.collection.models[0].numParticles);
this.renderEditTypeView();
this.renderViewTypeView();
Expand Down
10 changes: 5 additions & 5 deletions client/job-view/templates/gillespyResultsEnsembleView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ div#workflow-results.card
data-hook="stddevran-plot-csv"
data-target="download-plot-csv"
data-type="stddevran"
) Plot Results as .csv
) Plot CSV Results as .zip

div.card

Expand Down Expand Up @@ -129,7 +129,7 @@ div#workflow-results.card
data-hook="trajectories-plot-csv"
data-target="download-plot-csv"
data-type="trajectories"
) Plot Results as .csv
) Plot CSV Results as .zip

div.card

Expand Down Expand Up @@ -181,7 +181,7 @@ div#workflow-results.card
data-hook="stddev-plot-csv"
data-target="download-plot-csv"
data-type="stddev"
) Plot Results as .csv
) Plot CSV Results as .zip

div.card

Expand Down Expand Up @@ -233,13 +233,13 @@ div#workflow-results.card
data-hook="avg-plot-csv"
data-target="download-plot-csv"
data-type="avg"
) Plot Results as .csv
) Plot CSV Results as .zip

div

button.btn.btn-primary.box-shadow(id="convert-to-notebook" data-hook="convert-to-notebook") Convert to Notebook

button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Full Results as .csv
button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Full CSV Results as .zip

button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish

Expand Down
4 changes: 2 additions & 2 deletions client/job-view/templates/gillespyResultsView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ div#workflow-results.card
data-hook="trajectories-plot-csv"
data-target="download-plot-csv"
data-type="trajectories"
) Plot Results as .csv
) Plot CSV Results as .zip

div

button.btn.btn-primary.box-shadow(id="convert-to-notebook" data-hook="convert-to-notebook") Convert to Notebook

button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Full Results as .csv
button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Full CSV Results as .zip

button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish

Expand Down
Loading

0 comments on commit f4b1f9f

Please sign in to comment.