Skip to content

Commit

Permalink
feat(user): add acl edit and create views
Browse files Browse the repository at this point in the history
  • Loading branch information
velrest authored and anehx committed Oct 21, 2020
1 parent 50d5a22 commit cc990ab
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 0 deletions.
48 changes: 48 additions & 0 deletions addon/controllers/users/edit/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { inject as service } from "@ember/service";
import { tracked } from "@glimmer/tracking";
import { task } from "ember-concurrency-decorators";

import PaginationController from "ember-emeis/controllers/pagination";
import handleModelErrors from "ember-emeis/decorators/handle-model-errors";

export default class UsersEditAclController extends PaginationController {
@service intl;
@service notification;
@service store;

get queryParamsfilter() {
return { user: this.model.id };
}

@tracked showAclWizzard = false;

@task
@handleModelErrors({ errorMessage: "emeis.form.save-error" })
*createEntry(aclProperties) {
const aclEntry = this.store.createRecord("acl", { ...aclProperties });

try {
yield aclEntry.save();
this.notification.success(this.intl.t("emeis.form.save-success"));
this.showAclWizzard = false;
} catch (exception) {
if (
exception.isAdapterError &&
exception.errors[0].status === "400" &&
exception.errors[0].code === "unique"
) {
this.notification.danger(this.intl.t("emeis.acl-wizzard.duplicate"));
} else {
throw exception;
}
}
}

@task
@handleModelErrors({ errorMessage: "emeis.form.delete-error" })
*deleteEntry(aclEntry, refreshDataTable) {
yield aclEntry.destroyRecord();
this.notification.success(this.intl.t("emeis.form.delete-success"));
refreshDataTable();
}
}
7 changes: 7 additions & 0 deletions addon/routes/users/edit/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Route from "@ember/routing/route";

