Merge branch 'master' into clostridium

* master: (27 commits)
  Temporary fix for quill editor use in strains edit
  Test new species (plus minor cleanup)
  Wrapping up form cleanup
  Quill DDAU
  Fixed up checkbox input
  WIP (checkbox)
  ember-one-way-input
  DeleteModel Mixin
  Using mixins on new species
  ElevatedAccess Mixin
  SaveModel Mixin
  Refactor species edit
  Refactor species/show
  fix format date import
  nvm
  Drop node version
  trying a different phantomjs route
  Rough in species index test
  Tweak mirage config
  ember-cli-mirage
  ...
This commit is contained in:
Matthew Dillon 2015-11-04 20:29:14 -07:00
commit d674d07951
54 changed files with 549 additions and 267 deletions

View file

@ -13,7 +13,7 @@ export default Ember.Controller.extend({
ajaxError(characteristic.get('errors'), this.get('flashMessages'));
});
} else {
characteristic.deleteRecord().then(() => {
characteristic.destroyRecord().then(() => {
this.transitionToRoute('protected.characteristics.show', characteristic);
});
}

View file

@ -13,12 +13,16 @@ export default Ember.Controller.extend({
ajaxError(characteristic.get('errors'), this.get('flashMessages'));
});
} else {
this.transitionToRoute('protected.characteristics.index');
characteristic.destroyRecord().then(() => {
this.transitionToRoute('protected.characteristics.index');
});
}
},
cancel: function() {
this.transitionToRoute('protected.characteristics.index');
this.get('model').destroyRecord().then(() => {
this.transitionToRoute('protected.characteristics.index');
});
},
},

View file

