@projectcaluma/ember-distribution 11.0.0-beta.25 → 11.0.0-beta.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  import { inject as service } from "@ember/service";
2
2
  import { Ability } from "ember-can";
3
+ import { DateTime } from "luxon";
3
4
 
4
5
  import config from "@projectcaluma/ember-distribution/config";
5
6
 
@@ -56,4 +57,32 @@ export default class InquiryAbility extends Ability {
56
57
  ) ?? true
57
58
  );
58
59
  }
60
+
61
+ get canReopen() {
62
+ return (
63
+ this.model.isRedoable &&
64
+ this.model?.addressedGroups
65
+ .map(String)
66
+ .includes(String(this.calumaOptions.currentGroupId)) &&
67
+ (this.config.permissions.reopenInquiry?.(this.model) ?? true)
68
+ );
69
+ }
70
+
71
+ get canSendReminder() {
72
+ const deadline = DateTime.fromISO(
73
+ this.model.document?.deadline.edges[0]?.node.value
74
+ );
75
+
76
+ return (
77
+ !this.config.ui.readonly &&
78
+ this.config.enableReminders &&
79
+ this.model?.task.slug === this.config.inquiry.task &&
80
+ this.model?.status === "READY" &&
81
+ this.model?.controllingGroups
82
+ .map(String)
83
+ .includes(String(this.calumaOptions.currentGroupId)) &&
84
+ deadline.diffNow("days").days <= 0 &&
85
+ (this.config.permissions.sendReminder?.(this.model) ?? true)
86
+ );
87
+ }
59
88
  }
@@ -77,7 +77,47 @@
77
77
  </LinkTo>
78
78
  </li>
79
79
  {{/if}}
