diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 0e7e5f7f7..accba55a0 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -21,6 +21,10 @@ Router.map(function () { this.route('group', { path: ':group_id' }, function () {}); this.route('new'); }); + this.route('roles', function () { + this.route('role', { path: ':role_id' }, function () {}); + this.route('new'); + }); }); }); diff --git a/ui/core/app/routes/scopes/scope/roles.js b/ui/core/app/routes/scopes/scope/roles.js new file mode 100644 index 000000000..fd451c719 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/roles.js @@ -0,0 +1,72 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; + +export default class ScopesScopeRolesRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Load all roles under current scope. + * @return {Promise{[RoleModel]}} + */ + async model() { + return this.store.findAll('role', this.scopeAdapterOptions()); + } + + // =actions + /** + * Rollback changes on an role. + * @param {RoleModel} role + */ + @action + cancel(role) { + const { isNew } = role; + role.rollbackAttributes(); + if (isNew) this.transitionTo('scopes.scope.roles'); + } + + /** + * Save an role in current scope. + * @param {RoleModel} role + */ + @action + async save(role) { + try { + await role.save(this.scopeAdapterOptions()); + this.refresh(); + this.notify.success(this.intl.t('notify.save-success')); + this.transitionTo('scopes.scope.roles.role', role); + } catch (error) { + // TODO: replace with translated strings + this.notify.error(error.message, { closeAfter: null }); + } + } + + /** + * Delete role in current scope and redirect to index. + * @param {RoleModel} role + */ + @action + async delete(role) { + try { + await role.destroyRecord(this.scopeAdapterOptions()); + this.refresh(); + this.notify.success(this.intl.t('notify.role.delete-success')); + this.transitionTo('scopes.scope.roles'); + } catch (error) { + // TODO: replace with translated strings + this.notify.error(error.message, { closeAfter: null }); + } + } + + scopeAdapterOptions() { + const { id: scope_id } = this.modelFor('scopes.scope'); + const adapterOptions = { scopeID: scope_id }; + return { adapterOptions }; + } +} diff --git a/ui/core/app/routes/scopes/scope/roles/index.js b/ui/core/app/routes/scopes/scope/roles/index.js new file mode 100644 index 000000000..f2a8d7af1 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/roles/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeRolesIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/roles/new.js b/ui/core/app/routes/scopes/scope/roles/new.js new file mode 100644 index 000000000..f39f6e6c2 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/roles/new.js @@ -0,0 +1,13 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeRolesNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved role. + * @return {RoleModel} + */ + model() { + return this.store.createRecord('role'); + } +} diff --git a/ui/core/app/routes/scopes/scope/roles/role.js b/ui/core/app/routes/scopes/scope/roles/role.js new file mode 100644 index 000000000..781bb4e47 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/roles/role.js @@ -0,0 +1,17 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeRolesRoleRoute extends Route { + // =methods + + /** + * Load a role in current scope. + * @param {object} params + * @param {string} params.role_id + * @return {RoleModel} + */ + async model({ role_id }) { + const { id: scope_id } = this.modelFor('scopes.scope'); + const adapterOptions = { scopeID: scope_id }; + return this.store.findRecord('role', role_id, { adapterOptions }); + } +} diff --git a/ui/core/app/routes/scopes/scope/roles/role/index.js b/ui/core/app/routes/scopes/scope/roles/role/index.js new file mode 100644 index 000000000..359e9c9f5 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/roles/role/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeRolesRoleIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/users.js b/ui/core/app/routes/scopes/scope/users.js index bf0ba95c4..8f4f65905 100644 --- a/ui/core/app/routes/scopes/scope/users.js +++ b/ui/core/app/routes/scopes/scope/users.js @@ -58,7 +58,7 @@ export default class ScopesScopeUsersRoute extends Route { await user.destroyRecord(this.scopeAdapterOptions()); this.refresh(); this.transitionTo('scopes.scope.users'); - this.notify.success(this.intl.t('notify.delete-success')); + this.notify.success(this.intl.t('notify.user.delete-success')); } catch (error) { // TODO: replace with translated strings this.notify.error(error.message, { closeAfter: null }); diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index f3199821b..55e35d7e0 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -15,6 +15,9 @@ {{t "resources.groups"}} + + {{t "resources.roles"}} + {{outlet "sidebar"}} diff --git a/ui/core/app/templates/scopes/scope/roles.hbs b/ui/core/app/templates/scopes/scope/roles.hbs new file mode 100644 index 000000000..6d511b7f7 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/roles.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.roles")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/roles/index.hbs b/ui/core/app/templates/scopes/scope/roles/index.hbs new file mode 100644 index 000000000..e0e28cf9a --- /dev/null +++ b/ui/core/app/templates/scopes/scope/roles/index.hbs @@ -0,0 +1,63 @@ + + + + + + + +

{{t "resources.roles"}}

+
+ + + {{#if @model}} + {{t 'titles.new'}} + {{/if}} + + + + + {{#if @model}} + + + + + {{t 'form.label.name'}} + {{t 'form.label.description'}} + + + + {{#each @model as |role|}} + + + + {{role.displayName}} + + + {{role.description}} + + {{/each}} + + + + {{else}} + + + + + {{t 'descriptions.roles-welcome'}} + + + + {{t 'titles.new'}} + + + + + {{/if}} + + + +
diff --git a/ui/core/app/templates/scopes/scope/roles/new.hbs b/ui/core/app/templates/scopes/scope/roles/new.hbs new file mode 100644 index 000000000..efddd8fb9 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/roles/new.hbs @@ -0,0 +1,19 @@ +{{title (t 'titles.new')}} + + + + + + + +

{{t "titles.new"}}

+
+ + + + +
diff --git a/ui/core/app/templates/scopes/scope/roles/role.hbs b/ui/core/app/templates/scopes/scope/roles/role.hbs new file mode 100644 index 000000000..d66e83390 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/roles/role.hbs @@ -0,0 +1,3 @@ +{{title @model.displayName}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/roles/role/index.hbs b/ui/core/app/templates/scopes/scope/roles/role/index.hbs new file mode 100644 index 000000000..1b35c1929 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/roles/role/index.hbs @@ -0,0 +1,27 @@ + + + + + + + +

{{t "resources.role"}}

+
+ + + + + + {{t 'actions.delete'}} + + + +
diff --git a/ui/core/tests/unit/routes/scopes/scope/roles-test.js b/ui/core/tests/unit/routes/scopes/scope/roles-test.js new file mode 100644 index 000000000..f2aa633ee --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/roles-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/roles/index-test.js b/ui/core/tests/unit/routes/scopes/scope/roles/index-test.js new file mode 100644 index 000000000..aad8dd94c --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/roles/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles/index', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/roles/new-test.js b/ui/core/tests/unit/routes/scopes/scope/roles/new-test.js new file mode 100644 index 000000000..1ddf02ba6 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/roles/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles/new', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles/new'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/roles/role-test.js b/ui/core/tests/unit/routes/scopes/scope/roles/role-test.js new file mode 100644 index 000000000..41e292c3c --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/roles/role-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles/role', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles/role'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/roles/role/index-test.js b/ui/core/tests/unit/routes/scopes/scope/roles/role/index-test.js new file mode 100644 index 000000000..1a4aecbf1 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/roles/role/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles/role/index', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles/role/index'); + assert.ok(route); + }); +});