@ -18,11 +18,11 @@ export default Ember.Route.extend({
actions: {
willTransition: function(/*transition*/) {
let controller = this.get('controller');
let characteristic = controller.get('model');
const controller = this.get('controller');
const characteristic = controller.get('model');
if (characteristic.get('isNew')) {
characteristic.deleteRecord();
characteristic.destroyRecord();
}
},
},

View file

@ -1,30 +1,9 @@
import Ember from 'ember';
import ajaxError from '../../../../utils/ajax-error';
import SaveModel from '../../../../mixins/save-model';
export default Ember.Controller.extend({
actions: {
save: function() {
let species = this.get('model');
const { Controller } = Ember;
if (species.get('hasDirtyAttributes')) {
species.save().then((species) => {
this.transitionToRoute('protected.species.show', species);
}, () => {
ajaxError(species.get('errors'), this.get('flashMessages'));
});
} else {
this.transitionToRoute('protected.species.show', species);
}
},
cancel: function() {
let species = this.get('model');
species.get('errors').clear();
species.rollbackAttributes();
this.transitionToRoute('protected.species.show', species);
},
},
export default Controller.extend(SaveModel, {
// Required for SaveModel mixin
fallbackRoute: 'protected.species.show',
});

View file

@ -1,28 +1,15 @@
import Ember from 'ember';
import ElevatedAccess from '../../../../mixins/elevated-access';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
beforeModel: function(transition) {
this._super(transition);
this.get('currentUser.account').then((user) => {
if (user.get('isReader')) {
this.transitionTo('protected.species.index');
}
});
},
export default Route.extend(ElevatedAccess, {
// Required for ElevatedAccess mixin
fallbackRouteBefore: 'protected.species.index',
fallbackRouteAfter: 'protected.species.show',
afterModel: function(species) {
if (!species.get('canEdit')) {
this.transitionTo('species.show', species.get('id'));
}
},
setupController: function(controller, model) {
controller.set('model', model);
this.get('currentUser.account').then((user) => {
controller.set('metaData', user.get('metaData'));
});
model: function(params) {
return this.store.findRecord('species', params.species_id);
},
});

View file

@ -1,7 +1,6 @@
{{
protected/species/species-form
species=model
metaData=metaData
save="save"
cancel="cancel"
on-save=(action "save")
on-cancel=(action "cancel")
}}

View file

@ -1,6 +0,0 @@
import Ember from 'ember';
export default Ember.Controller.extend({
sortParams: ['speciesName', 'strainCount'],
sortedSpecies: Ember.computed.sort('model', 'sortParams'),
});

View file

@ -1,17 +1,10 @@
import Ember from 'ember';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
export default Route.extend({
model: function() {
return this.store.findAll('species');
},
setupController: function(controller, model) {
controller.set('model', model);
this.get('currentUser.account').then((user) => {
controller.set('metaData', user.get('metaData'));
});
},
});

View file

@ -0,0 +1,20 @@
import Ember from 'ember';
const { Component, inject: { service }} = Ember;
export default Component.extend({
currentUser: service('session-account'),
metaData: null,
species: null,
setupMetaDataOnInit: Ember.on('init', function() {
this.get('currentUser.account').then((user) => {
this.set('metaData', user.get('metaData'));
});
}),
sortParams: ['speciesName', 'strainCount'],
sortedSpecies: Ember.computed.sort('species', 'sortParams'),
});

View file

@ -0,0 +1,33 @@
<h3 id="total-species">Total species: {{species.length}}</h3>
{{add-button label="Add Species" link="protected.species.new" canAdd=metaData.canAdd}}
<table class="flakes-table">
<thead>
<tr>
<th>Name</th>
<th>Strains</th>
</tr>
</thead>
<tbody>
{{#each sortedSpecies as |species|}}
<tr>
<td>
<em>
{{#link-to 'protected.species.show' species}}
{{species.speciesName}}
{{/link-to}}
</em>
</td>
<td>
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
{{/each}}
</td>
</tr>
{{/each}}
</tbody>
</table>

View file

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

View file

@ -1,27 +1,9 @@
import Ember from 'ember';
import ajaxError from '../../../../utils/ajax-error';
import SaveModel from '../../../../mixins/save-model';
export default Ember.Controller.extend({
actions: {
save: function() {
let species = this.get('model');
const { Controller } = Ember;
if (species.get('hasDirtyAttributes')) {
species.save().then((species) => {
this.transitionToRoute('protected.species.show', species.get('id'));
}, () => {
ajaxError(species.get('errors'), this.get('flashMessages'));
});
} else {
species.deleteRecord().then(() => {
this.transitionToRoute('protected.species.index');
});
}
},
cancel: function() {
this.transitionToRoute('protected.species.index');
},
},
export default Controller.extend(SaveModel, {
// Required for SaveModel mixin
fallbackRoute: 'protected.species.show',
});

View file

@ -1,30 +1,14 @@
import Ember from 'ember';
import ElevatedAccess from '../../../../mixins/elevated-access';
export default Ember.Route.extend({
currentUser: Ember.inject.service('session-account'),
const { Route } = Ember;
beforeModel: function(transition) {
this._super(transition);
this.get('currentUser.account').then((user) => {
if (user.get('isReader')) {
this.transitionTo('protected.species.index');
}
});
},
export default Route.extend(ElevatedAccess, {
// Required for ElevatedAccess mixin
fallbackRouteBefore: 'protected.species.index',
fallbackRouteAfter: 'protected.species.show',
model: function() {
return this.store.createRecord('species');
},
actions: {
willTransition: function(/*transition*/) {
let controller = this.get('controller');
let species = controller.get('model');
if (species.get('isNew')) {
species.deleteRecord();
}
},
},
});

View file

@ -1,6 +1,6 @@
{{
protected/species/species-form
species=model
save="save"
cancel="cancel"
on-save=(action "save")
on-cancel=(action "cancel")
}}

View file

@ -1,12 +1,9 @@
import Ember from 'ember';
import DeleteModel from '../../../../mixins/delete-model';
export default Ember.Controller.extend({
actions: {
delete: function() {
this.get('model').destroyRecord().then(() => {
this.transitionToRoute('protected.species.index');
});
},
},
const { Controller } = Ember;
export default Controller.extend(DeleteModel, {
// Required for DeleteModel mixin
transitionRoute: 'protected.species.index',
});

View file

@ -1,8 +1,10 @@
import Ember from 'ember';
export default Ember.Route.extend({
const { Route } = Ember;
export default Route.extend({
model: function(params) {
return this.store.findRecord('species', params.species_id, { reload: true });
return this.store.findRecord('species', params.species_id);
},
});

View file

@ -0,0 +1,14 @@
import Ember from 'ember';
const { Component } = Ember;
export default Component.extend({
species: null,
"on-delete": null,
actions: {
deleteSpecies: function() {
return this.attrs['on-delete']();
},
},
});

View file

@ -0,0 +1,62 @@
<div class="grid-1">
<div class="span-1">
<fieldset class="flakes-information-box">
<legend>
Species <em>{{species.speciesName}}</em>
</legend>
{{! ROW 1 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Strains</dt>
<dd>
<ul>
{{#each species.strains as |strain index|}}
<li>
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
</li>
{{/each}}
</ul>
</dd>
</dl>
<dl class="span-1">
<dt>Type Species?</dt>
<dd>
{{if species.typeSpecies 'Yes' 'No'}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-1 gutter-20">
<dl class="span-1">
<dt>Etymology</dt>
<dd>
{{{species.etymology}}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-2 gutter-20">
<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>
</div>
</fieldset>
</div>
</div>
{{#if species.canEdit}}
<br>
{{#link-to 'protected.species.edit' species class="button-gray smaller"}}
Edit
{{/link-to}}
{{delete-button delete=(action 'deleteSpecies')}}
{{/if}}

View file

@ -1,62 +1,5 @@
<div class="grid-1">
<div class="span-1">
<fieldset class="flakes-information-box">
<legend>
Species <em>{{model.speciesName}}</em>
</legend>
{{! ROW 1 }}
<div class="grid-2 gutter-20">
<dl class="span-1">
<dt>Strains</dt>
<dd>
<ul>
{{#each model.strains as |strain index|}}
<li>
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
{{/link-to}}
</li>
{{/each}}
</ul>
</dd>
</dl>
<dl class="span-1">
<dt>Type Species?</dt>
<dd>
{{if model.typeSpecies 'Yes' 'No'}}
</dd>
</dl>
</div>
{{! ROW 2 }}
<div class="grid-1 gutter-20">
<dl class="span-1">
<dt>Etymology</dt>
<dd>
{{{model.etymology}}}
</dd>
</dl>
</div>
{{! ROW 3 }}
<div class="grid-2 gutter-20">
<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>
</div>
</fieldset>
</div>
</div>
{{#if model.canEdit}}
<br>
{{#link-to 'protected.species.edit' model class="button-gray smaller"}}
Edit
{{/link-to}}
{{delete-button delete=(action 'delete')}}
{{/if}}
{{
protected/species/show/species-card
species=model
on-delete=(action 'delete')
}}

View file

@ -1,13 +1,71 @@
import Ember from 'ember';
export default Ember.Component.extend({
const { Component, inject: { service } } = Ember;
export default Component.extend({
currentUser: service('session-account'),
// Read-only attributes
species: null,
isNew: null,
isDirty: false,
// Actions
"on-save": null,
"on-cancel": null,
"on-update": null,
// Property mapping
propertiesList: ['speciesName', 'typeSpecies', 'strains', 'etymology'],
speciesName: null,
typeSpecies: null,
strains: null,
etymology: null,
resetOnInit: Ember.on('init', function() {
this.get('propertiesList').forEach((field) => {
const valueInSpecies = this.get('species').get(field);
this.set(field, valueInSpecies);
});
// Read-only attributes
this.set('isNew', this.get('species.isNew'));
}),
setupMetaDataOnInit: Ember.on('init', function() {
this.get('currentUser.account').then((user) => {
this.set('metaData', user.get('metaData'));
});
}),
updateField: function(property, value) {
this.set(property, value);
// Manually compare against passed in value
if (this.get('species').get(property) !== value) {
this.set('isDirty', true);
} else {
this.set('isDirty', false);
}
},
actions: {
save: function() {
this.sendAction('save');
return this.attrs['on-save'](this.getProperties(this.get('propertiesList')));
},
cancel: function() {
this.sendAction('cancel');
return this.attrs['on-cancel']();
},
}
speciesNameDidChange: function(value) {
this.updateField('speciesName', value);
},
typeSpeciesDidChange: function() {
this.updateField('typeSpecies', !this.get('typeSpecies'));
},
etymologyDidChange: function(value) {
this.updateField('etymology', value);
},
},
});

View file

@ -1,21 +1,22 @@
<form class="grid-form" {{action 'save' on='submit'}}>
<fieldset>
<legend><em>{{species.speciesName}}</em></legend>
<legend><em>{{speciesName}}</em></legend>
<div data-row-span="2">
<div data-field-span="1">
<label>Species Name</label>
{{input value=species.speciesName}}
{{one-way-input type="text" class="species-name" value=speciesName update=(action "speciesNameDidChange")}}
</div>
<div data-field-span="1">
<label>Type Species?</label>
{{input type="checkbox" checked=species.typeSpecies}} {{if species.typeSpecies 'Yes' 'No'}}
<input type="checkbox" checked={{typeSpecies}} value="{{typeSpecies}}" onchange={{action "typeSpeciesDidChange"}}>
{{if typeSpecies 'Yes' 'No'}}
</div>
</div>
{{#unless species.isNew}}
{{#unless isNew}}
<div data-row-span="1">
<div data-field-span="1">
<label>Strains</label>
{{#each species.strains as |strain index|}}
{{#each strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
{{{strain.strainNameMU}}}
@ -29,7 +30,7 @@
<div data-row-span="1">
<div data-field-span="1">
<label>Etymology</label>
{{text-editor value=species.etymology}}
{{text-editor value=etymology update=(action "etymologyDidChange")}}
</div>
</div>
</fieldset>
@ -37,8 +38,8 @@
<a class="button-red smaller" {{action 'cancel'}}>
Cancel
</a>
{{#if species.hasDirtyAttributes}}
<button type="submit" class="button-green smaller">
{{# if isDirty}}
<button type="submit" class="button-green smaller save-species">
Save
</button>
{{/if}}

View file

@ -13,7 +13,7 @@ export default Ember.Controller.extend({
ajaxError(strain.get('errors'), this.get('flashMessages'));
});
} else {
strain.deleteRecord().then(() => {
strain.destroyRecord().then(() => {
this.transitionToRoute('protected.strains.show', strain);
});
}

View file

@ -13,12 +13,16 @@ export default Ember.Controller.extend({
ajaxError(strain.get('errors'), this.get('flashMessages'));
});
} else {
this.transitionToRoute('protected.strains.index');
strain.destroyRecord().then(() => {
this.transitionToRoute('protected.strains.index');
});
}
},
cancel: function() {
this.transitionToRoute('protected.strains.index');
this.get('strain').destroyRecord().then(() => {
this.transitionToRoute('protected.strains.index');
});
},
},

View file

@ -25,11 +25,11 @@ export default Ember.Route.extend({
actions: {
willTransition: function(/*transition*/) {
let controller = this.get('controller');
let strain = controller.get('strain');
const controller = this.get('controller');
const strain = controller.get('strain');
if (strain.get('isNew')) {
strain.deleteRecord();
strain.destroyRecord();
}
},
},

View file

@ -25,7 +25,7 @@ export default Ember.Component.extend({
save: function() {
if (this.get('rowChanged')) {
this.get('row').save().then(() => {
this.get('flashMessages').clearMessage();
this.get('flashMessages').clearMessages();
this.toggleProperty('isEditing');
}, () => {
ajaxError(this.get('row.errors'), this.get('flashMessages'));

View file

@ -9,5 +9,13 @@ export default Ember.Component.extend({
cancel: function() {
this.sendAction('cancel');
},
}
isolatedFromDidChange: function(value) {
this.set('strain.isolatedFrom', value);
},
notesDidChange: function(value) {
this.set('strain.notes', value);
},
},
});

View file

@ -25,7 +25,7 @@
<div data-row-span="2">
<div data-field-span="2">
<label>Isolated From</label>
{{text-editor value=strain.isolatedFrom}}
{{text-editor value=strain.isolatedFrom update=(action "isolatedFromDidChange")}}
</div>
</div>
<div data-row-span="3">
@ -45,7 +45,7 @@
<div data-row-span="2">
<div data-field-span="2">
<label>Notes</label>
{{text-editor value=strain.notes}}
{{text-editor value=strain.notes update=(action "notesDidChange")}}
</div>
</div>
</fieldset>