Commit 5c84a686 authored by David Trudgian's avatar David Trudgian

Refactor JS files, add package.json and Gruntfile for dist build etc.

parent 014e68d9
.idea .idea
bower_components/
node_modules/
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: {
dist: {
files: [ {src: 'index.html', dest: 'dist/index.html'} ]
}
},
'useminPrepare': {
options: {
dest: 'dist'
},
html: 'index.html'
},
usemin: {
html: ['dist/index.html']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-usemin');
grunt.registerTask('default', ['useminPrepare', 'copy', 'concat', 'uglify', 'usemin']);
};
\ No newline at end of file
# ember_sbatch
This is a prototype frontend for the BioHPC portal sbatch script generator.
To work on code install npm and bower deps:
````
npm install
bower install
````
To minify, build dist:
````
grunt
````
This diff is collapsed.
This diff is collapsed.
index.hbs
\ No newline at end of file
This diff is collapsed.
/*global Ember, DS, App */ /*global Ember, DS*/
// APP AND ROUTES
App = Ember.Application.create({LOG_TRANSITIONS: true}); var App = Ember.Application.create({LOG_TRANSITIONS: true});
App.ApplicationAdapter = DS.FixtureAdapter; App.ApplicationAdapter = DS.FixtureAdapter;
...@@ -11,17 +12,14 @@ App.Router.map(function() { ...@@ -11,17 +12,14 @@ App.Router.map(function() {
}); });
App.IndexRoute = Ember.Route.extend({ App.IndexRoute = Ember.Route.extend({
beforeModel: function() { beforeModel: function() {
this.transitionTo('script'); this.transitionTo('script');
} }
}); });
App.ScriptRoute = Ember.Route.extend({ App.ScriptRoute = Ember.Route.extend({
actions: { actions: {
showModal: function(name, model) { showModal: function(name, model) {
this.render(name, { this.render(name, {
...@@ -45,85 +43,20 @@ App.ScriptRoute = Ember.Route.extend({ ...@@ -45,85 +43,20 @@ App.ScriptRoute = Ember.Route.extend({
// Create the batch script object // Create the batch script object
var sbatch = this.store.createRecord('script'); var sbatch = this.store.createRecord('script');
// Add a single command group as an example // Add a single command group as an example
var runGroup1 = this.store.createRecord('run-group'); var runGroup1 = this.store.createRecord('run-group');
// Run 'hostname' in this command group // Run 'hostname' in this command group
runGroup1.get('runCmds').addObject(this.store.createRecord('run-cmd', {cmd: 'hostname'})); runGroup1.get('runCmds').addObject(this.store.createRecord('run-cmd', {cmd: 'hostname'}));
// Add the command group to the batch script // Add the command group to the batch script
sbatch.get('runGroups').addObject(runGroup1); sbatch.get('runGroups').addObject(runGroup1);
return sbatch; return sbatch;
},
});
App.MyModalComponent = Ember.Component.extend({
actions: {
ok: function() {
this.$('.modal').modal('hide');
this.sendAction('ok');
} }
},
show: function() {
this.$('.modal').modal().on('hidden.bs.modal', function() {
this.sendAction('close');
}.bind(this));
}.on('didInsertElement')
});
App.ScriptModulesModalController = Ember.ObjectController.extend({
moduleList: function(){ });
return this.store.find('module');
}.property(),
actions: {
save: function() {
// save to server
}
}
});
App.CheckboxSelectComponent = Ember.Component.extend({
/* The property to be used as label */
labelPath: null,
/* The model */
model: null,
/* The has many property from the model */
propertyPath: null,
/* All possible elements, to be selected */
elements: null,
elementsOfProperty: function() {
return this.get('model.' + this.get('propertyPath'));
}.property()
});
App.CheckboxItemController = Ember.ObjectController.extend({
selected: function() {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
return children.contains(activity);
}.property(),
label: function() {
return this.get('model.' + this.get('parentController.labelPath'));
}.property(),
selectedChanged: function() {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
if (this.get('selected')) {
children.pushObject(activity);
} else {
children.removeObject(activity);
}
}.observes('selected')
});
/*global Ember, DS, App */
(function() {
'use strict';
App.CheckboxSelectComponent = Ember.Component.extend({
/* The property to be used as label */
labelPath: null,
/* The model */
model: null,
/* The has many property from the model */
propertyPath: null,
/* All possible elements, to be selected */
elements: null,
elementsOfProperty: function () {
return this.get('model.' + this.get('propertyPath'));
}.property()
});
App.CheckboxItemController = Ember.ObjectController.extend({
selected: function () {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
return children.contains(activity);
}.property(),
label: function () {
return this.get('model.' + this.get('parentController.labelPath'));
}.property(),
selectedChanged: function () {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
if (this.get('selected')) {
children.pushObject(activity);
} else {
children.removeObject(activity);
}
}.observes('selected')
});
})();
\ No newline at end of file
/*global Ember, DS, App */
(function(){
'use strict';
App.MyModalComponent = Ember.Component.extend({
actions: {
ok: function () {
this.$('.modal').modal('hide');
this.sendAction('ok');
}
},
show: function () {
this.$('.modal').modal().on('hidden.bs.modal', function () {
this.sendAction('close');
}.bind(this));
}.on('didInsertElement')
});
})();
\ No newline at end of file
/*global Ember, App, DS */
(function () {
'use strict';
App.RunCmdsController = Ember.ArrayController.extend({
actions: {
addRunCmd: function () {
this.get('model').addObject(this.store.createRecord('run-cmd', {cmd: ''}));
}
}
});
App.RunCmdController = Ember.ObjectController.extend({
actions: {
removeRunCmd: function () {
var runCmd = this.get('model');
runCmd.deleteRecord();
runCmd.save();
}
}
});
})();
\ No newline at end of file
/*global Ember, App, DS */
(function () {
'use strict';
App.RunGroupsController = Ember.ArrayController.extend({
actions: {
addRunGroup: function () {
var runCmd = this.store.createRecord('run-cmd', {cmd: '' });
var runGroup = this.store.createRecord('run-group');
runGroup.get('runCmds').addObject(runCmd);
this.get('model').addObject(runGroup);
}
}
});
App.RunGroupController = Ember.ObjectController.extend({
actions: {
removeRunGroup: function () {
var runGroup = this.get('model');
runGroup.deleteRecord();
runGroup.save();
},
},
});
})();
\ No newline at end of file
/*global Ember, App, DS */
(function () {
'use strict';
App.ScriptController = Ember.ObjectController.extend({
partitions: function () {
return this.get('store').find('partition');
}.property(),
partitionChanged: function () {
this.set('memGB', null);
}.observes('partition'),
// Hard-coded Options for mail type
optionMailTypes: [
{id: null, description: 'Never'},
{id: 'ALL', description: 'All status changes'}
],
optionNodes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
// Job Limit Fields - Options & Selections
optionDays: [0, 1, 2, 3, 4, 5, 6, 7],
optionHours: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
optionMinutes: [0, 15, 30, 45],
selectedDays: 0,
selectedHours: 2,
selectedMinutes: 0,
timeLimitChanged: function () {
this.get('model').set('timeLimit', this.get('selectedDays') + '-' + this.get('selectedHours') + ':' + this.get('selectedMinutes') + ':00');
}.observes('selectedDays', 'selectedHours', 'selectedMinutes'),
memGB: null,
memGBChanged: function () {
this.get('model').set('mem', this.get('memGB') * 1024);
}.observes('memGB'),
actions: {
openModal: function(modalName, model) {
this.controllerFor(modalName).set('model', model);
return this.render(modalName, {
into: 'script',
outlet: 'modal'
});
},
closeModal: function() {
return this.disconnectOutlet({
outlet: 'modal',
parentView: 'script'
});
}
}
});
})();
/*global Ember, DS, App */
(function() {
'use strict';
App.ScriptModulesModalController = Ember.ObjectController.extend({
moduleList: function () {
return this.store.find('module');
}.property(),
actions: {
save: function () {
// save to server
}
}
});
})();
\ No newline at end of file
/*global App, DS */
(function () {
'use strict';
App.Module = DS.Model.extend({
description: DS.attr('string'),
});
App.Module.reopenClass({
FIXTURES: [
{
id: 'gcc',
},
{
id: 'intel',
},
{
id: 'R',
},
{
id: 'python',
}
]
});
})();
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
var output = ''; var output = '';
var validCmds = this.get('runCmds').filter(function(item,index,self){ var validCmds = this.get('runCmds').filter(function(item,index,self){
if ( item.get('cmdString') ) { return true }; if ( item.get('cmdString') ) { return true; }
}); });
var cmdCount = validCmds.length; var cmdCount = validCmds.length;
......
/*global App, DS */
/*jslint plusplus: true */
(function () {
'use strict';
App.Script = DS.Model.extend({
// -p
partition: DS.belongsTo('partition'),
// -N
nodes: DS.attr('number', {defaultValue: 1}),
// --mem
mem: DS.attr('number'),
// -t
timeLimit: DS.attr('string', {defaultValue: '0-2:0:0'}),
// -o
stdout: DS.attr('string', {defaultValue: 'job_%j.out'}),
// -e
stderr: DS.attr('string', {defaultValue: 'job_%j.err'}),
// --mail-type
mailType: DS.attr('string', {defaultValue: 'ALL'}),
// --mail-user
mailUser: DS.attr('string'),
// --job-name
jobName: DS.attr('string', {defaultValue: 'NewJob'}),
// --ntasks-per-node
nTasksPerNode: DS.attr('number', {defaultValue: null}),
// modules
modules: DS.hasMany('module',{async:true}),
runGroups: DS.hasMany('run-group'),
script: function () {
var script_lines = [], groupCount = 1;
script_lines.push('#');
script_lines.push('# CREATED USING THE BIOHPC PORTAL on ' + new Date().toString());
script_lines.push('#');
script_lines.push('# This file is batch script used to run commands on the BioHPC cluster.');
script_lines.push('# The script is submitted to the cluster using the SLURM `sbatch` command.');
script_lines.push('# Lines starting with # are comments, and will not be run.');
script_lines.push('# Lines starting with #SBATCH specify options for the scheduler.');
script_lines.push('# Lines that do not start with # or #SBATCH are commands that will run.');
script_lines.push('');
script_lines.push('# Name for the job that will be visible in the job queue and accounting tools.');
script_lines.push('#SBATCH --job-name ' + this.get('jobName'));
script_lines.push('');
if (this.get('partition')) {
script_lines.push('# Name of the SLURM partition that this job should run on.');
script_lines.push('#SBATCH -p ' + this.get('partition').id + ' # partition (queue)');
}
script_lines.push('# Number of nodes required to run this job');
script_lines.push('#SBATCH -N ' + this.get('nodes'));
script_lines.push('');
if (this.get('nTasksPerNode')) {
script_lines.push('# When using srun or mpirun, start n tasks on each node.');
script_lines.push('#SBATCH --ntasks-per-node ' + this.get('nTasksPerNode') + ' # tasks per node');
script_lines.push('');
}
if (this.get('mem')) {
script_lines.push('# Memory (RAM) requirement/limit in MB.');
script_lines.push('#SBATCH --mem ' + this.get('mem') + ' # Memory Requirement (MB)');
script_lines.push('');
}
script_lines.push('# Time limit for the job in the format Days-H:M:S');
script_lines.push('# A job that reaches its time limit will be cancelled.');
script_lines.push('# Specify an accurate time limit for efficient scheduling so your job runs promptly.');
script_lines.push('#SBATCH -t ' + this.get('timeLimit'));
script_lines.push('');
script_lines.push('# The standard output and errors from commands will be written to these files.');
script_lines.push('# %j in the filename will be replace with the job number when it is submitted.');
script_lines.push('#SBATCH -o ' + this.get('stdout'));
script_lines.push('#SBATCH -e ' + this.get('stderr'));
script_lines.push('');
if (this.get('mailType')) {
script_lines.push('# Send an email when the job status changes, to the specfied address.');
script_lines.push('#SBATCH --mail-type ' + this.get('mailType'));
script_lines.push('#SBATCH --mail-user ' + this.get('mailUser'));
script_lines.push('');
}
this.get('runGroups').forEach(function (runGroup) {
script_lines.push("# COMMAND GROUP " + groupCount);
script_lines.push(runGroup.get('cmdString'));
groupCount++;
});
script_lines.push("");
script_lines.push("# END OF SCRIPT");
script_lines.push("");
return script_lines.join('\n');
}.property('partition', 'nodes', 'mem', 'timeLimit', 'jobName', 'stderr', 'stdout', 'mailType', 'mailUser', 'nTasksPerNode', 'runGroups.@each.cmdString')
});
}());
{
"name": "ember_sbatch",
"version": "1.0.0",
"description": "Prototype Ember.JS SLURM sbatch creation frontend",
"main": "Gruntfile.js",
"repository": {
"type": "git",
"url": "git@git.biohpc.swmed.edu:david.trudgian/ember_sbatch.git"
},
"author": "David Trudgian <david.trudgian@utsouthwestern.edu>",
"devDependencies": {
"grunt": ">=0.4.5",
"grunt-contrib-concat": ">=0.5.0",
"grunt-contrib-copy": ">=0.7.0",
"grunt-contrib-jshint": ">=0.10.0",
"grunt-contrib-uglify": ">=0.7.0",
"grunt-usemin": ">=3.0.0",
"bower": ">=1.3.12"
}
}