export default class UsersEditAclRoute extends Route {
model() {
return this.modelFor("users.edit");
}
}
63 changes: 63 additions & 0 deletions addon/templates/users/edit/acl.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{{#if this.showAclWizzard}}
<span class="uk-flex uk-flex-left">
<UkButton data-test-back {{on "click" (set this.showAclWizzard false)}}>
<UkIcon @icon="arrow-left" @ratio="1.5" />
{{t "emeis.form.back"}}
</UkButton>
</span>
<AclWizzard @createAclEntry={{perform this.createEntry}} @user={{@model}} />
{{else}}
<DataTable
@modelName="acl"
@filter={{this.queryParamsfilter}}
@include="user,role,scope"
@page={{this.page}}
@search={{this.search}}
@updatePage={{fn this.updateQueryParam "page"}}
@updateSearch={{fn this.updateQueryParam "search"}} as |table|
>
<table.head>
<th>
{{t "emeis.acl-table.headings.role"}}
</th>

<th>
{{t "emeis.acl-table.headings.scope"}}
</th>
<th class="uk-table-shrink uk-text-nowrap">
<UkButton
data-test-add-acl
@color="primary"
{{on "click" (fn (set this.showAclWizzard true))}}
>
{{t "emeis.acl-table.headings.add-entry"}}
</UkButton>
</th>
</table.head>
<table.body as |body|>
<body.row>
{{#with body.model as |aclEntry|}}
<td data-test-acl-role={{aclEntry.id}}>
{{aclEntry.role.name}}
</td>

<td data-test-acl-scope={{aclEntry.id}}>
{{aclEntry.scope.name}}
</td>

<td data-test-acl-delete={{aclEntry.id}}>
<span class="uk-flex uk-flex-center">
<button
type="button"
class="uk-icon-button uk-margin-small-right"
uk-icon="trash"
tooltip="hey there"
{{on "click" (perform this.deleteEntry aclEntry table.refresh)}}
></button>
</span>
</td>
{{/with}}
</body.row>
</table.body>
</DataTable>
{{/if}}
1 change: 1 addition & 0 deletions app/controllers/users/edit/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/controllers/users/edit/acl";
1 change: 1 addition & 0 deletions app/routes/users/edit/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/routes/users/edit/acl";
1 change: 1 addition & 0 deletions app/templates/users/edit/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/templates/users/edit/acl";
101 changes: 101 additions & 0 deletions tests/acceptance/users-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,105 @@ module("Acceptance | users", function (hooks) {
assert.dom("[data-test-edit-link]").exists();
assert.dom("[data-test-acl-link]").exists();
});

test("list view /users/:id/acl", async function (assert) {
assert.expect(12);

const user = this.server.create("user");
const acl = this.server.createList("acl", 3)[0];

await visit(`/users`);
// Each acl also creates a user
assert.dom("[data-test-user-username]").exists({ count: 4 });

await click("[data-test-user-username] a");
assert.equal(currentURL(), `/users/${user.id}`);

assert.dom("[data-test-edit-link]").exists();
assert.dom("[data-test-acl-link]").exists();

this.assertRequest("GET", `/api/v1/acls`, (request) => {
assert.equal(user.id, request.queryParams["filter[user]"]);
});
await click("[data-test-acl-link]");
assert.equal(currentURL(), `/users/${user.id}/acl`);

// For some reason the await click is not actually waiting for the fetch task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table thead"));

assert.dom("[data-test-acl-role]").exists({ count: 3 });
assert.dom("[data-test-acl-delete]").exists({ count: 3 });

assert.dom("[data-test-acl-role]").hasText(acl.role.name.en);
assert.dom("[data-test-acl-scope]").hasText(acl.scope.name.en);

this.assertRequest("DELETE", `/api/v1/acls/:id`, (request) => {
assert.equal(request.params.id, acl.id);
});
await click("[data-test-acl-delete] button");
// For some reason the await click is not actually waiting for the delete task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table thead"));
assert.dom("[data-test-acl-role]").exists({ count: 2 });
});

test("create view /users/:id/acl", async function (assert) {
assert.expect(17);

const user = this.server.create("user");
const role = this.server.createList("role", 2)[0];
const scope = this.server.createList("scope", 2)[0];

await visit(`/users/${user.id}/acl`);
assert.equal(currentURL(), `/users/${user.id}/acl`);

assert.dom("[data-test-acl-role]").doesNotExist();
assert.dom("[data-test-add-acl]").exists();
assert.dom("table").exists();

await click("[data-test-add-acl]");
assert.dom("table").doesNotExist();
assert.dom("[data-test-back]").exists();

// Test back button
await click("[data-test-back]");
assert.dom("[data-test-acl-role]").doesNotExist();
assert.dom("[data-test-back]").doesNotExist();
// For some reason the await click is not actually waiting for the fetch task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table thead"));
assert.dom("[data-test-add-acl]").exists();
assert.dom("table").exists();

await click("[data-test-add-acl]");

await click("button[data-test-select-role]");
// For some reason the await click is not actually waiting for the fetch task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table tr"));
assert.dom("[data-test-row]").exists({ count: 2 });

await click("[data-test-row]");

assert.dom("[data-test-create-acl]").hasAttribute("disabled");

await click("button[data-test-select-scope]");
// For some reason the await click is not actually waiting for the fetch task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table tr"));
assert.dom("[data-test-row]").exists({ count: 2 });

await click("[data-test-row]");
assert.dom("[data-test-create-acl]").doesNotHaveAttribute("disabled");

// Create acl entry
await click("[data-test-create-acl]");
// For some reason the await click is not actually waiting for the fetch task to finish.
// Probably some runloop issue.
await waitUntil(() => this.element.querySelector("table tr"));
assert.dom("[data-test-back]").doesNotExist();
assert.dom("[data-test-acl-scope]").hasText(scope.name.en);
assert.dom("[data-test-acl-role]").hasText(role.name.en);
});
});
47 changes: 47 additions & 0 deletions tests/unit/controllers/users/edit/acl-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { setupMirage } from "ember-cli-mirage/test-support";
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";

import setupRequestAssertions from "./../../../../helpers/assert-request";
module("Unit | Controller | users/edit/acl", function (hooks) {
setupTest(hooks);
setupMirage(hooks);
setupRequestAssertions(hooks);

test("queryParamsfilter", function (assert) {
const controller = this.owner.lookup("controller:users/edit/acl");
assert.ok(controller);

controller.model = { id: 1 };
assert.deepEqual(controller.queryParamsfilter, { "user": 1 });
});

test("createEntry", async function (assert) {
assert.expect(3);
const controller = this.owner.lookup("controller:users/edit/acl");
assert.ok(controller);

this.assertRequest("POST", "/api/v1/acls", (request) => {
const relationships = JSON.parse(request.requestBody).data.relationships;
assert.ok(relationships.role);
assert.ok(relationships.scope);
});
await controller.createEntry.perform({ role: 1, scope: 2 });
});

test("createEntry", async function (assert) {
assert.expect(3);
const controller = this.owner.lookup("controller:users/edit/acl");
assert.ok(controller);
const refresh = () => {
assert.ok(true);
};
const model = {
destroyRecord() {
assert.ok(true);
},
};

await controller.deleteEntry.perform(model, refresh);
});
});

0 comments on commit cc990ab

Please sign in to comment.