Skip to content

Commit

Permalink
Merge pull request #1035 from StochSS/usability-updates
Browse files Browse the repository at this point in the history
Usability updates
  • Loading branch information
seanebum authored Oct 13, 2020
2 parents 42f6b54 + a15001a commit c17df7f
Show file tree
Hide file tree
Showing 38 changed files with 469 additions and 245 deletions.
19 changes: 11 additions & 8 deletions client/modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,17 @@ module.exports = {

return templates.input(modalID, inputID, title, label, value)
},
newProjectModelHtml : () => {
newProjectModelHtml : (options) => {
let modalID = "newProjectModelModal"
let inputID = "modelPathInput"
let selectID = "modelPathInput"
let title = "Add Existing Model to Project"
let label = "Path to the Model"
let value = ""
options = options.map(function (name) {
return `<option value="${name}">${name}</option>`
})
options = options.join(" ")

return templates.input(modalID, inputID, title, label, value)
return templates.select(modalID, selectID, title, label, options)
},
addExistingWorkflowToProjectHtml : () => {
let modalID = "newProjectWorkflowModal"
Expand Down Expand Up @@ -424,16 +427,16 @@ module.exports = {
return templates.message(modalID, title, message)
},
renderDefaultModeModalHtml : () => {
let concentrationDesciption = `Species will only be represented using continuous (floating point) values.`;
let populationDescription = `Population - Species will only be represented using discrete (integer count) values.`;
let concentrationDesciption = `Variables will only be represented using continuous (floating point) values.`;
let populationDescription = `Population - Variables will only be represented using discrete (integer count) values.`;
let hybridDescription = `Allows a species to be represented using continuous and/or discrete values.`;

return `
<div id="defaultModeModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content info">
<div class="modal-header">
<h5 class="modal-title">Default Species Mode (required)</h5>
<h5 class="modal-title">Default Variables Mode (required)</h5>
<button type="button" class="close close-modal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
Expand All @@ -442,7 +445,7 @@ module.exports = {
<div>
<p>
The default mode is used to set the mode of all species added to the model.
The mode of a species is used to determine how it will be represented in a Hybrid simulation.
The mode of a species is used to determine how it will be represented in a Hybrid Concentration/Population simulation.
</p>
<p>Select one of the following: </p>
</div>
Expand Down
33 changes: 10 additions & 23 deletions client/pages/file-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -679,37 +679,24 @@ let FileBrowser = PageView.extend({
if(document.querySelector('#newProjectModelModal')){
document.querySelector('#newProjectModelModal').remove()
}
let modal = $(modals.newProjectModelHtml()).modal()
let okBtn = document.querySelector('#newProjectModelModal .ok-model-btn')
let input = document.querySelector('#newProjectModelModal #modelPathInput')
input.addEventListener("keyup", function (event) {
if(event.keyCode === 13){
event.preventDefault();
okBtn.click();
}
});
input.addEventListener("input", function (e) {
var endErrMsg = document.querySelector('#newProjectModelModal #modelPathInputEndCharError')
var charErrMsg = document.querySelector('#newProjectModelModal #modelPathInputSpecCharError')
let error = self.validateName(input.value)
okBtn.disabled = error !== ""
charErrMsg.style.display = error === "both" || error === "special" ? "block" : "none"
endErrMsg.style.display = error === "both" || error === "forward" ? "block" : "none"
});
okBtn.addEventListener("click", function (e) {
if(Boolean(input.value)) {
let queryString = "?path="+o.original._path+"&mdlPath="+input.value.trim()
let mdlListEP = path.join(app.getApiPath(), 'project/add-existing-model') + "?path="+o.original._path
xhr({uri:mdlListEP, json:true}, function (err, response, body) {
let modal = $(modals.newProjectModelHtml(body.models)).modal()
let okBtn = document.querySelector('#newProjectModelModal .ok-model-btn')
let select = document.querySelector('#newProjectModelModal #modelPathInput')
okBtn.addEventListener("click", function (e) {
let queryString = "?path="+o.original._path+"&mdlPath="+select.value
let endpoint = path.join(app.getApiPath(), 'project/add-existing-model') + queryString
xhr({uri:endpoint, json:true}, function (err, response, body) {
xhr({uri:endpoint, json:true, method:"post"}, function (err, response, body) {
if(response.statusCode < 400) {
let successModal = $(modals.newProjectModelSuccessHtml(body.message)).modal()
}else{
let errorModal = $(modals.newProjectModelErrorHtml(body.Reason, body.Message)).modal()
}
});
modal.modal('hide')
}
});
});
})
},
newModelOrDirectory: function (o, isModel, isSpatial) {
var self = this
Expand Down
114 changes: 88 additions & 26 deletions client/pages/model-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ var modals = require('../modals')
var PageView = require('../pages/base');
var MeshEditorView = require('../views/mesh-editor');
var SpeciesEditorView = require('../views/species-editor');
var SpeciesViewer = require('../views/species-viewer');
var InitialConditionsEditorView = require('../views/initial-conditions-editor');
var ParametersEditorView = require('../views/parameters-editor');
var ParameterViewer = require('../views/parameters-viewer');
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 ModelSettingsView = require('../views/model-settings');
var ModelStateButtonsView = require('../views/model-state-buttons');
Expand All @@ -47,7 +52,9 @@ let ModelEditor = PageView.extend({
'click [data-hook=edit-model-help]' : function () {
let modal = $(modals.operationInfoModalHtml('model-editor')).modal();
},
'click [data-hook=project-breadcrumb-link]' : 'handleProjectBreadcrumbClick'
'click [data-hook=collapse-me-advanced-section]' : 'changeCollapseButtonText',
'click [data-hook=project-breadcrumb-link]' : 'handleProjectBreadcrumbClick',
'click [data-hook=toggle-preview-plot]' : 'togglePreviewPlot'
},
initialize: function (attrs, options) {
PageView.prototype.initialize.apply(this, arguments);
Expand All @@ -66,7 +73,7 @@ let ModelEditor = PageView.extend({
});
if(directory.includes('.proj')) {
this.projectPath = path.dirname(directory)
this.projectName = this.projectPath.split('/').pop().split('.')[0]
this.projectName = this.getFileName(this.projectPath)
}
this.model.fetch({
success: function (model, response, options) {
Expand Down Expand Up @@ -180,20 +187,9 @@ let ModelEditor = PageView.extend({
var meshEditor = new MeshEditorView({
model: this.model.meshSettings
});
var speciesEditor = new SpeciesEditorView({
collection: this.model.species
});
var initialConditionsEditor = new InitialConditionsEditorView({
collection: this.model.initialConditions
});
var parametersEditor = new ParametersEditorView({
collection: this.model.parameters
});
var reactionsEditor = new ReactionsEditorView({
collection: this.model.reactions
});
this.renderEventsView();
this.renderRulesView();
var sbmlComponentView = new SBMLComponentView({
functionDefinitions: this.model.functionDefinitions,
});
Expand All @@ -205,18 +201,19 @@ let ModelEditor = PageView.extend({
model: this.model
});
this.registerRenderSubview(meshEditor, 'mesh-editor-container');
this.registerRenderSubview(speciesEditor, 'species-editor-container');
this.renderSpeciesView();
this.registerRenderSubview(initialConditionsEditor, 'initial-conditions-editor-container');
this.registerRenderSubview(parametersEditor, 'parameters-editor-container');
this.registerRenderSubview(reactionsEditor, 'reactions-editor-container');
this.renderParametersView();
this.renderReactionsView();
this.renderEventsView();
this.renderRulesView();
this.registerRenderSubview(sbmlComponentView, 'sbml-component-container');
this.registerRenderSubview(modelSettings, 'model-settings-container');
this.registerRenderSubview(this.modelStateButtons, 'model-state-buttons-container');
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').click(function () {
$('[data-toggle="tooltip"]').tooltip("hide");

});
});
$(document).on('hide.bs.modal', '.modal', function (e) {
Expand All @@ -227,26 +224,91 @@ let ModelEditor = PageView.extend({
this.registerSubview(view);
this.renderSubview(view, this.queryByHook(hook));
},
renderEventsView: function () {
renderSpeciesView: function (mode="edit") {
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.registerRenderSubview(this.speciesEditor, 'species-editor-container');
},
renderParametersView: function (mode="edit", opened=false) {
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.registerRenderSubview(this.parametersEditor, 'parameters-editor-container');
},
renderReactionsView: function (mode="edit", opened=false) {
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.registerRenderSubview(this.reactionsEditor, 'reactions-editor-container');
},
renderEventsView: function (mode="edit", opened=false) {
if(this.eventsEditor){
this.eventsEditor.remove();
}
this.eventsEditor = new EventsEditorView({
collection: this.model.eventsCollection
});
if(mode === "edit") {
this.eventsEditor = new EventsEditorView({collection: this.model.eventsCollection, opened: opened});
}else{
this.eventsEditor = new EventsViewer({collection: this.model.eventsCollection});
}
this.registerRenderSubview(this.eventsEditor, 'events-editor-container');
},
renderRulesView: function () {
renderRulesView: function (mode="edit", opened=false) {
if(this.rulesEditor){
this.rulesEditor.remove();
}
this.rulesEditor = new RulesEditorView({
collection: this.model.rules
});
if(mode === "edit") {
this.rulesEditor = new RulesEditorView({collection: this.model.rules, opened: opened});
}else{
this.rulesEditor = new RulesViewer({collection: this.model.rules})
}
this.registerRenderSubview(this.rulesEditor, 'rules-editor-container');
},
subviews: {
changeCollapseButtonText: function (e) {
let source = e.target.dataset.hook
let collapseContainer = $(this.queryByHook(source).dataset.target)
if(!collapseContainer.length || !collapseContainer.attr("class").includes("collapsing")) {
let collapseBtn = $(this.queryByHook(source))
let text = collapseBtn.text();
text === '+' ? collapseBtn.text('-') : collapseBtn.text('+');
}
},
togglePreviewPlot: function (e) {
let action = e.target.innerText
console.log(action)
if(action === "Hide Preview") {
this.closePlot()
}else{
this.openPlot()
}
},
closePlot: function () {
let plot = this.queryByHook("model-run-container")
let button = this.queryByHook("toggle-preview-plot")
plot.style.display = "none"
button.innerText = "Show Preview"
},
openPlot: function () {
let plot = this.queryByHook("model-run-container")
let button = this.queryByHook("toggle-preview-plot")
plot.style.display = "block"
button.innerText = "Hide Preview"
}
});

initPage(ModelEditor);
31 changes: 9 additions & 22 deletions client/pages/project-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,28 +369,15 @@ let ProjectManager = PageView.extend({
if(document.querySelector('#newProjectModelModal')){
document.querySelector('#newProjectModelModal').remove()
}
let modal = $(modals.newProjectModelHtml()).modal()
let okBtn = document.querySelector('#newProjectModelModal .ok-model-btn')
let input = document.querySelector('#newProjectModelModal #modelPathInput')
input.addEventListener("keyup", function (event) {
if(event.keyCode === 13){
event.preventDefault();
okBtn.click();
}
});
input.addEventListener("input", function (e) {
var endErrMsg = document.querySelector('#newProjectModelModal #modelPathInputEndCharError')
var charErrMsg = document.querySelector('#newProjectModelModal #modelPathInputSpecCharError')
let error = self.validateName(input.value)
okBtn.disabled = error !== ""
charErrMsg.style.display = error === "both" || error === "special" ? "block" : "none"
endErrMsg.style.display = error === "both" || error === "forward" ? "block" : "none"
});
okBtn.addEventListener("click", function (e) {
if(Boolean(input.value)) {
let queryString = "?path="+self.projectPath+"&mdlPath="+input.value
let mdlListEP = path.join(app.getApiPath(), 'project/add-existing-model') + "?path="+self.projectPath
xhr({uri:mdlListEP, json:true}, function (err, response, body) {
let modal = $(modals.newProjectModelHtml(body.models)).modal()
let okBtn = document.querySelector('#newProjectModelModal .ok-model-btn')
let select = document.querySelector('#newProjectModelModal #modelPathInput')
okBtn.addEventListener("click", function (e) {
let queryString = "?path="+self.projectPath+"&mdlPath="+select.value
let endpoint = path.join(app.getApiPath(), 'project/add-existing-model') + queryString
xhr({uri:endpoint, json:true}, function (err, response, body) {
xhr({uri:endpoint, json:true, method:"post"}, function (err, response, body) {
if(response.statusCode < 400) {
let successModal = $(modals.newProjectModelSuccessHtml(body.message)).modal()
}else{
Expand All @@ -399,7 +386,7 @@ let ProjectManager = PageView.extend({
});
modal.modal('hide')
self.update("existing-model")
}
});
});
},
exportAsCombine: function(target, download) {
Expand Down
38 changes: 38 additions & 0 deletions client/styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,41 @@ span.checkbox {
#models-jstree .jstree-default .jstree-anchor {
height: auto;
}

.reaction-lb2 {
display: none;
}

.dropdown-item:hover .reaction-lb2 {
position: absolute;
left: 195px;
display: inline-block;
background-color: black;
color: white;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
border: .5px solid rgb(228, 229, 230) !important;
padding: 0px 5px;
}

.preview-nav {
position: fixed;
width: 100%;
left: 0;
right: 0;
bottom: 0;
background-color: rgb(248, 249, 250);
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
border: .5px solid rgb(228, 229, 230) !important;
padding: 0px 5px;
}

.preview-close {
position: relative;
display: none;
float: right;
top: 8px;
}

.model-state-buttons {
float: right;
}
4 changes: 2 additions & 2 deletions client/templates/includes/editWorkflowsView.pug
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ div#edit-project-workflows

ul.dropdown-menu(aria-labelledby="add-workflow-btn")
li.dropdown-item(id="project-workflow-group-new-workflow" data-hook="project-workflow-group-new-workflow") New Workflow
li.dropdown-divider
li.dropdown-item(id="project-workflow-group-add-workflow" data-hook="project-workflow-group-add-workflow") Existing Workflow
li.dropdown-divider(style="display: none;")
li.dropdown-item(id="project-workflow-group-add-workflow" data-hook="project-workflow-group-add-workflow" style="display: none;") Existing Workflow


Loading

0 comments on commit c17df7f

Please sign in to comment.