@weaver-apps/service-desk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/weaver-apps-service-desk-desk-list-page-DPxs6zRX.mjs +74 -0
- package/fesm2022/weaver-apps-service-desk-desk-list-page-DPxs6zRX.mjs.map +1 -0
- package/fesm2022/weaver-apps-service-desk-desk-page-_ZyGwKSa.mjs +781 -0
- package/fesm2022/weaver-apps-service-desk-desk-page-_ZyGwKSa.mjs.map +1 -0
- package/fesm2022/weaver-apps-service-desk-service-desk-gateway-BK42Rgow.mjs +48 -0
- package/fesm2022/weaver-apps-service-desk-service-desk-gateway-BK42Rgow.mjs.map +1 -0
- package/fesm2022/weaver-apps-service-desk-service-desk-paths-BmQrbz-V.mjs +8 -0
- package/fesm2022/weaver-apps-service-desk-service-desk-paths-BmQrbz-V.mjs.map +1 -0
- package/fesm2022/weaver-apps-service-desk.mjs +4 -875
- package/fesm2022/weaver-apps-service-desk.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
import { a as serviceDeskIconNames, s as serviceDeskHost, t as SERVICE_DESK_GATEWAY } from "./weaver-apps-service-desk-service-desk-gateway-BK42Rgow.mjs";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, computed, inject, input, output, resource, signal, viewChild } from "@angular/core";
|
|
4
|
+
import { TranslocoPipe, TranslocoService, translateObjectSignal } from "@jsverse/transloco";
|
|
5
|
+
import { toSignal } from "@angular/core/rxjs-interop";
|
|
6
|
+
import { ActivatedRoute } from "@angular/router";
|
|
7
|
+
import { map } from "rxjs";
|
|
8
|
+
import { DialogRef } from "@loomweaver/plugin-sdk";
|
|
9
|
+
import { DataGrid, ListFilter, listingDatasource, openOnRow } from "@weaver-apps/data-grid";
|
|
10
|
+
function activeLocale() {
|
|
11
|
+
const transloco = inject(TranslocoService);
|
|
12
|
+
return toSignal(transloco.langChanges$, { initialValue: transloco.getActiveLang() });
|
|
13
|
+
}
|
|
14
|
+
const ServiceRequestOrigin = {
|
|
15
|
+
manual: "manual",
|
|
16
|
+
voiceChat: "voiceChat",
|
|
17
|
+
textChat: "textChat",
|
|
18
|
+
widget: "widget",
|
|
19
|
+
email: "email",
|
|
20
|
+
phone: "phone"
|
|
21
|
+
};
|
|
22
|
+
const ServiceRequestPriority = {
|
|
23
|
+
low: "low",
|
|
24
|
+
normal: "normal",
|
|
25
|
+
high: "high",
|
|
26
|
+
urgent: "urgent"
|
|
27
|
+
};
|
|
28
|
+
const ServiceRequestStatus = {
|
|
29
|
+
open: "open",
|
|
30
|
+
inProgress: "inProgress",
|
|
31
|
+
completed: "completed",
|
|
32
|
+
cancelled: "cancelled"
|
|
33
|
+
};
|
|
34
|
+
const ServiceRequestType = {
|
|
35
|
+
inquiry: "inquiry",
|
|
36
|
+
task: "task",
|
|
37
|
+
callbackRequest: "callbackRequest",
|
|
38
|
+
conversationSummary: "conversationSummary",
|
|
39
|
+
complaint: "complaint",
|
|
40
|
+
quote: "quote"
|
|
41
|
+
};
|
|
42
|
+
const requestTypes = Object.values(ServiceRequestType);
|
|
43
|
+
const requestPriorities = Object.values(ServiceRequestPriority);
|
|
44
|
+
const requestOrigins = Object.values(ServiceRequestOrigin);
|
|
45
|
+
const settableStatuses = [ServiceRequestStatus.open, ServiceRequestStatus.inProgress];
|
|
46
|
+
function isClosed(status) {
|
|
47
|
+
return status === ServiceRequestStatus.completed || status === ServiceRequestStatus.cancelled;
|
|
48
|
+
}
|
|
49
|
+
function localDate(value) {
|
|
50
|
+
const pad = (part) => `${part}`.padStart(2, "0");
|
|
51
|
+
return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}`;
|
|
52
|
+
}
|
|
53
|
+
function pick(choices, value) {
|
|
54
|
+
return choices.find((choice) => choice === value);
|
|
55
|
+
}
|
|
56
|
+
var RequestDialog = class RequestDialog {
|
|
57
|
+
dialog = inject(DialogRef);
|
|
58
|
+
gateway = inject(SERVICE_DESK_GATEWAY);
|
|
59
|
+
data = this.dialog.data;
|
|
60
|
+
existing = this.data.request;
|
|
61
|
+
editing = this.existing !== null;
|
|
62
|
+
closed = this.existing !== null && isClosed(this.existing.status);
|
|
63
|
+
types = requestTypes;
|
|
64
|
+
priorities = requestPriorities;
|
|
65
|
+
origins = requestOrigins;
|
|
66
|
+
statuses = settableStatuses;
|
|
67
|
+
title = signal(this.existing?.title ?? "", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
|
|
68
|
+
type = signal(this.existing?.type ?? ServiceRequestType.inquiry, ...ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []);
|
|
69
|
+
priority = signal(this.existing?.priority ?? ServiceRequestPriority.normal, ...ngDevMode ? [{ debugName: "priority" }] : /* istanbul ignore next */ []);
|
|
70
|
+
origin = signal(this.existing?.origin ?? ServiceRequestOrigin.manual, ...ngDevMode ? [{ debugName: "origin" }] : /* istanbul ignore next */ []);
|
|
71
|
+
status = signal(this.existing?.status ?? "open", ...ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []);
|
|
72
|
+
contactName = signal(this.existing?.contactName ?? "", ...ngDevMode ? [{ debugName: "contactName" }] : /* istanbul ignore next */ []);
|
|
73
|
+
contactPhone = signal(this.existing?.contactPhone ?? "", ...ngDevMode ? [{ debugName: "contactPhone" }] : /* istanbul ignore next */ []);
|
|
74
|
+
contactEmail = signal(this.existing?.contactEmail ?? "", ...ngDevMode ? [{ debugName: "contactEmail" }] : /* istanbul ignore next */ []);
|
|
75
|
+
assignee = signal(this.existing?.assignee ?? "", ...ngDevMode ? [{ debugName: "assignee" }] : /* istanbul ignore next */ []);
|
|
76
|
+
dueDate = signal(this.existing?.dueAt ? localDate(new Date(this.existing.dueAt)) : "", ...ngDevMode ? [{ debugName: "dueDate" }] : /* istanbul ignore next */ []);
|
|
77
|
+
description = signal(this.existing?.description ?? "", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
|
|
78
|
+
cancellationReason = this.existing?.cancellationReason ?? null;
|
|
79
|
+
saving = signal(false, ...ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []);
|
|
80
|
+
problem = signal("", ...ngDevMode ? [{ debugName: "problem" }] : /* istanbul ignore next */ []);
|
|
81
|
+
persisted = false;
|
|
82
|
+
bind(target, event) {
|
|
83
|
+
target.set(event.target.value);
|
|
84
|
+
}
|
|
85
|
+
chooseType(event) {
|
|
86
|
+
this.choose(this.type, requestTypes, event);
|
|
87
|
+
}
|
|
88
|
+
choosePriority(event) {
|
|
89
|
+
this.choose(this.priority, requestPriorities, event);
|
|
90
|
+
}
|
|
91
|
+
chooseOrigin(event) {
|
|
92
|
+
this.choose(this.origin, requestOrigins, event);
|
|
93
|
+
}
|
|
94
|
+
chooseStatus(event) {
|
|
95
|
+
this.choose(this.status, settableStatuses, event);
|
|
96
|
+
}
|
|
97
|
+
close() {
|
|
98
|
+
this.dialog.close(this.persisted);
|
|
99
|
+
}
|
|
100
|
+
async save() {
|
|
101
|
+
if (!this.title().trim()) {
|
|
102
|
+
this.problem.set("weaver-apps-service-desk.dialog.titleRequired");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.saving.set(true);
|
|
106
|
+
try {
|
|
107
|
+
const changes = this.changes();
|
|
108
|
+
const outcome = this.existing ? await this.gateway.edit(this.data.deskId, this.existing.id, changes) : await this.gateway.raise(this.data.deskId, {
|
|
109
|
+
...changes,
|
|
110
|
+
origin: this.origin()
|
|
111
|
+
});
|
|
112
|
+
this.settle(await this.applyStatus(outcome));
|
|
113
|
+
} catch {
|
|
114
|
+
this.problem.set("weaver-apps-service-desk.errors.save");
|
|
115
|
+
} finally {
|
|
116
|
+
this.saving.set(false);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
changes() {
|
|
120
|
+
const keptDue = this.existing?.dueAt && localDate(new Date(this.existing.dueAt)) === this.dueDate() ? this.existing.dueAt : null;
|
|
121
|
+
if (keptDue) return {
|
|
122
|
+
...this.fields(),
|
|
123
|
+
dueAt: keptDue
|
|
124
|
+
};
|
|
125
|
+
const due = this.dueDate() ? /* @__PURE__ */ new Date(`${this.dueDate()}T12:00`) : null;
|
|
126
|
+
return {
|
|
127
|
+
...this.fields(),
|
|
128
|
+
dueAt: due && !Number.isNaN(due.getTime()) ? due.toISOString() : null
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
fields() {
|
|
132
|
+
return {
|
|
133
|
+
title: this.title().trim(),
|
|
134
|
+
description: this.optional(this.description()),
|
|
135
|
+
type: this.type(),
|
|
136
|
+
priority: this.priority(),
|
|
137
|
+
contactName: this.optional(this.contactName()),
|
|
138
|
+
contactPhone: this.optional(this.contactPhone()),
|
|
139
|
+
contactEmail: this.optional(this.contactEmail()),
|
|
140
|
+
assignee: this.optional(this.assignee())
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async applyStatus(outcome) {
|
|
144
|
+
if (outcome.kind === "saved") {
|
|
145
|
+
this.existing = outcome.request;
|
|
146
|
+
this.persisted = true;
|
|
147
|
+
}
|
|
148
|
+
if (outcome.kind !== "saved" || outcome.request.status === this.status()) return outcome;
|
|
149
|
+
return this.gateway.setStatus(this.data.deskId, outcome.request.id, this.status());
|
|
150
|
+
}
|
|
151
|
+
settle(outcome) {
|
|
152
|
+
const messages = {
|
|
153
|
+
closed: "weaver-apps-service-desk.dialog.closed",
|
|
154
|
+
changed: "weaver-apps-service-desk.dialog.changed",
|
|
155
|
+
invalid: "weaver-apps-service-desk.dialog.invalid",
|
|
156
|
+
missing: "weaver-apps-service-desk.dialog.missing"
|
|
157
|
+
};
|
|
158
|
+
if (outcome.kind === "saved") {
|
|
159
|
+
this.dialog.close(true);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.problem.set(messages[outcome.kind]);
|
|
163
|
+
}
|
|
164
|
+
choose(target, choices, event) {
|
|
165
|
+
const chosen = pick(choices, event.target.value);
|
|
166
|
+
if (chosen) target.set(chosen);
|
|
167
|
+
}
|
|
168
|
+
optional(value) {
|
|
169
|
+
return value.trim() ? value.trim() : null;
|
|
170
|
+
}
|
|
171
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
172
|
+
minVersion: "12.0.0",
|
|
173
|
+
version: "22.2.3",
|
|
174
|
+
ngImport: i0,
|
|
175
|
+
type: RequestDialog,
|
|
176
|
+
deps: [],
|
|
177
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
178
|
+
});
|
|
179
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
180
|
+
minVersion: "17.0.0",
|
|
181
|
+
version: "22.2.3",
|
|
182
|
+
type: RequestDialog,
|
|
183
|
+
isStandalone: true,
|
|
184
|
+
selector: "wa-request-dialog",
|
|
185
|
+
ngImport: i0,
|
|
186
|
+
template: "<form class=\"flex flex-col gap-4\" (submit)=\"$event.preventDefault(); save()\">\n @if (closed) {\n <p class=\"text-sm text-content-faint\" role=\"status\">\n {{ 'weaver-apps-service-desk.dialog.closedNote' | transloco }}\n @if (cancellationReason) {\n {{ 'weaver-apps-service-desk.dialog.reason' | transloco: { reason: cancellationReason } }}\n }\n </p>\n }\n\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.title' | transloco }}\n <input class=\"lw-field\" required [disabled]=\"closed\" [value]=\"title()\" (input)=\"bind(title, $event)\" />\n </label>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.type' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"chooseType($event)\">\n @for (choice of types; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === type()\">{{ 'weaver-apps-service-desk.type.' + choice | transloco }}</option>\n }\n </select>\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.priority' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"choosePriority($event)\">\n @for (choice of priorities; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === priority()\">{{ 'weaver-apps-service-desk.priority.' + choice | transloco }}</option>\n }\n </select>\n </label>\n @if (editing) {\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.status' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"chooseStatus($event)\">\n @if (closed) {\n <option selected>{{ 'weaver-apps-service-desk.status.' + status() | transloco }}</option>\n } @else {\n @for (choice of statuses; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === status()\">{{ 'weaver-apps-service-desk.status.' + choice | transloco }}</option>\n }\n }\n </select>\n </label>\n } @else {\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.origin' | transloco }}\n <select class=\"lw-field\" (change)=\"chooseOrigin($event)\">\n @for (choice of origins; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === origin()\">{{ 'weaver-apps-service-desk.origin.' + choice | transloco }}</option>\n }\n </select>\n </label>\n }\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactName' | transloco }}\n <input class=\"lw-field\" [disabled]=\"closed\" [value]=\"contactName()\" (input)=\"bind(contactName, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactPhone' | transloco }}\n <input class=\"lw-field\" type=\"tel\" [disabled]=\"closed\" [value]=\"contactPhone()\" (input)=\"bind(contactPhone, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactEmail' | transloco }}\n <input class=\"lw-field\" type=\"email\" [disabled]=\"closed\" [value]=\"contactEmail()\" (input)=\"bind(contactEmail, $event)\" />\n </label>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.assignee' | transloco }}\n <input class=\"lw-field\" [disabled]=\"closed\" [value]=\"assignee()\" (input)=\"bind(assignee, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.due' | transloco }}\n <input class=\"lw-field\" type=\"date\" [disabled]=\"closed\" [value]=\"dueDate()\" (input)=\"bind(dueDate, $event)\" />\n </label>\n </div>\n\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.description' | transloco }}\n <textarea class=\"lw-field\" rows=\"3\" [disabled]=\"closed\" [value]=\"description()\" (input)=\"bind(description, $event)\"></textarea>\n </label>\n\n @if (problem()) {\n <p class=\"text-sm text-negative\" role=\"alert\">{{ problem() | transloco }}</p>\n }\n\n <div class=\"flex justify-end gap-2\">\n <button type=\"button\" class=\"lw-btn lw-btn--default\" (click)=\"close()\">{{ (closed ? 'weaver-apps-service-desk.dialog.close' : 'weaver-apps-service-desk.dialog.cancel') | transloco }}</button>\n @if (!closed) {\n <button type=\"submit\" class=\"lw-btn lw-btn--primary\" [disabled]=\"saving()\">{{ 'weaver-apps-service-desk.dialog.save' | transloco }}</button>\n }\n </div>\n</form>\n",
|
|
187
|
+
dependencies: [{
|
|
188
|
+
kind: "pipe",
|
|
189
|
+
type: TranslocoPipe,
|
|
190
|
+
name: "transloco"
|
|
191
|
+
}],
|
|
192
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
196
|
+
minVersion: "12.0.0",
|
|
197
|
+
version: "22.2.3",
|
|
198
|
+
ngImport: i0,
|
|
199
|
+
type: RequestDialog,
|
|
200
|
+
decorators: [{
|
|
201
|
+
type: Component,
|
|
202
|
+
args: [{
|
|
203
|
+
selector: "wa-request-dialog",
|
|
204
|
+
imports: [TranslocoPipe],
|
|
205
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
206
|
+
template: "<form class=\"flex flex-col gap-4\" (submit)=\"$event.preventDefault(); save()\">\n @if (closed) {\n <p class=\"text-sm text-content-faint\" role=\"status\">\n {{ 'weaver-apps-service-desk.dialog.closedNote' | transloco }}\n @if (cancellationReason) {\n {{ 'weaver-apps-service-desk.dialog.reason' | transloco: { reason: cancellationReason } }}\n }\n </p>\n }\n\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.title' | transloco }}\n <input class=\"lw-field\" required [disabled]=\"closed\" [value]=\"title()\" (input)=\"bind(title, $event)\" />\n </label>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.type' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"chooseType($event)\">\n @for (choice of types; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === type()\">{{ 'weaver-apps-service-desk.type.' + choice | transloco }}</option>\n }\n </select>\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.priority' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"choosePriority($event)\">\n @for (choice of priorities; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === priority()\">{{ 'weaver-apps-service-desk.priority.' + choice | transloco }}</option>\n }\n </select>\n </label>\n @if (editing) {\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.status' | transloco }}\n <select class=\"lw-field\" [disabled]=\"closed\" (change)=\"chooseStatus($event)\">\n @if (closed) {\n <option selected>{{ 'weaver-apps-service-desk.status.' + status() | transloco }}</option>\n } @else {\n @for (choice of statuses; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === status()\">{{ 'weaver-apps-service-desk.status.' + choice | transloco }}</option>\n }\n }\n </select>\n </label>\n } @else {\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.origin' | transloco }}\n <select class=\"lw-field\" (change)=\"chooseOrigin($event)\">\n @for (choice of origins; track choice) {\n <option [value]=\"choice\" [selected]=\"choice === origin()\">{{ 'weaver-apps-service-desk.origin.' + choice | transloco }}</option>\n }\n </select>\n </label>\n }\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactName' | transloco }}\n <input class=\"lw-field\" [disabled]=\"closed\" [value]=\"contactName()\" (input)=\"bind(contactName, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactPhone' | transloco }}\n <input class=\"lw-field\" type=\"tel\" [disabled]=\"closed\" [value]=\"contactPhone()\" (input)=\"bind(contactPhone, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.contactEmail' | transloco }}\n <input class=\"lw-field\" type=\"email\" [disabled]=\"closed\" [value]=\"contactEmail()\" (input)=\"bind(contactEmail, $event)\" />\n </label>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.assignee' | transloco }}\n <input class=\"lw-field\" [disabled]=\"closed\" [value]=\"assignee()\" (input)=\"bind(assignee, $event)\" />\n </label>\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.due' | transloco }}\n <input class=\"lw-field\" type=\"date\" [disabled]=\"closed\" [value]=\"dueDate()\" (input)=\"bind(dueDate, $event)\" />\n </label>\n </div>\n\n <label class=\"flex flex-col gap-1 text-sm text-content\">\n {{ 'weaver-apps-service-desk.fields.description' | transloco }}\n <textarea class=\"lw-field\" rows=\"3\" [disabled]=\"closed\" [value]=\"description()\" (input)=\"bind(description, $event)\"></textarea>\n </label>\n\n @if (problem()) {\n <p class=\"text-sm text-negative\" role=\"alert\">{{ problem() | transloco }}</p>\n }\n\n <div class=\"flex justify-end gap-2\">\n <button type=\"button\" class=\"lw-btn lw-btn--default\" (click)=\"close()\">{{ (closed ? 'weaver-apps-service-desk.dialog.close' : 'weaver-apps-service-desk.dialog.cancel') | transloco }}</button>\n @if (!closed) {\n <button type=\"submit\" class=\"lw-btn lw-btn--primary\" [disabled]=\"saving()\">{{ 'weaver-apps-service-desk.dialog.save' | transloco }}</button>\n }\n </div>\n</form>\n"
|
|
207
|
+
}]
|
|
208
|
+
}]
|
|
209
|
+
});
|
|
210
|
+
var RequestCell = class RequestCell {
|
|
211
|
+
params = null;
|
|
212
|
+
kind = signal("title", ...ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []);
|
|
213
|
+
request = signal(null, ...ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []);
|
|
214
|
+
locale = signal("en", ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
|
|
215
|
+
closed = computed(() => {
|
|
216
|
+
const request = this.request();
|
|
217
|
+
return request !== null && isClosed(request.status);
|
|
218
|
+
}, ...ngDevMode ? [{ debugName: "closed" }] : /* istanbul ignore next */ []);
|
|
219
|
+
dates = computed(() => {
|
|
220
|
+
const request = this.request();
|
|
221
|
+
const date = new Intl.DateTimeFormat(this.locale(), {
|
|
222
|
+
day: "2-digit",
|
|
223
|
+
month: "2-digit",
|
|
224
|
+
year: "numeric"
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
raised: request ? date.format(new Date(request.raisedAt)) : "",
|
|
228
|
+
due: request?.dueAt ? date.format(new Date(request.dueAt)) : ""
|
|
229
|
+
};
|
|
230
|
+
}, ...ngDevMode ? [{ debugName: "dates" }] : /* istanbul ignore next */ []);
|
|
231
|
+
agInit(params) {
|
|
232
|
+
this.params = params;
|
|
233
|
+
this.kind.set(params.kind);
|
|
234
|
+
this.request.set(params.data ?? null);
|
|
235
|
+
this.locale.set(params.locale());
|
|
236
|
+
}
|
|
237
|
+
refresh(params) {
|
|
238
|
+
this.agInit(params);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
openActions(event) {
|
|
242
|
+
const request = this.request();
|
|
243
|
+
if (request) this.params?.actions({
|
|
244
|
+
request,
|
|
245
|
+
...menuAnchor(event)
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
249
|
+
minVersion: "12.0.0",
|
|
250
|
+
version: "22.2.3",
|
|
251
|
+
ngImport: i0,
|
|
252
|
+
type: RequestCell,
|
|
253
|
+
deps: [],
|
|
254
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
255
|
+
});
|
|
256
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
257
|
+
minVersion: "17.0.0",
|
|
258
|
+
version: "22.2.3",
|
|
259
|
+
type: RequestCell,
|
|
260
|
+
isStandalone: true,
|
|
261
|
+
selector: "wa-request-cell",
|
|
262
|
+
ngImport: i0,
|
|
263
|
+
template: "@if (request(); as request) {\n @switch (kind()) {\n @case ('title') {\n <span class=\"font-medium\" [class.text-content]=\"!closed()\" [class.line-through]=\"request.status === 'cancelled'\" data-testid=\"request-title\">{{ request.title }}</span>\n }\n @case ('type') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs text-content\">{{ 'weaver-apps-service-desk.type.' + request.type | transloco }}</span>\n }\n @case ('priority') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs\" [class.text-negative]=\"request.priority === 'urgent'\" [class.font-semibold]=\"request.priority === 'urgent' || request.priority === 'high'\" data-testid=\"request-priority\">{{ 'weaver-apps-service-desk.priority.' + request.priority | transloco }}</span>\n }\n @case ('status') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs text-content\" data-testid=\"request-status\">{{ 'weaver-apps-service-desk.status.' + request.status | transloco }}</span>\n }\n @case ('contact') {\n <span>{{ request.contactName ?? '–' }}</span>\n @if (request.contactPhone ?? request.contactEmail; as reach) {\n <span class=\"ml-2 text-content-faint\">{{ reach }}</span>\n }\n }\n @case ('raised') {\n <span>{{ dates().raised }}</span>\n }\n @case ('due') {\n <span>{{ dates().due }}</span>\n }\n @case ('actions') {\n <button type=\"button\" class=\"relative lw-btn lw-btn--ghost lw-btn--sm lw-btn--icon\" [attr.aria-label]=\"'weaver-apps-service-desk.actions.more' | transloco\" (click)=\"openActions($event)\">\n <lw-icon name=\"more\" size=\"1rem\"></lw-icon>\n </button>\n }\n }\n}\n",
|
|
264
|
+
dependencies: [{
|
|
265
|
+
kind: "pipe",
|
|
266
|
+
type: TranslocoPipe,
|
|
267
|
+
name: "transloco"
|
|
268
|
+
}],
|
|
269
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
273
|
+
minVersion: "12.0.0",
|
|
274
|
+
version: "22.2.3",
|
|
275
|
+
ngImport: i0,
|
|
276
|
+
type: RequestCell,
|
|
277
|
+
decorators: [{
|
|
278
|
+
type: Component,
|
|
279
|
+
args: [{
|
|
280
|
+
selector: "wa-request-cell",
|
|
281
|
+
imports: [TranslocoPipe],
|
|
282
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
283
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
284
|
+
template: "@if (request(); as request) {\n @switch (kind()) {\n @case ('title') {\n <span class=\"font-medium\" [class.text-content]=\"!closed()\" [class.line-through]=\"request.status === 'cancelled'\" data-testid=\"request-title\">{{ request.title }}</span>\n }\n @case ('type') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs text-content\">{{ 'weaver-apps-service-desk.type.' + request.type | transloco }}</span>\n }\n @case ('priority') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs\" [class.text-negative]=\"request.priority === 'urgent'\" [class.font-semibold]=\"request.priority === 'urgent' || request.priority === 'high'\" data-testid=\"request-priority\">{{ 'weaver-apps-service-desk.priority.' + request.priority | transloco }}</span>\n }\n @case ('status') {\n <span class=\"rounded-full border border-border px-2 py-0.5 text-xs text-content\" data-testid=\"request-status\">{{ 'weaver-apps-service-desk.status.' + request.status | transloco }}</span>\n }\n @case ('contact') {\n <span>{{ request.contactName ?? '–' }}</span>\n @if (request.contactPhone ?? request.contactEmail; as reach) {\n <span class=\"ml-2 text-content-faint\">{{ reach }}</span>\n }\n }\n @case ('raised') {\n <span>{{ dates().raised }}</span>\n }\n @case ('due') {\n <span>{{ dates().due }}</span>\n }\n @case ('actions') {\n <button type=\"button\" class=\"relative lw-btn lw-btn--ghost lw-btn--sm lw-btn--icon\" [attr.aria-label]=\"'weaver-apps-service-desk.actions.more' | transloco\" (click)=\"openActions($event)\">\n <lw-icon name=\"more\" size=\"1rem\"></lw-icon>\n </button>\n }\n }\n}\n"
|
|
285
|
+
}]
|
|
286
|
+
}]
|
|
287
|
+
});
|
|
288
|
+
function menuAnchor(event) {
|
|
289
|
+
if (event.detail > 0) return {
|
|
290
|
+
x: event.clientX,
|
|
291
|
+
y: event.clientY
|
|
292
|
+
};
|
|
293
|
+
const bounds = event.currentTarget.getBoundingClientRect();
|
|
294
|
+
return {
|
|
295
|
+
x: bounds.left,
|
|
296
|
+
y: bounds.bottom
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const requestColumn = {
|
|
300
|
+
title: "title",
|
|
301
|
+
type: "type",
|
|
302
|
+
priority: "priority",
|
|
303
|
+
status: "status",
|
|
304
|
+
contact: "contact",
|
|
305
|
+
raised: "raisedAt",
|
|
306
|
+
due: "dueAt",
|
|
307
|
+
actions: "actions"
|
|
308
|
+
};
|
|
309
|
+
const defaultStatuses = [
|
|
310
|
+
ServiceRequestStatus.open,
|
|
311
|
+
ServiceRequestStatus.inProgress,
|
|
312
|
+
ServiceRequestStatus.completed
|
|
313
|
+
];
|
|
314
|
+
const defaultRequestFilter = { [requestColumn.status]: { values: [...defaultStatuses] } };
|
|
315
|
+
const sortableColumns = /* @__PURE__ */ new Set([
|
|
316
|
+
requestColumn.title,
|
|
317
|
+
requestColumn.priority,
|
|
318
|
+
requestColumn.status,
|
|
319
|
+
requestColumn.raised,
|
|
320
|
+
requestColumn.due
|
|
321
|
+
]);
|
|
322
|
+
function listingOf(request) {
|
|
323
|
+
const { filters, sort } = request;
|
|
324
|
+
return {
|
|
325
|
+
...sort && sortableColumns.has(sort.column) ? {
|
|
326
|
+
sort: sort.column,
|
|
327
|
+
descending: sort.descending
|
|
328
|
+
} : {},
|
|
329
|
+
...textOf("text", filters[requestColumn.title]),
|
|
330
|
+
...textOf("contact", filters[requestColumn.contact]),
|
|
331
|
+
...valuesOf("type", filters[requestColumn.type]),
|
|
332
|
+
...valuesOf("status", filters[requestColumn.status]),
|
|
333
|
+
...valuesOf("priority", filters[requestColumn.priority]),
|
|
334
|
+
offset: request.offset,
|
|
335
|
+
limit: request.limit
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function textOf(key, filter) {
|
|
339
|
+
const text = filter?.filter?.trim();
|
|
340
|
+
return text ? { [key]: text } : {};
|
|
341
|
+
}
|
|
342
|
+
function valuesOf(key, filter) {
|
|
343
|
+
const values = filter?.values ?? [];
|
|
344
|
+
return values.length > 0 ? { [key]: [...values] } : {};
|
|
345
|
+
}
|
|
346
|
+
const allStatuses = [
|
|
347
|
+
"open",
|
|
348
|
+
"inProgress",
|
|
349
|
+
"completed",
|
|
350
|
+
"cancelled"
|
|
351
|
+
];
|
|
352
|
+
const actionsWidthPx = 72;
|
|
353
|
+
const titleMinWidthPx = 160;
|
|
354
|
+
const contactMinWidthPx = 140;
|
|
355
|
+
const narrowMinWidthPx = 112;
|
|
356
|
+
var RequestGrid = class RequestGrid {
|
|
357
|
+
table = translateObjectSignal("weaver-apps-service-desk.table");
|
|
358
|
+
types = translateObjectSignal("weaver-apps-service-desk.type");
|
|
359
|
+
statuses = translateObjectSignal("weaver-apps-service-desk.status");
|
|
360
|
+
priorities = translateObjectSignal("weaver-apps-service-desk.priority");
|
|
361
|
+
api = null;
|
|
362
|
+
fetch = input.required(...ngDevMode ? [{ debugName: "fetch" }] : /* istanbul ignore next */ []);
|
|
363
|
+
locale = input.required(...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
|
|
364
|
+
requestActions = output();
|
|
365
|
+
openRequest = output();
|
|
366
|
+
counted = output();
|
|
367
|
+
failed = output();
|
|
368
|
+
translated = computed(() => typeof this.table() === "object" && typeof this.table()["title"] === "string", ...ngDevMode ? [{ debugName: "translated" }] : /* istanbul ignore next */ []);
|
|
369
|
+
empty = computed(() => ({ noRowsToShow: this.table()["empty"] ?? "" }), ...ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []);
|
|
370
|
+
options = computed(() => ({
|
|
371
|
+
columnDefs: this.columns(this.table()),
|
|
372
|
+
defaultColDef: {
|
|
373
|
+
sortable: false,
|
|
374
|
+
resizable: true,
|
|
375
|
+
suppressHeaderMenuButton: true
|
|
376
|
+
},
|
|
377
|
+
datasource: listingDatasource(this.fetch(), {
|
|
378
|
+
answered: (answer) => this.counted.emit(answer.total),
|
|
379
|
+
failed: () => this.failed.emit()
|
|
380
|
+
}),
|
|
381
|
+
initialState: {
|
|
382
|
+
sort: { sortModel: [{
|
|
383
|
+
colId: requestColumn.raised,
|
|
384
|
+
sort: "desc"
|
|
385
|
+
}] },
|
|
386
|
+
filter: { filterModel: { ...defaultRequestFilter } }
|
|
387
|
+
},
|
|
388
|
+
rowClassRules: { "text-content-faint": (params) => !!params.data && isClosed(params.data.status) },
|
|
389
|
+
...openOnRow((request) => this.openRequest.emit(request), { except: [requestColumn.actions] })
|
|
390
|
+
}), ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
391
|
+
reload() {
|
|
392
|
+
this.api?.refreshInfiniteCache();
|
|
393
|
+
}
|
|
394
|
+
ready(api) {
|
|
395
|
+
this.api = api;
|
|
396
|
+
}
|
|
397
|
+
columns(table) {
|
|
398
|
+
const narrow = {
|
|
399
|
+
flex: 1,
|
|
400
|
+
minWidth: narrowMinWidthPx
|
|
401
|
+
};
|
|
402
|
+
return [
|
|
403
|
+
{
|
|
404
|
+
...this.cell(requestColumn.title, "title", table["title"]),
|
|
405
|
+
sortable: true,
|
|
406
|
+
flex: 3,
|
|
407
|
+
minWidth: titleMinWidthPx,
|
|
408
|
+
filter: "agTextColumnFilter",
|
|
409
|
+
filterParams: {
|
|
410
|
+
filterOptions: ["contains"],
|
|
411
|
+
maxNumConditions: 1
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
...this.cell(requestColumn.type, "type", table["type"]),
|
|
416
|
+
...narrow,
|
|
417
|
+
filter: ListFilter,
|
|
418
|
+
filterParams: this.choices(requestTypes, this.types)
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
...this.cell(requestColumn.priority, "priority", table["priority"]),
|
|
422
|
+
...narrow,
|
|
423
|
+
sortable: true,
|
|
424
|
+
filter: ListFilter,
|
|
425
|
+
filterParams: this.choices(requestPriorities, this.priorities)
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
...this.cell(requestColumn.status, "status", table["status"]),
|
|
429
|
+
...narrow,
|
|
430
|
+
sortable: true,
|
|
431
|
+
filter: ListFilter,
|
|
432
|
+
filterParams: this.choices(allStatuses, this.statuses)
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
...this.cell(requestColumn.contact, "contact", table["contact"]),
|
|
436
|
+
flex: 2,
|
|
437
|
+
minWidth: contactMinWidthPx,
|
|
438
|
+
filter: "agTextColumnFilter",
|
|
439
|
+
filterParams: {
|
|
440
|
+
filterOptions: ["contains"],
|
|
441
|
+
maxNumConditions: 1
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
...this.cell(requestColumn.raised, "raised", table["raised"]),
|
|
446
|
+
...narrow,
|
|
447
|
+
sortable: true,
|
|
448
|
+
sortingOrder: ["desc", "asc"]
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
...this.cell(requestColumn.due, "due", table["due"]),
|
|
452
|
+
...narrow,
|
|
453
|
+
sortable: true
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
...this.cell(requestColumn.actions, "actions", ""),
|
|
457
|
+
width: actionsWidthPx,
|
|
458
|
+
resizable: false,
|
|
459
|
+
sortable: false
|
|
460
|
+
}
|
|
461
|
+
];
|
|
462
|
+
}
|
|
463
|
+
cell(colId, kind, headerName) {
|
|
464
|
+
return {
|
|
465
|
+
colId,
|
|
466
|
+
headerName: headerName ?? "",
|
|
467
|
+
cellRenderer: RequestCell,
|
|
468
|
+
cellRendererParams: {
|
|
469
|
+
kind,
|
|
470
|
+
locale: () => this.locale(),
|
|
471
|
+
actions: (actions) => this.requestActions.emit(actions)
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
choices(values, labels) {
|
|
476
|
+
return { options: () => values.map((value) => ({
|
|
477
|
+
value,
|
|
478
|
+
label: labels()[value] ?? value
|
|
479
|
+
})) };
|
|
480
|
+
}
|
|
481
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
482
|
+
minVersion: "12.0.0",
|
|
483
|
+
version: "22.2.3",
|
|
484
|
+
ngImport: i0,
|
|
485
|
+
type: RequestGrid,
|
|
486
|
+
deps: [],
|
|
487
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
488
|
+
});
|
|
489
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
490
|
+
minVersion: "17.0.0",
|
|
491
|
+
version: "22.2.3",
|
|
492
|
+
type: RequestGrid,
|
|
493
|
+
isStandalone: true,
|
|
494
|
+
selector: "wa-request-grid",
|
|
495
|
+
inputs: {
|
|
496
|
+
fetch: {
|
|
497
|
+
classPropertyName: "fetch",
|
|
498
|
+
publicName: "fetch",
|
|
499
|
+
isSignal: true,
|
|
500
|
+
isRequired: true,
|
|
501
|
+
transformFunction: null
|
|
502
|
+
},
|
|
503
|
+
locale: {
|
|
504
|
+
classPropertyName: "locale",
|
|
505
|
+
publicName: "locale",
|
|
506
|
+
isSignal: true,
|
|
507
|
+
isRequired: true,
|
|
508
|
+
transformFunction: null
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
outputs: {
|
|
512
|
+
requestActions: "requestActions",
|
|
513
|
+
openRequest: "openRequest",
|
|
514
|
+
counted: "counted",
|
|
515
|
+
failed: "failed"
|
|
516
|
+
},
|
|
517
|
+
host: { classAttribute: "block h-full w-full" },
|
|
518
|
+
ngImport: i0,
|
|
519
|
+
template: "@if (translated()) {\n <wa-data-grid [options]=\"options()\" [localeOverrides]=\"empty()\" (ready)=\"ready($event)\" />\n}\n",
|
|
520
|
+
dependencies: [{
|
|
521
|
+
kind: "component",
|
|
522
|
+
type: DataGrid,
|
|
523
|
+
selector: "wa-data-grid",
|
|
524
|
+
inputs: ["options", "localeOverrides"],
|
|
525
|
+
outputs: ["ready"]
|
|
526
|
+
}],
|
|
527
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
528
|
+
});
|
|
529
|
+
};
|
|
530
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
531
|
+
minVersion: "12.0.0",
|
|
532
|
+
version: "22.2.3",
|
|
533
|
+
ngImport: i0,
|
|
534
|
+
type: RequestGrid,
|
|
535
|
+
decorators: [{
|
|
536
|
+
type: Component,
|
|
537
|
+
args: [{
|
|
538
|
+
selector: "wa-request-grid",
|
|
539
|
+
imports: [DataGrid],
|
|
540
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
541
|
+
host: { class: "block h-full w-full" },
|
|
542
|
+
template: "@if (translated()) {\n <wa-data-grid [options]=\"options()\" [localeOverrides]=\"empty()\" (ready)=\"ready($event)\" />\n}\n"
|
|
543
|
+
}]
|
|
544
|
+
}],
|
|
545
|
+
propDecorators: {
|
|
546
|
+
fetch: [{
|
|
547
|
+
type: i0.Input,
|
|
548
|
+
args: [{
|
|
549
|
+
isSignal: true,
|
|
550
|
+
alias: "fetch",
|
|
551
|
+
required: true
|
|
552
|
+
}]
|
|
553
|
+
}],
|
|
554
|
+
locale: [{
|
|
555
|
+
type: i0.Input,
|
|
556
|
+
args: [{
|
|
557
|
+
isSignal: true,
|
|
558
|
+
alias: "locale",
|
|
559
|
+
required: true
|
|
560
|
+
}]
|
|
561
|
+
}],
|
|
562
|
+
requestActions: [{
|
|
563
|
+
type: i0.Output,
|
|
564
|
+
args: ["requestActions"]
|
|
565
|
+
}],
|
|
566
|
+
openRequest: [{
|
|
567
|
+
type: i0.Output,
|
|
568
|
+
args: ["openRequest"]
|
|
569
|
+
}],
|
|
570
|
+
counted: [{
|
|
571
|
+
type: i0.Output,
|
|
572
|
+
args: ["counted"]
|
|
573
|
+
}],
|
|
574
|
+
failed: [{
|
|
575
|
+
type: i0.Output,
|
|
576
|
+
args: ["failed"]
|
|
577
|
+
}]
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
var DeskPage = class DeskPage {
|
|
581
|
+
gateway = inject(SERVICE_DESK_GATEWAY);
|
|
582
|
+
route = inject(ActivatedRoute);
|
|
583
|
+
grid = viewChild(RequestGrid, ...ngDevMode ? [{ debugName: "grid" }] : /* istanbul ignore next */ []);
|
|
584
|
+
locale = activeLocale();
|
|
585
|
+
deskId = toSignal(this.route.paramMap.pipe(map((params) => params.get("deskId") ?? "")), { initialValue: this.route.snapshot.paramMap.get("deskId") ?? "" });
|
|
586
|
+
count = signal(null, ...ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []);
|
|
587
|
+
loadFailed = signal(false, ...ngDevMode ? [{ debugName: "loadFailed" }] : /* istanbul ignore next */ []);
|
|
588
|
+
desk = resource({
|
|
589
|
+
...ngDevMode ? { debugName: "desk" } : /* istanbul ignore next */ {},
|
|
590
|
+
params: () => this.deskId(),
|
|
591
|
+
loader: ({ params }) => this.gateway.desk(params)
|
|
592
|
+
});
|
|
593
|
+
fetch = computed(() => {
|
|
594
|
+
const deskId = this.deskId();
|
|
595
|
+
return async (request) => {
|
|
596
|
+
const page = await this.gateway.requests(deskId, listingOf(request));
|
|
597
|
+
return {
|
|
598
|
+
items: page.items,
|
|
599
|
+
total: Number(page.total)
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
}, ...ngDevMode ? [{ debugName: "fetch" }] : /* istanbul ignore next */ []);
|
|
603
|
+
counted(total) {
|
|
604
|
+
this.loadFailed.set(false);
|
|
605
|
+
this.count.set(total);
|
|
606
|
+
}
|
|
607
|
+
failed() {
|
|
608
|
+
this.loadFailed.set(true);
|
|
609
|
+
}
|
|
610
|
+
add() {
|
|
611
|
+
this.openDialog({
|
|
612
|
+
deskId: this.deskId(),
|
|
613
|
+
request: null
|
|
614
|
+
}, "weaver-apps-service-desk.dialog.addTitle");
|
|
615
|
+
}
|
|
616
|
+
actions({ request, x, y }) {
|
|
617
|
+
const closed = isClosed(request.status);
|
|
618
|
+
serviceDeskHost.ui.openMenu([
|
|
619
|
+
{
|
|
620
|
+
label: closed ? "weaver-apps-service-desk.actions.view" : "weaver-apps-service-desk.actions.edit",
|
|
621
|
+
icon: closed ? "preview" : "edit",
|
|
622
|
+
run: () => this.open(request)
|
|
623
|
+
},
|
|
624
|
+
...closed ? [] : [{
|
|
625
|
+
label: "weaver-apps-service-desk.actions.complete",
|
|
626
|
+
icon: serviceDeskIconNames.complete,
|
|
627
|
+
run: () => void this.complete(request)
|
|
628
|
+
}, {
|
|
629
|
+
label: "weaver-apps-service-desk.actions.cancel",
|
|
630
|
+
icon: serviceDeskIconNames.cancel,
|
|
631
|
+
run: () => void this.cancel(request)
|
|
632
|
+
}],
|
|
633
|
+
{
|
|
634
|
+
label: "weaver-apps-service-desk.actions.delete",
|
|
635
|
+
icon: "trash",
|
|
636
|
+
run: () => void this.remove(request)
|
|
637
|
+
}
|
|
638
|
+
], {
|
|
639
|
+
x,
|
|
640
|
+
y
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
open(request) {
|
|
644
|
+
const closed = isClosed(request.status);
|
|
645
|
+
this.openDialog({
|
|
646
|
+
deskId: this.deskId(),
|
|
647
|
+
request
|
|
648
|
+
}, closed ? "weaver-apps-service-desk.dialog.viewTitle" : "weaver-apps-service-desk.dialog.editTitle");
|
|
649
|
+
}
|
|
650
|
+
async complete(request) {
|
|
651
|
+
await this.attempt(async () => this.report(await this.gateway.complete(this.deskId(), request.id), "weaver-apps-service-desk.complete.done"));
|
|
652
|
+
}
|
|
653
|
+
async cancel(request) {
|
|
654
|
+
const reason = await serviceDeskHost.ui.prompt({
|
|
655
|
+
title: "weaver-apps-service-desk.cancel.title",
|
|
656
|
+
message: "weaver-apps-service-desk.cancel.message",
|
|
657
|
+
confirmLabel: "weaver-apps-service-desk.cancel.confirm",
|
|
658
|
+
tone: "warning"
|
|
659
|
+
});
|
|
660
|
+
if (reason === null) return;
|
|
661
|
+
await this.attempt(async () => this.report(await this.gateway.cancel(this.deskId(), request.id, reason.trim() || null), "weaver-apps-service-desk.cancel.done"));
|
|
662
|
+
}
|
|
663
|
+
async remove(request) {
|
|
664
|
+
if (!await serviceDeskHost.ui.confirm({
|
|
665
|
+
title: "weaver-apps-service-desk.delete.title",
|
|
666
|
+
message: "weaver-apps-service-desk.delete.message",
|
|
667
|
+
confirmLabel: "weaver-apps-service-desk.delete.confirm",
|
|
668
|
+
tone: "danger"
|
|
669
|
+
})) return;
|
|
670
|
+
await this.attempt(async () => {
|
|
671
|
+
await this.gateway.remove(this.deskId(), request.id);
|
|
672
|
+
serviceDeskHost.ui.toast({
|
|
673
|
+
message: "weaver-apps-service-desk.delete.done",
|
|
674
|
+
kind: "success"
|
|
675
|
+
});
|
|
676
|
+
this.reload();
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
reload() {
|
|
680
|
+
this.grid()?.reload();
|
|
681
|
+
}
|
|
682
|
+
async attempt(work) {
|
|
683
|
+
try {
|
|
684
|
+
await work();
|
|
685
|
+
} catch {
|
|
686
|
+
serviceDeskHost.ui.toast({
|
|
687
|
+
message: "weaver-apps-service-desk.errors.save",
|
|
688
|
+
kind: "error"
|
|
689
|
+
});
|
|
690
|
+
this.reload();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
openDialog(data, title) {
|
|
694
|
+
serviceDeskHost.ui.open(RequestDialog, {
|
|
695
|
+
data,
|
|
696
|
+
title,
|
|
697
|
+
size: "lg",
|
|
698
|
+
dismiss: "explicit"
|
|
699
|
+
}).closed.then((saved) => {
|
|
700
|
+
if (saved) {
|
|
701
|
+
serviceDeskHost.ui.toast({
|
|
702
|
+
message: "weaver-apps-service-desk.dialog.saved",
|
|
703
|
+
kind: "success"
|
|
704
|
+
});
|
|
705
|
+
this.reload();
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
report(outcome, done) {
|
|
710
|
+
const saved = outcome.kind === "saved";
|
|
711
|
+
serviceDeskHost.ui.toast({
|
|
712
|
+
message: saved ? done : "weaver-apps-service-desk.errors.save",
|
|
713
|
+
kind: saved ? "success" : "error"
|
|
714
|
+
});
|
|
715
|
+
this.reload();
|
|
716
|
+
}
|
|
717
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
718
|
+
minVersion: "12.0.0",
|
|
719
|
+
version: "22.2.3",
|
|
720
|
+
ngImport: i0,
|
|
721
|
+
type: DeskPage,
|
|
722
|
+
deps: [],
|
|
723
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
724
|
+
});
|
|
725
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
726
|
+
minVersion: "17.0.0",
|
|
727
|
+
version: "22.2.3",
|
|
728
|
+
type: DeskPage,
|
|
729
|
+
isStandalone: true,
|
|
730
|
+
selector: "wa-desk-page",
|
|
731
|
+
viewQueries: [{
|
|
732
|
+
propertyName: "grid",
|
|
733
|
+
first: true,
|
|
734
|
+
predicate: RequestGrid,
|
|
735
|
+
descendants: true,
|
|
736
|
+
isSignal: true
|
|
737
|
+
}],
|
|
738
|
+
ngImport: i0,
|
|
739
|
+
template: "<div class=\"flex h-full flex-col gap-4 p-6\">\n <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <h2 class=\"text-lg font-semibold text-content\">{{ desk.value()?.name ?? ('weaver-apps-service-desk.title' | transloco) }}</h2>\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (count() !== null) {\n <span class=\"text-sm text-content-faint\" data-testid=\"request-count\">{{ 'weaver-apps-service-desk.table.count' | transloco: { count: count() } }}</span>\n }\n <button type=\"button\" class=\"lw-btn lw-btn--primary\" (click)=\"add()\">\n <lw-icon name=\"add\" size=\"1rem\"></lw-icon>\n {{ 'weaver-apps-service-desk.actions.add' | transloco }}\n </button>\n </div>\n </div>\n\n @if (loadFailed()) {\n <p class=\"text-sm text-negative\" role=\"alert\">{{ 'weaver-apps-service-desk.errors.load' | transloco }}</p>\n }\n <div class=\"min-h-80 flex-1\">\n <wa-request-grid [fetch]=\"fetch()\" [locale]=\"locale()\" (requestActions)=\"actions($event)\" (openRequest)=\"open($event)\" (counted)=\"counted($event)\" (failed)=\"failed()\" />\n </div>\n</div>\n",
|
|
740
|
+
dependencies: [{
|
|
741
|
+
kind: "component",
|
|
742
|
+
type: RequestGrid,
|
|
743
|
+
selector: "wa-request-grid",
|
|
744
|
+
inputs: ["fetch", "locale"],
|
|
745
|
+
outputs: [
|
|
746
|
+
"requestActions",
|
|
747
|
+
"openRequest",
|
|
748
|
+
"counted",
|
|
749
|
+
"failed"
|
|
750
|
+
]
|
|
751
|
+
}, {
|
|
752
|
+
kind: "pipe",
|
|
753
|
+
type: TranslocoPipe,
|
|
754
|
+
name: "transloco"
|
|
755
|
+
}],
|
|
756
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
757
|
+
});
|
|
758
|
+
};
|
|
759
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
760
|
+
minVersion: "12.0.0",
|
|
761
|
+
version: "22.2.3",
|
|
762
|
+
ngImport: i0,
|
|
763
|
+
type: DeskPage,
|
|
764
|
+
decorators: [{
|
|
765
|
+
type: Component,
|
|
766
|
+
args: [{
|
|
767
|
+
selector: "wa-desk-page",
|
|
768
|
+
imports: [TranslocoPipe, RequestGrid],
|
|
769
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
770
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
771
|
+
template: "<div class=\"flex h-full flex-col gap-4 p-6\">\n <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <h2 class=\"text-lg font-semibold text-content\">{{ desk.value()?.name ?? ('weaver-apps-service-desk.title' | transloco) }}</h2>\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (count() !== null) {\n <span class=\"text-sm text-content-faint\" data-testid=\"request-count\">{{ 'weaver-apps-service-desk.table.count' | transloco: { count: count() } }}</span>\n }\n <button type=\"button\" class=\"lw-btn lw-btn--primary\" (click)=\"add()\">\n <lw-icon name=\"add\" size=\"1rem\"></lw-icon>\n {{ 'weaver-apps-service-desk.actions.add' | transloco }}\n </button>\n </div>\n </div>\n\n @if (loadFailed()) {\n <p class=\"text-sm text-negative\" role=\"alert\">{{ 'weaver-apps-service-desk.errors.load' | transloco }}</p>\n }\n <div class=\"min-h-80 flex-1\">\n <wa-request-grid [fetch]=\"fetch()\" [locale]=\"locale()\" (requestActions)=\"actions($event)\" (openRequest)=\"open($event)\" (counted)=\"counted($event)\" (failed)=\"failed()\" />\n </div>\n</div>\n"
|
|
772
|
+
}]
|
|
773
|
+
}],
|
|
774
|
+
propDecorators: { grid: [{
|
|
775
|
+
type: i0.ViewChild,
|
|
776
|
+
args: [i0.forwardRef(() => RequestGrid), { isSignal: true }]
|
|
777
|
+
}] }
|
|
778
|
+
});
|
|
779
|
+
export { DeskPage };
|
|
780
|
+
|
|
781
|
+
//# sourceMappingURL=weaver-apps-service-desk-desk-page-_ZyGwKSa.mjs.map
|