From 7696fc62ef7a20cfa2dbe6656bea775d5d7dd259 Mon Sep 17 00:00:00 2001 From: yelinz Date: Mon, 3 May 2021 18:05:57 +0200 Subject: [PATCH] feat(ember): add work item list --- ember/app/caluma-query/models/work-item.js | 162 ++++++++++++++ ember/app/cases/detail/template.hbs | 3 + .../detail/work-items/edit/controller.js | 3 + .../detail/work-items/edit/form/controller.js | 49 +++++ .../detail/work-items/edit/form/route.js | 12 ++ .../detail/work-items/edit/form/template.hbs | 12 ++ .../work-items/edit/index/controller.js | 100 +++++++++ .../detail/work-items/edit/index/route.js | 7 + .../detail/work-items/edit/index/template.hbs | 176 +++++++++++++++ .../app/cases/detail/work-items/edit/route.js | 7 + .../cases/detail/work-items/edit/template.hbs | 1 + .../detail/work-items/index/controller.js | 53 +++++ .../cases/detail/work-items/index/route.js | 28 +++ .../detail/work-items/index/template.hbs | 18 ++ .../app/components/context-menu/component.js | 25 +++ .../app/components/context-menu/template.hbs | 25 +++ .../filters/radio-buttons/template.hbs | 13 ++ ember/app/components/filters/template.hbs | 3 + ember/app/components/nav-bar/template.hbs | 5 + .../app/components/notifications/component.js | 24 +++ .../app/components/notifications/template.hbs | 8 + ember/app/components/pagination/template.hbs | 14 ++ .../components/work-item-list/component.js | 19 ++ .../work-item-list/item/component.js | 91 ++++++++ .../work-item-list/item/template.hbs | 53 +++++ .../components/work-item-list/template.hbs | 37 ++++ .../gql/mutations/complete-work-item.graphql | 5 + .../app/gql/mutations/save-work-item.graphql | 12 ++ ember/app/gql/queries/get-case.graphql | 2 +- ember/app/gql/queries/get-cases.graphql | 2 +- .../register-caluma-query-model-work-item.js | 9 + ember/app/router.js | 12 ++ ember/app/services/notification.js | 29 +++ ember/app/styles/app.scss | 3 + .../styles/components/context-menu/index.scss | 39 ++++ .../components/filters/_radio-buttons.scss | 24 +++ .../app/styles/components/filters/index.scss | 9 + .../components/work-item-list/index.scss | 64 ++++++ .../app/work-items/detail/edit/controller.js | 100 +++++++++ ember/app/work-items/detail/edit/route.js | 7 + ember/app/work-items/detail/edit/template.hbs | 201 ++++++++++++++++++ ember/app/work-items/detail/index/route.js | 7 + ember/app/work-items/detail/route.js | 11 + ember/app/work-items/index/controller.js | 82 +++++++ ember/app/work-items/index/route.js | 8 + ember/app/work-items/index/template.hbs | 71 +++++++ ember/app/work-items/template.hbs | 1 + ember/package.json | 5 +- .../components/filters/component-test.js | 17 ++ .../filters/radio-buttons/component-test.js | 17 ++ .../notifications/component-test.js | 17 ++ .../components/pagination/component-test.js | 17 ++ ember/translations/en.yaml | 59 +++++ ember/yarn.lock | 27 +++ 54 files changed, 1802 insertions(+), 3 deletions(-) create mode 100644 ember/app/caluma-query/models/work-item.js create mode 100644 ember/app/cases/detail/work-items/edit/controller.js create mode 100644 ember/app/cases/detail/work-items/edit/form/controller.js create mode 100644 ember/app/cases/detail/work-items/edit/form/route.js create mode 100644 ember/app/cases/detail/work-items/edit/form/template.hbs create mode 100644 ember/app/cases/detail/work-items/edit/index/controller.js create mode 100644 ember/app/cases/detail/work-items/edit/index/route.js create mode 100644 ember/app/cases/detail/work-items/edit/index/template.hbs create mode 100644 ember/app/cases/detail/work-items/edit/route.js create mode 100644 ember/app/cases/detail/work-items/edit/template.hbs create mode 100644 ember/app/cases/detail/work-items/index/controller.js create mode 100644 ember/app/cases/detail/work-items/index/route.js create mode 100644 ember/app/cases/detail/work-items/index/template.hbs create mode 100644 ember/app/components/context-menu/component.js create mode 100644 ember/app/components/context-menu/template.hbs create mode 100644 ember/app/components/filters/radio-buttons/template.hbs create mode 100644 ember/app/components/filters/template.hbs create mode 100644 ember/app/components/notifications/component.js create mode 100644 ember/app/components/notifications/template.hbs create mode 100644 ember/app/components/pagination/template.hbs create mode 100644 ember/app/components/work-item-list/component.js create mode 100644 ember/app/components/work-item-list/item/component.js create mode 100644 ember/app/components/work-item-list/item/template.hbs create mode 100644 ember/app/components/work-item-list/template.hbs create mode 100644 ember/app/gql/mutations/complete-work-item.graphql create mode 100644 ember/app/gql/mutations/save-work-item.graphql create mode 100644 ember/app/initializers/register-caluma-query-model-work-item.js create mode 100644 ember/app/services/notification.js create mode 100644 ember/app/styles/components/context-menu/index.scss create mode 100644 ember/app/styles/components/filters/_radio-buttons.scss create mode 100644 ember/app/styles/components/filters/index.scss create mode 100644 ember/app/styles/components/work-item-list/index.scss create mode 100644 ember/app/work-items/detail/edit/controller.js create mode 100644 ember/app/work-items/detail/edit/route.js create mode 100644 ember/app/work-items/detail/edit/template.hbs create mode 100644 ember/app/work-items/detail/index/route.js create mode 100644 ember/app/work-items/detail/route.js create mode 100644 ember/app/work-items/index/controller.js create mode 100644 ember/app/work-items/index/route.js create mode 100644 ember/app/work-items/index/template.hbs create mode 100644 ember/app/work-items/template.hbs create mode 100644 ember/tests/integration/components/filters/component-test.js create mode 100644 ember/tests/integration/components/filters/radio-buttons/component-test.js create mode 100644 ember/tests/integration/components/notifications/component-test.js create mode 100644 ember/tests/integration/components/pagination/component-test.js diff --git a/ember/app/caluma-query/models/work-item.js b/ember/app/caluma-query/models/work-item.js new file mode 100644 index 00000000..10156f0b --- /dev/null +++ b/ember/app/caluma-query/models/work-item.js @@ -0,0 +1,162 @@ +import { inject as service } from "@ember/service"; +import { tracked } from "@glimmer/tracking"; +import saveWorkItemMutation from "caluma-portal-demo/gql/mutations/save-work-item"; +import { queryManager } from "ember-apollo-client"; +import WorkItemModel from "ember-caluma/caluma-query/models/work-item"; + +export default class CustomWorkItemModel extends WorkItemModel { + @queryManager apollo; + + @service store; + @service router; + @service intl; + @service notifications; + + @tracked meta = this.raw.meta; + @tracked notViewed = this.raw.meta["not-viewed"]; + @tracked assignedUsers = this.raw.assignedUsers; + @tracked addressedGroups = this.raw.addressedGroups; + + get assignedUser() { + return this.assignedUsers; + } + set assignedUser(user) { + this.assignedUsers = [user]; + } + + get addressedGroup() { + return this.addressedGroups; + } + + get closedByUser() { + return this.raw.closedByUser; + } + + get createdByUser() { + return this.raw.createdByUser; + } + + get createdByGroup() { + return this.raw.createdByGroup; + } + + get isReady() { + return this.raw.status === "READY"; + } + + get isCompleted() { + return this.raw.status === "COMPLETED"; + } + + get canEdit() { + return this.isReady; + } + + get canEditAsCreator() { + return this.isReady; + } + + get canComplete() { + return this.isReady; + } + + get responsible() { + return this.assignedUser; + } + + get case() { + return this.raw.case.parentWorkItem?.case || this.raw.case; + } + + get calumaForm() { + return null; + } + + async toggleRead() { + try { + this.notViewed = !this.notViewed; + + await this.apollo.mutate({ + mutation: saveWorkItemMutation, + variables: { + input: { + workItem: this.id, + meta: JSON.stringify({ + ...this.raw.meta, + "not-viewed": this.notViewed, + }), + }, + }, + }); + + return true; + } catch (error) { + this.notifications.error(this.intl.t("workItems.saveError")); + } + } + + async assignToMe() { + return await this.assignToUser(/* TODO current user*/); + } + + async assignToUser(user) { + try { + this.assignedUser = user; + + await this.apollo.mutate({ + mutation: saveWorkItemMutation, + variables: { + input: { + workItem: this.id, + assignedUsers: this.assignedUsers, + }, + }, + }); + + return true; + } catch (error) { + this.notifications.error(this.intl.t("workItems.saveError")); + } + } + + static fragment = `{ + createdAt + createdByUser + createdByGroup + closedAt + closedByUser + closedByGroup + status + meta + addressedGroups + controllingGroups + assignedUsers + name + deadline + description + document { + id + form { + slug + } + } + case { + id + meta + document { + id + form { + slug + name + } + } + } + task { + slug + name + description + meta + __typename + } + }`; +} diff --git a/ember/app/cases/detail/template.hbs b/ember/app/cases/detail/template.hbs index 4bf8cae7..966ee5eb 100644 --- a/ember/app/cases/detail/template.hbs +++ b/ember/app/cases/detail/template.hbs @@ -16,6 +16,9 @@ {{t "documents.subnav.overview"}} + + {{t "documents.subnav.workItems"}} + {{t "documents.subnav.document"}} diff --git a/ember/app/cases/detail/work-items/edit/controller.js b/ember/app/cases/detail/work-items/edit/controller.js new file mode 100644 index 00000000..4f653f7a --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/controller.js @@ -0,0 +1,3 @@ +import Controller from "@ember/controller"; + +export default class CasesDetailWorkItemsEditController extends Controller {} diff --git a/ember/app/cases/detail/work-items/edit/form/controller.js b/ember/app/cases/detail/work-items/edit/form/controller.js new file mode 100644 index 00000000..cb06ac56 --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/form/controller.js @@ -0,0 +1,49 @@ +import Controller from "@ember/controller"; +import { inject as service } from "@ember/service"; +import completeWorkItem from "caluma-portal-demo/gql/mutations/complete-work-item"; +import { queryManager } from "ember-apollo-client"; +import calumaQuery from "ember-caluma/caluma-query"; +import { allWorkItems } from "ember-caluma/caluma-query/queries"; +import { + dropTask, + restartableTask, + lastValue, +} from "ember-concurrency-decorators"; + +export default class CasesDetailWorkItemsEditFormController extends Controller { + @queryManager apollo; + + @service store; + @service notifications; + @service intl; + @service moment; + + @lastValue("fetchWorkItems") workItem; + + @calumaQuery({ query: allWorkItems }) + workItemsQuery; + + @restartableTask() + *fetchWorkItems(model) { + if (typeof model === "object") { + return model; + } + try { + yield this.workItemsQuery.fetch({ filter: [{ id: model }] }); + + return this.workItemsQuery.value[0]; + } catch (error) { + console.error(error); + this.notifications.error(this.intl.t("workItems.fetchError")); + } + } + + @dropTask() + *completeWorkItem() { + yield this.apollo.mutate({ + mutation: completeWorkItem, + variables: { id: this.workItem.id }, + }); + this.transitionToRoute("cases.detail.work-items"); + } +} diff --git a/ember/app/cases/detail/work-items/edit/form/route.js b/ember/app/cases/detail/work-items/edit/form/route.js new file mode 100644 index 00000000..ab618e39 --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/form/route.js @@ -0,0 +1,12 @@ +import Route from "@ember/routing/route"; + +export default class CasesDetailWorkItemsEditFormRoute extends Route { + model() { + return this.modelFor("cases.detail.work-items.edit"); + } + + setupController(controller, model) { + super.setupController(controller, model); + controller.fetchWorkItems.perform(model); + } +} diff --git a/ember/app/cases/detail/work-items/edit/form/template.hbs b/ember/app/cases/detail/work-items/edit/form/template.hbs new file mode 100644 index 00000000..5a860083 --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/form/template.hbs @@ -0,0 +1,12 @@ +

