@sneat/extension-contactus 0.13.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.
- package/README.md +37 -0
- package/fesm2022/sneat-extension-contactus-contact-base-page-D6vHs5em.mjs +63 -0
- package/fesm2022/sneat-extension-contactus-contact-base-page-D6vHs5em.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-contacts-page.component-BzTRhfPJ.mjs +118 -0
- package/fesm2022/sneat-extension-contactus-contacts-page.component-BzTRhfPJ.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-index-DVC9hDgV.mjs +352 -0
- package/fesm2022/sneat-extension-contactus-index-DVC9hDgV.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-index-weKgp-3B.mjs +272 -0
- package/fesm2022/sneat-extension-contactus-index-weKgp-3B.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-members-page.component-DPXZ6eSl.mjs +188 -0
- package/fesm2022/sneat-extension-contactus-members-page.component-DPXZ6eSl.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-sneat-extension-contactus-BkVEPHoJ.mjs +560 -0
- package/fesm2022/sneat-extension-contactus-sneat-extension-contactus-BkVEPHoJ.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus-space-member-page.component-BgZCwQmN.mjs +124 -0
- package/fesm2022/sneat-extension-contactus-space-member-page.component-BgZCwQmN.mjs.map +1 -0
- package/fesm2022/sneat-extension-contactus.mjs +2 -0
- package/fesm2022/sneat-extension-contactus.mjs.map +1 -0
- package/package.json +48 -0
- package/types/sneat-extension-contactus.d.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @sneat/extension-contactus
|
|
2
|
+
|
|
3
|
+
Host-facing runtime for the **contactus** extension: provider wiring, routes,
|
|
4
|
+
pages, dialogs, and concrete services. The package is public because host apps
|
|
5
|
+
install it, but its root API is intentionally limited to `provideContactus()`,
|
|
6
|
+
`contactusRoutes`, and `membersRoutes`. Extension libraries must depend on the
|
|
7
|
+
contract or UI package instead.
|
|
8
|
+
|
|
9
|
+
## App bootstrap wiring (required)
|
|
10
|
+
|
|
11
|
+
Cross-extension consumers (e.g. `calendarius`) inject the contactus services
|
|
12
|
+
through the `InjectionToken`s defined in `@sneat/extension-contactus-contract`
|
|
13
|
+
(`CONTACT_SERVICE`, `CONTACTUS_SPACE_SERVICE`, `CONTACT_NAV_SERVICE`,
|
|
14
|
+
`CONTACTUS_NAV_SERVICE`, `CONTACT_GROUP_SERVICE`, `CONTACT_ROLE_SERVICE`,
|
|
15
|
+
`INVITE_SERVICE`). The concrete implementations live here and are bound to those
|
|
16
|
+
tokens by `provideContactus()`.
|
|
17
|
+
|
|
18
|
+
The **application** (the `sneat-apps` super-app, which installs every `@sneat/*`
|
|
19
|
+
as a real package) must call this at bootstrap:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { provideContactus } from '@sneat/extension-contactus';
|
|
23
|
+
|
|
24
|
+
bootstrapApplication(AppComponent, {
|
|
25
|
+
providers: [
|
|
26
|
+
...getStandardSneatProviders(environmentConfig),
|
|
27
|
+
...provideContactus(),
|
|
28
|
+
// ...other extension providers
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Without this, injecting a contactus token resolves to nothing at runtime. In
|
|
34
|
+
unit tests, provide the token with a mock instead.
|
|
35
|
+
|
|
36
|
+
The composition root is the app. A library importing this runtime is rejected
|
|
37
|
+
by both Nx project-boundary rules and the package-pattern ESLint policy.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { b as ContactusSpaceService } from './sneat-extension-contactus-sneat-extension-contactus-BkVEPHoJ.mjs';
|
|
3
|
+
import { SpaceItemPageBaseComponent } from '@sneat/space-components';
|
|
4
|
+
import { throwError, takeUntil } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
class ContactBasePage extends SpaceItemPageBaseComponent {
|
|
7
|
+
contactService;
|
|
8
|
+
$contact = this.$item.asReadonly();
|
|
9
|
+
$contactID = this.$itemID;
|
|
10
|
+
get contact() {
|
|
11
|
+
return this.$contact();
|
|
12
|
+
}
|
|
13
|
+
contactusSpaceService = inject(ContactusSpaceService);
|
|
14
|
+
constructor(contactService, defaultBackPage = 'contacts') {
|
|
15
|
+
super(defaultBackPage, 'contact', contactService);
|
|
16
|
+
this.contactService = contactService;
|
|
17
|
+
}
|
|
18
|
+
watchItemChanges() {
|
|
19
|
+
const itemID = this.$itemID();
|
|
20
|
+
if (!itemID) {
|
|
21
|
+
return throwError(() => new Error('no contact context'));
|
|
22
|
+
}
|
|
23
|
+
const space = this.space;
|
|
24
|
+
if (!space) {
|
|
25
|
+
return throwError(() => new Error('no team context'));
|
|
26
|
+
}
|
|
27
|
+
return this.contactService.watchContactById(space, itemID);
|
|
28
|
+
// .pipe(this.takeUntilNeeded(), takeUntil(this.spaceIDChanged$))
|
|
29
|
+
}
|
|
30
|
+
briefs() {
|
|
31
|
+
return undefined;
|
|
32
|
+
// throw new Error('Method not implemented.'); // return this.contactusTeam?.dto?.contacts;
|
|
33
|
+
}
|
|
34
|
+
onSpaceIdChanged() {
|
|
35
|
+
super.onSpaceIdChanged();
|
|
36
|
+
this.watchSpaceContactusEntry();
|
|
37
|
+
}
|
|
38
|
+
watchSpaceContactusEntry() {
|
|
39
|
+
if (this.space?.id) {
|
|
40
|
+
this.contactusSpaceService
|
|
41
|
+
.watchContactBriefs(this.space.id)
|
|
42
|
+
.pipe(this.takeUntilDestroyed(), takeUntil(this.spaceIDChanged$))
|
|
43
|
+
.subscribe({
|
|
44
|
+
next: (contacts) => {
|
|
45
|
+
console.log('watchSpaceContactusEntry() => contacts:', contacts, 'this.contact:', this.contact);
|
|
46
|
+
if (this.contact?.id && !this.contact?.dbo) {
|
|
47
|
+
const contactID = this.contact.id;
|
|
48
|
+
const contact = contacts.find((c) => c.id === contactID);
|
|
49
|
+
if (contact) {
|
|
50
|
+
console.log('setItemContext from contact space brief', contact.brief);
|
|
51
|
+
this.setItemContext({ ...this.contact, brief: contact.brief });
|
|
52
|
+
// this.contact = { brief: contact.brief, ...this.contact };
|
|
53
|
+
// this.teamParams.changeDetectorRef.detectChanges();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { ContactBasePage as C };
|
|
63
|
+
//# sourceMappingURL=sneat-extension-contactus-contact-base-page-D6vHs5em.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-extension-contactus-contact-base-page-D6vHs5em.mjs","sources":["../../../../../../libs/extensions/contactus/runtime/src/lib/pages/contact-base-page.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport {\n ContactService,\n ContactusSpaceService,\n} from '../services';\nimport {\n IContactBrief,\n IContactDbo,\n IContactContext,\n} from '@sneat/extension-contactus-contract';\nimport { SpaceItemPageBaseComponent } from '@sneat/space-components';\nimport { Observable, takeUntil, throwError } from 'rxjs';\n\nexport abstract class ContactBasePage extends SpaceItemPageBaseComponent<\n IContactBrief,\n IContactDbo\n> {\n protected readonly $contact = this.$item.asReadonly();\n protected readonly $contactID = this.$itemID;\n\n public get contact() {\n return this.$contact();\n }\n\n protected readonly contactusSpaceService = inject(ContactusSpaceService);\n\n protected constructor(\n protected readonly contactService: ContactService,\n defaultBackPage: 'contacts' | 'members' = 'contacts',\n ) {\n super(defaultBackPage, 'contact', contactService);\n }\n\n protected override watchItemChanges(): Observable<IContactContext> {\n const itemID = this.$itemID();\n if (!itemID) {\n return throwError(() => new Error('no contact context'));\n }\n const space = this.space;\n if (!space) {\n return throwError(() => new Error('no team context'));\n }\n return this.contactService.watchContactById(space, itemID);\n // .pipe(this.takeUntilNeeded(), takeUntil(this.spaceIDChanged$))\n }\n\n protected override briefs(): Record<string, IContactBrief> | undefined {\n return undefined;\n // throw new Error('Method not implemented.'); // return this.contactusTeam?.dto?.contacts;\n }\n\n protected override onSpaceIdChanged(): void {\n super.onSpaceIdChanged();\n this.watchSpaceContactusEntry();\n }\n\n private watchSpaceContactusEntry(): void {\n if (this.space?.id) {\n this.contactusSpaceService\n .watchContactBriefs(this.space.id)\n .pipe(this.takeUntilDestroyed(), takeUntil(this.spaceIDChanged$))\n .subscribe({\n next: (contacts) => {\n console.log(\n 'watchSpaceContactusEntry() => contacts:',\n contacts,\n 'this.contact:',\n this.contact,\n );\n if (this.contact?.id && !this.contact?.dbo) {\n const contactID = this.contact.id;\n const contact = contacts.find((c) => c.id === contactID);\n if (contact) {\n console.log(\n 'setItemContext from contact space brief',\n contact.brief,\n );\n this.setItemContext({ ...this.contact, brief: contact.brief });\n // this.contact = { brief: contact.brief, ...this.contact };\n // this.teamParams.changeDetectorRef.detectChanges();\n }\n }\n },\n });\n }\n }\n\n // private watchContact(): void {\n // \tconsole.log('ContactBasePage.watchContact()');\n // \tif (!this.contact?.id) {\n // \t\treturn;\n // \t}\n // \tconst team = this.team;\n // \tif (!team) {\n // \t\treturn;\n // \t}\n // \tthis.contactService\n // \t\t.watchContactById(team, this.contact?.id)\n // \t\t.pipe(this.takeUntilNeeded())\n // \t\t.subscribe({\n // \t\t\tnext: (contact) => {\n // \t\t\t\tconsole.log('watchContact =>', contact);\n // \t\t\t\tif (!contact) {\n // \t\t\t\t\treturn;\n // \t\t\t\t}\n // \t\t\t\tthis.contact = contact;\n // \t\t\t},\n // \t\t\terror: this.errorLogger.logErrorHandler('failed to get contact by ID'),\n // \t\t});\n // }\n\n // private trackContactId(): void {\n // \tconsole.log('ContactBasePage.trackContactId()');\n // \tthis.route.paramMap\n // \t\t.pipe(\n // \t\t\tthis.takeUntilNeeded(),\n // \t\t\tmap((params) => params.get('contactID')),\n // \t\t\tdistinctUntilChanged(),\n // \t\t)\n // \t\t.subscribe({\n // \t\t\tnext: (contactID) => {\n // \t\t\t\tconsole.log('trackContactId() =>', contactID, this.contact);\n // \t\t\t\tif (!contactID) {\n // \t\t\t\t\tthis.contact = undefined;\n // \t\t\t\t\treturn;\n // \t\t\t\t}\n // \t\t\t\tconst team = this.team;\n // \t\t\t\tthis.contact = {\n // \t\t\t\t\tid: contactID,\n // \t\t\t\t\tbrief: undefined,\n // \t\t\t\t\tdto: undefined,\n // \t\t\t\t\tteam,\n // \t\t\t\t};\n // \t\t\t\tthis.onContactIdChanged(contactID);\n // \t\t\t},\n // \t\t\terror: this.logErrorHandler(),\n // \t\t});\n // }\n}\n"],"names":[],"mappings":";;;;;AAaM,MAAgB,eAAgB,SAAQ,0BAG7C,CAAA;AAWsB,IAAA,cAAA;AAVF,IAAA,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;AAClC,IAAA,UAAU,GAAG,IAAI,CAAC,OAAO;AAE5C,IAAA,IAAW,OAAO,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,QAAQ,EAAE;IACxB;AAEmB,IAAA,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC;IAExE,WAAA,CACqB,cAA8B,EACjD,eAAA,GAA0C,UAAU,EAAA;AAEpD,QAAA,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,cAAc,CAAC;QAH9B,IAAA,CAAA,cAAc,GAAd,cAAc;IAInC;IAEmB,gBAAgB,GAAA;AACjC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;QAC7B,IAAI,CAAC,MAAM,EAAE;YACX,OAAO,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC1D;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;QACxB,IAAI,CAAC,KAAK,EAAE;YACV,OAAO,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvD;QACA,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC;;IAE5D;IAEmB,MAAM,GAAA;AACvB,QAAA,OAAO,SAAS;;IAElB;IAEmB,gBAAgB,GAAA;QACjC,KAAK,CAAC,gBAAgB,EAAE;QACxB,IAAI,CAAC,wBAAwB,EAAE;IACjC;IAEQ,wBAAwB,GAAA;AAC9B,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE;AAClB,YAAA,IAAI,CAAC;AACF,iBAAA,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAChC,iBAAA,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC;AAC/D,iBAAA,SAAS,CAAC;AACT,gBAAA,IAAI,EAAE,CAAC,QAAQ,KAAI;AACjB,oBAAA,OAAO,CAAC,GAAG,CACT,yCAAyC,EACzC,QAAQ,EACR,eAAe,EACf,IAAI,CAAC,OAAO,CACb;AACD,oBAAA,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;AAC1C,wBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE;AACjC,wBAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC;wBACxD,IAAI,OAAO,EAAE;4BACX,OAAO,CAAC,GAAG,CACT,yCAAyC,EACzC,OAAO,CAAC,KAAK,CACd;AACD,4BAAA,IAAI,CAAC,cAAc,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;;;wBAGhE;oBACF;gBACF,CAAC;AACF,aAAA,CAAC;QACN;IACF;AAqDD;;;;"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { IonHeader, IonToolbar, IonButtons, IonBackButton, IonButton, IonTitle, IonIcon, IonFooter, IonLabel, IonContent, IonMenuButton } from '@ionic/angular/standalone';
|
|
4
|
+
import { ContactsComponent } from '@sneat/extension-contactus-ui';
|
|
5
|
+
import { setHrefQueryParam } from '@sneat/core';
|
|
6
|
+
import { addSpace } from '@sneat/extension-contactus-contract';
|
|
7
|
+
import { SpaceItemsBaseComponent, SpacePageTitleComponent } from '@sneat/space-components';
|
|
8
|
+
import { b as ContactusSpaceService, a as ContactusServicesModule } from './sneat-extension-contactus-sneat-extension-contactus-BkVEPHoJ.mjs';
|
|
9
|
+
import { SpaceServiceModule } from '@sneat/space-services';
|
|
10
|
+
import { ClassName } from '@sneat/ui';
|
|
11
|
+
import { Subject } from 'rxjs';
|
|
12
|
+
|
|
13
|
+
class ContactsPageComponent extends SpaceItemsBaseComponent {
|
|
14
|
+
contactusSpaceService = inject(ContactusSpaceService);
|
|
15
|
+
$allContacts = signal(undefined, ...(ngDevMode ? [{ debugName: "$allContacts" }] : /* istanbul ignore next */ []));
|
|
16
|
+
// public readonly $filter = signal<string>('');
|
|
17
|
+
$role = signal(undefined, ...(ngDevMode ? [{ debugName: "$role" }] : /* istanbul ignore next */ []));
|
|
18
|
+
$group = signal(undefined, ...(ngDevMode ? [{ debugName: "$group" }] : /* istanbul ignore next */ []));
|
|
19
|
+
$pageTitle = computed(() => {
|
|
20
|
+
const role = this.$role();
|
|
21
|
+
if (role) {
|
|
22
|
+
return `${role.toUpperCase() + role.substr(1)}s`;
|
|
23
|
+
}
|
|
24
|
+
return 'Contacts';
|
|
25
|
+
}, ...(ngDevMode ? [{ debugName: "$pageTitle" }] : /* istanbul ignore next */ []));
|
|
26
|
+
$selectedContacts = computed(() => this.$allContacts()?.filter((c) => c.isChecked), ...(ngDevMode ? [{ debugName: "$selectedContacts" }] : /* istanbul ignore next */ []));
|
|
27
|
+
constructor() {
|
|
28
|
+
super('');
|
|
29
|
+
const role = location.pathname.match(/(applicant|landlord|tenant)/);
|
|
30
|
+
if (role) {
|
|
31
|
+
this.$role.set(role[1]);
|
|
32
|
+
}
|
|
33
|
+
// const allContacts = window.history.state.contacts as IContactWithSpace[];
|
|
34
|
+
// if (allContacts) {
|
|
35
|
+
// this.$allContacts.set(allContacts);
|
|
36
|
+
// }
|
|
37
|
+
this.route.queryParamMap.pipe(this.takeUntilDestroyed()).subscribe({
|
|
38
|
+
next: (q) => {
|
|
39
|
+
this.$role.set(q.get('role') || undefined);
|
|
40
|
+
this.$group.set(q.get('group') || undefined);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
this.spaceIDChanged$.subscribe({
|
|
44
|
+
next: (spaceID) => {
|
|
45
|
+
if (!spaceID) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.contactusSpaceService
|
|
49
|
+
.watchContactBriefs(this.space.id)
|
|
50
|
+
.pipe(this.takeUntilDestroyed(), this.takeUntilSpaceIdChanged())
|
|
51
|
+
.subscribe({
|
|
52
|
+
next: (contacts) => {
|
|
53
|
+
const space = this.$space();
|
|
54
|
+
if (space.id !== spaceID) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.setSpaceContacts(contacts.map(addSpace(space)) || []);
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
$titleIcon = computed(() => {
|
|
64
|
+
switch (this.$role()) {
|
|
65
|
+
case 'tenant':
|
|
66
|
+
return '🤠';
|
|
67
|
+
case 'landlord':
|
|
68
|
+
return '🤴';
|
|
69
|
+
case 'applicant':
|
|
70
|
+
return '🤔';
|
|
71
|
+
default:
|
|
72
|
+
return '📇';
|
|
73
|
+
}
|
|
74
|
+
}, ...(ngDevMode ? [{ debugName: "$titleIcon" }] : /* istanbul ignore next */ []));
|
|
75
|
+
setSpaceContacts = (contacts) => {
|
|
76
|
+
this.$allContacts.set(contacts);
|
|
77
|
+
};
|
|
78
|
+
onRoleChanged(role) {
|
|
79
|
+
this.$role.set(role);
|
|
80
|
+
const url = setHrefQueryParam('role', role || '');
|
|
81
|
+
history.replaceState(undefined, document.title, url);
|
|
82
|
+
}
|
|
83
|
+
command = new Subject();
|
|
84
|
+
sendCommand(event, name) {
|
|
85
|
+
this.command.next({ name, event });
|
|
86
|
+
}
|
|
87
|
+
ngOnDestroy() {
|
|
88
|
+
this.command.complete();
|
|
89
|
+
super.ngOnDestroy();
|
|
90
|
+
}
|
|
91
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContactsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
92
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ContactsPageComponent, isStandalone: true, selector: "sneat-contacts-page", providers: [{ provide: ClassName, useValue: 'ContactsPageComponent' }], usesInheritance: true, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button with-end-buttons\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <sneat-space-page-title\n [space]=\"$role() ? undefined : $space()\"\n [generalTitle]=\"$pageTitle()\"\n [icon]=\"$titleIcon()\"\n [titlesBySpaceType]=\"{\n personal: 'Personal contacts',\n family: 'Family contacts',\n }\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n color=\"primary\"\n size=\"small\"\n title=\"Add contact\"\n (click)=\"sendCommand($event, 'new_contact')\"\n >\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n <sneat-contacts\n [$space]=\"$space()\"\n [$roleID]=\"$role()\"\n [$groupID]=\"$group()\"\n [$allContacts]=\"$allContacts()\"\n [command]=\"command.asObservable()\"\n (contactsChange)=\"$allContacts.set($event)\"\n (roleChange)=\"onRoleChanged($event)\"\n />\n <div style=\"height: 30px\"></div>\n</ion-content>\n\n@if ($selectedContacts()?.length; as numberOfSelectedContacts) {\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-button\n title=\"Reset\"\n (click)=\"sendCommand($event, 'reset_selected')\"\n >\n <ion-icon name=\"close-circle-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n @if (numberOfSelectedContacts === 1) {\n {{ numberOfSelectedContacts }} contact selected\n } @else {\n {{ numberOfSelectedContacts }} contacts selected\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button color=\"success\">Share</ion-button>\n <ion-button color=\"warning\">Archive</ion-button>\n <!--\t\t\t\t<ion-button color=\"danger\">Delete</ion-button>-->\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n}\n", dependencies: [{ kind: "component", type: SpacePageTitleComponent, selector: "sneat-space-page-title", inputs: ["icon", "generalTitle", "space", "titlesBySpaceType"] }, { kind: "ngmodule", type: ContactusServicesModule }, { kind: "ngmodule", type: SpaceServiceModule }, { kind: "component", type: ContactsComponent, selector: "sneat-contacts", inputs: ["$space", "$roleID", "$groupID", "command", "goToNewContactPage", "$allContacts", "contactClicked"], outputs: ["roleChange", "contactsChange", "addContactEvent", "addContactClick"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonBackButton, selector: "ion-back-button" }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
93
|
+
}
|
|
94
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContactsPageComponent, decorators: [{
|
|
95
|
+
type: Component,
|
|
96
|
+
args: [{ imports: [
|
|
97
|
+
SpacePageTitleComponent,
|
|
98
|
+
ContactusServicesModule,
|
|
99
|
+
SpaceServiceModule,
|
|
100
|
+
ContactsComponent,
|
|
101
|
+
IonHeader,
|
|
102
|
+
IonToolbar,
|
|
103
|
+
IonButtons,
|
|
104
|
+
IonBackButton,
|
|
105
|
+
IonButtons,
|
|
106
|
+
IonButton,
|
|
107
|
+
IonBackButton,
|
|
108
|
+
IonTitle,
|
|
109
|
+
IonIcon,
|
|
110
|
+
IonFooter,
|
|
111
|
+
IonLabel,
|
|
112
|
+
IonContent,
|
|
113
|
+
IonMenuButton,
|
|
114
|
+
], providers: [{ provide: ClassName, useValue: 'ContactsPageComponent' }], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sneat-contacts-page', template: "<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button with-end-buttons\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <sneat-space-page-title\n [space]=\"$role() ? undefined : $space()\"\n [generalTitle]=\"$pageTitle()\"\n [icon]=\"$titleIcon()\"\n [titlesBySpaceType]=\"{\n personal: 'Personal contacts',\n family: 'Family contacts',\n }\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n color=\"primary\"\n size=\"small\"\n title=\"Add contact\"\n (click)=\"sendCommand($event, 'new_contact')\"\n >\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n <sneat-contacts\n [$space]=\"$space()\"\n [$roleID]=\"$role()\"\n [$groupID]=\"$group()\"\n [$allContacts]=\"$allContacts()\"\n [command]=\"command.asObservable()\"\n (contactsChange)=\"$allContacts.set($event)\"\n (roleChange)=\"onRoleChanged($event)\"\n />\n <div style=\"height: 30px\"></div>\n</ion-content>\n\n@if ($selectedContacts()?.length; as numberOfSelectedContacts) {\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-button\n title=\"Reset\"\n (click)=\"sendCommand($event, 'reset_selected')\"\n >\n <ion-icon name=\"close-circle-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n @if (numberOfSelectedContacts === 1) {\n {{ numberOfSelectedContacts }} contact selected\n } @else {\n {{ numberOfSelectedContacts }} contacts selected\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button color=\"success\">Share</ion-button>\n <ion-button color=\"warning\">Archive</ion-button>\n <!--\t\t\t\t<ion-button color=\"danger\">Delete</ion-button>-->\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n}\n" }]
|
|
115
|
+
}], ctorParameters: () => [] });
|
|
116
|
+
|
|
117
|
+
export { ContactsPageComponent };
|
|
118
|
+
//# sourceMappingURL=sneat-extension-contactus-contacts-page.component-BzTRhfPJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-extension-contactus-contacts-page.component-BzTRhfPJ.mjs","sources":["../../../../../../libs/extensions/contactus/runtime/src/lib/pages/contacts/contacts-page.component.ts","../../../../../../libs/extensions/contactus/runtime/src/lib/pages/contacts/contacts-page.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n OnDestroy,\n signal,\n inject,\n} from '@angular/core';\nimport {\n IonBackButton,\n IonButton,\n IonButtons,\n IonContent,\n IonFooter,\n IonHeader,\n IonIcon,\n IonLabel,\n IonMenuButton,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n ContactsComponent,\n ContactsComponentCommand,\n ContactsComponentCommandName,\n} from '@sneat/extension-contactus-ui';\nimport { setHrefQueryParam } from '@sneat/core';\nimport {\n addSpace,\n ContactRole,\n IContactWithCheck,\n} from '@sneat/extension-contactus-contract';\nimport {\n SpacePageTitleComponent,\n SpaceItemsBaseComponent,\n} from '@sneat/space-components';\nimport {\n ContactusServicesModule,\n ContactusSpaceService,\n} from '../../services';\nimport { SpaceServiceModule } from '@sneat/space-services';\nimport { ClassName } from '@sneat/ui';\nimport { Subject } from 'rxjs';\n\n@Component({\n imports: [\n SpacePageTitleComponent,\n ContactusServicesModule,\n SpaceServiceModule,\n ContactsComponent,\n IonHeader,\n IonToolbar,\n IonButtons,\n IonBackButton,\n IonButtons,\n IonButton,\n IonBackButton,\n IonTitle,\n IonIcon,\n IonFooter,\n IonLabel,\n IonContent,\n IonMenuButton,\n ],\n providers: [{ provide: ClassName, useValue: 'ContactsPageComponent' }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-contacts-page',\n templateUrl: './contacts-page.component.html',\n})\nexport class ContactsPageComponent\n extends SpaceItemsBaseComponent\n implements OnDestroy\n{\n private readonly contactusSpaceService = inject(ContactusSpaceService);\n\n protected readonly $allContacts = signal<\n undefined | readonly IContactWithCheck[]\n >(undefined);\n\n // public readonly $filter = signal<string>('');\n public readonly $role = signal<ContactRole | undefined>(undefined);\n public readonly $group = signal<string | undefined>(undefined);\n\n protected $pageTitle = computed(() => {\n const role = this.$role();\n if (role) {\n return `${role.toUpperCase() + role.substr(1)}s`;\n }\n return 'Contacts';\n });\n\n protected readonly $selectedContacts = computed(() =>\n this.$allContacts()?.filter((c) => c.isChecked),\n );\n\n constructor() {\n super('');\n const role = location.pathname.match(/(applicant|landlord|tenant)/);\n if (role) {\n this.$role.set(role[1] as ContactRole);\n }\n\n // const allContacts = window.history.state.contacts as IContactWithSpace[];\n // if (allContacts) {\n // \tthis.$allContacts.set(allContacts);\n // }\n\n this.route.queryParamMap.pipe(this.takeUntilDestroyed()).subscribe({\n next: (q) => {\n this.$role.set((q.get('role') as ContactRole) || undefined);\n this.$group.set(q.get('group') || undefined);\n },\n });\n this.spaceIDChanged$.subscribe({\n next: (spaceID) => {\n if (!spaceID) {\n return;\n }\n this.contactusSpaceService\n .watchContactBriefs(this.space.id)\n .pipe(this.takeUntilDestroyed(), this.takeUntilSpaceIdChanged())\n .subscribe({\n next: (contacts) => {\n const space = this.$space();\n if (space.id !== spaceID) {\n return;\n }\n this.setSpaceContacts(contacts.map(addSpace(space)) || []);\n },\n });\n },\n });\n }\n\n protected $titleIcon = computed(() => {\n switch (this.$role()) {\n case 'tenant':\n return '🤠';\n case 'landlord':\n return '🤴';\n case 'applicant':\n return '🤔';\n default:\n return '📇';\n }\n });\n\n private readonly setSpaceContacts = (contacts: IContactWithCheck[]): void => {\n this.$allContacts.set(contacts);\n };\n\n protected onRoleChanged(role?: ContactRole): void {\n this.$role.set(role);\n const url = setHrefQueryParam('role', role || '');\n history.replaceState(undefined, document.title, url);\n }\n\n protected readonly command = new Subject<ContactsComponentCommand>();\n\n protected sendCommand(\n event: Event,\n name: ContactsComponentCommandName,\n ): void {\n this.command.next({ name, event });\n }\n\n public override ngOnDestroy(): void {\n this.command.complete();\n super.ngOnDestroy();\n }\n}\n","<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button with-end-buttons\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <sneat-space-page-title\n [space]=\"$role() ? undefined : $space()\"\n [generalTitle]=\"$pageTitle()\"\n [icon]=\"$titleIcon()\"\n [titlesBySpaceType]=\"{\n personal: 'Personal contacts',\n family: 'Family contacts',\n }\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n color=\"primary\"\n size=\"small\"\n title=\"Add contact\"\n (click)=\"sendCommand($event, 'new_contact')\"\n >\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n <sneat-contacts\n [$space]=\"$space()\"\n [$roleID]=\"$role()\"\n [$groupID]=\"$group()\"\n [$allContacts]=\"$allContacts()\"\n [command]=\"command.asObservable()\"\n (contactsChange)=\"$allContacts.set($event)\"\n (roleChange)=\"onRoleChanged($event)\"\n />\n <div style=\"height: 30px\"></div>\n</ion-content>\n\n@if ($selectedContacts()?.length; as numberOfSelectedContacts) {\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-button\n title=\"Reset\"\n (click)=\"sendCommand($event, 'reset_selected')\"\n >\n <ion-icon name=\"close-circle-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n @if (numberOfSelectedContacts === 1) {\n {{ numberOfSelectedContacts }} contact selected\n } @else {\n {{ numberOfSelectedContacts }} contacts selected\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button color=\"success\">Share</ion-button>\n <ion-button color=\"warning\">Archive</ion-button>\n <!--\t\t\t\t<ion-button color=\"danger\">Delete</ion-button>-->\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAqEM,MAAO,qBACX,SAAQ,uBAAuB,CAAA;AAGd,IAAA,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC;AAEnD,IAAA,YAAY,GAAG,MAAM,CAEtC,SAAS,mFAAC;;AAGI,IAAA,KAAK,GAAG,MAAM,CAA0B,SAAS,4EAAC;AAClD,IAAA,MAAM,GAAG,MAAM,CAAqB,SAAS,6EAAC;AAEpD,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AACnC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE;QACzB,IAAI,IAAI,EAAE;AACR,YAAA,OAAO,CAAA,EAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG;QAClD;AACA,QAAA,OAAO,UAAU;AACnB,IAAA,CAAC,iFAAC;IAEiB,iBAAiB,GAAG,QAAQ,CAAC,MAC9C,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,mBAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAChD;AAED,IAAA,WAAA,GAAA;QACE,KAAK,CAAC,EAAE,CAAC;QACT,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,6BAA6B,CAAC;QACnE,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAgB,CAAC;QACxC;;;;;AAOA,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC;AACjE,YAAA,IAAI,EAAE,CAAC,CAAC,KAAI;AACV,gBAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAiB,IAAI,SAAS,CAAC;AAC3D,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;YAC9C,CAAC;AACF,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC;AAC7B,YAAA,IAAI,EAAE,CAAC,OAAO,KAAI;gBAChB,IAAI,CAAC,OAAO,EAAE;oBACZ;gBACF;AACA,gBAAA,IAAI,CAAC;AACF,qBAAA,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;qBAChC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,IAAI,CAAC,uBAAuB,EAAE;AAC9D,qBAAA,SAAS,CAAC;AACT,oBAAA,IAAI,EAAE,CAAC,QAAQ,KAAI;AACjB,wBAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC3B,wBAAA,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,EAAE;4BACxB;wBACF;AACA,wBAAA,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC5D,CAAC;AACF,iBAAA,CAAC;YACN,CAAC;AACF,SAAA,CAAC;IACJ;AAEU,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AACnC,QAAA,QAAQ,IAAI,CAAC,KAAK,EAAE;AAClB,YAAA,KAAK,QAAQ;AACX,gBAAA,OAAO,IAAI;AACb,YAAA,KAAK,UAAU;AACb,gBAAA,OAAO,IAAI;AACb,YAAA,KAAK,WAAW;AACd,gBAAA,OAAO,IAAI;AACb,YAAA;AACE,gBAAA,OAAO,IAAI;;AAEjB,IAAA,CAAC,iFAAC;AAEe,IAAA,gBAAgB,GAAG,CAAC,QAA6B,KAAU;AAC1E,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;AACjC,IAAA,CAAC;AAES,IAAA,aAAa,CAAC,IAAkB,EAAA;AACxC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QACpB,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACjD,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;IACtD;AAEmB,IAAA,OAAO,GAAG,IAAI,OAAO,EAA4B;IAE1D,WAAW,CACnB,KAAY,EACZ,IAAkC,EAAA;QAElC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACpC;IAEgB,WAAW,GAAA;AACzB,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;QACvB,KAAK,CAAC,WAAW,EAAE;IACrB;uGApGW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,kEALrB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAuB,EAAE,CAAC,iDChExE,mmEAoEA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDtBI,uBAAuB,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,cAAA,EAAA,OAAA,EAAA,mBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACvB,uBAAuB,8BACvB,kBAAkB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,iBAAiB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,oBAAA,EAAA,cAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,EAAA,gBAAA,EAAA,iBAAA,EAAA,iBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,SAAS,oGACT,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,aAAa,4DAEb,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,OAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAET,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,OAAO,2JACP,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,UAAU,wKACV,aAAa,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAOJ,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAzBjC,SAAS;AACC,YAAA,IAAA,EAAA,CAAA,EAAA,OAAA,EAAA;wBACP,uBAAuB;wBACvB,uBAAuB;wBACvB,kBAAkB;wBAClB,iBAAiB;wBACjB,SAAS;wBACT,UAAU;wBACV,UAAU;wBACV,aAAa;wBACb,UAAU;wBACV,SAAS;wBACT,aAAa;wBACb,QAAQ;wBACR,OAAO;wBACP,SAAS;wBACT,QAAQ;wBACR,UAAU;wBACV,aAAa;AACd,qBAAA,EAAA,SAAA,EACU,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAuB,EAAE,CAAC,EAAA,eAAA,EACrD,uBAAuB,CAAC,MAAM,YACrC,qBAAqB,EAAA,QAAA,EAAA,mmEAAA,EAAA;;;;;"}
|