@sneat/contactus-internal 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.
- package/esm2022/index.js +2 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/lib/contactus-routing.module.js +48 -0
- package/esm2022/lib/contactus-routing.module.js.map +1 -0
- package/esm2022/lib/index.js +3 -0
- package/esm2022/lib/index.js.map +1 -0
- package/esm2022/lib/members/index.js +4 -0
- package/esm2022/lib/members/index.js.map +1 -0
- package/esm2022/lib/members/members-base-page.js +30 -0
- package/esm2022/lib/members/members-base-page.js.map +1 -0
- package/esm2022/lib/members/members-routing.js +32 -0
- package/esm2022/lib/members/members-routing.js.map +1 -0
- package/esm2022/lib/members/pages/member/space-member-page.component.js +95 -0
- package/esm2022/lib/members/pages/member/space-member-page.component.js.map +1 -0
- package/esm2022/lib/members/pages/member-base-page.js +23 -0
- package/esm2022/lib/members/pages/member-base-page.js.map +1 -0
- package/esm2022/lib/members/pages/members/members-page.component.js +155 -0
- package/esm2022/lib/members/pages/members/members-page.component.js.map +1 -0
- package/esm2022/lib/members/pages/new-member/index.js +2 -0
- package/esm2022/lib/members/pages/new-member/index.js.map +1 -0
- package/esm2022/lib/members/pages/new-member/new-member-form.component.js +223 -0
- package/esm2022/lib/members/pages/new-member/new-member-form.component.js.map +1 -0
- package/esm2022/lib/members/pages/new-member/new-member-page.component.js +132 -0
- package/esm2022/lib/members/pages/new-member/new-member-page.component.js.map +1 -0
- package/esm2022/lib/pages/contact/contact-page.component.js +96 -0
- package/esm2022/lib/pages/contact/contact-page.component.js.map +1 -0
- package/esm2022/lib/pages/contact/index.js +2 -0
- package/esm2022/lib/pages/contact/index.js.map +1 -0
- package/esm2022/lib/pages/contact-base-page.js +59 -0
- package/esm2022/lib/pages/contact-base-page.js.map +1 -0
- package/esm2022/lib/pages/contacts/contacts-page.component.js +113 -0
- package/esm2022/lib/pages/contacts/contacts-page.component.js.map +1 -0
- package/esm2022/lib/pages/contacts/index.js +2 -0
- package/esm2022/lib/pages/contacts/index.js.map +1 -0
- package/esm2022/lib/pages/index.js +5 -0
- package/esm2022/lib/pages/index.js.map +1 -0
- package/esm2022/lib/pages/new-contact/index.js +2 -0
- package/esm2022/lib/pages/new-contact/index.js.map +1 -0
- package/esm2022/lib/pages/new-contact/new-contact-page.component.js +104 -0
- package/esm2022/lib/pages/new-contact/new-contact-page.component.js.map +1 -0
- package/esm2022/lib/pages/new-location/index.js +2 -0
- package/esm2022/lib/pages/new-location/index.js.map +1 -0
- package/esm2022/lib/pages/new-location/new-location-page.component.js +55 -0
- package/esm2022/lib/pages/new-location/new-location-page.component.js.map +1 -0
- package/esm2022/sneat-contactus-internal.js +5 -0
- package/esm2022/sneat-contactus-internal.js.map +1 -0
- package/index.d.ts +1 -0
- package/lib/contactus-routing.module.d.ts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/members/index.d.ts +2 -0
- package/lib/members/members-base-page.d.ts +12 -0
- package/lib/members/members-routing.d.ts +2 -0
- package/lib/members/pages/member/space-member-page.component.d.ts +11 -0
- package/lib/members/pages/member-base-page.d.ts +10 -0
- package/lib/members/pages/members/members-page.component.d.ts +18 -0
- package/lib/members/pages/new-member/index.d.ts +1 -0
- package/lib/members/pages/new-member/new-member-form.component.d.ts +26 -0
- package/lib/members/pages/new-member/new-member-page.component.d.ts +17 -0
- package/lib/pages/contact/contact-page.component.d.ts +15 -0
- package/lib/pages/contact/index.d.ts +1 -0
- package/lib/pages/contact-base-page.d.ts +16 -0
- package/lib/pages/contacts/contacts-page.component.d.ts +22 -0
- package/lib/pages/contacts/index.d.ts +1 -0
- package/lib/pages/index.d.ts +4 -0
- package/lib/pages/new-contact/index.d.ts +1 -0
- package/lib/pages/new-contact/new-contact-page.component.d.ts +24 -0
- package/lib/pages/new-location/index.d.ts +1 -0
- package/lib/pages/new-location/new-location-page.component.d.ts +12 -0
- package/package.json +26 -0
- package/sneat-contactus-internal.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, inject, signal, ViewChild, } from '@angular/core';
|
|
2
|
+
import { FormsModule, ReactiveFormsModule, UntypedFormGroup, } from '@angular/forms';
|
|
3
|
+
import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCol, IonGrid, IonLabel, IonRow, IonSpinner, NavController, } from '@ionic/angular/standalone';
|
|
4
|
+
import { namesToUrlParams } from '@sneat/auth-models';
|
|
5
|
+
import { MemberService } from '@sneat/contactus-services';
|
|
6
|
+
import { PersonWizardComponent } from '@sneat/contactus-shared';
|
|
7
|
+
import { formNexInAnimation } from '@sneat/core';
|
|
8
|
+
import { personNames } from '@sneat/auth-ui';
|
|
9
|
+
import { RoutingState } from '@sneat/core';
|
|
10
|
+
import { isRelatedPersonReady, } from '@sneat/contactus-core';
|
|
11
|
+
import { zipMapBriefsWithIDs } from '@sneat/space-models';
|
|
12
|
+
import { QRCodeComponent } from 'angularx-qrcode';
|
|
13
|
+
import { WithNewContactInput } from '@sneat/contactus-shared';
|
|
14
|
+
import { ClassName } from '@sneat/ui';
|
|
15
|
+
import * as i0 from "@angular/core";
|
|
16
|
+
import * as i1 from "@angular/forms";
|
|
17
|
+
export class NewMemberFormComponent extends WithNewContactInput {
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
this.personRequirements = {
|
|
21
|
+
ageGroup: { required: true },
|
|
22
|
+
gender: { required: true },
|
|
23
|
+
};
|
|
24
|
+
this.navController = inject(NavController);
|
|
25
|
+
this.$isSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "$isSubmitting" }] : []));
|
|
26
|
+
this.$canSubmit = computed(() => this.$spaceRef().id &&
|
|
27
|
+
!this.$isSubmitting() &&
|
|
28
|
+
this.$isContactReady() &&
|
|
29
|
+
!this.addMemberForm.disabled && //TODO(check) Could be a problem with Push detection strategy?
|
|
30
|
+
this.addMemberForm.valid, ...(ngDevMode ? [{ debugName: "$canSubmit" }] : []));
|
|
31
|
+
this.$qrData = computed(() => {
|
|
32
|
+
const contact = this.$contact();
|
|
33
|
+
let url = `https://sneat.app/pwa/join?family=${contact.space.id}`;
|
|
34
|
+
const { gender, ageGroup } = contact.dbo;
|
|
35
|
+
if (gender &&
|
|
36
|
+
gender !== 'unknown' &&
|
|
37
|
+
gender !== 'undisclosed' &&
|
|
38
|
+
gender !== 'other') {
|
|
39
|
+
url += '&gender=' + gender;
|
|
40
|
+
}
|
|
41
|
+
if (ageGroup) {
|
|
42
|
+
url += '&ageGroup=' + ageGroup;
|
|
43
|
+
}
|
|
44
|
+
url += namesToUrlParams(contact.dbo.names);
|
|
45
|
+
url += '&utm_source=sneat.app&utm_medium=qr_code&utm_campaign=new_member';
|
|
46
|
+
return url;
|
|
47
|
+
}, ...(ngDevMode ? [{ debugName: "$qrData" }] : []));
|
|
48
|
+
this.$isContactReady = computed(() => {
|
|
49
|
+
const contact = this.$contact();
|
|
50
|
+
return (contact && isRelatedPersonReady(contact.dbo, this.personRequirements));
|
|
51
|
+
}, ...(ngDevMode ? [{ debugName: "$isContactReady" }] : []));
|
|
52
|
+
// @ViewChild('emailInput', { static: false }) emailInput?: IonInput;
|
|
53
|
+
// @ViewChild('genderFirstInput', { static: false }) genderFirstInput?: IonRadio;
|
|
54
|
+
// public get isPersonFormReady(): boolean {
|
|
55
|
+
// return isRelatedPersonNotReady(this.member, this.personRequirements);
|
|
56
|
+
// }
|
|
57
|
+
//
|
|
58
|
+
// public readonly setFocusToInput = createSetFocusToInput(
|
|
59
|
+
// this.params.errorLogger,
|
|
60
|
+
// );
|
|
61
|
+
// public readonly memberType = new FormControl<TeamMemberType>('member', [
|
|
62
|
+
// Validators.required,
|
|
63
|
+
// ]);
|
|
64
|
+
this.addMemberForm = new UntypedFormGroup({
|
|
65
|
+
// email: this.email,
|
|
66
|
+
// phone: this.phone,
|
|
67
|
+
// ageGroup: this.ageGroup,
|
|
68
|
+
// relationship: this.relationship,
|
|
69
|
+
});
|
|
70
|
+
this.memberService = inject(MemberService);
|
|
71
|
+
const routingState = inject(RoutingState);
|
|
72
|
+
this.hasNavHistory = routingState.hasHistory();
|
|
73
|
+
}
|
|
74
|
+
ngOnChanges(changes) {
|
|
75
|
+
if (changes['$space']) {
|
|
76
|
+
this.setPersonRequirements(this.$contact());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
setPersonRequirements(contact) {
|
|
80
|
+
const spaceRef = this.$spaceRef();
|
|
81
|
+
this.personRequirements = {
|
|
82
|
+
// TODO: Should we move it inside person form wizard?
|
|
83
|
+
...this.personRequirements,
|
|
84
|
+
ageGroup: spaceRef.type === 'family' && contact.dbo.type !== 'animal'
|
|
85
|
+
? { required: true }
|
|
86
|
+
: { hide: true },
|
|
87
|
+
roles: spaceRef.type === 'family' && contact.dbo.type !== 'animal'
|
|
88
|
+
? { hide: true }
|
|
89
|
+
: { required: true },
|
|
90
|
+
relatedAs: spaceRef.type === 'family' && contact.dbo.type !== 'animal'
|
|
91
|
+
? { required: true }
|
|
92
|
+
: { hide: true },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
submit() {
|
|
96
|
+
// if (!this.hasNames) {
|
|
97
|
+
// alert('Please enter first or last or full name of the new member');
|
|
98
|
+
// if (!this.firstName.value && !this.lastName.value) {
|
|
99
|
+
// this.setFocusToInput(this.firstNameInput);
|
|
100
|
+
// } else {
|
|
101
|
+
// this.setFocusToInput(this.fullNameInput);
|
|
102
|
+
// }
|
|
103
|
+
// return;
|
|
104
|
+
// }
|
|
105
|
+
if (!this.personFormComponent) {
|
|
106
|
+
throw '!this.personFormComponent';
|
|
107
|
+
}
|
|
108
|
+
const spaceRef = this.$spaceRef();
|
|
109
|
+
const contact = this.$contact();
|
|
110
|
+
if (!spaceRef?.id) {
|
|
111
|
+
this.errorLogger.logError('not able to add new member without space context');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (!contact) {
|
|
115
|
+
this.errorLogger.logError('member field is undefined');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (this.personRequirements.ageGroup?.required && !contact.dbo.ageGroup) {
|
|
119
|
+
throw new Error('Age group is a required field');
|
|
120
|
+
}
|
|
121
|
+
if (this.personRequirements.gender?.required && !contact.dbo.gender) {
|
|
122
|
+
throw new Error('Gender is a required field');
|
|
123
|
+
}
|
|
124
|
+
const displayName = personNames(contact.dbo.names);
|
|
125
|
+
const duplicateMember = zipMapBriefsWithIDs(this.contactusSpace?.dbo?.contacts)?.find((m) => personNames(m.brief.names) === displayName);
|
|
126
|
+
if (duplicateMember) {
|
|
127
|
+
alert('There is already a member with same name: ' + displayName);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const request = {
|
|
131
|
+
...contact.dbo,
|
|
132
|
+
type: contact.dbo.type,
|
|
133
|
+
status: 'active',
|
|
134
|
+
countryID: '--',
|
|
135
|
+
roles: ['contributor'],
|
|
136
|
+
spaceID: spaceRef.id,
|
|
137
|
+
};
|
|
138
|
+
this.$isSubmitting.set(true);
|
|
139
|
+
this.addMemberForm.disable();
|
|
140
|
+
this.memberService.createMember(request).subscribe({
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
142
|
+
next: (_member) => {
|
|
143
|
+
// console.log('member created:', member);
|
|
144
|
+
if (this.hasNavHistory) {
|
|
145
|
+
this.navController
|
|
146
|
+
.pop()
|
|
147
|
+
.catch(this.errorLogger.logErrorHandler('failed to navigate to prev page'));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
this.spaceNavService
|
|
151
|
+
.navigateBackToSpacePage(spaceRef, 'members')
|
|
152
|
+
.catch(this.errorLogger.logErrorHandler('failed to navigate back to members page'));
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
error: (err) => {
|
|
156
|
+
this.errorLogger.logError(err, 'Failed to create a new member');
|
|
157
|
+
this.addMemberForm.enable();
|
|
158
|
+
setTimeout(() => {
|
|
159
|
+
this.$isSubmitting.set(false);
|
|
160
|
+
}, 1000);
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
// this.startCommuneReadwriteTx([MemberKind], (tx, communeDto, userDto) =>
|
|
164
|
+
// this.membersService.addCommuneItem(
|
|
165
|
+
// {
|
|
166
|
+
// ...memberDto,
|
|
167
|
+
// communeId: communeDto.id,
|
|
168
|
+
// },
|
|
169
|
+
// tx,
|
|
170
|
+
// ))
|
|
171
|
+
// .subscribe({
|
|
172
|
+
// next: member => {
|
|
173
|
+
// console.log('New member ID:', member.id);
|
|
174
|
+
// setTimeout(
|
|
175
|
+
// () => {
|
|
176
|
+
// this.navigateRoot(
|
|
177
|
+
// 'member',
|
|
178
|
+
// { id: member.id },
|
|
179
|
+
// { memberDto: member },
|
|
180
|
+
// );
|
|
181
|
+
// },
|
|
182
|
+
// // tslint:disable-next-line:no-magic-numbers
|
|
183
|
+
// 100,
|
|
184
|
+
// );
|
|
185
|
+
// },
|
|
186
|
+
// error: err => {
|
|
187
|
+
// this.errorLogger.logError(err, 'Failed to create new member');
|
|
188
|
+
// },
|
|
189
|
+
// },
|
|
190
|
+
// );
|
|
191
|
+
}
|
|
192
|
+
onContactChanged(contact) {
|
|
193
|
+
// console.log('NewMemberFormComponent.onContactChanged()', contact);
|
|
194
|
+
this.setPersonRequirements(contact);
|
|
195
|
+
this.contactChange.emit(contact);
|
|
196
|
+
}
|
|
197
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NewMemberFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
198
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NewMemberFormComponent, isStandalone: true, selector: "sneat-new-member-form", providers: [{ provide: ClassName, useValue: 'NewMemberFormComponent' }], viewQueries: [{ propertyName: "personFormComponent", first: true, predicate: PersonWizardComponent, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"addMemberForm\" (ngSubmit)=\"submit()\">\n <sneat-person-wizard\n [$space]=\"$spaceRef()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"onContactChanged($event)\"\n [displayAgeGroupValue]=\"true\"\n [disabled]=\"$isSubmitting()\"\n [requires]=\"personRequirements\"\n [$fields]=\"{ contactType: { hide: true } }\"\n />\n\n @if (addMemberForm.errors) {\n <ion-card>\n <ion-card-header color=\"danger\">\n <ion-card-title>Errors</ion-card-title>\n </ion-card-header>\n <ion-card-content> Errors: {{ addMemberForm.errors }}</ion-card-content>\n </ion-card>\n }\n\n <ion-card>\n <ion-grid>\n <ion-row>\n <ion-col size=\"5\">\n <!--\t\t\t\t\tpersonRequirements: {{personRequirements|json}}-->\n <!--\t\t\t\t\t$isContactReady: {{$isContactReady()}}-->\n <ion-button\n expand=\"full\"\n size=\"large\"\n (click)=\"submit()\"\n [disabled]=\"!$canSubmit()\"\n >\n @if ($isSubmitting()) {\n <ion-spinner\n name=\"lines-small\"\n slot=\"start\"\n class=\"ion-margin-end\"\n />\n }\n <ion-label>Add member</ion-label>\n </ion-button>\n </ion-col>\n <ion-col size=\"1\" style=\"text-align: center\">\n <p>or</p>\n </ion-col>\n @if (!$isSubmitting()) {\n <ion-col size=\"6\">\n <qrcode\n style=\"float: left\"\n [qrdata]=\"$qrData()\"\n [width]=\"140\"\n errorCorrectionLevel=\"M\"\n />\n <ion-card-header>\n <ion-card-title>Self-add</ion-card-title>\n <ion-card-subtitle>\n Ask the new member to scan this QR code and fill the form to\n join this space. Or send them this\n <a target=\"_blank\" [href]=\"$qrData()\">link</a>.\n </ion-card-subtitle>\n </ion-card-header>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n </ion-card>\n</form>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PersonWizardComponent, selector: "sneat-person-wizard", inputs: ["requires", "disabled", "hideRelationship", "hidePetOption", "displayAgeGroupValue", "nameFields", "$fields"], outputs: ["isReadyToSubmitChange"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: QRCodeComponent, selector: "qrcode", inputs: ["allowEmptyString", "colorDark", "colorLight", "cssClass", "elementType", "errorCorrectionLevel", "imageSrc", "imageHeight", "imageWidth", "margin", "qrdata", "scale", "version", "width", "alt", "ariaLabel", "title"], outputs: ["qrCodeURL"] }, { 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: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonRow, selector: "ion-row" }, { kind: "component", type: IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }], animations: [formNexInAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
199
|
+
}
|
|
200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NewMemberFormComponent, decorators: [{
|
|
201
|
+
type: Component,
|
|
202
|
+
args: [{ animations: [formNexInAnimation], imports: [
|
|
203
|
+
FormsModule,
|
|
204
|
+
ReactiveFormsModule,
|
|
205
|
+
PersonWizardComponent,
|
|
206
|
+
IonCard,
|
|
207
|
+
IonCardContent,
|
|
208
|
+
IonCardHeader,
|
|
209
|
+
IonCardTitle,
|
|
210
|
+
IonCardSubtitle,
|
|
211
|
+
QRCodeComponent,
|
|
212
|
+
IonButton,
|
|
213
|
+
IonSpinner,
|
|
214
|
+
IonLabel,
|
|
215
|
+
IonRow,
|
|
216
|
+
IonGrid,
|
|
217
|
+
IonCol,
|
|
218
|
+
], providers: [{ provide: ClassName, useValue: 'NewMemberFormComponent' }], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sneat-new-member-form', template: "<form [formGroup]=\"addMemberForm\" (ngSubmit)=\"submit()\">\n <sneat-person-wizard\n [$space]=\"$spaceRef()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"onContactChanged($event)\"\n [displayAgeGroupValue]=\"true\"\n [disabled]=\"$isSubmitting()\"\n [requires]=\"personRequirements\"\n [$fields]=\"{ contactType: { hide: true } }\"\n />\n\n @if (addMemberForm.errors) {\n <ion-card>\n <ion-card-header color=\"danger\">\n <ion-card-title>Errors</ion-card-title>\n </ion-card-header>\n <ion-card-content> Errors: {{ addMemberForm.errors }}</ion-card-content>\n </ion-card>\n }\n\n <ion-card>\n <ion-grid>\n <ion-row>\n <ion-col size=\"5\">\n <!--\t\t\t\t\tpersonRequirements: {{personRequirements|json}}-->\n <!--\t\t\t\t\t$isContactReady: {{$isContactReady()}}-->\n <ion-button\n expand=\"full\"\n size=\"large\"\n (click)=\"submit()\"\n [disabled]=\"!$canSubmit()\"\n >\n @if ($isSubmitting()) {\n <ion-spinner\n name=\"lines-small\"\n slot=\"start\"\n class=\"ion-margin-end\"\n />\n }\n <ion-label>Add member</ion-label>\n </ion-button>\n </ion-col>\n <ion-col size=\"1\" style=\"text-align: center\">\n <p>or</p>\n </ion-col>\n @if (!$isSubmitting()) {\n <ion-col size=\"6\">\n <qrcode\n style=\"float: left\"\n [qrdata]=\"$qrData()\"\n [width]=\"140\"\n errorCorrectionLevel=\"M\"\n />\n <ion-card-header>\n <ion-card-title>Self-add</ion-card-title>\n <ion-card-subtitle>\n Ask the new member to scan this QR code and fill the form to\n join this space. Or send them this\n <a target=\"_blank\" [href]=\"$qrData()\">link</a>.\n </ion-card-subtitle>\n </ion-card-header>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n </ion-card>\n</form>\n" }]
|
|
219
|
+
}], ctorParameters: () => [], propDecorators: { personFormComponent: [{
|
|
220
|
+
type: ViewChild,
|
|
221
|
+
args: [PersonWizardComponent, { static: false }]
|
|
222
|
+
}] } });
|
|
223
|
+
//# sourceMappingURL=new-member-form.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-member-form.component.js","sourceRoot":"","sources":["../../../../../../../../../libs/contactus/internal/src/lib/members/pages/new-member/new-member-form.component.ts","../../../../../../../../../libs/contactus/internal/src/lib/members/pages/new-member/new-member-form.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n OnChanges,\n signal,\n SimpleChanges,\n ViewChild,\n} from '@angular/core';\nimport {\n FormsModule,\n ReactiveFormsModule,\n UntypedFormGroup,\n} from '@angular/forms';\nimport {\n IonButton,\n IonCard,\n IonCardContent,\n IonCardHeader,\n IonCardSubtitle,\n IonCardTitle,\n IonCol,\n IonGrid,\n IonLabel,\n IonRow,\n IonSpinner,\n NavController,\n} from '@ionic/angular/standalone';\nimport { namesToUrlParams } from '@sneat/auth-models';\nimport { MemberService } from '@sneat/contactus-services';\nimport { PersonWizardComponent } from '@sneat/contactus-shared';\nimport { formNexInAnimation } from '@sneat/core';\nimport { personNames } from '@sneat/auth-ui';\nimport { RoutingState } from '@sneat/core';\nimport {\n IContactusSpaceDboAndID,\n ICreateSpaceMemberRequest,\n IPersonRequirements,\n isRelatedPersonReady,\n MemberContactType,\n NewContactBaseDboAndSpaceRef,\n} from '@sneat/contactus-core';\nimport { zipMapBriefsWithIDs } from '@sneat/space-models';\nimport { QRCodeComponent } from 'angularx-qrcode';\nimport { WithNewContactInput } from '@sneat/contactus-shared';\nimport { ClassName } from '@sneat/ui';\n\n@Component({\n animations: [formNexInAnimation],\n imports: [\n FormsModule,\n ReactiveFormsModule,\n PersonWizardComponent,\n IonCard,\n IonCardContent,\n IonCardHeader,\n IonCardTitle,\n IonCardSubtitle,\n QRCodeComponent,\n IonButton,\n IonSpinner,\n IonLabel,\n IonRow,\n IonGrid,\n IonCol,\n ],\n providers: [{ provide: ClassName, useValue: 'NewMemberFormComponent' }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-new-member-form',\n templateUrl: 'new-member-form.component.html',\n})\nexport class NewMemberFormComponent\n extends WithNewContactInput\n implements OnChanges\n{\n public personRequirements: IPersonRequirements = {\n ageGroup: { required: true },\n gender: { required: true },\n };\n\n private readonly navController = inject(NavController);\n\n private readonly hasNavHistory: boolean;\n protected readonly $isSubmitting = signal(false);\n\n protected readonly $canSubmit = computed(\n () =>\n this.$spaceRef().id &&\n !this.$isSubmitting() &&\n this.$isContactReady() &&\n !this.addMemberForm.disabled && //TODO(check) Could be a problem with Push detection strategy?\n this.addMemberForm.valid,\n );\n\n protected readonly $qrData = computed(() => {\n const contact = this.$contact();\n let url = `https://sneat.app/pwa/join?family=${contact.space.id}`;\n const { gender, ageGroup } = contact.dbo;\n if (\n gender &&\n gender !== 'unknown' &&\n gender !== 'undisclosed' &&\n gender !== 'other'\n ) {\n url += '&gender=' + gender;\n }\n if (ageGroup) {\n url += '&ageGroup=' + ageGroup;\n }\n url += namesToUrlParams(contact.dbo.names);\n url += '&utm_source=sneat.app&utm_medium=qr_code&utm_campaign=new_member';\n return url;\n });\n\n protected contactusSpace?: IContactusSpaceDboAndID;\n\n protected readonly $isContactReady = computed(() => {\n const contact = this.$contact();\n return (\n contact && isRelatedPersonReady(contact.dbo, this.personRequirements)\n );\n });\n\n @ViewChild(PersonWizardComponent, { static: false })\n personFormComponent?: PersonWizardComponent;\n // @ViewChild('emailInput', { static: false }) emailInput?: IonInput;\n // @ViewChild('genderFirstInput', { static: false }) genderFirstInput?: IonRadio;\n\n // public get isPersonFormReady(): boolean {\n // \treturn isRelatedPersonNotReady(this.member, this.personRequirements);\n // }\n //\n // public readonly setFocusToInput = createSetFocusToInput(\n // \tthis.params.errorLogger,\n // );\n\n // public readonly memberType = new FormControl<TeamMemberType>('member', [\n // \tValidators.required,\n // ]);\n\n public addMemberForm = new UntypedFormGroup({\n // email: this.email,\n // phone: this.phone,\n // ageGroup: this.ageGroup,\n // relationship: this.relationship,\n });\n\n private readonly memberService = inject(MemberService);\n\n public constructor() {\n super();\n const routingState = inject(RoutingState);\n this.hasNavHistory = routingState.hasHistory();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['$space']) {\n this.setPersonRequirements(this.$contact());\n }\n }\n\n private setPersonRequirements(contact: NewContactBaseDboAndSpaceRef): void {\n const spaceRef = this.$spaceRef();\n this.personRequirements = {\n // TODO: Should we move it inside person form wizard?\n ...this.personRequirements,\n ageGroup:\n spaceRef.type === 'family' && contact.dbo.type !== 'animal'\n ? { required: true }\n : { hide: true },\n roles:\n spaceRef.type === 'family' && contact.dbo.type !== 'animal'\n ? { hide: true }\n : { required: true },\n relatedAs:\n spaceRef.type === 'family' && contact.dbo.type !== 'animal'\n ? { required: true }\n : { hide: true },\n };\n }\n\n submit(): void {\n // if (!this.hasNames) {\n // \talert('Please enter first or last or full name of the new member');\n // \tif (!this.firstName.value && !this.lastName.value) {\n // \t\tthis.setFocusToInput(this.firstNameInput);\n // \t} else {\n // \t\tthis.setFocusToInput(this.fullNameInput);\n // \t}\n // \treturn;\n // }\n if (!this.personFormComponent) {\n throw '!this.personFormComponent';\n }\n const spaceRef = this.$spaceRef();\n const contact = this.$contact();\n if (!spaceRef?.id) {\n this.errorLogger.logError(\n 'not able to add new member without space context',\n );\n return;\n }\n if (!contact) {\n this.errorLogger.logError('member field is undefined');\n return;\n }\n if (this.personRequirements.ageGroup?.required && !contact.dbo.ageGroup) {\n throw new Error('Age group is a required field');\n }\n if (this.personRequirements.gender?.required && !contact.dbo.gender) {\n throw new Error('Gender is a required field');\n }\n const displayName = personNames(contact.dbo.names);\n const duplicateMember = zipMapBriefsWithIDs(\n this.contactusSpace?.dbo?.contacts,\n )?.find((m) => personNames(m.brief.names) === displayName);\n if (duplicateMember) {\n alert('There is already a member with same name: ' + displayName);\n return;\n }\n\n const request: ICreateSpaceMemberRequest = {\n ...contact.dbo,\n type: contact.dbo.type as MemberContactType,\n status: 'active',\n countryID: '--',\n roles: ['contributor'],\n spaceID: spaceRef.id,\n };\n\n this.$isSubmitting.set(true);\n this.addMemberForm.disable();\n this.memberService.createMember(request).subscribe({\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n next: (_member) => {\n // console.log('member created:', member);\n if (this.hasNavHistory) {\n this.navController\n .pop()\n .catch(\n this.errorLogger.logErrorHandler(\n 'failed to navigate to prev page',\n ),\n );\n } else {\n this.spaceNavService\n .navigateBackToSpacePage(spaceRef, 'members')\n .catch(\n this.errorLogger.logErrorHandler(\n 'failed to navigate back to members page',\n ),\n );\n }\n },\n error: (err) => {\n this.errorLogger.logError(err, 'Failed to create a new member');\n this.addMemberForm.enable();\n setTimeout(() => {\n this.$isSubmitting.set(false);\n }, 1000);\n },\n });\n\n // this.startCommuneReadwriteTx([MemberKind], (tx, communeDto, userDto) =>\n // \tthis.membersService.addCommuneItem(\n // \t\t{\n // \t\t\t...memberDto,\n // \t\t\tcommuneId: communeDto.id,\n // \t\t},\n // \t\ttx,\n // \t))\n // \t.subscribe({\n // \t\t\tnext: member => {\n // \t\t\t\tconsole.log('New member ID:', member.id);\n // \t\t\t\tsetTimeout(\n // \t\t\t\t\t() => {\n // \t\t\t\t\t\tthis.navigateRoot(\n // \t\t\t\t\t\t\t'member',\n // \t\t\t\t\t\t\t{ id: member.id },\n // \t\t\t\t\t\t\t{ memberDto: member },\n // \t\t\t\t\t\t);\n // \t\t\t\t\t},\n // \t\t\t\t\t// tslint:disable-next-line:no-magic-numbers\n // \t\t\t\t\t100,\n // \t\t\t\t);\n // \t\t\t},\n // \t\t\terror: err => {\n // \t\t\t\tthis.errorLogger.logError(err, 'Failed to create new member');\n // \t\t\t},\n // \t\t},\n // \t);\n }\n\n onContactChanged(contact: NewContactBaseDboAndSpaceRef): void {\n // console.log('NewMemberFormComponent.onContactChanged()', contact);\n this.setPersonRequirements(contact);\n this.contactChange.emit(contact);\n }\n}\n","<form [formGroup]=\"addMemberForm\" (ngSubmit)=\"submit()\">\n <sneat-person-wizard\n [$space]=\"$spaceRef()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"onContactChanged($event)\"\n [displayAgeGroupValue]=\"true\"\n [disabled]=\"$isSubmitting()\"\n [requires]=\"personRequirements\"\n [$fields]=\"{ contactType: { hide: true } }\"\n />\n\n @if (addMemberForm.errors) {\n <ion-card>\n <ion-card-header color=\"danger\">\n <ion-card-title>Errors</ion-card-title>\n </ion-card-header>\n <ion-card-content> Errors: {{ addMemberForm.errors }}</ion-card-content>\n </ion-card>\n }\n\n <ion-card>\n <ion-grid>\n <ion-row>\n <ion-col size=\"5\">\n <!--\t\t\t\t\tpersonRequirements: {{personRequirements|json}}-->\n <!--\t\t\t\t\t$isContactReady: {{$isContactReady()}}-->\n <ion-button\n expand=\"full\"\n size=\"large\"\n (click)=\"submit()\"\n [disabled]=\"!$canSubmit()\"\n >\n @if ($isSubmitting()) {\n <ion-spinner\n name=\"lines-small\"\n slot=\"start\"\n class=\"ion-margin-end\"\n />\n }\n <ion-label>Add member</ion-label>\n </ion-button>\n </ion-col>\n <ion-col size=\"1\" style=\"text-align: center\">\n <p>or</p>\n </ion-col>\n @if (!$isSubmitting()) {\n <ion-col size=\"6\">\n <qrcode\n style=\"float: left\"\n [qrdata]=\"$qrData()\"\n [width]=\"140\"\n errorCorrectionLevel=\"M\"\n />\n <ion-card-header>\n <ion-card-title>Self-add</ion-card-title>\n <ion-card-subtitle>\n Ask the new member to scan this QR code and fill the form to\n join this space. Or send them this\n <a target=\"_blank\" [href]=\"$qrData()\">link</a>.\n </ion-card-subtitle>\n </ion-card-header>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n </ion-card>\n</form>\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Component, computed, effect, signal } from '@angular/core';
|
|
2
|
+
import { IonBackButton, IonButtons, IonCard, IonCardContent, IonContent, IonHeader, IonSegment, IonSegmentButton, IonTitle, IonToolbar, } from '@ionic/angular/standalone';
|
|
3
|
+
import { ContactusServicesModule, ContactusSpaceContextService, } from '@sneat/contactus-services';
|
|
4
|
+
import { InviteLinksComponent, NewPetFormComponent, } from '@sneat/contactus-shared';
|
|
5
|
+
import { RoleSpaceMember, } from '@sneat/contactus-core';
|
|
6
|
+
import { SpacePageBaseComponent } from '@sneat/space-components';
|
|
7
|
+
import { SpaceServiceModule } from '@sneat/space-services';
|
|
8
|
+
import { filter, first, takeUntil } from 'rxjs';
|
|
9
|
+
import { NewMemberFormComponent } from './new-member-form.component';
|
|
10
|
+
import { ClassName } from '@sneat/ui';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
export class NewMemberPageComponent extends SpacePageBaseComponent {
|
|
13
|
+
// @ViewChild('nameInput', { static: false }) nameInput?: IonInput;
|
|
14
|
+
onContactTypeChanged(event) {
|
|
15
|
+
this.$contact.update((contact) => ({
|
|
16
|
+
...contact,
|
|
17
|
+
dbo: {
|
|
18
|
+
...contact.dbo,
|
|
19
|
+
type: event.detail.value,
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
this.$inviteType = signal('mass', ...(ngDevMode ? [{ debugName: "$inviteType" }] : []));
|
|
26
|
+
this.$contact = signal({
|
|
27
|
+
space: { id: '' },
|
|
28
|
+
dbo: {
|
|
29
|
+
type: 'person',
|
|
30
|
+
gender: 'unknown', // Undefined would indicate "loading" and gender form would be disabled.
|
|
31
|
+
roles: [RoleSpaceMember],
|
|
32
|
+
},
|
|
33
|
+
}, ...(ngDevMode ? [{ debugName: "$contact" }] : []));
|
|
34
|
+
this.$contactType = computed(() => this.$contact().dbo?.type, ...(ngDevMode ? [{ debugName: "$contactType" }] : []));
|
|
35
|
+
this.trackFirstSpaceTypeChanged = () => {
|
|
36
|
+
try {
|
|
37
|
+
this.spaceTypeChanged$
|
|
38
|
+
.pipe(takeUntil(this.destroyed$), filter((v) => !!v), first())
|
|
39
|
+
.subscribe({
|
|
40
|
+
next: (spaceType) => {
|
|
41
|
+
console.log('NewMemberPageComponent: spaceTypeChanged$ =>', spaceType);
|
|
42
|
+
if (spaceType === 'family' && this.$inviteType() === 'mass') {
|
|
43
|
+
this.$inviteType.set('personal');
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
error: this.logErrorHandler('failed to process space type changes'),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
this.logError(e, 'failed to subscribe for first space type change');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
this.$defaultBackUrlSpacePath.set('members');
|
|
54
|
+
const contactusSpaceContextService = new ContactusSpaceContextService(this.destroyed$, this.spaceIDChanged$);
|
|
55
|
+
effect(() => {
|
|
56
|
+
const space = this.$spaceRef();
|
|
57
|
+
this.$contact.update((contact) => ({
|
|
58
|
+
...contact,
|
|
59
|
+
space: space || { id: '' },
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
this.trackFirstSpaceTypeChanged();
|
|
63
|
+
this.route.queryParams.subscribe((params) => {
|
|
64
|
+
const group = params['group'];
|
|
65
|
+
const setContactTypeAndAgeGroup = (contact, contactType, ageGroup) => ({
|
|
66
|
+
...contact,
|
|
67
|
+
dbo: {
|
|
68
|
+
...contact.dbo,
|
|
69
|
+
type: contactType,
|
|
70
|
+
ageGroup,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
switch (group) {
|
|
74
|
+
case 'adults':
|
|
75
|
+
this.$contact.update((contact) => setContactTypeAndAgeGroup(contact, 'person', 'adult'));
|
|
76
|
+
break;
|
|
77
|
+
case 'kids':
|
|
78
|
+
this.$contact.update((contact) => setContactTypeAndAgeGroup(contact, 'person', 'child'));
|
|
79
|
+
break;
|
|
80
|
+
case 'pets':
|
|
81
|
+
this.$contact.update((contact) => setContactTypeAndAgeGroup(contact, 'animal'));
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
this.$contact.update((contact) => setContactTypeAndAgeGroup(contact, 'person'));
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const roles = params['roles'] || '';
|
|
88
|
+
if (roles) {
|
|
89
|
+
this.$contact.update((contact) => ({
|
|
90
|
+
...contact,
|
|
91
|
+
dbo: {
|
|
92
|
+
...contact.dbo,
|
|
93
|
+
roles: roles.split(',').map((s) => s.trim()),
|
|
94
|
+
},
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
contactusSpaceContextService.contactusSpaceContext$
|
|
99
|
+
.pipe(this.takeUntilDestroyed())
|
|
100
|
+
.subscribe({
|
|
101
|
+
next: (contactusTeam) => {
|
|
102
|
+
this.contactusSpace = contactusTeam;
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
onTabChanged(event) {
|
|
107
|
+
this.$inviteType.set(event.detail.value);
|
|
108
|
+
}
|
|
109
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NewMemberPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
110
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NewMemberPageComponent, isStandalone: true, selector: "sneat-new-member-page", providers: [{ provide: ClassName, useValue: 'NewMemberPageComponent' }], usesInheritance: true, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if (space.brief || space.type) {\n @if ($contact().dbo.type === \"animal\") {\n New pet\n } @else {\n @switch ($contact().dbo.ageGroup) {\n @case (\"child\") {\n New child\n }\n @case (\"adult\") {\n New adult\n }\n @default {\n New member\n }\n }\n }\n @ {{ $space().brief?.title || space.type }}\n } @else {\n New member\n }\n </ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-segment\n [value]=\"$contactType()\"\n (ionChange)=\"onContactTypeChanged($event)\"\n>\n <ion-segment-button value=\"person\">Person</ion-segment-button>\n <ion-segment-button value=\"animal\">Pet</ion-segment-button>\n</ion-segment>\n\n<ion-content class=\"cardy\">\n @switch ($contactType()) {\n @case (\"person\") {\n @if (space.id && space.type !== \"family\") {\n <ion-segment [value]=\"$inviteType()\" (ionChange)=\"onTabChanged($event)\">\n <ion-segment-button value=\"mass\">\n Mass invite [{{ space.id }} - {{ space.type }}]\n </ion-segment-button>\n <ion-segment-button value=\"personal\"\n >Personal invite</ion-segment-button\n >\n </ion-segment>\n }\n\n @switch ($inviteType()) {\n @case (\"personal\") {\n <sneat-new-member-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n @case (\"mass\") {\n <ion-card>\n <ion-card-content>\n <sneat-invite-links [contactusSpace]=\"contactusSpace\" />\n\n <p>\n <b>Or</b> you can send\n <a\n href=\"\"\n (click)=\"$inviteType.set('personal'); $event.preventDefault()\"\n >personal invite</a\n >\n by email.\n </p>\n </ion-card-content>\n </ion-card>\n }\n }\n }\n @case (\"animal\") {\n <sneat-new-pet-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n }\n</ion-content>\n", dependencies: [{ kind: "ngmodule", type: ContactusServicesModule }, { kind: "component", type: NewMemberFormComponent, selector: "sneat-new-member-form" }, { kind: "component", type: InviteLinksComponent, selector: "sneat-invite-links", inputs: ["contactusSpace"] }, { kind: "ngmodule", type: SpaceServiceModule }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: IonSegmentButton, selector: "ion-segment-button", inputs: ["contentId", "disabled", "layout", "mode", "type", "value"] }, { 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: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: NewPetFormComponent, selector: "sneat-new-pet-form" }] }); }
|
|
111
|
+
}
|
|
112
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NewMemberPageComponent, decorators: [{
|
|
113
|
+
type: Component,
|
|
114
|
+
args: [{ imports: [
|
|
115
|
+
ContactusServicesModule,
|
|
116
|
+
NewMemberFormComponent,
|
|
117
|
+
InviteLinksComponent,
|
|
118
|
+
SpaceServiceModule,
|
|
119
|
+
IonContent,
|
|
120
|
+
IonSegment,
|
|
121
|
+
IonSegmentButton,
|
|
122
|
+
IonHeader,
|
|
123
|
+
IonToolbar,
|
|
124
|
+
IonButtons,
|
|
125
|
+
IonBackButton,
|
|
126
|
+
IonTitle,
|
|
127
|
+
IonCard,
|
|
128
|
+
IonCardContent,
|
|
129
|
+
NewPetFormComponent,
|
|
130
|
+
], providers: [{ provide: ClassName, useValue: 'NewMemberPageComponent' }], selector: 'sneat-new-member-page', template: "<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if (space.brief || space.type) {\n @if ($contact().dbo.type === \"animal\") {\n New pet\n } @else {\n @switch ($contact().dbo.ageGroup) {\n @case (\"child\") {\n New child\n }\n @case (\"adult\") {\n New adult\n }\n @default {\n New member\n }\n }\n }\n @ {{ $space().brief?.title || space.type }}\n } @else {\n New member\n }\n </ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-segment\n [value]=\"$contactType()\"\n (ionChange)=\"onContactTypeChanged($event)\"\n>\n <ion-segment-button value=\"person\">Person</ion-segment-button>\n <ion-segment-button value=\"animal\">Pet</ion-segment-button>\n</ion-segment>\n\n<ion-content class=\"cardy\">\n @switch ($contactType()) {\n @case (\"person\") {\n @if (space.id && space.type !== \"family\") {\n <ion-segment [value]=\"$inviteType()\" (ionChange)=\"onTabChanged($event)\">\n <ion-segment-button value=\"mass\">\n Mass invite [{{ space.id }} - {{ space.type }}]\n </ion-segment-button>\n <ion-segment-button value=\"personal\"\n >Personal invite</ion-segment-button\n >\n </ion-segment>\n }\n\n @switch ($inviteType()) {\n @case (\"personal\") {\n <sneat-new-member-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n @case (\"mass\") {\n <ion-card>\n <ion-card-content>\n <sneat-invite-links [contactusSpace]=\"contactusSpace\" />\n\n <p>\n <b>Or</b> you can send\n <a\n href=\"\"\n (click)=\"$inviteType.set('personal'); $event.preventDefault()\"\n >personal invite</a\n >\n by email.\n </p>\n </ion-card-content>\n </ion-card>\n }\n }\n }\n @case (\"animal\") {\n <sneat-new-pet-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n }\n</ion-content>\n" }]
|
|
131
|
+
}], ctorParameters: () => [] });
|
|
132
|
+
//# sourceMappingURL=new-member-page.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-member-page.component.js","sourceRoot":"","sources":["../../../../../../../../../libs/contactus/internal/src/lib/members/pages/new-member/new-member-page.component.ts","../../../../../../../../../libs/contactus/internal/src/lib/members/pages/new-member/new-member-page.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, computed, effect, signal } from '@angular/core';\nimport {\n IonBackButton,\n IonButtons,\n IonCard,\n IonCardContent,\n IonContent,\n IonHeader,\n IonSegment,\n IonSegmentButton,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n ContactusServicesModule,\n ContactusSpaceContextService,\n} from '@sneat/contactus-services';\nimport {\n InviteLinksComponent,\n NewPetFormComponent,\n} from '@sneat/contactus-shared';\nimport {\n ContactType,\n IContactusSpaceDboAndID,\n NewContactBaseDboAndSpaceRef,\n RoleSpaceMember,\n} from '@sneat/contactus-core';\nimport { AgeGroupID } from '@sneat/core';\nimport { SpacePageBaseComponent } from '@sneat/space-components';\nimport { SpaceServiceModule } from '@sneat/space-services';\nimport { filter, first, takeUntil } from 'rxjs';\nimport { NewMemberFormComponent } from './new-member-form.component';\nimport { ClassName } from '@sneat/ui';\n\ntype InviteType = 'personal' | 'mass';\n\n@Component({\n imports: [\n ContactusServicesModule,\n NewMemberFormComponent,\n InviteLinksComponent,\n SpaceServiceModule,\n IonContent,\n IonSegment,\n IonSegmentButton,\n IonHeader,\n IonToolbar,\n IonButtons,\n IonBackButton,\n IonTitle,\n IonCard,\n IonCardContent,\n NewPetFormComponent,\n ],\n providers: [{ provide: ClassName, useValue: 'NewMemberPageComponent' }],\n selector: 'sneat-new-member-page',\n templateUrl: './new-member-page.component.html',\n})\nexport class NewMemberPageComponent extends SpacePageBaseComponent {\n // @ViewChild('nameInput', { static: false }) nameInput?: IonInput;\n\n protected onContactTypeChanged(event: CustomEvent): void {\n this.$contact.update((contact) => ({\n ...contact,\n dbo: {\n ...contact.dbo,\n type: event.detail.value as ContactType,\n },\n }));\n }\n\n protected readonly $inviteType = signal<InviteType>('mass');\n\n protected readonly $contact = signal<NewContactBaseDboAndSpaceRef>({\n space: { id: '' },\n dbo: {\n type: 'person',\n gender: 'unknown', // Undefined would indicate \"loading\" and gender form would be disabled.\n roles: [RoleSpaceMember],\n },\n });\n\n protected readonly $contactType = computed(() => this.$contact().dbo?.type);\n\n public constructor() {\n super();\n this.$defaultBackUrlSpacePath.set('members');\n const contactusSpaceContextService = new ContactusSpaceContextService(\n this.destroyed$,\n this.spaceIDChanged$,\n );\n effect(() => {\n const space = this.$spaceRef();\n this.$contact.update((contact) => ({\n ...contact,\n space: space || { id: '' },\n }));\n });\n this.trackFirstSpaceTypeChanged();\n this.route.queryParams.subscribe((params) => {\n const group = params['group'];\n const setContactTypeAndAgeGroup = (\n contact: NewContactBaseDboAndSpaceRef,\n contactType: ContactType,\n ageGroup?: AgeGroupID,\n ) => ({\n ...contact,\n dbo: {\n ...contact.dbo,\n type: contactType,\n ageGroup,\n },\n });\n switch (group) {\n case 'adults':\n this.$contact.update((contact) =>\n setContactTypeAndAgeGroup(contact, 'person', 'adult'),\n );\n break;\n case 'kids':\n this.$contact.update((contact) =>\n setContactTypeAndAgeGroup(contact, 'person', 'child'),\n );\n break;\n case 'pets':\n this.$contact.update((contact) =>\n setContactTypeAndAgeGroup(contact, 'animal'),\n );\n break;\n default:\n this.$contact.update((contact) =>\n setContactTypeAndAgeGroup(contact, 'person'),\n );\n break;\n }\n const roles = params['roles'] || '';\n if (roles) {\n this.$contact.update((contact) => ({\n ...contact,\n dbo: {\n ...contact.dbo,\n roles: roles.split(',').map((s: string) => s.trim()),\n },\n }));\n }\n });\n\n contactusSpaceContextService.contactusSpaceContext$\n .pipe(this.takeUntilDestroyed())\n .subscribe({\n next: (contactusTeam) => {\n this.contactusSpace = contactusTeam;\n },\n });\n }\n\n protected contactusSpace?: IContactusSpaceDboAndID;\n\n private readonly trackFirstSpaceTypeChanged = (): void => {\n try {\n this.spaceTypeChanged$\n .pipe(\n takeUntil(this.destroyed$),\n filter((v) => !!v),\n first(),\n )\n .subscribe({\n next: (spaceType) => {\n console.log(\n 'NewMemberPageComponent: spaceTypeChanged$ =>',\n spaceType,\n );\n if (spaceType === 'family' && this.$inviteType() === 'mass') {\n this.$inviteType.set('personal');\n }\n },\n error: this.logErrorHandler('failed to process space type changes'),\n });\n } catch (e) {\n this.logError(e, 'failed to subscribe for first space type change');\n }\n };\n\n protected onTabChanged(event: CustomEvent): void {\n this.$inviteType.set(event.detail.value as InviteType);\n }\n}\n","<ion-header>\n <ion-toolbar color=\"light\" class=\"with-back-button\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if (space.brief || space.type) {\n @if ($contact().dbo.type === \"animal\") {\n New pet\n } @else {\n @switch ($contact().dbo.ageGroup) {\n @case (\"child\") {\n New child\n }\n @case (\"adult\") {\n New adult\n }\n @default {\n New member\n }\n }\n }\n @ {{ $space().brief?.title || space.type }}\n } @else {\n New member\n }\n </ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-segment\n [value]=\"$contactType()\"\n (ionChange)=\"onContactTypeChanged($event)\"\n>\n <ion-segment-button value=\"person\">Person</ion-segment-button>\n <ion-segment-button value=\"animal\">Pet</ion-segment-button>\n</ion-segment>\n\n<ion-content class=\"cardy\">\n @switch ($contactType()) {\n @case (\"person\") {\n @if (space.id && space.type !== \"family\") {\n <ion-segment [value]=\"$inviteType()\" (ionChange)=\"onTabChanged($event)\">\n <ion-segment-button value=\"mass\">\n Mass invite [{{ space.id }} - {{ space.type }}]\n </ion-segment-button>\n <ion-segment-button value=\"personal\"\n >Personal invite</ion-segment-button\n >\n </ion-segment>\n }\n\n @switch ($inviteType()) {\n @case (\"personal\") {\n <sneat-new-member-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n @case (\"mass\") {\n <ion-card>\n <ion-card-content>\n <sneat-invite-links [contactusSpace]=\"contactusSpace\" />\n\n <p>\n <b>Or</b> you can send\n <a\n href=\"\"\n (click)=\"$inviteType.set('personal'); $event.preventDefault()\"\n >personal invite</a\n >\n by email.\n </p>\n </ion-card-content>\n </ion-card>\n }\n }\n }\n @case (\"animal\") {\n <sneat-new-pet-form\n [$space]=\"$space()\"\n [$contact]=\"$contact()\"\n (contactChange)=\"$contact.set($event)\"\n />\n }\n }\n</ion-content>\n"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Component, inject } from '@angular/core';
|
|
2
|
+
import { IonBackButton, IonButton, IonButtons, IonContent, IonHeader, IonIcon, IonMenuButton, IonTitle, IonToolbar, } from '@ionic/angular/standalone';
|
|
3
|
+
import { ContactDetailsComponent, PersonTitle } from '@sneat/contactus-shared';
|
|
4
|
+
import { SneatNavService } from '@sneat/core';
|
|
5
|
+
import { ContactService, ContactusServicesModule, } from '@sneat/contactus-services';
|
|
6
|
+
import { SpaceServiceModule } from '@sneat/space-services';
|
|
7
|
+
import { ClassName } from '@sneat/ui';
|
|
8
|
+
import { ContactBasePage } from '../contact-base-page';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
export class ContactPageComponent extends ContactBasePage {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(inject(ContactService));
|
|
13
|
+
this.contactsService = inject(ContactService);
|
|
14
|
+
this.sneatNavService = inject(SneatNavService);
|
|
15
|
+
this.segment = 'contact';
|
|
16
|
+
this.defaultBackPage = 'contacts';
|
|
17
|
+
}
|
|
18
|
+
// TODO: use or remove
|
|
19
|
+
watchChildContacts() {
|
|
20
|
+
const contactID = this.$contactID();
|
|
21
|
+
if (!contactID) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const space = this.space;
|
|
25
|
+
if (!space) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.contactsService
|
|
29
|
+
.watchChildContacts(space, contactID)
|
|
30
|
+
.pipe(this.takeUntilDestroyed())
|
|
31
|
+
.subscribe({
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
next: (_children) => {
|
|
34
|
+
// Handle children if needed
|
|
35
|
+
},
|
|
36
|
+
error: this.errorLogger.logErrorHandler('failed to get child contacts'),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// TODO: use or remove
|
|
40
|
+
saveAddress(save) {
|
|
41
|
+
const spaceID = this.space?.id, contactID = this.$contactID(), address = save.object;
|
|
42
|
+
if (!spaceID || !contactID || !address) {
|
|
43
|
+
save.error('Can not save address without team and contact context');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const request = {
|
|
47
|
+
spaceID,
|
|
48
|
+
contactID,
|
|
49
|
+
address,
|
|
50
|
+
};
|
|
51
|
+
this.contactService.updateContact(request).subscribe({
|
|
52
|
+
next: () => save.success(),
|
|
53
|
+
error: save.error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
deleteContact() {
|
|
57
|
+
const contact = this.$contact();
|
|
58
|
+
if (!contact) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!confirm(`Are you sure you want to delete contact "${contact.brief?.title}"?`)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const request = {
|
|
65
|
+
spaceID: this.space.id,
|
|
66
|
+
contactID: contact.id,
|
|
67
|
+
};
|
|
68
|
+
this.contactsService.deleteContact(request).subscribe({
|
|
69
|
+
next: () => {
|
|
70
|
+
this.sneatNavService.goBack(`/space/${this.space?.id}/contacts`);
|
|
71
|
+
},
|
|
72
|
+
error: this.errorLogger.logErrorHandler('failed to delete contact'),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ContactPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
76
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ContactPageComponent, isStandalone: true, selector: "sneat-contact-page", providers: [{ provide: ClassName, useValue: 'ContactPageComponent' }], usesInheritance: true, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if ($contact(); as contact) {\n {{ contact | personTitle }}\n } @else {\n Contact\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button\n title=\"Delete contact\"\n color=\"medium\"\n (click)=\"deleteContact()\"\n >\n <ion-icon name=\"trash\" slot=\"start\" />\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n <sneat-contact-details [$contact]=\"$contact()\" [$space]=\"$space()\" />\n</ion-content>\n", dependencies: [{ kind: "component", type: ContactDetailsComponent, selector: "sneat-contact-details", inputs: ["$contact"], outputs: ["contactChange"] }, { kind: "ngmodule", type: ContactusServicesModule }, { kind: "ngmodule", type: SpaceServiceModule }, { 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: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "pipe", type: PersonTitle, name: "personTitle" }] }); }
|
|
77
|
+
}
|
|
78
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ContactPageComponent, decorators: [{
|
|
79
|
+
type: Component,
|
|
80
|
+
args: [{ selector: 'sneat-contact-page', imports: [
|
|
81
|
+
ContactDetailsComponent,
|
|
82
|
+
ContactusServicesModule,
|
|
83
|
+
SpaceServiceModule,
|
|
84
|
+
PersonTitle,
|
|
85
|
+
IonHeader,
|
|
86
|
+
IonToolbar,
|
|
87
|
+
IonButtons,
|
|
88
|
+
IonBackButton,
|
|
89
|
+
IonTitle,
|
|
90
|
+
IonButton,
|
|
91
|
+
IonIcon,
|
|
92
|
+
IonMenuButton,
|
|
93
|
+
IonContent,
|
|
94
|
+
], providers: [{ provide: ClassName, useValue: 'ContactPageComponent' }], template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if ($contact(); as contact) {\n {{ contact | personTitle }}\n } @else {\n Contact\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button\n title=\"Delete contact\"\n color=\"medium\"\n (click)=\"deleteContact()\"\n >\n <ion-icon name=\"trash\" slot=\"start\" />\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n <sneat-contact-details [$contact]=\"$contact()\" [$space]=\"$space()\" />\n</ion-content>\n" }]
|
|
95
|
+
}], ctorParameters: () => [] });
|
|
96
|
+
//# sourceMappingURL=contact-page.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-page.component.js","sourceRoot":"","sources":["../../../../../../../../libs/contactus/internal/src/lib/pages/contact/contact-page.component.ts","../../../../../../../../libs/contactus/internal/src/lib/pages/contact/contact-page.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, inject } from '@angular/core';\nimport {\n IonBackButton,\n IonButton,\n IonButtons,\n IonContent,\n IonHeader,\n IonIcon,\n IonMenuButton,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport { ISaveEvent } from '@sneat/components';\nimport { ContactDetailsComponent, PersonTitle } from '@sneat/contactus-shared';\nimport { SneatNavService } from '@sneat/core';\nimport { IAddress } from '@sneat/contactus-core';\nimport {\n ContactService,\n ContactusServicesModule,\n IContactRequest,\n IUpdateContactRequest,\n} from '@sneat/contactus-services';\nimport { SpaceServiceModule } from '@sneat/space-services';\nimport { ClassName } from '@sneat/ui';\nimport { ContactBasePage } from '../contact-base-page';\n\n@Component({\n selector: 'sneat-contact-page',\n templateUrl: './contact-page.component.html',\n imports: [\n ContactDetailsComponent,\n ContactusServicesModule,\n SpaceServiceModule,\n PersonTitle,\n IonHeader,\n IonToolbar,\n IonButtons,\n IonBackButton,\n IonTitle,\n IonButton,\n IonIcon,\n IonMenuButton,\n IonContent,\n ],\n providers: [{ provide: ClassName, useValue: 'ContactPageComponent' }],\n})\nexport class ContactPageComponent extends ContactBasePage {\n private readonly contactsService = inject(ContactService);\n private readonly sneatNavService = inject(SneatNavService);\n\n protected segment: 'contact' | 'members' | 'assets' = 'contact';\n\n constructor() {\n super(inject(ContactService));\n this.defaultBackPage = 'contacts';\n }\n\n // TODO: use or remove\n private watchChildContacts(): void {\n const contactID = this.$contactID();\n if (!contactID) {\n return;\n }\n const space = this.space;\n if (!space) {\n return;\n }\n this.contactsService\n .watchChildContacts(space, contactID)\n .pipe(this.takeUntilDestroyed())\n .subscribe({\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n next: (_children) => {\n // Handle children if needed\n },\n error: this.errorLogger.logErrorHandler('failed to get child contacts'),\n });\n }\n\n // TODO: use or remove\n protected saveAddress(save: ISaveEvent<IAddress>): void {\n const spaceID = this.space?.id,\n contactID = this.$contactID(),\n address = save.object;\n\n if (!spaceID || !contactID || !address) {\n save.error('Can not save address without team and contact context');\n return;\n }\n\n const request: IUpdateContactRequest = {\n spaceID,\n contactID,\n address,\n };\n\n this.contactService.updateContact(request).subscribe({\n next: () => save.success(),\n error: save.error,\n });\n }\n\n protected deleteContact(): void {\n const contact = this.$contact();\n if (!contact) {\n return;\n }\n if (\n !confirm(\n `Are you sure you want to delete contact \"${contact.brief?.title}\"?`,\n )\n ) {\n return;\n }\n const request: IContactRequest = {\n spaceID: this.space.id,\n contactID: contact.id,\n };\n\n this.contactsService.deleteContact(request).subscribe({\n next: () => {\n this.sneatNavService.goBack(`/space/${this.space?.id}/contacts`);\n },\n error: this.errorLogger.logErrorHandler('failed to delete contact'),\n });\n }\n}\n","<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>\n @if ($contact(); as contact) {\n {{ contact | personTitle }}\n } @else {\n Contact\n }\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button\n title=\"Delete contact\"\n color=\"medium\"\n (click)=\"deleteContact()\"\n >\n <ion-icon name=\"trash\" slot=\"start\" />\n </ion-button>\n <ion-menu-button />\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n <sneat-contact-details [$contact]=\"$contact()\" [$space]=\"$space()\" />\n</ion-content>\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/contactus/internal/src/lib/pages/contact/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './contact-page.component';\n"]}
|