Refactored users/edit
This commit is contained in:
parent
b742ddbb51
commit
1dd0910ed1
13 changed files with 92 additions and 65 deletions
|
@ -1,7 +1,9 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
const { Helper: { helper } } = Ember;
|
||||||
|
|
||||||
export function equalHelper(params) {
|
export function equalHelper(params) {
|
||||||
return params[0] === params[1];
|
return params[0] === params[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Ember.HTMLBars.makeBoundHelper(equalHelper);
|
export default helper(equalHelper);
|
||||||
|
|
|
@ -2,7 +2,7 @@ export default function() {
|
||||||
// Don't use mirage for development (for now)
|
// Don't use mirage for development (for now)
|
||||||
this.urlPrefix = 'http://127.0.0.1:8901';
|
this.urlPrefix = 'http://127.0.0.1:8901';
|
||||||
this.namespace = '/api';
|
this.namespace = '/api';
|
||||||
this.passthrough();
|
this.passthrough('http://localhost:4200/**', 'http://127.0.0.1:8901/**');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function testConfig() {
|
export function testConfig() {
|
||||||
|
|
|
@ -16,6 +16,7 @@ export default Mixin.create({
|
||||||
|
|
||||||
if (model.get('hasDirtyAttributes')) {
|
if (model.get('hasDirtyAttributes')) {
|
||||||
model.save().then((model) => {
|
model.save().then((model) => {
|
||||||
|
this.get('flashMessages').clearMessages();
|
||||||
this.transitionToRoute(fallbackRoute, model);
|
this.transitionToRoute(fallbackRoute, model);
|
||||||
}, () => {
|
}, () => {
|
||||||
ajaxError(model.get('errors'), this.get('flashMessages'));
|
ajaxError(model.get('errors'), this.get('flashMessages'));
|
||||||
|
|
|
@ -5,10 +5,12 @@ const { Mixin, inject: { service }} = Ember;
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
currentUser: service('session-account'),
|
currentUser: service('session-account'),
|
||||||
metaData: null,
|
metaData: null,
|
||||||
|
isAdmin: null,
|
||||||
|
|
||||||
setupMetaDataOnInit: Ember.on('init', function() {
|
setupMetaDataOnInit: Ember.on('init', function() {
|
||||||
this.get('currentUser.account').then((user) => {
|
this.get('currentUser.account').then((user) => {
|
||||||
this.set('metaData', user.get('metaData'));
|
this.set('metaData', user.get('metaData'));
|
||||||
|
this.set('isAdmin', user.get('isAdmin'));
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,5 +6,5 @@ const { Controller } = Ember;
|
||||||
export default Controller.extend(SaveModel, {
|
export default Controller.extend(SaveModel, {
|
||||||
// Required for SaveModel mixin
|
// Required for SaveModel mixin
|
||||||
fallbackRouteSave: 'protected.characteristics.show',
|
fallbackRouteSave: 'protected.characteristics.show',
|
||||||
fallbackRouteCancel: 'protected.characteristics.index',
|
fallbackRouteCancel: 'protected.characteristics.show',
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,40 +1,10 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import ajaxError from '../../../../utils/ajax-error';
|
import SaveModel from '../../../../mixins/save-model';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
const { Controller } = Ember;
|
||||||
actions: {
|
|
||||||
save: function() {
|
|
||||||
let user = this.get('model');
|
|
||||||
|
|
||||||
if (user.get('hasDirtyAttributes')) {
|
export default Controller.extend(SaveModel, {
|
||||||
let attrs = user.changedAttributes(), roleChanged = false;
|
// Required for SaveModel mixin
|
||||||
if (attrs.role) {
|
fallbackRouteSave: 'protected.users.show',
|
||||||
roleChanged = true;
|
fallbackRouteCancel: 'protected.users.show',
|
||||||
}
|
|
||||||
user.save().then((user) => {
|
|
||||||
this.get('flashMessages').clearMessages();
|
|
||||||
if (roleChanged) {
|
|
||||||
// Need to clear the store so that canEdit and canAdd
|
|
||||||
// attributes reflect the new role.
|
|
||||||
this.get('store').unloadAll();
|
|
||||||
}
|
|
||||||
this.transitionToRoute('protected.users.show', user);
|
|
||||||
}, () => {
|
|
||||||
ajaxError(user.get('errors'), this.get('flashMessages'));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.transitionToRoute('protected.users.show', user);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function() {
|
|
||||||
let user = this.get('model');
|
|
||||||
|
|
||||||
user.get('errors').clear();
|
|
||||||
user.rollbackAttributes();
|
|
||||||
|
|
||||||
this.transitionToRoute('protected.users.show', user);
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
const { Route, inject: { service } } = Ember;
|
||||||
currentUser: Ember.inject.service('session-account'),
|
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
currentUser: service('session-account'),
|
||||||
|
|
||||||
|
// Not using ElevatedAccess Mixin because the rules for viewing user accounts
|
||||||
|
// is slightly different.
|
||||||
beforeModel: function(transition) {
|
beforeModel: function(transition) {
|
||||||
this._super(transition);
|
this._super(transition);
|
||||||
|
|
||||||
|
@ -16,7 +20,7 @@ export default Ember.Route.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
model: function(params) {
|
model: function(params) {
|
||||||
return this.store.findRecord('user', params.user_id, { reload: true });
|
return this.store.findRecord('user', params.user_id);
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{{
|
{{
|
||||||
protected/users/user-form
|
protected/users/user-form
|
||||||
user=model
|
user=model
|
||||||
currentUser=currentUser.account
|
on-save=(action "save")
|
||||||
save="save"
|
on-cancel=(action "cancel")
|
||||||
cancel="cancel"
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -5,7 +5,9 @@ const { Component, computed, inject: { service } } = Ember;
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
currentUser: service('session-account'),
|
currentUser: service('session-account'),
|
||||||
|
|
||||||
isUser: computed('model.id', 'currentUser.account.id', function() {
|
user: null,
|
||||||
return this.get('model.id') === this.get('currentUser.account.id');
|
|
||||||
|
isUser: computed('user.id', 'currentUser.account.id', function() {
|
||||||
|
return this.get('user.id') === this.get('currentUser.account.id');
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="span-1">
|
<div class="span-1">
|
||||||
{{#if model.canEdit}}
|
{{#if user.canEdit}}
|
||||||
{{#link-to 'protected.users.edit' user.id class="button-gray smaller"}}
|
{{#link-to 'protected.users.edit' user.id class="button-gray smaller"}}
|
||||||
Edit
|
Edit
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
|
|
|
@ -1,15 +1,61 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import SetupMetaData from '../../../../mixins/setup-metadata';
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
const { Component } = Ember;
|
||||||
|
|
||||||
|
export default Component.extend(SetupMetaData, {
|
||||||
|
// Read-only attributes
|
||||||
|
user: null,
|
||||||
|
isDirty: false,
|
||||||
roles: Ember.String.w('A R W'),
|
roles: Ember.String.w('A R W'),
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
"on-save": null,
|
||||||
|
"on-cancel": null,
|
||||||
|
"on-update": null,
|
||||||
|
|
||||||
|
// Property mapping
|
||||||
|
propertiesList: ['name', 'email', 'role'],
|
||||||
|
name: null,
|
||||||
|
email: null,
|
||||||
|
role: null,
|
||||||
|
|
||||||
|
resetOnInit: Ember.on('init', function() {
|
||||||
|
this.get('propertiesList').forEach((field) => {
|
||||||
|
const valueInUser = this.get('user').get(field);
|
||||||
|
this.set(field, valueInUser);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateField: function(property, value) {
|
||||||
|
this.set(property, value);
|
||||||
|
// Manually compare against passed in value
|
||||||
|
if (this.get('user').get(property) !== value) {
|
||||||
|
this.set('isDirty', true);
|
||||||
|
} else {
|
||||||
|
this.set('isDirty', false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
save: function() {
|
save: function() {
|
||||||
this.sendAction('save');
|
return this.attrs['on-save'](this.getProperties(this.get('propertiesList')));
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel: function() {
|
cancel: function() {
|
||||||
this.sendAction('cancel');
|
return this.attrs['on-cancel']();
|
||||||
|
},
|
||||||
|
|
||||||
|
nameDidChange: function(value) {
|
||||||
|
this.updateField('name', value);
|
||||||
|
},
|
||||||
|
|
||||||
|
emailDidChange: function(value) {
|
||||||
|
this.updateField('email', value);
|
||||||
|
},
|
||||||
|
|
||||||
|
roleDidChange: function(value) {
|
||||||
|
this.updateField('role', value);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
<form class="grid-form" {{action 'save' on='submit'}}>
|
<form class="grid-form" {{action 'save' on='submit'}}>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><em>{{user.name}}</em></legend>
|
<legend><em>{{name}}</em></legend>
|
||||||
<div data-row-span="1">
|
<div data-row-span="1">
|
||||||
<div data-field-span="1">
|
<div data-field-span="1">
|
||||||
<label>Name</label>
|
<label>Name</label>
|
||||||
{{input value=user.name class="user-name"}}
|
{{one-way-input type="text" class="user-name" value=name update=(action "nameDidChange")}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-row-span="1">
|
<div data-row-span="1">
|
||||||
<div data-field-span="1">
|
<div data-field-span="1">
|
||||||
<label>Email</label>
|
<label>Email</label>
|
||||||
{{input value=user.email}}
|
{{one-way-input type="text" class="email" value=email update=(action "emailDidChange")}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-row-span="1">
|
<div data-row-span="1">
|
||||||
<div data-field-span="1">
|
<div data-field-span="1">
|
||||||
<label>Role</label>
|
<label>Role</label>
|
||||||
{{#if session.currentUser.isAdmin}}
|
{{#if isAdmin}}
|
||||||
<select onchange={{action (mut user.role) value="target.value"}}>
|
<select onchange={{action "roleDidChange" value="target.value"}}>
|
||||||
{{#each roles as |roleChoice|}}
|
{{#each roles as |roleChoice|}}
|
||||||
<option value={{roleChoice}} selected={{equal user.role roleChoice}}>{{roleChoice}}</option>
|
<option value={{roleChoice}} selected={{equal role roleChoice}}>{{roleChoice}}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{user.role}}
|
{{role}} {{!-- Not editable --}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
<a class="button-red smaller" {{action 'cancel'}}>
|
<a class="button-red smaller" {{action 'cancel'}}>
|
||||||
Cancel
|
Cancel
|
||||||
</a>
|
</a>
|
||||||
{{#if user.hasDirtyAttributes}}
|
{{#if isDirty}}
|
||||||
<button type="submit" class="button-green smaller save-user">
|
<button type="submit" class="button-green smaller save-user">
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -2,19 +2,20 @@ import Ember from 'ember';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
import parseBase64 from '../utils/parse-base64';
|
import parseBase64 from '../utils/parse-base64';
|
||||||
|
|
||||||
const { service } = Ember.inject;
|
const { Service, computed, isEmpty, inject: { service } } = Ember;
|
||||||
|
const { PromiseObject } = DS;
|
||||||
|
|
||||||
export default Ember.Service.extend({
|
export default Service.extend({
|
||||||
session: service('session'),
|
session: service('session'),
|
||||||
store: service(),
|
store: service(),
|
||||||
|
|
||||||
account: Ember.computed('session.data.authenticated.access_token', function() {
|
account: computed('session.data.authenticated.access_token', function() {
|
||||||
const token = this.get('session.data.authenticated.access_token');
|
const token = this.get('session.data.authenticated.access_token');
|
||||||
const claims = parseBase64(token);
|
const claims = parseBase64(token);
|
||||||
const id = claims['sub'];
|
const id = claims['sub'];
|
||||||
|
|
||||||
if (!Ember.isEmpty(id)) {
|
if (!isEmpty(id)) {
|
||||||
return DS.PromiseObject.create({
|
return PromiseObject.create({
|
||||||
promise: this.get('store').findRecord('user', id),
|
promise: this.get('store').findRecord('user', id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue