diff --git a/.gitignore b/.gitignore
index 581ad43..08e02d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,4 +15,4 @@
/libpeerconnection.log
npm-debug.log
testem.log
-.divshot-cache
\ No newline at end of file
+.firebase
diff --git a/app/pods/application/adapter.js b/app/adapters/application.js
similarity index 86%
rename from app/pods/application/adapter.js
rename to app/adapters/application.js
index 0d7ed91..aa4cbcf 100644
--- a/app/pods/application/adapter.js
+++ b/app/adapters/application.js
@@ -1,9 +1,13 @@
import DS from 'ember-data';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
+import Ember from 'ember';
+const { inject: { service } } = Ember;
const { RESTAdapter } = DS;
export default RESTAdapter.extend(DataAdapterMixin, {
+ globals: service(),
+
authorizer: 'authorizer:application',
namespace: function() {
diff --git a/app/adapters/user.js b/app/adapters/user.js
new file mode 100644
index 0000000..689a6ec
--- /dev/null
+++ b/app/adapters/user.js
@@ -0,0 +1,7 @@
+import ApplicationAdapter from '../adapters/application';
+
+export default ApplicationAdapter.extend({
+ // If coalesceFindRequests is on, and we 403 on any requests, ESA logs
+ // the current user out. Better to split the requests up at the adapter level.
+ coalesceFindRequests: false,
+});
diff --git a/app/authenticators/oauth2.js b/app/authenticators/oauth2.js
index c5c9221..7662be1 100644
--- a/app/authenticators/oauth2.js
+++ b/app/authenticators/oauth2.js
@@ -1,6 +1,70 @@
import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
import config from '../config/environment';
+import parseBase64 from '../utils/parse-base64';
+import Ember from 'ember';
+const { RSVP: { Promise }, isEmpty, run, Logger: { warn } } = Ember;
export default OAuth2PasswordGrant.extend({
serverTokenEndpoint: `${config.apiURL}/api/authenticate`,
+ serverTokenRefreshEndpoint: `${config.apiURL}/api/refresh`,
+
+ authenticate: function(identification, password) {
+ return new Promise((resolve, reject) => {
+ const data = { username: identification, password };
+ const serverTokenEndpoint = this.get('serverTokenEndpoint');
+ this.makeRequest(serverTokenEndpoint, data).then((response) => {
+ run(() => {
+ const token = parseBase64(response['access_token']);
+ const expiresAt = this._absolutizeExpirationTime(token['exp']);
+ this._scheduleAccessTokenRefresh(expiresAt, response['access_token']);
+ if (!isEmpty(expiresAt)) {
+ response = Ember.merge(response, { 'expires_at': expiresAt });
+ }
+ resolve(response);
+ });
+ }, (xhr) => {
+ run(null, reject, xhr.responseJSON || xhr.responseText);
+ });
+ });
+ },
+
+ _scheduleAccessTokenRefresh: function(expiresAt, accessToken) {
+ if (this.get('refreshAccessTokens')) {
+ const now = (new Date()).getTime();
+ const offset = (Math.floor(Math.random() * 5) + 5) * 1000;
+ if (!isEmpty(accessToken) && !isEmpty(expiresAt) && expiresAt > now - offset) {
+ run.cancel(this._refreshTokenTimeout);
+ delete this._refreshTokenTimeout;
+ if (!Ember.testing) {
+ this._refreshTokenTimeout = run.later(this, this._refreshAccessToken, expiresAt, accessToken, expiresAt - now - offset);
+ }
+ }
+ }
+ },
+
+ _refreshAccessToken: function(expiresAt, accessToken) {
+ const data = { 'token': accessToken };
+ const serverTokenRefreshEndpoint = this.get('serverTokenRefreshEndpoint');
+ return new Promise((resolve, reject) => {
+ this.makeRequest(serverTokenRefreshEndpoint, data).then((response) => {
+ run(() => {
+ const token = parseBase64(response['access_token']);
+ const expiresAt = this._absolutizeExpirationTime(token['exp']);
+ const data = Ember.merge(response, { 'expires_at': expiresAt });
+ this._scheduleAccessTokenRefresh(expiresAt, response['access_token']);
+ this.trigger('sessionDataUpdated', data);
+ resolve(data);
+ });
+ }, (xhr, status, error) => {
+ warn(`Access token could not be refreshed - server responded with ${error}.`);
+ reject();
+ });
+ });
+ },
+
+ _absolutizeExpirationTime: function(expiresAt) {
+ if (!isEmpty(expiresAt)) {
+ return new Date(expiresAt * 1000).getTime();
+ }
+ }
});
diff --git a/app/helpers/get-property.js b/app/helpers/get-property.js
index 9801d7b..4ba442b 100644
--- a/app/helpers/get-property.js
+++ b/app/helpers/get-property.js
@@ -2,7 +2,6 @@ import Ember from 'ember';
const { get, Helper: { helper } } = Ember;
-// This will be unneccesary when ember 2.0 lands
export default helper(function(params) {
return get(params[0], params[1]);
});
diff --git a/app/initializers/global-variables.js b/app/initializers/global-variables.js
deleted file mode 100644
index 554e6d8..0000000
--- a/app/initializers/global-variables.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Ember from 'ember';
-import config from '../config/environment';
-
-var globals = Ember.Object.extend({
- genus: config.APP.genus,
- apiURL: config.apiURL,
-});
-
-export function initialize(container, application) {
- application.register('service:globals', globals, {singleton: true});
- application.inject('route', 'globals', 'service:globals');
- application.inject('controller', 'globals', 'service:globals');
- application.inject('component', 'globals', 'service:globals');
- application.inject('adapter', 'globals', 'service:globals');
-}
-
-export default {
- name: 'global-variables',
- initialize: initialize
-};
diff --git a/app/mirage/config.js b/app/mirage/config.js
index 935eb17..418da09 100644
--- a/app/mirage/config.js
+++ b/app/mirage/config.js
@@ -19,11 +19,13 @@ export function testConfig() {
this.post('/species');
this.get('/species/:id');
this.put('/species/:id');
+ this.delete('/species/:id');
this.get('/characteristics');
this.post('/characteristics');
this.get('/characteristics/:id');
this.put('/characteristics/:id');
+ this.delete('/characteristics/:id');
this.get('/strains', function(db /*, request*/) {
return {
@@ -39,4 +41,5 @@ export function testConfig() {
};
});
this.put('/strains/:id');
+ this.delete('/strains/:id');
}
diff --git a/app/mixins/delete-model.js b/app/mixins/delete-model.js
index e16fb76..9e113a0 100644
--- a/app/mixins/delete-model.js
+++ b/app/mixins/delete-model.js
@@ -8,6 +8,10 @@ export default Mixin.create({
actions: {
delete: function() {
this.get('model').destroyRecord().then(() => {
+ // Instead of unloading the entire store, we keep the loaded user models
+ ['species', 'strain', 'characteristic', 'measurement'].map((model) => {
+ this.get('store').unloadAll(model);
+ });
this.transitionToRoute(this.get('transitionRoute'));
});
},
diff --git a/app/mixins/save-model.js b/app/mixins/save-model.js
index d4459e3..2b652ff 100644
--- a/app/mixins/save-model.js
+++ b/app/mixins/save-model.js
@@ -23,11 +23,16 @@ export default Mixin.create({
cancel: function() {
const model = this.get('model');
+ const isNew = model.get('isNew');
model.get('errors').clear();
model.rollbackAttributes();
- this.transitionToRoute(this.get('fallbackRouteCancel'), model);
+ if (isNew) {
+ this.transitionToRoute(this.get('fallbackRouteCancel'));
+ } else {
+ this.transitionToRoute(this.get('fallbackRouteCancel'), model);
+ }
},
},
});
diff --git a/app/models/species.js b/app/models/species.js
index 7581d10..362462b 100644
--- a/app/models/species.js
+++ b/app/models/species.js
@@ -1,6 +1,5 @@
import DS from 'ember-data';
import config from '../config/environment';
-import Ember from 'ember';
const { Model, attr, hasMany } = DS;
@@ -17,9 +16,4 @@ export default Model.extend({
updatedBy : attr('number'),
sortOrder : attr('number'),
canEdit : attr('boolean'),
-
- // TODO: move this to component/helper
- speciesNameMU: function() {
- return Ember.String.htmlSafe(`${this.get('speciesName')}`);
- }.property('speciesName').readOnly(),
});
diff --git a/app/models/strain.js b/app/models/strain.js
index b202a78..04489a0 100644
--- a/app/models/strain.js
+++ b/app/models/strain.js
@@ -2,6 +2,7 @@ import DS from 'ember-data';
import Ember from 'ember';
const { Model, hasMany, belongsTo, attr } = DS;
+const { computed, String: { htmlSafe } } = Ember;
export default Model.extend({
measurements : hasMany('measurements', { async: false }),
@@ -22,19 +23,8 @@ export default Model.extend({
sortOrder : attr('number'),
canEdit : attr('boolean'),
- // TODO: move this to component/helper
- strainNameMU: function() {
- let type = this.get('typeStrain') ? 'T' : '';
- return Ember.String.htmlSafe(`${this.get('strainName')}${type}`);
- }.property('strainName', 'typeStrain').readOnly(),
-
- // TODO: move this to component/helper
- fullName: Ember.computed('species', 'strainName', function() {
- return `${this.get('species.speciesName')} ${this.get('strainNameMU')}`;
+ fullNameMU: computed('species', 'strainName', function() {
+ const type = this.get('typeStrain') ? 'T' : '';
+ return htmlSafe(`${this.get('species.speciesName')} ${this.get('strainName')}${type}`);
}),
-
- // TODO: move this to component/helper
- fullNameMU: function() {
- return Ember.String.htmlSafe(`${this.get('species.speciesName')} ${this.get('strainNameMU')}`);
- }.property('species', 'strainNameMU').readOnly(),
});
diff --git a/app/pods/components/delete-button/component.js b/app/pods/components/delete-button/component.js
index 2ceca5b..77fc1d0 100644
--- a/app/pods/components/delete-button/component.js
+++ b/app/pods/components/delete-button/component.js
@@ -1,13 +1,23 @@
import Ember from 'ember';
-export default Ember.Component.extend({
- tagName: 'button',
- classNames: ["button-red", "smaller"],
+const { Component } = Ember;
- click: function() {
- if (window.confirm("Do you really want to delete this?")) {
+export default Component.extend({
+ tagName: 'span',
+ showConfirmDelete: false,
+
+ actions: {
+ initialClick: function() {
+ this.set('showConfirmDelete', true);
+ },
+
+ cancelDelete: function() {
+ this.set('showConfirmDelete', false);
+ },
+
+ confirmDelete: function() {
this.attrs.delete();
- }
+ },
},
});
diff --git a/app/pods/components/delete-button/template.hbs b/app/pods/components/delete-button/template.hbs
index 4b2e04f..0fd90d7 100644
--- a/app/pods/components/delete-button/template.hbs
+++ b/app/pods/components/delete-button/template.hbs
@@ -1 +1,12 @@
-Delete
+{{#unless showConfirmDelete}}
+
+{{else}}
+
+
+{{/unless}}
diff --git a/app/pods/components/genus-name/component.js b/app/pods/components/genus-name/component.js
index ce66e93..23cb0a1 100644
--- a/app/pods/components/genus-name/component.js
+++ b/app/pods/components/genus-name/component.js
@@ -1,8 +1,14 @@
import Ember from 'ember';
-export default Ember.Component.extend({
+const { Component, computed, inject: { service } } = Ember;
+
+export default Component.extend({
+ globals: service(),
+
tagName: 'em',
- genus: function() {
+
+ genus: computed('globals.genus', function() {
return this.get('globals.genus').capitalize();
- }.property().readOnly(),
+ }),
+
});
diff --git a/app/pods/components/site-logo/component.js b/app/pods/components/site-logo/component.js
index 6e705e6..2e79985 100644
--- a/app/pods/components/site-logo/component.js
+++ b/app/pods/components/site-logo/component.js
@@ -1,3 +1,7 @@
import Ember from 'ember';
-export default Ember.Component.extend({});
+const { Component, inject: { service } } = Ember;
+
+export default Component.extend({
+ globals: service(),
+});
diff --git a/app/pods/components/strain-name/template.hbs b/app/pods/components/strain-name/template.hbs
new file mode 100644
index 0000000..38822c5
--- /dev/null
+++ b/app/pods/components/strain-name/template.hbs
@@ -0,0 +1 @@
+{{strain.strainName}}{{{if strain.typeStrain 'T' ''}}}
diff --git a/app/pods/components/text-editor/component.js b/app/pods/components/text-editor/component.js
index 01d00fd..5fca82d 100644
--- a/app/pods/components/text-editor/component.js
+++ b/app/pods/components/text-editor/component.js
@@ -1,13 +1,25 @@
import Ember from 'ember';
/* global Quill */
-export default Ember.Component.extend({
- quill: null,
+const { Component } = Ember;
+
+export default Component.extend({
+ // Passed in
value: null,
- update: null,
+
+ // Internal
+ quill: null,
+
+ didReceiveAttrs() {
+ this._super(...arguments);
+
+ if (!this.attrs.update) {
+ throw new Error(`You must provide an \`update\` action.`);
+ }
+ },
didInsertElement: function() {
- let quill = new Quill(`#${this.get('elementId')} .editor`, {
+ const quill = new Quill(`#${this.get('elementId')} .editor`, {
formats: ['bold', 'italic', 'underline'],
modules: {
'toolbar': { container: `#${this.get('elementId')} .toolbar` }
diff --git a/app/pods/components/x-application/component.js b/app/pods/components/x-application/component.js
index 967b497..edb934e 100644
--- a/app/pods/components/x-application/component.js
+++ b/app/pods/components/x-application/component.js
@@ -1,10 +1,12 @@
import Ember from 'ember';
-export default Ember.Component.extend({
+const { Component, inject: { service } } = Ember;
+
+export default Component.extend({
classNames: ["flakes-frame"],
- session: Ember.inject.service('session'),
- currentUser: Ember.inject.service('session-account'),
+ session: service(),
+ currentUser: service('session-account'),
didInsertElement: function() {
FlakesFrame.init();
diff --git a/app/pods/components/x-application/template.hbs b/app/pods/components/x-application/template.hbs
index 49cc38e..386353d 100644
--- a/app/pods/components/x-application/template.hbs
+++ b/app/pods/components/x-application/template.hbs
@@ -33,7 +33,7 @@
{{link-to 'Sign Up' 'users.new'}}
- {{link-to 'Locked Out?' 'users.requestlockouthelp'}}
+ {{link-to 'Reset Password' 'users.requestlockouthelp'}}
{{/if}}
diff --git a/app/pods/components/x-select/component.js b/app/pods/components/x-select/component.js
index 129b943..681597b 100644
--- a/app/pods/components/x-select/component.js
+++ b/app/pods/components/x-select/component.js
@@ -1,50 +1,54 @@
import Ember from 'ember';
-const { Component, isEmpty } = Ember;
+const { Component, get, run: { schedule } } = Ember;
export default Component.extend({
tagName: 'select',
-
- nameAttr: null,
- listItems: null,
- placeholder: null,
- selected: null,
- selectize: null,
- multiple: false,
-
attributeBindings: [
'multiple',
],
+ options: null,
+ selected: null,
+ nameAttr: null,
+ placeholder: null,
+
change: function() {
- this.attrs["update"](this.$()[0].selectize.getValue());
- },
+ let selectedInComponent = this.get('selected');
+ let selectedInWidget = this.$().val();
- didReceiveAttrs: function() {
- this._super(...arguments);
- console.log('didReceiveAttrs');
-
- if (!this.attrs.update) {
- throw new Error(`You must provide an \`update\` action.`);
+ if (this.get('multiple')) {
+ if (selectedInWidget === null) {
+ selectedInWidget = [];
+ }
+ selectedInComponent = selectedInComponent.toString();
+ selectedInWidget = selectedInWidget.toString();
}
- Ember.run.schedule('actions', this, () => {
- console.log('before adding');
- this.$()[0].selectize.setValue(this.get('selected'), true);
- console.log('after adding')
- });
+ // We need this to prevent an infinite loop of afterRender -> change.
+ if (selectedInComponent !== selectedInWidget) {
+ this.attrs.update(this.$().val());
+ }
},
didInsertElement: function() {
- console.log('didInsertElement');
- const options = {
- closeAfterSelect: true,
- selectOnTab: true,
- plugins: ['drag_drop'],
- items: this.get('selected'),
- }
+ let options = {};
+ options.placeholder = this.get('placeholder');
+ options.templateResult = function(item) {
+ if (!item.disabled) {
+ const text = get(item, 'element.innerHTML');
+ const $item = Ember.$(`${text}`);
+ return $item;
+ }
+ };
+ this.$().select2(options);
+ },
- this.$().selectize(options);
+ didRender: function() {
+ const selected = this.get('selected');
+ schedule('afterRender', this, function() {
+ this.$().val(selected).trigger('change');
+ });
},
});
diff --git a/app/pods/components/x-select/template.hbs b/app/pods/components/x-select/template.hbs
index 093ed1e..131449b 100644
--- a/app/pods/components/x-select/template.hbs
+++ b/app/pods/components/x-select/template.hbs
@@ -1,6 +1,3 @@
-{{#if placeholder}}
-
-{{/if}}
-{{#each listItems as |option|}}
-
+{{#each options as |option|}}
+
{{/each}}
diff --git a/app/pods/login/login-form/template.hbs b/app/pods/login/login-form/template.hbs
index 45afb9b..52773ca 100644
--- a/app/pods/login/login-form/template.hbs
+++ b/app/pods/login/login-form/template.hbs
@@ -10,3 +10,7 @@
{{link-to 'Forget your password?' 'users.requestlockouthelp'}}
+
+
+ Just checking things out? Log in with email read-only
and password bacteria
!
+
diff --git a/app/pods/protected/characteristics/show/characteristic-card/template.hbs b/app/pods/protected/characteristics/show/characteristic-card/template.hbs
index e404106..a7520fd 100644
--- a/app/pods/protected/characteristics/show/characteristic-card/template.hbs
+++ b/app/pods/protected/characteristics/show/characteristic-card/template.hbs
@@ -26,7 +26,6 @@
- Measurements
-
-
To add/edit/remove a measurement, please visit the strain's page (links below)
{{protected/characteristics/show/measurements-table characteristic=characteristic}}
diff --git a/app/pods/protected/characteristics/show/measurements-table/component.js b/app/pods/protected/characteristics/show/measurements-table/component.js
index 96b79fc..e1d47d2 100644
--- a/app/pods/protected/characteristics/show/measurements-table/component.js
+++ b/app/pods/protected/characteristics/show/measurements-table/component.js
@@ -1,7 +1,7 @@
import Ember from 'ember';
const { Component, computed } = Ember;
-const { sort } = computed;
+const { alias, sort } = computed;
export default Component.extend({
characteristic: null,
@@ -10,10 +10,9 @@ export default Component.extend({
return this.get('characteristic.measurements.length') > 0;
}),
- sortParams: ['characteristic.characteristicTypeName', 'characteristic.sortOrder', 'characteristic.characteristicName'],
- sortAsc: true,
- paramsChanged: false,
- sortedMeasurements: sort('characteristic.measurements', 'sortParams'),
+ measurements: alias('characteristic.measurements'),
+ sortParams: ['strain.sortOrder'],
+ sortedMeasurements: sort('measurements', 'sortParams'),
actions: {
changeSortParam: function(col) {
diff --git a/app/pods/protected/characteristics/show/measurements-table/template.hbs b/app/pods/protected/characteristics/show/measurements-table/template.hbs
index 8ee1a86..74ce23b 100644
--- a/app/pods/protected/characteristics/show/measurements-table/template.hbs
+++ b/app/pods/protected/characteristics/show/measurements-table/template.hbs
@@ -7,24 +7,24 @@
- Strain |
+ Strain |
Value |
Notes |
- {{#each sortedMeasurements as |row|}}
+ {{#each sortedMeasurements as |measurement|}}
- {{#link-to 'protected.strains.show' row.strain.id}}
- {{{row.strain.strainNameMU}}}
+ {{#link-to 'protected.strains.show' measurement.strain.id classBinding="measurement.strain.typeStrain:type-strain"}}
+ {{measurement.strain.fullNameMU}}
{{/link-to}}
|
- {{row.value}}
+ {{measurement.value}}
|
- {{row.notes}}
+ {{measurement.notes}}
|
{{/each}}
diff --git a/app/pods/protected/characteristics/show/route.js b/app/pods/protected/characteristics/show/route.js
index 0f50705..d6394ce 100644
--- a/app/pods/protected/characteristics/show/route.js
+++ b/app/pods/protected/characteristics/show/route.js
@@ -4,7 +4,7 @@ const { Route } = Ember;
export default Route.extend({
model: function(params) {
- return this.store.findRecord('characteristic', params.characteristic_id);
+ return this.store.findRecord('characteristic', params.characteristic_id, { reload: true });
},
});
diff --git a/app/pods/protected/compare/controller.js b/app/pods/protected/compare/controller.js
index 7e0d72d..378407e 100644
--- a/app/pods/protected/compare/controller.js
+++ b/app/pods/protected/compare/controller.js
@@ -3,8 +3,8 @@ import Ember from 'ember';
const { Controller } = Ember;
export default Controller.extend({
- selectedStrains: null,
- selectedCharacteristics: null,
+ selectedStrains: [],
+ selectedCharacteristics: [],
actions: {
search: function(query) {
@@ -12,12 +12,10 @@ export default Controller.extend({
},
updateStrainSelection: function(selection) {
- console.log(selection);
this.set('selectedStrains', selection);
},
updateCharacteristicSelection: function(selection) {
- console.log(selection);
this.set('selectedCharacteristics', selection);
},
}
diff --git a/app/pods/protected/compare/results/results-table/component.js b/app/pods/protected/compare/results/results-table/component.js
index 87b2369..1fa35ac 100644
--- a/app/pods/protected/compare/results/results-table/component.js
+++ b/app/pods/protected/compare/results/results-table/component.js
@@ -4,6 +4,7 @@ const { Component, computed, inject: { service } } = Ember;
export default Component.extend({
session: service(),
+ globals: service(),
strains: null,
characteristics: null,
diff --git a/app/pods/protected/compare/results/results-table/template.hbs b/app/pods/protected/compare/results/results-table/template.hbs
index c90d3bc..3ecfe46 100644
--- a/app/pods/protected/compare/results/results-table/template.hbs
+++ b/app/pods/protected/compare/results/results-table/template.hbs
@@ -14,8 +14,16 @@
{{#each characteristics as |row|}}
- {{#each row key="@index" as |col|}}
- {{col}} |
+ {{#each row key="@index" as |col index|}}
+
+ {{#unless index}}
+ {{#link-to 'protected.characteristics.show' col.id}}
+ {{col.characteristicName}}
+ {{/link-to}}
+ {{else}}
+ {{col}}
+ {{/unless}}
+ |
{{/each}}
{{/each}}
diff --git a/app/pods/protected/compare/results/route.js b/app/pods/protected/compare/results/route.js
index 72c01f2..6085d85 100644
--- a/app/pods/protected/compare/results/route.js
+++ b/app/pods/protected/compare/results/route.js
@@ -30,16 +30,15 @@ export default Route.extend({
}
const compare = this.controllerFor('protected.compare');
- compare.set('selectedStrains', params.strain_ids.split(','));
- compare.set('selectedCharacteristics', params.characteristic_ids.split(','));
+ compare.set('selectedStrains', params.strain_ids.split(","));
+ compare.set('selectedCharacteristics', params.characteristic_ids.split(","));
return this.get('ajax').request('/compare', { data: params });
},
setupController: function(controller, model) {
model.forEach((m, i) => {
- const c = this.store.peekRecord('characteristic', m[0]);
- model[i][0] = c.get('characteristicName');
+ model[i][0] = this.store.peekRecord('characteristic', m[0]);
});
const compare = this.controllerFor('protected.compare');
diff --git a/app/pods/protected/compare/select-form/component.js b/app/pods/protected/compare/select-form/component.js
index 8c90170..692be67 100644
--- a/app/pods/protected/compare/select-form/component.js
+++ b/app/pods/protected/compare/select-form/component.js
@@ -1,6 +1,6 @@
import Ember from 'ember';
-const { Component } = Ember;
+const { Component, computed: { sort } } = Ember;
export default Component.extend({
characteristics: null,
@@ -10,12 +10,23 @@ export default Component.extend({
"update-strains": null,
"update-characteristics": null,
+
+ charSortParams: ['characteristicTypeName', 'sortOrder', 'characteristicName'],
+ sortedCharacteristics: sort('characteristics', 'charSortParams'),
+ strainSortParams: ['sortOrder'],
+ sortedStrains: sort('strains', 'sortParams'),
+
+ selectedStrains: [],
+ selectedCharacteristics: [],
+
updateStrains: function(selection) {
- this.attrs["update-strains"](selection);
+ this.set('selectedStrains', selection);
+ this.attrs['update-strains'](this.get('selectedStrains'));
},
updateCharacteristics: function(selection) {
- this.attrs['update-characteristics'](selection);
+ this.set('selectedCharacteristics', selection);
+ this.attrs['update-characteristics'](this.get('selectedCharacteristics'));
},
actions: {
@@ -57,7 +68,7 @@ export default Component.extend({
this.updateStrains(selection);
},
- updateCharacteristicSelection: function(selection) {
+ updateCharacteristicsSelection: function(selection) {
this.updateCharacteristics(selection);
},
},
diff --git a/app/pods/protected/compare/select-form/template.hbs b/app/pods/protected/compare/select-form/template.hbs
index 6bf7985..331535d 100644
--- a/app/pods/protected/compare/select-form/template.hbs
+++ b/app/pods/protected/compare/select-form/template.hbs
@@ -6,12 +6,12 @@
{{
x-select
- listItems=strains
- nameAttr="fullNameMU"
- update=(action "updateStrainSelection")
- placeholder="Select one ore more strains"
+ options=sortedStrains
+ nameAttr='fullNameMU'
multiple=true
selected=selectedStrains
+ update=(action "updateStrainSelection")
+ placeholder="Select one or more strains"
}}
@@ -26,12 +26,12 @@
{{
x-select
- listItems=characteristics
- nameAttr="characteristicName"
- update=(action "updateCharacteristicSelection")
- placeholder="Select one ore more characteristics"
+ options=sortedCharacteristics
+ nameAttr='characteristicName'
multiple=true
selected=selectedCharacteristics
+ update=(action "updateCharacteristicsSelection")
+ placeholder="Select one or more characteristics"
}}
diff --git a/app/pods/protected/species/index/species-table/component.js b/app/pods/protected/species/index/species-table/component.js
index 528c48d..53e46a1 100644
--- a/app/pods/protected/species/index/species-table/component.js
+++ b/app/pods/protected/species/index/species-table/component.js
@@ -6,7 +6,7 @@ const { Component, computed: { sort } } = Ember;
export default Component.extend(SetupMetaData, {
species: null,
- sortParams: ['speciesName', 'strainCount'],
+ sortParams: ['sortOrder'],
sortedSpecies: sort('species', 'sortParams'),
});
diff --git a/app/pods/protected/species/index/species-table/template.hbs b/app/pods/protected/species/index/species-table/template.hbs
index f96f9cf..ab9d772 100644
--- a/app/pods/protected/species/index/species-table/template.hbs
+++ b/app/pods/protected/species/index/species-table/template.hbs
@@ -23,7 +23,7 @@
{{#each species.strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
- {{{strain.strainNameMU}}}
+ {{strain-name strain=strain}}
{{/link-to}}
{{/each}}
diff --git a/app/pods/protected/species/show/route.js b/app/pods/protected/species/show/route.js
index c99362f..ac07e8f 100644
--- a/app/pods/protected/species/show/route.js
+++ b/app/pods/protected/species/show/route.js
@@ -4,7 +4,7 @@ const { Route } = Ember;
export default Route.extend({
model: function(params) {
- return this.store.findRecord('species', params.species_id);
+ return this.store.findRecord('species', params.species_id, { reload: true });
},
});
diff --git a/app/pods/protected/species/show/species-card/template.hbs b/app/pods/protected/species/show/species-card/template.hbs
index fac8247..b4e753d 100644
--- a/app/pods/protected/species/show/species-card/template.hbs
+++ b/app/pods/protected/species/show/species-card/template.hbs
@@ -14,7 +14,7 @@
{{#each species.strains as |strain index|}}
{{#link-to 'protected.strains.show' strain.id}}
- {{{strain.strainNameMU}}}
+ {{strain-name strain=strain}}
{{/link-to}}
{{/each}}
diff --git a/app/pods/protected/species/species-form/template.hbs b/app/pods/protected/species/species-form/template.hbs
index 888b03e..f523d56 100644
--- a/app/pods/protected/species/species-form/template.hbs
+++ b/app/pods/protected/species/species-form/template.hbs
@@ -19,7 +19,7 @@
{{#each strains as |strain index|}}
{{if index ","}}
{{#link-to 'protected.strains.show' strain.id}}
- {{{strain.strainNameMU}}}
+ {{strain-name strain=strain}}
{{/link-to}}
{{/each}}
{{add-button label="Add Strain" link="protected.strains.new" canAdd=metaData.canAdd}}
diff --git a/app/pods/protected/strains/edit/controller.js b/app/pods/protected/strains/edit/controller.js
index 4d68665..509b1e7 100644
--- a/app/pods/protected/strains/edit/controller.js
+++ b/app/pods/protected/strains/edit/controller.js
@@ -1,36 +1,61 @@
import Ember from 'ember';
-import SaveModel from '../../../../mixins/save-model';
-import ajaxError from '../../../../utils/ajax-error';
-const { Controller } = Ember;
+const { Controller, RSVP, inject: { service } } = Ember;
+
+export default Controller.extend({
+ ajaxError: service('ajax-error'),
-export default Controller.extend(SaveModel, {
- // Required for SaveModel mixin
fallbackRouteSave: 'protected.strains.show',
fallbackRouteCancel: 'protected.strains.show',
actions: {
- addCharacteristic: function() {
- return this.store.createRecord('measurement', {
- characteristic: this.store.createRecord('characteristic', { sortOrder: -999 }),
+ save: function(properties, deleteQueue, updateQueue) {
+ let promises = [];
+ properties.measurements.forEach((measurement) => {
+ if (measurement.get('isNew')) {
+ promises.push(measurement.save());
+ }
+ });
+
+ updateQueue.forEach((measurement) => {
+ promises.push(measurement.save());
+ });
+
+ deleteQueue.forEach((measurement) => {
+ promises.push(measurement.destroyRecord());
+ });
+
+ const model = this.get('model');
+ const fallbackRoute = this.get('fallbackRouteSave');
+
+ RSVP.all(promises).then(() => {
+ // Can't call _super inside promise, have to reproduce save-model
+ // mixin here :-(
+ model.setProperties(properties);
+ model.save().then((model) => {
+ this.get('flashMessages').clearMessages();
+ this.transitionToRoute(fallbackRoute, model);
+ });
+ }, (errors) => {
+ this.get('ajaxError').alert(errors);
});
},
- saveMeasurement: function(measurement, properties) {
- measurement.setProperties(properties);
- measurement.save().then(() => {
- this.get('flashMessages').clearMessages();
- }, () => {
- ajaxError(measurement.get('errors'), this.get('flashMessages'));
- });
- },
+ cancel: function() {
+ const model = this.get('model');
- deleteMeasurement: function(measurement) {
- const characteristic = measurement.get('characteristic');
- if (characteristic.get('isNew')) {
- characteristic.destroyRecord();
+ model.get('errors').clear();
+ model.rollbackAttributes();
+
+ if (model.get('isNew')) {
+ this.transitionToRoute(this.get('fallbackRouteCancel'));
+ } else {
+ this.transitionToRoute(this.get('fallbackRouteCancel'), model);
}
- measurement.destroyRecord();
+ },
+
+ addMeasurement: function() {
+ return this.store.createRecord('measurement');
},
},
diff --git a/app/pods/protected/strains/edit/template.hbs b/app/pods/protected/strains/edit/template.hbs
index 59d1633..334ad07 100644
--- a/app/pods/protected/strains/edit/template.hbs
+++ b/app/pods/protected/strains/edit/template.hbs
@@ -2,10 +2,8 @@
protected/strains/strain-form
strain=model
speciesList=speciesList
- add-characteristic=(action "addCharacteristic")
+ add-measurement=(action "addMeasurement")
allCharacteristics=allCharacteristics
- save-measurement=(action "saveMeasurement")
- delete-measurement=(action "deleteMeasurement")
on-save=(action "save")
on-cancel=(action "cancel")
}}
diff --git a/app/pods/protected/strains/index/strain-table/component.js b/app/pods/protected/strains/index/strain-table/component.js
index 7b3b21c..1de7256 100644
--- a/app/pods/protected/strains/index/strain-table/component.js
+++ b/app/pods/protected/strains/index/strain-table/component.js
@@ -6,7 +6,7 @@ const { Component, computed: { sort } } = Ember;
export default Component.extend(SetupMetaData, {
strains: null,
- sortParams: ['fullName'],
+ sortParams: ['sortOrder'],
sortedStrains: sort('strains', 'sortParams'),
});
diff --git a/app/pods/protected/strains/index/strain-table/template.hbs b/app/pods/protected/strains/index/strain-table/template.hbs
index bb13d76..afb8cf2 100644
--- a/app/pods/protected/strains/index/strain-table/template.hbs
+++ b/app/pods/protected/strains/index/strain-table/template.hbs
@@ -13,7 +13,7 @@
{{#each sortedStrains as |strain|}}
- {{#link-to 'protected.strains.show' strain classBinding="data.typeStrain:type-strain"}}
+ {{#link-to 'protected.strains.show' strain classBinding="strain.typeStrain:type-strain"}}
{{strain.fullNameMU}}
{{/link-to}}
|
diff --git a/app/pods/protected/strains/measurements-table-row/component.js b/app/pods/protected/strains/measurements-table-row/component.js
index ad63dc9..6b67968 100644
--- a/app/pods/protected/strains/measurements-table-row/component.js
+++ b/app/pods/protected/strains/measurements-table-row/component.js
@@ -10,6 +10,8 @@ export default Component.extend({
allCharacteristics: null,
measurement: null,
isDirty: null,
+ isNew: false,
+ isQueued: false,
// Actions
"save-measurement": null,
@@ -22,11 +24,23 @@ export default Component.extend({
notes: null,
resetOnInit: Ember.on('init', function() {
+ this._resetProperties();
+ }),
+
+ _resetProperties: function() {
this.get('propertiesList').forEach((field) => {
const valueInMeasurement = this.get('measurement').get(field);
this.set(field, valueInMeasurement);
});
- }),
+ // Read-only attributes
+ this.set('isNew', this.get('measurement.isNew'));
+ if (this.get('isNew') && !this.get('isQueued')) {
+ this.set('isEditing', true);
+ } else {
+ this.set('isEditing', false);
+ }
+ this.set('isDirty', false);
+ },
updateField: function(property, value) {
this.set(property, value);
@@ -40,12 +54,22 @@ export default Component.extend({
actions: {
edit: function() {
- this.toggleProperty('isEditing');
+ this.set('isEditing', true);
},
save: function() {
this.attrs['save-measurement'](this.get('measurement'), this.getProperties(this.get('propertiesList')));
- this.toggleProperty('isEditing');
+ this.set('isQueued', true);
+ this._resetProperties();
+ },
+
+ cancel: function() {
+ if (this.get('isNew')) {
+ this.attrs['delete-measurement'](this.get('measurement'));
+ } else {
+ this._resetProperties();
+ this.set('isEditing', false);
+ }
},
delete: function() {
diff --git a/app/pods/protected/strains/measurements-table-row/loading/template.hbs b/app/pods/protected/strains/measurements-table-row/loading/template.hbs
new file mode 100644
index 0000000..e5a3e05
--- /dev/null
+++ b/app/pods/protected/strains/measurements-table-row/loading/template.hbs
@@ -0,0 +1 @@
+{{loading-panel}}
diff --git a/app/pods/protected/strains/measurements-table-row/template.hbs b/app/pods/protected/strains/measurements-table-row/template.hbs
index 0dc03b7..7a51e78 100644
--- a/app/pods/protected/strains/measurements-table-row/template.hbs
+++ b/app/pods/protected/strains/measurements-table-row/template.hbs
@@ -1,5 +1,7 @@
{{#if isEditing}}
- |
+
+ {{{characteristic.characteristicTypeName}}}
+ |
|
{{#if canEdit}}
- {{#if isDirty}}
-
- {{else}}
- |
{{/if}}
diff --git a/app/pods/protected/strains/measurements-table/component.js b/app/pods/protected/strains/measurements-table/component.js
index e4fd3a1..87bf403 100644
--- a/app/pods/protected/strains/measurements-table/component.js
+++ b/app/pods/protected/strains/measurements-table/component.js
@@ -5,13 +5,13 @@ const { sort } = computed;
export default Component.extend({
// Passed in
- strain: null,
+ measurements: null,
allCharacteristics: null,
canEdit: false,
canAdd: false,
// Actions
- "add-characteristic": null,
+ "add-measurement": null,
"save-measurement": null,
"delete-measurement": null,
@@ -19,15 +19,11 @@ export default Component.extend({
sortParams: ['characteristic.characteristicTypeName', 'characteristic.sortOrder', 'characteristic.characteristicName'],
sortAsc: true,
paramsChanged: false,
- sortedMeasurements: sort('strain.measurements', 'sortParams'),
- measurementsPresent: computed('strain.measurements', function() {
- return this.get('strain.measurements.length') > 0;
- }),
+ sortedMeasurements: sort('measurements', 'sortParams'),
actions: {
- addCharacteristic: function() {
- const newChar = this.attrs['add-characteristic']();
- this.get('strain.measurements').addObject(newChar);
+ addMeasurement: function() {
+ return this.attrs['add-measurement']();
},
changeSortParam: function(col) {
diff --git a/app/pods/protected/strains/measurements-table/template.hbs b/app/pods/protected/strains/measurements-table/template.hbs
index 9e22393..9d648b4 100644
--- a/app/pods/protected/strains/measurements-table/template.hbs
+++ b/app/pods/protected/strains/measurements-table/template.hbs
@@ -1,17 +1,16 @@
{{#if canAdd}}
-
- Add characteristic
+
+ Add measurement
{{/if}}
-{{#if measurementsPresent}}
- {{#if paramsChanged}}
-
- Reset sort
-
- {{/if}}
+{{#if paramsChanged}}
+
+ Reset sort
+
+{{/if}}
{{#if canEdit}}
@@ -48,9 +47,10 @@
allCharacteristics=allCharacteristics
canEdit=canEdit
}}
+ {{else}}
+
+ No Measurements on Record |
+
{{/each}}
-{{else}}
-No measurements on record.
-{{/if}}
diff --git a/app/pods/protected/strains/show/route.js b/app/pods/protected/strains/show/route.js
index ea320bd..20008bb 100644
--- a/app/pods/protected/strains/show/route.js
+++ b/app/pods/protected/strains/show/route.js
@@ -4,7 +4,7 @@ const { Route } = Ember;
export default Route.extend({
model: function(params) {
- return this.store.findRecord('strain', params.strain_id);
+ return this.store.findRecord('strain', params.strain_id, { reload: true });
},
});
diff --git a/app/pods/protected/strains/show/strain-card/template.hbs b/app/pods/protected/strains/show/strain-card/template.hbs
index 995326a..4629f23 100644
--- a/app/pods/protected/strains/show/strain-card/template.hbs
+++ b/app/pods/protected/strains/show/strain-card/template.hbs
@@ -1,7 +1,7 @@