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..45adc26d0
--- /dev/null
+++ b/ui/core/app/components/form/target/index.hbs
@@ -0,0 +1,49 @@
+
+
+
+ {{#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 eb486f950..34435c631 100644
--- a/ui/core/app/router.js
+++ b/ui/core/app/router.js
@@ -29,7 +29,9 @@ Router.map(function () {
});
});
});
- this.route('targets', function() {});
+ this.route('targets', function() {
+ this.route('target', { path: ':target_id' }, function() {});
+ });
});
this.route('new');
});
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
index 7247e9446..b9afbdf98 100644
--- 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
@@ -17,7 +17,7 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogRoute exte
});
}
- /**
+ /**
* Renders the host-catalog specific templates for header, navigation, and actions page sections.
* @override
* @param {object} controller
diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets.js b/ui/core/app/routes/scopes/scope/projects/project/targets.js
index 91f399648..acb1e07cc 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/targets.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/targets.js
@@ -1,6 +1,14 @@
import Route from '@ember/routing/route';
+import { inject as service } from '@ember/service';
+import { action } from '@ember/object';
export default class ScopesScopeProjectsProjectTargetsRoute extends Route {
+
+ // =services
+
+ @service intl;
+ @service notify;
+
// =methods
/**
@@ -11,4 +19,56 @@ export default class ScopesScopeProjectsProjectTargetsRoute extends Route {
const scopeID = this.modelFor('scopes.scope.projects.project').id;
return this.store.findAll('target', { adapterOptions: { scopeID } });
}
+
+ // =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
+ async save(target) {
+ const { isNew } = target;
+ try {
+ await target.save();
+ this.refresh();
+ this.notify.success(
+ this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
+ );
+ this.transitionTo('scopes.scope.projects.project.targets.target', target);
+ } catch (error) {
+ // TODO: replace with translated strings
+ this.notify.error(error.message, { closeAfter: null });
+ }
+ }
+
+ /**
+ * Deletes a target and redirects to targets index.
+ * @param {TargetModel} target
+ */
+ @action
+ async delete(target) {
+ try {
+ await target.destroyRecord();
+ this.refresh();
+ this.notify.success(this.intl.t('notify.delete-success'));
+ this.transitionTo('scopes.scope.projects.project.targets');
+ } catch (error) {
+ // TODO: replace with translated strings
+ this.notify.error(error.message, { closeAfter: null });
+ }
+ }
+
}
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
new file mode 100644
index 000000000..8b5cf77ab
--- /dev/null
+++ b/ui/core/app/routes/scopes/scope/projects/project/targets/target.js
@@ -0,0 +1,18 @@
+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 }) {
+ const { id: scopeID } = this.modelFor('scopes.scope.projects.project');
+ return this.store.findRecord('target', target_id, { adapterOptions: { scopeID } });
+ }
+
+}
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
new file mode 100644
index 000000000..ff772f61f
--- /dev/null
+++ b/ui/core/app/routes/scopes/scope/projects/project/targets/target/index.js
@@ -0,0 +1,4 @@
+import Route from '@ember/routing/route';
+
+export default class ScopesScopeProjectsProjectTargetsTargetIndexRoute extends Route {
+}
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
index 113b126dc..8d330854c 100644
--- a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs
+++ b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs
@@ -20,7 +20,12 @@
{{#each @model as |target|}}
- {{target.displayName}}
+
+ {{target.displayName}}
+
{{target.description}}
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
new file mode 100644
index 000000000..e2147cab0
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target.hbs
@@ -0,0 +1 @@
+{{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
new file mode 100644
index 000000000..64fc6b7d2
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target/index.hbs
@@ -0,0 +1,35 @@
+
+
+
+ {{t "resources.target"}}
+
+
+
+
+
+ {{t 'titles.details'}}
+
+
+
+
+
+
+
+ {{t 'actions.delete-target'}}
+
+
+
+
+
+
+
+
+
diff --git a/ui/core/tests/integration/components/form/target-test.js b/ui/core/tests/integration/components/form/target-test.js
new file mode 100644
index 000000000..e0246833f
--- /dev/null
+++ b/ui/core/tests/integration/components/form/target-test.js
@@ -0,0 +1,23 @@
+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/unit/routes/scopes/scope/projects/project/targets/target-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js
new file mode 100644
index 000000000..0fa4c6fc5
--- /dev/null
+++ b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target-test.js
@@ -0,0 +1,11 @@
+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/index-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js
new file mode 100644
index 000000000..5b1f35962
--- /dev/null
+++ b/ui/core/tests/unit/routes/scopes/scope/projects/project/targets/target/index-test.js
@@ -0,0 +1,11 @@
+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);
+ });
+});
diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml
index b2d630279..20114979f 100644
--- a/ui/core/translations/en-us.yaml
+++ b/ui/core/translations/en-us.yaml
@@ -16,6 +16,7 @@ actions:
delete-host-catalog: Delete host catalog
delete-auth-method: Delete auth method
delete-host-set: Delete host set
+ delete-target: Delete target
add-host-set: Create Host Set
auth:
titles:
@@ -52,6 +53,7 @@ resources:
auth-methods: Auth Methods
host-set: Host Set
host-sets: Host Sets
+ target: Target
targets: Targets
titles:
iam: IAM