@weaver-apps/service-desk 0.2.0 → 0.3.0

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