Updated merge from master

This commit is contained in:
Matthew Dillon 2015-07-07 14:41:40 -08:00
commit 8ab97c00e1
127 changed files with 578 additions and 1802 deletions

View file

@ -5,10 +5,13 @@ export default DS.RESTAdapter.extend({
namespace: function() {
return 'api/' + this.get('globals.genus');
}.property(),
host: function() {
return this.get('globals.apiURL');
}.property(),
coalesceFindRequests: true,
ajaxError: function(jqXHR) {
// http://stackoverflow.com/a/24027443
var error = this._super(jqXHR);
@ -25,5 +28,5 @@ export default DS.RESTAdapter.extend({
} else {
return error;
}
}
},
});

View file

@ -4,7 +4,16 @@ import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';
export default Ember.Route.extend(ApplicationRouteMixin, {
actions: {
invalidateSession: function() {
this.get('session').invalidate();
this.get('session').invalidate().then(() => {
// Wait until promise is resolved
return true;
});
},
didTransition: function() {
this.get('flashMessages').clearMessages();
return true;
},
}
});

View file

@ -1,7 +1,5 @@
<div class="flakes-navigation">
{{#link-to 'index' class='logo'}}
{{globals.genus}}.info
{{/link-to}}
{{site-logo}}
{{#if session.isAuthenticated}}
<ul>
{{#link-to 'compare' tagName='li' href=false}}
@ -29,24 +27,25 @@
</p>
{{else}}
<p class="foot">
{{#link-to 'login' Login}}Login{{/link-to}}
{{link-to 'Login' 'login'}}
<br>
Sign Up
{{link-to 'Sign Up' 'users.new'}}
</p>
{{/if}}
</div>
<div class="flakes-content">
<div class="flakes-mobile-top-bar">
<a href="" class="logo-wrap">
{{globals.genus}}.info
</a>
{{site-logo}}
<a href="" class="navigation-expand-target">
<img src="img/navigation-expand-target.png" height="26px">
</a>
</div>
<div class="view-wrap">
{{#each flashMessages.queue as |flash|}}
{{custom-flash-message flash=flash}}
{{/each}}
{{outlet}}
</div>
</div>

View file

@ -0,0 +1,6 @@
import Ember from 'ember';
export default Ember.Controller.extend({
sortParams: ['characteristicType.characteristicTypeName', 'characteristicName'],
sortedCharacteristics: Ember.computed.sort('characteristics', 'sortParams'),
});

View file

@ -8,14 +8,8 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
characteristics: this.store.findAll('characteristic'),
});
},
setupController: function(controller, models) {
var tableAttrs = [
{ name: 'Name', attr: 'characteristicName' },
{ name: 'Type', attr: 'characteristicType.characteristicTypeName' }
];
controller.set('model', models.characteristics);
controller.set('tableAttrs', tableAttrs);
controller.set('row', 'characteristic-index-row');
controller.set('sort', ['characteristicName']);
controller.setProperties(models);
},
});

View file

@ -1,10 +1,19 @@
<h2>{{genus-name}} Characteristics</h2>
<h3>Total characteristics: {{model.length}}</h3>
<h3>Total characteristics: {{characteristics.length}}</h3>
{{
sortable-table
content=model
tableAttrs=tableAttrs
row=row
sortProperties=sort
}}
<table class="flakes-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
<tbody>
{{#each sortedCharacteristics as |row|}}
<tr>
<td>{{row.characteristicName}}</td>
<td>{{row.characteristicType.characteristicTypeName}}</td>
</tr>
{{/each}}
</tbody>
</table>

View file

@ -1,4 +1,12 @@
import Ember from 'ember';
import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin);
export default Ember.Route.extend(AuthenticatedRouteMixin, {
resetController: function(controller, isExiting /*, transition*/) {
if (isExiting) {
controller.set('data', null);
controller.set('strains', null);
controller.set('dataEmpty', true);
}
}
});

View file

@ -1,19 +1,28 @@
<h2>{{genus-name}} - Compare Strains</h2>
{{measurement-search-panel search='search'}}
{{
measurement-search-panel
search='search'
strainLabel='Select one or more strains'
charLabel='Select one or more characteristics'
}}
{{#if dataEmpty}}
<div class="flakes-message information">
Please select one or more strains and one or more characteristics.
</div>
{{else}}
<div>
<div class="overflow-div">
<table class="flakes-table">
<thead>
<tr>
<th>Characteristic</th>
{{#each strains as |strain|}}
<th>{{strain.fullNameMU}}</th>
<th>
{{#link-to 'strains.show' strain.id classBinding="data.typeStrain:type-strain"}}
{{strain.fullNameMU}}
{{/link-to}}
</th>
{{/each}}
</tr>
</thead>

View file

@ -1,8 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
canAdd: function() {
let role = this.get('session.currentUser.role');
return (role === 'W') || (role === 'A');
}.property('session.currentUser.role')
});

View file

@ -1,5 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'tr',
});

View file

@ -1,6 +0,0 @@
<td>
{{data.characteristicName}}
</td>
<td>
{{data.characteristicType.characteristicTypeName}}
</td>

View file

@ -0,0 +1,7 @@
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['flakes-message'],
classNameBindings: ['type'],
type: Ember.computed.readOnly('flash.type'),
});

View file

@ -0,0 +1 @@
{{flash.message}}

View file

@ -1,3 +1,3 @@
{{#each error in a}}
{{#each a as |error|}}
<div class="flakes-message error">{{error.message}}</div>
{{/each}}

View file

@ -0,0 +1,12 @@
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
save: function() {
this.sendAction('save');
},
cancel: function() {
this.sendAction('cancel');
},
}
});

View file

@ -0,0 +1,42 @@
<form class="grid-form">
<fieldset>
<legend><em>{{species.speciesName}}</em></legend>
<div data-row-span="2">
<div data-field-span="1">
<label>Species Name</label>
{{input value=species.speciesName}}
</div>
<div data-field-span="1">
<label>Type Species?</label>
{{input type="checkbox" checked=species.typeSpecies}} {{if species.typeSpecies 'Yes' 'No'}}
</div>
</div>
<div data-row-span="2">
<div data-field-span="2">
<label>Strains</label>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
{{add-button label="Add Strain" link="strains.new"}}
</div>
</div>
<div data-row-span="2">
<div data-field-span="2">
<label>Etymology</label>
{{textarea value=species.etymology cols="70" rows="5"}}
</div>
</div>
</fieldset>
</form>
<br>
{{#if species.isDirty}}
<a class="button-green smaller" {{action 'save'}}>
Save
</a>
{{/if}}
<a class="button-red smaller" {{action 'cancel'}}>
Cancel
</a>

View file

@ -23,10 +23,10 @@ export default Ember.Component.extend({
models[item.model] = models[item.model].filter((i) => {
if (!Ember.isEmpty(i.get(item.children))) { return true; }
});
models[item.model] = models[item.model].sortBy(item.text);
models[item.model] = models[item.model].sortBy('sortOrder');
let temp = models[item.model].map((data) => {
let temp_children = [];
let sorted_children = data.get(item.children).sortBy(item.ctext);
let sorted_children = data.get(item.children).sortBy('sortOrder');
sorted_children.forEach((child) => {
temp_children.push({id: child.get(item.cid), text: child.get(item.ctext)});
});

View file

@ -10,7 +10,7 @@
content=species
value=selectedStrains
optionValuePath="id"
placeholder="All strains"
placeholder=strainLabel
}}
</li>
<li>
@ -21,7 +21,7 @@
content=characteristicTypes
value=selectedCharacteristics
optionValuePath="id"
placeholder="All characteristics"
placeholder=charLabel
}}
</li>
<li>

View file

@ -0,0 +1,3 @@
{{#link-to 'index' class='logo'}}
<h2>{{globals.genus}}.info</h2>
{{/link-to}}

View file

@ -1,13 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'th',
upArrow: '&#9650',
downArrow: '&#9660',
actions: {
sortBy: function(sortProperty, ascending) {
this.sendAction('action', sortProperty, ascending);
}
},
});

View file

@ -1,3 +0,0 @@
{{title}}
<span {{action 'sortBy' sortProperty true}}>{{{upArrow}}}</span>
<span {{action 'sortBy' sortProperty false}}>{{{downArrow}}}</span>

View file

@ -1,14 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend(Ember.SortableMixin, {
tagName: 'table',
classNames: ['flakes-table'],
sortProperties: [],
actions: {
sortBy: function(property, ascending) {
this.set('sortAscending', ascending);
this.set('sortProperties', [property]);
}
},
});

View file

@ -1,13 +0,0 @@
<thead>
<tr>
{{#each a in tableAttrs}}
{{sortable-table-header title=a.name sortProperty=a.attr action="sortBy"}}
{{/each}}
</tr>
</thead>
<tbody>
{{#each item in arrangedContent}}
{{component row data=item}}
{{/each}}
</tbody>

View file

@ -1,22 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['grid-1'],
isEditing: false,
canEdit: function() {
let role = this.get('session.currentUser.role');
let id = this.get('session.currentUser.id');
let author = this.get('species.createdBy');
return (role === 'W' && (+id === author)) || (role === 'A');
}.property('session.currentUser.role', 'session.currentUser.id', 'species.createdBy'),
actions: {
save: function() {
this.sendAction('save');
},
cancel: function() {
this.sendAction('cancel');
},
}
});

View file

@ -1,89 +0,0 @@
<div class="span-1">
<fieldset class="flakes-information-box {{if isEditing 'is-editing'}}">
<legend>
Species
{{#if isEditing}}
{{input value=species.speciesName}}
{{else}}
<em>{{species.speciesName}}</em>
{{/if}}
{{display-errors a=species.errors.speciesName}}
</legend>
{{! ROW 1 }}
<div class="grid-4">
<dl class="span-2">
<dt>Strains</dt>
<dd>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
{{#unless species.isNew}}
{{add-button label="Add Strain" link="strains.new"}}
{{/unless}}
</dd>
</dl>
<dl class="span-2">
<dt>Type Species?</dt>
<dd>
{{#if isEditing}}
{{input type="checkbox" checked=species.typeSpecies}}
{{/if}}
{{if species.typeSpecies 'Yes' 'No'}}
{{display-errors a=species.errors.typeSpecies}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-4">
<dl class="span-4">
<dt>Etymology</dt>
<dd>
{{#if isEditing}}
{{textarea value=species.etymology cols="70" rows="3"}}
{{else}}
{{species.etymology}}
{{/if}}
{{display-errors a=species.errors.etymology}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-4">
<dl class="span-1">
<dt>Record Created</dt>
<dd>{{null-time species.createdAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Updated</dt>
<dd>{{null-time species.updatedAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Deleted</dt>
<dd>{{null-time species.deletedAt 'LL'}}</dd>
</dl>
<dl class="span-1"></dl>
</div>
{{! ROW 4 }}
{{#if canEdit}}
<div class="grid-4">
<div class="span-1">
<a class="smaller {{if isEditing 'button-red' 'button-gray'}}" {{action 'cancel'}}>
{{#if isEditing}}Cancel{{else}}Edit{{/if}}
</a>
{{#if isEditing}}
<a class="button-green smaller" {{action 'save'}}>
Save
</a>
{{/if}}
</div>
</div>
{{/if}}
</fieldset>
</div>

View file

@ -1,5 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'tr',
});

View file

@ -1,15 +0,0 @@
<td>
<em>
{{#link-to 'species.show' data}}
{{data.speciesName}}
{{/link-to}}
</em>
</td>
<td>
{{#each data.strains as |strain index|}}
{{if index ","}}
{{#link-to 'strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</td>

View file

@ -1,15 +1,13 @@
import Ember from 'ember';
import userCanEdit from '../../../utils/user-can-edit';
export default Ember.Component.extend({
classNames: ['grid-1'],
isEditing: false,
canEdit: function() {
let role = this.get('session.currentUser.role');
let id = this.get('session.currentUser.id');
let author = this.get('strain.createdBy');
return (role === 'W' && (+id === author)) || (role === 'A');
}.property('session.currentUser.role', 'session.currentUser.id', 'strain.createdBy'),
return userCanEdit(this.get('session.currentUser'), this.get('strain.createdBy'));
}.property('session.currentUser', 'strain.createdBy').readOnly(),
actions: {
save: function() {

View file

@ -5,23 +5,22 @@
{{#if isEditing}}
{{input value=strain.strainName}}
{{else}}
<em>{{strain.strainName}}</em>
{{strain.strainNameMU}}
{{/if}}
{{display-errors a=strain.errors.strainName}}
</legend>
{{! ROW 1 }}
<div class="grid-4">
<div class="grid-4 gutter-50">
<dl class="span-2">
<dt>Species</dt>
<dd>
{{#if isEditing}}
{{
view "select"
select-2
content=species
optionValuePath="content.id"
optionLabelPath="content.speciesName"
selection=strain.species
optionLabelPath="speciesName"
value=strain.species
}}
{{else}}
{{#link-to 'species.show' strain.species}}
@ -43,7 +42,7 @@
</div>
{{! ROW 2 }}
<div class="grid-4">
<div class="grid-6">
<dl class="span-2">
<dt>Accession Numbers</dt>
<dd>
@ -66,6 +65,17 @@
{{display-errors a=strain.errors.genbank}}
</dd>
</dl>
<dl class="span-2">
<dt>Whole Genome Sequence</dt>
<dd>
{{#if isEditing}}
{{input value=strain.wholeGenomeSequence}}
{{else}}
{{strain.wholeGenomeSequence}}
{{/if}}
{{display-errors a=strain.errors.wholeGenomeSequence}}
</dd>
</dl>
</div>
{{! ROW 3 }}

View file

@ -1,5 +0,0 @@
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'tr',
});

View file

@ -1,8 +0,0 @@
<td>
{{#link-to 'strains.show' data.id classBinding="data.typeStrain:type-strain"}}
{{{data.fullNameMU}}}
{{/link-to}}
</td>
<td>
{{data.totalMeasurements}}
</td>

View file

@ -1,18 +1,25 @@
import Ember from 'ember';
import parseBase64 from '../../utils/parse-base64';
export default Ember.Controller.extend({
actions: {
authenticate: function() {
this.set('errorMessage', null);
let credentials = this.getProperties('identification', 'password');
let session = this.get('session');
let authenticator = 'simple-auth-authenticator:token';
this.set('loading', true);
this.get('session').authenticate(authenticator, credentials).then(()=>{
// Manually clean up because there might not be a transition
this.get('flashMessages').clearMessages();
session.authenticate(authenticator, credentials).then(()=>{
this.set('loading', false);
let t = parseBase64(session.get('secure.token'));
this.store.find('user', t['sub']).then((user) => {
session.set('currentUser', user);
});
}, (error)=> {
this.set('loading', false);
this.set('errorMessage', error.error);
this.get('flashMessages').error(error.error);
});
}
}

View file

@ -1,8 +1,4 @@
import Ember from 'ember';
import UnauthenticatedRouteMixin from 'simple-auth/mixins/unauthenticated-route-mixin';
export default Ember.Route.extend(UnauthenticatedRouteMixin, {
setupController: function(controller) {
controller.set('errorMessage', null);
}
});
export default Ember.Route.extend(UnauthenticatedRouteMixin, {});

View file

@ -2,10 +2,7 @@
<p>You are already logged in!</p>
{{else}}
{{#if loading}}
<div class="spinner">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
{{loading-panel}}
{{else}}
<form {{action "authenticate" on="submit"}}>
<h2>Log In</h2>
@ -14,7 +11,4 @@
{{input class="button-gray" type="submit" value="Log In"}}
</form>
{{/if}}
{{#if errorMessage}}
<div class="flakes-message error">{{errorMessage}}</div>
{{/if}}
{{/if}}

View file

@ -1,6 +1,6 @@
<h2>{{genus-name}} Measurements</h2>
{{measurement-search-panel search='search'}}
{{measurement-search-panel search='search' strainLabel='All strains' charLabel='All characteristics'}}
<div class="grid-12 gutter-50">
<div class="span-12">

View file

@ -0,0 +1,29 @@
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
save: function() {
let species = this.get('model');
if (species.get('isDirty')) {
species.save().then((species) => {
this.transitionToRoute('species.show', species.get('id'));
}, (err) => {
this.get('flashMessages').error(err.responseJSON.error);
});
} else {
this.transitionToRoute('species.show', species.get('id'));
}
},
cancel: function() {
let species = this.get('model');
species.get('errors').clear();
species.rollback();
this.transitionToRoute('species.show', species.get('id'));
},
},
});

View file

@ -0,0 +1,4 @@
import Ember from 'ember';
import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {});

View file

@ -0,0 +1,6 @@
{{
forms/species-form
species=model
save="save"
cancel="cancel"
}}

View file

@ -0,0 +1,11 @@
import Ember from 'ember';
export default Ember.Controller.extend({
sortParams: ['speciesName', 'strainCount'],
sortedSpecies: Ember.computed.sort('model', 'sortParams'),
metaData: function() {
return this.store.metadataFor('species');
}.property('model.isLoaded').readOnly(),
});

View file

@ -4,15 +4,5 @@ import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixi
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model: function() {
return this.store.findAll('species');
},
setupController: function(controller, model) {
var tableAttrs = [
{ name: 'Name', attr: 'speciesName' },
{ name: 'Strains', attr: 'totalStrains' }
];
controller.set('model', model);
controller.set('tableAttrs', tableAttrs);
controller.set('row', 'species-index-row');
controller.set('sort', ['speciesName']);
},
}
});

View file

@ -1,12 +1,34 @@
<h2>{{genus-name}} Species</h2>
<h3>Total species: {{controller.length}}</h3>
<h3>Total species: {{model.length}}</h3>
{{add-button label="Add Species" link="species.new"}}
{{add-button label="Add Species" link="species.new" canAdd=metaData.canAdd}}
{{
sortable-table
content=model
tableAttrs=tableAttrs
row=row
sortProperties=sort
}}
<table class="flakes-table">
<thead>
<tr>
<th>Name</th>
<th>Strains</th>
</tr>
</thead>
<tbody>
{{#each sortedSpecies as |species|}}
<tr>
<td>
<em>
{{#link-to 'species.show' species}}
{{species.speciesName}}
{{/link-to}}
</em>
</td>
<td>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</td>
</tr>
{{/each}}
</tbody>
</table>

View file

@ -1,21 +1,30 @@
import Ember from 'ember';
export default Ember.Controller.extend({
isEditing: true,
actions: {
save: function() {
var species = this.get('model');
let species = this.get('model');
if (species.get('isDirty')) {
species.save();
species.save().then((species) => {
this.transitionToRoute('species.show', species.get('id'));
}, (err) => {
this.get('flashMessages').error(err.responseJSON.error);
});
} else {
this.transitionToRoute('species.index');
}
this.transitionToRoute('species.index');
},
cancel: function() {
var species = this.get('model');
let species = this.get('model');
if (species.get('isNew')) {
species.deleteRecord();
}
this.transitionToRoute('species.index');
}
}
},
},
});

View file

@ -5,9 +5,5 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
model: function() {
return this.store.createRecord('species');
},
actions: {
cancelSpecies: function() {
this.transitionTo('species.index');
}
}
});

View file

@ -1,7 +1,6 @@
{{
species-details
forms/species-form
species=model
isEditing=true
save="save"
cancel="cancel"
}}

View file

@ -1,22 +1,14 @@
import Ember from 'ember';
export default Ember.Controller.extend({
isEditing: false,
actions: {
save: function() {
var species = this.get('model');
if (species.get('isDirty')) {
species.save();
}
this.toggleProperty('isEditing');
},
cancel: function() {
if (this.get('isEditing')) {
var species = this.get('model');
species.get('errors').clear();
species.rollback();
}
this.toggleProperty('isEditing');
userCanEdit: function() {
let meta = this.store.metadataFor('species');
let id = this.get('model.id');
if (meta.canEdit.indexOf( +id ) === -1) {
return false
}
}
return true;
}.property('model.isLoaded').readOnly(),
});

View file

@ -1,7 +1,63 @@
{{
species-details
species=model
isEditing=isEditing
save="save"
cancel="cancel"
}}
<div class="grid-1">
<div class="span-1">
<fieldset class="flakes-information-box {{if isEditing 'is-editing'}}">
<legend>
Species <em>{{model.speciesName}}</em>
</legend>
{{! ROW 1 }}
<div class="grid-4">
<dl class="span-2">
<dt>Strains</dt>
<dd>
{{#each model.strains as |strain index|}}
{{if index ","}}
{{#link-to 'strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</dd>
</dl>
<dl class="span-2">
<dt>Type Species?</dt>
<dd>
{{if model.typeSpecies 'Yes' 'No'}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-4">
<dl class="span-4">
<dt>Etymology</dt>
<dd>
{{model.etymology}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-4">
<dl class="span-1">
<dt>Record Created</dt>
<dd>{{null-time model.createdAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Updated</dt>
<dd>{{null-time model.updatedAt 'LL'}}</dd>
</dl>
<dl class="span-1">
<dt>Record Deleted</dt>
<dd>{{null-time model.deletedAt 'LL'}}</dd>
</dl>
<dl class="span-1"></dl>
</div>
</fieldset>
</div>
</div>
{{#if userCanEdit}}
<br>
{{#link-to 'species.edit' model class="button-gray smaller"}}
Edit
{{/link-to}}
{{/if}}

View file

@ -0,0 +1,6 @@
import Ember from 'ember';
export default Ember.Controller.extend({
sortParams: ['fullNameMU', 'totalMeasurements'],
sortedStrains: Ember.computed.sort('strains', 'sortParams'),
});

View file

@ -3,16 +3,12 @@ import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixi
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model: function() {
return this.store.findAll('strain');
return Ember.RSVP.hash({
strains: this.store.findAll('strain'),
});
},
setupController: function(controller, model) {
var tableAttrs = [
{ name: 'Name', attr: 'fullNameMU' },
{ name: 'Total Measurements', attr: 'totalMeasurements' }
];
controller.set('model', model);
controller.set('tableAttrs', tableAttrs);
controller.set('row', 'strain-index-row');
controller.set('sort', ['fullNameMU']);
controller.setProperties(model);
},
});

View file

@ -1,12 +1,27 @@
<h2>{{genus-name}} Strains</h2>
<h3>Total strains: {{model.length}}</h3>
<h3>Total strains: {{strains.length}}</h3>
{{add-button label="Add Strain" link="strains.new"}}
{{
sortable-table
content=model
tableAttrs=tableAttrs
row=row
sortProperties=sort
}}
<table class="flakes-table">
<thead>
<tr>
<th>Species</th>
<th>Total Measurements</th>
</tr>
</thead>
<tbody>
{{#each sortedStrains as |row|}}
<tr>
<td>
{{#link-to 'strains.show' row.id classBinding="data.typeStrain:type-strain"}}
{{row.fullNameMU}}
{{/link-to}}
</td>
<td>
{{row.totalMeasurements}}
</td>
</tr>
{{/each}}
</tbody>
</table>

View file

@ -1,9 +0,0 @@
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
namespace: 'api',
host: function() {
return this.get('globals.apiURL');
}.property(),
coalesceFindRequests: true,
});

View file

@ -1,3 +1,3 @@
{{#each user in model}}
{{#each model as |user|}}
{{user.email}}<br>
{{/each}}

View file

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View file

@ -0,0 +1 @@
<h3>Failure</h3>

View file

@ -0,0 +1,31 @@
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['grid-1'],
passwordConfirm: null,
actions: {
save: function() {
let user = this.get('user');
// All validation is server-side, except for password verification matching
if (user.get('password') !== this.get('passwordConfirm')) {
this.get('flashMessages').clearMessages();
this.get('flashMessages').error("Password fields don't match");
return;
}
if (user.get('isDirty')) {
user.save().then(() => {
this.sendAction();
}).catch(() => {
// Manually clean up messages because there is no transition
this.get('flashMessages').clearMessages();
user.get('errors').forEach((error) => {
this.get('flashMessages').error(`${error.attribute.capitalize()} - ${error.message}`);
});
});
}
},
},
});

View file

@ -0,0 +1,30 @@
<div class="span-1">
<fieldset>
<legend>New User Signup</legend>
<form>
<ul>
<li>
<label>Name</label>
{{input value=user.name}}
</li>
<li>
<label>Email</label>
{{input value=user.email}}
</li>
<li>
<label>Password</label>
{{input type="password" value=user.password}}
</li>
<li>
<label>Password (confirm)</label>
{{input type="password" value=passwordConfirm}}
</li>
<li>
<a class="button-green smaller" {{action 'save'}}>
Submit
</a>
</li>
</ul>
</form>
</fieldset>
</div>

View file

@ -0,0 +1,23 @@
import Ember from 'ember';
import UnauthenticatedRouteMixin from 'simple-auth/mixins/unauthenticated-route-mixin';
export default Ember.Route.extend(UnauthenticatedRouteMixin, {
model: function() {
return Ember.RSVP.hash({
user: this.store.createRecord('user'),
});
},
setupController: function(controller, model) {
controller.setProperties(model);
},
actions: {
success: function() {
this.transitionTo('login').then(() => {
this.get('flashMessages').information(`You have successfully signed up.
Please check your email for further instructions.`);
});
}
},
});

View file

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View file

@ -0,0 +1 @@
<h3>Success</h3>

View file

@ -0,0 +1 @@
{{users/new/new-user-form user=user action="success"}}

View file

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View file

@ -0,0 +1 @@
{{outlet}}