80
+ {{#if (and (eq @type "answer") (can "reopen inquiry" @inquiry))}}
81
+ <li>
82
+ <a href="" {{on "click" (perform this.reopen)}} data-test-reopen>
83
+ {{t "caluma.distribution.reopen-inquiry.link"}}
84
+ </a>
85
+ </li>
86
+ {{/if}}
80
87
  {{/unless}}
88
+ {{#if (can "send reminder inquiry" @inquiry)}}
89
+ <li>
90
+ <a
91
+ data-test-send-reminder
92
+ href=""
93
+ {{on "click" (perform this.sendReminder)}}
94
+ >
95
+ {{t "caluma.distribution.reminder.link"}}
96
+ </a>
97
+ <div
98
+ uk-dropdown="mode: hover; pos: bottom"
99
+ class="uk-padding-small uk-width-small"
100
+ >
101
+ <div class="uk-text-center uk-text-bold uk-margin-small-bottom">
102
+ {{t "caluma.distribution.reminder.title"}}
103
+ </div>
104
+ {{#if @inquiry.meta.reminders}}
105
+ <div class="uk-height-max-small uk-overflow-auto">
106
+ {{#each @inquiry.meta.reminders as |reminder|}}
107
+ <div class="uk-text-center uk-text-small uk-text-muted">
108
+ {{format-date reminder}}
109
+ {{format-time reminder hour="2-digit" minute="2-digit"}}
110
+ </div>
111
+ {{/each}}
112
+ </div>
113
+ {{else}}
114
+ <div class="uk-text-center">
115
+ {{t "caluma.distribution.reminder.no-reminders"}}
116
+ </div>
117
+ {{/if}}
118
+ </div>
119
+ </li>
120
+ {{/if}}
81
121
  </ul>
82
122
 
83
123
  {{#if this.requestInfo}}
@@ -4,9 +4,12 @@ import Component from "@glimmer/component";
4
4
  import { queryManager } from "ember-apollo-client";
5
5
  import { dropTask } from "ember-concurrency";
6
6
  import { confirm } from "ember-uikit";
7
+ import { DateTime } from "luxon";
7
8
 
8
9
  import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
9
10
  import config from "@projectcaluma/ember-distribution/config";
11
+ import reopenInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/reopen-inquiry.graphql";
12
+ import updateInquiryMetaMutation from "@projectcaluma/ember-distribution/gql/mutations/update-inquiry-meta.graphql";
10
13
  import withdrawInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/withdraw-inquiry.graphql";
11
14
  import inquiryAnswerStatus from "@projectcaluma/ember-distribution/utils/inquiry-answer-status";
12
15
 
@@ -14,6 +17,7 @@ export default class CdInquiryDialogInquiryPartComponent extends Component {
14
17
  @service notification;
15
18
  @service router;
16
19
  @service intl;
20
+ @service calumaOptions;
17
21
 
18
22
  @queryManager apollo;
19
23
 
@@ -73,4 +77,70 @@ export default class CdInquiryDialogInquiryPartComponent extends Component {
73
77
  );
74
78
  }
75
79
  }
80
+
81
+ @dropTask
82
+ *reopen(e) {
83
+ e.preventDefault();
84
+
85
+ /* istanbul ignore next */
86
+ if (
87
+ !(yield confirm(
88
+ this.intl.t("caluma.distribution.reopen-inquiry.confirm")
89
+ ))
90
+ ) {
91
+ return;
92
+ }
93
+
94
+ try {
95
+ yield this.apollo.mutate({
96
+ mutation: reopenInquiryMutation,
97
+ variables: {
98
+ workItem: decodeId(this.args.inquiry.id),
99
+ statusQuestion: this.config.inquiry.answer.statusQuestion,
100
+ buttonTasks: Object.keys(this.config.inquiry.answer.buttons),
101
+ },
102
+ });
103
+ } catch (error) {
104
+ this.notification.danger(
105
+ this.intl.t("caluma.distribution.reopen-inquiry.error")
106
+ );
107
+ }
108
+ }
109
+
110
+ @dropTask
111
+ *sendReminder(e) {
112
+ e.preventDefault();
113
+
114
+ if (!(yield confirm(this.intl.t("caluma.distribution.reminder.confirm")))) {
115
+ return;
116
+ }
117
+
118
+ try {
119
+ yield this.calumaOptions.sendReminderDistributionInquiry(
120
+ decodeId(this.args.inquiry.id)
121
+ );
122
+
123
+ this.notification.success(
124
+ this.intl.t("caluma.distribution.reminder.success")
125
+ );
126
+
127
+ yield this.apollo.mutate({
128
+ mutation: updateInquiryMetaMutation,
129
+ variables: {
130
+ inquiry: decodeId(this.args.inquiry.id),
131
+ meta: JSON.stringify({
132
+ ...this.args.inquiry.meta,
133
+ reminders: [
134
+ DateTime.now().toISO(),
135
+ ...(this.args.inquiry.meta.reminders ?? []),
136
+ ],
137
+ }),
138
+ },
139
+ });
140
+ } catch (error) {
141
+ this.notification.danger(
142
+ this.intl.t("caluma.distribution.reminder.error")
143
+ );
144
+ }
145
+ }
76
146
  }
@@ -52,6 +52,8 @@ export default class CdInquiryDialogComponent extends Component {
52
52
  },
53
53
  });
54
54
 
55
+ this._setRedoableStates(response.allWorkItems);
56
+
55
57
  /**
56
58
  * Sadly this is necessary to handle what happens after the withdraw task in
57
59
  * the inquiry part component because the mutation triggers a refresh of the
@@ -68,11 +70,39 @@ export default class CdInquiryDialogComponent extends Component {
68
70
  if (allWorkItems.edges.every((edge) => edge.node.status === "CANCELED")) {
69
71
  this.router.transitionTo("index");
70
72
  }
73
+
74
+ /**
75
+ * Get work item that was redoable in the previous calulation and is now
76
+ * not anymore. This indicates that the work item was redone which should
77
+ * result in a transition to the answer view.
78
+ */
79
+ const redoneWorkItem = this._redoableStates.find((stateObj) => {
80
+ const updatedWorkItem = allWorkItems.edges.find(
81
+ (edge) => decodeId(edge.node.id) === stateObj.id
82
+ );
83
+
84
+ return (
85
+ stateObj.isRedoable && !(updatedWorkItem?.node.isRedoable ?? true)
86
+ );
87
+ });
88
+
89
+ if (redoneWorkItem) {
90
+ this.router.transitionTo("inquiry.detail.answer", redoneWorkItem.id);
91
+ }
92
+
93
+ this._setRedoableStates(allWorkItems);
71
94
  });
72
95
 
73
96
  return response;
74
97
  }
75
98
 
99
+ _setRedoableStates(allWorkItems) {
100
+ this._redoableStates = allWorkItems.edges.map((edge) => ({
101
+ id: decodeId(edge.node.id),
102
+ isRedoable: edge.node.isRedoable,
103
+ }));
104
+ }
105
+
76
106
  @dropTask
77
107
  *createInquiry(e) {
78
108
  e.preventDefault();
@@ -8,7 +8,7 @@ import { gql } from "graphql-tag";
8
8
  import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
9
9
  import config from "@projectcaluma/ember-distribution/config";
10
10
  import completeWorkItemMutation from "@projectcaluma/ember-distribution/gql/mutations/complete-work-item.graphql";
11
- import redoWorkItemMutation from "@projectcaluma/ember-distribution/gql/mutations/redo-work-item.graphql";
11
+ import reopenDistributionMutation from "@projectcaluma/ember-distribution/gql/mutations/reopen-distribution.graphql";
12
12
  import incompleteInquiriesQuery from "@projectcaluma/ember-distribution/gql/queries/incomplete-inquiries.graphql";
13
13
 
14
14
  export default class CdNavigationControlsComponent extends Component {
@@ -55,6 +55,8 @@ export default class CdNavigationControlsComponent extends Component {
55
55
  },
56
56
  });
57
57
 
58
+ yield this.config.hooks.postCompleteDistribution?.();
59
+
58
60
  yield this.distribution.refetch();
59
61
  this.router.transitionTo("index");
60
62
  } catch (e) {
@@ -76,7 +78,7 @@ export default class CdNavigationControlsComponent extends Component {
76
78
  );
77
79
 
78
80
  yield this.apollo.mutate({
79
- mutation: redoWorkItemMutation,
81
+ mutation: reopenDistributionMutation,
80
82
  variables: {
81
83
  workItem: distributionWorkItemId,
82
84
  },
package/addon/config.js CHANGED
@@ -69,6 +69,8 @@ export default function config(target, property) {
69
69
  },
70
70
  },
71
71
  permissions: {},
72
+ hooks: {},
73
+ enableReminders: true,
72
74
  },
73
75
  getOwner(this).lookup("service:calumaOptions")?.distribution ?? {}
74
76
  );
@@ -67,10 +67,12 @@ fragment InquiryDialog on WorkItem {
67
67
  createdAt
68
68
  closedAt
69
69
  status
70
+ isRedoable
70
71
  task {
71
72
  id
72
73
  slug
73
74
  }
75
+ meta
74
76
  document {
75
77
  ...InquiryRequest
76
78
  }
@@ -29,6 +29,7 @@ mutation CompleteInquiryWorkItem(
29
29
  parentWorkItem {
30
30
  id
31
31
  status
32
+ isRedoable
32
33
  }
33
34
  }
34
35
  }
@@ -1,4 +1,4 @@
1
- mutation RedoWorkItem($workItem: ID!) {
1
+ mutation ReopenDistribution($workItem: ID!) {
2
2
  redoWorkItem(input: { id: $workItem }) {
3
3
  workItem {
4
4
  id
@@ -0,0 +1,33 @@
1
+ #import InquiryStatusDocument from '../fragments/inquiry.graphql'
2
+
3
+ mutation ReopenInquiry(
4
+ $workItem: ID!
5
+ $statusQuestion: ID!
6
+ $buttonTasks: [String]!
7
+ ) {
8
+ redoWorkItem(input: { id: $workItem }) {
9
+ workItem {
10
+ id
11
+ status
12
+ isRedoable
13
+ childCase {
14
+ id
15
+ document {
16
+ id
17
+ ...InquiryStatusDocument
18
+ }
19
+ workItems(filter: [{ tasks: $buttonTasks }, { status: READY }]) {
20
+ edges {
21
+ node {
22
+ id
23
+ task {
24
+ id
25
+ slug
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,8 @@
1
+ mutation UpdateInquiryMeta($inquiry: ID!, $meta: JSONString!) {
2
+ saveWorkItem(input: { workItem: $inquiry, meta: $meta }) {
3
+ workItem {
4
+ id
5
+ meta
6
+ }
7
+ }
8
+ }
@@ -21,7 +21,7 @@ function decorator(
21
21
  const value = inquiry.document?.deadline.edges[0]?.node.value;
22
22
  const isDone = ["COMPLETED", "SKIPPED"].includes(inquiry.status);
23
23
 
24
- const { days: diff } = DateTime.fromISO(value).diffNow("days").toObject();
24
+ const diff = DateTime.fromISO(value).diffNow("days").days;
25
25
 
26
26
  const isOverdue = !isDone && diff <= 0;
27
27
  const isWarning = !isDone && diff <= this.config.warningPeriod;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectcaluma/ember-distribution",
3
- "version": "11.0.0-beta.25",
3
+ "version": "11.0.0-beta.28",
4
4
  "description": "Ember engine for the Caluma distribution module.",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -22,35 +22,35 @@
22
22
  "@embroider/macros": "^1.8.3",
23
23
  "@glimmer/component": "^1.1.2",
24
24
  "@glimmer/tracking": "^1.1.2",
25
- "@projectcaluma/ember-core": "^11.0.0-beta.25",
26
- "@projectcaluma/ember-form": "^11.0.0-beta.25",
27
- "@projectcaluma/ember-workflow": "^11.0.0-beta.25",
25
+ "@projectcaluma/ember-core": "^11.0.0-beta.28",
26
+ "@projectcaluma/ember-form": "^11.0.0-beta.28",
27
+ "@projectcaluma/ember-workflow": "^11.0.0-beta.28",
28
28
  "ember-apollo-client": "~4.0.2",
29
29
  "ember-auto-import": "^2.4.2",
30
30
  "ember-can": "^4.2.0",
31
31
  "ember-cli-babel": "^7.26.11",
32
- "ember-cli-htmlbars": "^6.1.0",
33
- "ember-concurrency": "^2.3.2",
32
+ "ember-cli-htmlbars": "^6.1.1",
33
+ "ember-concurrency": "^2.3.7",
34
34
  "ember-engines-router-service": "^0.3.0",
35
35
  "ember-fetch": "^8.1.2",
36
36
  "ember-intl": "^5.7.2",
37
37
  "ember-pikaday": "^4.0.0",
38
- "ember-resources": "^5.3.0",
38
+ "ember-resources": "^5.3.2",
39
39
  "ember-svg-jar": "^2.3.4",
40
40
  "ember-test-selectors": "^6.0.0",
41
41
  "ember-uikit": "^6.0.0",
42
42
  "graphql": "^15.8.0",
43
43
  "graphql-tag": "^2.12.6",
44
44
  "lodash.merge": "^4.6.2",
45
- "luxon": "^3.0.2",
45
+ "luxon": "^3.0.3",
46
46
  "tracked-toolbox": "^1.2.3"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@ember/optional-features": "2.0.0",
50
50
  "@ember/test-helpers": "2.8.1",
51
51
  "@embroider/test-setup": "1.8.3",
52
- "@faker-js/faker": "7.4.0",
53
- "@projectcaluma/ember-testing": "11.0.0-beta.25",
52
+ "@faker-js/faker": "7.5.0",
53
+ "@projectcaluma/ember-testing": "11.0.0-beta.28",
54
54
  "broccoli-asset-rev": "3.0.0",
55
55
  "ember-cli": "3.28.5",
56
56
  "ember-cli-code-coverage": "1.0.3",
@@ -75,7 +75,7 @@
75
75
  "npm-run-all": "4.1.5",
76
76
  "qunit": "2.19.1",
77
77
  "qunit-dom": "2.0.0",
78
- "sass": "1.54.5",
78
+ "sass": "1.54.9",
79
79
  "webpack": "5.74.0"
80
80
  },
81
81
  "engines": {
@@ -61,6 +61,14 @@ caluma:
61
61
  create-draft: "Entwurf erstellen"
62
62
  error: "Fehler beim Erstellen der {count, plural, =1 {Anfragen} other {Anfrage}}"
63
63
 
64
+ reminder:
65
+ link: "Erinnerung versenden"
66
+ confirm: "Wollen Sie wirklich eine Erinnerung für diese Anfrage versenden?"
67
+ title: "Versendete Erinnerungen"
68
+ no-reminders: "Es wurden noch keine Erinnerungen für diese Anfrage versendet."
69
+ success: "Die Erinnerung wurde erfolgreich versendet"
70
+ error: "Fehler beim Versenden der Erinnerung"
71
+
64
72
  types:
65
73
  controlling: "Angefordert"
66
74
  addressed: "Zu beantworten"
@@ -85,3 +93,8 @@ caluma:
85
93
  confirm: "Wollen Sie die Anfrage wirklich zurückziehen?"
86
94
  error: "Fehler beim Zurückziehen der Anfrage"
87
95
  status: "Zurückgezogen"
96
+
97
+ reopen-inquiry:
98
+ link: "Wiedereröffnen"
99
+ confirm: "Wollen Sie die Anfrage wirklich wiedereröffnen?"
100
+ error: "Fehler beim Wiedereröffnen der Anfrage"
@@ -62,6 +62,14 @@ caluma:
62
62
  create-draft: "Create draft"
63
63
  error: "Error while creating the {count, plural, =1 {inquiry} other {inquiries}}"
64
64
 
65
+ reminder:
66
+ link: "Send reminder"
67
+ confirm: "Do you really want to send a reminder for this inquiry?"
68
+ title: "Sent reminders"
69
+ no-reminders: "No reminders have been sent for this inquiry yet."
70
+ success: "The reminder has been sent successfully"
71
+ error: "Error while sending the reminder"
72
+
65
73
  types:
66
74
  controlling: "Requested"
67
75
  addressed: "To answer"
@@ -86,3 +94,8 @@ caluma:
86
94
  confirm: "Do you really want to withdraw the inquiry?"
87
95
  error: "Error while withdrawing the inquiry"
88
96
  status: "Withdrawn"
97
+
98
+ reopen-inquiry:
99
+ link: "Reopen"
100
+ confirm: "Do you really want to reopen the inquiry?"
101
+ error: "Error while reopening the inquiry"
@@ -61,6 +61,14 @@ caluma:
61
61
  create-draft: "Créer un brouillon"
62
62
  error: "Error lors de la création {count, plural, =1 {de la demande} other {des demandes}}"
63
63
 
64
+ reminder:
65
+ link: "Envoyer un rappel"
66
+ confirm: "Voulez-vous vraiment envoyer un rappel pour cette demande ?"
67
+ title: "Rappels envoyés"
68
+ no-reminders: Aucun rappel n'a encore été envoyé pour cette demande.
69
+ success: "Le rappel a été envoyé avec succès"
70
+ error: "Erreur lors de l'envoi du rappel"
71
+
64
72
  types:
65
73
  controlling: "Demandé"
66
74
  addressed: "A répondre"
@@ -85,3 +93,8 @@ caluma:
85
93
  confirm: "Voulez-vous vraiment retirer la demande ?"
86
94
  error: "Erreur lors du retrait de la demande"
87
95
  status: "Retirée"
96
+
97
+ reopen-inquiry:
98
+ link: "Rouvrir"
99
+ confirm: "Voulez-vous vraiment rouvrir la demande ?"
100
+ error: "Erreur lors de la réouverture de la demande"