@projectcaluma/ember-distribution 11.0.0-beta.33 → 11.0.0-beta.35

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,101 +4,131 @@ import { DateTime } from "luxon";
4
4
 
5
5
  import config from "@projectcaluma/ember-distribution/config";
6
6
 
7
+ /**
8
+ * This class contains all permission definitions for inquiries. To improve
9
+ * performance there are a few helpers and rules for optimal permission
10
+ * computation. The permissions need to be ordered by how expensive their
11
+ * computation is: the least expensive first and the most expensive last and so
12
+ * on:
13
+ *
14
+ * 1. Static config properties (e.g. `enableReminders`)
15
+ * 2. Base permission which checks for the correct task and the readonly config
16
+ * 3. Simple work item property checks (e.g. `isReady` or `isSuspended`)
17
+ * 4. Addressed / controlling group affiliation (e.g. `isAddressed` or `isControlling`)
18
+ * 5. All other computations (e.g. whether the deadline is overdue)
19
+ * 6. Custom permissions served by the host app (using `hasCustomPermission`)
20
+ */
7
21
  export default class InquiryAbility extends Ability {
8
22
  @service calumaOptions;
9
23
 
10
24
  @config config;
11
25
 
12
- get canEdit() {
26
+ hasCustomPermission(permissionName, ...args) {
27
+ return this.config.permissions[permissionName]?.(...args) ?? true;
28
+ }
29
+
30
+ get hasBasePermission() {
13
31
  return (
14
32
  !this.config.ui.readonly &&
15
- this.model?.task.slug === this.config.inquiry.task &&
16
- ["SUSPENDED", "READY"].includes(this.model?.status) &&
17
- this.model?.controllingGroups
18
- .map(String)
19
- .includes(String(this.calumaOptions.currentGroupId))
33
+ this.model?.task.slug === this.config.inquiry.task
34
+ );
35
+ }
36
+
37
+ get isReady() {
38
+ return this.model.status === "READY";
39
+ }
40
+
41
+ get isSuspended() {
42
+ return this.model.status === "SUSPENDED";
43
+ }
44
+
45
+ get isAddressed() {
46
+ return this.model.addressedGroups
47
+ .map(String)
48
+ .includes(String(this.calumaOptions.currentGroupId));
49
+ }
50
+
51
+ get isControlling() {
52
+ return this.model.controllingGroups
53
+ .map(String)
54
+ .includes(String(this.calumaOptions.currentGroupId));
55
+ }
56
+
57
+ get canEdit() {
58
+ return (
59
+ this.hasBasePermission &&
60
+ // Since editing in the status ready has the same character as sending an
61
+ // inquiry, we need to make sure that permission would be given
62
+ (this.isSuspended ||
63
+ (this.isReady &&
64
+ this.hasCustomPermission("sendInquiry", this.model))) &&
65
+ this.isControlling
20
66
  );
21
67
  }
22
68
 
23
69
  get canSend() {
24
70
  return (
25
- !this.config.ui.readonly &&
26
- this.model?.task.slug === this.config.inquiry.task &&
27
- this.model?.status === "SUSPENDED" &&
28
- (this.config.permissions.sendInquiry?.(this.model) ?? true) &&
29
- this.model?.controllingGroups
30
- .map(String)
31
- .includes(String(this.calumaOptions.currentGroupId))
71
+ this.hasBasePermission &&
72
+ this.isSuspended &&
73
+ this.isControlling &&
74
+ this.hasCustomPermission("sendInquiry", this.model)
32
75
  );
33
76
  }
34
77
 
35
78
  get canWithdraw() {
36
79
  return (
37
- !this.config.ui.readonly &&
38
- this.model?.task.slug === this.config.inquiry.task &&
39
- this.model?.status === "SUSPENDED" &&
40
- (this.config.permissions.withdrawInquiry?.(this.model) ?? true) &&
41
- this.model?.controllingGroups
42
- .map(String)
43
- .includes(String(this.calumaOptions.currentGroupId))
80
+ this.hasBasePermission &&
81
+ this.isSuspended &&
82
+ this.isControlling &&
83
+ this.hasCustomPermission("withdrawInquiry", this.model)
44
84
  );
45
85
  }
46
86
 
47
87
  get canAnswer() {
48
- return (
49
- !this.config.ui.readonly &&
50
- this.model?.task.slug === this.config.inquiry.task &&
51
- this.model?.status === "READY" &&
52
- this.model?.addressedGroups
53
- .map(String)
54
- .includes(String(this.calumaOptions.currentGroupId))
55
- );
88
+ return this.hasBasePermission && this.isReady && this.isAddressed;
56
89
  }
57
90
 
58
91
  get canEditAnswerForm() {
59
92
  return (
60
- !this.config.ui.readonly &&
61
93
  this.canAnswer &&
62
- this.model?.childCase.workItems.edges.some(
63
- (edge) => edge.node.task.__typename === "CompleteWorkflowFormTask"
94
+ this.model.childCase.workItems.edges.some(
95
+ (edge) =>
96
+ edge.node.status === "READY" &&
97
+ edge.node.task.__typename === "CompleteWorkflowFormTask"
64
98
  )
65
99
  );
66
100
  }
67
101
 
68
102
  get canCompleteChildWorkItem() {
69
103
  return (
70
- this.config.permissions.completeInquiryChildWorkItem?.(
104
+ this.hasBasePermission &&
105
+ this.hasCustomPermission(
106
+ "completeInquiryChildWorkItem",
71
107
  this.model,
72
108
  this.task
73
- ) ?? true
109
+ )
74
110
  );
75
111
  }
76
112
 
77
113
  get canReopen() {
78
114
  return (
115
+ this.hasBasePermission &&
79
116
  this.model.isRedoable &&
80
- this.model?.controllingGroups
81
- .map(String)
82
- .includes(String(this.calumaOptions.currentGroupId)) &&
83
- (this.config.permissions.reopenInquiry?.(this.model) ?? true)
117
+ this.isControlling &&
118
+ this.hasCustomPermission("reopenInquiry", this.model)
84
119
  );
85
120
  }
86
121
 
87
122
  get canSendReminder() {
88
- const deadline = DateTime.fromISO(
89
- this.model.document?.deadline.edges[0]?.node.value
90
- );
91
-
92
123
  return (
93
- !this.config.ui.readonly &&
94
124
  this.config.enableReminders &&
95
- this.model?.task.slug === this.config.inquiry.task &&
96
- this.model?.status === "READY" &&
97
- this.model?.controllingGroups
98
- .map(String)
99
- .includes(String(this.calumaOptions.currentGroupId)) &&
100
- deadline.diffNow("days").days <= 0 &&
101
- (this.config.permissions.sendReminder?.(this.model) ?? true)
125
+ this.hasBasePermission &&
126
+ this.isReady &&
127
+ this.isControlling &&
128
+ DateTime.fromISO(
129
+ this.model.document?.deadline.edges[0]?.node.value
130
+ ).diffNow("days").days <= 0 &&
131
+ this.hasCustomPermission("sendReminder", this.model)
102
132
  );
103
133
  }
104
134
  }
@@ -1,11 +1,11 @@
1
1
  <div class="uk-text-large uk-flex uk-flex-middle" data-test-document-header>
2
- <div class="uk-width-expand">
2
+ <div class="uk-width-expand uk-flex-inline uk-flex-middle">
3
3
  {{@name}}
4
4
  {{#if @group}}
5
5
  ({{group-name @group}})
6
6
  {{/if}}
7
7
  {{#if @status}}
8
- <UkLabel @label={{@status}} class="uk-margin-left" />
8
+ <UkLabel @label={{@status}} class="uk-margin-left uk-text-default" />
9
9
  {{/if}}
10
10
  </div>
11
11
  {{yield}}
@@ -2,14 +2,15 @@
2
2
  <div class="uk-flex uk-flex-middle uk-text-large" data-test-title>
3
3
  {{#if (eq @type "request")}}
4
4
  <UkIcon @icon="forward" class="uk-margin-small-right" />
5
- <div class="uk-width-expand uk-margin-small-right">
5
+ <div
6
+ class="uk-width-expand uk-margin-small-right uk-flex-inline uk-flex-middle"
7
+ >
6
8
  {{group-name @inquiry.controllingGroups}}
7
- {{#if
8
- (and
9
- (can "answer inquiry" @inquiry) (not @disabled) this.answerStatus
10
- )
11
- }}
12
- <UkLabel @label={{this.answerStatus}} class="uk-margin-left" />
9
+ {{#if this.status}}
10
+ <UkLabel
11
+ @label={{this.status}}
12
+ class="uk-margin-left uk-text-default"
13
+ />
13
14
  {{/if}}
14
15
  </div>
15
16
  {{else if (eq @type "answer")}}
@@ -18,6 +18,7 @@ export default class CdInquiryDialogInquiryPartComponent extends Component {
18
18
  @service router;
19
19
  @service intl;
20
20
  @service calumaOptions;
21
+ @service abilities;
21
22
 
22
23
  @queryManager apollo;
23
24
 
@@ -25,6 +26,25 @@ export default class CdInquiryDialogInquiryPartComponent extends Component {
25
26
 
26
27
  @inquiryAnswerStatus answerStatus;
27
28
 
29
+ get status() {
30
+ if (!this.args.type === "request" || this.args.disabled) {
31
+ return null;
32
+ }
33
+
34
+ const inquiry = this.args.inquiry;
35
+
36
+ if (
37
+ inquiry.status === "SUSPENDED" &&
38
+ this.abilities.can("edit inquiry", inquiry)
39
+ ) {
40
+ return this.intl.t("caluma.distribution.status.draft");
41
+ } else if (this.abilities.can("answer inquiry", inquiry)) {
42
+ return this.answerStatus;
43
+ }
44
+
45
+ return null;
46
+ }
47
+
28
48
  get date() {
29
49
  const key = this.args.type === "request" ? "createdAt" : "closedAt";
30
50
 
@@ -24,7 +24,12 @@ export default class CdInquiryDialogComponent extends Component {
24
24
  }
25
25
 
26
26
  get inquiries() {
27
- return this._inquiries.value?.allWorkItems.edges.map((edge) => edge.node);
27
+ return this._inquiries.value?.allWorkItems.edges
28
+ .map((edge) => edge.node)
29
+ .filter(
30
+ // suspended inquiries should only be visible to its creator
31
+ (node) => this.currentGroupIsCreator || node.status !== "SUSPENDED"
32
+ );
28
33
  }
29
34
 
30
35
  _inquiries = trackedTask(this, this.fetchDialog, () => [
@@ -38,6 +43,7 @@ export default class CdInquiryDialogComponent extends Component {
38
43
  *fetchDialog(from, to, caseId, config) {
39
44
  const response = yield this.apollo.watchQuery({
40
45
  query: inquiryDialogQuery,
46
+ fetchPolicy: "cache-and-network",
41
47
  variables: {
42
48
  from,
43
49
  to,
@@ -14,6 +14,9 @@ export default class CdNavigationStatusIndicatorComponent extends Component {
14
14
  @inquiryDeadline deadline;
15
15
 
16
16
  get showDeadlineIndicator() {
17
- return this.deadline.isOverdue || this.deadline.isWarning;
17
+ return (
18
+ ["addressed", "controlling"].includes(this.args.type) &&
19
+ (this.deadline.isOverdue || this.deadline.isWarning)
20
+ );
18
21
  }
19
22
  }
package/addon/config.js CHANGED
@@ -6,6 +6,7 @@ export const INQUIRY_STATUS = {
6
6
  DRAFT: "draft",
7
7
  SKIPPED: "skipped",
8
8
  SENT: "sent",
9
+ IN_PROGRESS: "in-progress",
9
10
  POSITIVE: "positive",
10
11
  NEGATIVE: "negative",
11
12
  NEEDS_INTERACTION: "needs-interaction",
@@ -45,7 +46,11 @@ export default function config(target, property) {
45
46
  "confirm-inquiry-answer": {
46
47
  color: "primary",
47
48
  label: "caluma.distribution.answer.buttons.confirm.label",
48
- status: "caluma.distribution.answer.buttons.confirm.status",
49
+ status: {
50
+ label: "caluma.distribution.answer.buttons.confirm.status",
51
+ color: { addressed: "muted", controlling: "emphasis" },
52
+ icon: "user",
53
+ },
49
54
  willCompleteInquiry: true,
50
55
  },
51
56
  "revise-inquiry-answer": {
@@ -28,6 +28,7 @@ fragment InquiryAnswerButtons on Case {
28
28
  id
29
29
  status
30
30
  closedAt
31
+ closedByUser
31
32
  task {
32
33
  id
33
34
  slug
@@ -39,6 +40,7 @@ fragment InquiryAnswerButtons on Case {
39
40
 
40
41
  fragment InquiryAnswer on Document {
41
42
  ...InquiryAnswerStatus
43
+ modifiedContentAt
42
44
  info: answers(filter: [{ questions: $answerInfoQuestions }]) {
43
45
  edges {
44
46
  node {
@@ -1,4 +1,4 @@
1
- # import InquiryAnswerStatus from '../fragments/inquiry-answer.graphql'
1
+ # import InquiryAnswerStatus, InquiryAnswerButtons from '../fragments/inquiry-answer.graphql'
2
2
  # import InquiryRequestDeadline from '../fragments/inquiry-request.graphql'
3
3
 
4
4
  fragment NavigationInquiry on WorkItem {
@@ -14,8 +14,10 @@ fragment NavigationInquiry on WorkItem {
14
14
  id
15
15
  document {
16
16
  id
17
+ modifiedContentAt
17
18
  ...InquiryAnswerStatus
18
19
  }
20
+ ...InquiryAnswerButtons
19
21
  }
20
22
  }
21
23
 
@@ -25,6 +27,7 @@ query Navigation(
25
27
  $deadlineQuestion: ID
26
28
  $currentGroup: String!
27
29
  $caseId: ID!
30
+ $buttonTasks: [String]!
28
31
  ) {
29
32
  controlling: allWorkItems(
30
33
  filter: [
@@ -9,7 +9,6 @@ import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
9
9
  import config from "@projectcaluma/ember-distribution/config";
10
10
  import createInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/create-inquiry.graphql";
11
11
  import controlsQuery from "@projectcaluma/ember-distribution/gql/queries/controls.graphql";
12
- import inquiryDialogQuery from "@projectcaluma/ember-distribution/gql/queries/inquiry-dialog.graphql";
13
12
  import navigationQuery from "@projectcaluma/ember-distribution/gql/queries/navigation.graphql";
14
13
  import uniqueByGroups from "@projectcaluma/ember-distribution/utils/unique-by-groups";
15
14
 
@@ -75,6 +74,7 @@ export default class DistributionService extends Service {
75
74
  currentGroup: String(this.calumaOptions.currentGroupId),
76
75
  statusQuestion: this.config.inquiry.answer.statusQuestion,
77
76
  deadlineQuestion: this.config.inquiry.deadlineQuestion,
77
+ buttonTasks: Object.keys(this.config.inquiry.answer.buttons),
78
78
  },
79
79
  });
80
80
 
@@ -107,22 +107,6 @@ export default class DistributionService extends Service {
107
107
  // get create inquiry work item to complete
108
108
  const createId = decodeId(this.controls.value?.create.edges[0].node.id);
109
109
 
110
- // refetch dialog queries of the groups that will have a new inquiry
111
- const refetchQueries = groups.map((group) => ({
112
- query: inquiryDialogQuery,
113
- variables: {
114
- from: String(this.calumaOptions.currentGroupId),
115
- to: String(group),
116
- caseId: this.caseId,
117
- task: this.config.inquiry.task,
118
- infoQuestion: this.config.inquiry.infoQuestion,
119
- deadlineQuestion: this.config.inquiry.deadlineQuestion,
120
- statusQuestion: this.config.inquiry.answer.statusQuestion,
121
- answerInfoQuestions: this.config.inquiry.answer.infoQuestions,
122
- buttonTasks: Object.keys(this.config.inquiry.answer.buttons),
123
- },
124
- }));
125
-
126
110
  // create new inquiries
127
111
  yield this.apollo.mutate({
128
112
  mutation: createInquiryMutation,
@@ -133,7 +117,6 @@ export default class DistributionService extends Service {
133
117
  addressed_groups: groups.map(String),
134
118
  }),
135
119
  },
136
- refetchQueries,
137
120
  });
138
121
 
139
122
  // refetch navigation and controls data
@@ -26,7 +26,9 @@ function decorator(
26
26
  this.config.inquiry.answer.buttons
27
27
  ).find(([task]) => readyWorkItems.includes(task))?.[1];
28
28
 
29
- return buttonConfig?.status ? this.intl.t(buttonConfig.status) : null;
29
+ return buttonConfig?.status
30
+ ? this.intl.t(buttonConfig.status.label ?? buttonConfig.status)
31
+ : null;
30
32
  },
31
33
  };
32
34
  }
@@ -8,6 +8,7 @@ export const ICON_MAP = {
8
8
  [INQUIRY_STATUS.DRAFT]: "commenting",
9
9
  [INQUIRY_STATUS.SKIPPED]: "lock",
10
10
  [INQUIRY_STATUS.SENT]: "comment",
11
+ [INQUIRY_STATUS.IN_PROGRESS]: "file-edit",
11
12
  [INQUIRY_STATUS.POSITIVE]: "check",
12
13
  [INQUIRY_STATUS.NEGATIVE]: "close",
13
14
  [INQUIRY_STATUS.NEEDS_INTERACTION]: "file-text",
@@ -17,6 +18,7 @@ export const COLOR_MAP = {
17
18
  [INQUIRY_STATUS.DRAFT]: "muted",
18
19
  [INQUIRY_STATUS.SKIPPED]: "muted",
19
20
  [INQUIRY_STATUS.SENT]: "emphasis",
21
+ [INQUIRY_STATUS.IN_PROGRESS]: { addressed: "muted", controlling: "emphasis" },
20
22
  [INQUIRY_STATUS.POSITIVE]: "success",
21
23
  [INQUIRY_STATUS.NEGATIVE]: "danger",
22
24
  [INQUIRY_STATUS.NEEDS_INTERACTION]: "warning",
@@ -41,16 +43,51 @@ function decorator(
41
43
  return {
42
44
  get() {
43
45
  const inquiry = get(this, inquiryProperty);
44
- const isAddressed = get(this, inquiryTypeProperty) === "addressed";
46
+ const inquiryType = get(this, inquiryTypeProperty);
47
+ const isAddressed = inquiryType === "addressed";
48
+ const isControlling = inquiryType === "controlling";
49
+
45
50
  const isDraft = isAddressed
46
51
  ? inquiry.status === "READY"
47
52
  : inquiry.status === "SUSPENDED";
48
53
  const isSent = !isAddressed && inquiry.status === "READY";
49
54
  const isSkipped = inquiry.status === "SKIPPED";
55
+ const isInProgress =
56
+ (isAddressed || isControlling) &&
57
+ inquiry.status === "READY" &&
58
+ inquiry.childCase?.document?.modifiedContentAt;
59
+
60
+ const buttonConfig = this.config.inquiry.answer.buttons;
61
+ const inquiryAnswerStatus =
62
+ buttonConfig &&
63
+ (isAddressed || isControlling) &&
64
+ inquiry.status === "READY"
65
+ ? inquiry?.childCase?.workItems.edges
66
+ .filter((edge) => edge.node.status === "READY")
67
+ .map((edge) => {
68
+ const config = buttonConfig[edge.node.task.slug]?.status;
69
+ if (!config?.icon) {
70
+ return null;
71
+ }
72
+
73
+ return {
74
+ ...config,
75
+ label: this.intl.t(config.label),
76
+ color: config.color[inquiryType] ?? config.color,
77
+ };
78
+ })
79
+ .filter(Boolean)[0]
80
+ : null;
81
+
82
+ if (inquiryAnswerStatus) {
83
+ return inquiryAnswerStatus;
84
+ }
50
85
 
51
86
  const answer = inquiry.childCase?.document.status.edges[0]?.node;
52
87
  const slug = isSkipped
53
88
  ? INQUIRY_STATUS.SKIPPED
89
+ : isInProgress
90
+ ? INQUIRY_STATUS.IN_PROGRESS
54
91
  : isDraft
55
92
  ? INQUIRY_STATUS.DRAFT
56
93
  : isSent
@@ -63,7 +100,7 @@ function decorator(
63
100
  !isSkipped && !isDraft && !isSent
64
101
  ? answer?.selectedOption.label
65
102
  : this.intl.t(`caluma.distribution.status.${slug}`),
66
- color: COLOR_MAP[slug],
103
+ color: COLOR_MAP[slug][inquiryType] ?? COLOR_MAP[slug],
67
104
  icon: ICON_MAP[slug],
68
105
  };
69
106
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectcaluma/ember-distribution",
3
- "version": "11.0.0-beta.33",
3
+ "version": "11.0.0-beta.35",
4
4
  "description": "Ember engine for the Caluma distribution module.",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -23,9 +23,9 @@
23
23
  "@embroider/macros": "^1.9.0",
24
24
  "@glimmer/component": "^1.1.2",
25
25
  "@glimmer/tracking": "^1.1.2",
26
- "@projectcaluma/ember-core": "^11.0.0-beta.33",
27
- "@projectcaluma/ember-form": "^11.0.0-beta.33",
28
- "@projectcaluma/ember-workflow": "^11.0.0-beta.33",
26
+ "@projectcaluma/ember-core": "^11.0.0-beta.35",
27
+ "@projectcaluma/ember-form": "^11.0.0-beta.35",
28
+ "@projectcaluma/ember-workflow": "^11.0.0-beta.35",
29
29
  "ember-apollo-client": "~4.0.2",
30
30
  "ember-auto-import": "^2.4.3",
31
31
  "ember-can": "^4.2.0",
@@ -36,8 +36,8 @@
36
36
  "ember-fetch": "^8.1.2",
37
37
  "ember-flatpickr": "^3.2.3",
38
38
  "ember-intl": "^5.7.2",
39
- "ember-resources": "^5.4.0",
40
- "ember-svg-jar": "^2.4.1",
39
+ "ember-resources": "^5.5.0",
40
+ "ember-svg-jar": "^2.4.2",
41
41
  "ember-test-selectors": "^6.0.0",
42
42
  "ember-uikit": "^6.1.0",
43
43
  "graphql": "^15.8.0",
@@ -51,7 +51,7 @@
51
51
  "@ember/test-helpers": "2.7.0",
52
52
  "@embroider/test-setup": "1.8.3",
53
53
  "@faker-js/faker": "7.6.0",
54
- "@projectcaluma/ember-testing": "11.0.0-beta.33",
54
+ "@projectcaluma/ember-testing": "11.0.0-beta.35",
55
55
  "broccoli-asset-rev": "3.0.0",
56
56
  "ember-cli": "4.8.0",
57
57
  "ember-cli-code-coverage": "1.0.3",
@@ -72,7 +72,7 @@
72
72
  "loader.js": "4.7.0",
73
73
  "miragejs": "0.1.45",
74
74
  "npm-run-all": "4.1.5",
75
- "qunit": "2.19.2",
75
+ "qunit": "2.19.3",
76
76
  "qunit-dom": "2.0.0",
77
77
  "sass": "1.55.0",
78
78
  "webpack": "5.74.0"
@@ -103,6 +103,7 @@ caluma:
103
103
  draft: "Entwurf"
104
104
  skipped: "Vorzeitig beendet"
105
105
  sent: "Versendet"
106
+ in-progress: "In Bearbeitung"
106
107
  positive: "Positiv"
107
108
  negative: "Negativ"
108
109
  needs-interaction: "Aktion erforderlich"
@@ -103,6 +103,7 @@ caluma:
103
103
  draft: "Draft"
104
104
  skipped: "Aborted"
105
105
  sent: "Sent"
106
+ in-progress: "In Progress"
106
107
  positive: "Positive"
107
108
  negative: "Negative"
108
109
  needs-interaction: "Needs interaction"
@@ -15,7 +15,7 @@ caluma:
15
15
  demandes ouvertes}} </b> sur la circulation actuelle. Si vous clôturez la
16
16
  circulation, toutes les demandes ouvertes seront annulées. Voulez-vous
17
17
  continuer ?"
18
- complete-confirm-empty: "Vous voulez vraiment fermer la circulation ?"
18
+ complete-confirm-empty: "Vous voulez vraiment clore la circulation ?"
19
19
  skip-confirm: "Vous voulez vraiment sauter la circulation ?"
20
20
  reopen-confirm: "Vous voulez vraiment rouvrir la circulation ?"
21
21
  send-error: "Erreur lors de l'envoi des demandes ouvertes"
@@ -77,11 +77,11 @@ caluma:
77
77
  title: "Nouvelle demande"
78
78
  search: "Chercher..."
79
79
  suggestions: "Propositions"
80
- empty: "Aucune services n'a été trouvée"
80
+ empty: "Aucune service n'a été trouvée"
81
81
  groups: "{count} {count, plural, =1 {service} other {services}}"
82
82
  selected: "{count, plural, =1 {sélectionné} other {sélectionnés}}"
83
83
  reset: "Réinitialiser"
84
- create-draft: "Créer un brouillon"
84
+ create-draft: "Créer le brouillon"
85
85
  continue: "Continuer"
86
86
  back: "Retour"
87
87
  error: "Error lors de la création {count, plural, =1 {de la demande} other {des demandes}}"
@@ -90,7 +90,7 @@ caluma:
90
90
  link: "Envoyer un rappel"
91
91
  confirm: "Voulez-vous vraiment envoyer un rappel pour cette demande ?"
92
92
  title: "Rappels envoyés"
93
- no-reminders: Aucun rappel n'a encore été envoyé pour cette demande.
93
+ no-reminders: "Aucun rappel n'a encore été envoyé pour cette demande."
94
94
  success: "Le rappel a été envoyé avec succès"
95
95
  error: "Erreur lors de l'envoi du rappel"
96
96
 
@@ -103,6 +103,7 @@ caluma:
103
103
  draft: "Brouillon"
104
104
  skipped: "Terminé prématurément"
105
105
  sent: "Envoyé"
106
+ in-progress: "En cours"
106
107
  positive: "Positif"
107
108
  negative: "Negatif"
108
109
  needs-interaction: "Action nécessaire"