{{this.workItem.name}}

+ +{{#if this.fetchWorkItems.isRunning}} +
+ +
+{{else}} + +{{/if}} \ No newline at end of file diff --git a/ember/app/cases/detail/work-items/edit/index/controller.js b/ember/app/cases/detail/work-items/edit/index/controller.js new file mode 100644 index 00000000..f6c923ea --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/index/controller.js @@ -0,0 +1,100 @@ +import Controller from "@ember/controller"; +import { action } from "@ember/object"; +import { inject as service } from "@ember/service"; +import { tracked } from "@glimmer/tracking"; +import completeWorkItem from "caluma-portal-demo/gql/mutations/complete-work-item"; +import saveWorkItem from "caluma-portal-demo/gql/mutations/save-work-item"; +import { queryManager } from "ember-apollo-client"; +import calumaQuery from "ember-caluma/caluma-query"; +import { allWorkItems } from "ember-caluma/caluma-query/queries"; +import { dropTask } from "ember-concurrency-decorators"; +import moment from "moment"; + +export default class CasesDetailWorkItemsEditController extends Controller { + @queryManager apollo; + + @service store; + @service notifications; + @service intl; + @service moment; + + @tracked workItem; + + @calumaQuery({ query: allWorkItems, options: "options" }) + workItemsQuery; + + get options() { + return { + pageSize: 1, + }; + } + + @dropTask() + *fetchWorkItems() { + try { + yield this.workItemsQuery.fetch({ filter: [{ id: this.model }] }); + + this.workItem = this.workItemsQuery.value[0]; + } catch (error) { + this.notifications.error(this.intl.t("workItems.fetchError")); + } + } + + @dropTask + *finishWorkItem(event) { + event.preventDefault(); + + try { + yield this.apollo.mutate({ + mutation: saveWorkItem, + variables: { + input: { + workItem: this.workItem.id, + meta: JSON.stringify(this.workItem.meta), + }, + }, + }); + + yield this.apollo.mutate({ + mutation: completeWorkItem, + variables: { id: this.workItem.id }, + }); + + this.notifications.success(this.intl.t("workItems.finishSuccess")); + + this.transitionToRoute("cases.detail.work-items.index"); + } catch (error) { + this.notifications.error(this.intl.t("workItems.saveError")); + } + } + + @dropTask + *saveManualWorkItem(event) { + event.preventDefault(); + + try { + yield this.apollo.mutate({ + mutation: saveWorkItem, + variables: { + input: { + workItem: this.workItem.id, + description: this.workItem.description, + deadline: this.workItem.deadline, + meta: JSON.stringify(this.workItem?.meta), + }, + }, + }); + + this.notifications.success(this.intl.t("workItems.saveSuccess")); + + this.transitionToRoute("cases.detail.work-items.index"); + } catch (error) { + this.notifications.error(this.intl.t("workItems.saveError")); + } + } + + @action + setDeadline(value) { + this.workItem.deadline = moment(value); + } +} diff --git a/ember/app/cases/detail/work-items/edit/index/route.js b/ember/app/cases/detail/work-items/edit/index/route.js new file mode 100644 index 00000000..1cfcf4f9 --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/index/route.js @@ -0,0 +1,7 @@ +import Route from "@ember/routing/route"; + +export default class CasesDetailWorkItemsEditRoute extends Route { + model() { + return this.modelFor("cases.detail.work-items.edit"); + } +} diff --git a/ember/app/cases/detail/work-items/edit/index/template.hbs b/ember/app/cases/detail/work-items/edit/index/template.hbs new file mode 100644 index 00000000..7e989a5a --- /dev/null +++ b/ember/app/cases/detail/work-items/edit/index/template.hbs @@ -0,0 +1,176 @@ + + +

+ {{t "workItems.edit"}} +

+ +
+ +

+ {{this.workItem.task.name}} +

+ +
+ {{#if this.workItem.isCompleted}} +
+ + {{t "workItems.closedBy"}} + + {{this.workItem.closedByUser.fullName}} +
+
+ + {{t "workItems.closedAt"}} + + {{ + format-date + this.workItem.closedAt + day="2-digit" + month="2-digit" + year="numeric" + hour="2-digit" + minute="2-digit" + hour12=false + }} +
+
+ + {{t "workItems.comment"}} + + {{or this.workItem.meta.completion-comment "-"}} +
+ {{/if}} +
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+