From e284e4e78abe2397ffeba4f9f8ecee0992721187 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Mon, 26 Oct 2020 19:14:30 -0400 Subject: [PATCH 01/27] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20always=20attem?= =?UTF-8?q?pt=20to=20load=20org=20scopes=20for=20nav=20purposes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/routes/scopes/scope.js | 21 +++++++++++++++---- .../templates/scopes/scope/-header-nav.hbs | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 7af8591f0..f0911b566 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -1,10 +1,13 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +import { hash } from 'rsvp'; +import { A } from '@ember/array'; export default class ScopesScopeRoute extends Route { // =services @service intl; + @service session; // =methods @@ -35,14 +38,24 @@ export default class ScopesScopeRoute extends Route { } /** - * Adds the set of all org scopes to the controller, which is used by the - * scope navigation template. + * Load all scopes within the current scope context. For example, + * if **this** scope is a project, attempt to load all projects for the owning + * org, as well as all orgs. If **this** scope is an org, attempt to load all + * orgs within the global scope. These are used for scope navigation. + */ + async afterModel() { + this.scopes = await hash({ + orgs: this.store.query('scope', { scope_id: 'global' }).catch(() => A([])) + }); + } + + /** + * Adds the scopes hash to the controller context (see `afterModel`). * @param {Controller} controller */ setupController(controller) { super.setupController(...arguments); - const orgScopes = this.modelFor('scopes').filterBy('isOrg', true); - controller.setProperties({ orgScopes }); + controller.setProperties({ scopes: this.scopes }); } /** diff --git a/ui/core/app/templates/scopes/scope/-header-nav.hbs b/ui/core/app/templates/scopes/scope/-header-nav.hbs index 00484b51a..be1e33452 100644 --- a/ui/core/app/templates/scopes/scope/-header-nav.hbs +++ b/ui/core/app/templates/scopes/scope/-header-nav.hbs @@ -7,7 +7,7 @@ {{t "titles.global"}} - {{#each this.orgScopes as |scope|}} + {{#each this.scopes.orgs as |scope|}} {{scope.displayName}} From cbf2e360ceccabfcc7f03acf57e55ff86383e941 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Mon, 26 Oct 2020 19:44:23 -0400 Subject: [PATCH 02/27] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20scope=20route?= =?UTF-8?q?=20should=20load=20project=20scopes=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/routes/scopes/scope.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index f0911b566..39ba70dfa 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -38,15 +38,19 @@ export default class ScopesScopeRoute extends Route { } /** - * Load all scopes within the current scope context. For example, - * if **this** scope is a project, attempt to load all projects for the owning - * org, as well as all orgs. If **this** scope is an org, attempt to load all - * orgs within the global scope. These are used for scope navigation. + * Load all scopes within the current scope context. Always attempt to load + * org scopes. Only attempt to load project scopes if the current scope is + * a project. These are used for scope navigation. */ - async afterModel() { - this.scopes = await hash({ + async afterModel(model) { + const scopes = { orgs: this.store.query('scope', { scope_id: 'global' }).catch(() => A([])) - }); + }; + if (model.isProject) { + this.projects = this.store.query('scope', { scope_id: model.scopeID }) + .catch(() => A([])) + } + this.scopes = await hash(scopes); } /** From 5c2c910c22eabd700b626b84ffa6ac9333cb2ab1 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 09:52:10 -0400 Subject: [PATCH 03/27] =?UTF-8?q?chore:=20=F0=9F=A4=96=20find=20the=20curr?= =?UTF-8?q?ently=20selected=20org=20and=20project=20for=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/routes/scopes/scope.js | 23 ++++++++++++------- .../templates/scopes/scope/-header-nav.hbs | 15 +++++++++++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 39ba70dfa..4351e112d 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -1,6 +1,5 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { hash } from 'rsvp'; import { A } from '@ember/array'; export default class ScopesScopeRoute extends Route { @@ -43,14 +42,22 @@ export default class ScopesScopeRoute extends Route { * a project. These are used for scope navigation. */ async afterModel(model) { - const scopes = { - orgs: this.store.query('scope', { scope_id: 'global' }).catch(() => A([])) - }; + // First, load orgs and, if necessary, projects + let orgs, projects; + orgs = await this.store.query('scope', { scope_id: 'global' }) + .catch(() => A([])); if (model.isProject) { - this.projects = this.store.query('scope', { scope_id: model.scopeID }) + projects = await this.store.query('scope', { scope_id: model.scopeID }) .catch(() => A([])) } - this.scopes = await hash(scopes); + // Then pull out the "selected" scopes, if relevant + let selectedOrg, selectedProject; + if (model.isGlobal || model.isOrg) selectedOrg = model; + if (model.isProject) { + selectedProject = model; + selectedOrg = this.store.peekRecord('scope', model.scopeID); + } + this.scopes = { orgs, projects, selectedOrg, selectedProject }; } /** @@ -59,7 +66,8 @@ export default class ScopesScopeRoute extends Route { */ setupController(controller) { super.setupController(...arguments); - controller.setProperties({ scopes: this.scopes }); + const scopes = this.scopes; + controller.setProperties({ scopes }); } /** @@ -74,7 +82,6 @@ export default class ScopesScopeRoute extends Route { this.render('scopes/scope/-header-nav', { into: 'application', outlet: 'header-nav', - model: model, }); this.render('scopes/scope/-sidebar', { diff --git a/ui/core/app/templates/scopes/scope/-header-nav.hbs b/ui/core/app/templates/scopes/scope/-header-nav.hbs index be1e33452..02b952ec8 100644 --- a/ui/core/app/templates/scopes/scope/-header-nav.hbs +++ b/ui/core/app/templates/scopes/scope/-header-nav.hbs @@ -1,5 +1,5 @@ {{#if this.session.data.authenticated.isGlobal}} @@ -18,3 +18,16 @@ {{/if}} + +{{#if this.scopes.selectedProject}} + + {{#each this.scopes.projects as |scope|}} + + {{scope.displayName}} + + {{/each}} + +{{/if}} From e8a015676fc101289d32ad0e0136e0a7b338712c Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 11:21:48 -0400 Subject: [PATCH 04/27] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20simplify=20pos?= =?UTF-8?q?t-authenticate=20redirect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/routes/scopes/scope/authenticate/method.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/core/app/routes/scopes/scope/authenticate/method.js b/ui/core/app/routes/scopes/scope/authenticate/method.js index 891fbea04..7f9f87856 100644 --- a/ui/core/app/routes/scopes/scope/authenticate/method.js +++ b/ui/core/app/routes/scopes/scope/authenticate/method.js @@ -53,11 +53,7 @@ export default class ScopesScopeAuthenticateMethodRoute extends Route { requestCookies, { scope, authMethod } ); - if (scope.isGlobal) { - this.transitionTo('scopes.scope.orgs'); - } else { - this.transitionTo('scopes.scope.projects'); - } + this.transitionTo('index'); } catch (e) { const errorMessage = this.intl.t('errors.authentication-failed.title'); this.notify.error(errorMessage, { closeAfter: null }); From 11d3b08b3693627c407331e56df9f4f6b7bdddce Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 13:39:46 -0400 Subject: [PATCH 05/27] =?UTF-8?q?chore:=20=F0=9F=A4=96=20rip=20out=20all?= =?UTF-8?q?=20existing=20projects,=20orgs,=20and=20sub=20scopes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/form/host-catalog/index.hbs | 53 --- .../form/host-set/add-hosts/index.hbs | 56 ---- .../form/host-set/add-hosts/index.js | 57 ---- .../form/host-set/create-host/index.hbs | 82 ----- .../app/components/form/host-set/index.hbs | 59 ---- ui/core/app/components/form/host/index.hbs | 77 ----- ui/core/app/components/form/org/index.hbs | 53 --- ui/core/app/components/form/project/index.hbs | 53 --- .../form/target/add-host-sets/index.hbs | 60 ---- .../form/target/add-host-sets/index.js | 55 --- ui/core/app/components/form/target/index.hbs | 115 ------- ui/core/app/controllers/scopes/scope/orgs.js | 17 - .../app/controllers/scopes/scope/orgs/new.js | 17 - .../app/controllers/scopes/scope/projects.js | 17 - .../controllers/scopes/scope/projects/new.js | 17 - .../scopes/scope/projects/project.js | 12 - .../scope/projects/project/host-catalogs.js | 17 - .../project/host-catalogs/host-catalog.js | 12 - .../host-catalogs/host-catalog/host-sets.js | 18 - .../host-catalog/host-sets/host-set.js | 13 - .../host-sets/host-set/create-host.js | 18 - .../host-catalog/host-sets/new.js | 18 - .../host-catalogs/host-catalog/hosts.js | 18 - .../host-catalogs/host-catalog/hosts/host.js | 13 - .../host-catalogs/host-catalog/hosts/new.js | 18 - .../projects/project/host-catalogs/new.js | 18 - .../scopes/scope/projects/project/sessions.js | 19 -- .../scopes/scope/projects/project/targets.js | 18 - .../scope/projects/project/targets/new.js | 18 - .../scope/projects/project/targets/target.js | 13 - .../project/targets/target/add-host-sets.js | 17 - .../project/targets/target/host-sets.js | 18 - ui/core/app/router.js | 41 --- ui/core/app/routes/scopes/scope.js | 9 +- .../app/routes/scopes/scope/authenticate.js | 9 +- ui/core/app/routes/scopes/scope/index.js | 9 +- ui/core/app/routes/scopes/scope/orgs.js | 60 ---- ui/core/app/routes/scopes/scope/orgs/index.js | 3 - ui/core/app/routes/scopes/scope/orgs/new.js | 16 - ui/core/app/routes/scopes/scope/projects.js | 90 ----- .../app/routes/scopes/scope/projects/index.js | 3 - .../app/routes/scopes/scope/projects/new.js | 17 - .../routes/scopes/scope/projects/project.js | 31 -- .../scope/projects/project/host-catalogs.js | 70 ---- .../project/host-catalogs/host-catalog.js | 52 --- .../host-catalogs/host-catalog/host-sets.js | 76 ----- .../host-catalog/host-sets/host-set.js | 52 --- .../host-sets/host-set/add-hosts.js | 92 ----- .../host-sets/host-set/create-host.js | 90 ----- .../host-catalog/host-sets/host-set/hosts.js | 55 --- .../host-catalog/host-sets/host-set/index.js | 3 - .../host-catalog/host-sets/index.js | 3 - .../host-catalog/host-sets/new.js | 50 --- .../host-catalogs/host-catalog/hosts.js | 77 ----- .../host-catalogs/host-catalog/hosts/host.js | 52 --- .../host-catalog/hosts/host/index.js | 3 - .../host-catalogs/host-catalog/hosts/index.js | 3 - .../host-catalogs/host-catalog/hosts/new.js | 50 --- .../host-catalogs/host-catalog/index.js | 3 - .../projects/project/host-catalogs/index.js | 3 - .../projects/project/host-catalogs/new.js | 17 - .../scopes/scope/projects/project/index.js | 3 - .../scopes/scope/projects/project/sessions.js | 103 ------ .../scope/projects/project/sessions/index.js | 4 - .../scopes/scope/projects/project/targets.js | 67 ---- .../scope/projects/project/targets/index.js | 3 - .../scope/projects/project/targets/new.js | 17 - .../scope/projects/project/targets/target.js | 39 --- .../project/targets/target/add-host-sets.js | 92 ----- .../project/targets/target/host-sets.js | 67 ---- .../targets/target/host-sets/host-set.js | 3 - .../project/targets/target/host-sets/index.js | 3 - .../projects/project/targets/target/index.js | 3 - ui/core/app/templates/scopes/scope.hbs | 50 ++- ui/core/app/templates/scopes/scope/orgs.hbs | 3 - .../app/templates/scopes/scope/orgs/index.hbs | 63 ---- .../app/templates/scopes/scope/orgs/new.hbs | 24 -- .../app/templates/scopes/scope/projects.hbs | 3 - .../templates/scopes/scope/projects/index.hbs | 63 ---- .../templates/scopes/scope/projects/new.hbs | 24 -- .../scopes/scope/projects/project.hbs | 3 - .../scope/projects/project/-sidebar.hbs | 20 -- .../scope/projects/project/host-catalogs.hbs | 3 - .../project/host-catalogs/host-catalog.hbs | 25 -- .../host-catalogs/host-catalog/-actions.hbs | 22 -- .../host-catalogs/host-catalog/-header.hbs | 12 - .../host-catalog/-navigation.hbs | 11 - .../host-catalogs/host-catalog/host-sets.hbs | 3 - .../host-catalog/host-sets/host-set.hbs | 3 - .../host-sets/host-set/-actions.hbs | 16 - .../host-sets/host-set/-header.hbs | 12 - .../host-sets/host-set/-navigation.hbs | 8 - .../host-sets/host-set/add-hosts.hbs | 8 - .../host-sets/host-set/add-hosts/-header.hbs | 5 - .../host-sets/host-set/create-host.hbs | 7 - .../host-set/create-host/-header.hbs | 4 - .../host-catalog/host-sets/host-set/hosts.hbs | 71 ---- .../host-catalog/host-sets/host-set/index.hbs | 5 - .../host-catalog/host-sets/index.hbs | 56 ---- .../host-catalog/host-sets/new.hbs | 7 - .../host-catalog/host-sets/new/-header.hbs | 4 - .../host-catalogs/host-catalog/hosts.hbs | 3 - .../host-catalogs/host-catalog/hosts/host.hbs | 3 - .../host-catalog/hosts/host/-actions.hbs | 9 - .../host-catalog/hosts/host/-header.hbs | 12 - .../host-catalog/hosts/host/-navigation.hbs | 5 - .../host-catalog/hosts/host/index.hbs | 5 - .../host-catalog/hosts/index.hbs | 60 ---- .../host-catalogs/host-catalog/hosts/new.hbs | 7 - .../host-catalog/hosts/new/-header.hbs | 4 - .../host-catalogs/host-catalog/index.hbs | 5 - .../projects/project/host-catalogs/index.hbs | 84 ----- .../projects/project/host-catalogs/new.hbs | 24 -- .../scopes/scope/projects/project/index.hbs | 50 --- .../scope/projects/project/sessions.hbs | 3 - .../scope/projects/project/sessions/index.hbs | 82 ----- .../scopes/scope/projects/project/targets.hbs | 3 - .../scope/projects/project/targets/index.hbs | 88 ----- .../scope/projects/project/targets/new.hbs | 24 -- .../scope/projects/project/targets/target.hbs | 25 -- .../project/targets/target/-actions.hbs | 13 - .../project/targets/target/-header.hbs | 12 - .../project/targets/target/-navigation.hbs | 8 - .../project/targets/target/add-host-sets.hbs | 25 -- .../targets/target/add-host-sets/-header.hbs | 5 - .../project/targets/target/host-sets.hbs | 68 ---- .../targets/target/host-sets/host-set.hbs | 1 - .../projects/project/targets/target/index.hbs | 5 - .../tests/acceptance/authentication-test.js | 24 +- ui/core/tests/acceptance/bread-crumbs-test.js | 249 -------------- .../tests/acceptance/host-catalogs-test.js | 217 ------------ ui/core/tests/acceptance/host-sets-test.js | 203 ----------- .../tests/acceptance/host-sets/hosts-test.js | 235 ------------- ui/core/tests/acceptance/hosts-test.js | 205 ------------ ui/core/tests/acceptance/orgs-test.js | 148 -------- ui/core/tests/acceptance/projects-test.js | 264 --------------- ui/core/tests/acceptance/sessions-test.js | 104 ------ ui/core/tests/acceptance/targets-test.js | 316 ------------------ .../components/form/host-catalog-test.js | 23 -- .../components/form/host-set-test.js | 23 -- .../form/host-set/add-hosts-test.js | 12 - .../integration/components/form/host-test.js | 23 -- .../integration/components/form/org-test.js | 23 -- .../components/form/project-test.js | 23 -- .../components/form/target-test.js | 23 -- .../form/target/add-host-sets-test.js | 12 - .../controllers/scopes/scope/orgs-test.js | 12 - .../controllers/scopes/scope/orgs/new-test.js | 12 - .../controllers/scopes/scope/projects-test.js | 12 - .../scopes/scope/projects/new-test.js | 12 - .../scopes/scope/projects/project-test.js | 14 - .../projects/project/host-catalogs-test.js | 17 - .../host-catalogs/host-catalog-test.js | 17 - .../host-catalog/host-sets-test.js | 17 - .../host-catalog/host-sets/host-set-test.js | 17 - .../host-sets/host-set/create-host-test.js | 12 - .../host-catalog/host-sets/new-test.js | 17 - .../host-catalogs/host-catalog/hosts-test.js | 17 - .../host-catalog/hosts/host-test.js | 17 - .../host-catalog/hosts/new-test.js | 17 - .../project/host-catalogs/new-test.js | 17 - .../scope/projects/project/sessions-test.js | 12 - .../scope/projects/project/targets-test.js | 16 - .../projects/project/targets/new-test.js | 17 - .../projects/project/targets/target-test.js | 17 - .../targets/target/add-host-sets-test.js | 17 - .../project/targets/target/host-sets-test.js | 17 - .../unit/routes/scopes/scope/orgs-test.js | 11 - .../routes/scopes/scope/orgs/index-test.js | 11 - .../unit/routes/scopes/scope/orgs/new-test.js | 11 - .../unit/routes/scopes/scope/projects-test.js | 11 - .../scopes/scope/projects/index-test.js | 11 - .../routes/scopes/scope/projects/new-test.js | 11 - .../scopes/scope/projects/project-test.js | 11 - .../projects/project/host-catalogs-test.js | 15 - .../host-catalogs/host-catalog-test.js | 16 - .../host-catalog/host-sets-test.js | 16 - .../host-catalog/host-sets/host-set-test.js | 16 - .../host-sets/host-set/add-hosts-test.js | 16 - .../host-sets/host-set/create-host-test.js | 11 - .../host-sets/host-set/hosts-test.js | 16 - .../host-sets/host-set/index-test.js | 16 - .../host-catalog/host-sets/index-test.js | 16 - .../host-catalog/host-sets/new-test.js | 16 - .../host-catalogs/host-catalog/hosts-test.js | 16 - .../host-catalog/hosts/host-test.js | 16 - .../host-catalog/hosts/host/index-test.js | 16 - .../host-catalog/hosts/index-test.js | 16 - .../host-catalog/hosts/new-test.js | 16 - .../host-catalogs/host-catalog/index-test.js | 16 - .../project/host-catalogs/index-test.js | 16 - .../project/host-catalogs/new-test.js | 16 - .../scope/projects/project/index-test.js | 11 - .../scope/projects/project/sessions-test.js | 11 - .../projects/project/sessions/index-test.js | 11 - .../scope/projects/project/targets-test.js | 15 - .../projects/project/targets/index-test.js | 15 - .../projects/project/targets/new-test.js | 15 - .../projects/project/targets/target-test.js | 15 - .../targets/target/add-host-sets-test.js | 16 - .../project/targets/target/host-sets-test.js | 16 - .../targets/target/host-sets/host-set-test.js | 16 - .../project/targets/target/index-test.js | 16 - 203 files changed, 68 insertions(+), 6575 deletions(-) delete mode 100644 ui/core/app/components/form/host-catalog/index.hbs delete mode 100644 ui/core/app/components/form/host-set/add-hosts/index.hbs delete mode 100644 ui/core/app/components/form/host-set/add-hosts/index.js delete mode 100644 ui/core/app/components/form/host-set/create-host/index.hbs delete mode 100644 ui/core/app/components/form/host-set/index.hbs delete mode 100644 ui/core/app/components/form/host/index.hbs delete mode 100644 ui/core/app/components/form/org/index.hbs delete mode 100644 ui/core/app/components/form/project/index.hbs delete mode 100644 ui/core/app/components/form/target/add-host-sets/index.hbs delete mode 100644 ui/core/app/components/form/target/add-host-sets/index.js delete mode 100644 ui/core/app/components/form/target/index.hbs delete mode 100644 ui/core/app/controllers/scopes/scope/orgs.js delete mode 100644 ui/core/app/controllers/scopes/scope/orgs/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/sessions.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/targets.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/targets/new.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/targets/target.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/targets/target/add-host-sets.js delete mode 100644 ui/core/app/controllers/scopes/scope/projects/project/targets/target/host-sets.js delete mode 100644 ui/core/app/routes/scopes/scope/orgs.js delete mode 100644 ui/core/app/routes/scopes/scope/orgs/index.js delete mode 100644 ui/core/app/routes/scopes/scope/orgs/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/sessions.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/sessions/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/new.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/host-set.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/index.js delete mode 100644 ui/core/app/routes/scopes/scope/projects/project/targets/target/index.js delete mode 100644 ui/core/app/templates/scopes/scope/orgs.hbs delete mode 100644 ui/core/app/templates/scopes/scope/orgs/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/orgs/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/-sidebar.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-actions.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-navigation.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-actions.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-navigation.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/sessions.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/new.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/-actions.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/-navigation.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets/-header.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets/host-set.hbs delete mode 100644 ui/core/app/templates/scopes/scope/projects/project/targets/target/index.hbs delete mode 100644 ui/core/tests/acceptance/bread-crumbs-test.js delete mode 100644 ui/core/tests/acceptance/host-catalogs-test.js delete mode 100644 ui/core/tests/acceptance/host-sets-test.js delete mode 100644 ui/core/tests/acceptance/host-sets/hosts-test.js delete mode 100644 ui/core/tests/acceptance/hosts-test.js delete mode 100644 ui/core/tests/acceptance/orgs-test.js delete mode 100644 ui/core/tests/acceptance/projects-test.js delete mode 100644 ui/core/tests/acceptance/sessions-test.js delete mode 100644 ui/core/tests/acceptance/targets-test.js delete mode 100644 ui/core/tests/integration/components/form/host-catalog-test.js delete mode 100644 ui/core/tests/integration/components/form/host-set-test.js delete mode 100644 ui/core/tests/integration/components/form/host-set/add-hosts-test.js delete mode 100644 ui/core/tests/integration/components/form/host-test.js delete mode 100644 ui/core/tests/integration/components/form/org-test.js delete mode 100644 ui/core/tests/integration/components/form/project-test.js delete mode 100644 ui/core/tests/integration/components/form/target-test.js delete mode 100644 ui/core/tests/integration/components/form/target/add-host-sets-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/orgs-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/orgs/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/sessions-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/targets-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/new-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/add-host-sets-test.js delete mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/host-sets-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/orgs-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/orgs/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/orgs/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/sessions-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/sessions/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/index-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/new-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/add-host-sets-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets/host-set-test.js delete mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js diff --git a/ui/core/app/components/form/host-catalog/index.hbs b/ui/core/app/components/form/host-catalog/index.hbs deleted file mode 100644 index 0e024b1fb..000000000 --- a/ui/core/app/components/form/host-catalog/index.hbs +++ /dev/null @@ -1,53 +0,0 @@ - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/host-set/add-hosts/index.hbs b/ui/core/app/components/form/host-set/add-hosts/index.hbs deleted file mode 100644 index 0ff9064ee..000000000 --- a/ui/core/app/components/form/host-set/add-hosts/index.hbs +++ /dev/null @@ -1,56 +0,0 @@ -{{#if this.hasAvailableHosts}} - - - - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - - - - {{#each this.filteredHosts as |host|}} - - - - - {{host.name}} - - {{host.type}} - - - {{/each}} - - - - -{{/if}} - -{{#unless this.hasAvailableHosts}} - - - - {{t "resources.host-set.host.messages.add-none.description"}} - - - - {{t "actions.back"}} - - - -{{/unless}} diff --git a/ui/core/app/components/form/host-set/add-hosts/index.js b/ui/core/app/components/form/host-set/add-hosts/index.js deleted file mode 100644 index 4f1a8eb22..000000000 --- a/ui/core/app/components/form/host-set/add-hosts/index.js +++ /dev/null @@ -1,57 +0,0 @@ -import Component from '@glimmer/component'; -import { computed, action } from '@ember/object'; -import { A } from '@ember/array'; - -export default class FormHostSetAddHostsIndexComponent extends Component { - // =properties - - /** - * Array of selected host IDs. - * @type {EmberArray} - */ - selectedHostIDs = A(); - - /** - * Checks for unassigned hosts. - * @param {[HostModel]} filteredHosts - * @type {boolean} - */ - @computed('filteredHosts.length') - get hasAvailableHosts() { - return this.filteredHosts.length > 0; - } - - /** - * Hosts currently not assigned to current host set. - * @type {[HostModel]} - */ - @computed('args.{model,model.host_ids,hosts}') - get filteredHosts() { - const currentHostIDs = this.args.model.host_ids.map((host) => host.value); - return this.args.hosts.filter(({ id }) => !currentHostIDs.includes(id)); - } - - // =actions - - /** - * Toggle host selection - * @param {HostModel} host - */ - @action - toggleHost(host) { - if (!this.selectedHostIDs.includes(host.id)) { - this.selectedHostIDs.addObject(host.id); - } else { - this.selectedHostIDs.removeObject(host.id); - } - } - - /** - * Callback submit with selected host ids - * @param {requestCallback} fn - */ - @action - submit(fn) { - fn(this.selectedHostIDs); - } -} diff --git a/ui/core/app/components/form/host-set/create-host/index.hbs b/ui/core/app/components/form/host-set/create-host/index.hbs deleted file mode 100644 index e12cabec9..000000000 --- a/ui/core/app/components/form/host-set/create-host/index.hbs +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - {{#if @model.host.errors.name}} - - {{#each @model.host.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.host.errors.description}} - - {{#each @model.host.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.host.errors.name}} - - {{#each @model.host.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/host-set/index.hbs b/ui/core/app/components/form/host-set/index.hbs deleted file mode 100644 index d457ad0e7..000000000 --- a/ui/core/app/components/form/host-set/index.hbs +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/host/index.hbs b/ui/core/app/components/form/host/index.hbs deleted file mode 100644 index b5a931880..000000000 --- a/ui/core/app/components/form/host/index.hbs +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/org/index.hbs b/ui/core/app/components/form/org/index.hbs deleted file mode 100644 index 0e024b1fb..000000000 --- a/ui/core/app/components/form/org/index.hbs +++ /dev/null @@ -1,53 +0,0 @@ - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/project/index.hbs b/ui/core/app/components/form/project/index.hbs deleted file mode 100644 index 0e024b1fb..000000000 --- a/ui/core/app/components/form/project/index.hbs +++ /dev/null @@ -1,53 +0,0 @@ - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/components/form/target/add-host-sets/index.hbs b/ui/core/app/components/form/target/add-host-sets/index.hbs deleted file mode 100644 index 545f45f91..000000000 --- a/ui/core/app/components/form/target/add-host-sets/index.hbs +++ /dev/null @@ -1,60 +0,0 @@ -{{#if this.hasAvailableHostSets}} - - - - - - - - {{t 'form.id.label'}} - {{t 'form.name.label'}} - {{t 'form.type.label'}} - {{t 'resources.host-catalog.title'}} - - - - {{#each this.filteredHostSets as |hostSet|}} - - - - - {{hostSet.name}} - - {{t (concat 'resources.host-set.types.' hostSet.type)}} - - - {{hostSet.host_catalog_id}} - - - {{/each}} - - - - -{{/if}} - -{{#unless this.hasAvailableHostSets}} - - - - {{t "resources.target.host-set.messages.none.description"}} - - - - {{t "actions.back"}} - - - -{{/unless}} diff --git a/ui/core/app/components/form/target/add-host-sets/index.js b/ui/core/app/components/form/target/add-host-sets/index.js deleted file mode 100644 index f49dda570..000000000 --- a/ui/core/app/components/form/target/add-host-sets/index.js +++ /dev/null @@ -1,55 +0,0 @@ -import Component from '@glimmer/component'; -import { computed, action } from '@ember/object'; -import { A } from '@ember/array'; - -export default class FormTargetAddHostSetsComponent extends Component { - // =properties - - /** - * Array of selected host set IDs. - * @type {EmberArray} - */ - selectedHostSetIDs = A(); - - /** - * Checks for unassigned hostsets. - * @param {[HostSetModel]} filteredHostSets - * @type {boolean} - */ - @computed('filteredHostSets.length') - get hasAvailableHostSets() { - return this.filteredHostSets.length > 0; - } - - /** - * Host sets not already added to the target. - * @type {[HostSetModel]} - */ - @computed('args.{hostSets.[],model.host_sets.[]}') - get filteredHostSets() { - // Get IDs for host sets already added to the current target - const alreadyAddedHostSetIDs = this.args.model.host_sets.map( - ({ host_set_id }) => host_set_id - ); - const notAddedHostSets = this.args.hostSets.filter( - ({ id }) => !alreadyAddedHostSetIDs.includes(id) - ); - return notAddedHostSets; - } - - // =actions - - @action - toggleHostSet(hostSet) { - if (!this.selectedHostSetIDs.includes(hostSet.id)) { - this.selectedHostSetIDs.addObject(hostSet.id); - } else { - this.selectedHostSetIDs.removeObject(hostSet.id); - } - } - - @action - submit(fn) { - fn(this.selectedHostSetIDs); - } -} diff --git a/ui/core/app/components/form/target/index.hbs b/ui/core/app/components/form/target/index.hbs deleted file mode 100644 index afbfc76b0..000000000 --- a/ui/core/app/components/form/target/index.hbs +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - {{#if @model.errors.name}} - - {{#each @model.errors.name as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.description}} - - {{#each @model.errors.description as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.session_max_seconds}} - - {{#each @model.errors.session_max_seconds as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - {{#if @model.errors.session_connection_limit}} - - {{#each @model.errors.session_connection_limit as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - {{!-- TODO this is a type-specific field --}} - - {{!-- TODO need to figure out how to reference `attributes.errors` here --}} - {{#if @model.errors.default_port}} - - {{#each @model.errors.default_port as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - - - diff --git a/ui/core/app/controllers/scopes/scope/orgs.js b/ui/core/app/controllers/scopes/scope/orgs.js deleted file mode 100644 index d52189e5f..000000000 --- a/ui/core/app/controllers/scopes/scope/orgs.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeOrgsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.org.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/orgs/new.js b/ui/core/app/controllers/scopes/scope/orgs/new.js deleted file mode 100644 index d41b81a96..000000000 --- a/ui/core/app/controllers/scopes/scope/orgs/new.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeOrgsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects.js b/ui/core/app/controllers/scopes/scope/projects.js deleted file mode 100644 index fb93923df..000000000 --- a/ui/core/app/controllers/scopes/scope/projects.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.project.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/new.js b/ui/core/app/controllers/scopes/scope/projects/new.js deleted file mode 100644 index d1f87399f..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/new.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project.js b/ui/core/app/controllers/scopes/scope/projects/project.js deleted file mode 100644 index 8d1219267..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project.js +++ /dev/null @@ -1,12 +0,0 @@ -import Controller from '@ember/controller'; - -export default class ScopesScopeProjectsProjectController extends Controller { - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.model.displayName; - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs.js deleted file mode 100644 index 5e90268a0..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.host-catalog.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog.js deleted file mode 100644 index 333fbfe1a..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog.js +++ /dev/null @@ -1,12 +0,0 @@ -import Controller from '@ember/controller'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogController extends Controller { - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.model.displayName; - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js deleted file mode 100644 index 2ec9620d3..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Host sets breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.host-set.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js deleted file mode 100644 index 8e59a9fa9..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js +++ /dev/null @@ -1,13 +0,0 @@ -import Controller from '@ember/controller'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetController extends Controller { - // =attributes - - /** - * Host set breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.model.displayName; - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js deleted file mode 100644 index e5ff5fa35..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetCreateHostController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Translated new host set breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.host-set.actions.create-host'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js deleted file mode 100644 index 8a0383067..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Translated new host set breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js deleted file mode 100644 index 589649129..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Hosts breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.host.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js deleted file mode 100644 index fc59d096c..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js +++ /dev/null @@ -1,13 +0,0 @@ -import Controller from '@ember/controller'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsHostController extends Controller { - // =attributes - - /** - * Host breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.model.displayName; - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js deleted file mode 100644 index 420a7f671..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Translated new host breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/new.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/new.js deleted file mode 100644 index 040876e4f..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/new.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectHostCatalogsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Translated new role breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/sessions.js b/ui/core/app/controllers/scopes/scope/projects/project/sessions.js deleted file mode 100644 index 4c49105c6..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/sessions.js +++ /dev/null @@ -1,19 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectSessionsController extends Controller { - - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.session.title_plural'); - } - -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/targets.js b/ui/core/app/controllers/scopes/scope/projects/project/targets.js deleted file mode 100644 index 9c51e3de1..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/targets.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectTargetsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Targets breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.target.title_plural'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/targets/new.js b/ui/core/app/controllers/scopes/scope/projects/project/targets/new.js deleted file mode 100644 index 588dca4b6..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/targets/new.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectTargetsNewController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Translated new target breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('titles.new'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/targets/target.js b/ui/core/app/controllers/scopes/scope/projects/project/targets/target.js deleted file mode 100644 index 4cad64e2b..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/targets/target.js +++ /dev/null @@ -1,13 +0,0 @@ -import Controller from '@ember/controller'; - -export default class ScopesScopeProjectsProjectTargetsTargetController extends Controller { - // =attributes - - /** - * A target breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.model.displayName; - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/targets/target/add-host-sets.js b/ui/core/app/controllers/scopes/scope/projects/project/targets/target/add-host-sets.js deleted file mode 100644 index 8a4cb606e..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/targets/target/add-host-sets.js +++ /dev/null @@ -1,17 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectTargetsTargetAddHostSetsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.target.actions.add-host-sets'); - } -} diff --git a/ui/core/app/controllers/scopes/scope/projects/project/targets/target/host-sets.js b/ui/core/app/controllers/scopes/scope/projects/project/targets/target/host-sets.js deleted file mode 100644 index 92a90208b..000000000 --- a/ui/core/app/controllers/scopes/scope/projects/project/targets/target/host-sets.js +++ /dev/null @@ -1,18 +0,0 @@ -import Controller from '@ember/controller'; -import { inject as service } from '@ember/service'; - -export default class ScopesScopeProjectsProjectTargetsTargetHostSetsController extends Controller { - // =services - - @service intl; - - // =attributes - - /** - * Host sets breadcrumb - * @type {string} - */ - get breadCrumb() { - return this.intl.t('resources.host-set.title_plural'); - } -} diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 192b9d8c5..88358232c 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -17,47 +17,6 @@ Router.map(function () { this.route('new'); }); - this.route('projects', function () { - this.route('project', { path: ':project_id' }, function () { - this.route('host-catalogs', function () { - this.route('new'); - this.route( - 'host-catalog', - { path: ':host_catalog_id' }, - function () { - this.route('host-sets', function () { - this.route('host-set', { path: ':host_set_id' }, function () { - this.route('hosts'); - this.route('add-hosts'); - this.route('create-host'); - }); - this.route('new'); - }); - this.route('hosts', function () { - this.route('host', { path: ':host_id' }, function () {}); - this.route('new'); - }); - } - ); - }); - this.route('targets', function () { - this.route('target', { path: ':target_id' }, function () { - this.route('host-sets', function () { - this.route( - 'host-set', - { path: ':host_set_id' }, - function () {} - ); - }); - this.route('add-host-sets'); - }); - this.route('new'); - }); - this.route('sessions', function() {}); - }); - this.route('new'); - }); - this.route('users', function () { this.route('user', { path: ':user_id' }, function () { this.route('accounts'); diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 4351e112d..179fbc865 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -76,18 +76,11 @@ export default class ScopesScopeRoute extends Route { * @param {object} controller * @param {object} model */ - renderTemplate(controller, model) { + renderTemplate() { super.renderTemplate(...arguments); - this.render('scopes/scope/-header-nav', { into: 'application', outlet: 'header-nav', }); - - this.render('scopes/scope/-sidebar', { - into: 'scopes/scope', - outlet: 'sidebar', - model: model, - }); } } diff --git a/ui/core/app/routes/scopes/scope/authenticate.js b/ui/core/app/routes/scopes/scope/authenticate.js index 883bbb704..53bafba60 100644 --- a/ui/core/app/routes/scopes/scope/authenticate.js +++ b/ui/core/app/routes/scopes/scope/authenticate.js @@ -10,14 +10,7 @@ export default class ScopesScopeAuthenticateRoute extends Route { // =methods beforeModel() { - if (this.session.isAuthenticated) { - const scope = this.modelFor('scopes.scope'); - if (scope.isGlobal) { - this.transitionTo('scopes.scope.orgs'); - } else { - this.transitionTo('scopes.scope.projects'); - } - } + if (this.session.isAuthenticated) this.transitionTo('scopes.scope.index'); } /** diff --git a/ui/core/app/routes/scopes/scope/index.js b/ui/core/app/routes/scopes/scope/index.js index 36261b82d..796253603 100644 --- a/ui/core/app/routes/scopes/scope/index.js +++ b/ui/core/app/routes/scopes/scope/index.js @@ -1,12 +1,19 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default class ScopesScopeIndexRoute extends Route { + // =services + + @service session; + // =methods /** * Redirects to scopes/scope/authenticate for further processing. */ redirect() { - this.transitionTo('scopes.scope.authenticate'); + if (!this.session.isAuthenticated) { + this.transitionTo('scopes.scope.authenticate'); + } } } diff --git a/ui/core/app/routes/scopes/scope/orgs.js b/ui/core/app/routes/scopes/scope/orgs.js deleted file mode 100644 index 5aad80343..000000000 --- a/ui/core/app/routes/scopes/scope/orgs.js +++ /dev/null @@ -1,60 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { notifySuccess, notifyError } from '../../../decorators/notify'; - -export default class ScopesScopeOrgsRoute extends Route { - // =services - - @service intl; - @service notify; - @service session; - - // =methods - - /** - * If arriving here unauthenticated or from a non-global scope, - * redirect to index for further processing. - */ - beforeModel() { - if (!this.session.isAuthenticated) this.transitionTo('index'); - const scope = this.modelFor('scopes.scope'); - if(!scope.isGlobal) this.transitionTo('index'); - } - - /** - * Loads all scopes under the global scope. - * @return {Promise{[ScopeModel]}} - */ - async model() { - return this.store.query('scope', { scope_id: 'global' }); - } - - // =actions - - /** - * Rollback changes on org. - * @param {ScopeModel} org - */ - @action - cancel(org) { - org.rollbackAttributes(); - this.transitionTo('scopes.scope.orgs'); - } - - /** - * Handle save org. - * @param {ScopeModel} org - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.create-success') - async save(org) { - await org.save(); - await this.transitionTo('scopes.scope.projects', org); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/orgs/index.js b/ui/core/app/routes/scopes/scope/orgs/index.js deleted file mode 100644 index e41a21c19..000000000 --- a/ui/core/app/routes/scopes/scope/orgs/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeOrgsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/orgs/new.js b/ui/core/app/routes/scopes/scope/orgs/new.js deleted file mode 100644 index a8819e58c..000000000 --- a/ui/core/app/routes/scopes/scope/orgs/new.js +++ /dev/null @@ -1,16 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeOrgsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved org scope belonging to the global scope. - * @return {ScopeModel} - */ - model() { - return this.store.createRecord('scope', { - type: 'org', - scopeID: 'global', - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects.js b/ui/core/app/routes/scopes/scope/projects.js deleted file mode 100644 index 7a43e0e71..000000000 --- a/ui/core/app/routes/scopes/scope/projects.js +++ /dev/null @@ -1,90 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../decorators/notify'; - -export default class ScopesScopeProjectsRoute extends Route { - // =services - - @service intl; - @service notify; - @service session; - @service confirm; - - // =methods - - /** - * If arriving here unauthenticated, redirect to index for further processing. - */ - beforeModel() { - if (!this.session.isAuthenticated) this.transitionTo('index'); - } - - /** - * Loads all scopes under the current scope. - * @return {Promise{[ScopeModel]}} - */ - async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('scope', { scope_id }); - } - - /** - * If arriving here within a verifiable project scope, redirect to its - * parent, which is necessarily an org, in order to list projects. - * - * TODO: this conditional redirect based on the scope type is probably - * necessary for many routes directly under scope, so we may want - * to move this into a mixin. - * @param {ScopeModel} - */ - redirect() { - const { isProject, scopeID } = this.modelFor('scopes.scope'); - if (isProject) this.transitionTo('scopes.scope.projects', scopeID); - } - - // =actions - - /** - * Rollback changes on project. - * @param {ProjectModel} project - */ - @action - cancel(project) { - const { isNew } = project; - project.rollbackAttributes(); - if (isNew) this.transitionTo('scopes.scope.projects'); - } - - /** - * Handle save project. - * @param {ProjectModel} project - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') - async save(project) { - await project.save(); - await this.transitionTo('scopes.scope.projects.project', project); - this.refresh(); - } - - /** - * Deletes the project and redirects to index. - * @param {ProjectModel} project - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async delete(project) { - await project.destroyRecord(); - await this.replaceWith('scopes.scope.projects'); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/index.js b/ui/core/app/routes/scopes/scope/projects/index.js deleted file mode 100644 index d763c183c..000000000 --- a/ui/core/app/routes/scopes/scope/projects/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/new.js b/ui/core/app/routes/scopes/scope/projects/new.js deleted file mode 100644 index 207ca3dbc..000000000 --- a/ui/core/app/routes/scopes/scope/projects/new.js +++ /dev/null @@ -1,17 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved project scope belonging to the current org scope. - * @return {ScopeModel} - */ - model() { - const { id } = this.modelFor('scopes.scope'); - return this.store.createRecord('scope', { - type: 'project', - scopeID: id, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project.js b/ui/core/app/routes/scopes/scope/projects/project.js deleted file mode 100644 index 0f3e7dbdb..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project.js +++ /dev/null @@ -1,31 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectRoute extends Route { - // =methods - - /** - * Loads a scope by ID (ostensibly a project scope). - * @param {object} params - * @param {string} params.project_id - * @return {ScopeModel} - */ - model({ project_id }) { - return this.store.findRecord('scope', project_id); - } - - /** - * Renders the project-specific sidebar template. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render('scopes/scope/projects/project/-sidebar', { - into: 'scopes/scope', - outlet: 'sidebar', - model: model, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs.js deleted file mode 100644 index ab01b5b7e..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs.js +++ /dev/null @@ -1,70 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all host catalogs under the current scope. - * @return {Promise{[HostCatalogModel]}} - */ - async model() { - const { id: scope_id } = this.modelFor('scopes.scope.projects.project'); - return this.store.query('host-catalog', { scope_id }); - } - - // =actions - - /** - * Rollback changes on project. - * @param {HostCatalogModel} hostCatalog - */ - @action - cancel(hostCatalog) { - const { isNew } = hostCatalog; - hostCatalog.rollbackAttributes(); - if (isNew) this.transitionTo('scopes.scope.projects.project.host-catalogs'); - } - - /** - * Handle save. - * @param {HostCatalogModel} hostCatalog - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') - async save(hostCatalog) { - await hostCatalog.save(); - await this.transitionTo( - 'scopes.scope.projects.project.host-catalogs.host-catalog', - hostCatalog - ); - this.refresh(); - } - - /** - * Deletes the host catalog and redirects to index. - * @param {HostCatalogModel} hostCatalog - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async delete(hostCatalog) { - await hostCatalog.destroyRecord(); - await this.replaceWith('scopes.scope.projects.project.host-catalogs'); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog.js deleted file mode 100644 index 71fbe290b..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog.js +++ /dev/null @@ -1,52 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogRoute extends Route { - // =methods - - /** - * Load a host catalog. - * @param {object} params - * @param {string} params.host_catalog_id - * @return {HostCatalogModel} - */ - async model({ host_catalog_id }) { - return this.store.findRecord('host-catalog', host_catalog_id); - } - - /** - * Renders the host-catalog specific templates for header, navigation, and actions page sections. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/-navigation', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/-actions', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - model: model, - } - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js deleted file mode 100644 index 380250c3e..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js +++ /dev/null @@ -1,76 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all host-sets under the current host catalog and it's parent scope. - * @return {Promise{[HostSetModel]}} - */ - model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - return this.store.query('host-set', { host_catalog_id }); - } - - // =actions - - /** - * Rollback changes on a host set. - * @param {HostSetModel} hostSet - */ - @action - cancel(hostSet) { - const { isNew } = hostSet; - hostSet.rollbackAttributes(); - if (isNew) - this.transitionTo( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets' - ); - } - - /** - * Handle save of a host set. - * @param {HostSetModel} hostSet - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') - async save(hostSet) { - await hostSet.save(); - await this.transitionTo( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set', - hostSet - ); - this.refresh(); - } - - /** - * Delete host set in current scope and redirect to index. - * @param {HostSetModel} hostSet - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async deleteHostSet(hostSet) { - await hostSet.destroyRecord(); - await this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets' - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js deleted file mode 100644 index 4d88c52b1..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.js +++ /dev/null @@ -1,52 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetRoute extends Route { - // =methods - - /** - * Load a host-set using current host-catalog and it's parent project scope. - * @param {object} params - * @param {string} params.host_set_id - * @return {HostSetModel} - */ - async model({ host_set_id }) { - return this.store.findRecord('host-set', host_set_id, { reload: true }); - } - - /** - * Renders the host-set specific templates for header, navigation, and action page sections. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-navigation', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - model: model, - } - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js deleted file mode 100644 index 3b398fcec..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js +++ /dev/null @@ -1,92 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { hash } from 'rsvp'; -import loading from 'ember-loading/decorator'; -import { notifySuccess, notifyError } from '../../../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetAddHostsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Empty out any previously loaded hosts. - */ - beforeModel() { - this.store.unloadAll('host'); - } - - /** - * Loads current host set and all hosts under the current host catalog. - * @return {Promise{HostSetModel,[HostModel]}} - */ - async model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - return hash({ - hostSet: this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set' - ), - hosts: this.store.query('host', { host_catalog_id }), - }); - } - - /** - * Renders the add-hosts-specific header template. - * Empties the actions and navigation outlets and renders a custom empty header. - * @override - */ - renderTemplate() { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - } - ); - - this.render('-empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - }); - - this.render('-empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - }); - } - - // =actions - - /** - * Saves host IDs on the host set. - * @param {HostSetModel} hostSet - */ - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async addHosts(hostSet, hostIDs) { - await hostSet.addHosts(hostIDs); - await this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' - ); - } - - /** - * Redirect to hosts as if nothing ever happened. - */ - @action - cancel() { - this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js deleted file mode 100644 index 05aa6ed6f..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js +++ /dev/null @@ -1,90 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { hash } from 'rsvp'; -import loading from 'ember-loading/decorator'; -import { notifySuccess, notifyError } from '../../../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetCreateHostRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Creates a new unsaved host in current host catalog scope. - * @return {Promise{HostSetModel,HostModel}} - */ - async model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - - return hash({ - hostSet: this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set' - ), - host: this.store.createRecord('host', { - type: 'static', - host_catalog_id, - }), - }); - } - - /** - * Renders the create-host-specific header template. - * Empties the actions and navigation outlets and renders a custom empty header. - * @override - */ - renderTemplate() { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - } - ); - - this.render('-empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - }); - - this.render('-empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - }); - } - - // =actions - - /** - * Saves host and add it to current host set. - * @param {HostSetModel,HostModel} model - */ - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async save(model) { - await model.host.save(); - await model.hostSet.addHost(model.host.id); - await this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' - ); - } - - /** - * Redirect to hosts in host set as if nothing ever happened. - */ - @action - cancel() { - this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.js deleted file mode 100644 index 8b4a5514d..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.js +++ /dev/null @@ -1,55 +0,0 @@ -import Route from '@ember/routing/route'; -import { hash, all } from 'rsvp'; -import { action } from '@ember/object'; -import { inject as service } from '@ember/service'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetHostsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all hosts under the current host set. - * @return {Promise{HostSetModel,[HostModel]}} - */ - async model() { - const hostSet = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set' - ); - return hash({ - hostSet, - hosts: all( - hostSet.host_ids.map((host) => - this.store.findRecord('host', host.value, { reload: true }) - ) - ), - }); - } - - /** - * Remove a host from the current host set and redirect to hosts index. - * @param {HostSetModel} hostSet - * @param {HostModel} host - */ - @action - @loading - @confirm('questions.remove-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.remove-success') - async removeHost(hostSet, host) { - const scopeID = this.modelFor('scopes.scope.projects.project').id; - const hostCatalogID = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ).id; - await hostSet.removeHost(host.id, { - adapterOptions: { scopeID, hostCatalogID }, - }); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.js deleted file mode 100644 index 0f73c321d..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.js deleted file mode 100644 index 8243577dc..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js deleted file mode 100644 index 44a134995..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js +++ /dev/null @@ -1,50 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved host set in current host catalog scope. - * @return {HostSetModel} - */ - model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - return this.store.createRecord('host-set', { - type: 'static', - host_catalog_id, - }); - } - - /** - * Renders new host-set specific templates for header, navigation, and action page sections. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - model: model, - } - ); - - this.render('_empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - model: model, - }); - - this.render('_empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - model: model, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js deleted file mode 100644 index 9b9732e2a..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js +++ /dev/null @@ -1,77 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all hosts under the current host catalog and it's parent project scope. - * @return {Promise{[HostModel]}} - */ - model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - return this.store.query('host', { host_catalog_id }); - } - - // =actions - - /** - * Rollback changes on a host. - * @param {HostModel} host - */ - @action - cancel(host) { - const { isNew } = host; - host.rollbackAttributes(); - if (isNew) - this.transitionTo( - 'scopes.scope.projects.project.host-catalogs.host-catalog.hosts' - ); - } - - /** - * Handle save of a host. - * @param {HostModel} host - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') - async save(host) { - await host.save(); - await this.transitionTo( - 'scopes.scope.projects.project.host-catalogs.host-catalog.hosts.host', - host - ); - this.refresh(); - } - - /** - * Delete host in current scope and redirect to index. - * @param {HostModel} host - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async deleteHost(host) { - await host.destroyRecord(); - await this.replaceWith( - 'scopes.scope.projects.project.host-catalogs.host-catalog.hosts' - ); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js deleted file mode 100644 index da1ca0685..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js +++ /dev/null @@ -1,52 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsHostRoute extends Route { - // =methods - - /** - * Load a host using current host-catalog and it's parent project scope. - * @param {object} params - * @param {string} params.host_id - * @return {HostModel} - */ - async model({ host_id }) { - return this.store.findRecord('host', host_id, { reload: true }); - } - - /** - * Renders the host specific templates for header, navigation, and action page sections. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-navigation', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - model: model, - } - ); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-actions', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - model: model, - } - ); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.js deleted file mode 100644 index 14e5c2210..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsHostIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.js deleted file mode 100644 index d6847d0b1..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js deleted file mode 100644 index 6ea7a3f7b..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js +++ /dev/null @@ -1,50 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved host in current host catalog scope. - * @return {HostModel} - */ - model() { - const { id: host_catalog_id } = this.modelFor( - 'scopes.scope.projects.project.host-catalogs.host-catalog' - ); - return this.store.createRecord('host', { - type: 'static', - host_catalog_id, - }); - } - - /** - * Renders new host specific templates for header, navigation, and action page sections. - * @override - * @param {object} controller - * @param {object} model - */ - renderTemplate(controller, model) { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new/-header', - { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'header', - model: model, - } - ); - - this.render('_empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'navigation', - model: model, - }); - - this.render('_empty', { - into: 'scopes/scope/projects/project/host-catalogs/host-catalog', - outlet: 'actions', - model: model, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index.js deleted file mode 100644 index 88bc29fe9..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/index.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/index.js deleted file mode 100644 index be34e9260..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/new.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/new.js deleted file mode 100644 index 58e326cb8..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/new.js +++ /dev/null @@ -1,17 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectHostCatalogsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved host catalog belonging to the current project scope. - * @return {HostCatalogModel} - */ - model() { - const scopeModel = this.modelFor('scopes.scope.projects.project'); - return this.store.createRecord('host-catalog', { - type: 'static', - scopeModel, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/index.js b/ui/core/app/routes/scopes/scope/projects/project/index.js deleted file mode 100644 index a004bac08..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/sessions.js b/ui/core/app/routes/scopes/scope/projects/project/sessions.js deleted file mode 100644 index 3e01b9f44..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/sessions.js +++ /dev/null @@ -1,103 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { all, hash } from 'rsvp'; -import { task, timeout } from 'ember-concurrency'; -import { A } from '@ember/array'; -import { notifySuccess, notifyError } from '../../../../../decorators/notify'; -import config from '../../../../../config/environment'; - -const POLL_TIMEOUT_SECONDS = config.sessionPollingTimeoutSeconds; - -export default class ScopesScopeProjectsProjectSessionsRoute extends Route { - - // =services - - @service intl; - @service notify; - - // =attributes - - /** - * A simple Ember Concurrency-based polling task that refreshes the route - * every POLL_TIMEOUT_SECONDS seconds. This is necessary to display changes - * to session `status` that may occur. - * - * NOTE: tasks are sort of attributes and sort of methods, but they are not - * language-level constructs. Thus we annotate this task as if it - * is an attribute. - * @type {Task} - */ - @task(function * () { - while(true) { - yield timeout(POLL_TIMEOUT_SECONDS * 1000); - yield this.refresh(); - } - }).drop() poller; - - // =methods - - /** - * Loads all sessions under the current scope and encapsulates them into - * an array of objects containing their associated users and targets. - * @return {Promise{[{session: SessionModel, user: UserModel, target: TargetModel}]}} - */ - async model() { - const { id: scope_id } = this.modelFor('scopes.scope.projects.project'); - const sessions = await this.store.query('session', { scope_id }); - const sessionAggregates = await all( - sessions.map(session => hash({ - session, - user: session.user_id - ? ( - this.store.peekRecord('user', session.user_id) || - this.store.findRecord('user', session.user_id) - ) - : null, - target: session.target_id - ? ( - this.store.peekRecord('target', session.target_id) || - this.store.findRecord('target', session.target_id) - ) - : null, - })) - ); - // Sort sessions by time created... - let sortedSessionAggregates = - A(sessionAggregates).sortBy('session.created_time').reverse(); - // Then move active sessions to the top... - sortedSessionAggregates = [ - ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status === 'active'), - ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status !== 'active'), - ]; - return sortedSessionAggregates; - } - - /** - * When this route is activated (entered), begin polling for changes. - */ - activate() { - this.poller.perform(); - } - - /** - * When this route is deactivated (exited), stop polling for changes. - */ - deactivate() { - this.poller.cancelAll(); - } - - // =actions - - /** - * Cancels the specified session and notifies user of success or error. - * @param {SessionModel} - */ - @action - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.canceled-success') - async cancelSession(session) { - await session.cancelSession(); - } - -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/sessions/index.js b/ui/core/app/routes/scopes/scope/projects/project/sessions/index.js deleted file mode 100644 index a8ae56692..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/sessions/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectSessionsIndexRoute extends Route { -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets.js b/ui/core/app/routes/scopes/scope/projects/project/targets.js deleted file mode 100644 index 68e0b98d0..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets.js +++ /dev/null @@ -1,67 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectTargetsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all targets under current project scope. - * @return {Promise{[TargetModel]}} - */ - async model() { - const { id: scope_id } = this.modelFor('scopes.scope.projects.project'); - return this.store.query('target', { scope_id }); - } - - // =actions - - /** - * Rollback changes on a target. - * @param {TargetModel} target - */ - @action - cancel(target) { - const { isNew } = target; - target.rollbackAttributes(); - if (isNew) this.transitionTo('scopes.scope.projects.project.targets'); - } - - /** - * Handle save. - * @param {TargetModel} target - * @param {Event} e - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') - async save(target) { - await target.save(); - await this.transitionTo('scopes.scope.projects.project.targets.target', target); - this.refresh(); - } - - /** - * Deletes a target and redirects to targets index. - * @param {TargetModel} target - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async delete(target) { - await target.destroyRecord(); - await this.replaceWith('scopes.scope.projects.project.targets'); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/index.js b/ui/core/app/routes/scopes/scope/projects/project/targets/index.js deleted file mode 100644 index 903db12df..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/new.js b/ui/core/app/routes/scopes/scope/projects/project/targets/new.js deleted file mode 100644 index d6cbcaf99..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/new.js +++ /dev/null @@ -1,17 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsNewRoute extends Route { - // =methods - - /** - * Creates a new unsaved target in current project scope. - * @return {TargetModel} - */ - model() { - const scopeModel = this.modelFor('scopes.scope.projects.project'); - return this.store.createRecord('target', { - type: 'tcp', - scopeModel, - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target.js deleted file mode 100644 index 83bd76120..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target.js +++ /dev/null @@ -1,39 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsTargetRoute extends Route { - // =methods - - /** - * Load a target. - * @param {object} params - * @param {string} params.target_id - * @return {TargetModel} - */ - async model({ target_id }) { - return this.store.findRecord('target', target_id, { reload: true }); - } - - /** - * Renders the target-specific templates for header, navigation, - * and actions page sections. - * @override - */ - renderTemplate() { - super.renderTemplate(...arguments); - - this.render('scopes/scope/projects/project/targets/target/-header', { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'header', - }); - - this.render('scopes/scope/projects/project/targets/target/-navigation', { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'navigation', - }); - - this.render('scopes/scope/projects/project/targets/target/-actions', { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'actions', - }); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js deleted file mode 100644 index b747fda00..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js +++ /dev/null @@ -1,92 +0,0 @@ -import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { all } from 'rsvp'; -import loading from 'ember-loading/decorator'; -import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectTargetsTargetAddHostSetsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Empty out any previously loaded host sets. - */ - beforeModel() { - this.store.unloadAll('host-set'); - } - - /** - * Returns the current target, all host catalogs, and all host sets. - * @return {{target: TargetModel, hostCatalogs: [HostCatalogModel], hostSets: [HostSetModel]}} - */ - async model() { - const target = this.modelFor( - 'scopes.scope.projects.project.targets.target' - ); - const { id: scope_id } = this.modelFor('scopes.scope.projects.project'); - const hostCatalogs = await this.store.query('host-catalog', { scope_id }); - await all( - hostCatalogs.map(({ id: host_catalog_id }) => - this.store.query('host-set', { host_catalog_id }) - ) - ); - const hostSets = this.store.peekAll('host-set'); - return { - target, - hostCatalogs, - hostSets, - }; - } - - /** - * Renders the add-host-sets-specific header template. - * @override - */ - renderTemplate() { - super.renderTemplate(...arguments); - - this.render( - 'scopes/scope/projects/project/targets/target/add-host-sets/-header', - { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'header', - } - ); - - this.render('-empty', { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'navigation', - }); - - this.render('-empty', { - into: 'scopes/scope/projects/project/targets/target', - outlet: 'actions', - }); - } - - // =actions - - @action - @loading - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.add-success') - async save(target, hostSetIDs) { - await target.addHostSets(hostSetIDs); - this.replaceWith( - 'scopes.scope.projects.project.targets.target.host-sets' - ); - } - - /** - * Redirect to target host sets as if nothing ever happened. - */ - @action - cancel() { - this.replaceWith('scopes.scope.projects.project.targets.target.host-sets'); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets.js deleted file mode 100644 index 08d839f1f..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets.js +++ /dev/null @@ -1,67 +0,0 @@ -import Route from '@ember/routing/route'; -import { all, hash } from 'rsvp'; -import { action } from '@ember/object'; -import { inject as service } from '@ember/service'; -import loading from 'ember-loading/decorator'; -import { confirm } from '../../../../../../../decorators/confirm'; -import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; - -export default class ScopesScopeProjectsProjectTargetsTargetHostSetsRoute extends Route { - // =services - - @service intl; - @service notify; - - // =methods - - /** - * Loads all host-sets and associated host-catalogs under the current target - * and it's parent scope. - * @return {Promise{[HostSetModel, HostCatalogModel]}} - */ - beforeModel() { - const { scopeID, host_sets } = this.modelFor( - 'scopes.scope.projects.project.targets.target' - ); - const promises = host_sets.map( - ({ host_set_id, host_catalog_id: hostCatalogID }) => - hash({ - // TODO: multiple host sets may belong to the same catalog, - // resulting in the catalog being loaded multiple times. - // An improvement would be to find the unique set of catalogs first. - hostCatalog: this.store.findRecord('host-catalog', hostCatalogID, { - adapterOptions: { scopeID }, - }), - hostSet: this.store.findRecord('host-set', host_set_id, { - adapterOptions: { scopeID, hostCatalogID }, - }), - }) - ); - return all(promises); - } - - /** - * Returns the previously loaded target instance. - * @return {TargetModel} - */ - model() { - return this.modelFor('scopes.scope.projects.project.targets.target'); - } - - // =actions - - /** - * Removes a host set from the current target and redirects to index. - * @param {TargetModel} target - * @param {HostSetModel} hostSet - */ - @action - @loading - @confirm('questions.remove-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.remove-success') - async removeHostSet(target, hostSet) { - await target.removeHostSet(hostSet.id); - this.refresh(); - } -} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/host-set.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/host-set.js deleted file mode 100644 index e7843fca7..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/host-set.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsTargetHostSetsHostSetRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/index.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/index.js deleted file mode 100644 index 80a35e875..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/host-sets/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsTargetHostSetsIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/index.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/index.js deleted file mode 100644 index 3eb6dfa5f..000000000 --- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeProjectsProjectTargetsTargetIndexRoute extends Route {} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index 75c531af1..ec91c3722 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -5,7 +5,7 @@ {{#if @model.isGlobal}} - + @@ -16,7 +16,7 @@ {{#if @model.isOrg}} - + @@ -25,7 +25,51 @@ {{/if}} - {{outlet "sidebar"}} + {{#unless @model.isProject}} + + + + {{t "resources.user.title_plural"}} + + + + {{t "resources.group.title_plural"}} + + + + {{t "resources.role.title_plural"}} + + + + {{t "resources.auth-method.title_plural"}} + + + {{/unless}} + + {{#if @model.isProject}} + + + + {{t "resources.group.title_plural"}} + + + + {{t "resources.role.title_plural"}} + + + {{/if}} {{/if}} diff --git a/ui/core/app/templates/scopes/scope/orgs.hbs b/ui/core/app/templates/scopes/scope/orgs.hbs deleted file mode 100644 index 0f9dd522a..000000000 --- a/ui/core/app/templates/scopes/scope/orgs.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.org.title_plural")}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/orgs/index.hbs b/ui/core/app/templates/scopes/scope/orgs/index.hbs deleted file mode 100644 index 7218551bb..000000000 --- a/ui/core/app/templates/scopes/scope/orgs/index.hbs +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - -

- {{t "resources.org.title_plural"}} - -

- {{#if @model}} -

{{t "resources.org.description"}}

- {{/if}} -
- - - {{#if @model}} - - {{t 'titles.new'}} - - {{/if}} - - - - - {{#if @model}} - - - {{#each @model as |org|}} - - {{/each}} - - - {{else}} - - - - - {{t 'resources.org.description'}} - - - - {{t 'titles.new'}} - - - - - {{/if}} - - - -
diff --git a/ui/core/app/templates/scopes/scope/orgs/new.hbs b/ui/core/app/templates/scopes/scope/orgs/new.hbs deleted file mode 100644 index 390f0f04b..000000000 --- a/ui/core/app/templates/scopes/scope/orgs/new.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{{title (t 'titles.new')}} - - - - - - - - -

- {{t "titles.new"}} - -

-
- - - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects.hbs b/ui/core/app/templates/scopes/scope/projects.hbs deleted file mode 100644 index dd40ba6c8..000000000 --- a/ui/core/app/templates/scopes/scope/projects.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.project.title_plural")}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/index.hbs b/ui/core/app/templates/scopes/scope/projects/index.hbs deleted file mode 100644 index 2c220f15b..000000000 --- a/ui/core/app/templates/scopes/scope/projects/index.hbs +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - -

- {{t "resources.project.title_plural"}} - -

- {{#if @model}} -

{{t "resources.project.description"}}

- {{/if}} -
- - - {{#if @model}} - - {{t 'titles.new'}} - - {{/if}} - - - - - {{#if @model}} - - - {{#each @model as |project|}} - - {{/each}} - - - {{else}} - - - - - {{t 'resources.project.description'}} - - - - {{t 'titles.new'}} - - - - - {{/if}} - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/new.hbs b/ui/core/app/templates/scopes/scope/projects/new.hbs deleted file mode 100644 index 0e9dedf59..000000000 --- a/ui/core/app/templates/scopes/scope/projects/new.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{{title (t 'titles.new')}} - - - - - - - - -

- {{t "titles.new"}} - -

-
- - - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/project.hbs b/ui/core/app/templates/scopes/scope/projects/project.hbs deleted file mode 100644 index d66e83390..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title @model.displayName}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/-sidebar.hbs b/ui/core/app/templates/scopes/scope/projects/project/-sidebar.hbs deleted file mode 100644 index e82349443..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/-sidebar.hbs +++ /dev/null @@ -1,20 +0,0 @@ - - - - {{t "resources.session.title_plural"}} - - - - {{t "resources.target.title_plural"}} - - - - {{t "resources.host-catalog.title_plural"}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs.hbs deleted file mode 100644 index abbb6702e..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.host-catalog.title_plural")}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs deleted file mode 100644 index 271a98d73..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs +++ /dev/null @@ -1,25 +0,0 @@ -{{title @model.displayName}} - - - - - - - - - {{outlet "header"}} - - - - {{outlet "actions"}} - - - - {{outlet "navigation"}} - - - - {{outlet}} - - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-actions.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-actions.hbs deleted file mode 100644 index 96af1687a..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-actions.hbs +++ /dev/null @@ -1,22 +0,0 @@ - - - {{t "resources.host.actions.create"}} - - - {{t "resources.host-set.actions.create"}} - - - - {{t "resources.host-catalog.actions.delete"}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs deleted file mode 100644 index 58e6f4b02..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs +++ /dev/null @@ -1,12 +0,0 @@ -

- {{t "resources.host-catalog.title"}} - -

-

{{t "resources.host-catalog.description"}}

- - {{@model.id}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-navigation.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-navigation.hbs deleted file mode 100644 index 5be44792b..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-navigation.hbs +++ /dev/null @@ -1,11 +0,0 @@ - - - {{t 'titles.details'}} - - - {{t 'resources.host-set.title_plural'}} - - - {{t 'resources.host.title_plural'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs deleted file mode 100644 index 37ecd2d33..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.host-set.title_plural")}} - -{{outlet}} \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.hbs deleted file mode 100644 index d66e83390..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title @model.displayName}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs deleted file mode 100644 index 2eb61121a..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs +++ /dev/null @@ -1,16 +0,0 @@ - - - {{t 'resources.host-set.actions.create-host'}} - - - {{t 'resources.host-set.actions.add-hosts'}} - - - - {{t 'resources.host-set.actions.delete'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-header.hbs deleted file mode 100644 index a101b0a8a..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-header.hbs +++ /dev/null @@ -1,12 +0,0 @@ -

- {{t "resources.host-set.title"}} - -

-

{{t "resources.host-set.description"}}

- - {{@model.id}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs deleted file mode 100644 index 93590ba90..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs +++ /dev/null @@ -1,8 +0,0 @@ - - - {{t 'titles.details'}} - - - {{t 'resources.host.title_plural'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs deleted file mode 100644 index b185f9550..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs +++ /dev/null @@ -1,8 +0,0 @@ -{{title (t "resources.host-set.actions.add-hosts")}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs deleted file mode 100644 index 6ff650141..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs +++ /dev/null @@ -1,5 +0,0 @@ -

- {{t "resources.host-set.host.messages.add.title"}} - -

-

{{t "resources.host-set.host.messages.add.description"}}

diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs deleted file mode 100644 index 455daa19b..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs +++ /dev/null @@ -1,7 +0,0 @@ -{{title (t 'resources.host-set.actions.create-host')}} - - \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs deleted file mode 100644 index c8ea81660..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs +++ /dev/null @@ -1,4 +0,0 @@ -

- {{t "resources.host-set.actions.create-host"}} - -

diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs deleted file mode 100644 index 50b35d364..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ /dev/null @@ -1,71 +0,0 @@ -{{#if @model.hosts}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - {{t "titles.actions"}} - - - - {{#each @model.hosts as |host|}} - - - - {{host.displayName}} - -

{{host.description}}

-
- - {{host.type}} - - - - {{host.id}} - - - - - - {{t "actions.remove"}} - - - -
- {{/each}} -
-
- -{{/if}} - -{{#unless @model.hosts}} - - - - {{t "resources.host-set.host.messages.none.description"}} - - - - {{t "resources.host-set.actions.create-host"}} - - - -{{/unless}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.hbs deleted file mode 100644 index ac0b64897..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index.hbs +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs deleted file mode 100644 index bb5f4c14c..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs +++ /dev/null @@ -1,56 +0,0 @@ -{{#if @model}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - - - - {{#each @model as |hostSet|}} - - - - {{hostSet.displayName}} - -

{{hostSet.description}}

-
- - - {{t (concat 'resources.host-set.types.' hostSet.type)}} - - - - - {{hostSet.id}} - - -
- {{/each}} -
-
- -{{else}} - - - - - {{t "resources.host-set.description"}} - - - - {{t "titles.new"}} - - - - -{{/if}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.hbs deleted file mode 100644 index 1d5d73000..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.hbs +++ /dev/null @@ -1,7 +0,0 @@ -{{title (t 'titles.new')}} - - \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new/-header.hbs deleted file mode 100644 index 38ae01334..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new/-header.hbs +++ /dev/null @@ -1,4 +0,0 @@ -

- {{t "titles.new"}} - -

diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.hbs deleted file mode 100644 index aff384fe4..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.host.title_plural")}} - -{{outlet}} \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.hbs deleted file mode 100644 index d66e83390..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title @model.displayName}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-actions.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-actions.hbs deleted file mode 100644 index 4c9a91aa3..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-actions.hbs +++ /dev/null @@ -1,9 +0,0 @@ - - - {{t 'resources.host.actions.delete'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-header.hbs deleted file mode 100644 index 7b15e6f0f..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-header.hbs +++ /dev/null @@ -1,12 +0,0 @@ -

- {{t "resources.host.title"}} - -

-

{{t "resources.host.description"}}

- - {{@model.id}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-navigation.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-navigation.hbs deleted file mode 100644 index d79e3afa2..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/-navigation.hbs +++ /dev/null @@ -1,5 +0,0 @@ - - - {{t 'titles.details'}} - - \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.hbs deleted file mode 100644 index 6cc780607..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index.hbs +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs deleted file mode 100644 index e29e8dca1..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs +++ /dev/null @@ -1,60 +0,0 @@ -{{#if @model}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - {{t "form.address.label"}} - - - - {{#each @model as |host|}} - - - - {{host.displayName}} - -

{{host.description}}

-
- - - {{t (concat 'resources.host.types.' host.type)}} - - - - - {{host.id}} - - - - {{host.attributes.address}} - -
- {{/each}} -
-
- -{{else}} - - - - - {{t "resources.host.description"}} - - - - {{t "titles.new"}} - - - - -{{/if}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.hbs deleted file mode 100644 index 29bf7404f..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.hbs +++ /dev/null @@ -1,7 +0,0 @@ -{{title (t 'titles.new')}} - - \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new/-header.hbs deleted file mode 100644 index 3122f3b43..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new/-header.hbs +++ /dev/null @@ -1,4 +0,0 @@ -

- {{t "titles.new"}} - -

diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs deleted file mode 100644 index 71bdd4437..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs deleted file mode 100644 index 91a17f32d..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - -

- {{t "resources.host-catalog.title_plural"}} - -

-

{{t "resources.host-catalog.description"}}

-
- - - {{#if @model}} - - {{t "titles.new"}} - - {{/if}} - - - - - {{#if @model}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - - - - {{#each @model as |hostCatalog|}} - - - - {{hostCatalog.displayName}} - -

{{hostCatalog.description}}

-
- - - {{t (concat 'resources.host-catalog.types.' hostCatalog.type)}} - - - - - {{hostCatalog.id}} - - -
- {{/each}} -
-
- - {{else}} - - - - - {{t "resources.host-catalog.description"}} - - - - {{t "titles.new"}} - - - - - {{/if}} - -
- -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/new.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/new.hbs deleted file mode 100644 index 641fd3ff9..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/new.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{{title (t 'titles.new')}} - - - - - - - - -

- {{t "titles.new"}} - -

-
- - - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/index.hbs deleted file mode 100644 index af31fd2e6..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/index.hbs +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - -

- {{t "resources.project.title"}} - -

-

{{t "resources.project.description"}}

- - {{@model.id}} - -
- - - - - {{t 'titles.details'}} - - - - - - - - {{t 'resources.project.actions.delete'}} - - - - - - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/sessions.hbs b/ui/core/app/templates/scopes/scope/projects/project/sessions.hbs deleted file mode 100644 index f7ffb23d4..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/sessions.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.session.title_plural")}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs deleted file mode 100644 index 8865b085f..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - -

- {{t "resources.session.title_plural"}} - -

-

{{t "resources.session.description"}}

-
- - - - {{#if @model}} - - - - - {{t "form.id.label"}} - {{t "resources.user.title"}} - {{t "resources.target.title"}} - {{t "form.started.label"}} - {{t "form.status.label"}} - {{t "titles.actions"}} - - - - {{#each @model as |sessionAggregate|}} - - - - - {{sessionAggregate.session.id}} - - - {{sessionAggregate.user.displayName}} - {{sessionAggregate.target.displayName}} - - - - - {{sessionAggregate.session.status}} - - - {{#if sessionAggregate.session.isCancelable}} - - {{t "actions.cancel"}} - - {{/if}} - - - {{/each}} - - - - {{else}} - - - - - {{t "resources.session.messages.none.description"}} - - - - - {{/if}} - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets.hbs deleted file mode 100644 index 8b5774916..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{title (t "resources.target.title_plural")}} - -{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs deleted file mode 100644 index 6efba5727..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - -

- {{t "resources.target.title_plural"}} - -

- {{#if @model}} -

{{t "resources.target.description"}}

- {{/if}} -
- - - {{#if @model}} - - {{t "titles.new"}} - - {{/if}} - - - - - {{#if @model}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - - - - {{#each @model as |target|}} - - - - {{target.displayName}} - -

{{target.description}}

-
- - {{#if target.type}} - - {{t (concat "resources.target.types." target.type)}} - - {{/if}} - - - - {{target.id}} - - -
- {{/each}} -
-
- - {{else}} - - - - - {{t "resources.target.description"}} - - - - {{t "titles.new"}} - - - - - {{/if}} - -
- -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/new.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/new.hbs deleted file mode 100644 index f161f252b..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/new.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{{title (t 'titles.new')}} - - - - - - - - -

- {{t "titles.new"}} - -

-
- - - - - -
diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target.hbs deleted file mode 100644 index 2a878ff51..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target.hbs +++ /dev/null @@ -1,25 +0,0 @@ -{{title @model.displayName}} - - - - - - - - - {{outlet "header"}} - - - - {{outlet "navigation"}} - - - - {{outlet "actions"}} - - - - {{outlet}} - - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-actions.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-actions.hbs deleted file mode 100644 index 46c053cbe..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-actions.hbs +++ /dev/null @@ -1,13 +0,0 @@ - - - {{t 'resources.target.actions.add-host-sets'}} - - - - {{t 'resources.target.actions.delete'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs deleted file mode 100644 index 14e01c1de..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs +++ /dev/null @@ -1,12 +0,0 @@ -

- {{t "resources.target.title"}} - -

-

{{t "resources.target.description"}}

- - {{@model.id}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-navigation.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-navigation.hbs deleted file mode 100644 index a31f1590c..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-navigation.hbs +++ /dev/null @@ -1,8 +0,0 @@ - - - {{t 'titles.details'}} - - - {{t 'resources.host-set.title_plural'}} - - diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets.hbs deleted file mode 100644 index 15daf752a..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets.hbs +++ /dev/null @@ -1,25 +0,0 @@ -{{title (t 'resources.target.actions.add-host-sets')}} - -{{#if @model.hostSets}} - -{{/if}} - -{{#unless @model.hostSets}} - - - - {{t "resources.target.host-set.messages.none.description"}} - - - - {{t "actions.back"}} - - - -{{/unless}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets/-header.hbs deleted file mode 100644 index 64fc3df9a..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/add-host-sets/-header.hbs +++ /dev/null @@ -1,5 +0,0 @@ -

- {{t "resources.target.host-set.messages.add.title"}} - -

-

{{t "resources.target.host-set.messages.add.description"}}

diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs deleted file mode 100644 index 5e49da20d..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs +++ /dev/null @@ -1,68 +0,0 @@ -{{title (t "resources.host-set.title_plural")}} - -{{#if @model.hostSets}} - - - - - {{t "form.name.label"}} - {{t "form.type.label"}} - {{t "form.id.label"}} - {{t "titles.actions"}} - - - - {{#each @model.hostSets as |hostSet|}} - - - {{hostSet.model.displayName}} -

{{hostSet.model.description}}

-
- - {{t (concat 'resources.host-set.types.' hostSet.model.type)}} - - - - {{hostSet.model.id}} - - - - - - {{t "actions.remove"}} - - - -
- {{/each}} -
-
- -{{else}} - - - - - {{t "resources.target.host-set.messages.welcome.description"}} - - - - {{t 'resources.target.actions.add-host-sets'}} - - - - -{{/if}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets/host-set.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets/host-set.hbs deleted file mode 100644 index e2147cab0..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets/host-set.hbs +++ /dev/null @@ -1 +0,0 @@ -{{outlet}} \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/index.hbs deleted file mode 100644 index 5c39ce009..000000000 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/index.hbs +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/ui/core/tests/acceptance/authentication-test.js b/ui/core/tests/acceptance/authentication-test.js index d8bdb6162..d6c23666f 100644 --- a/ui/core/tests/acceptance/authentication-test.js +++ b/ui/core/tests/acceptance/authentication-test.js @@ -6,7 +6,7 @@ import { click, find, findAll, - setupOnerror, + //setupOnerror, } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; @@ -72,8 +72,8 @@ module('Acceptance | authentication', function (hooks) { authMethodGlobalAuthenticateURL = `/scopes/global/authenticate/${globalAuthMethodID}`; authMethodAuthenticateURL = `/scopes/${orgScopeID}/authenticate/${authMethodID}`; changePasswordURL = `/account/change-password`; - orgsURL = `/scopes/global/orgs`; - projectsURL = `/scopes/${orgScopeID}/projects`; + orgsURL = `/scopes/global`; + projectsURL = `/scopes/${orgScopeID}`; usersURL = `/scopes/${orgScopeID}/users`; groupsURL = `/scopes/${orgScopeID}/groups`; rolesURL = `/scopes/${orgScopeID}/roles`; @@ -129,10 +129,10 @@ module('Acceptance | authentication', function (hooks) { assert.notOk(currentSession().isAuthenticated); }); - test('visiting projects while unauthenticated redirects to first global authenticate method', async function (assert) { + test('visiting projects while unauthenticated redirects to first org authenticate method', async function (assert) { assert.expect(2); await visit(projectsURL); - assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.equal(currentURL(), authMethodAuthenticateURL); assert.notOk(currentSession().isAuthenticated); }); @@ -263,13 +263,11 @@ module('Acceptance | authentication', function (hooks) { currentSession().isAuthenticated, 'Session begins authenticated, before encountering 401' ); - this.server.get('/scopes', () => new Response(401)); - setupOnerror(() => { - assert.notOk( - currentSession().isAuthenticated, - 'Session is unauthenticated, after encountering 401' - ); - }); - await visit(projectsURL); + this.server.get('/users', () => new Response(401)); + await visit(usersURL); + assert.notOk( + currentSession().isAuthenticated, + 'Session is unauthenticated, after encountering 401' + ); }); }); diff --git a/ui/core/tests/acceptance/bread-crumbs-test.js b/ui/core/tests/acceptance/bread-crumbs-test.js deleted file mode 100644 index 02d7474f2..000000000 --- a/ui/core/tests/acceptance/bread-crumbs-test.js +++ /dev/null @@ -1,249 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, click, find, findAll } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | breadcrumbs', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - let orgScope; - let getProjectScope; - let project; - let hostCatalog; - let user; - let role; - let group; - let projectsURL, projectURL, newProjectURL; - let hostCatalogsURL, hostCatalogURL, newHostCatalogURL; - let usersURL, userURL, newUserURL; - let rolesURL, roleURL, newRoleURL; - let groupsURL, groupURL, newGroupURL; - - let crumbPath; - - hooks.beforeEach(function () { - authenticateSession({}); - orgScope = this.server.create( - 'scope', - { - type: 'org', - }, - 'withChildren' - ); - - getProjectScope = () => - this.server.schema.scopes.where({ type: 'project' }).models[0]; - - project = getProjectScope(); - user = this.server.create('user', { scope: orgScope }); - role = this.server.create('role', { scope: orgScope }); - group = this.server.create('group', { scope: orgScope }); - hostCatalog = this.server.create('host-catalog', { - scope: getProjectScope(), - }); - - projectsURL = `/scopes/${orgScope.id}/projects`; - newProjectURL = `${projectsURL}/new`; - projectURL = `${projectsURL}/${project.id}`; - - rolesURL = `/scopes/${orgScope.id}/roles`; - newRoleURL = `${rolesURL}/new`; - roleURL = `${rolesURL}/${role.id}`; - - groupsURL = `/scopes/${orgScope.id}/groups`; - newGroupURL = `${groupsURL}/new`; - groupURL = `${groupsURL}/${group.id}`; - - usersURL = `/scopes/${orgScope.id}/users`; - newUserURL = `${usersURL}/${user.id}`; - userURL = `${usersURL}/new`; - - hostCatalogsURL = `${projectURL}/host-catalogs`; - newHostCatalogURL = `${hostCatalogsURL}/new`; - hostCatalogURL = `${hostCatalogsURL}/${hostCatalog.id}`; - }); - - test('can navigate via breadcrumbs to projects from project', async function (assert) { - assert.expect(3); - await visit(projectURL); - assert.equal(currentURL(), projectURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, projectURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - projectsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to projects from new project', async function (assert) { - assert.expect(3); - await visit(newProjectURL); - assert.equal(currentURL(), newProjectURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, newProjectURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - projectsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to project from host catalogs', async function (assert) { - assert.expect(3); - await visit(hostCatalogsURL); - assert.equal( - currentURL(), - hostCatalogsURL, - 'We begin on the expected page.' - ); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, hostCatalogsURL, 'Last crumb has expected URL.'); - await click(findAll('.rose-nav-breadcrumbs-link')[1]); - assert.equal( - currentURL(), - projectURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to host catalogs from host catalog', async function (assert) { - assert.expect(3); - await visit(hostCatalogURL); - assert.equal( - currentURL(), - hostCatalogURL, - 'We begin on the expected page.' - ); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, hostCatalogURL, 'Last crumb has expected URL.'); - await click(findAll('.rose-nav-breadcrumbs-link')[2]); - assert.equal( - currentURL(), - hostCatalogsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to host catalogs from new host catalog', async function (assert) { - assert.expect(3); - await visit(newHostCatalogURL); - assert.equal( - currentURL(), - newHostCatalogURL, - 'We begin on the expected page.' - ); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, newHostCatalogURL, 'Last crumb has expected URL.'); - await click(findAll('.rose-nav-breadcrumbs-link')[2]); - assert.equal( - currentURL(), - hostCatalogsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to roles from role', async function (assert) { - assert.expect(3); - await visit(roleURL); - assert.equal(currentURL(), roleURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, roleURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - rolesURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to roles from new role', async function (assert) { - assert.expect(3); - await visit(newRoleURL); - assert.equal(currentURL(), newRoleURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, newRoleURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - rolesURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to groups from group', async function (assert) { - assert.expect(3); - await visit(groupURL); - assert.equal(currentURL(), groupURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, groupURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - groupsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to groups from new group', async function (assert) { - assert.expect(3); - await visit(newGroupURL); - assert.equal(currentURL(), newGroupURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, newGroupURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - groupsURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to users from user', async function (assert) { - assert.expect(3); - await visit(userURL); - assert.equal(currentURL(), userURL, 'We begin on the expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, userURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - usersURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); - - test('can navigate via breadcrumbs to users from new user', async function (assert) { - assert.expect(3); - await visit(newUserURL); - assert.equal(currentURL(), newUserURL, 'We begin on th expected page.'); - crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href) - .pathname; - assert.equal(crumbPath, newUserURL, 'Last crumb has expected URL.'); - await click(find('.rose-nav-breadcrumbs-link:first-child')); - assert.equal( - currentURL(), - usersURL, - 'After navigating via breadcrumbs, we are one level up.' - ); - }); -}); diff --git a/ui/core/tests/acceptance/host-catalogs-test.js b/ui/core/tests/acceptance/host-catalogs-test.js deleted file mode 100644 index bcb07a0a3..000000000 --- a/ui/core/tests/acceptance/host-catalogs-test.js +++ /dev/null @@ -1,217 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, fillIn, click, find } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | host catalogs', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - project: null, - }, - hostCatalog: null, - }; - const urls = { - orgScope: null, - projects: null, - project: null, - hostCatalogs: null, - newHostCatalog: null, - hostCatalog: null, - }; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession(); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: 'org' }, - }); - instances.hostCatalog = this.server.create('host-catalog', { - scope: instances.scopes.project, - }); - - // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.projects = `${urls.orgScope}/projects`; - urls.project = `${urls.projects}/${instances.hostCatalog.scope.id}`; - urls.hostCatalogs = `${urls.project}/host-catalogs`; - urls.newHostCatalog = `${urls.hostCatalogs}/new`; - urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; - }); - - test('visiting host catalogs', async function (assert) { - assert.expect(1); - await visit(urls.hostCatalogs); - await a11yAudit(); - assert.equal(currentURL(), urls.hostCatalogs); - }); - - test('can navigate to host catalog form', async function (assert) { - assert.expect(1); - await visit(urls.hostCatalogs); - await click('main tbody .rose-table-header-cell:nth-child(1) a'); - await a11yAudit(); - assert.equal(currentURL(), urls.hostCatalog); - }); - - test('can delete host catalog', async function (assert) { - assert.expect(2); - const hostCatalogsCount = this.server.db.hostCatalogs.length; - await visit(urls.hostCatalog); - assert.equal(currentURL(), urls.hostCatalog); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(this.server.db.hostCatalogs.length, hostCatalogsCount - 1); - }); - - test('can update host catalog and save changes', async function (assert) { - assert.expect(1); - await visit(urls.hostCatalog); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Test Name'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.hostCatalogs[0].name, 'Test Name'); - }); - - test('can update host catalog and cancel changes', async function (assert) { - assert.expect(1); - await visit(urls.hostCatalog); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Test Name'); - await click('form button:not([type="submit"])'); - assert.notEqual(this.server.db.hostCatalogs[0].name, 'Test Name'); - }); - - test('can create host catalog and save changes', async function (assert) { - assert.expect(1); - const hostCatalogsCount = this.server.db.hostCatalogs.length; - await visit(urls.newHostCatalog); - await fillIn('[name="name"]', 'Test Name'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.hostCatalogs.length, hostCatalogsCount + 1); - }); - - test('can create host catalog and cancel changes', async function (assert) { - assert.expect(1); - const hostCatalogsCount = this.server.db.hostCatalogs.length; - await visit(urls.newHostCatalog); - await fillIn('[name="name"]', 'Test Name'); - await click('form button:not([type="submit"])'); - assert.equal(this.server.db.hostCatalogs.length, hostCatalogsCount); - }); - - test('errors are displayed when delete host catalog fails', async function (assert) { - assert.expect(1); - this.server.del('/host-catalogs/:id', () => { - return new Response( - 490, - {}, - { - status: 490, - code: 'error', - message: 'Oops.', - } - ); - }); - await visit(urls.hostCatalog); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - await a11yAudit(); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'Oops.', - 'Displays primary error message.' - ); - }); - - test('saving a new host catalog with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/host-catalogs', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.newHostCatalog); - await fillIn('[name="name"]', 'random string'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'The request was invalid.', - 'Displays primary error message.' - ); - assert.ok( - find('.rose-form-error-message').textContent.trim(), - 'Name is required.', - 'Displays field-level errors.' - ); - }); - - test('saving an existing host catalog with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.patch('/host-catalogs/:id', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.hostCatalog); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'The request was invalid.', - 'Displays primary error message.' - ); - assert.ok( - find('.rose-form-error-message').textContent.trim(), - 'Name is required.', - 'Displays field-level errors.' - ); - }); -}); diff --git a/ui/core/tests/acceptance/host-sets-test.js b/ui/core/tests/acceptance/host-sets-test.js deleted file mode 100644 index 1b69b06a3..000000000 --- a/ui/core/tests/acceptance/host-sets-test.js +++ /dev/null @@ -1,203 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, fillIn, click, find, findAll } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | host sets', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - project: null, - }, - hostCatalog: null, - hostSet: null, - }; - const urls = { - orgScope: null, - projects: null, - project: null, - hostCatalogs: null, - hostCatalog: null, - hostSets: null, - hostSet: null, - newHostSet: null - }; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession(); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: 'org' }, - }); - instances.hostCatalog = this.server.create('host-catalog', { - scope: instances.scopes.project, - }); - instances.hostSet = this.server.create('host-set', { - scope: instances.scopes.project, - hostCatalog: instances.hostCatalog - }); - // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.projects = `${urls.orgScope}/projects`; - urls.project = `${urls.projects}/${instances.hostCatalog.scope.id}`; - urls.hostCatalogs = `${urls.project}/host-catalogs`; - urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; - urls.hostSets = `${urls.hostCatalog}/host-sets`; - urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`; - urls.newHostSet = `${urls.hostSets}/new`; - }); - - test('visiting a host set', async function (assert) { - assert.expect(1); - await visit(urls.hostSet); - await a11yAudit(); - assert.equal(currentURL(), urls.hostSet); - }); - - test('can update a host set and save changes', async function (assert) { - assert.expect(3); - await visit(urls.hostSet); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Updated name'); - await fillIn('[name="description"]', 'Updated description'); - await click('.rose-form-actions [type="submit"]'); - assert.equal(currentURL(), urls.hostSet); - assert.equal(this.server.db.hostSets[0].name, 'Updated name'); - assert.equal(this.server.db.hostSets[0].description, 'Updated description'); - }); - - test('can update a host set and cancel changes', async function (assert) { - assert.expect(1); - await visit(urls.hostSet); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Updated name'); - await click('.rose-form-actions [type="button"]'); - assert.notEqual(find('[name="name"]').value, 'Updated name'); - }); - - test('can delete host set', async function (assert) { - assert.expect(2); - const hostSetsCount = this.server.db.hostSets.length; - await visit(urls.hostSet); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(currentURL(), urls.hostSets); - assert.equal(this.server.db.hostSets.length, hostSetsCount - 1); - }); - - test('saving an existing host set with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.patch('/host-sets/:id', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.hostSet); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'existing host'); - await click('[type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); - - test('errors are displayed when delete on a host set fails', async function (assert) { - assert.expect(1); - this.server.del('/host-sets/:id', () => { - return new Response( - 490, - {}, - { - status: 490, - code: 'error', - message: 'Oops.', - } - ); - }); - await visit(urls.hostSet); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - }); - - test('can create host set and save changes', async function (assert) { - assert.expect(1); - const hostSetsCount = this.server.db.hostSets.length; - await visit(urls.newHostSet); - await fillIn('[name="name"]', 'Test Name'); - await fillIn('[name="description"]', 'description'); - await click('form [type="submit"]:not(:disabled)'); - await visit(urls.hostSets); - assert.equal(findAll('tbody tr').length, hostSetsCount + 1); - }); - - test('can create host set and cancel changes', async function (assert) { - assert.expect(2); - const hostSetsCount = this.server.db.hostSets.length; - await visit(urls.newHostSet); - await fillIn('[name="name"]', 'Test Name'); - await click('form button:not([type="submit"])'); - assert.equal(currentURL(), urls.hostSets); - assert.equal(findAll('tbody tr').length, hostSetsCount); - }); - - test('saving a new host set with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/host-sets', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.newHostSet); - await fillIn('[name="name"]', 'new target'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); -}); diff --git a/ui/core/tests/acceptance/host-sets/hosts-test.js b/ui/core/tests/acceptance/host-sets/hosts-test.js deleted file mode 100644 index f7ca0eb8b..000000000 --- a/ui/core/tests/acceptance/host-sets/hosts-test.js +++ /dev/null @@ -1,235 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, click, find, findAll, fillIn } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | host-sets | hosts', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - project: null, - }, - hostCatalog: null, - hostSet: null, - }; - const urls = { - orgScope: null, - projects: null, - project: null, - hostCatalogs: null, - hostCatalog: null, - hostSets: null, - hostSet: null, - hostSetHosts: null, - addHosts: null, - newHost: null, - }; - let hostSetHostsCount; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession(); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: 'org' }, - }); - instances.hostCatalog = this.server.create('host-catalog', { - scope: instances.scopes.project, - }, 'withChildren'); - instances.hostSet = this.server.schema.hostSets.all().models[0]; - // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.projects = `${urls.orgScope}/projects`; - urls.project = `${urls.projects}/${instances.hostCatalog.scope.id}`; - urls.hostCatalogs = `${urls.project}/host-catalogs`; - urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; - urls.hostSets = `${urls.hostCatalog}/host-sets`; - urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`; - urls.hostSetHosts = `${urls.hostSet}/hosts`; - urls.addHosts = `${urls.hostSet}/add-hosts`; - urls.newHost = `${urls.hostSet}/create-host`; - // Counts - hostSetHostsCount = instances.hostSet.hosts.length; - }); - - test('visiting host set hosts', async function (assert) { - assert.expect(2); - await visit(urls.hostSetHosts); - await a11yAudit(); - assert.equal(currentURL(), urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, hostSetHostsCount); - }); - - test('can remove a host', async function (assert) { - assert.expect(2); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, hostSetHostsCount); - await click('tbody tr .rose-dropdown-button-danger'); - assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1); - }); - - test('shows error message on host remove error', async function (assert) { - assert.expect(2); - this.server.post('/host-sets/:idMethod', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, hostSetHostsCount); - await click('tbody tr .rose-dropdown-button-danger'); - assert.ok(find('[role="alert"]')); - }); - - test('visiting add hosts', async function(assert) { - assert.expect(1); - await visit(urls.addHosts); - await a11yAudit(); - assert.equal(currentURL(), urls.addHosts); - }); - - test('select and save hosts to add', async function (assert) { - assert.expect(3); - instances.hostSet.update({ hostIds: [] }); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, 0); - await click('.rose-layout-page-actions a:nth-child(2)') - assert.equal(currentURL(), urls.addHosts); - // Click three times to select, unselect, then reselect (for coverage) - await click('tbody label'); - await click('tbody label'); - await click('tbody label'); - await click('form [type="submit"]'); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, 1); - }); - - test('select and cancel hosts to add', async function (assert) { - assert.expect(4); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, hostSetHostsCount); - await click('tbody tr .rose-dropdown-button-danger'); - assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1); - await click('.rose-layout-page-actions a:nth-child(2)') - assert.equal(currentURL(), urls.addHosts); - await click('tbody label'); - await click('form [type="button"]'); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1); - }); - - test('shows error message on host add error', async function (assert) { - assert.expect(1); - this.server.post('/host-sets/:idMethod', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - instances.hostSet.update({ hostIds: [] }); - await visit(urls.addHosts); - await click('tbody label'); - await click('form [type="submit"]'); - assert.ok(find('[role="alert"]')); - }); - - test('visiting host creation from a host set', async function (assert) { - assert.expect(1); - await visit(urls.newHost); - await a11yAudit(); - assert.equal(currentURL(), urls.newHost); - }); - - test('create and add host to host set', async function (assert) { - assert.expect(3); - instances.hostSet.update({ hostIds: [] }); - await visit(urls.hostSet); - assert.equal(findAll('tbody tr').length, 0); - await click('.rose-layout-page-actions a:nth-child(1)') - assert.equal(currentURL(), urls.newHost); - await fillIn('[name="name"]', 'Test Name'); - await fillIn('[name="description"]', 'description'); - await click('form [type="submit"]:not(:disabled)'); - await visit(urls.hostSetHosts); - assert.equal(findAll('tbody tr').length, 1); - }); - - test('create and cancel host add to host set', async function (assert) { - assert.expect(1); - await visit(urls.newHost); - await click('form [type="button"]'); - assert.equal(currentURL(), urls.hostSetHosts); - }); - - test('shows error message on host creation error', async function (assert) { - assert.expect(1); - this.server.post('/hosts', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - instances.hostSet.update({ hostIds: [] }); - await visit(urls.newHost); - await fillIn('[name="name"]', 'New Host'); - await click('form [type="submit"]'); - assert.ok(find('[role="alert"]')); - }); - - test('shows error message on host addition to host set error', async function (assert) { - assert.expect(1); - this.server.post('/host-sets/:idMethod', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - instances.hostSet.update({ hostIds: [] }); - await visit(urls.newHost); - await fillIn('[name="name"]', 'New Host'); - await click('form [type="submit"]'); - assert.ok(find('[role="alert"]')); - }); -}); diff --git a/ui/core/tests/acceptance/hosts-test.js b/ui/core/tests/acceptance/hosts-test.js deleted file mode 100644 index d04904da9..000000000 --- a/ui/core/tests/acceptance/hosts-test.js +++ /dev/null @@ -1,205 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, fillIn, click, find, findAll } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | hosts', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - project: null, - }, - hostCatalog: null, - host: null, - }; - const urls = { - orgScope: null, - projects: null, - project: null, - hostCatalogs: null, - hostCatalog: null, - hosts: null, - host: null, - newHost: null - }; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession(); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: 'org' }, - }); - instances.hostCatalog = this.server.create('host-catalog', { - scope: instances.scopes.project, - }); - instances.host = this.server.create('host', { - scope: instances.scopes.project, - hostCatalog: instances.hostCatalog - }); - // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.projects = `${urls.orgScope}/projects`; - urls.project = `${urls.projects}/${instances.hostCatalog.scope.id}`; - urls.hostCatalogs = `${urls.project}/host-catalogs`; - urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; - urls.hosts = `${urls.hostCatalog}/hosts`; - urls.host = `${urls.hosts}/${instances.host.id}`; - urls.newHost = `${urls.hosts}/new`; - }); - - test('visiting a host', async function (assert) { - assert.expect(1); - await visit(urls.host); - await a11yAudit(); - assert.equal(currentURL(), urls.host); - }); - - test('can update a host and save changes', async function (assert) { - assert.expect(4); - await visit(urls.host); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Updated name'); - await fillIn('[name="description"]', 'Updated description'); - await fillIn('[name="address"]', '::1'); - await click('.rose-form-actions [type="submit"]'); - assert.equal(currentURL(), urls.host); - assert.equal(this.server.db.hosts[0].name, 'Updated name'); - assert.equal(this.server.db.hosts[0].description, 'Updated description'); - assert.equal(this.server.db.hosts[0].attributes.address, '::1'); - }); - - test('can update a host and cancel changes', async function (assert) { - assert.expect(1); - await visit(urls.host); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'Updated name'); - await click('.rose-form-actions [type="button"]'); - assert.notEqual(find('[name="name"]').value, 'Updated name'); - }); - - test('can delete host', async function (assert) { - assert.expect(2); - const hostsCount = this.server.db.hosts.length; - await visit(urls.host); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(currentURL(), urls.hosts); - assert.equal(this.server.db.hosts.length, hostsCount - 1); - }); - - test('saving an existing host with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.patch('/hosts/:id', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.host); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'existing host'); - await click('[type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); - - test('errors are displayed when delete on a host fails', async function (assert) { - assert.expect(1); - this.server.del('/hosts/:id', () => { - return new Response( - 490, - {}, - { - status: 490, - code: 'error', - message: 'Oops.', - } - ); - }); - await visit(urls.host); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - }); - - test('can create host and save changes', async function (assert) { - assert.expect(1); - const hostsCount = this.server.db.hosts.length; - await visit(urls.newHost); - await fillIn('[name="name"]', 'Test Name'); - await fillIn('[name="description"]', 'description'); - await click('form [type="submit"]:not(:disabled)'); - await visit(urls.hosts); - assert.equal(findAll('tbody tr').length, hostsCount + 1); - }); - - test('can create host and cancel changes', async function (assert) { - assert.expect(2); - const hostsCount = this.server.db.hosts.length; - await visit(urls.newHost); - await fillIn('[name="name"]', 'Test Name'); - await click('form button:not([type="submit"])'); - assert.equal(currentURL(), urls.hosts); - assert.equal(findAll('tbody tr').length, hostsCount); - }); - - test('saving a new host with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/hosts', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.newHost); - await fillIn('[name="name"]', 'new target'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); -}); diff --git a/ui/core/tests/acceptance/orgs-test.js b/ui/core/tests/acceptance/orgs-test.js deleted file mode 100644 index 4215d3db7..000000000 --- a/ui/core/tests/acceptance/orgs-test.js +++ /dev/null @@ -1,148 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, click, find, findAll, fillIn } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | org', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - }, - orgs: null, - }; - const urls = { - root: null, - scopes: null, - globalScope: null, - orgs: null, - newOrg: null, - }; - let orgsCount; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.orgs = this.server.createList('scope', 2, { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - orgsCount = instances.orgs.length; - // Generate route URLs for resources - urls.root = '/'; - urls.scopes = `/scopes`; - urls.globalScope = `${urls.scopes}/global`; - urls.orgs = `${urls.globalScope}/orgs`; - urls.newOrg = `${urls.orgs}/new`; - }); - - test('visiting orgs', async function (assert) { - assert.expect(3); - await visit(urls.orgs); - await a11yAudit(); - assert.ok(orgsCount); - assert.equal(currentURL(), urls.orgs); - assert.equal(findAll('article').length, orgsCount); - }); - - test('visiting orgs when endpoint 404s shows an error message', async function (assert) { - assert.expect(1); - this.server.get('/scopes', () => new Response(404)); - await visit(urls.orgs); - await a11yAudit(); - assert.ok(find('.rose-message')); - }); - - test('visiting orgs is successful even when the global scope cannot be fetched', async function (assert) { - assert.expect(3); - this.server.get('/scopes/:id', ({ scopes }, { params: { id } }) => { - const scope = scopes.find(id); - return (id === 'global') - ? new Response(404) - : scope; - }); - await visit(urls.orgs); - await a11yAudit(); - assert.ok(orgsCount); - assert.equal(currentURL(), urls.orgs); - assert.equal(findAll('article').length, orgsCount); - }); - - test('visiting scopes redirects to index', async function (assert) { - assert.expect(1); - await visit(urls.scopes); - assert.equal(currentURL(), urls.orgs); - }); - - test('visiting root redirects to index', async function (assert) { - assert.expect(1); - await visit(urls.root); - assert.equal(currentURL(), urls.orgs); - }); - - test('visiting orgs within a non global scope redirects to index', async function (assert) { - const nonGlobalScopeURL = `${urls.scopes}/123/orgs`; - assert.expect(1); - await visit(nonGlobalScopeURL); - assert.equal(currentURL(), urls.orgs); - }); - - test('can create a new org', async function (assert) { - assert.expect(1); - await visit(urls.newOrg); - await fillIn('[name="name"]', 'Org name'); - await fillIn('[name="description"]', 'description'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.scopes.where(scope => scope.type === 'org').length, orgsCount + 1); - }); - - test('can cancel new org creation', async function (assert) { - assert.expect(2); - await visit(urls.newOrg); - await fillIn('[name="name"]', 'Org name'); - await fillIn('[name="description"]', 'description'); - await click('form button:not([type="submit"])'); - assert.equal(currentURL(), urls.orgs); - assert.equal(this.server.db.scopes.where(scope => scope.type === 'org').length, orgsCount); - }); - - test('saving a new org with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/scopes', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.newOrg); - await fillIn('[name="name"]', 'new org'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); -}); diff --git a/ui/core/tests/acceptance/projects-test.js b/ui/core/tests/acceptance/projects-test.js deleted file mode 100644 index 068323951..000000000 --- a/ui/core/tests/acceptance/projects-test.js +++ /dev/null @@ -1,264 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, click, fillIn, find } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { resolve, reject } from 'rsvp'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; -import sinon from 'sinon'; - -module('Acceptance | projects', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - let org; - let orgID; - let projectsURL; - let newProjectURL; - let existingProject; - let existingProjectURL; - let getProjectScopesCount; - let getFirstProjectScope; - let initialProjectScopesCount; - - hooks.beforeEach(function () { - authenticateSession({}); - org = this.server.create('scope', { type: 'org' }, 'withChildren'); - getProjectScopesCount = () => - this.server.schema.scopes.where({ type: 'project' }).length; - getFirstProjectScope = () => - this.server.schema.scopes.where({ type: 'project' }).models[0]; - initialProjectScopesCount = getProjectScopesCount(); - orgID = org.id; - projectsURL = `/scopes/${orgID}/projects`; - newProjectURL = `/scopes/${orgID}/projects/new`; - existingProject = getFirstProjectScope(); - existingProjectURL = `/scopes/${orgID}/projects/${existingProject.id}`; - }); - - test('visiting projects', async function (assert) { - assert.expect(1); - await visit(projectsURL); - await a11yAudit(); - assert.equal(currentURL(), projectsURL); - }); - - test('visiting projects within a project scope redirects to the parent org scope', async function (assert) { - assert.expect(2); - const wrongProjectsURL = `/scopes/${existingProject.id}/projects`; - assert.notEqual(wrongProjectsURL, projectsURL); - await visit(wrongProjectsURL); - await a11yAudit(); - assert.equal( - currentURL(), - projectsURL, - 'Wrong projects path was redirected to correct path.' - ); - }); - - test('can create new projects', async function (assert) { - assert.expect(1); - await visit(newProjectURL); - await fillIn('[name="name"]', 'random string'); - await click('[type="submit"]'); - assert.equal(getProjectScopesCount(), initialProjectScopesCount + 1); - }); - - test('can cancel create new projects', async function (assert) { - assert.expect(3); - assert.equal(getProjectScopesCount(), initialProjectScopesCount); - await visit(newProjectURL); - await fillIn('[name="name"]', 'random string'); - await click('.rose-form-actions [type="button"]'); - assert.equal(currentURL(), projectsURL); - assert.equal(getProjectScopesCount(), initialProjectScopesCount); - }); - - test('saving a new project with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/scopes', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(newProjectURL); - await click('[type="submit"]'); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'The request was invalid.', - 'Displays primary error message.' - ); - assert.ok( - find('.rose-form-error-message').textContent.trim(), - 'Name is required.', - 'Displays field-level errors.' - ); - }); - - test('can save changes to existing project', async function (assert) { - assert.expect(3); - assert.notEqual(existingProject.name, 'random string'); - await visit(existingProjectURL); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - await click('.rose-form-actions [type="submit"]'); - assert.equal(currentURL(), existingProjectURL); - assert.equal(getFirstProjectScope().name, 'random string'); - }); - - test('can cancel changes to existing project', async function (assert) { - assert.expect(2); - await visit(existingProjectURL); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - await click('.rose-form-actions [type="button"]'); - assert.notEqual(existingProject.name, 'random string'); - assert.equal(find('[name="name"]').value, existingProject.name); - }); - - test('can discard unsaved changes via dialog', async function (assert) { - assert.expect(5); - const confirmService = this.owner.lookup('service:confirm'); - confirmService.enabled = true; - assert.notEqual(existingProject.name, 'random string'); - await visit(existingProjectURL); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - assert.equal(currentURL(), existingProjectURL); - try { - await visit(projectsURL); - } catch (e) { - assert.ok(find('.rose-dialog')); - await click('.rose-dialog-footer button:first-child'); - assert.equal(currentURL(), projectsURL); - assert.notEqual(getFirstProjectScope().name, 'random string'); - } - }); - - test('can cancel discard unsaved changes via dialog', async function (assert) { - assert.expect(5); - const confirmService = this.owner.lookup('service:confirm'); - confirmService.enabled = true; - assert.notEqual(existingProject.name, 'random string'); - await visit(existingProjectURL); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - assert.equal(currentURL(), existingProjectURL); - try { - await visit(projectsURL); - } catch (e) { - assert.ok(find('.rose-dialog')); - await click('.rose-dialog-footer button:last-child'); - assert.equal(currentURL(), existingProjectURL); - assert.notEqual(getFirstProjectScope().name, 'random string'); - } - }); - - test('can delete project', async function (assert) { - assert.expect(1); - await visit(existingProjectURL); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getProjectScopesCount(), initialProjectScopesCount - 1); - }); - - test('can delete project with confirmation acceptance', async function (assert) { - assert.expect(2); - const confirmService = this.owner.lookup('service:confirm'); - confirmService.enabled = true; - confirmService.confirm = sinon.fake.returns(resolve()); - await visit(existingProjectURL); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getProjectScopesCount(), initialProjectScopesCount - 1); - assert.ok(confirmService.confirm.calledOnce); - }); - - test('cannot delete project with confirmation denial', async function (assert) { - assert.expect(2); - const confirmService = this.owner.lookup('service:confirm'); - confirmService.enabled = true; - confirmService.confirm = sinon.fake.returns(reject()); - await visit(existingProjectURL); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getProjectScopesCount(), initialProjectScopesCount); - assert.ok(confirmService.confirm.calledOnce); - }); - - test('saving an existing project with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.patch('/scopes/:id', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(existingProjectURL); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'random string'); - await click('[type="submit"]'); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'The request was invalid.', - 'Displays primary error message.' - ); - assert.ok( - find('.rose-form-error-message').textContent.trim(), - 'Name is required.', - 'Displays field-level errors.' - ); - }); - - test('errors are displayed when delete project fails', async function (assert) { - assert.expect(1); - this.server.del('/scopes/:id', () => { - return new Response( - 490, - {}, - { - status: 490, - code: 'error', - message: 'Oops.', - } - ); - }); - await visit(existingProjectURL); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.ok( - find('[role="alert"]').textContent.trim(), - 'Oops.', - 'Displays primary error message.' - ); - }); -}); diff --git a/ui/core/tests/acceptance/sessions-test.js b/ui/core/tests/acceptance/sessions-test.js deleted file mode 100644 index 2757712f6..000000000 --- a/ui/core/tests/acceptance/sessions-test.js +++ /dev/null @@ -1,104 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, findAll, find, click } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { run, later } from '@ember/runloop'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | sessions', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - }, - sessions: null, - }; - const urls = { - orgScope: null, - sessions: null, - }; - - hooks.beforeEach(function () { - authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: instances.scopes.org.type }, - }); - this.server.createList('group', 1, { scope: instances.scopes.org }, 'withMembers'); - this.server.createList('host-catalog', 1, { scope: instances.scopes.project }, 'withChildren'); - this.server.createList('target', 1, { scope: instances.scopes.project }, 'withRandomHostSets'); - instances.sessions = this.server.createList('session', 3, { - scope: instances.scopes.project, - status: 'active' - }, 'withAssociations'); - urls.sessions = `/scopes/${instances.scopes.org.id}/projects/${instances.scopes.project.id}/sessions`; - }); - - test('visiting sessions', async function (assert) { - assert.expect(2); - authenticateSession({}); - later(async () => { - run.cancelTimers(); - await a11yAudit(); - assert.equal(currentURL(), urls.sessions); - assert.equal(findAll('tbody tr').length, instances.sessions.length); - }, 750); - await visit(urls.sessions); - }); - - test('visiting sessions without users or targets is OK', async function (assert) { - assert.expect(2); - instances.sessions[0].update({ - userId: null, - targetId: null - }); - authenticateSession({}); - later(async () => { - run.cancelTimers(); - await a11yAudit(); - assert.equal(currentURL(), urls.sessions); - assert.equal(findAll('tbody tr').length, instances.sessions.length); - }, 750); - await visit(urls.sessions); - }); - - test('cancelling a session', async function (assert) { - assert.expect(2); - authenticateSession({}); - later(async () => { - run.cancelTimers(); - await click('tbody tr:first-child td:last-child button'); - assert.ok(find('[role="alert"].is-success')); - }, 750); - await visit(urls.sessions); - assert.equal(currentURL(), urls.sessions); - }); - - test('cancelling a session with error shows notification', async function (assert) { - assert.expect(2); - this.server.post('/sessions/:id_method', () => new Response(400)); - authenticateSession({}); - later(async () => { - run.cancelTimers(); - await click('tbody tr:first-child td:last-child button'); - assert.ok(find('[role="alert"].is-error')); - }, 750); - await visit(urls.sessions); - assert.equal(currentURL(), urls.sessions); - }); -}); diff --git a/ui/core/tests/acceptance/targets-test.js b/ui/core/tests/acceptance/targets-test.js deleted file mode 100644 index 76e87a931..000000000 --- a/ui/core/tests/acceptance/targets-test.js +++ /dev/null @@ -1,316 +0,0 @@ -import { module, test } from 'qunit'; -import { visit, currentURL, click, find, findAll, fillIn } from '@ember/test-helpers'; -import { setupApplicationTest } from 'ember-qunit'; -import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; -import { Response } from 'miragejs'; -import { - authenticateSession, - // These are left here intentionally for future reference. - //currentSession, - //invalidateSession, -} from 'ember-simple-auth/test-support'; - -module('Acceptance | targets', function (hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); - - const instances = { - scopes: { - global: null, - org: null, - project: null, - }, - target: null, - hostSets: null, - }; - const urls = { - orgScope: null, - projects: null, - project: null, - targets: null, - newTarget: null, - target: null, - targetHostSets: null, - targetAddHostSets: null, - }; - - hooks.beforeEach(function () { - // Setup Mirage mock resources for this test - authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); - instances.scopes.project = this.server.create('scope', { - type: 'project', - scope: { id: instances.scopes.org.id, type: 'org' }, - }); - - instances.hostCatalog = this.server.create('host-catalog', { - scope: instances.scopes.project - }, 'withChildren'); - instances.target = this.server.create('target', { - scope: instances.scopes.project, - hostSets: instances.hostCatalog.hostSets - }); - - // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.projects = `${urls.orgScope}/projects`; - urls.project = `${urls.projects}/${instances.scopes.project.id}`; - urls.targets = `${urls.project}/targets`; - urls.newTarget = `${urls.targets}/new`; - urls.target = `${urls.targets}/${instances.target.id}`; - urls.targetHostSets = `${urls.target}/host-sets`; - urls.targetAddHostSets = `${urls.target}/add-host-sets`; - }); - - hooks.afterEach(async function() { - const notification = find('.rose-notification'); - if(notification) { - await click('.rose-notification-dismiss'); - } - }); - - test('visiting targets', async function (assert) { - assert.expect(1); - await visit(urls.targets); - await a11yAudit(); - assert.equal(currentURL(), urls.targets); - }); - - test('can navigate to a target form', async function (assert) { - assert.expect(1); - await visit(urls.targets); - await click('main tbody .rose-table-header-cell:nth-child(1) a'); - await a11yAudit(); - assert.equal(currentURL(), urls.target); - }); - - test('can update a target and save changes', async function (assert) { - assert.expect(2); - await visit(urls.target); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'update name'); - await fillIn('[name="default_port"]', '1234'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.targets[0].name, 'update name'); - assert.equal(this.server.db.targets[0].attributes.default_port, '1234'); - }); - - test('can update a target and cancel changes', async function (assert) { - assert.expect(2); - await visit(urls.target); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'update name'); - await fillIn('[name="default_port"]', '1234'); - await click('form button:not([type="submit"])'); - assert.notEqual(this.server.db.targets[0].name, 'update name'); - assert.notEqual(this.server.db.targets[0].port, '1234'); - }); - - test('can create new target', async function (assert) { - assert.expect(1); - const targetsCount = this.server.db.targets.length; - await visit(urls.newTarget); - await fillIn('[name="name"]', 'Target name'); - await fillIn('[name="description"]', 'description'); - await fillIn('[name="default_port"]', '1234'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.targets.length, targetsCount + 1); - }); - - test('can cancel new target creation', async function (assert) { - assert.expect(2); - const targetsCount = this.server.db.targets.length; - await visit(urls.newTarget); - await fillIn('[name="name"]', 'Target Name'); - await click('form button:not([type="submit"])'); - assert.equal(this.server.db.targets.length, targetsCount); - assert.equal(currentURL(), urls.targets); - }); - - test('can delete a target', async function(assert) { - assert.expect(1); - const targetsCount = this.server.db.targets.length; - await visit(urls.target); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(this.server.db.targets.length, targetsCount - 1); - }); - - test('saving a new target with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.post('/targets', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.newTarget); - await fillIn('[name="name"]', 'new target'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); - - test('errors are displayed when delete on a target fails', async function (assert) { - assert.expect(1); - this.server.del('/targets/:id', () => { - return new Response( - 490, - {}, - { - status: 490, - code: 'error', - message: 'Oops.', - } - ); - }); - await visit(urls.target); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - }); - - test('saving an existing target with invalid fields displays error messages', async function (assert) { - assert.expect(2); - this.server.patch('/targets/:id', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: { - request_fields: [ - { - name: 'name', - description: 'Name is required.', - }, - ], - }, - } - ); - }); - await visit(urls.target); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'existing target'); - await click('form [type="submit"]'); - await a11yAudit(); - assert.ok(find('[role="alert"]')); - assert.ok(find('.rose-form-error-message')); - }); - - test('visiting target host sets', async function (assert) { - assert.expect(3); - const targetHostSetCount = instances.target.hostSets.length; - await visit(urls.targetHostSets); - await a11yAudit(); - assert.equal(currentURL(), urls.targetHostSets); - assert.ok(targetHostSetCount); - assert.equal(findAll('tbody tr').length, targetHostSetCount); - }); - - test('can remove a host sets', async function (assert) { - assert.expect(2); - const targetHostSetCount = instances.target.hostSets.length; - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, targetHostSetCount); - await click('tbody tr .rose-dropdown-button-danger'); - assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); - }); - - test('shows error message on host set remove', async function (assert) { - assert.expect(2); - this.server.post('/targets/:idMethod', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - const targetHostSetCount = instances.target.hostSets.length; - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, targetHostSetCount); - await click('tbody tr .rose-dropdown-button-danger'); - assert.ok(find('[role="alert"]')); - }); - - test('select and save host sets to add', async function (assert) { - assert.expect(3); - instances.target.update({ hostSetIds: [] }); - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, 0); - await click('.rose-layout-page-actions a') - assert.equal(currentURL(), urls.targetAddHostSets); - // Click three times to select, unselect, then reselect (for coverage) - await click('tbody label'); - await click('tbody label'); - await click('tbody label'); - await click('form [type="submit"]'); - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, 1); - }); - - test('select and cancel host sets to add', async function (assert) { - assert.expect(4); - const targetHostSetCount = instances.target.hostSets.length; - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, targetHostSetCount); - // first, remove a target host set (otherwise none would be available to add) - await click('tbody tr .rose-dropdown-button-danger'); - assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); - await click('.rose-layout-page-actions a') - assert.equal(currentURL(), urls.targetAddHostSets); - await click('tbody label'); - await click('form [type="button"]'); - await visit(urls.targetHostSets); - assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); - }); - - test('shows error message on host set add', async function (assert) { - assert.expect(4); - this.server.post('/targets/:idMethod', () => { - return new Response( - 400, - {}, - { - status: 400, - code: 'invalid_argument', - message: 'The request was invalid.', - details: {}, - } - ); - }); - instances.target.update({ hostSetIds: [] }); - await visit(urls.targetAddHostSets); - assert.equal(instances.target.hostSets.length, 0); - assert.equal(currentURL(), urls.targetAddHostSets); - await click('tbody label'); - await click('form [type="submit"]'); - assert.equal(currentURL(), urls.targetAddHostSets); - assert.equal(instances.target.hostSets.length, 0); - }); -}); diff --git a/ui/core/tests/integration/components/form/host-catalog-test.js b/ui/core/tests/integration/components/form/host-catalog-test.js deleted file mode 100644 index 20dbd545f..000000000 --- a/ui/core/tests/integration/components/form/host-catalog-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/host-catalog', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/host-set-test.js b/ui/core/tests/integration/components/form/host-set-test.js deleted file mode 100644 index 849ca7651..000000000 --- a/ui/core/tests/integration/components/form/host-set-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/host-set', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/host-set/add-hosts-test.js b/ui/core/tests/integration/components/form/host-set/add-hosts-test.js deleted file mode 100644 index 2614047a0..000000000 --- a/ui/core/tests/integration/components/form/host-set/add-hosts-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -// import { render } from '@ember/test-helpers'; -// import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/host-set/add-hosts', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - assert.expect(0); - }); -}); diff --git a/ui/core/tests/integration/components/form/host-test.js b/ui/core/tests/integration/components/form/host-test.js deleted file mode 100644 index bb4420a6f..000000000 --- a/ui/core/tests/integration/components/form/host-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/host', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/org-test.js b/ui/core/tests/integration/components/form/org-test.js deleted file mode 100644 index cfc7d25e5..000000000 --- a/ui/core/tests/integration/components/form/org-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/org', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/project-test.js b/ui/core/tests/integration/components/form/project-test.js deleted file mode 100644 index d4cb276ed..000000000 --- a/ui/core/tests/integration/components/form/project-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/project', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/target-test.js b/ui/core/tests/integration/components/form/target-test.js deleted file mode 100644 index e0246833f..000000000 --- a/ui/core/tests/integration/components/form/target-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/target', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - this.submit = () => {}; - this.cancel = () => {}; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/target/add-host-sets-test.js b/ui/core/tests/integration/components/form/target/add-host-sets-test.js deleted file mode 100644 index ce93c7a02..000000000 --- a/ui/core/tests/integration/components/form/target/add-host-sets-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -// import { render } from '@ember/test-helpers'; -// import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/target/add-host-sets', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - assert.expect(0); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/orgs-test.js b/ui/core/tests/unit/controllers/scopes/scope/orgs-test.js deleted file mode 100644 index 2833aba29..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/orgs-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/orgs', function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup('controller:scopes/scope/orgs'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/orgs/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/orgs/new-test.js deleted file mode 100644 index e11003833..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/orgs/new-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/orgs/new', function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup('controller:scopes/scope/orgs/new'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects-test.js deleted file mode 100644 index 052687cd2..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects', function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup('controller:scopes/scope/projects'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/new-test.js deleted file mode 100644 index 8da2a6f6d..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/new-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects/new', function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup('controller:scopes/scope/projects/new'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project-test.js deleted file mode 100644 index ee20af93d..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project-test.js +++ /dev/null @@ -1,14 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects/project', function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project' - ); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs-test.js deleted file mode 100644 index 76cfc0a4d..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog-test.js deleted file mode 100644 index a7f2eed72..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js deleted file mode 100644 index ac959ef1c..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js deleted file mode 100644 index 10fc9c009..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js deleted file mode 100644 index aba1c7c22..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host', function(hooks) { - setupTest(hooks); - - // TODO: Replace this with your real tests. - test('it exists', function(assert) { - let controller = this.owner.lookup('controller:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js deleted file mode 100644 index 5781b7eaa..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js deleted file mode 100644 index 21d65d16a..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/hosts', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/hosts' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js deleted file mode 100644 index 48b020001..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js deleted file mode 100644 index 8823785d6..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/new-test.js deleted file mode 100644 index f6fe63dbd..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/new-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/host-catalogs/new', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/host-catalogs/new' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/sessions-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/sessions-test.js deleted file mode 100644 index 8361f91f2..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/sessions-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects/project/sessions', function(hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function(assert) { - let controller = this.owner.lookup('controller:scopes/scope/projects/project/sessions'); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets-test.js deleted file mode 100644 index 738a97d05..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Controller | scopes/scope/projects/project/targets', function ( - hooks -) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/targets' - ); - assert.ok(controller); - }); -}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/new-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/new-test.js deleted file mode 100644 index d4e27841c..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/new-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/targets/new', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/targets/new' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target-test.js deleted file mode 100644 index 982aa3005..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/targets/target', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/targets/target' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/add-host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/add-host-sets-test.js deleted file mode 100644 index 2c14ea978..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/add-host-sets-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/targets/target/add-host-sets', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/targets/target/add-host-sets' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/host-sets-test.js deleted file mode 100644 index 4708b25e9..000000000 --- a/ui/core/tests/unit/controllers/scopes/scope/projects/project/targets/target/host-sets-test.js +++ /dev/null @@ -1,17 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Controller | scopes/scope/projects/project/targets/target/host-sets', - function (hooks) { - setupTest(hooks); - - // Replace this with your real tests. - test('it exists', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/projects/project/targets/target/host-sets' - ); - assert.ok(controller); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/orgs-test.js b/ui/core/tests/unit/routes/scopes/scope/orgs-test.js deleted file mode 100644 index 860f214b3..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/orgs-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/orgs', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/orgs'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/orgs/index-test.js b/ui/core/tests/unit/routes/scopes/scope/orgs/index-test.js deleted file mode 100644 index 9dde8b948..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/orgs/index-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/orgs/index', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/orgs/index'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/orgs/new-test.js b/ui/core/tests/unit/routes/scopes/scope/orgs/new-test.js deleted file mode 100644 index 15aa7691f..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/orgs/new-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/orgs/new', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/orgs/new'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects-test.js b/ui/core/tests/unit/routes/scopes/scope/projects-test.js deleted file mode 100644 index 127213dac..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/projects'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/index-test.js deleted file mode 100644 index 74a15f224..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/index-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/index', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/projects/index'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/new-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/new-test.js deleted file mode 100644 index 8c28e87b5..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/new-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/new', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/projects/new'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project-test.js deleted file mode 100644 index ed0ffe51a..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/projects/project'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs-test.js deleted file mode 100644 index 30ac55d7a..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/host-catalogs', function ( - hooks -) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs' - ); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog-test.js deleted file mode 100644 index 4855fd74a..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js deleted file mode 100644 index f57da0c59..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js deleted file mode 100644 index 6b6057ddf..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js deleted file mode 100644 index b93eea3c7..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js deleted file mode 100644 index ad9e0c61e..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host', function(hooks) { - setupTest(hooks); - - test('it exists', function(assert) { - let route = this.owner.lookup('route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js deleted file mode 100644 index c527a620f..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index-test.js deleted file mode 100644 index 3454fcc25..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index-test.js deleted file mode 100644 index 781e1b605..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js deleted file mode 100644 index 74cda4552..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js deleted file mode 100644 index 24a7ab5e9..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/hosts', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/hosts' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js deleted file mode 100644 index 4c1510f8b..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index-test.js deleted file mode 100644 index cb7589b5a..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index-test.js deleted file mode 100644 index 4250615d8..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js deleted file mode 100644 index c4f727b6e..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index-test.js deleted file mode 100644 index e440523af..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/host-catalog/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/index-test.js deleted file mode 100644 index aa6495519..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/index' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/new-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/new-test.js deleted file mode 100644 index 60ca74f13..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/new-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/host-catalogs/new', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/host-catalogs/new' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/index-test.js deleted file mode 100644 index f14370229..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/index-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/index', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/projects/project/index'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions-test.js deleted file mode 100644 index 70769438e..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/sessions', function(hooks) { - setupTest(hooks); - - test('it exists', function(assert) { - let route = this.owner.lookup('route:scopes/scope/projects/project/sessions'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions/index-test.js deleted file mode 100644 index a774bf223..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/sessions/index-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/sessions/index', function(hooks) { - setupTest(hooks); - - test('it exists', function(assert) { - let route = this.owner.lookup('route:scopes/scope/projects/project/sessions/index'); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets-test.js deleted file mode 100644 index 24a8476c4..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/targets', function ( - hooks -) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets' - ); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/index-test.js deleted file mode 100644 index 7d77e93a0..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/index-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/targets/index', function ( - hooks -) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/index' - ); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/new-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/new-test.js deleted file mode 100644 index a4b79d78c..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/new-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/targets/new', function ( - hooks -) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/new' - ); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js deleted file mode 100644 index 22acb8b9e..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Route | scopes/scope/projects/project/targets/target', function ( - hooks -) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/target' - ); - assert.ok(route); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/add-host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/add-host-sets-test.js deleted file mode 100644 index 3238718e1..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/add-host-sets-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/targets/target/add-host-sets', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/target/add-host-sets' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets-test.js deleted file mode 100644 index 063b787d5..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/targets/target/host-sets', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/target/host-sets' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets/host-set-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets/host-set-test.js deleted file mode 100644 index afc25f627..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/host-sets/host-set-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/targets/target/host-sets/host-set', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/target/host-sets/host-set' - ); - assert.ok(route); - }); - } -); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js deleted file mode 100644 index ec0c8507b..000000000 --- a/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module( - 'Unit | Route | scopes/scope/projects/project/targets/target/index', - function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let route = this.owner.lookup( - 'route:scopes/scope/projects/project/targets/target/index' - ); - assert.ok(route); - }); - } -); From aace22e5cac80ca33b0e2a462b6f0311a26ec7a9 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 14:30:11 -0400 Subject: [PATCH 06/27] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20header=20sco?= =?UTF-8?q?pe=20nav=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/scopes/scope/-header-nav.hbs | 14 +-- ui/core/tests/acceptance/scopes-test.js | 93 +++++++++++++++++++ 2 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 ui/core/tests/acceptance/scopes-test.js diff --git a/ui/core/app/templates/scopes/scope/-header-nav.hbs b/ui/core/app/templates/scopes/scope/-header-nav.hbs index 02b952ec8..809ce6e32 100644 --- a/ui/core/app/templates/scopes/scope/-header-nav.hbs +++ b/ui/core/app/templates/scopes/scope/-header-nav.hbs @@ -7,16 +7,12 @@ {{t "titles.global"}} - {{#each this.scopes.orgs as |scope|}} - - {{scope.displayName}} - - {{/each}} - {{else}} - - {{this.model.displayName}} - {{/if}} + {{#each this.scopes.orgs as |scope|}} + + {{scope.displayName}} + + {{/each}} {{#if this.scopes.selectedProject}} diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js new file mode 100644 index 000000000..d1d873a5c --- /dev/null +++ b/ui/core/tests/acceptance/scopes-test.js @@ -0,0 +1,93 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, click } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | scopes', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + org2: null, + project: null, + project2: null, + } + }; + const urls = { + globalScope: null, + orgScope: null, + org2Scope: null, + projectScope: null, + project2Scope: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.org2 = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.scopes.project2 = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global`; + urls.orgScope = `/scopes/${instances.scopes.org.id}`; + urls.org2Scope = `/scopes/${instances.scopes.org2.id}`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.project2Scope = `/scopes/${instances.scopes.project2.id}`; + authenticateSession({}); + }); + + test('visiting org scope', async function (assert) { + assert.expect(1); + await visit(urls.orgScope); + await a11yAudit(); + assert.equal(currentURL(), urls.orgScope); + }); + + // NOTE: In reality, we'd have a third "Global" item listed in the org + // dropdown. But since the mock test authenticator bypasses the auth + // normalization step, the UI doesn't know it's authenticated with global + // and thus doesn't display the "Global" item in the org nav dropdown. + test('can navigate among org scopes via header navigation', async function (assert) { + assert.expect(3); + await visit(urls.globalScope); + await a11yAudit(); + assert.equal(currentURL(), urls.globalScope); + await click('.rose-header-nav .rose-dropdown a:nth-child(1)'); + assert.equal(currentURL(), urls.orgScope); + // In reality, there would be a third item in the list + await click('.rose-header-nav .rose-dropdown a:nth-child(2)'); + assert.equal(currentURL(), urls.org2Scope); + }); + + test('can navigate among project scopes via header navigation', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + await a11yAudit(); + assert.equal(currentURL(), urls.projectScope); + await click('.rose-header-nav .rose-dropdown + .rose-dropdown a:nth-child(2)'); + assert.equal(currentURL(), urls.project2Scope); + }); + +}); From 2fba8025b07d2381996a9699b3745f8ad08e1ffc Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 14:57:56 -0400 Subject: [PATCH 07/27] chore --- ui/core/app/routes/scopes/scope.js | 2 +- ui/core/app/templates/scopes/scope.hbs | 66 ++++++++++++++++++-------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 179fbc865..95b31260d 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -48,7 +48,7 @@ export default class ScopesScopeRoute extends Route { .catch(() => A([])); if (model.isProject) { projects = await this.store.query('scope', { scope_id: model.scopeID }) - .catch(() => A([])) + .catch(() => A([])); } // Then pull out the "selected" scopes, if relevant let selectedOrg, selectedProject; diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index ec91c3722..a490c2148 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -5,7 +5,7 @@ {{#if @model.isGlobal}} - + @@ -16,7 +16,15 @@ {{#if @model.isOrg}} - + {{#if this.session.data.authenticated.isGlobal}} + + + {{t "resources.org.title_plural"}} + + {{/if}} + @@ -25,6 +33,43 @@ {{/if}} + {{#if @model.isProject}} + + {{#if this.session.data.authenticated.isGlobal}} + + + {{t "resources.org.title_plural"}} + + {{/if}} + + + {{t "resources.project.title_plural"}} + + + {{!-- TODO: after scope awareness refactor, update groups and roles + to support project scopes --}} + {{!-- + + + + {{t "resources.group.title_plural"}} + + + + {{t "resources.role.title_plural"}} + + + --}} + {{/if}} + {{#unless @model.isProject}} @@ -54,23 +99,6 @@ {{/unless}} - {{#if @model.isProject}} - - - - {{t "resources.group.title_plural"}} - - - - {{t "resources.role.title_plural"}} - - - {{/if}} - {{/if}} From 14408bc63ed98e73d7255a378bfac3451a02aa90 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 15:26:12 -0400 Subject: [PATCH 08/27] =?UTF-8?q?test:=20=F0=9F=92=8D=20test=20global=20sc?= =?UTF-8?q?ope=20auto-create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/routes/scopes/scope.js | 4 ++-- ui/core/tests/acceptance/scopes-test.js | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 95b31260d..3bc4ecaaa 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -27,6 +27,7 @@ export default class ScopesScopeRoute extends Route { return this.store.findRecord('scope', id).catch(() => { const maybeExistingScope = this.store.peekRecord('scope', id); const scopeOptions = { id, type }; + /* istanbul ignore else */ if (type === 'global') { scopeOptions.name = this.intl.t('titles.global'); } @@ -47,8 +48,7 @@ export default class ScopesScopeRoute extends Route { orgs = await this.store.query('scope', { scope_id: 'global' }) .catch(() => A([])); if (model.isProject) { - projects = await this.store.query('scope', { scope_id: model.scopeID }) - .catch(() => A([])); + projects = await this.store.query('scope', { scope_id: model.scopeID }); } // Then pull out the "selected" scopes, if relevant let selectedOrg, selectedProject; diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js index d1d873a5c..2894c32c4 100644 --- a/ui/core/tests/acceptance/scopes-test.js +++ b/ui/core/tests/acceptance/scopes-test.js @@ -3,6 +3,7 @@ import { visit, currentURL, click } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; import { authenticateSession, // These are left here intentionally for future reference. @@ -58,6 +59,30 @@ module('Acceptance | scopes', function (hooks) { authenticateSession({}); }); + test('visiting global scope', async function (assert) { + assert.expect(1); + await visit(urls.globalScope); + await a11yAudit(); + assert.equal(currentURL(), urls.globalScope); + }); + + // TODO: this probably shouldn't be the case, but was setup to enable + // authentication when the global scope couldn't be loaded. + // In order to resolve this, we might hoist authentication routes up from + // under scopes. + test('visiting global scope is successful even when the global scope cannot be fetched', async function (assert) { + assert.expect(1); + this.server.get('/scopes/:id', ({ scopes }, { params: { id } }) => { + const scope = scopes.find(id); + const response = (id === 'global') + ? new Response(404) + : scope; + return response; + }); + await visit(urls.globalScope); + assert.equal(currentURL(), urls.globalScope); + }); + test('visiting org scope', async function (assert) { assert.expect(1); await visit(urls.orgScope); From 2c8ff79d369494d6f7c1105f6f3d20e1ee79d7c8 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 16:50:10 -0400 Subject: [PATCH 09/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20scopes=20ind?= =?UTF-8?q?ex=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/router.js | 1 + ui/core/app/routes/scopes/scope/index.js | 4 + ui/core/app/routes/scopes/scope/scopes.js | 39 ++++++++ .../app/routes/scopes/scope/scopes/index.js | 4 + ui/core/app/templates/scopes/scope.hbs | 10 +-- ui/core/app/templates/scopes/scope/scopes.hbs | 18 ++++ .../templates/scopes/scope/scopes/index.hbs | 90 +++++++++++++++++++ .../tests/acceptance/authentication-test.js | 4 +- ui/core/tests/acceptance/scopes-test.js | 10 +-- .../unit/routes/scopes/scope/scopes-test.js | 11 +++ .../routes/scopes/scope/scopes/index-test.js | 11 +++ 11 files changed, 190 insertions(+), 12 deletions(-) create mode 100644 ui/core/app/routes/scopes/scope/scopes.js create mode 100644 ui/core/app/routes/scopes/scope/scopes/index.js create mode 100644 ui/core/app/templates/scopes/scope/scopes.hbs create mode 100644 ui/core/app/templates/scopes/scope/scopes/index.hbs create mode 100644 ui/core/tests/unit/routes/scopes/scope/scopes-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/scopes/index-test.js diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 88358232c..df0228147 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -53,6 +53,7 @@ Router.map(function () { }); this.route('new'); }); + this.route('scopes', function() {}); }); }); diff --git a/ui/core/app/routes/scopes/scope/index.js b/ui/core/app/routes/scopes/scope/index.js index 796253603..958b958ec 100644 --- a/ui/core/app/routes/scopes/scope/index.js +++ b/ui/core/app/routes/scopes/scope/index.js @@ -10,10 +10,14 @@ export default class ScopesScopeIndexRoute extends Route { /** * Redirects to scopes/scope/authenticate for further processing. + * If already authenticated, redirects to scopes/scope/scopes to display + * list of sub scopes. */ redirect() { if (!this.session.isAuthenticated) { this.transitionTo('scopes.scope.authenticate'); + } else { + this.transitionTo('scopes.scope.scopes'); } } } diff --git a/ui/core/app/routes/scopes/scope/scopes.js b/ui/core/app/routes/scopes/scope/scopes.js new file mode 100644 index 000000000..520215dcd --- /dev/null +++ b/ui/core/app/routes/scopes/scope/scopes.js @@ -0,0 +1,39 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeScopesRoute extends Route { + // =services + + @service session; + + // =methods + + /** + * Redirects to scopes/scope/authenticate if unauthenticated. + */ + beforeModel() { + if (!this.session.isAuthenticated) { + this.transitionTo('scopes.scope.authenticate'); + } + } + + /** + * Loads sub scopes for the current scope. + * @param {object} params + * @param {string} params.scope_id + * @return {Promise{ScopeModel}} + */ + async model() { + const currentScope = this.modelFor('scopes.scope'); + const parentScope = !currentScope.isGlobal + ? await this.store.findRecord('scope', currentScope.scopeID) + : null; + const subScopes = + await this.store.query('scope', { scope_id: currentScope.id }); + return { + currentScope, + parentScope, + subScopes + }; + } +} diff --git a/ui/core/app/routes/scopes/scope/scopes/index.js b/ui/core/app/routes/scopes/scope/scopes/index.js new file mode 100644 index 000000000..4c30c0049 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/scopes/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeScopesIndexRoute extends Route { +} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index a490c2148..8ae14473a 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -5,7 +5,7 @@ {{#if @model.isGlobal}} - + @@ -17,14 +17,14 @@ {{#if @model.isOrg}} {{#if this.session.data.authenticated.isGlobal}} - + {{t "resources.org.title_plural"}} {{/if}} - + @@ -36,14 +36,14 @@ {{#if @model.isProject}} {{#if this.session.data.authenticated.isGlobal}} - + {{t "resources.org.title_plural"}} {{/if}} - + diff --git a/ui/core/app/templates/scopes/scope/scopes.hbs b/ui/core/app/templates/scopes/scope/scopes.hbs new file mode 100644 index 000000000..c1cefb761 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/scopes.hbs @@ -0,0 +1,18 @@ +{{#if @model.currentScope.isGlobal}} + {{title (t "resources.org.title_plural") }} +{{/if}} + +{{#if @model.currentScope.isOrg}} + {{title (t "resources.org.title_plural") }} + {{title @model.currentScope.displayName}} + {{title (t "resources.project.title_plural") }} +{{/if}} + +{{#if @model.currentScope.isProject}} + {{title (t "resources.org.title_plural") }} + {{title @model.parentScope.displayName}} + {{title (t "resources.project.title_plural") }} + {{title @model.currentScope.displayName}} +{{/if}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/scopes/index.hbs b/ui/core/app/templates/scopes/scope/scopes/index.hbs new file mode 100644 index 000000000..ba21bb6b8 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/scopes/index.hbs @@ -0,0 +1,90 @@ + + + + + + + + {{#if @model.currentScope.isGlobal}} +

+ {{t "resources.org.title_plural"}} + +

+ {{#if @model.subScopes}} +

{{t "resources.org.description"}}

+ {{/if}} + {{/if}} + {{#if @model.currentScope.isOrg}} +

+ {{t "resources.project.title_plural"}} + +

+ {{#if @model.subScopes}} +

{{t "resources.project.description"}}

+ {{/if}} + {{/if}} +
+ + + {{#if @model.subScopes}} + + {{t 'titles.new'}} + + {{/if}} + + + + + {{#if @model.subScopes}} + + + {{#each @model.subScopes as |scope|}} + + {{/each}} + + + {{else}} + + {{#if @model.currentScope.isGlobal}} + + + + {{t 'resources.org.description'}} + + + + {{t 'titles.new'}} + + + + {{/if}} + + {{#if @model.currentScope.isOrg}} + + + + {{t 'resources.project.description'}} + + + + {{t 'titles.new'}} + + + + {{/if}} + + {{/if}} + + + +
diff --git a/ui/core/tests/acceptance/authentication-test.js b/ui/core/tests/acceptance/authentication-test.js index d6c23666f..d9d5c3a0e 100644 --- a/ui/core/tests/acceptance/authentication-test.js +++ b/ui/core/tests/acceptance/authentication-test.js @@ -72,8 +72,8 @@ module('Acceptance | authentication', function (hooks) { authMethodGlobalAuthenticateURL = `/scopes/global/authenticate/${globalAuthMethodID}`; authMethodAuthenticateURL = `/scopes/${orgScopeID}/authenticate/${authMethodID}`; changePasswordURL = `/account/change-password`; - orgsURL = `/scopes/global`; - projectsURL = `/scopes/${orgScopeID}`; + orgsURL = `/scopes/global/scopes`; + projectsURL = `/scopes/${orgScopeID}/scopes`; usersURL = `/scopes/${orgScopeID}/users`; groupsURL = `/scopes/${orgScopeID}/groups`; rolesURL = `/scopes/${orgScopeID}/roles`; diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js index 2894c32c4..4473e2aee 100644 --- a/ui/core/tests/acceptance/scopes-test.js +++ b/ui/core/tests/acceptance/scopes-test.js @@ -51,11 +51,11 @@ module('Acceptance | scopes', function (hooks) { scope: { id: instances.scopes.org.id, type: 'org' }, }); // Generate route URLs for resources - urls.globalScope = `/scopes/global`; - urls.orgScope = `/scopes/${instances.scopes.org.id}`; - urls.org2Scope = `/scopes/${instances.scopes.org2.id}`; - urls.projectScope = `/scopes/${instances.scopes.project.id}`; - urls.project2Scope = `/scopes/${instances.scopes.project2.id}`; + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.org2Scope = `/scopes/${instances.scopes.org2.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}/scopes`; + urls.project2Scope = `/scopes/${instances.scopes.project2.id}/scopes`; authenticateSession({}); }); diff --git a/ui/core/tests/unit/routes/scopes/scope/scopes-test.js b/ui/core/tests/unit/routes/scopes/scope/scopes-test.js new file mode 100644 index 000000000..7cb21ef85 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/scopes-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/scopes', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/scopes'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/scopes/index-test.js b/ui/core/tests/unit/routes/scopes/scope/scopes/index-test.js new file mode 100644 index 000000000..ca7e3fb91 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/scopes/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/scopes/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/scopes/index'); + assert.ok(route); + }); +}); From b77fc6a449834367dc3b647264899d66e89f10ea Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 17:47:59 -0400 Subject: [PATCH 10/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20scope=20edit?= =?UTF-8?q?=20route=20and=20persistence=20actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/components/form/scope/index.hbs | 53 +++++++++++++++++ ui/core/app/router.js | 1 + ui/core/app/routes/scopes/scope.js | 49 +++++++++++++++ ui/core/app/routes/scopes/scope/edit.js | 4 ++ ui/core/app/routes/scopes/scope/index.js | 4 +- ui/core/app/templates/scopes/scope/edit.hbs | 59 +++++++++++++++++++ .../templates/scopes/scope/scopes/index.hbs | 2 +- ui/core/tests/acceptance/scopes-test.js | 12 ++-- .../unit/routes/scopes/scope/edit-test.js | 11 ++++ 9 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 ui/core/app/components/form/scope/index.hbs create mode 100644 ui/core/app/routes/scopes/scope/edit.js create mode 100644 ui/core/app/templates/scopes/scope/edit.hbs create mode 100644 ui/core/tests/unit/routes/scopes/scope/edit-test.js diff --git a/ui/core/app/components/form/scope/index.hbs b/ui/core/app/components/form/scope/index.hbs new file mode 100644 index 000000000..0e024b1fb --- /dev/null +++ b/ui/core/app/components/form/scope/index.hbs @@ -0,0 +1,53 @@ + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.description}} + + {{#each @model.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/router.js b/ui/core/app/router.js index df0228147..8c575ea0e 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -54,6 +54,7 @@ Router.map(function () { this.route('new'); }); this.route('scopes', function() {}); + this.route('edit'); }); }); diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 3bc4ecaaa..3bc2e102f 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -1,6 +1,10 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; import { A } from '@ember/array'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../decorators/notify'; export default class ScopesScopeRoute extends Route { // =services @@ -83,4 +87,49 @@ export default class ScopesScopeRoute extends Route { outlet: 'header-nav', }); } + + // =actions + + /** + * Rollback changes on scope. + * @param {Model} scope + */ + @action + cancel(scope) { + const { isNew } = scope; + scope.rollbackAttributes(); + if (isNew) this.transitionTo('scopes.scope'); + } + + /** + * Handle save scope. + * @param {Model} scope + * @param {Event} e + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') + async save(scope) { + const { isNew } = scope; + await scope.save(); + await this.transitionTo('scopes.scope.edit', scope); + if (isNew) this.refresh(); + } + + /** + * Deletes the scope and redirects to index. + * @param {Model} scope + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async delete(scope) { + const { scopeID } = scope; + await scope.destroyRecord(); + await this.replaceWith('scopes.scope.scopes', scopeID); + //this.refresh(); + } } diff --git a/ui/core/app/routes/scopes/scope/edit.js b/ui/core/app/routes/scopes/scope/edit.js new file mode 100644 index 000000000..b77391dbd --- /dev/null +++ b/ui/core/app/routes/scopes/scope/edit.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeEditRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/index.js b/ui/core/app/routes/scopes/scope/index.js index 958b958ec..8ae76d0a6 100644 --- a/ui/core/app/routes/scopes/scope/index.js +++ b/ui/core/app/routes/scopes/scope/index.js @@ -13,9 +13,11 @@ export default class ScopesScopeIndexRoute extends Route { * If already authenticated, redirects to scopes/scope/scopes to display * list of sub scopes. */ - redirect() { + redirect(model) { if (!this.session.isAuthenticated) { this.transitionTo('scopes.scope.authenticate'); + } else if (model.isProject) { + this.transitionTo('scopes.scope.edit'); } else { this.transitionTo('scopes.scope.scopes'); } diff --git a/ui/core/app/templates/scopes/scope/edit.hbs b/ui/core/app/templates/scopes/scope/edit.hbs new file mode 100644 index 000000000..610b3026e --- /dev/null +++ b/ui/core/app/templates/scopes/scope/edit.hbs @@ -0,0 +1,59 @@ + + + + + + + + {{#if @model.isOrg}} +

+ {{t "resources.org.title"}} + +

+

{{t "resources.org.description"}}

+ {{/if}} + {{#if @model.isProject}} +

+ {{t "resources.project.title"}} + +

+

{{t "resources.project.description"}}

+ {{/if}} + + {{@model.id}} + +
+ + + + + {{t 'titles.details'}} + + + + + + + + {{t 'resources.project.actions.delete'}} + + + + + + + + +
diff --git a/ui/core/app/templates/scopes/scope/scopes/index.hbs b/ui/core/app/templates/scopes/scope/scopes/index.hbs index ba21bb6b8..8f4969c7d 100644 --- a/ui/core/app/templates/scopes/scope/scopes/index.hbs +++ b/ui/core/app/templates/scopes/scope/scopes/index.hbs @@ -46,7 +46,7 @@ @title={{scope.name}} @description={{scope.description}} @id={{scope.id}} - @icon={{if @model.currentScope.isGlobal "app-icons/org" "app-icons/project"}} + @icon={{if scope.isOrg "app-icons/org" "app-icons/project"}} @route="scopes.scope" @model={{scope.id}} /> diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js index 4473e2aee..2e8fe6a99 100644 --- a/ui/core/tests/acceptance/scopes-test.js +++ b/ui/core/tests/acceptance/scopes-test.js @@ -30,6 +30,8 @@ module('Acceptance | scopes', function (hooks) { org2Scope: null, projectScope: null, project2Scope: null, + projectScopeEdit: null, + project2ScopeEdit: null, }; hooks.beforeEach(function () { @@ -54,8 +56,10 @@ module('Acceptance | scopes', function (hooks) { urls.globalScope = `/scopes/global/scopes`; urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; urls.org2Scope = `/scopes/${instances.scopes.org2.id}/scopes`; - urls.projectScope = `/scopes/${instances.scopes.project.id}/scopes`; - urls.project2Scope = `/scopes/${instances.scopes.project2.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.project2Scope = `/scopes/${instances.scopes.project2.id}`; + urls.projectScopeEdit = `/scopes/${instances.scopes.project.id}/edit`; + urls.project2ScopeEdit = `/scopes/${instances.scopes.project2.id}/edit`; authenticateSession({}); }); @@ -110,9 +114,9 @@ module('Acceptance | scopes', function (hooks) { assert.expect(2); await visit(urls.projectScope); await a11yAudit(); - assert.equal(currentURL(), urls.projectScope); + assert.equal(currentURL(), urls.projectScopeEdit); await click('.rose-header-nav .rose-dropdown + .rose-dropdown a:nth-child(2)'); - assert.equal(currentURL(), urls.project2Scope); + assert.equal(currentURL(), urls.project2ScopeEdit); }); }); diff --git a/ui/core/tests/unit/routes/scopes/scope/edit-test.js b/ui/core/tests/unit/routes/scopes/scope/edit-test.js new file mode 100644 index 000000000..0b4334ea0 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/edit-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/edit', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/edit'); + assert.ok(route); + }); +}); From d927fe2735baac962aed87f827774b5667b93ad8 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 18:23:08 -0400 Subject: [PATCH 11/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20new=20scope?= =?UTF-8?q?=20route?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/router.js | 1 + ui/core/app/routes/scopes/scope/new.js | 18 +++++++++++++ ui/core/app/templates/scopes/scope/new.hbs | 27 +++++++++++++++++++ .../templates/scopes/scope/scopes/index.hbs | 2 +- .../unit/routes/scopes/scope/new-test.js | 11 ++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 ui/core/app/routes/scopes/scope/new.js create mode 100644 ui/core/app/templates/scopes/scope/new.hbs create mode 100644 ui/core/tests/unit/routes/scopes/scope/new-test.js diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 8c575ea0e..e2bb6acda 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -55,6 +55,7 @@ Router.map(function () { }); this.route('scopes', function() {}); this.route('edit'); + this.route('new'); }); }); diff --git a/ui/core/app/routes/scopes/scope/new.js b/ui/core/app/routes/scopes/scope/new.js new file mode 100644 index 000000000..c518a483a --- /dev/null +++ b/ui/core/app/routes/scopes/scope/new.js @@ -0,0 +1,18 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved scope belonging to the current scope. + * @return {ScopeModel} + */ + model() { + const { id: scopeID, isOrg } = this.modelFor('scopes.scope'); + // NOTE: if the current scope is an org, we create a project, otherwise + // it must be global and we create an org. Boundary does not support + // scopes under a project, so such a case is ignored. + const type = isOrg ? 'project' : 'org'; + return this.store.createRecord('scope', { type, scopeID }); + } +} diff --git a/ui/core/app/templates/scopes/scope/new.hbs b/ui/core/app/templates/scopes/scope/new.hbs new file mode 100644 index 000000000..b33c28109 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/new.hbs @@ -0,0 +1,27 @@ +{{title (t 'titles.new')}} + + + + + + + + +

+ {{t "titles.new"}} + +

+
+ + + + + +
diff --git a/ui/core/app/templates/scopes/scope/scopes/index.hbs b/ui/core/app/templates/scopes/scope/scopes/index.hbs index 8f4969c7d..0b92f707d 100644 --- a/ui/core/app/templates/scopes/scope/scopes/index.hbs +++ b/ui/core/app/templates/scopes/scope/scopes/index.hbs @@ -28,7 +28,7 @@ {{#if @model.subScopes}} {{t 'titles.new'}} diff --git a/ui/core/tests/unit/routes/scopes/scope/new-test.js b/ui/core/tests/unit/routes/scopes/scope/new-test.js new file mode 100644 index 000000000..76ed6531b --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/new', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/new'); + assert.ok(route); + }); +}); From 575fba37bbaf02f83c322326e25f4803726121a7 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Tue, 27 Oct 2020 18:36:29 -0400 Subject: [PATCH 12/27] chore: empty set message should have correct link --- ui/core/app/templates/scopes/scope/scopes/index.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/core/app/templates/scopes/scope/scopes/index.hbs b/ui/core/app/templates/scopes/scope/scopes/index.hbs index 0b92f707d..295eb06f3 100644 --- a/ui/core/app/templates/scopes/scope/scopes/index.hbs +++ b/ui/core/app/templates/scopes/scope/scopes/index.hbs @@ -61,7 +61,7 @@ {{t 'resources.org.description'}} - + {{t 'titles.new'}} @@ -75,7 +75,7 @@ {{t 'resources.project.description'}} - + {{t 'titles.new'}} From be0d7b5f79706a50dd2fdb628be2fb4bf3e9bf41 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 09:15:27 -0400 Subject: [PATCH 13/27] docs: tweak comments --- ui/core/app/routes/scopes/scope/scopes.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui/core/app/routes/scopes/scope/scopes.js b/ui/core/app/routes/scopes/scope/scopes.js index 520215dcd..a678edcc9 100644 --- a/ui/core/app/routes/scopes/scope/scopes.js +++ b/ui/core/app/routes/scopes/scope/scopes.js @@ -1,6 +1,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +/** + * The scopes route lists subscopes under the currently active scope. + * For the global scope, the listed scopes are orgs. + * For org scopes, the listed scopes are projects. + */ export default class ScopesScopeScopesRoute extends Route { // =services @@ -19,9 +24,7 @@ export default class ScopesScopeScopesRoute extends Route { /** * Loads sub scopes for the current scope. - * @param {object} params - * @param {string} params.scope_id - * @return {Promise{ScopeModel}} + * @return {Promise */ async model() { const currentScope = this.modelFor('scopes.scope'); From 9c7158f93004d15c913c905d0f9a5dcf7682810a Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 09:49:19 -0400 Subject: [PATCH 14/27] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20scope=20acce?= =?UTF-8?q?ptance=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/tests/acceptance/scopes-test.js | 223 +++++++++++++++++++++++- 1 file changed, 222 insertions(+), 1 deletion(-) diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js index 2e8fe6a99..175099bb3 100644 --- a/ui/core/tests/acceptance/scopes-test.js +++ b/ui/core/tests/acceptance/scopes-test.js @@ -1,9 +1,11 @@ import { module, test } from 'qunit'; -import { visit, currentURL, click } from '@ember/test-helpers'; +import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import a11yAudit from 'ember-a11y-testing/test-support/audit'; import { Response } from 'miragejs'; +import { resolve, reject } from 'rsvp'; +import sinon from 'sinon'; import { authenticateSession, // These are left here intentionally for future reference. @@ -15,6 +17,8 @@ module('Acceptance | scopes', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + let getScopeCount; + const instances = { scopes: { global: null, @@ -28,6 +32,8 @@ module('Acceptance | scopes', function (hooks) { globalScope: null, orgScope: null, org2Scope: null, + orgScopeEdit: null, + org2ScopeEdit: null, projectScope: null, project2Scope: null, projectScopeEdit: null, @@ -54,12 +60,18 @@ module('Acceptance | scopes', function (hooks) { }); // Generate route URLs for resources urls.globalScope = `/scopes/global/scopes`; + urls.newOrgScope = `/scopes/global/new`; urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; urls.org2Scope = `/scopes/${instances.scopes.org2.id}/scopes`; + urls.orgScopeEdit = `/scopes/${instances.scopes.org.id}/edit`; + urls.org2ScopeEdit = `/scopes/${instances.scopes.org2.id}/edit`; + urls.newProjectScope = `/scopes/${instances.scopes.org.id}/new`; urls.projectScope = `/scopes/${instances.scopes.project.id}`; urls.project2Scope = `/scopes/${instances.scopes.project2.id}`; urls.projectScopeEdit = `/scopes/${instances.scopes.project.id}/edit`; urls.project2ScopeEdit = `/scopes/${instances.scopes.project2.id}/edit`; + // Generate scope couners + getScopeCount = (type) => this.server.schema.scopes.where({ type }).length; authenticateSession({}); }); @@ -119,4 +131,213 @@ module('Acceptance | scopes', function (hooks) { assert.equal(currentURL(), urls.project2ScopeEdit); }); + test('can create new org scopes', async function (assert) { + assert.expect(1); + const orgScopeCount = getScopeCount('org'); + await visit(urls.newOrgScope); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(getScopeCount('org'), orgScopeCount + 1); + }); + + test('can create new project scopes', async function (assert) { + assert.expect(1); + const orgScopeCount = getScopeCount('project'); + await visit(urls.newProjectScope); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(getScopeCount('project'), orgScopeCount + 1); + }); + + test('can cancel create new org scopes', async function (assert) { + assert.expect(2); + const orgScopeCount = getScopeCount('org'); + await visit(urls.newOrgScope); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.globalScope); + assert.equal(getScopeCount('org'), orgScopeCount); + }); + + test('can cancel create new project scopes', async function (assert) { + assert.expect(2); + const projectScopeCount = getScopeCount('project'); + await visit(urls.newProjectScope); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.orgScope); + assert.equal(getScopeCount('project'), projectScopeCount); + }); + + test('saving a new scope with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/scopes', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.newOrgScope); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can save changes to existing scope', async function (assert) { + assert.expect(3); + assert.notEqual(instances.scopes.org.name, 'random string'); + await visit(urls.orgScopeEdit); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="submit"]'); + assert.equal(currentURL(), urls.orgScopeEdit); + assert.equal(this.server.schema.scopes.where({ type: 'org' }).models[0].name, 'random string'); + }); + + test('can cancel changes to existing scope', async function (assert) { + assert.expect(2); + await visit(urls.orgScopeEdit); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.notEqual(instances.scopes.org.name, 'random string'); + assert.equal(find('[name="name"]').value, instances.scopes.org.name); + }); + + test('saving an existing scope with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.patch('/scopes/:id', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.orgScopeEdit); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can discard unsaved scope changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.scopes.org.name, 'random string'); + await visit(urls.orgScopeEdit); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.orgScopeEdit); + try { + await visit(urls.globalScope); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:first-child'); + assert.equal(currentURL(), urls.globalScope); + assert.notEqual(this.server.schema.scopes.where({ type: 'org' }).models[0].name, 'random string'); + } + }); + + test('can cancel discard unsaved scope changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.scopes.org.name, 'random string'); + await visit(urls.orgScopeEdit); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.orgScopeEdit); + try { + await visit(urls.globalScope); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:last-child'); + assert.equal(currentURL(), urls.orgScopeEdit); + assert.notEqual(this.server.schema.scopes.where({ type: 'org' }).models[0].name, 'random string'); + } + }); + + test('can delete scope', async function (assert) { + assert.expect(1); + const orgScopeCount = getScopeCount('org'); + await visit(urls.orgScopeEdit); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getScopeCount('org'), orgScopeCount - 1); + }); + + test('can accept delete scope via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(resolve()); + const orgScopeCount = getScopeCount('org'); + await visit(urls.orgScopeEdit); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getScopeCount('org'), orgScopeCount - 1); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('cannot cancel delete scope via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(reject()); + const orgScopeCount = getScopeCount('org'); + await visit(urls.orgScopeEdit); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getScopeCount('org'), orgScopeCount); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('deleting a scope which errors displays error messages', async function (assert) { + assert.expect(1); + this.server.del('/scopes/:id', () => { + return new Response( + 490, + {}, + { + status: 490, + code: 'error', + message: 'Oops.', + } + ); + }); + await visit(urls.orgScopeEdit); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); + }); + }); From 369bff94027d622d43ea0fac9a81b94a32e3d825 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 11:14:58 -0400 Subject: [PATCH 15/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20sess?= =?UTF-8?q?ions=20UX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/router.js | 1 + ui/core/app/routes/scopes/scope/sessions.js | 103 +++++++++++++++++ .../app/routes/scopes/scope/sessions/index.js | 4 + ui/core/app/templates/scopes/scope.hbs | 22 ++++ .../app/templates/scopes/scope/sessions.hbs | 3 + .../templates/scopes/scope/sessions/index.hbs | 82 ++++++++++++++ ui/core/tests/acceptance/sessions-test.js | 104 ++++++++++++++++++ .../unit/routes/scopes/scope/sessions-test.js | 11 ++ .../scopes/scope/sessions/index-test.js | 11 ++ 9 files changed, 341 insertions(+) create mode 100644 ui/core/app/routes/scopes/scope/sessions.js create mode 100644 ui/core/app/routes/scopes/scope/sessions/index.js create mode 100644 ui/core/app/templates/scopes/scope/sessions.hbs create mode 100644 ui/core/app/templates/scopes/scope/sessions/index.hbs create mode 100644 ui/core/tests/acceptance/sessions-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/sessions-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/sessions/index-test.js diff --git a/ui/core/app/router.js b/ui/core/app/router.js index e2bb6acda..434fad587 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -56,6 +56,7 @@ Router.map(function () { this.route('scopes', function() {}); this.route('edit'); this.route('new'); + this.route('sessions', function() {}); }); }); diff --git a/ui/core/app/routes/scopes/scope/sessions.js b/ui/core/app/routes/scopes/scope/sessions.js new file mode 100644 index 000000000..7f64fdb67 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/sessions.js @@ -0,0 +1,103 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { all, hash } from 'rsvp'; +import { task, timeout } from 'ember-concurrency'; +import { A } from '@ember/array'; +import { notifySuccess, notifyError } from '../../../decorators/notify'; +import config from '../../../config/environment'; + +const POLL_TIMEOUT_SECONDS = config.sessionPollingTimeoutSeconds; + +export default class ScopesScopeSessionsRoute extends Route { + + // =services + + @service intl; + @service notify; + + // =attributes + + /** + * A simple Ember Concurrency-based polling task that refreshes the route + * every POLL_TIMEOUT_SECONDS seconds. This is necessary to display changes + * to session `status` that may occur. + * + * NOTE: tasks are sort of attributes and sort of methods, but they are not + * language-level constructs. Thus we annotate this task as if it + * is an attribute. + * @type {Task} + */ + @task(function * () { + while(true) { + yield timeout(POLL_TIMEOUT_SECONDS * 1000); + yield this.refresh(); + } + }).drop() poller; + + // =methods + + /** + * Loads all sessions under the current scope and encapsulates them into + * an array of objects containing their associated users and targets. + * @return {Promise{[{session: SessionModel, user: UserModel, target: TargetModel}]}} + */ + async model() { + const { id: scope_id } = this.modelFor('scopes.scope'); + const sessions = await this.store.query('session', { scope_id }); + const sessionAggregates = await all( + sessions.map(session => hash({ + session, + user: session.user_id + ? ( + this.store.peekRecord('user', session.user_id) || + this.store.findRecord('user', session.user_id) + ) + : null, + target: session.target_id + ? ( + this.store.peekRecord('target', session.target_id) || + this.store.findRecord('target', session.target_id) + ) + : null, + })) + ); + // Sort sessions by time created... + let sortedSessionAggregates = + A(sessionAggregates).sortBy('session.created_time').reverse(); + // Then move active sessions to the top... + sortedSessionAggregates = [ + ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status === 'active'), + ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status !== 'active'), + ]; + return sortedSessionAggregates; + } + + /** + * When this route is activated (entered), begin polling for changes. + */ + activate() { + this.poller.perform(); + } + + /** + * When this route is deactivated (exited), stop polling for changes. + */ + deactivate() { + this.poller.cancelAll(); + } + + // =actions + + /** + * Cancels the specified session and notifies user of success or error. + * @param {SessionModel} + */ + @action + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.canceled-success') + async cancelSession(session) { + await session.cancelSession(); + } + +} diff --git a/ui/core/app/routes/scopes/scope/sessions/index.js b/ui/core/app/routes/scopes/scope/sessions/index.js new file mode 100644 index 000000000..bf1a6aeaf --- /dev/null +++ b/ui/core/app/routes/scopes/scope/sessions/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeSessionsIndexRoute extends Route { +} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index 8ae14473a..c86d0ac09 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -68,6 +68,28 @@
--}} + + + + {{t "resources.session.title_plural"}} + + {{!-- + + + {{t "resources.target.title_plural"}} + + + + {{t "resources.host-catalog.title_plural"}} + + --}} + {{/if}} {{#unless @model.isProject}} diff --git a/ui/core/app/templates/scopes/scope/sessions.hbs b/ui/core/app/templates/scopes/scope/sessions.hbs new file mode 100644 index 000000000..f7ffb23d4 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/sessions.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.session.title_plural")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/sessions/index.hbs b/ui/core/app/templates/scopes/scope/sessions/index.hbs new file mode 100644 index 000000000..8865b085f --- /dev/null +++ b/ui/core/app/templates/scopes/scope/sessions/index.hbs @@ -0,0 +1,82 @@ + + + + + + + +

+ {{t "resources.session.title_plural"}} + +

+

{{t "resources.session.description"}}

+
+ + + + {{#if @model}} + + + + + {{t "form.id.label"}} + {{t "resources.user.title"}} + {{t "resources.target.title"}} + {{t "form.started.label"}} + {{t "form.status.label"}} + {{t "titles.actions"}} + + + + {{#each @model as |sessionAggregate|}} + + + + + {{sessionAggregate.session.id}} + + + {{sessionAggregate.user.displayName}} + {{sessionAggregate.target.displayName}} + + + + + {{sessionAggregate.session.status}} + + + {{#if sessionAggregate.session.isCancelable}} + + {{t "actions.cancel"}} + + {{/if}} + + + {{/each}} + + + + {{else}} + + + + + {{t "resources.session.messages.none.description"}} + + + + + {{/if}} + + + +
diff --git a/ui/core/tests/acceptance/sessions-test.js b/ui/core/tests/acceptance/sessions-test.js new file mode 100644 index 000000000..6026eaa24 --- /dev/null +++ b/ui/core/tests/acceptance/sessions-test.js @@ -0,0 +1,104 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, findAll, find, click } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { run, later } from '@ember/runloop'; +import { Response } from 'miragejs'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | sessions', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + }, + sessions: null, + }; + const urls = { + orgScope: null, + sessions: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: instances.scopes.org.type }, + }); + this.server.createList('group', 1, { scope: instances.scopes.org }, 'withMembers'); + this.server.createList('host-catalog', 1, { scope: instances.scopes.project }, 'withChildren'); + this.server.createList('target', 1, { scope: instances.scopes.project }, 'withRandomHostSets'); + instances.sessions = this.server.createList('session', 3, { + scope: instances.scopes.project, + status: 'active' + }, 'withAssociations'); + urls.sessions = `/scopes/${instances.scopes.project.id}/sessions`; + }); + + test('visiting sessions', async function (assert) { + assert.expect(2); + authenticateSession({}); + later(async () => { + run.cancelTimers(); + await a11yAudit(); + assert.equal(currentURL(), urls.sessions); + assert.equal(findAll('tbody tr').length, instances.sessions.length); + }, 750); + await visit(urls.sessions); + }); + + test('visiting sessions without users or targets is OK', async function (assert) { + assert.expect(2); + instances.sessions[0].update({ + userId: null, + targetId: null + }); + authenticateSession({}); + later(async () => { + run.cancelTimers(); + await a11yAudit(); + assert.equal(currentURL(), urls.sessions); + assert.equal(findAll('tbody tr').length, instances.sessions.length); + }, 750); + await visit(urls.sessions); + }); + + test('cancelling a session', async function (assert) { + assert.expect(2); + authenticateSession({}); + later(async () => { + run.cancelTimers(); + await click('tbody tr:first-child td:last-child button'); + assert.ok(find('[role="alert"].is-success')); + }, 750); + await visit(urls.sessions); + assert.equal(currentURL(), urls.sessions); + }); + + test('cancelling a session with error shows notification', async function (assert) { + assert.expect(2); + this.server.post('/sessions/:id_method', () => new Response(400)); + authenticateSession({}); + later(async () => { + run.cancelTimers(); + await click('tbody tr:first-child td:last-child button'); + assert.ok(find('[role="alert"].is-error')); + }, 750); + await visit(urls.sessions); + assert.equal(currentURL(), urls.sessions); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/sessions-test.js b/ui/core/tests/unit/routes/scopes/scope/sessions-test.js new file mode 100644 index 000000000..078865278 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/sessions-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/sessions', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/sessions'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/sessions/index-test.js b/ui/core/tests/unit/routes/scopes/scope/sessions/index-test.js new file mode 100644 index 000000000..3d18fa306 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/sessions/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/sessions/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/sessions/index'); + assert.ok(route); + }); +}); From 95652d84219ccfd2340579b3b9dccb0df7a78b90 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 11:19:09 -0400 Subject: [PATCH 16/27] chore: add settings nav --- ui/core/app/templates/scopes/scope.hbs | 10 ++++++++++ ui/core/translations/resources/en-us.yaml | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index c86d0ac09..cdd095a45 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -121,6 +121,16 @@
{{/unless}} + {{#unless @model.isGlobal}} + + + {{t (if @model.isOrg + "resources.org.messages.settings.title" + "resources.project.messages.settings.title")}} + + + {{/unless}} + {{/if}} diff --git a/ui/core/translations/resources/en-us.yaml b/ui/core/translations/resources/en-us.yaml index a19916d43..b753327bc 100644 --- a/ui/core/translations/resources/en-us.yaml +++ b/ui/core/translations/resources/en-us.yaml @@ -116,6 +116,8 @@ org: messages: welcome: title: Welcome to Orgs + settings: + title: Org Settings project: title: Project title_plural: Projects @@ -123,6 +125,8 @@ project: messages: welcome: title: Welcome to Projects + settings: + title: Project Settings actions: delete: Delete Project user: From 6e0595c62c43ec15881f86d45357a47710ef57fa Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 13:36:41 -0400 Subject: [PATCH 17/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20targ?= =?UTF-8?q?ets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/components/form/target/index.hbs | 115 ++++++++ ui/core/app/router.js | 17 +- ui/core/app/routes/scopes/scope/targets.js | 67 +++++ .../app/routes/scopes/scope/targets/index.js | 4 + .../app/routes/scopes/scope/targets/new.js | 17 ++ .../app/routes/scopes/scope/targets/target.js | 39 +++ .../scopes/scope/targets/target/index.js | 4 + ui/core/app/templates/scopes/scope.hbs | 6 +- .../app/templates/scopes/scope/targets.hbs | 3 + .../templates/scopes/scope/targets/index.hbs | 88 ++++++ .../templates/scopes/scope/targets/new.hbs | 24 ++ .../templates/scopes/scope/targets/target.hbs | 25 ++ .../scopes/scope/targets/target/-actions.hbs | 15 + .../scopes/scope/targets/target/-header.hbs | 12 + .../scope/targets/target/-navigation.hbs | 10 + .../scopes/scope/targets/target/index.hbs | 5 + ui/core/tests/acceptance/scopes-test.js | 3 +- ui/core/tests/acceptance/targets-test.js | 274 ++++++++++++++++++ .../unit/routes/scopes/scope/targets-test.js | 11 + .../routes/scopes/scope/targets/index-test.js | 11 + .../routes/scopes/scope/targets/new-test.js | 11 + .../scopes/scope/targets/target-test.js | 11 + .../scopes/scope/targets/target/index-test.js | 11 + 23 files changed, 773 insertions(+), 10 deletions(-) create mode 100644 ui/core/app/components/form/target/index.hbs create mode 100644 ui/core/app/routes/scopes/scope/targets.js create mode 100644 ui/core/app/routes/scopes/scope/targets/index.js create mode 100644 ui/core/app/routes/scopes/scope/targets/new.js create mode 100644 ui/core/app/routes/scopes/scope/targets/target.js create mode 100644 ui/core/app/routes/scopes/scope/targets/target/index.js create mode 100644 ui/core/app/templates/scopes/scope/targets.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/new.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/-actions.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/-navigation.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/index.hbs create mode 100644 ui/core/tests/acceptance/targets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/new-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/target-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/target/index-test.js diff --git a/ui/core/app/components/form/target/index.hbs b/ui/core/app/components/form/target/index.hbs new file mode 100644 index 000000000..afbfc76b0 --- /dev/null +++ b/ui/core/app/components/form/target/index.hbs @@ -0,0 +1,115 @@ + + + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.description}} + + {{#each @model.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.session_max_seconds}} + + {{#each @model.errors.session_max_seconds as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.session_connection_limit}} + + {{#each @model.errors.session_connection_limit as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + {{!-- TODO this is a type-specific field --}} + + {{!-- TODO need to figure out how to reference `attributes.errors` here --}} + {{#if @model.errors.default_port}} + + {{#each @model.errors.default_port as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 434fad587..a88062809 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -9,13 +9,14 @@ export default class Router extends EmberRouter { Router.map(function () { this.route('scopes', function () { this.route('scope', { path: ':scope_id' }, function () { + this.route('authenticate', function () { this.route('method', { path: ':auth_method_id' }); }); - this.route('orgs', function () { - this.route('new'); - }); + this.route('scopes', function() {}); + this.route('edit'); + this.route('new'); this.route('users', function () { this.route('user', { path: ':user_id' }, function () { @@ -53,10 +54,14 @@ Router.map(function () { }); this.route('new'); }); - this.route('scopes', function() {}); - this.route('edit'); - this.route('new'); + this.route('sessions', function() {}); + + this.route('targets', function() { + this.route('target', { path: ':target_id' }, function() {}); + this.route('new'); + }); + }); }); diff --git a/ui/core/app/routes/scopes/scope/targets.js b/ui/core/app/routes/scopes/scope/targets.js new file mode 100644 index 000000000..30f049682 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets.js @@ -0,0 +1,67 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../decorators/notify'; + +export default class ScopesScopeTargetsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all targets under current scope. + * @return {Promise{[TargetModel]}} + */ + async model() { + const { id: scope_id } = this.modelFor('scopes.scope'); + return this.store.query('target', { scope_id }); + } + + // =actions + + /** + * Rollback changes on a target. + * @param {TargetModel} target + */ + @action + cancel(target) { + const { isNew } = target; + target.rollbackAttributes(); + if (isNew) this.transitionTo('scopes.scope.targets'); + } + + /** + * Handle save. + * @param {TargetModel} target + * @param {Event} e + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') + async save(target) { + await target.save(); + await this.transitionTo('scopes.scope.targets.target', target); + this.refresh(); + } + + /** + * Deletes a target and redirects to targets index. + * @param {TargetModel} target + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async delete(target) { + await target.destroyRecord(); + await this.replaceWith('scopes.scope.targets'); + this.refresh(); + } +} diff --git a/ui/core/app/routes/scopes/scope/targets/index.js b/ui/core/app/routes/scopes/scope/targets/index.js new file mode 100644 index 000000000..3902b6c03 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeTargetsIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/targets/new.js b/ui/core/app/routes/scopes/scope/targets/new.js new file mode 100644 index 000000000..5e3d97603 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/new.js @@ -0,0 +1,17 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeTargetsNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved target in current scope. + * @return {TargetModel} + */ + model() { + const scopeModel = this.modelFor('scopes.scope'); + return this.store.createRecord('target', { + type: 'tcp', + scopeModel, + }); + } +} diff --git a/ui/core/app/routes/scopes/scope/targets/target.js b/ui/core/app/routes/scopes/scope/targets/target.js new file mode 100644 index 000000000..4702bb059 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/target.js @@ -0,0 +1,39 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeTargetsTargetRoute extends Route { + // =methods + + /** + * Load a target. + * @param {object} params + * @param {string} params.target_id + * @return {TargetModel} + */ + async model({ target_id }) { + return this.store.findRecord('target', target_id, { reload: true }); + } + + /** + * Renders the target-specific templates for header, navigation, + * and actions page sections. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render('scopes/scope/targets/target/-header', { + into: 'scopes/scope/targets/target', + outlet: 'header', + }); + + this.render('scopes/scope/targets/target/-navigation', { + into: 'scopes/scope/targets/target', + outlet: 'navigation', + }); + + this.render('scopes/scope/targets/target/-actions', { + into: 'scopes/scope/targets/target', + outlet: 'actions', + }); + } +} diff --git a/ui/core/app/routes/scopes/scope/targets/target/index.js b/ui/core/app/routes/scopes/scope/targets/target/index.js new file mode 100644 index 000000000..2f80e30b7 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/target/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeTargetsTargetIndexRoute extends Route { +} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index cdd095a45..e735d5640 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -75,14 +75,14 @@ @size="medium" /> {{t "resources.session.title_plural"}}
- {{!-- - + {{t "resources.target.title_plural"}} - + {{!-- + diff --git a/ui/core/app/templates/scopes/scope/targets.hbs b/ui/core/app/templates/scopes/scope/targets.hbs new file mode 100644 index 000000000..8b5774916 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.target.title_plural")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/targets/index.hbs b/ui/core/app/templates/scopes/scope/targets/index.hbs new file mode 100644 index 000000000..2aa1d6376 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/index.hbs @@ -0,0 +1,88 @@ + + + + + + + +

+ {{t "resources.target.title_plural"}} + +

+ {{#if @model}} +

{{t "resources.target.description"}}

+ {{/if}} +
+ + + {{#if @model}} + + {{t "titles.new"}} + + {{/if}} + + + + + {{#if @model}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + + + + {{#each @model as |target|}} + + + + {{target.displayName}} + +

{{target.description}}

+
+ + {{#if target.type}} + + {{t (concat "resources.target.types." target.type)}} + + {{/if}} + + + + {{target.id}} + + +
+ {{/each}} +
+
+ + {{else}} + + + + + {{t "resources.target.description"}} + + + + {{t "titles.new"}} + + + + + {{/if}} + +
+ +
diff --git a/ui/core/app/templates/scopes/scope/targets/new.hbs b/ui/core/app/templates/scopes/scope/targets/new.hbs new file mode 100644 index 000000000..f161f252b --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/new.hbs @@ -0,0 +1,24 @@ +{{title (t 'titles.new')}} + + + + + + + + +

+ {{t "titles.new"}} + +

+
+ + + + + +
diff --git a/ui/core/app/templates/scopes/scope/targets/target.hbs b/ui/core/app/templates/scopes/scope/targets/target.hbs new file mode 100644 index 000000000..2a878ff51 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target.hbs @@ -0,0 +1,25 @@ +{{title @model.displayName}} + + + + + + + + + {{outlet "header"}} + + + + {{outlet "navigation"}} + + + + {{outlet "actions"}} + + + + {{outlet}} + + + diff --git a/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs b/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs new file mode 100644 index 000000000..0b07c9565 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs @@ -0,0 +1,15 @@ + + {{!-- + + {{t 'resources.target.actions.add-host-sets'}} + + --}} + + + {{t 'resources.target.actions.delete'}} + + diff --git a/ui/core/app/templates/scopes/scope/targets/target/-header.hbs b/ui/core/app/templates/scopes/scope/targets/target/-header.hbs new file mode 100644 index 000000000..14e01c1de --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/-header.hbs @@ -0,0 +1,12 @@ +

+ {{t "resources.target.title"}} + +

+

{{t "resources.target.description"}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/targets/target/-navigation.hbs b/ui/core/app/templates/scopes/scope/targets/target/-navigation.hbs new file mode 100644 index 000000000..1e0071737 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/-navigation.hbs @@ -0,0 +1,10 @@ + + + {{t 'titles.details'}} + + {{!-- + + {{t 'resources.host-set.title_plural'}} + + --}} + diff --git a/ui/core/app/templates/scopes/scope/targets/target/index.hbs b/ui/core/app/templates/scopes/scope/targets/target/index.hbs new file mode 100644 index 000000000..83fc83598 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/index.hbs @@ -0,0 +1,5 @@ + diff --git a/ui/core/tests/acceptance/scopes-test.js b/ui/core/tests/acceptance/scopes-test.js index 175099bb3..9af9e1da8 100644 --- a/ui/core/tests/acceptance/scopes-test.js +++ b/ui/core/tests/acceptance/scopes-test.js @@ -41,6 +41,7 @@ module('Acceptance | scopes', function (hooks) { }; hooks.beforeEach(function () { + // Generate resources instances.scopes.global = this.server.create('scope', { id: 'global' }); instances.scopes.org = this.server.create('scope', { type: 'org', @@ -70,7 +71,7 @@ module('Acceptance | scopes', function (hooks) { urls.project2Scope = `/scopes/${instances.scopes.project2.id}`; urls.projectScopeEdit = `/scopes/${instances.scopes.project.id}/edit`; urls.project2ScopeEdit = `/scopes/${instances.scopes.project2.id}/edit`; - // Generate scope couners + // Generate resource couner getScopeCount = (type) => this.server.schema.scopes.where({ type }).length; authenticateSession({}); }); diff --git a/ui/core/tests/acceptance/targets-test.js b/ui/core/tests/acceptance/targets-test.js new file mode 100644 index 000000000..d8e9c811b --- /dev/null +++ b/ui/core/tests/acceptance/targets-test.js @@ -0,0 +1,274 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { resolve, reject } from 'rsvp'; +import sinon from 'sinon'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | targets', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let getTargetCount; + + const instances = { + scopes: { + global: null, + org: null, + org2: null, + project: null, + project2: null, + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + targets: null, + target: null, + newTarget: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.targets = `/scopes/${instances.scopes.project.id}/targets`; + urls.target = `/scopes/${instances.scopes.project.id}/targets/${instances.target.id}`; + urls.unknownTarget = `/scopes/${instances.scopes.project.id}/targets/foo`; + urls.newTarget = `/scopes/${instances.scopes.project.id}/targets/new`; + // Generate resource couner + getTargetCount = () => this.server.schema.targets.all().models.length; + authenticateSession({}); + }); + + test('visiting targets', async function (assert) { + assert.expect(2); + await visit(urls.targets); + await a11yAudit(); + assert.equal(currentURL(), urls.targets); + await visit(urls.target); + await a11yAudit(); + assert.equal(currentURL(), urls.target); + }); + + test('visiting an unknown target displays 404 message', async function (assert) { + assert.expect(1); + await visit(urls.unknownTarget); + await a11yAudit(); + assert.ok(find('.rose-message-subtitle').textContent.trim(), 'Error 404'); + }); + + test('can create new targets', async function (assert) { + assert.expect(1); + const count = getTargetCount(); + await visit(urls.newTarget); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(getTargetCount(), count + 1); + }); + + test('can cancel create new targets', async function (assert) { + assert.expect(2); + const count = getTargetCount(); + await visit(urls.newTarget); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.targets); + assert.equal(getTargetCount(), count); + }); + + test('saving a new target with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/targets', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.newTarget); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can save changes to existing target', async function (assert) { + assert.expect(3); + assert.notEqual(instances.target.name, 'random string'); + await visit(urls.target); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="submit"]'); + assert.equal(currentURL(), urls.target); + assert.equal(this.server.schema.targets.all().models[0].name, 'random string'); + }); + + test('can cancel changes to existing target', async function (assert) { + assert.expect(2); + await visit(urls.target); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.notEqual(instances.target.name, 'random string'); + assert.equal(find('[name="name"]').value, instances.target.name); + }); + + test('saving an existing target with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.patch('/targets/:id', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.target); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can discard unsaved target changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.target.name, 'random string'); + await visit(urls.target); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.target); + try { + await visit(urls.targets); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:first-child'); + assert.equal(currentURL(), urls.targets); + assert.notEqual(this.server.schema.targets.all().models[0].name, 'random string'); + } + }); + + test('can cancel discard unsaved target changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.target.name, 'random string'); + await visit(urls.target); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.target); + try { + await visit(urls.targets); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:last-child'); + assert.equal(currentURL(), urls.target); + assert.notEqual(this.server.schema.targets.all().models[0].name, 'random string'); + } + }); + + test('can delete target', async function (assert) { + assert.expect(1); + const count = getTargetCount(); + await visit(urls.target); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getTargetCount(), count - 1); + }); + + test('can accept delete target via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(resolve()); + const count = getTargetCount(); + await visit(urls.target); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getTargetCount(), count - 1); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('cannot cancel delete target via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(reject()); + const count = getTargetCount(); + await visit(urls.target); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getTargetCount(), count); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('deleting a target which errors displays error messages', async function (assert) { + assert.expect(1); + this.server.del('/targets/:id', () => { + return new Response( + 490, + {}, + { + status: 490, + code: 'error', + message: 'Oops.', + } + ); + }); + await visit(urls.target); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); + }); + +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets-test.js b/ui/core/tests/unit/routes/scopes/scope/targets-test.js new file mode 100644 index 000000000..45d66036b --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/index-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/index-test.js new file mode 100644 index 000000000..fea08576c --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/new-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/new-test.js new file mode 100644 index 000000000..1c1402d57 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/new', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/new'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/target-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/target-test.js new file mode 100644 index 000000000..d2cb9f9fa --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/target-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/target', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/target'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/target/index-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/target/index-test.js new file mode 100644 index 000000000..6f4f3b248 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/target/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/target/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/target/index'); + assert.ok(route); + }); +}); From f7118f221622e66bbd21f7e829bac9502612af5a Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 14:17:55 -0400 Subject: [PATCH 18/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20targ?= =?UTF-8?q?et=20host=20sets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/target/add-host-sets/index.hbs | 60 +++++++ .../form/target/add-host-sets/index.js | 55 ++++++ ui/core/app/router.js | 5 +- .../scope/targets/target/add-host-sets.js | 92 ++++++++++ .../scopes/scope/targets/target/host-sets.js | 67 ++++++++ .../scopes/scope/targets/target/-actions.hbs | 2 - .../scope/targets/target/-navigation.hbs | 2 - .../scope/targets/target/add-host-sets.hbs | 25 +++ .../targets/target/add-host-sets/-header.hbs | 5 + .../scopes/scope/targets/target/host-sets.hbs | 68 ++++++++ ui/core/tests/acceptance/targets-test.js | 10 +- .../acceptance/targets/host-sets-test.js | 160 ++++++++++++++++++ .../targets/target/add-host-sets-test.js | 11 ++ .../scope/targets/target/host-sets-test.js | 11 ++ 14 files changed, 562 insertions(+), 11 deletions(-) create mode 100644 ui/core/app/components/form/target/add-host-sets/index.hbs create mode 100644 ui/core/app/components/form/target/add-host-sets/index.js create mode 100644 ui/core/app/routes/scopes/scope/targets/target/add-host-sets.js create mode 100644 ui/core/app/routes/scopes/scope/targets/target/host-sets.js create mode 100644 ui/core/app/templates/scopes/scope/targets/target/add-host-sets.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/add-host-sets/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/targets/target/host-sets.hbs create mode 100644 ui/core/tests/acceptance/targets/host-sets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/target/add-host-sets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/targets/target/host-sets-test.js diff --git a/ui/core/app/components/form/target/add-host-sets/index.hbs b/ui/core/app/components/form/target/add-host-sets/index.hbs new file mode 100644 index 000000000..372c52f69 --- /dev/null +++ b/ui/core/app/components/form/target/add-host-sets/index.hbs @@ -0,0 +1,60 @@ +{{#if this.hasAvailableHostSets}} + + + + + + + + {{t 'form.id.label'}} + {{t 'form.name.label'}} + {{t 'form.type.label'}} + {{t 'resources.host-catalog.title'}} + + + + {{#each this.filteredHostSets as |hostSet|}} + + + + + {{hostSet.name}} + + {{t (concat 'resources.host-set.types.' hostSet.type)}} + + + {{hostSet.host_catalog_id}} + + + {{/each}} + + + + +{{/if}} + +{{#unless this.hasAvailableHostSets}} + + + + {{t "resources.target.host-set.messages.none.description"}} + + + + {{t "actions.back"}} + + + +{{/unless}} diff --git a/ui/core/app/components/form/target/add-host-sets/index.js b/ui/core/app/components/form/target/add-host-sets/index.js new file mode 100644 index 000000000..f49dda570 --- /dev/null +++ b/ui/core/app/components/form/target/add-host-sets/index.js @@ -0,0 +1,55 @@ +import Component from '@glimmer/component'; +import { computed, action } from '@ember/object'; +import { A } from '@ember/array'; + +export default class FormTargetAddHostSetsComponent extends Component { + // =properties + + /** + * Array of selected host set IDs. + * @type {EmberArray} + */ + selectedHostSetIDs = A(); + + /** + * Checks for unassigned hostsets. + * @param {[HostSetModel]} filteredHostSets + * @type {boolean} + */ + @computed('filteredHostSets.length') + get hasAvailableHostSets() { + return this.filteredHostSets.length > 0; + } + + /** + * Host sets not already added to the target. + * @type {[HostSetModel]} + */ + @computed('args.{hostSets.[],model.host_sets.[]}') + get filteredHostSets() { + // Get IDs for host sets already added to the current target + const alreadyAddedHostSetIDs = this.args.model.host_sets.map( + ({ host_set_id }) => host_set_id + ); + const notAddedHostSets = this.args.hostSets.filter( + ({ id }) => !alreadyAddedHostSetIDs.includes(id) + ); + return notAddedHostSets; + } + + // =actions + + @action + toggleHostSet(hostSet) { + if (!this.selectedHostSetIDs.includes(hostSet.id)) { + this.selectedHostSetIDs.addObject(hostSet.id); + } else { + this.selectedHostSetIDs.removeObject(hostSet.id); + } + } + + @action + submit(fn) { + fn(this.selectedHostSetIDs); + } +} diff --git a/ui/core/app/router.js b/ui/core/app/router.js index a88062809..41725c425 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -58,7 +58,10 @@ Router.map(function () { this.route('sessions', function() {}); this.route('targets', function() { - this.route('target', { path: ':target_id' }, function() {}); + this.route('target', { path: ':target_id' }, function() { + this.route('host-sets', function() {}); + this.route('add-host-sets'); + }); this.route('new'); }); diff --git a/ui/core/app/routes/scopes/scope/targets/target/add-host-sets.js b/ui/core/app/routes/scopes/scope/targets/target/add-host-sets.js new file mode 100644 index 000000000..1a211d30c --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/target/add-host-sets.js @@ -0,0 +1,92 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { all } from 'rsvp'; +import loading from 'ember-loading/decorator'; +import { notifySuccess, notifyError } from '../../../../../decorators/notify'; + +export default class ScopesScopeTargetsTargetAddHostSetsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Empty out any previously loaded host sets. + */ + beforeModel() { + this.store.unloadAll('host-set'); + } + + /** + * Returns the current target, all host catalogs, and all host sets. + * @return {{target: TargetModel, hostCatalogs: [HostCatalogModel], hostSets: [HostSetModel]}} + */ + async model() { + const target = this.modelFor( + 'scopes.scope.targets.target' + ); + const { id: scope_id } = this.modelFor('scopes.scope'); + const hostCatalogs = await this.store.query('host-catalog', { scope_id }); + await all( + hostCatalogs.map(({ id: host_catalog_id }) => + this.store.query('host-set', { host_catalog_id }) + ) + ); + const hostSets = this.store.peekAll('host-set'); + return { + target, + hostCatalogs, + hostSets, + }; + } + + /** + * Renders the add-host-sets-specific header template. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/targets/target/add-host-sets/-header', + { + into: 'scopes/scope/targets/target', + outlet: 'header', + } + ); + + this.render('-empty', { + into: 'scopes/scope/targets/target', + outlet: 'navigation', + }); + + this.render('-empty', { + into: 'scopes/scope/targets/target', + outlet: 'actions', + }); + } + + // =actions + + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(target, hostSetIDs) { + await target.addHostSets(hostSetIDs); + this.replaceWith( + 'scopes.scope.targets.target.host-sets' + ); + } + + /** + * Redirect to target host sets as if nothing ever happened. + */ + @action + cancel() { + this.replaceWith('scopes.scope.targets.target.host-sets'); + } +} diff --git a/ui/core/app/routes/scopes/scope/targets/target/host-sets.js b/ui/core/app/routes/scopes/scope/targets/target/host-sets.js new file mode 100644 index 000000000..e181d4cdd --- /dev/null +++ b/ui/core/app/routes/scopes/scope/targets/target/host-sets.js @@ -0,0 +1,67 @@ +import Route from '@ember/routing/route'; +import { all, hash } from 'rsvp'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../../../decorators/notify'; + +export default class ScopesScopeTargetsTargetHostSetsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all host-sets and associated host-catalogs under the current target + * and it's parent scope. + * @return {Promise{[HostSetModel, HostCatalogModel]}} + */ + beforeModel() { + const { scopeID, host_sets } = this.modelFor( + 'scopes.scope.targets.target' + ); + const promises = host_sets.map( + ({ host_set_id, host_catalog_id: hostCatalogID }) => + hash({ + // TODO: multiple host sets may belong to the same catalog, + // resulting in the catalog being loaded multiple times. + // An improvement would be to find the unique set of catalogs first. + hostCatalog: this.store.findRecord('host-catalog', hostCatalogID, { + adapterOptions: { scopeID }, + }), + hostSet: this.store.findRecord('host-set', host_set_id, { + adapterOptions: { scopeID, hostCatalogID }, + }), + }) + ); + return all(promises); + } + + /** + * Returns the previously loaded target instance. + * @return {TargetModel} + */ + model() { + return this.modelFor('scopes.scope.targets.target'); + } + + // =actions + + /** + * Removes a host set from the current target and redirects to index. + * @param {TargetModel} target + * @param {HostSetModel} hostSet + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeHostSet(target, hostSet) { + await target.removeHostSet(hostSet.id); + this.refresh(); + } +} diff --git a/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs b/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs index 0b07c9565..1d87ec790 100644 --- a/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/targets/target/-actions.hbs @@ -1,9 +1,7 @@ - {{!-- {{t 'resources.target.actions.add-host-sets'}} - --}} {{t 'titles.details'}}
- {{!-- {{t 'resources.host-set.title_plural'}} - --}} diff --git a/ui/core/app/templates/scopes/scope/targets/target/add-host-sets.hbs b/ui/core/app/templates/scopes/scope/targets/target/add-host-sets.hbs new file mode 100644 index 000000000..e214aa895 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/add-host-sets.hbs @@ -0,0 +1,25 @@ +{{title (t 'resources.target.actions.add-host-sets')}} + +{{#if @model.hostSets}} + +{{/if}} + +{{#unless @model.hostSets}} + + + + {{t "resources.target.host-set.messages.none.description"}} + + + + {{t "actions.back"}} + + + +{{/unless}} diff --git a/ui/core/app/templates/scopes/scope/targets/target/add-host-sets/-header.hbs b/ui/core/app/templates/scopes/scope/targets/target/add-host-sets/-header.hbs new file mode 100644 index 000000000..64fc3df9a --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/add-host-sets/-header.hbs @@ -0,0 +1,5 @@ +

+ {{t "resources.target.host-set.messages.add.title"}} + +

+

{{t "resources.target.host-set.messages.add.description"}}

diff --git a/ui/core/app/templates/scopes/scope/targets/target/host-sets.hbs b/ui/core/app/templates/scopes/scope/targets/target/host-sets.hbs new file mode 100644 index 000000000..464dc32e1 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/targets/target/host-sets.hbs @@ -0,0 +1,68 @@ +{{title (t "resources.host-set.title_plural")}} + +{{#if @model.hostSets}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + {{t "titles.actions"}} + + + + {{#each @model.hostSets as |hostSet|}} + + + {{hostSet.model.displayName}} +

{{hostSet.model.description}}

+
+ + {{t (concat 'resources.host-set.types.' hostSet.model.type)}} + + + + {{hostSet.model.id}} + + + + + + {{t "actions.remove"}} + + + +
+ {{/each}} +
+
+ +{{else}} + + + + + {{t "resources.target.host-set.messages.welcome.description"}} + + + + {{t 'resources.target.actions.add-host-sets'}} + + + + +{{/if}} diff --git a/ui/core/tests/acceptance/targets-test.js b/ui/core/tests/acceptance/targets-test.js index d8e9c811b..594756b52 100644 --- a/ui/core/tests/acceptance/targets-test.js +++ b/ui/core/tests/acceptance/targets-test.js @@ -23,9 +23,7 @@ module('Acceptance | targets', function (hooks) { scopes: { global: null, org: null, - org2: null, project: null, - project2: null, } }; const urls = { @@ -55,10 +53,10 @@ module('Acceptance | targets', function (hooks) { urls.globalScope = `/scopes/global/scopes`; urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; urls.projectScope = `/scopes/${instances.scopes.project.id}`; - urls.targets = `/scopes/${instances.scopes.project.id}/targets`; - urls.target = `/scopes/${instances.scopes.project.id}/targets/${instances.target.id}`; - urls.unknownTarget = `/scopes/${instances.scopes.project.id}/targets/foo`; - urls.newTarget = `/scopes/${instances.scopes.project.id}/targets/new`; + urls.targets = `${urls.projectScope}/targets`; + urls.target = `${urls.targets}/${instances.target.id}`; + urls.unknownTarget = `${urls.targets}/foo`; + urls.newTarget = `${urls.targets}/new`; // Generate resource couner getTargetCount = () => this.server.schema.targets.all().models.length; authenticateSession({}); diff --git a/ui/core/tests/acceptance/targets/host-sets-test.js b/ui/core/tests/acceptance/targets/host-sets-test.js new file mode 100644 index 000000000..21655f223 --- /dev/null +++ b/ui/core/tests/acceptance/targets/host-sets-test.js @@ -0,0 +1,160 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, find, findAll, click } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | targets | host-sets', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + project: null, + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + targets: null, + target: null, + targetHostSets: null, + targetAddHostSets: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project + }, 'withChildren'); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + hostSets: instances.hostCatalog.hostSets + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.targets = `/scopes/${instances.scopes.project.id}/targets`; + urls.target = `${urls.targets}/${instances.target.id}`; + urls.targetHostSets = `${urls.target}/host-sets`; + urls.targetAddHostSets = `${urls.target}/add-host-sets`; + authenticateSession({}); + }); + + test('visiting target host sets', async function (assert) { + assert.expect(3); + const targetHostSetCount = instances.target.hostSets.length; + await visit(urls.targetHostSets); + await a11yAudit(); + assert.equal(currentURL(), urls.targetHostSets); + assert.ok(targetHostSetCount); + assert.equal(findAll('tbody tr').length, targetHostSetCount); + }); + + test('can remove a host sets', async function (assert) { + assert.expect(2); + const targetHostSetCount = instances.target.hostSets.length; + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, targetHostSetCount); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); + }); + + test('removing a target host set which errors displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/targets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + const targetHostSetCount = instances.target.hostSets.length; + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, targetHostSetCount); + await click('tbody tr .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]')); + }); + + test('select and save host sets to add', async function (assert) { + assert.expect(3); + instances.target.update({ hostSetIds: [] }); + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, 0); + await click('.rose-layout-page-actions a') + assert.equal(currentURL(), urls.targetAddHostSets); + // Click three times to select, unselect, then reselect (for coverage) + await click('tbody label'); + await click('tbody label'); + await click('tbody label'); + await click('form [type="submit"]'); + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, 1); + }); + + test('select and cancel host sets to add', async function (assert) { + assert.expect(4); + const targetHostSetCount = instances.target.hostSets.length; + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, targetHostSetCount); + // first, remove a target host set (otherwise none would be available to add) + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); + await click('.rose-layout-page-actions a') + assert.equal(currentURL(), urls.targetAddHostSets); + await click('tbody label'); + await click('form [type="button"]'); + await visit(urls.targetHostSets); + assert.equal(findAll('tbody tr').length, targetHostSetCount - 1); + }); + + test('adding a target host set which errors displays error messages', async function (assert) { + assert.expect(4); + this.server.post('/targets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.target.update({ hostSetIds: [] }); + await visit(urls.targetAddHostSets); + assert.equal(instances.target.hostSets.length, 0); + assert.equal(currentURL(), urls.targetAddHostSets); + await click('tbody label'); + await click('form [type="submit"]'); + assert.equal(currentURL(), urls.targetAddHostSets); + assert.equal(instances.target.hostSets.length, 0); + }); + +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/target/add-host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/target/add-host-sets-test.js new file mode 100644 index 000000000..c07db35c9 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/target/add-host-sets-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/target/add-host-sets', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/target/add-host-sets'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/targets/target/host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/targets/target/host-sets-test.js new file mode 100644 index 000000000..1309e5b03 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/targets/target/host-sets-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/targets/target/host-sets', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/targets/target/host-sets'); + assert.ok(route); + }); +}); From 225373d4374b9283d19093b4342b9c2db35b0d12 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 18:19:14 -0400 Subject: [PATCH 19/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20host?= =?UTF-8?q?=20catalogs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/form/host-catalog/index.hbs | 53 ++++ ui/core/app/router.js | 7 +- .../app/routes/scopes/scope/host-catalogs.js | 70 +++++ .../scope/host-catalogs/host-catalog.js | 53 ++++ .../scope/host-catalogs/host-catalog/index.js | 3 + .../scopes/scope/host-catalogs/index.js | 4 + .../routes/scopes/scope/host-catalogs/new.js | 17 ++ ui/core/app/templates/scopes/scope.hbs | 2 - .../templates/scopes/scope/host-catalogs.hbs | 3 + .../scope/host-catalogs/host-catalog.hbs | 25 ++ .../host-catalogs/host-catalog/-actions.hbs | 24 ++ .../host-catalogs/host-catalog/-header.hbs | 12 + .../host-catalog/-navigation.hbs | 13 + .../host-catalogs/host-catalog/index.hbs | 5 + .../scopes/scope/host-catalogs/index.hbs | 86 ++++++ .../scopes/scope/host-catalogs/new.hbs | 24 ++ .../tests/acceptance/host-catalogs-test.js | 272 ++++++++++++++++++ .../routes/scopes/scope/host-catalogs-test.js | 11 + .../scope/host-catalogs/host-catalog-test.js | 11 + .../host-catalogs/host-catalog/index-test.js | 11 + .../scopes/scope/host-catalogs/index-test.js | 11 + .../scopes/scope/host-catalogs/new-test.js | 11 + 22 files changed, 724 insertions(+), 4 deletions(-) create mode 100644 ui/core/app/components/form/host-catalog/index.hbs create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/new.js create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-navigation.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/new.hbs create mode 100644 ui/core/tests/acceptance/host-catalogs-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/new-test.js diff --git a/ui/core/app/components/form/host-catalog/index.hbs b/ui/core/app/components/form/host-catalog/index.hbs new file mode 100644 index 000000000..0e024b1fb --- /dev/null +++ b/ui/core/app/components/form/host-catalog/index.hbs @@ -0,0 +1,53 @@ + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.description}} + + {{#each @model.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 41725c425..e3419f5f5 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -9,7 +9,6 @@ export default class Router extends EmberRouter { Router.map(function () { this.route('scopes', function () { this.route('scope', { path: ':scope_id' }, function () { - this.route('authenticate', function () { this.route('method', { path: ':auth_method_id' }); }); @@ -64,7 +63,11 @@ Router.map(function () { }); this.route('new'); }); - + + this.route('host-catalogs', function() { + this.route('new'); + this.route('host-catalog', { path: ':host_catalog_id' }, function() {}); + }); }); }); diff --git a/ui/core/app/routes/scopes/scope/host-catalogs.js b/ui/core/app/routes/scopes/scope/host-catalogs.js new file mode 100644 index 000000000..03adfed44 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs.js @@ -0,0 +1,70 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all host catalogs under the current scope. + * @return {Promise{[HostCatalogModel]}} + */ + async model() { + const { id: scope_id } = this.modelFor('scopes.scope'); + return this.store.query('host-catalog', { scope_id }); + } + + // =actions + + /** + * Rollback changes on host catalog. + * @param {HostCatalogModel} hostCatalog + */ + @action + cancel(hostCatalog) { + const { isNew } = hostCatalog; + hostCatalog.rollbackAttributes(); + if (isNew) this.transitionTo('scopes.scope.host-catalogs'); + } + + /** + * Handle save. + * @param {HostCatalogModel} hostCatalog + * @param {Event} e + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') + async save(hostCatalog) { + await hostCatalog.save(); + await this.transitionTo( + 'scopes.scope.host-catalogs.host-catalog', + hostCatalog + ); + this.refresh(); + } + + /** + * Deletes the host catalog and redirects to index. + * @param {HostCatalogModel} hostCatalog + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async delete(hostCatalog) { + await hostCatalog.destroyRecord(); + await this.replaceWith('scopes.scope.host-catalogs'); + this.refresh(); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog.js new file mode 100644 index 000000000..98f8c40b4 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog.js @@ -0,0 +1,53 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogRoute extends Route { + // =methods + + /** + * Load a host catalog. + * @param {object} params + * @param {string} params.host_catalog_id + * @return {HostCatalogModel} + */ + async model({ host_catalog_id }) { + return this.store.findRecord('host-catalog', host_catalog_id); + } + + /** + * Renders the host-catalog specific templates for header, navigation, + * and actions page sections. + * @override + * @param {object} controller + * @param {object} model + */ + renderTemplate(controller, model) { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/-navigation', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/-actions', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + model: model, + } + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/index.js new file mode 100644 index 000000000..a039b120c --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogIndexRoute extends Route {} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/index.js new file mode 100644 index 000000000..7698589d9 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/new.js b/ui/core/app/routes/scopes/scope/host-catalogs/new.js new file mode 100644 index 000000000..9af8baaef --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/new.js @@ -0,0 +1,17 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved host catalog belonging to the current scope. + * @return {HostCatalogModel} + */ + model() { + const scopeModel = this.modelFor('scopes.scope'); + return this.store.createRecord('host-catalog', { + type: 'static', + scopeModel, + }); + } +} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index e735d5640..ba8eeda68 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -81,14 +81,12 @@ @size="medium" /> {{t "resources.target.title_plural"}}
- {{!-- {{t "resources.host-catalog.title_plural"}} - --}}
{{/if}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs.hbs b/ui/core/app/templates/scopes/scope/host-catalogs.hbs new file mode 100644 index 000000000..abbb6702e --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.host-catalog.title_plural")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog.hbs new file mode 100644 index 000000000..271a98d73 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog.hbs @@ -0,0 +1,25 @@ +{{title @model.displayName}} + + + + + + + + + {{outlet "header"}} + + + + {{outlet "actions"}} + + + + {{outlet "navigation"}} + + + + {{outlet}} + + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs new file mode 100644 index 000000000..14538798b --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs @@ -0,0 +1,24 @@ + + {{!-- + + {{t "resources.host.actions.create"}} + + + {{t "resources.host-set.actions.create"}} + + --}} + + + {{t "resources.host-catalog.actions.delete"}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-header.hbs new file mode 100644 index 000000000..58e6f4b02 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-header.hbs @@ -0,0 +1,12 @@ +

+ {{t "resources.host-catalog.title"}} + +

+

{{t "resources.host-catalog.description"}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-navigation.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-navigation.hbs new file mode 100644 index 000000000..a0940466a --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-navigation.hbs @@ -0,0 +1,13 @@ + + + {{t 'titles.details'}} + + {{!-- + + {{t 'resources.host-set.title_plural'}} + + + {{t 'resources.host.title_plural'}} + + --}} + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/index.hbs new file mode 100644 index 000000000..71bdd4437 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/index.hbs @@ -0,0 +1,5 @@ + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/index.hbs new file mode 100644 index 000000000..7fdf6fc12 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/index.hbs @@ -0,0 +1,86 @@ + + + + + + + +

+ {{t "resources.host-catalog.title_plural"}} + +

+ {{#if @model}} +

{{t "resources.host-catalog.description"}}

+ {{/if}} +
+ + + {{#if @model}} + + {{t "titles.new"}} + + {{/if}} + + + + + {{#if @model}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + + + + {{#each @model as |hostCatalog|}} + + + + {{hostCatalog.displayName}} + +

{{hostCatalog.description}}

+
+ + + {{t (concat 'resources.host-catalog.types.' hostCatalog.type)}} + + + + + {{hostCatalog.id}} + + +
+ {{/each}} +
+
+ + {{else}} + + + + + {{t "resources.host-catalog.description"}} + + + + {{t "titles.new"}} + + + + + {{/if}} + +
+ +
diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/new.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/new.hbs new file mode 100644 index 000000000..641fd3ff9 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/new.hbs @@ -0,0 +1,24 @@ +{{title (t 'titles.new')}} + + + + + + + + +

+ {{t "titles.new"}} + +

+
+ + + + + +
diff --git a/ui/core/tests/acceptance/host-catalogs-test.js b/ui/core/tests/acceptance/host-catalogs-test.js new file mode 100644 index 000000000..0c2a1fb30 --- /dev/null +++ b/ui/core/tests/acceptance/host-catalogs-test.js @@ -0,0 +1,272 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { resolve, reject } from 'rsvp'; +import sinon from 'sinon'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | host-catalogs', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let gethostCatalogCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + hostCatalogs: null, + hostCatalog: null, + newHostCatalog: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project, + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; + urls.unknownHostCatalog = `${urls.hostCatalogs}/foo`; + urls.newHostCatalog = `${urls.hostCatalogs}/new`; + // Generate resource couner + gethostCatalogCount = () => this.server.schema.hostCatalogs.all().models.length; + authenticateSession({}); + }); + + test('visiting host catalogs', async function (assert) { + assert.expect(2); + await visit(urls.hostCatalogs); + await a11yAudit(); + assert.equal(currentURL(), urls.hostCatalogs); + await visit(urls.hostCatalog); + await a11yAudit(); + assert.equal(currentURL(), urls.hostCatalog); + }); + + test('visiting an unknown host catalog displays 404 message', async function (assert) { + assert.expect(1); + await visit(urls.unknownHostCatalog); + await a11yAudit(); + assert.ok(find('.rose-message-subtitle').textContent.trim(), 'Error 404'); + }); + + test('can create new host catalogs', async function (assert) { + assert.expect(1); + const count = gethostCatalogCount(); + await visit(urls.newHostCatalog); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(gethostCatalogCount(), count + 1); + }); + + test('can cancel create new host catalogs', async function (assert) { + assert.expect(2); + const count = gethostCatalogCount(); + await visit(urls.newHostCatalog); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.hostCatalogs); + assert.equal(gethostCatalogCount(), count); + }); + + test('saving a new host catalog with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/host-catalogs', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.newHostCatalog); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can save changes to existing host catalog', async function (assert) { + assert.expect(3); + assert.notEqual(instances.hostCatalog.name, 'random string'); + await visit(urls.hostCatalog); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="submit"]'); + assert.equal(currentURL(), urls.hostCatalog); + assert.equal(this.server.schema.hostCatalogs.all().models[0].name, 'random string'); + }); + + test('can cancel changes to existing host catalog', async function (assert) { + assert.expect(2); + await visit(urls.hostCatalog); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.notEqual(instances.hostCatalog.name, 'random string'); + assert.equal(find('[name="name"]').value, instances.hostCatalog.name); + }); + + test('saving an existing host catalog with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.patch('/host-catalogs/:id', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.hostCatalog); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can discard unsaved host catalog changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.hostCatalog.name, 'random string'); + await visit(urls.hostCatalog); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.hostCatalog); + try { + await visit(urls.hostCatalogs); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:first-child'); + assert.equal(currentURL(), urls.hostCatalogs); + assert.notEqual(this.server.schema.hostCatalogs.all().models[0].name, 'random string'); + } + }); + + test('can cancel discard unsaved host catalog changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.hostCatalog.name, 'random string'); + await visit(urls.hostCatalog); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.hostCatalog); + try { + await visit(urls.hostCatalogs); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:last-child'); + assert.equal(currentURL(), urls.hostCatalog); + assert.notEqual(this.server.schema.hostCatalogs.all().models[0].name, 'random string'); + } + }); + + test('can delete host catalog', async function (assert) { + assert.expect(1); + const count = gethostCatalogCount(); + await visit(urls.hostCatalog); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(gethostCatalogCount(), count - 1); + }); + + test('can accept delete host catalog via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(resolve()); + const count = gethostCatalogCount(); + await visit(urls.hostCatalog); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(gethostCatalogCount(), count - 1); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('cannot cancel delete host catalog via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(reject()); + const count = gethostCatalogCount(); + await visit(urls.hostCatalog); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(gethostCatalogCount(), count); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('deleting a host catalog which errors displays error messages', async function (assert) { + assert.expect(1); + this.server.del('/host-catalogs/:id', () => { + return new Response( + 490, + {}, + { + status: 490, + code: 'error', + message: 'Oops.', + } + ); + }); + await visit(urls.hostCatalog); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); + }); + +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs-test.js new file mode 100644 index 000000000..391eaa2c5 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog-test.js new file mode 100644 index 000000000..cefbf9457 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/index-test.js new file mode 100644 index 000000000..6bd3f5df2 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/index-test.js new file mode 100644 index 000000000..a64c67754 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/new-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/new-test.js new file mode 100644 index 000000000..c2d2397d3 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/new', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/new'); + assert.ok(route); + }); +}); From 709a8e39490d86eef3da4c5934fa5b9615345e26 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 28 Oct 2020 19:00:35 -0400 Subject: [PATCH 20/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20host?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/components/form/host/index.hbs | 77 +++++ ui/core/app/router.js | 7 +- .../scope/host-catalogs/host-catalog/hosts.js | 77 +++++ .../host-catalogs/host-catalog/hosts/host.js | 52 ++++ .../host-catalog/hosts/host/index.js | 4 + .../host-catalogs/host-catalog/hosts/index.js | 4 + .../host-catalogs/host-catalog/hosts/new.js | 51 ++++ .../host-catalogs/host-catalog/-actions.hbs | 2 +- .../host-catalog/-navigation.hbs | 6 +- .../host-catalogs/host-catalog/hosts.hbs | 3 + .../host-catalogs/host-catalog/hosts/host.hbs | 3 + .../host-catalog/hosts/host/-actions.hbs | 9 + .../host-catalog/hosts/host/-header.hbs | 12 + .../host-catalog/hosts/host/-navigation.hbs | 5 + .../host-catalog/hosts/host/index.hbs | 5 + .../host-catalog/hosts/index.hbs | 60 ++++ .../host-catalogs/host-catalog/hosts/new.hbs | 7 + .../host-catalog/hosts/new/-header.hbs | 4 + .../acceptance/host-catalogs/hosts-test.js | 283 ++++++++++++++++++ .../components/form/account-test.js | 23 -- .../components/form/account/password-test.js | 23 -- .../account/password/change-password-test.js | 26 -- .../account/password/set-password-test.js | 26 -- .../components/form/auth-method-test.js | 23 -- .../form/role/add-principals-test.js | 12 - .../components/form/user/add-accounts-test.js | 12 - .../host-catalogs/host-catalog/hosts-test.js | 11 + .../host-catalog/hosts/host-test.js | 11 + .../host-catalog/hosts/host/index-test.js | 11 + .../host-catalog/hosts/index-test.js | 11 + .../host-catalog/hosts/new-test.js | 11 + 31 files changed, 721 insertions(+), 150 deletions(-) create mode 100644 ui/core/app/components/form/host/index.hbs create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/new.js create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-actions.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-navigation.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new/-header.hbs create mode 100644 ui/core/tests/acceptance/host-catalogs/hosts-test.js delete mode 100644 ui/core/tests/integration/components/form/account-test.js delete mode 100644 ui/core/tests/integration/components/form/account/password-test.js delete mode 100644 ui/core/tests/integration/components/form/account/password/change-password-test.js delete mode 100644 ui/core/tests/integration/components/form/account/password/set-password-test.js delete mode 100644 ui/core/tests/integration/components/form/auth-method-test.js delete mode 100644 ui/core/tests/integration/components/form/role/add-principals-test.js delete mode 100644 ui/core/tests/integration/components/form/user/add-accounts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/new-test.js diff --git a/ui/core/app/components/form/host/index.hbs b/ui/core/app/components/form/host/index.hbs new file mode 100644 index 000000000..b5a931880 --- /dev/null +++ b/ui/core/app/components/form/host/index.hbs @@ -0,0 +1,77 @@ + + + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.description}} + + {{#each @model.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/router.js b/ui/core/app/router.js index e3419f5f5..cf7accb4a 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -66,7 +66,12 @@ Router.map(function () { this.route('host-catalogs', function() { this.route('new'); - this.route('host-catalog', { path: ':host_catalog_id' }, function() {}); + this.route('host-catalog', { path: ':host_catalog_id' }, function() { + this.route('hosts', function() { + this.route('new'); + this.route('host', { path: ':host_id' }, function() {}); + }); + }); }); }); }); diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js new file mode 100644 index 000000000..912381a39 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js @@ -0,0 +1,77 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all hosts under the current host catalog and it's parent scope. + * @return {Promise{[HostModel]}} + */ + model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + return this.store.query('host', { host_catalog_id }); + } + + // =actions + + /** + * Rollback changes on a host. + * @param {HostModel} host + */ + @action + cancel(host) { + const { isNew } = host; + host.rollbackAttributes(); + if (isNew) + this.transitionTo( + 'scopes.scope.host-catalogs.host-catalog.hosts' + ); + } + + /** + * Handle save of a host. + * @param {HostModel} host + * @param {Event} e + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') + async save(host) { + await host.save(); + await this.transitionTo( + 'scopes.scope.host-catalogs.host-catalog.hosts.host', + host + ); + this.refresh(); + } + + /** + * Delete host in current scope and redirect to index. + * @param {HostModel} host + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async deleteHost(host) { + await host.destroyRecord(); + await this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.hosts' + ); + this.refresh(); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host.js new file mode 100644 index 000000000..8cbd978a2 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host.js @@ -0,0 +1,52 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsHostRoute extends Route { + // =methods + + /** + * Load a host using current host-catalog and it's parent scope. + * @param {object} params + * @param {string} params.host_id + * @return {HostModel} + */ + async model({ host_id }) { + return this.store.findRecord('host', host_id, { reload: true }); + } + + /** + * Renders the host specific templates for header, navigation, and action page sections. + * @override + * @param {object} controller + * @param {object} model + */ + renderTemplate(controller, model) { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/hosts/host/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/hosts/host/-navigation', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/hosts/host/-actions', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + model: model, + } + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index.js new file mode 100644 index 000000000..8d1674617 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsHostIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/index.js new file mode 100644 index 000000000..931deeb2e --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/new.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/new.js new file mode 100644 index 000000000..e82bfe0e4 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/hosts/new.js @@ -0,0 +1,51 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved host in current host catalog scope. + * @return {HostModel} + */ + model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + return this.store.createRecord('host', { + type: 'static', + host_catalog_id, + }); + } + + /** + * Renders new host specific templates for header, navigation, + * and action page sections. + * @override + * @param {object} controller + * @param {object} model + */ + renderTemplate(controller, model) { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/hosts/new/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + model: model, + } + ); + + this.render('_empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + model: model, + }); + + this.render('_empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + model: model, + }); + } +} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs index 14538798b..2cfb73b07 100644 --- a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs @@ -1,11 +1,11 @@ - {{!-- {{t "resources.host.actions.create"}} + {{!-- {{t 'titles.details'}}
+ + {{t 'resources.host.title_plural'}} + {{!-- {{t 'resources.host-set.title_plural'}} - - {{t 'resources.host.title_plural'}} - --}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts.hbs new file mode 100644 index 000000000..5e74dd528 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.host.title_plural")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host.hbs new file mode 100644 index 000000000..d66e83390 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host.hbs @@ -0,0 +1,3 @@ +{{title @model.displayName}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-actions.hbs new file mode 100644 index 000000000..4c9a91aa3 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-actions.hbs @@ -0,0 +1,9 @@ + + + {{t 'resources.host.actions.delete'}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-header.hbs new file mode 100644 index 000000000..7b15e6f0f --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-header.hbs @@ -0,0 +1,12 @@ +

+ {{t "resources.host.title"}} + +

+

{{t "resources.host.description"}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-navigation.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-navigation.hbs new file mode 100644 index 000000000..157f7472f --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/-navigation.hbs @@ -0,0 +1,5 @@ + + + {{t 'titles.details'}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/index.hbs new file mode 100644 index 000000000..6cc780607 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/host/index.hbs @@ -0,0 +1,5 @@ + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs new file mode 100644 index 000000000..dcf9b3b63 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs @@ -0,0 +1,60 @@ +{{#if @model}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + {{t "form.address.label"}} + + + + {{#each @model as |host|}} + + + + {{host.displayName}} + +

{{host.description}}

+
+ + + {{t (concat 'resources.host.types.' host.type)}} + + + + + {{host.id}} + + + + {{host.attributes.address}} + +
+ {{/each}} +
+
+ +{{else}} + + + + + {{t "resources.host.description"}} + + + + {{t "titles.new"}} + + + + +{{/if}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new.hbs new file mode 100644 index 000000000..2e3ec8149 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new.hbs @@ -0,0 +1,7 @@ +{{title (t 'titles.new')}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new/-header.hbs new file mode 100644 index 000000000..3122f3b43 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/new/-header.hbs @@ -0,0 +1,4 @@ +

+ {{t "titles.new"}} + +

diff --git a/ui/core/tests/acceptance/host-catalogs/hosts-test.js b/ui/core/tests/acceptance/host-catalogs/hosts-test.js new file mode 100644 index 000000000..ba1acae76 --- /dev/null +++ b/ui/core/tests/acceptance/host-catalogs/hosts-test.js @@ -0,0 +1,283 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { resolve, reject } from 'rsvp'; +import sinon from 'sinon'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | host-catalogs | hosts', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let getHostCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + hostCatalog: null, + host: null + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + hostCatalogs: null, + hostCatalog: null, + hosts: null, + host: null, + unknownHost: null, + newHost: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project, + }); + instances.host = this.server.create('host', { + scope: instances.scopes.project, + hostCatalog: instances.hostCatalog + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; + urls.hosts = `${urls.hostCatalog}/hosts`; + urls.host = `${urls.hosts}/${instances.host.id}`; + urls.unknownHost = `${urls.hosts}/foo`; + urls.newHost = `${urls.hosts}/new`; + // Generate resource couner + getHostCount = () => this.server.schema.hosts.all().models.length; + authenticateSession({}); + }); + + test('visiting hosts', async function (assert) { + assert.expect(2); + await visit(urls.hosts); + await a11yAudit(); + assert.equal(currentURL(), urls.hosts); + await visit(urls.host); + await a11yAudit(); + assert.equal(currentURL(), urls.host); + }); + + test('visiting an unknown host displays 404 message', async function (assert) { + assert.expect(1); + await visit(urls.unknownHost); + await a11yAudit(); + assert.ok(find('.rose-message-subtitle').textContent.trim(), 'Error 404'); + }); + + test('can create new host', async function (assert) { + assert.expect(1); + const count = getHostCount(); + await visit(urls.newHost); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(getHostCount(), count + 1); + }); + + test('can cancel create new host', async function (assert) { + assert.expect(2); + const count = getHostCount(); + await visit(urls.newHost); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.hosts); + assert.equal(getHostCount(), count); + }); + + test('saving a new host with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/hosts', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.newHost); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can save changes to existing host', async function (assert) { + assert.expect(3); + assert.notEqual(instances.host.name, 'random string'); + await visit(urls.host); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="submit"]'); + assert.equal(currentURL(), urls.host); + assert.equal(this.server.schema.hosts.all().models[0].name, 'random string'); + }); + + test('can cancel changes to existing host', async function (assert) { + assert.expect(2); + await visit(urls.host); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.notEqual(instances.host.name, 'random string'); + assert.equal(find('[name="name"]').value, instances.host.name); + }); + + test('saving an existing host with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.patch('/hosts/:id', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.host); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can discard unsaved host changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.host.name, 'random string'); + await visit(urls.host); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.host); + try { + await visit(urls.hosts); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:first-child'); + assert.equal(currentURL(), urls.hosts); + assert.notEqual(this.server.schema.hosts.all().models[0].name, 'random string'); + } + }); + + test('can cancel discard unsaved host changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.host.name, 'random string'); + await visit(urls.host); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.host); + try { + await visit(urls.hosts); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:last-child'); + assert.equal(currentURL(), urls.host); + assert.notEqual(this.server.schema.hosts.all().models[0].name, 'random string'); + } + }); + + test('can delete host', async function (assert) { + assert.expect(1); + const count = getHostCount(); + await visit(urls.host); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count - 1); + }); + + test('can accept delete host via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(resolve()); + const count = getHostCount(); + await visit(urls.host); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count - 1); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('cannot cancel delete host via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(reject()); + const count = getHostCount(); + await visit(urls.host); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('deleting a host which errors displays error messages', async function (assert) { + assert.expect(1); + this.server.del('/hosts/:id', () => { + return new Response( + 490, + {}, + { + status: 490, + code: 'error', + message: 'Oops.', + } + ); + }); + await visit(urls.host); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); + }); + +}); diff --git a/ui/core/tests/integration/components/form/account-test.js b/ui/core/tests/integration/components/form/account-test.js deleted file mode 100644 index 5fc184035..000000000 --- a/ui/core/tests/integration/components/form/account-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/account/index', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - this.submit = () => {}; - this.cancel = () => {}; - this.model = { type: 'password' }; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/account/password-test.js b/ui/core/tests/integration/components/form/account/password-test.js deleted file mode 100644 index 3ac6bf4ed..000000000 --- a/ui/core/tests/integration/components/form/account/password-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/account/password', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - this.submit = () => {}; - this.cancel = () => {}; - this.model = { type: 'password' }; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/account/password/change-password-test.js b/ui/core/tests/integration/components/form/account/password/change-password-test.js deleted file mode 100644 index 54a6f61dd..000000000 --- a/ui/core/tests/integration/components/form/account/password/change-password-test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module( - 'Integration | Component | form/account/password/change-password', - function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - this.submit = () => {}; - this.cancel = () => {}; - this.model = { type: 'password' }; - - await render(hbs` - `); - - assert.ok(find('form')); - }); - } -); diff --git a/ui/core/tests/integration/components/form/account/password/set-password-test.js b/ui/core/tests/integration/components/form/account/password/set-password-test.js deleted file mode 100644 index ae4e1d355..000000000 --- a/ui/core/tests/integration/components/form/account/password/set-password-test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module( - 'Integration | Component | form/account/password/set-password', - function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - this.submit = () => {}; - this.cancel = () => {}; - this.model = { type: 'password' }; - - await render(hbs` - `); - - assert.ok(find('form')); - }); - } -); diff --git a/ui/core/tests/integration/components/form/auth-method-test.js b/ui/core/tests/integration/components/form/auth-method-test.js deleted file mode 100644 index 267e516b5..000000000 --- a/ui/core/tests/integration/components/form/auth-method-test.js +++ /dev/null @@ -1,23 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/auth-method', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - this.submit = () => {}; - this.cancel = () => {}; - this.model = { type: 'password' }; - - await render(hbs` - `); - - assert.ok(find('form')); - }); -}); diff --git a/ui/core/tests/integration/components/form/role/add-principals-test.js b/ui/core/tests/integration/components/form/role/add-principals-test.js deleted file mode 100644 index 4b6ed6a3d..000000000 --- a/ui/core/tests/integration/components/form/role/add-principals-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -// import { render } from '@ember/test-helpers'; -// import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/role/add-principals', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - assert.expect(0); - }); -}); diff --git a/ui/core/tests/integration/components/form/user/add-accounts-test.js b/ui/core/tests/integration/components/form/user/add-accounts-test.js deleted file mode 100644 index ba96e4dba..000000000 --- a/ui/core/tests/integration/components/form/user/add-accounts-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -// import { render } from '@ember/test-helpers'; -// import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | form/user/add-accounts', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function(assert) { - assert.expect(0); - }); -}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts-test.js new file mode 100644 index 000000000..7c2891d51 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/hosts', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/hosts'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js new file mode 100644 index 000000000..d40fb98a9 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/hosts/host', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/hosts/host'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index-test.js new file mode 100644 index 000000000..1f6b2379b --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/host/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/hosts/host/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/hosts/host/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/index-test.js new file mode 100644 index 000000000..5bccae028 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/hosts/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/hosts/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/new-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/new-test.js new file mode 100644 index 000000000..e7d31cca4 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/hosts/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/hosts/new', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/hosts/new'); + assert.ok(route); + }); +}); From d01e0912ad47559386b8bf23410628ab8a9e98e6 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 11:09:04 -0400 Subject: [PATCH 21/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20host?= =?UTF-8?q?=20sets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/components/form/host-set/index.hbs | 59 ++++ ui/core/app/router.js | 4 + .../host-catalogs/host-catalog/host-sets.js | 76 +++++ .../host-catalog/host-sets/host-set.js | 52 ++++ .../host-catalog/host-sets/host-set/index.js | 4 + .../host-catalog/host-sets/index.js | 4 + .../host-catalog/host-sets/new.js | 50 ++++ .../host-catalogs/host-catalog/-actions.hbs | 2 - .../host-catalog/-navigation.hbs | 2 - .../host-catalogs/host-catalog/host-sets.hbs | 3 + .../host-catalog/host-sets/host-set.hbs | 3 + .../host-sets/host-set/-actions.hbs | 18 ++ .../host-sets/host-set/-header.hbs | 12 + .../host-sets/host-set/-navigation.hbs | 10 + .../host-catalog/host-sets/host-set/index.hbs | 5 + .../host-catalog/host-sets/index.hbs | 56 ++++ .../host-catalog/host-sets/new.hbs | 7 + .../host-catalog/host-sets/new/-header.hbs | 4 + .../host-catalogs/host-sets-test.js | 283 ++++++++++++++++++ .../host-catalog/host-sets-test.js | 11 + .../host-catalog/host-sets/host-set-test.js | 11 + .../host-sets/host-set/index-test.js | 11 + .../host-catalog/host-sets/index-test.js | 11 + .../host-catalog/host-sets/new-test.js | 11 + 24 files changed, 705 insertions(+), 4 deletions(-) create mode 100644 ui/core/app/components/form/host-set/index.hbs create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new.js create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new/-header.hbs create mode 100644 ui/core/tests/acceptance/host-catalogs/host-sets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new-test.js diff --git a/ui/core/app/components/form/host-set/index.hbs b/ui/core/app/components/form/host-set/index.hbs new file mode 100644 index 000000000..d457ad0e7 --- /dev/null +++ b/ui/core/app/components/form/host-set/index.hbs @@ -0,0 +1,59 @@ + + + + + + {{#if @model.errors.name}} + + {{#each @model.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.errors.description}} + + {{#each @model.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/router.js b/ui/core/app/router.js index cf7accb4a..ebed78060 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -71,6 +71,10 @@ Router.map(function () { this.route('new'); this.route('host', { path: ':host_id' }, function() {}); }); + this.route('host-sets', function() { + this.route('new'); + this.route('host-set', { path: ':host_set_id' }, function() {}); + }); }); }); }); diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js new file mode 100644 index 000000000..e3cbc969c --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js @@ -0,0 +1,76 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all host-sets under the current host catalog and it's parent scope. + * @return {Promise{[HostSetModel]}} + */ + model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + return this.store.query('host-set', { host_catalog_id }); + } + + // =actions + + /** + * Rollback changes on a host set. + * @param {HostSetModel} hostSet + */ + @action + cancel(hostSet) { + const { isNew } = hostSet; + hostSet.rollbackAttributes(); + if (isNew) + this.transitionTo( + 'scopes.scope.host-catalogs.host-catalog.host-sets' + ); + } + + /** + * Handle save of a host set. + * @param {HostSetModel} hostSet + * @param {Event} e + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => isNew ? 'notifications.create-success' : 'notifications.save-success') + async save(hostSet) { + await hostSet.save(); + await this.transitionTo( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set', + hostSet + ); + this.refresh(); + } + + /** + * Delete host set in current scope and redirect to index. + * @param {HostSetModel} hostSet + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async deleteHostSet(hostSet) { + await hostSet.destroyRecord(); + await this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.host-sets' + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js new file mode 100644 index 000000000..31339c0dc --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js @@ -0,0 +1,52 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute extends Route { + // =methods + + /** + * Load a host-set using current host-catalog and its parent scope. + * @param {object} params + * @param {string} params.host_set_id + * @return {HostSetModel} + */ + async model({ host_set_id }) { + return this.store.findRecord('host-set', host_set_id, { reload: true }); + } + + /** + * Renders the host-set specific templates for header, navigation, and action page sections. + * @override + * @param {object} controller + * @param {object} model + */ + renderTemplate(controller, model) { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-navigation', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + model: model, + } + ); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + model: model, + } + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.js new file mode 100644 index 000000000..48e4b444d --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index.js new file mode 100644 index 000000000..3af22321c --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsIndexRoute extends Route { +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new.js new file mode 100644 index 000000000..3980cf51b --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new.js @@ -0,0 +1,50 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsNewRoute extends Route { + // =methods + + /** + * Creates a new unsaved host set in current host catalog scope. + * @return {HostSetModel} + */ + model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + return this.store.createRecord('host-set', { + type: 'static', + host_catalog_id, + }); + } + + /** + * Renders new host-set specific templates for header, navigation, and action page sections. + * @override + * @param {object} controller + * @param {object} model + */ + renderTemplate(controller, model) { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/new/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + model: model, + } + ); + + this.render('_empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + model: model, + }); + + this.render('_empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + model: model, + }); + } +} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs index 2cfb73b07..1e65e6dc7 100644 --- a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/-actions.hbs @@ -5,14 +5,12 @@ > {{t "resources.host.actions.create"}} - {{!-- {{t "resources.host-set.actions.create"}} - --}} {{t 'resources.host.title_plural'}}
- {{!-- {{t 'resources.host-set.title_plural'}} - --}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets.hbs new file mode 100644 index 000000000..031f2510b --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets.hbs @@ -0,0 +1,3 @@ +{{title (t "resources.host-set.title_plural")}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.hbs new file mode 100644 index 000000000..d66e83390 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.hbs @@ -0,0 +1,3 @@ +{{title @model.displayName}} + +{{outlet}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs new file mode 100644 index 000000000..b49a0dd51 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs @@ -0,0 +1,18 @@ + + {{!-- + + {{t 'resources.host-set.actions.create-host'}} + + + {{t 'resources.host-set.actions.add-hosts'}} + + --}} + + + {{t 'resources.host-set.actions.delete'}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-header.hbs new file mode 100644 index 000000000..a101b0a8a --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-header.hbs @@ -0,0 +1,12 @@ +

+ {{t "resources.host-set.title"}} + +

+

{{t "resources.host-set.description"}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs new file mode 100644 index 000000000..656b39947 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-navigation.hbs @@ -0,0 +1,10 @@ + + + {{t 'titles.details'}} + + {{!-- + + {{t 'resources.host.title_plural'}} + + --}} + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.hbs new file mode 100644 index 000000000..ac0b64897 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index.hbs @@ -0,0 +1,5 @@ + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs new file mode 100644 index 000000000..d4cb8ca74 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs @@ -0,0 +1,56 @@ +{{#if @model}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + + + + {{#each @model as |hostSet|}} + + + + {{hostSet.displayName}} + +

{{hostSet.description}}

+
+ + + {{t (concat 'resources.host-set.types.' hostSet.type)}} + + + + + {{hostSet.id}} + + +
+ {{/each}} +
+
+ +{{else}} + + + + + {{t "resources.host-set.description"}} + + + + {{t "titles.new"}} + + + + +{{/if}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new.hbs new file mode 100644 index 000000000..bd5a0338c --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new.hbs @@ -0,0 +1,7 @@ +{{title (t 'titles.new')}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new/-header.hbs new file mode 100644 index 000000000..38ae01334 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/new/-header.hbs @@ -0,0 +1,4 @@ +

+ {{t "titles.new"}} + +

diff --git a/ui/core/tests/acceptance/host-catalogs/host-sets-test.js b/ui/core/tests/acceptance/host-catalogs/host-sets-test.js new file mode 100644 index 000000000..7f575a500 --- /dev/null +++ b/ui/core/tests/acceptance/host-catalogs/host-sets-test.js @@ -0,0 +1,283 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { resolve, reject } from 'rsvp'; +import sinon from 'sinon'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | host-catalogs | host sets', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let getHostCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + hostCatalog: null, + host: null + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + hostCatalogs: null, + hostCatalog: null, + hostSets: null, + hostSet: null, + unknownHostSet: null, + newHostSet: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project, + }); + instances.hostSet = this.server.create('host-set', { + scope: instances.scopes.project, + hostCatalog: instances.hostCatalog + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; + urls.hostSets = `${urls.hostCatalog}/host-sets`; + urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`; + urls.unknownHostSet = `${urls.hostSets}/foo`; + urls.newHostSet = `${urls.hostSets}/new`; + // Generate resource couner + getHostCount = () => this.server.schema.hostSets.all().models.length; + authenticateSession({}); + }); + + test('visiting host sets', async function (assert) { + assert.expect(2); + await visit(urls.hostSets); + await a11yAudit(); + assert.equal(currentURL(), urls.hostSets); + await visit(urls.hostSet); + await a11yAudit(); + assert.equal(currentURL(), urls.hostSet); + }); + + test('visiting an unknown host set displays 404 message', async function (assert) { + assert.expect(1); + await visit(urls.unknownHostSet); + await a11yAudit(); + assert.ok(find('.rose-message-subtitle').textContent.trim(), 'Error 404'); + }); + + test('can create new host', async function (assert) { + assert.expect(1); + const count = getHostCount(); + await visit(urls.newHostSet); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.equal(getHostCount(), count + 1); + }); + + test('can cancel create new host', async function (assert) { + assert.expect(2); + const count = getHostCount(); + await visit(urls.newHostSet); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.equal(currentURL(), urls.hostSets); + assert.equal(getHostCount(), count); + }); + + test('saving a new host set with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/host-sets', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.newHostSet); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can save changes to existing host', async function (assert) { + assert.expect(3); + assert.notEqual(instances.hostSet.name, 'random string'); + await visit(urls.hostSet); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="submit"]'); + assert.equal(currentURL(), urls.hostSet); + assert.equal(this.server.schema.hostSets.all().models[0].name, 'random string'); + }); + + test('can cancel changes to existing host', async function (assert) { + assert.expect(2); + await visit(urls.hostSet); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('.rose-form-actions [type="button"]'); + assert.notEqual(instances.hostSet.name, 'random string'); + assert.equal(find('[name="name"]').value, instances.hostSet.name); + }); + + test('saving an existing host set with invalid fields displays error messages', async function (assert) { + assert.expect(2); + this.server.patch('/host-sets/:id', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: { + request_fields: [ + { + name: 'name', + description: 'Name is required.', + }, + ], + }, + } + ); + }); + await visit(urls.hostSet); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + await click('[type="submit"]'); + assert.ok(find('[role="alert"]').textContent.trim(), 'The request was invalid.'); + assert.ok( + find('.rose-form-error-message').textContent.trim(), + 'Name is required.' + ); + }); + + test('can discard unsaved host set changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.hostSet.name, 'random string'); + await visit(urls.hostSet); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.hostSet); + try { + await visit(urls.hostSets); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:first-child'); + assert.equal(currentURL(), urls.hostSets); + assert.notEqual(this.server.schema.hostSets.all().models[0].name, 'random string'); + } + }); + + test('can cancel discard unsaved host set changes via dialog', async function (assert) { + assert.expect(5); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + assert.notEqual(instances.hostSet.name, 'random string'); + await visit(urls.hostSet); + await click('form [type="button"]', 'Activate edit mode'); + await fillIn('[name="name"]', 'random string'); + assert.equal(currentURL(), urls.hostSet); + try { + await visit(urls.hostSets); + } catch (e) { + assert.ok(find('.rose-dialog')); + await click('.rose-dialog-footer button:last-child'); + assert.equal(currentURL(), urls.hostSet); + assert.notEqual(this.server.schema.hostSets.all().models[0].name, 'random string'); + } + }); + + test('can delete host', async function (assert) { + assert.expect(1); + const count = getHostCount(); + await visit(urls.hostSet); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count - 1); + }); + + test('can accept delete host set via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(resolve()); + const count = getHostCount(); + await visit(urls.hostSet); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count - 1); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('cannot cancel delete host set via dialog', async function (assert) { + assert.expect(2); + const confirmService = this.owner.lookup('service:confirm'); + confirmService.enabled = true; + confirmService.confirm = sinon.fake.returns(reject()); + const count = getHostCount(); + await visit(urls.hostSet); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.equal(getHostCount(), count); + assert.ok(confirmService.confirm.calledOnce); + }); + + test('deleting a host set which errors displays error messages', async function (assert) { + assert.expect(1); + this.server.del('/host-sets/:id', () => { + return new Response( + 490, + {}, + { + status: 490, + code: 'error', + message: 'Oops.', + } + ); + }); + await visit(urls.hostSet); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); + }); + +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets-test.js new file mode 100644 index 000000000..8178e1810 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js new file mode 100644 index 000000000..56f46755c --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/host-set', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/host-set'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index-test.js new file mode 100644 index 000000000..f2c55644a --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index-test.js new file mode 100644 index 000000000..c158018f5 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/index', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/index'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new-test.js new file mode 100644 index 000000000..3216994c2 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/new-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/new', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/new'); + assert.ok(route); + }); +}); From 9aafbc58a7937fce9420735c3b93968f0f08dcc5 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 11:50:14 -0400 Subject: [PATCH 22/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20reintroduce=20host?= =?UTF-8?q?=20set=20hosts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/host-set/add-hosts/index.hbs | 56 ++++ .../form/host-set/add-hosts/index.js | 57 +++++ ui/core/app/router.js | 6 +- .../host-sets/host-set/add-hosts.js | 92 +++++++ .../host-sets/host-set/create-and-add-host.js | 85 +++++++ .../host-catalog/host-sets/host-set/hosts.js | 55 ++++ .../host-sets/host-set/-actions.hbs | 6 +- .../host-sets/host-set/-navigation.hbs | 2 - .../host-sets/host-set/add-hosts.hbs | 8 + .../host-sets/host-set/add-hosts/-header.hbs | 5 + .../host-set/create-and-add-host.hbs | 7 + .../host-set/create-and-add-host/-header.hbs | 4 + .../host-catalog/host-sets/host-set/hosts.hbs | 73 ++++++ .../host-catalogs/host-sets-test.js | 24 +- .../host-catalogs/host-sets/hosts-test.js | 240 ++++++++++++++++++ .../host-sets/host-set/add-hosts-test.js | 11 + .../host-set/create-and-add-host-test.js | 11 + .../host-sets/host-set/hosts-test.js | 11 + ui/core/translations/resources/en-us.yaml | 2 +- 19 files changed, 735 insertions(+), 20 deletions(-) create mode 100644 ui/core/app/components/form/host-set/add-hosts/index.hbs create mode 100644 ui/core/app/components/form/host-set/add-hosts/index.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js create mode 100644 ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs create mode 100644 ui/core/tests/acceptance/host-catalogs/host-sets/hosts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js diff --git a/ui/core/app/components/form/host-set/add-hosts/index.hbs b/ui/core/app/components/form/host-set/add-hosts/index.hbs new file mode 100644 index 000000000..1d467c2ef --- /dev/null +++ b/ui/core/app/components/form/host-set/add-hosts/index.hbs @@ -0,0 +1,56 @@ +{{#if this.hasAvailableHosts}} + + + + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + + + + {{#each this.filteredHosts as |host|}} + + + + + {{host.name}} + + {{host.type}} + + + {{/each}} + + + + +{{/if}} + +{{#unless this.hasAvailableHosts}} + + + + {{t "resources.host-set.host.messages.add-none.description"}} + + + + {{t "actions.back"}} + + + +{{/unless}} diff --git a/ui/core/app/components/form/host-set/add-hosts/index.js b/ui/core/app/components/form/host-set/add-hosts/index.js new file mode 100644 index 000000000..4f1a8eb22 --- /dev/null +++ b/ui/core/app/components/form/host-set/add-hosts/index.js @@ -0,0 +1,57 @@ +import Component from '@glimmer/component'; +import { computed, action } from '@ember/object'; +import { A } from '@ember/array'; + +export default class FormHostSetAddHostsIndexComponent extends Component { + // =properties + + /** + * Array of selected host IDs. + * @type {EmberArray} + */ + selectedHostIDs = A(); + + /** + * Checks for unassigned hosts. + * @param {[HostModel]} filteredHosts + * @type {boolean} + */ + @computed('filteredHosts.length') + get hasAvailableHosts() { + return this.filteredHosts.length > 0; + } + + /** + * Hosts currently not assigned to current host set. + * @type {[HostModel]} + */ + @computed('args.{model,model.host_ids,hosts}') + get filteredHosts() { + const currentHostIDs = this.args.model.host_ids.map((host) => host.value); + return this.args.hosts.filter(({ id }) => !currentHostIDs.includes(id)); + } + + // =actions + + /** + * Toggle host selection + * @param {HostModel} host + */ + @action + toggleHost(host) { + if (!this.selectedHostIDs.includes(host.id)) { + this.selectedHostIDs.addObject(host.id); + } else { + this.selectedHostIDs.removeObject(host.id); + } + } + + /** + * Callback submit with selected host ids + * @param {requestCallback} fn + */ + @action + submit(fn) { + fn(this.selectedHostIDs); + } +} diff --git a/ui/core/app/router.js b/ui/core/app/router.js index ebed78060..30e882b22 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -73,7 +73,11 @@ Router.map(function () { }); this.route('host-sets', function() { this.route('new'); - this.route('host-set', { path: ':host_set_id' }, function() {}); + this.route('host-set', { path: ':host_set_id' }, function() { + this.route('hosts'); + this.route('add-hosts'); + this.route('create-and-add-host'); + }); }); }); }); diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js new file mode 100644 index 000000000..afe7ce613 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js @@ -0,0 +1,92 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { hash } from 'rsvp'; +import loading from 'ember-loading/decorator'; +import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetAddHostsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Empty out any previously loaded hosts. + */ + beforeModel() { + this.store.unloadAll('host'); + } + + /** + * Loads current host set and all hosts under the current host catalog. + * @return {Promise{HostSetModel,[HostModel]}} + */ + async model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + return hash({ + hostSet: this.modelFor( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set' + ), + hosts: this.store.query('host', { host_catalog_id }), + }); + } + + /** + * Renders the add-hosts-specific header template. + * Empties the actions and navigation outlets and renders a custom empty header. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + } + ); + + this.render('-empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + }); + + this.render('-empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + }); + } + + // =actions + + /** + * Saves host IDs on the host set. + * @param {HostSetModel} hostSet + */ + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async addHosts(hostSet, hostIDs) { + await hostSet.addHosts(hostIDs); + await this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } + + /** + * Redirect to hosts as if nothing ever happened. + */ + @action + cancel() { + this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js new file mode 100644 index 000000000..a726302f2 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js @@ -0,0 +1,85 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetCreateAndAddHostRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Creates a new unsaved host in current host catalog scope. + * @return {Promise{HostSetModel,HostModel}} + */ + async model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ); + + return this.store.createRecord('host', { + type: 'static', + host_catalog_id, + }); + } + + /** + * Renders the create host-specific header template. + * Empties the actions and navigation outlets and renders a custom empty header. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host/-header', + { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'header', + } + ); + + this.render('-empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'navigation', + }); + + this.render('-empty', { + into: 'scopes/scope/host-catalogs/host-catalog', + outlet: 'actions', + }); + } + + // =actions + + /** + * Saves host and add it to current host set. + * @param {HostSetModel,HostModel} model + */ + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(host) { + const hostSet = this.modelFor('scopes.scope.host-catalogs.host-catalog.host-sets.host-set'); + await host.save(); + await hostSet.addHost(host.id); + await this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } + + /** + * Redirect to hosts in host set as if nothing ever happened. + */ + @action + cancel() { + this.replaceWith( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } +} diff --git a/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js new file mode 100644 index 000000000..32c5b8911 --- /dev/null +++ b/ui/core/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js @@ -0,0 +1,55 @@ +import Route from '@ember/routing/route'; +import { hash, all } from 'rsvp'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import loading from 'ember-loading/decorator'; +import { confirm } from '../../../../../../../decorators/confirm'; +import { notifySuccess, notifyError } from '../../../../../../../decorators/notify'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetHostsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Loads all hosts under the current host set. + * @return {Promise{HostSetModel,[HostModel]}} + */ + async model() { + const hostSet = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set' + ); + return hash({ + hostSet, + hosts: all( + hostSet.host_ids.map((host) => + this.store.findRecord('host', host.value, { reload: true }) + ) + ), + }); + } + + /** + * Remove a host from the current host set and redirect to hosts index. + * @param {HostSetModel} hostSet + * @param {HostModel} host + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeHost(hostSet, host) { + const scopeID = this.modelFor('scopes.scope').id; + const hostCatalogID = this.modelFor( + 'scopes.scope.host-catalogs.host-catalog' + ).id; + await hostSet.removeHost(host.id, { + adapterOptions: { scopeID, hostCatalogID }, + }); + this.refresh(); + } +} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs index b49a0dd51..7eccc7b44 100644 --- a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs @@ -1,12 +1,10 @@ - {{!-- - - {{t 'resources.host-set.actions.create-host'}} + + {{t 'resources.host-set.actions.create-and-add-host'}} {{t 'resources.host-set.actions.add-hosts'}} - --}} {{t 'titles.details'}}
- {{!-- {{t 'resources.host.title_plural'}} - --}} diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs new file mode 100644 index 000000000..b185f9550 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.hbs @@ -0,0 +1,8 @@ +{{title (t "resources.host-set.actions.add-hosts")}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs new file mode 100644 index 000000000..6ff650141 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts/-header.hbs @@ -0,0 +1,5 @@ +

+ {{t "resources.host-set.host.messages.add.title"}} + +

+

{{t "resources.host-set.host.messages.add.description"}}

diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.hbs new file mode 100644 index 000000000..3e7ed3f29 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.hbs @@ -0,0 +1,7 @@ +{{title (t 'resources.host-set.actions.create-and-add-host')}} + + diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host/-header.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host/-header.hbs new file mode 100644 index 000000000..ee94f8ff0 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host/-header.hbs @@ -0,0 +1,4 @@ +

+ {{t "resources.host-set.actions.create-and-add-host"}} + +

diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs new file mode 100644 index 000000000..d2ede5ddc --- /dev/null +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -0,0 +1,73 @@ +{{#if @model.hosts}} + + + + + {{t "form.name.label"}} + {{t "form.type.label"}} + {{t "form.id.label"}} + {{t "titles.actions"}} + + + + {{#each @model.hosts as |host|}} + + + + {{host.displayName}} + +

{{host.description}}

+
+ + {{host.type}} + + + + {{host.id}} + + + + + + {{t "actions.remove"}} + + + +
+ {{/each}} +
+
+ +{{/if}} + +{{#unless @model.hosts}} + + + + {{t "resources.host-set.host.messages.none.description"}} + + {{!-- + + + {{t "resources.host-set.actions.create-and-add-host"}} + + --}} + + +{{/unless}} diff --git a/ui/core/tests/acceptance/host-catalogs/host-sets-test.js b/ui/core/tests/acceptance/host-catalogs/host-sets-test.js index 7f575a500..aee192343 100644 --- a/ui/core/tests/acceptance/host-catalogs/host-sets-test.js +++ b/ui/core/tests/acceptance/host-catalogs/host-sets-test.js @@ -17,7 +17,7 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); - let getHostCount; + let getHostSetCount; const instances = { scopes: { @@ -69,7 +69,7 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { urls.unknownHostSet = `${urls.hostSets}/foo`; urls.newHostSet = `${urls.hostSets}/new`; // Generate resource couner - getHostCount = () => this.server.schema.hostSets.all().models.length; + getHostSetCount = () => this.server.schema.hostSets.all().models.length; authenticateSession({}); }); @@ -92,21 +92,21 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { test('can create new host', async function (assert) { assert.expect(1); - const count = getHostCount(); + const count = getHostSetCount(); await visit(urls.newHostSet); await fillIn('[name="name"]', 'random string'); await click('[type="submit"]'); - assert.equal(getHostCount(), count + 1); + assert.equal(getHostSetCount(), count + 1); }); test('can cancel create new host', async function (assert) { assert.expect(2); - const count = getHostCount(); + const count = getHostSetCount(); await visit(urls.newHostSet); await fillIn('[name="name"]', 'random string'); await click('.rose-form-actions [type="button"]'); assert.equal(currentURL(), urls.hostSets); - assert.equal(getHostCount(), count); + assert.equal(getHostSetCount(), count); }); test('saving a new host set with invalid fields displays error messages', async function (assert) { @@ -232,10 +232,10 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { test('can delete host', async function (assert) { assert.expect(1); - const count = getHostCount(); + const count = getHostSetCount(); await visit(urls.hostSet); await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getHostCount(), count - 1); + assert.equal(getHostSetCount(), count - 1); }); test('can accept delete host set via dialog', async function (assert) { @@ -243,10 +243,10 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { const confirmService = this.owner.lookup('service:confirm'); confirmService.enabled = true; confirmService.confirm = sinon.fake.returns(resolve()); - const count = getHostCount(); + const count = getHostSetCount(); await visit(urls.hostSet); await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getHostCount(), count - 1); + assert.equal(getHostSetCount(), count - 1); assert.ok(confirmService.confirm.calledOnce); }); @@ -255,10 +255,10 @@ module('Acceptance | host-catalogs | host sets', function (hooks) { const confirmService = this.owner.lookup('service:confirm'); confirmService.enabled = true; confirmService.confirm = sinon.fake.returns(reject()); - const count = getHostCount(); + const count = getHostSetCount(); await visit(urls.hostSet); await click('.rose-layout-page-actions .rose-dropdown-button-danger'); - assert.equal(getHostCount(), count); + assert.equal(getHostSetCount(), count); assert.ok(confirmService.confirm.calledOnce); }); diff --git a/ui/core/tests/acceptance/host-catalogs/host-sets/hosts-test.js b/ui/core/tests/acceptance/host-catalogs/host-sets/hosts-test.js new file mode 100644 index 000000000..224b479b4 --- /dev/null +++ b/ui/core/tests/acceptance/host-catalogs/host-sets/hosts-test.js @@ -0,0 +1,240 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, click, find, findAll, fillIn } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | host-catalogs | host-sets | hosts', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let getHostSetHostCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + hostCatalog: null, + host: null + } + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + hostCatalogs: null, + hostCatalog: null, + hostSets: null, + hostSet: null, + hostSetHosts: null, + addHosts: null, + newHost: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project, + }, 'withChildren'); + instances.hostSet = this.server.schema.hostSets.all().models[0]; + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; + urls.hostSets = `${urls.hostCatalog}/host-sets`; + urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`; + urls.hostSetHosts = `${urls.hostSet}/hosts`; + urls.addHosts = `${urls.hostSet}/add-hosts`; + urls.createAndAddHost = `${urls.hostSet}/create-and-add-host`; + // Generate resource couner + getHostSetHostCount = () => + this.server.schema.hostSets.all().models[0].hosts.length; + authenticateSession({}); + }); + + test('visiting host set hosts', async function (assert) { + assert.expect(2); + await visit(urls.hostSetHosts); + await a11yAudit(); + assert.equal(currentURL(), urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, getHostSetHostCount()); + }); + + test('can remove a host', async function (assert) { + assert.expect(2); + const count = getHostSetHostCount(); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, count); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, count - 1); + }); + + test('shows error message on host remove error', async function (assert) { + assert.expect(2); + this.server.post('/host-sets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, getHostSetHostCount()); + await click('tbody tr .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]')); + }); + + test('visiting add hosts', async function(assert) { + assert.expect(1); + await visit(urls.addHosts); + await a11yAudit(); + assert.equal(currentURL(), urls.addHosts); + }); + + test('select and save hosts to add', async function (assert) { + assert.expect(3); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, 0); + await click('.rose-layout-page-actions a:nth-child(2)') + assert.equal(currentURL(), urls.addHosts); + // Click three times to select, unselect, then reselect (for coverage) + await click('tbody label'); + await click('tbody label'); + await click('tbody label'); + await click('form [type="submit"]'); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, 1); + }); + + test('select and cancel hosts to add', async function (assert) { + assert.expect(4); + const count = getHostSetHostCount(); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, count); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, count - 1); + await click('.rose-layout-page-actions a:nth-child(2)') + assert.equal(currentURL(), urls.addHosts); + await click('tbody label'); + await click('form [type="button"]'); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, count - 1); + }); + + test('shows error message on host add error', async function (assert) { + assert.expect(1); + this.server.post('/host-sets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.addHosts); + await click('tbody label'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); + + test('visiting host creation from a host set', async function (assert) { + assert.expect(1); + await visit(urls.createAndAddHost); + await a11yAudit(); + assert.equal(currentURL(), urls.createAndAddHost); + }); + + test('create and add host to host set', async function (assert) { + assert.expect(3); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.hostSet); + assert.equal(findAll('tbody tr').length, 0); + await click('.rose-layout-page-actions a:nth-child(1)') + assert.equal(currentURL(), urls.createAndAddHost); + await fillIn('[name="name"]', 'Test Name'); + await fillIn('[name="description"]', 'description'); + await click('form [type="submit"]:not(:disabled)'); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, 1); + }); + + test('create and cancel host add to host set', async function (assert) { + assert.expect(1); + await visit(urls.createAndAddHost); + await click('form [type="button"]'); + assert.equal(currentURL(), urls.hostSetHosts); + }); + + test('shows error message on host creation error', async function (assert) { + assert.expect(1); + this.server.post('/hosts', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.createAndAddHost); + await fillIn('[name="name"]', 'New Host'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); + + test('shows error message on host addition to host set error', async function (assert) { + assert.expect(1); + this.server.post('/host-sets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.createAndAddHost); + await fillIn('[name="name"]', 'New Host'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); + +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js new file mode 100644 index 000000000..cfcfcffdb --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js new file mode 100644 index 000000000..9c8d8b120 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host'); + assert.ok(route); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js new file mode 100644 index 000000000..728788fe7 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts'); + assert.ok(route); + }); +}); diff --git a/ui/core/translations/resources/en-us.yaml b/ui/core/translations/resources/en-us.yaml index b753327bc..e24600300 100644 --- a/ui/core/translations/resources/en-us.yaml +++ b/ui/core/translations/resources/en-us.yaml @@ -67,7 +67,7 @@ host-set: add: Add Host Set create: New Host Set delete: Delete Host Set - create-host: Create and Add Host + create-and-add-host: Create and Add Host add-hosts: Add Existing Host messages: welcome: From f57130149c1308e53628ba71b60bfaf10612ec5f Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 12:30:18 -0400 Subject: [PATCH 23/27] chore: tweak page titles --- ui/core/app/templates/scopes/scope.hbs | 12 ++++++++++++ ui/core/app/templates/scopes/scope/scopes.hbs | 9 --------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index ba8eeda68..0e7de3048 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -1,3 +1,15 @@ +{{#if @model.isOrg}} + {{title (t "resources.org.title_plural") }} + {{title @model.displayName}} +{{/if}} + +{{#if @model.isProject}} + {{title (t "resources.org.title_plural") }} + {{title this.scopes.selectedOrg.displayName}} + {{title (t "resources.project.title_plural") }} + {{title @model.displayName}} +{{/if}} + {{#if this.session.isAuthenticated}} diff --git a/ui/core/app/templates/scopes/scope/scopes.hbs b/ui/core/app/templates/scopes/scope/scopes.hbs index c1cefb761..ef0177922 100644 --- a/ui/core/app/templates/scopes/scope/scopes.hbs +++ b/ui/core/app/templates/scopes/scope/scopes.hbs @@ -3,16 +3,7 @@ {{/if}} {{#if @model.currentScope.isOrg}} - {{title (t "resources.org.title_plural") }} - {{title @model.currentScope.displayName}} {{title (t "resources.project.title_plural") }} {{/if}} -{{#if @model.currentScope.isProject}} - {{title (t "resources.org.title_plural") }} - {{title @model.parentScope.displayName}} - {{title (t "resources.project.title_plural") }} - {{title @model.currentScope.displayName}} -{{/if}} - {{outlet}} From ac5a47c51dd964a6aa3007c6327b3189d8d814a5 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 12:33:32 -0400 Subject: [PATCH 24/27] chore: add missing host set hosts page title --- .../host-catalogs/host-catalog/host-sets/host-set/hosts.hbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs index d2ede5ddc..8eacc846b 100644 --- a/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ b/ui/core/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -1,3 +1,5 @@ +{{title (t "resources.host.title_plural")}} + {{#if @model.hosts}} From 5b8e5281740fd7d9d1ae32124efd270c2c8c8496 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 13:04:07 -0400 Subject: [PATCH 25/27] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20missing=20b?= =?UTF-8?q?readcrumbs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accounts/account/set-password.js | 18 ++++++++++++++++++ .../scopes/scope/groups/group/members.js | 18 ++++++++++++++++++ .../controllers/scopes/scope/host-catalogs.js | 18 ++++++++++++++++++ .../scopes/scope/host-catalogs/host-catalog.js | 13 +++++++++++++ .../host-catalogs/host-catalog/host-sets.js | 18 ++++++++++++++++++ .../host-catalog/host-sets/host-set.js | 13 +++++++++++++ .../host-sets/host-set/add-hosts.js | 18 ++++++++++++++++++ .../host-sets/host-set/create-and-add-host.js | 18 ++++++++++++++++++ .../host-catalog/host-sets/host-set/hosts.js | 18 ++++++++++++++++++ .../scope/host-catalogs/host-catalog/hosts.js | 18 ++++++++++++++++++ .../host-catalogs/host-catalog/hosts/host.js | 13 +++++++++++++ .../scopes/scope/roles/role/grants.js | 18 ++++++++++++++++++ .../scopes/scope/roles/role/principals.js | 18 ++++++++++++++++++ .../app/controllers/scopes/scope/sessions.js | 18 ++++++++++++++++++ .../app/controllers/scopes/scope/targets.js | 18 ++++++++++++++++++ .../controllers/scopes/scope/targets/target.js | 13 +++++++++++++ .../scope/targets/target/add-host-sets.js | 18 ++++++++++++++++++ .../scopes/scope/targets/target/host-sets.js | 18 ++++++++++++++++++ .../scopes/scope/users/user/accounts.js | 18 ++++++++++++++++++ .../accounts/account/set-password-test.js | 12 ++++++++++++ .../scopes/scope/groups/group/members-test.js | 12 ++++++++++++ .../scopes/scope/host-catalogs-test.js | 12 ++++++++++++ .../scope/host-catalogs/host-catalog-test.js | 12 ++++++++++++ .../host-catalog/host-sets-test.js | 12 ++++++++++++ .../host-catalog/host-sets/host-set-test.js | 12 ++++++++++++ .../host-sets/host-set/add-hosts-test.js | 12 ++++++++++++ .../host-set/create-and-add-host-test.js | 12 ++++++++++++ .../host-sets/host-set/hosts-test.js | 12 ++++++++++++ .../host-catalogs/host-catalog/hosts-test.js | 12 ++++++++++++ .../host-catalog/hosts/host-test.js | 12 ++++++++++++ .../scopes/scope/roles/role/grants-test.js | 12 ++++++++++++ .../scopes/scope/roles/role/principals-test.js | 12 ++++++++++++ .../controllers/scopes/scope/sessions-test.js | 12 ++++++++++++ .../controllers/scopes/scope/targets-test.js | 12 ++++++++++++ .../scopes/scope/targets/target-test.js | 12 ++++++++++++ .../scope/targets/target/add-host-sets-test.js | 12 ++++++++++++ .../scope/targets/target/host-sets-test.js | 12 ++++++++++++ .../scopes/scope/users/user/accounts-test.js | 12 ++++++++++++ 38 files changed, 550 insertions(+) create mode 100644 ui/core/app/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password.js create mode 100644 ui/core/app/controllers/scopes/scope/groups/group/members.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts.js create mode 100644 ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host.js create mode 100644 ui/core/app/controllers/scopes/scope/roles/role/grants.js create mode 100644 ui/core/app/controllers/scopes/scope/roles/role/principals.js create mode 100644 ui/core/app/controllers/scopes/scope/sessions.js create mode 100644 ui/core/app/controllers/scopes/scope/targets.js create mode 100644 ui/core/app/controllers/scopes/scope/targets/target.js create mode 100644 ui/core/app/controllers/scopes/scope/targets/target/add-host-sets.js create mode 100644 ui/core/app/controllers/scopes/scope/targets/target/host-sets.js create mode 100644 ui/core/app/controllers/scopes/scope/users/user/accounts.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/groups/group/members-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/roles/role/grants-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/roles/role/principals-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/sessions-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/targets-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/targets/target-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/targets/target/add-host-sets-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/targets/target/host-sets-test.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/users/user/accounts-test.js diff --git a/ui/core/app/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password.js b/ui/core/app/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password.js new file mode 100644 index 000000000..b4fb1d989 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeAuthMethodsAuthMethodAccountsAccountSetPasswordController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated users breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('actions.set-password'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/groups/group/members.js b/ui/core/app/controllers/scopes/scope/groups/group/members.js new file mode 100644 index 000000000..59af4a9e2 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/groups/group/members.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeGroupsGroupMembersController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated users breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.group.messages.members.title'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs.js b/ui/core/app/controllers/scopes/scope/host-catalogs.js new file mode 100644 index 000000000..542fc1ba4 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-catalog.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog.js new file mode 100644 index 000000000..3fc3cbe18 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog.js @@ -0,0 +1,13 @@ +import Controller from '@ember/controller'; + +export default class ScopesScopeHostCatalogsHostCatalogController extends Controller { + // =attributes + + /** + * A role breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.model.displayName; + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets.js new file mode 100644 index 000000000..bb139e823 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-set.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js new file mode 100644 index 000000000..b4a591507 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set.js @@ -0,0 +1,13 @@ +import Controller from '@ember/controller'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetController extends Controller { + // =attributes + + /** + * A role breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.model.displayName; + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js new file mode 100644 index 000000000..aa59cb3e1 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetAddHostsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-set.actions.add-hosts'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js new file mode 100644 index 000000000..209919d33 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetCreateAndAddHostController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-set.actions.create-and-add-host'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js new file mode 100644 index 000000000..60464a8cd --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetHostsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts.js new file mode 100644 index 000000000..437f35159 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host.js b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host.js new file mode 100644 index 000000000..4986888a0 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host.js @@ -0,0 +1,13 @@ +import Controller from '@ember/controller'; + +export default class ScopesScopeHostCatalogsHostCatalogHostsHostController extends Controller { + // =attributes + + /** + * A role breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.model.displayName; + } +} diff --git a/ui/core/app/controllers/scopes/scope/roles/role/grants.js b/ui/core/app/controllers/scopes/scope/roles/role/grants.js new file mode 100644 index 000000000..a8cb2149f --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/roles/role/grants.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeRolesRoleGrantsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated users breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.role.grant.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/roles/role/principals.js b/ui/core/app/controllers/scopes/scope/roles/role/principals.js new file mode 100644 index 000000000..a81e0eb4d --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/roles/role/principals.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeRolesRolePrincipalsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated users breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.role.principal.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/sessions.js b/ui/core/app/controllers/scopes/scope/sessions.js new file mode 100644 index 000000000..470bc46a3 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/sessions.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeSessionsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.session.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/targets.js b/ui/core/app/controllers/scopes/scope/targets.js new file mode 100644 index 000000000..e5fd8cd14 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/targets.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeTargetsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.target.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/targets/target.js b/ui/core/app/controllers/scopes/scope/targets/target.js new file mode 100644 index 000000000..efef4904b --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/targets/target.js @@ -0,0 +1,13 @@ +import Controller from '@ember/controller'; + +export default class ScopesScopeTargetsTargetController extends Controller { + // =attributes + + /** + * An user breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.model.displayName; + } +} diff --git a/ui/core/app/controllers/scopes/scope/targets/target/add-host-sets.js b/ui/core/app/controllers/scopes/scope/targets/target/add-host-sets.js new file mode 100644 index 000000000..6700b582d --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/targets/target/add-host-sets.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeTargetsTargetAddHostSetsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.target.actions.add-host-sets'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/targets/target/host-sets.js b/ui/core/app/controllers/scopes/scope/targets/target/host-sets.js new file mode 100644 index 000000000..930b1e083 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/targets/target/host-sets.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeTargetsTargetHostSetsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated roles breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-set.title_plural'); + } +} diff --git a/ui/core/app/controllers/scopes/scope/users/user/accounts.js b/ui/core/app/controllers/scopes/scope/users/user/accounts.js new file mode 100644 index 000000000..37756e46d --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/users/user/accounts.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeUsersUserAccountsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated users breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.account.title_plural'); + } +} diff --git a/ui/core/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js b/ui/core/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js new file mode 100644 index 000000000..daed6ca0a --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/auth-methods/auth-method/accounts/account/set-password', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/auth-methods/auth-method/accounts/account/set-password'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/groups/group/members-test.js b/ui/core/tests/unit/controllers/scopes/scope/groups/group/members-test.js new file mode 100644 index 000000000..026f44d5e --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/groups/group/members-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/groups/group/members', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/groups/group/members'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs-test.js new file mode 100644 index 000000000..0c055095e --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog-test.js new file mode 100644 index 000000000..32b03a815 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets-test.js new file mode 100644 index 000000000..677b9c125 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/host-sets', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/host-sets'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js new file mode 100644 index 000000000..49736df08 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/host-sets/host-set', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/host-sets/host-set'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js new file mode 100644 index 000000000..36621e39d --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/add-hosts'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js new file mode 100644 index 000000000..bebd552c3 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/create-and-add-host'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js new file mode 100644 index 000000000..0d3c2be24 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts-test.js new file mode 100644 index 000000000..f19f65477 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/hosts', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/hosts'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js new file mode 100644 index 000000000..15bc7b716 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/host-catalogs/host-catalog/hosts/host-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/host-catalogs/host-catalog/hosts/host', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/host-catalogs/host-catalog/hosts/host'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/roles/role/grants-test.js b/ui/core/tests/unit/controllers/scopes/scope/roles/role/grants-test.js new file mode 100644 index 000000000..41a7c1fcc --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/roles/role/grants-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/roles/role/grants', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/roles/role/grants'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/roles/role/principals-test.js b/ui/core/tests/unit/controllers/scopes/scope/roles/role/principals-test.js new file mode 100644 index 000000000..7ca6f77b9 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/roles/role/principals-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/roles/role/principals', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/roles/role/principals'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/sessions-test.js b/ui/core/tests/unit/controllers/scopes/scope/sessions-test.js new file mode 100644 index 000000000..58e72740c --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/sessions-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/sessions', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/sessions'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/targets-test.js b/ui/core/tests/unit/controllers/scopes/scope/targets-test.js new file mode 100644 index 000000000..16e710ca3 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/targets-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/targets', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/targets'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/targets/target-test.js b/ui/core/tests/unit/controllers/scopes/scope/targets/target-test.js new file mode 100644 index 000000000..d6e49be75 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/targets/target-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/targets/target', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/targets/target'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/targets/target/add-host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/targets/target/add-host-sets-test.js new file mode 100644 index 000000000..bef629ad8 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/targets/target/add-host-sets-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/targets/target/add-host-sets', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/targets/target/add-host-sets'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/targets/target/host-sets-test.js b/ui/core/tests/unit/controllers/scopes/scope/targets/target/host-sets-test.js new file mode 100644 index 000000000..d2f2ef7ea --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/targets/target/host-sets-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/targets/target/host-sets', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/targets/target/host-sets'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/controllers/scopes/scope/users/user/accounts-test.js b/ui/core/tests/unit/controllers/scopes/scope/users/user/accounts-test.js new file mode 100644 index 000000000..5bbf27235 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/users/user/accounts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/users/user/accounts', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/users/user/accounts'); + assert.ok(controller); + }); +}); From b4be0e08cf64ea3a34dc865d3943b7cc7a8c80e8 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 14:38:09 -0400 Subject: [PATCH 26/27] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20smart=20scop?= =?UTF-8?q?e=20breadcrumbs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/components/bread-crumbs.hbs | 50 +++++++++++++------ ui/core/app/components/bread-crumbs.js | 10 ++++ .../app/controllers/scopes/scope/scopes.js | 27 ++++++++++ ui/core/app/routes/scopes/scope.js | 4 ++ ui/core/app/services/scope.js | 22 ++++++++ .../controllers/scopes/scope/scopes-test.js | 12 +++++ ui/core/tests/unit/services/scope-test.js | 12 +++++ ui/core/translations/en-us.yaml | 1 + 8 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 ui/core/app/components/bread-crumbs.js create mode 100644 ui/core/app/controllers/scopes/scope/scopes.js create mode 100644 ui/core/app/services/scope.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/scopes-test.js create mode 100644 ui/core/tests/unit/services/scope-test.js diff --git a/ui/core/app/components/bread-crumbs.hbs b/ui/core/app/components/bread-crumbs.hbs index f969028c6..d902b4d1b 100644 --- a/ui/core/app/components/bread-crumbs.hbs +++ b/ui/core/app/components/bread-crumbs.hbs @@ -1,15 +1,35 @@ -{{#if this.breadCrumbs}} - - {{#each this.breadCrumbs as |crumb|}} - {{#if crumb.model}} - - {{crumb.label}} - - {{else}} - - {{crumb.label}} - - {{/if}} - {{/each}} - -{{/if}} + + + {{#if this.scope.org}} + {{#unless this.scope.org.isGlobal}} + + {{t "resources.org.title_plural"}} + + + {{this.scope.org.displayName}} + + {{/unless}} + {{/if}} + + {{#if this.scope.project}} + + {{t "resources.project.title_plural"}} + + + {{this.scope.project.displayName}} + + {{/if}} + + {{#each this.breadCrumbs as |crumb|}} + {{#if crumb.model}} + + {{crumb.label}} + + {{else}} + + {{crumb.label}} + + {{/if}} + {{/each}} + + diff --git a/ui/core/app/components/bread-crumbs.js b/ui/core/app/components/bread-crumbs.js new file mode 100644 index 000000000..be3c4921b --- /dev/null +++ b/ui/core/app/components/bread-crumbs.js @@ -0,0 +1,10 @@ +import BreadCrumbsComponent from 'ember-breadcrumbs/components/bread-crumbs'; +import { inject as service } from '@ember/service'; + +export default class crumbs extends BreadCrumbsComponent { + + // =services + + @service scope; + +} diff --git a/ui/core/app/controllers/scopes/scope/scopes.js b/ui/core/app/controllers/scopes/scope/scopes.js new file mode 100644 index 000000000..05060ebd8 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/scopes.js @@ -0,0 +1,27 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { computed } from '@ember/object'; + +export default class ScopesScopeScopesController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * @type {string} + */ + @computed('model.currentScope.{isGlobal,isOrg}') + get breadCrumb() { + if (this.model.currentScope.isGlobal) { + return this.intl.t('resources.org.title_plural'); + } + /* istanbul ignore else */ + if (this.model.currentScope.isOrg) { + return this.intl.t('resources.project.title_plural'); + } + /* istanbul ignore next */ + return null; + } +} diff --git a/ui/core/app/routes/scopes/scope.js b/ui/core/app/routes/scopes/scope.js index 3bc2e102f..9b6720dbd 100644 --- a/ui/core/app/routes/scopes/scope.js +++ b/ui/core/app/routes/scopes/scope.js @@ -11,6 +11,7 @@ export default class ScopesScopeRoute extends Route { @service intl; @service session; + @service scope; // =methods @@ -61,6 +62,9 @@ export default class ScopesScopeRoute extends Route { selectedProject = model; selectedOrg = this.store.peekRecord('scope', model.scopeID); } + // Update the scope service with the current scope(s); + this.scope.org = selectedOrg; + this.scope.project = selectedProject; this.scopes = { orgs, projects, selectedOrg, selectedProject }; } diff --git a/ui/core/app/services/scope.js b/ui/core/app/services/scope.js new file mode 100644 index 000000000..b4e93fe03 --- /dev/null +++ b/ui/core/app/services/scope.js @@ -0,0 +1,22 @@ +import Service from '@ember/service'; +import { tracked } from '@glimmer/tracking'; + +/** + * This simple non-functional service is used to retain references to + * the currently active scope or scopes. + */ +export default class ScopeService extends Service { + + // =attributes + + /** + * @type {ScopeModel} + */ + @tracked org; + + /** + * @type {ScopeModel} + */ + @tracked project; + +} diff --git a/ui/core/tests/unit/controllers/scopes/scope/scopes-test.js b/ui/core/tests/unit/controllers/scopes/scope/scopes-test.js new file mode 100644 index 000000000..6a6b181de --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/scopes-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/scopes', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/scopes'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/services/scope-test.js b/ui/core/tests/unit/services/scope-test.js new file mode 100644 index 000000000..95493c0b4 --- /dev/null +++ b/ui/core/tests/unit/services/scope-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Service | scope', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let service = this.owner.lookup('service:scope'); + assert.ok(service); + }); +}); diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml index 22fd19edb..d208e7102 100644 --- a/ui/core/translations/en-us.yaml +++ b/ui/core/translations/en-us.yaml @@ -6,6 +6,7 @@ auth: choose-org: Choose a scope to authenticate. authenticating-with-org: "You are authenticating with {name}." titles: + home: Home iam: IAM new: New resources: Resources From f5a3066985bd6b97d91e15a9a6bb739178bfc7dc Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 29 Oct 2020 16:58:15 -0400 Subject: [PATCH 27/27] =?UTF-8?q?chore:=20=F0=9F=A4=96=20clean=20up=20auth?= =?UTF-8?q?=20redirects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/core/app/components/bread-crumbs.hbs | 14 +++--- ui/core/app/components/bread-crumbs.js | 1 + .../app/routes/scopes/scope/authenticate.js | 2 +- ui/core/app/routes/scopes/scope/edit.js | 14 ++++++ .../app/routes/scopes/scope/host-catalogs.js | 8 +++ ui/core/app/routes/scopes/scope/new.js | 13 +++++ ui/core/app/routes/scopes/scope/scopes.js | 6 +-- ui/core/app/routes/scopes/scope/sessions.js | 8 +++ ui/core/app/routes/scopes/scope/targets.js | 8 +++ ui/core/app/templates/scopes/scope.hbs | 18 +++++-- .../templates/scopes/scope/authenticate.hbs | 3 ++ .../tests/acceptance/authentication-test.js | 49 ++++++++++++++++++- 12 files changed, 126 insertions(+), 18 deletions(-) diff --git a/ui/core/app/components/bread-crumbs.hbs b/ui/core/app/components/bread-crumbs.hbs index d902b4d1b..3c30c0e0c 100644 --- a/ui/core/app/components/bread-crumbs.hbs +++ b/ui/core/app/components/bread-crumbs.hbs @@ -2,12 +2,14 @@ {{#if this.scope.org}} {{#unless this.scope.org.isGlobal}} - - {{t "resources.org.title_plural"}} - - - {{this.scope.org.displayName}} - + {{#if this.session.data.authenticated.isGlobal}} + + {{t "resources.org.title_plural"}} + + + {{this.scope.org.displayName}} + + {{/if}} {{/unless}} {{/if}} diff --git a/ui/core/app/components/bread-crumbs.js b/ui/core/app/components/bread-crumbs.js index be3c4921b..38482914d 100644 --- a/ui/core/app/components/bread-crumbs.js +++ b/ui/core/app/components/bread-crumbs.js @@ -5,6 +5,7 @@ export default class crumbs extends BreadCrumbsComponent { // =services + @service session; @service scope; } diff --git a/ui/core/app/routes/scopes/scope/authenticate.js b/ui/core/app/routes/scopes/scope/authenticate.js index 53bafba60..1c49215a8 100644 --- a/ui/core/app/routes/scopes/scope/authenticate.js +++ b/ui/core/app/routes/scopes/scope/authenticate.js @@ -22,7 +22,7 @@ export default class ScopesScopeAuthenticateRoute extends Route { const { id: scope_id } = this.modelFor('scopes.scope'); return hash({ scope: this.modelFor('scopes.scope'), - scopes: this.modelFor('scopes'), + scopes: this.modelFor('scopes').filter(scope => scope.isOrg), authMethods: this.store.query('auth-method', { scope_id }), // for integration testing: diff --git a/ui/core/app/routes/scopes/scope/edit.js b/ui/core/app/routes/scopes/scope/edit.js index b77391dbd..a7b74c5ef 100644 --- a/ui/core/app/routes/scopes/scope/edit.js +++ b/ui/core/app/routes/scopes/scope/edit.js @@ -1,4 +1,18 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default class ScopesScopeEditRoute extends Route { + + // =services + + @service session; + + // =methods + + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } } diff --git a/ui/core/app/routes/scopes/scope/host-catalogs.js b/ui/core/app/routes/scopes/scope/host-catalogs.js index 03adfed44..5c082051c 100644 --- a/ui/core/app/routes/scopes/scope/host-catalogs.js +++ b/ui/core/app/routes/scopes/scope/host-catalogs.js @@ -10,9 +10,17 @@ export default class ScopesScopeHostCatalogsRoute extends Route { @service intl; @service notify; + @service session; // =methods + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } + /** * Loads all host catalogs under the current scope. * @return {Promise{[HostCatalogModel]}} diff --git a/ui/core/app/routes/scopes/scope/new.js b/ui/core/app/routes/scopes/scope/new.js index c518a483a..0ab9f7f5b 100644 --- a/ui/core/app/routes/scopes/scope/new.js +++ b/ui/core/app/routes/scopes/scope/new.js @@ -1,8 +1,21 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default class ScopesScopeNewRoute extends Route { + + // =services + + @service session; + // =methods + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } + /** * Creates a new unsaved scope belonging to the current scope. * @return {ScopeModel} diff --git a/ui/core/app/routes/scopes/scope/scopes.js b/ui/core/app/routes/scopes/scope/scopes.js index a678edcc9..933bfc531 100644 --- a/ui/core/app/routes/scopes/scope/scopes.js +++ b/ui/core/app/routes/scopes/scope/scopes.js @@ -14,12 +14,10 @@ export default class ScopesScopeScopesRoute extends Route { // =methods /** - * Redirects to scopes/scope/authenticate if unauthenticated. + * If arriving here unauthenticated, redirect to index for further processing. */ beforeModel() { - if (!this.session.isAuthenticated) { - this.transitionTo('scopes.scope.authenticate'); - } + if (!this.session.isAuthenticated) this.transitionTo('index'); } /** diff --git a/ui/core/app/routes/scopes/scope/sessions.js b/ui/core/app/routes/scopes/scope/sessions.js index 7f64fdb67..a8ae5eb19 100644 --- a/ui/core/app/routes/scopes/scope/sessions.js +++ b/ui/core/app/routes/scopes/scope/sessions.js @@ -15,6 +15,7 @@ export default class ScopesScopeSessionsRoute extends Route { @service intl; @service notify; + @service session; // =attributes @@ -37,6 +38,13 @@ export default class ScopesScopeSessionsRoute extends Route { // =methods + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } + /** * Loads all sessions under the current scope and encapsulates them into * an array of objects containing their associated users and targets. diff --git a/ui/core/app/routes/scopes/scope/targets.js b/ui/core/app/routes/scopes/scope/targets.js index 30f049682..f1da50944 100644 --- a/ui/core/app/routes/scopes/scope/targets.js +++ b/ui/core/app/routes/scopes/scope/targets.js @@ -10,9 +10,17 @@ export default class ScopesScopeTargetsRoute extends Route { @service intl; @service notify; + @service session; // =methods + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } + /** * Loads all targets under current scope. * @return {Promise{[TargetModel]}} diff --git a/ui/core/app/templates/scopes/scope.hbs b/ui/core/app/templates/scopes/scope.hbs index 0e7de3048..278755d24 100644 --- a/ui/core/app/templates/scopes/scope.hbs +++ b/ui/core/app/templates/scopes/scope.hbs @@ -131,15 +131,23 @@
{{/unless}} - {{#unless @model.isGlobal}} + {{#if @model.isOrg}} + {{#if this.session.data.authenticated.isGlobal}} + + + {{t "resources.org.messages.settings.title"}} + + + {{/if}} + {{/if}} + + {{#if @model.isProject}} - {{t (if @model.isOrg - "resources.org.messages.settings.title" - "resources.project.messages.settings.title")}} + {{t "resources.project.messages.settings.title"}} - {{/unless}} + {{/if}} {{/if}} diff --git a/ui/core/app/templates/scopes/scope/authenticate.hbs b/ui/core/app/templates/scopes/scope/authenticate.hbs index 0bee46a27..ccabf58d4 100644 --- a/ui/core/app/templates/scopes/scope/authenticate.hbs +++ b/ui/core/app/templates/scopes/scope/authenticate.hbs @@ -14,6 +14,9 @@ @text={{t "actions.choose-different-org"}} @icon="user-organization" as |dropdown|> + + {{t "titles.global"}} + {{#each this.sortedScopes as |scope|}} {{scope.displayName}} diff --git a/ui/core/tests/acceptance/authentication-test.js b/ui/core/tests/acceptance/authentication-test.js index d9d5c3a0e..e4965ce8e 100644 --- a/ui/core/tests/acceptance/authentication-test.js +++ b/ui/core/tests/acceptance/authentication-test.js @@ -39,11 +39,16 @@ module('Acceptance | authentication', function (hooks) { let authMethodGlobalAuthenticateURL; let changePasswordURL; let orgsURL; + let orgEditURL; + let newProjectURL; let projectsURL; let usersURL; let groupsURL; let rolesURL; let authMethodsURL; + let hostCatalogsURL; + let sessionsURL; + let targetsURL; hooks.beforeEach(function () { invalidateSession(); @@ -73,11 +78,16 @@ module('Acceptance | authentication', function (hooks) { authMethodAuthenticateURL = `/scopes/${orgScopeID}/authenticate/${authMethodID}`; changePasswordURL = `/account/change-password`; orgsURL = `/scopes/global/scopes`; + orgEditURL = `/scopes/${orgScopeID}/edit`; + newProjectURL = `/scopes/${orgScopeID}/new`; projectsURL = `/scopes/${orgScopeID}/scopes`; usersURL = `/scopes/${orgScopeID}/users`; groupsURL = `/scopes/${orgScopeID}/groups`; rolesURL = `/scopes/${orgScopeID}/roles`; authMethodsURL = `/scopes/${orgScopeID}/auth-methods`; + hostCatalogsURL = `/scopes/${orgScopeID}/host-catalogs`; + sessionsURL = `/scopes/${orgScopeID}/sessions`; + targetsURL = `/scopes/${orgScopeID}/targets`; }); test('visiting auth methods authenticate route redirects to first auth method', async function (assert) { @@ -129,10 +139,24 @@ module('Acceptance | authentication', function (hooks) { assert.notOk(currentSession().isAuthenticated); }); - test('visiting projects while unauthenticated redirects to first org authenticate method', async function (assert) { + test('visiting org edit while unauthenticated redirects to first global authenticate method', async function (assert) { + assert.expect(2); + await visit(orgEditURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.notOk(currentSession().isAuthenticated); + }); + + test('visiting projects while unauthenticated redirects to first global authenticate method', async function (assert) { assert.expect(2); await visit(projectsURL); - assert.equal(currentURL(), authMethodAuthenticateURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.notOk(currentSession().isAuthenticated); + }); + + test('visiting new project while unauthenticated redirects to first global authenticate method', async function (assert) { + assert.expect(2); + await visit(newProjectURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); assert.notOk(currentSession().isAuthenticated); }); @@ -157,6 +181,27 @@ module('Acceptance | authentication', function (hooks) { assert.notOk(currentSession().isAuthenticated); }); + test('visiting host catalogs while unauthenticated redirects to first global authenticate method', async function (assert) { + assert.expect(2); + await visit(hostCatalogsURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.notOk(currentSession().isAuthenticated); + }); + + test('visiting targets while unauthenticated redirects to first global authenticate method', async function (assert) { + assert.expect(2); + await visit(targetsURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.notOk(currentSession().isAuthenticated); + }); + + test('visiting sessions while unauthenticated redirects to first global authenticate method', async function (assert) { + assert.expect(2); + await visit(sessionsURL); + assert.equal(currentURL(), authMethodGlobalAuthenticateURL); + assert.notOk(currentSession().isAuthenticated); + }); + test('visiting auth methods while unauthenticated redirects to first global authenticate method', async function (assert) { assert.expect(2); await visit(authMethodsURL);