@sneat/space-components 0.2.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/avatar/avatar.component.js +15 -0
- package/esm2022/lib/avatar/avatar.component.js.map +1 -0
- package/esm2022/lib/index.js +13 -0
- package/esm2022/lib/index.js.map +1 -0
- package/esm2022/lib/space-base-component.directive.js +350 -0
- package/esm2022/lib/space-base-component.directive.js.map +1 -0
- package/esm2022/lib/space-component-base-params.service.js +22 -0
- package/esm2022/lib/space-component-base-params.service.js.map +1 -0
- package/esm2022/lib/space-item-page-base.component.js +121 -0
- package/esm2022/lib/space-item-page-base.component.js.map +1 -0
- package/esm2022/lib/space-items-base.component.js +8 -0
- package/esm2022/lib/space-items-base.component.js.map +1 -0
- package/esm2022/lib/space-menu/index.js +2 -0
- package/esm2022/lib/space-menu/index.js.map +1 -0
- package/esm2022/lib/space-menu/space-menu.component.js +119 -0
- package/esm2022/lib/space-menu/space-menu.component.js.map +1 -0
- package/esm2022/lib/space-module-base.component.js +28 -0
- package/esm2022/lib/space-module-base.component.js.map +1 -0
- package/esm2022/lib/space-page-base-component.service.js +11 -0
- package/esm2022/lib/space-page-base-component.service.js.map +1 -0
- package/esm2022/lib/space-page-title/space-page-title.component.js +27 -0
- package/esm2022/lib/space-page-title/space-page-title.component.js.map +1 -0
- package/esm2022/lib/spaces-card/index.js +2 -0
- package/esm2022/lib/spaces-card/index.js.map +1 -0
- package/esm2022/lib/spaces-card/spaces-card.component.js +208 -0
- package/esm2022/lib/spaces-card/spaces-card.component.js.map +1 -0
- package/esm2022/lib/spaces-list/index.js +2 -0
- package/esm2022/lib/spaces-list/index.js.map +1 -0
- package/esm2022/lib/spaces-list/spaces-list.component.js +111 -0
- package/esm2022/lib/spaces-list/spaces-list.component.js.map +1 -0
- package/esm2022/lib/spaces-menu/index.js +2 -0
- package/esm2022/lib/spaces-menu/index.js.map +1 -0
- package/esm2022/lib/spaces-menu/spaces-menu.component.js +105 -0
- package/esm2022/lib/spaces-menu/spaces-menu.component.js.map +1 -0
- package/esm2022/sneat-space-components.js +5 -0
- package/esm2022/sneat-space-components.js.map +1 -0
- package/index.d.ts +1 -0
- package/lib/avatar/avatar.component.d.ts +7 -0
- package/lib/index.d.ts +12 -0
- package/lib/space-base-component.directive.d.ts +68 -0
- package/lib/space-component-base-params.service.d.ts +15 -0
- package/lib/space-item-page-base.component.d.ts +22 -0
- package/lib/space-items-base.component.d.ts +4 -0
- package/lib/space-menu/index.d.ts +1 -0
- package/lib/space-menu/space-menu.component.d.ts +19 -0
- package/lib/space-module-base.component.d.ts +10 -0
- package/lib/space-page-base-component.service.d.ts +6 -0
- package/lib/space-page-title/space-page-title.component.d.ts +11 -0
- package/lib/spaces-card/index.d.ts +1 -0
- package/lib/spaces-card/spaces-card.component.d.ts +33 -0
- package/lib/spaces-list/index.d.ts +1 -0
- package/lib/spaces-list/spaces-list.component.d.ts +22 -0
- package/lib/spaces-menu/index.d.ts +1 -0
- package/lib/spaces-menu/spaces-menu.component.d.ts +22 -0
- package/package.json +27 -0
- package/sneat-space-components.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SpaceBaseComponent } from './space-base-component.directive';
|
|
2
|
+
export class SpaceItemsBaseComponent extends SpaceBaseComponent {
|
|
3
|
+
constructor(parentPagePath) {
|
|
4
|
+
super();
|
|
5
|
+
this.$defaultBackUrlSpacePath.set(parentPagePath);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=space-items-base.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-items-base.component.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-items-base.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,MAAM,OAAgB,uBAAwB,SAAQ,kBAAkB;IACtE,YAAsB,cAAsB;QAC1C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;CACF","sourcesContent":["import { SpaceBaseComponent } from './space-base-component.directive';\n\nexport abstract class SpaceItemsBaseComponent extends SpaceBaseComponent {\n protected constructor(parentPagePath: string) {\n super();\n this.$defaultBackUrlSpacePath.set(parentPagePath);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/space-menu/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC","sourcesContent":["export * from './space-menu.component';\n"]}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { TitleCasePipe } from '@angular/common';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, inject, signal, } from '@angular/core';
|
|
3
|
+
import { ActivatedRoute, NavigationEnd, Router, RouterLink, } from '@angular/router';
|
|
4
|
+
import { IonButton, IonButtons, IonIcon, IonItem, IonLabel, IonList, IonSelect, IonSelectOption, MenuController, } from '@ionic/angular/standalone';
|
|
5
|
+
import { AuthMenuItemComponent } from '@sneat/auth-ui';
|
|
6
|
+
import { ContactusServicesModule } from '@sneat/contactus-services';
|
|
7
|
+
import { zipMapBriefsWithIDs } from '@sneat/space-models';
|
|
8
|
+
import { SpaceServiceModule } from '@sneat/space-services';
|
|
9
|
+
import { filter } from 'rxjs';
|
|
10
|
+
import { takeUntil } from 'rxjs/operators';
|
|
11
|
+
import { SpaceBaseComponent } from '../space-base-component.directive';
|
|
12
|
+
import { SpaceComponentBaseParams } from '../space-component-base-params.service';
|
|
13
|
+
import { ClassName } from '@sneat/ui';
|
|
14
|
+
import * as i0 from "@angular/core";
|
|
15
|
+
export class SpaceMenuComponent extends SpaceBaseComponent {
|
|
16
|
+
constructor() {
|
|
17
|
+
const router = inject(Router);
|
|
18
|
+
super();
|
|
19
|
+
this.$spaces = signal(undefined, ...(ngDevMode ? [{ debugName: "$spaces" }] : []));
|
|
20
|
+
this.$disabled = computed(() => !this.$spaceID(), ...(ngDevMode ? [{ debugName: "$disabled" }] : []));
|
|
21
|
+
this.$currentPage = signal('', ...(ngDevMode ? [{ debugName: "$currentPage" }] : []));
|
|
22
|
+
this.activatedRoute = inject(ActivatedRoute);
|
|
23
|
+
this.menuCtrl = inject(MenuController);
|
|
24
|
+
this.onUserStateChanged = (userState) => {
|
|
25
|
+
this.$spaces.set(userState?.record
|
|
26
|
+
? zipMapBriefsWithIDs(userState.record.spaces) || []
|
|
27
|
+
: undefined);
|
|
28
|
+
};
|
|
29
|
+
this.spaceParams.userService.userState
|
|
30
|
+
.pipe(takeUntil(this.destroyed$))
|
|
31
|
+
.subscribe({
|
|
32
|
+
next: this.onUserStateChanged,
|
|
33
|
+
error: this.errorLogger.logErrorHandler('failed to get user stage'),
|
|
34
|
+
});
|
|
35
|
+
router.events
|
|
36
|
+
.pipe(this.takeUntilDestroyed(), filter((event) => event instanceof NavigationEnd))
|
|
37
|
+
.subscribe((event) => {
|
|
38
|
+
let route = this.activatedRoute.firstChild;
|
|
39
|
+
while (route?.firstChild) {
|
|
40
|
+
route = route.firstChild;
|
|
41
|
+
}
|
|
42
|
+
const url = event.urlAfterRedirects.split('/');
|
|
43
|
+
this.$currentPage.set(url.length > 4 ? url[4] : '');
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// TODO: Should we use goSpacePage('') instead?
|
|
47
|
+
goOverview() {
|
|
48
|
+
const space = this.$space();
|
|
49
|
+
if (!space) {
|
|
50
|
+
this.errorLogger.logError('no space context');
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
this.spaceParams.spaceNavService.navigateToSpace(space).then((v) => {
|
|
54
|
+
if (v) {
|
|
55
|
+
this.closeMenu();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
61
|
+
goSpacePage(event, _p) {
|
|
62
|
+
// At the moment we use routerLink for navigation
|
|
63
|
+
event.stopPropagation();
|
|
64
|
+
// event.preventDefault();
|
|
65
|
+
this.closeMenu();
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
closeMenu() {
|
|
69
|
+
this.menuCtrl.close().catch(this.errorLogger.logError);
|
|
70
|
+
}
|
|
71
|
+
onSpaceSelected(event) {
|
|
72
|
+
const spaceID = event.detail.value;
|
|
73
|
+
if (spaceID === this.space?.id) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const space = this.$spaces()?.find((t) => t.id === spaceID);
|
|
77
|
+
if (space) {
|
|
78
|
+
this.setSpaceRef(space);
|
|
79
|
+
this.spaceNav
|
|
80
|
+
.navigateToSpace(space)
|
|
81
|
+
.catch(this.errorLogger.logErrorHandler('Failed to navigate to teams page on current team changed from team menu dropdown'));
|
|
82
|
+
}
|
|
83
|
+
this.menuCtrl.close().catch(console.error);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
87
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: SpaceMenuComponent, isStandalone: true, selector: "sneat-space-menu", providers: [
|
|
88
|
+
{
|
|
89
|
+
provide: ClassName,
|
|
90
|
+
useValue: 'SpaceMenuComponent',
|
|
91
|
+
},
|
|
92
|
+
SpaceComponentBaseParams,
|
|
93
|
+
], usesInheritance: true, ngImport: i0, template: "<ion-list>\n <ion-item>\n <!--\t\t<ion-icon [name]=\"space.type === 'family' ? 'people-outline' : space.type === 'private' ? 'person-circle-outline' : 'people-outline' \" slot=\"end\" />-->\n <ion-select\n label=\"Space\"\n [value]=\"$space().id\"\n interface=\"popover\"\n (ionChange)=\"onSpaceSelected($event)\"\n style=\"font-weight: bold\"\n >\n @for (userSpace of $spaces(); track userSpace.id) {\n <ion-select-option [value]=\"userSpace.id\"\n >{{\n userSpace.brief.title ||\n (userSpace.brief.type | titlecase) ||\n space.id\n }}\n </ion-select-option>\n } @empty {\n @let space = $space();\n <ion-select-option [value]=\"space?.id\">\n @if (!space || (!space?.id && !space?.type)) {\n Loading...\n } @else {\n {{ space.brief?.title || (space.type | titlecase) || space.id }}\n }\n </ion-select-option>\n }\n </ion-select>\n <!--\t\t@if (!spaces) {-->\n <!--\t\t\t<ion-spinner name=\"lines\" slot=\"end\"></ion-spinner>-->\n <!--\t\t}-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('overview')\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === ''\"\n (click)=\"goOverview()\"\n >\n <ion-icon name=\"home-outline\" slot=\"start\" />\n <ion-label>Overview</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('assets')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'assets'\"\n (click)=\"goSpacePage($event, 'assets')\"\n >\n <ion-icon name=\"car-sport-outline\" slot=\"start\" />\n <ion-label>Assets</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('budget')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'budget'\"\n (click)=\"goSpacePage($event, 'budget')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Budget</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('calendar')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'calendar'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"calendar-outline\" slot=\"start\" />\n <ion-label>Calendar</ion-label>\n <!--\t\t<ion-buttons slot=\"end\">-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Today</ion-button>-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Tomorrow</ion-button>-->\n <!--\t\t</ion-buttons>-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('contacts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'contacts'\"\n (click)=\"goSpacePage($event, 'contacts')\"\n >\n <ion-icon name=\"people-outline\" slot=\"start\" />\n <ion-label>Contacts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('debts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'debts'\"\n (click)=\"goSpacePage($event, 'debts')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Debts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('documents')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'documents'\"\n (click)=\"goSpacePage($event, 'documents')\"\n >\n <ion-icon name=\"documents-outline\" slot=\"start\" />\n <ion-label>Documents</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('lists')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'lists'\"\n (click)=\"goSpacePage($event, 'lists')\"\n >\n <ion-icon name=\"list-outline\" slot=\"start\" />\n <ion-label>Lists</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button\n routerDirection=\"root\"\n [routerLink]=\"spacePageUrl('list/buy/groceries')\"\n (click)=\"goSpacePage($event, 'list/buy/groceries')\"\n >\n <ion-label>\uD83D\uDED2</ion-label>\n </ion-button>\n <!--\t\t\t<ion-button routerLink=\"./list/towatch\">\uD83C\uDF7F</ion-button>-->\n </ion-buttons>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('members')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'members'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"people-circle-outline\" slot=\"start\" />\n <ion-label>Members</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('trackers')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'trackers'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"bar-chart-outline\" slot=\"start\" />\n <ion-label>Trackers</ion-label>\n </ion-item>\n <sneat-auth-menu-item />\n</ion-list>\n", styles: [".currentPage ion-label{font-weight:700}\n"], dependencies: [{ kind: "component", type: AuthMenuItemComponent, selector: "sneat-auth-menu-item" }, { kind: "ngmodule", type: ContactusServicesModule }, { kind: "ngmodule", type: SpaceServiceModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
94
|
+
}
|
|
95
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceMenuComponent, decorators: [{
|
|
96
|
+
type: Component,
|
|
97
|
+
args: [{ selector: 'sneat-space-menu', imports: [
|
|
98
|
+
AuthMenuItemComponent,
|
|
99
|
+
ContactusServicesModule,
|
|
100
|
+
SpaceServiceModule,
|
|
101
|
+
TitleCasePipe,
|
|
102
|
+
RouterLink,
|
|
103
|
+
IonList,
|
|
104
|
+
IonItem,
|
|
105
|
+
IonSelect,
|
|
106
|
+
IonSelectOption,
|
|
107
|
+
IonIcon,
|
|
108
|
+
IonLabel,
|
|
109
|
+
IonButtons,
|
|
110
|
+
IonButton,
|
|
111
|
+
], providers: [
|
|
112
|
+
{
|
|
113
|
+
provide: ClassName,
|
|
114
|
+
useValue: 'SpaceMenuComponent',
|
|
115
|
+
},
|
|
116
|
+
SpaceComponentBaseParams,
|
|
117
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-list>\n <ion-item>\n <!--\t\t<ion-icon [name]=\"space.type === 'family' ? 'people-outline' : space.type === 'private' ? 'person-circle-outline' : 'people-outline' \" slot=\"end\" />-->\n <ion-select\n label=\"Space\"\n [value]=\"$space().id\"\n interface=\"popover\"\n (ionChange)=\"onSpaceSelected($event)\"\n style=\"font-weight: bold\"\n >\n @for (userSpace of $spaces(); track userSpace.id) {\n <ion-select-option [value]=\"userSpace.id\"\n >{{\n userSpace.brief.title ||\n (userSpace.brief.type | titlecase) ||\n space.id\n }}\n </ion-select-option>\n } @empty {\n @let space = $space();\n <ion-select-option [value]=\"space?.id\">\n @if (!space || (!space?.id && !space?.type)) {\n Loading...\n } @else {\n {{ space.brief?.title || (space.type | titlecase) || space.id }}\n }\n </ion-select-option>\n }\n </ion-select>\n <!--\t\t@if (!spaces) {-->\n <!--\t\t\t<ion-spinner name=\"lines\" slot=\"end\"></ion-spinner>-->\n <!--\t\t}-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('overview')\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === ''\"\n (click)=\"goOverview()\"\n >\n <ion-icon name=\"home-outline\" slot=\"start\" />\n <ion-label>Overview</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('assets')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'assets'\"\n (click)=\"goSpacePage($event, 'assets')\"\n >\n <ion-icon name=\"car-sport-outline\" slot=\"start\" />\n <ion-label>Assets</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('budget')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'budget'\"\n (click)=\"goSpacePage($event, 'budget')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Budget</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('calendar')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'calendar'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"calendar-outline\" slot=\"start\" />\n <ion-label>Calendar</ion-label>\n <!--\t\t<ion-buttons slot=\"end\">-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Today</ion-button>-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Tomorrow</ion-button>-->\n <!--\t\t</ion-buttons>-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('contacts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'contacts'\"\n (click)=\"goSpacePage($event, 'contacts')\"\n >\n <ion-icon name=\"people-outline\" slot=\"start\" />\n <ion-label>Contacts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('debts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'debts'\"\n (click)=\"goSpacePage($event, 'debts')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Debts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('documents')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'documents'\"\n (click)=\"goSpacePage($event, 'documents')\"\n >\n <ion-icon name=\"documents-outline\" slot=\"start\" />\n <ion-label>Documents</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('lists')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'lists'\"\n (click)=\"goSpacePage($event, 'lists')\"\n >\n <ion-icon name=\"list-outline\" slot=\"start\" />\n <ion-label>Lists</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button\n routerDirection=\"root\"\n [routerLink]=\"spacePageUrl('list/buy/groceries')\"\n (click)=\"goSpacePage($event, 'list/buy/groceries')\"\n >\n <ion-label>\uD83D\uDED2</ion-label>\n </ion-button>\n <!--\t\t\t<ion-button routerLink=\"./list/towatch\">\uD83C\uDF7F</ion-button>-->\n </ion-buttons>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('members')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'members'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"people-circle-outline\" slot=\"start\" />\n <ion-label>Members</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('trackers')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'trackers'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"bar-chart-outline\" slot=\"start\" />\n <ion-label>Trackers</ion-label>\n </ion-item>\n <sneat-auth-menu-item />\n</ion-list>\n", styles: [".currentPage ion-label{font-weight:700}\n"] }]
|
|
118
|
+
}], ctorParameters: () => [] });
|
|
119
|
+
//# sourceMappingURL=space-menu.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-menu.component.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/space-menu/space-menu.component.ts","../../../../../../../libs/space/components/src/lib/space-menu/space-menu.component.html"],"names":[],"mappings":"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","sourcesContent":["import { TitleCasePipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n NavigationEnd,\n Router,\n RouterLink,\n} from '@angular/router';\nimport {\n IonButton,\n IonButtons,\n IonIcon,\n IonItem,\n IonLabel,\n IonList,\n IonSelect,\n IonSelectOption,\n MenuController,\n} from '@ionic/angular/standalone';\nimport { ISneatUserState } from '@sneat/auth-core';\nimport { IUserSpaceBrief } from '@sneat/auth-models';\nimport { AuthMenuItemComponent } from '@sneat/auth-ui';\nimport { ContactusServicesModule } from '@sneat/contactus-services';\nimport { IIdAndBrief } from '@sneat/core';\nimport { zipMapBriefsWithIDs } from '@sneat/space-models';\nimport { SpaceServiceModule } from '@sneat/space-services';\nimport { filter } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SpaceBaseComponent } from '../space-base-component.directive';\nimport { SpaceComponentBaseParams } from '../space-component-base-params.service';\nimport { ClassName } from '@sneat/ui';\n\n@Component({\n selector: 'sneat-space-menu',\n templateUrl: './space-menu.component.html',\n styles: '.currentPage ion-label {font-weight: bold}',\n imports: [\n AuthMenuItemComponent,\n ContactusServicesModule,\n SpaceServiceModule,\n TitleCasePipe,\n RouterLink,\n IonList,\n IonItem,\n IonSelect,\n IonSelectOption,\n IonIcon,\n IonLabel,\n IonButtons,\n IonButton,\n ],\n providers: [\n {\n provide: ClassName,\n useValue: 'SpaceMenuComponent',\n },\n SpaceComponentBaseParams,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SpaceMenuComponent extends SpaceBaseComponent {\n protected readonly $spaces = signal<\n readonly IIdAndBrief<IUserSpaceBrief>[] | undefined\n >(undefined);\n\n protected readonly $disabled = computed(() => !this.$spaceID());\n\n protected readonly $currentPage = signal<string>('');\n\n private readonly activatedRoute = inject(ActivatedRoute);\n private readonly menuCtrl = inject(MenuController);\n\n constructor() {\n const router = inject(Router);\n\n super();\n this.spaceParams.userService.userState\n .pipe(takeUntil(this.destroyed$))\n .subscribe({\n next: this.onUserStateChanged,\n error: this.errorLogger.logErrorHandler('failed to get user stage'),\n });\n router.events\n .pipe(\n this.takeUntilDestroyed(),\n filter((event) => event instanceof NavigationEnd),\n )\n .subscribe((event: NavigationEnd) => {\n let route = this.activatedRoute.firstChild;\n while (route?.firstChild) {\n route = route.firstChild;\n }\n const url = event.urlAfterRedirects.split('/');\n this.$currentPage.set(url.length > 4 ? url[4] : '');\n });\n }\n\n // TODO: Should we use goSpacePage('') instead?\n protected goOverview(): boolean {\n const space = this.$space();\n if (!space) {\n this.errorLogger.logError('no space context');\n return false;\n }\n this.spaceParams.spaceNavService.navigateToSpace(space).then((v) => {\n if (v) {\n this.closeMenu();\n }\n });\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected goSpacePage(event: Event, _p: string): boolean {\n // At the moment we use routerLink for navigation\n event.stopPropagation();\n // event.preventDefault();\n this.closeMenu();\n return false;\n }\n\n protected closeMenu(): void {\n this.menuCtrl.close().catch(this.errorLogger.logError);\n }\n\n protected onSpaceSelected(event: Event): void {\n const spaceID = (event as CustomEvent).detail.value as string;\n if (spaceID === this.space?.id) {\n return;\n }\n const space = this.$spaces()?.find((t) => t.id === spaceID);\n if (space) {\n this.setSpaceRef(space);\n this.spaceNav\n .navigateToSpace(space)\n .catch(\n this.errorLogger.logErrorHandler(\n 'Failed to navigate to teams page on current team changed from team menu dropdown',\n ),\n );\n }\n this.menuCtrl.close().catch(console.error);\n return;\n }\n\n private readonly onUserStateChanged = (userState: ISneatUserState): void => {\n this.$spaces.set(\n userState?.record\n ? zipMapBriefsWithIDs(userState.record.spaces) || []\n : undefined,\n );\n };\n}\n","<ion-list>\n <ion-item>\n <!--\t\t<ion-icon [name]=\"space.type === 'family' ? 'people-outline' : space.type === 'private' ? 'person-circle-outline' : 'people-outline' \" slot=\"end\" />-->\n <ion-select\n label=\"Space\"\n [value]=\"$space().id\"\n interface=\"popover\"\n (ionChange)=\"onSpaceSelected($event)\"\n style=\"font-weight: bold\"\n >\n @for (userSpace of $spaces(); track userSpace.id) {\n <ion-select-option [value]=\"userSpace.id\"\n >{{\n userSpace.brief.title ||\n (userSpace.brief.type | titlecase) ||\n space.id\n }}\n </ion-select-option>\n } @empty {\n @let space = $space();\n <ion-select-option [value]=\"space?.id\">\n @if (!space || (!space?.id && !space?.type)) {\n Loading...\n } @else {\n {{ space.brief?.title || (space.type | titlecase) || space.id }}\n }\n </ion-select-option>\n }\n </ion-select>\n <!--\t\t@if (!spaces) {-->\n <!--\t\t\t<ion-spinner name=\"lines\" slot=\"end\"></ion-spinner>-->\n <!--\t\t}-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('overview')\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === ''\"\n (click)=\"goOverview()\"\n >\n <ion-icon name=\"home-outline\" slot=\"start\" />\n <ion-label>Overview</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('assets')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'assets'\"\n (click)=\"goSpacePage($event, 'assets')\"\n >\n <ion-icon name=\"car-sport-outline\" slot=\"start\" />\n <ion-label>Assets</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('budget')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'budget'\"\n (click)=\"goSpacePage($event, 'budget')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Budget</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('calendar')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'calendar'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"calendar-outline\" slot=\"start\" />\n <ion-label>Calendar</ion-label>\n <!--\t\t<ion-buttons slot=\"end\">-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Today</ion-button>-->\n <!--\t\t\t<ion-button color=\"primary\" style=\"text-transform: none; font-size: x-small\">Tomorrow</ion-button>-->\n <!--\t\t</ion-buttons>-->\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('contacts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'contacts'\"\n (click)=\"goSpacePage($event, 'contacts')\"\n >\n <ion-icon name=\"people-outline\" slot=\"start\" />\n <ion-label>Contacts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('debts')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'debts'\"\n (click)=\"goSpacePage($event, 'debts')\"\n >\n <ion-icon name=\"cash-outline\" slot=\"start\" />\n <ion-label>Debts</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('documents')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'documents'\"\n (click)=\"goSpacePage($event, 'documents')\"\n >\n <ion-icon name=\"documents-outline\" slot=\"start\" />\n <ion-label>Documents</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('lists')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'lists'\"\n (click)=\"goSpacePage($event, 'lists')\"\n >\n <ion-icon name=\"list-outline\" slot=\"start\" />\n <ion-label>Lists</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button\n routerDirection=\"root\"\n [routerLink]=\"spacePageUrl('list/buy/groceries')\"\n (click)=\"goSpacePage($event, 'list/buy/groceries')\"\n >\n <ion-label>🛒</ion-label>\n </ion-button>\n <!--\t\t\t<ion-button routerLink=\"./list/towatch\">🍿</ion-button>-->\n </ion-buttons>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('members')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'members'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"people-circle-outline\" slot=\"start\" />\n <ion-label>Members</ion-label>\n </ion-item>\n <ion-item\n tappable\n [routerLink]=\"spacePageUrl('trackers')\"\n routerDirection=\"root\"\n [disabled]=\"$disabled()\"\n [class.currentPage]=\"$currentPage() === 'trackers'\"\n (click)=\"closeMenu()\"\n >\n <ion-icon name=\"bar-chart-outline\" slot=\"start\" />\n <ion-label>Trackers</ion-label>\n </ion-item>\n <sneat-auth-menu-item />\n</ion-list>\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
|
+
import { takeUntil } from 'rxjs/operators';
|
|
3
|
+
import { SpaceBaseComponent } from './space-base-component.directive';
|
|
4
|
+
export class SpaceModuleBaseComponent extends SpaceBaseComponent {
|
|
5
|
+
constructor(spaceModuleService) {
|
|
6
|
+
super();
|
|
7
|
+
this.spaceModuleService = spaceModuleService;
|
|
8
|
+
this.spaceModuleDbo$ = new BehaviorSubject(undefined);
|
|
9
|
+
}
|
|
10
|
+
onSpaceIdChanged() {
|
|
11
|
+
super.onSpaceIdChanged();
|
|
12
|
+
this.spaceModuleService
|
|
13
|
+
.watchSpaceModuleRecord(this.space.id)
|
|
14
|
+
.pipe(takeUntil(this.spaceIDChanged$))
|
|
15
|
+
.subscribe({
|
|
16
|
+
next: (o) => {
|
|
17
|
+
this.spaceModuleDbo$.next(o.dbo);
|
|
18
|
+
this.onSpaceModuleDboChanged(o.dbo || null);
|
|
19
|
+
},
|
|
20
|
+
error: (err) => {
|
|
21
|
+
console.error('Failed to load team module record', err);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
|
|
26
|
+
onSpaceModuleDboChanged(_dbo) { }
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=space-module-base.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-module-base.component.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-module-base.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAGtE,MAAM,OAAgB,wBAGpB,SAAQ,kBAAkB;IAK1B,YAAsB,kBAA2C;QAC/D,KAAK,EAAE,CAAC;QADY,uBAAkB,GAAlB,kBAAkB,CAAyB;QAJ9C,oBAAe,GAAG,IAAI,eAAe,CAEtD,SAAS,CAAC,CAAC;IAIb,CAAC;IAEkB,gBAAgB;QACjC,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACzB,IAAI,CAAC,kBAAkB;aACpB,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;aACrC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;aACrC,SAAS,CAAC;YACT,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;gBACV,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YAC9C,CAAC;YACD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;gBACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC;SACF,CAAC,CAAC;IACP,CAAC;IAED,mGAAmG;IACzF,uBAAuB,CAAC,IAAgB,IAAG,CAAC;CACvD","sourcesContent":["import { BehaviorSubject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SpaceBaseComponent } from './space-base-component.directive';\nimport { SpaceModuleService } from '@sneat/space-services';\n\nexport abstract class SpaceModuleBaseComponent<\n Brief,\n Dbo extends Brief,\n> extends SpaceBaseComponent {\n protected readonly spaceModuleDbo$ = new BehaviorSubject<\n Dbo | null | undefined\n >(undefined);\n\n constructor(protected spaceModuleService: SpaceModuleService<Dbo>) {\n super();\n }\n\n protected override onSpaceIdChanged() {\n super.onSpaceIdChanged();\n this.spaceModuleService\n .watchSpaceModuleRecord(this.space.id)\n .pipe(takeUntil(this.spaceIDChanged$))\n .subscribe({\n next: (o) => {\n this.spaceModuleDbo$.next(o.dbo);\n this.onSpaceModuleDboChanged(o.dbo || null);\n },\n error: (err) => {\n console.error('Failed to load team module record', err);\n },\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function\n protected onSpaceModuleDboChanged(_dbo: Dbo | null) {}\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { SpaceBaseComponent } from './space-base-component.directive';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class SpacePageBaseComponent extends SpaceBaseComponent {
|
|
5
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacePageBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacePageBaseComponent }); }
|
|
7
|
+
}
|
|
8
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacePageBaseComponent, decorators: [{
|
|
9
|
+
type: Injectable
|
|
10
|
+
}] });
|
|
11
|
+
//# sourceMappingURL=space-page-base-component.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-page-base-component.service.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-page-base-component.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;;AAGtE,MAAM,OAAgB,sBAAuB,SAAQ,kBAAkB;8GAAjD,sBAAsB;kHAAtB,sBAAsB;;2FAAtB,sBAAsB;kBAD3C,UAAU","sourcesContent":["import { Injectable } from '@angular/core';\nimport { SpaceBaseComponent } from './space-base-component.directive';\n\n@Injectable() // we need this decorator so we can implement Angular interfaces\nexport abstract class SpacePageBaseComponent extends SpaceBaseComponent {}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TitleCasePipe } from '@angular/common';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
3
|
+
import { IonTitle } from '@ionic/angular/standalone';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export class SpacePageTitleComponent {
|
|
6
|
+
get typeTitle() {
|
|
7
|
+
return this.space?.type && this.titlesBySpaceType
|
|
8
|
+
? this.titlesBySpaceType[this.space.type]
|
|
9
|
+
: '';
|
|
10
|
+
}
|
|
11
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacePageTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
12
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: SpacePageTitleComponent, isStandalone: true, selector: "sneat-space-page-title", inputs: { icon: "icon", generalTitle: "generalTitle", space: "space", titlesBySpaceType: "titlesBySpaceType" }, ngImport: i0, template: "<ion-title>\n @if (space) {\n @if (!!typeTitle) {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ typeTitle }}</span>\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span\n >{{ generalTitle }} @\n {{ space.brief?.title || (space.type | titlecase) || space.id }}</span\n >\n }\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ generalTitle }}</span>\n }\n</ion-title>\n", dependencies: [{ kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13
|
+
}
|
|
14
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacePageTitleComponent, decorators: [{
|
|
15
|
+
type: Component,
|
|
16
|
+
args: [{ imports: [TitleCasePipe, IonTitle], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sneat-space-page-title', template: "<ion-title>\n @if (space) {\n @if (!!typeTitle) {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ typeTitle }}</span>\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span\n >{{ generalTitle }} @\n {{ space.brief?.title || (space.type | titlecase) || space.id }}</span\n >\n }\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ generalTitle }}</span>\n }\n</ion-title>\n" }]
|
|
17
|
+
}], propDecorators: { icon: [{
|
|
18
|
+
type: Input
|
|
19
|
+
}], generalTitle: [{
|
|
20
|
+
type: Input
|
|
21
|
+
}], space: [{
|
|
22
|
+
type: Input,
|
|
23
|
+
args: [{ required: true }]
|
|
24
|
+
}], titlesBySpaceType: [{
|
|
25
|
+
type: Input
|
|
26
|
+
}] } });
|
|
27
|
+
//# sourceMappingURL=space-page-title.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-page-title.component.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/space-page-title/space-page-title.component.ts","../../../../../../../libs/space/components/src/lib/space-page-title/space-page-title.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;;AASrD,MAAM,OAAO,uBAAuB;IAMlC,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,iBAAiB;YAC/C,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACzC,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;8GAVU,uBAAuB;kGAAvB,uBAAuB,kMCXpC,sfAiBA,4CDX2B,QAAQ,4EAAvB,aAAa;;2FAKZ,uBAAuB;kBANnC,SAAS;8BACC,CAAC,aAAa,EAAE,QAAQ,CAAC,mBACjB,uBAAuB,CAAC,MAAM,YACrC,wBAAwB;;sBAIjC,KAAK;;sBACL,KAAK;;sBACL,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBACxB,KAAK","sourcesContent":["import { TitleCasePipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core';\nimport { IonTitle } from '@ionic/angular/standalone';\nimport { ISpaceContext } from '@sneat/space-models';\n\n@Component({\n imports: [TitleCasePipe, IonTitle],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-space-page-title',\n templateUrl: './space-page-title.component.html',\n})\nexport class SpacePageTitleComponent {\n @Input() icon?: string;\n @Input() generalTitle?: string;\n @Input({ required: true }) space?: ISpaceContext;\n @Input() titlesBySpaceType?: Record<string, string>;\n\n public get typeTitle(): string {\n return this.space?.type && this.titlesBySpaceType\n ? this.titlesBySpaceType[this.space.type]\n : '';\n }\n}\n","<ion-title>\n @if (space) {\n @if (!!typeTitle) {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ typeTitle }}</span>\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span\n >{{ generalTitle }} @\n {{ space.brief?.title || (space.type | titlecase) || space.id }}</span\n >\n }\n } @else {\n <span style=\"margin-right: 0.5em\">{{ icon }}</span>\n <span>{{ generalTitle }}</span>\n }\n</ion-title>\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/spaces-card/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './spaces-card.component';\n"]}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Component, ViewChild, inject } from '@angular/core';
|
|
2
|
+
import { FormsModule } from '@angular/forms';
|
|
3
|
+
import { IonButton, IonButtons, IonCard, IonCardContent, IonCardTitle, IonIcon, IonInput, IonItem, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonSkeletonText, IonSpinner, ToastController, } from '@ionic/angular/standalone';
|
|
4
|
+
import { AnalyticsService } from '@sneat/core';
|
|
5
|
+
import { ErrorLogger } from '@sneat/core';
|
|
6
|
+
import { SpaceNavService, SpaceService } from '@sneat/space-services';
|
|
7
|
+
import { SneatUserService } from '@sneat/auth-core';
|
|
8
|
+
import { Subject } from 'rxjs';
|
|
9
|
+
import { takeUntil } from 'rxjs/operators';
|
|
10
|
+
import * as i0 from "@angular/core";
|
|
11
|
+
import * as i1 from "@angular/forms";
|
|
12
|
+
export class SpacesCardComponent {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.errorLogger = inject(ErrorLogger);
|
|
15
|
+
this.navService = inject(SpaceNavService);
|
|
16
|
+
this.userService = inject(SneatUserService);
|
|
17
|
+
this.spaceService = inject(SpaceService);
|
|
18
|
+
this.analyticsService = inject(AnalyticsService);
|
|
19
|
+
this.toastController = inject(ToastController);
|
|
20
|
+
this.loadingState = 'Authenticating';
|
|
21
|
+
this.spaceName = '';
|
|
22
|
+
this.adding = false;
|
|
23
|
+
this.showAdd = false; //
|
|
24
|
+
this.destroyed = new Subject();
|
|
25
|
+
this.subscriptions = [];
|
|
26
|
+
this.setUser = (userState) => {
|
|
27
|
+
// console.log('SpacesCardComponent => user:', userState);
|
|
28
|
+
const user = userState.record;
|
|
29
|
+
if (user) {
|
|
30
|
+
this.spaces = Object.entries(user?.spaces ? user.spaces : {}).map(([id, team]) => ({ id, brief: team }));
|
|
31
|
+
this.spaces.sort((a, b) => (a.brief.title > b.brief.title ? 1 : -1));
|
|
32
|
+
this.showAdd = !this.spaces?.length;
|
|
33
|
+
if (this.showAdd) {
|
|
34
|
+
this.startAddingSpace();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.spaces = undefined;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
ngOnDestroy() {
|
|
43
|
+
// console.log('SpacesCardComponent.ngOnDestroy()');
|
|
44
|
+
this.destroyed.next();
|
|
45
|
+
this.destroyed.complete();
|
|
46
|
+
this.unsubscribe('ngOnDestroy');
|
|
47
|
+
}
|
|
48
|
+
ngOnInit() {
|
|
49
|
+
this.watchUserRecord();
|
|
50
|
+
}
|
|
51
|
+
goSpace(space) {
|
|
52
|
+
this.navService
|
|
53
|
+
.navigateToSpace(space, 'forward')
|
|
54
|
+
.catch(this.errorLogger.logError);
|
|
55
|
+
}
|
|
56
|
+
addSpace() {
|
|
57
|
+
this.analyticsService.logEvent('addSpace');
|
|
58
|
+
const title = this.spaceName.trim();
|
|
59
|
+
if (!title) {
|
|
60
|
+
this.toastController
|
|
61
|
+
.create({
|
|
62
|
+
position: 'middle',
|
|
63
|
+
message: 'Space name is required',
|
|
64
|
+
color: 'tertiary',
|
|
65
|
+
duration: 5000,
|
|
66
|
+
keyboardClose: true,
|
|
67
|
+
buttons: [{ role: 'cancel', text: 'OK' }],
|
|
68
|
+
})
|
|
69
|
+
.then((toast) => toast
|
|
70
|
+
.present()
|
|
71
|
+
.catch((err) => this.errorLogger.logError(err, 'Failed to present toast')))
|
|
72
|
+
.catch((err) => this.errorLogger.logError(err, 'Faile to create toast'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (this.spaces?.find((t) => t.brief.title === title)) {
|
|
76
|
+
this.toastController
|
|
77
|
+
.create({
|
|
78
|
+
message: 'You already have a team with the same name',
|
|
79
|
+
color: 'danger',
|
|
80
|
+
buttons: ['close'],
|
|
81
|
+
position: 'middle',
|
|
82
|
+
animated: true,
|
|
83
|
+
duration: 3000,
|
|
84
|
+
})
|
|
85
|
+
.then((toast) => {
|
|
86
|
+
toast
|
|
87
|
+
.present()
|
|
88
|
+
.catch((err) => this.errorLogger.logError(err, 'Failed to present toast'));
|
|
89
|
+
})
|
|
90
|
+
.catch((err) => this.errorLogger.logError(err, 'Failed to create toast'));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const request = {
|
|
94
|
+
type: 'team',
|
|
95
|
+
// memberType: TeamMemberType.creator,
|
|
96
|
+
title,
|
|
97
|
+
};
|
|
98
|
+
this.adding = true;
|
|
99
|
+
this.spaceService.createSpace(request).subscribe({
|
|
100
|
+
next: (space) => {
|
|
101
|
+
this.analyticsService.logEvent('spaceCreated', { space: space.id });
|
|
102
|
+
const userTeamBrief2 = {
|
|
103
|
+
userContactID: 'TODO: populate userContactID',
|
|
104
|
+
title: space?.dbo?.title || space.id,
|
|
105
|
+
roles: ['creator'],
|
|
106
|
+
// memberType: request.memberType,
|
|
107
|
+
type: space?.dbo?.type || 'unknown',
|
|
108
|
+
};
|
|
109
|
+
if (userTeamBrief2 && !this.spaces?.find((t) => t.id === space.id)) {
|
|
110
|
+
this.spaces?.push({ id: space.id, brief: userTeamBrief2 });
|
|
111
|
+
}
|
|
112
|
+
this.adding = false;
|
|
113
|
+
this.spaceName = '';
|
|
114
|
+
this.goSpace(space);
|
|
115
|
+
},
|
|
116
|
+
error: (err) => {
|
|
117
|
+
this.errorLogger.logError(err, 'Failed to create new team record');
|
|
118
|
+
this.adding = false;
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
startAddingSpace() {
|
|
123
|
+
this.showAdd = true;
|
|
124
|
+
setTimeout(() => {
|
|
125
|
+
if (!this.addSpaceInput) {
|
|
126
|
+
this.errorLogger.logError('addTeamInput is not set');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.addSpaceInput
|
|
130
|
+
.setFocus()
|
|
131
|
+
.catch((err) => this.errorLogger.logError(err, 'Failed to set focus to "addTeamInput"'));
|
|
132
|
+
}, 200);
|
|
133
|
+
}
|
|
134
|
+
leaveSpace(space, event) {
|
|
135
|
+
if (event) {
|
|
136
|
+
event.stopPropagation();
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
}
|
|
139
|
+
if (!confirm(`Are you sure you want to leave team ${space.brief.title}?`)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const userID = this.userService.currentUserID;
|
|
143
|
+
if (!userID) {
|
|
144
|
+
this.errorLogger.logError('Failed to get current user ID');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.spaceService.leaveSpace({ spaceID: space.id }).subscribe({
|
|
148
|
+
next: () => console.log('left space'),
|
|
149
|
+
error: (err) => this.errorLogger.logError(err, `Failed to leave a space: ${space.brief.title}`),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
watchUserRecord() {
|
|
153
|
+
this.userService.userState.pipe(takeUntil(this.destroyed)).subscribe({
|
|
154
|
+
next: (userState) => {
|
|
155
|
+
// console.log('SpacesCardComponent => user state changed:', userState);
|
|
156
|
+
if (userState.status === 'authenticating') {
|
|
157
|
+
if (this.loadingState === 'Authenticating') {
|
|
158
|
+
this.loadingState = 'Loading';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const uid = userState.user?.uid;
|
|
162
|
+
this.spaces = undefined;
|
|
163
|
+
if (!uid) {
|
|
164
|
+
this.unsubscribe('user signed out');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.subscriptions.push(this.userService.userState.subscribe({
|
|
168
|
+
next: this.setUser,
|
|
169
|
+
error: (err) => this.errorLogger.logError(err, 'Failed to get user record'),
|
|
170
|
+
}));
|
|
171
|
+
},
|
|
172
|
+
error: (err) => this.errorLogger.logError(err, 'Failed to get user ID'),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
176
|
+
unsubscribe(_reason) {
|
|
177
|
+
// console.log(`SpacesCardComponent.unsubscribe(reason: ${reason})`);
|
|
178
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
179
|
+
this.subscriptions = [];
|
|
180
|
+
}
|
|
181
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
182
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: SpacesCardComponent, isStandalone: true, selector: "sneat-spaces-card", viewQueries: [{ propertyName: "addSpaceInput", first: true, predicate: IonInput, descendants: true }], ngImport: i0, template: "<ion-card>\n <ion-item>\n <ion-label>\n <ion-card-title color=\"medium\">Spaces</ion-card-title>\n </ion-label>\n <ion-buttons slot=\"end\" (click)=\"startAddingSpace()\">\n @if (!showAdd) {\n <ion-button color=\"primary\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n @if (spaces) {\n <ion-list>\n @for (space of spaces; track space.id) {\n <ion-item-sliding>\n <ion-item tappable detail (click)=\"goSpace(space)\">\n <ion-label>{{ space.brief.title }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"leaveSpace(space, $event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n <ion-item-options side=\"start\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n <ion-item-options side=\"end\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n </ion-item-sliding>\n }\n </ion-list>\n } @else {\n <ion-list>\n <ion-item>\n <ion-spinner name=\"\" slot=\"start\" color=\"medium\" />\n <ion-buttons slot=\"start\">\n <ion-button disabled=\"disabled\" style=\"text-transform: none\"\n >{{ loadingState }}...\n </ion-button>\n </ion-buttons>\n <ion-skeleton-text animated />\n </ion-item>\n </ion-list>\n }\n\n @if (showAdd) {\n <ion-item [disabled]=\"adding\">\n <ion-input\n (keyup.enter)=\"addSpace()\"\n #addTeamInput\n [(ngModel)]=\"spaceName\"\n (keyup.escape)=\"showAdd = false\"\n placeholder=\"New team name\"\n />\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" fill=\"solid\" (click)=\"addSpace()\">\n <ion-label>Create</ion-label>\n </ion-button>\n @if (!!spaces?.length) {\n <ion-button (click)=\"showAdd = false\" color=\"medium\" title=\"Cancel\">\n @if (adding) {\n <ion-spinner />\n } @else {\n <ion-icon name=\"close-outline\" />\n }\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (showAdd) {\n <ion-card-content>\n <p>Enter team name and click \"Create\" button to add a new team.</p>\n </ion-card-content>\n }\n</ion-card>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItemSliding, selector: "ion-item-sliding", inputs: ["disabled"] }, { kind: "component", type: IonItemOptions, selector: "ion-item-options", inputs: ["side"] }, { kind: "component", type: IonItemOption, selector: "ion-item-option", inputs: ["color", "disabled", "download", "expandable", "href", "mode", "rel", "target", "type"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }] }); }
|
|
183
|
+
}
|
|
184
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpacesCardComponent, decorators: [{
|
|
185
|
+
type: Component,
|
|
186
|
+
args: [{ selector: 'sneat-spaces-card', imports: [
|
|
187
|
+
FormsModule,
|
|
188
|
+
IonInput,
|
|
189
|
+
IonCard,
|
|
190
|
+
IonItem,
|
|
191
|
+
IonLabel,
|
|
192
|
+
IonCardTitle,
|
|
193
|
+
IonButtons,
|
|
194
|
+
IonButton,
|
|
195
|
+
IonIcon,
|
|
196
|
+
IonList,
|
|
197
|
+
IonItemSliding,
|
|
198
|
+
IonItemOptions,
|
|
199
|
+
IonItemOption,
|
|
200
|
+
IonSpinner,
|
|
201
|
+
IonSkeletonText,
|
|
202
|
+
IonCardContent,
|
|
203
|
+
], template: "<ion-card>\n <ion-item>\n <ion-label>\n <ion-card-title color=\"medium\">Spaces</ion-card-title>\n </ion-label>\n <ion-buttons slot=\"end\" (click)=\"startAddingSpace()\">\n @if (!showAdd) {\n <ion-button color=\"primary\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n @if (spaces) {\n <ion-list>\n @for (space of spaces; track space.id) {\n <ion-item-sliding>\n <ion-item tappable detail (click)=\"goSpace(space)\">\n <ion-label>{{ space.brief.title }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"leaveSpace(space, $event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n <ion-item-options side=\"start\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n <ion-item-options side=\"end\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n </ion-item-sliding>\n }\n </ion-list>\n } @else {\n <ion-list>\n <ion-item>\n <ion-spinner name=\"\" slot=\"start\" color=\"medium\" />\n <ion-buttons slot=\"start\">\n <ion-button disabled=\"disabled\" style=\"text-transform: none\"\n >{{ loadingState }}...\n </ion-button>\n </ion-buttons>\n <ion-skeleton-text animated />\n </ion-item>\n </ion-list>\n }\n\n @if (showAdd) {\n <ion-item [disabled]=\"adding\">\n <ion-input\n (keyup.enter)=\"addSpace()\"\n #addTeamInput\n [(ngModel)]=\"spaceName\"\n (keyup.escape)=\"showAdd = false\"\n placeholder=\"New team name\"\n />\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" fill=\"solid\" (click)=\"addSpace()\">\n <ion-label>Create</ion-label>\n </ion-button>\n @if (!!spaces?.length) {\n <ion-button (click)=\"showAdd = false\" color=\"medium\" title=\"Cancel\">\n @if (adding) {\n <ion-spinner />\n } @else {\n <ion-icon name=\"close-outline\" />\n }\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (showAdd) {\n <ion-card-content>\n <p>Enter team name and click \"Create\" button to add a new team.</p>\n </ion-card-content>\n }\n</ion-card>\n" }]
|
|
204
|
+
}], propDecorators: { addSpaceInput: [{
|
|
205
|
+
type: ViewChild,
|
|
206
|
+
args: [IonInput, { static: false }]
|
|
207
|
+
}] } });
|
|
208
|
+
//# sourceMappingURL=spaces-card.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spaces-card.component.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/spaces-card/spaces-card.component.ts","../../../../../../../libs/space/components/src/lib/spaces-card/spaces-card.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n IonButton,\n IonButtons,\n IonCard,\n IonCardContent,\n IonCardTitle,\n IonIcon,\n IonInput,\n IonItem,\n IonItemOption,\n IonItemOptions,\n IonItemSliding,\n IonLabel,\n IonList,\n IonSkeletonText,\n IonSpinner,\n ToastController,\n} from '@ionic/angular/standalone';\nimport { AnalyticsService, IAnalyticsService } from '@sneat/core';\nimport { IUserSpaceBrief } from '@sneat/auth-models';\nimport { IIdAndBrief } from '@sneat/core';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { ICreateSpaceRequest, ISpaceContext } from '@sneat/space-models';\nimport { SpaceNavService, SpaceService } from '@sneat/space-services';\nimport { ISneatUserState, SneatUserService } from '@sneat/auth-core';\nimport { Subject, Subscription } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'sneat-spaces-card',\n templateUrl: './spaces-card.component.html',\n imports: [\n FormsModule,\n IonInput,\n IonCard,\n IonItem,\n IonLabel,\n IonCardTitle,\n IonButtons,\n IonButton,\n IonIcon,\n IonList,\n IonItemSliding,\n IonItemOptions,\n IonItemOption,\n IonSpinner,\n IonSkeletonText,\n IonCardContent,\n ],\n})\nexport class SpacesCardComponent implements OnInit, OnDestroy {\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n private readonly navService = inject(SpaceNavService);\n private readonly userService = inject(SneatUserService);\n private readonly spaceService = inject(SpaceService);\n private readonly analyticsService =\n inject<IAnalyticsService>(AnalyticsService);\n private readonly toastController = inject(ToastController);\n\n @ViewChild(IonInput, { static: false }) addSpaceInput?: IonInput; // TODO: IonInput;\n\n public spaces?: IIdAndBrief<IUserSpaceBrief>[];\n public loadingState: 'Authenticating' | 'Loading' = 'Authenticating';\n public spaceName = '';\n public adding = false;\n public showAdd = false; //\n private readonly destroyed = new Subject<void>();\n private subscriptions: Subscription[] = [];\n\n public ngOnDestroy(): void {\n // console.log('SpacesCardComponent.ngOnDestroy()');\n this.destroyed.next();\n this.destroyed.complete();\n this.unsubscribe('ngOnDestroy');\n }\n\n public ngOnInit(): void {\n this.watchUserRecord();\n }\n\n public goSpace(space: ISpaceContext) {\n this.navService\n .navigateToSpace(space, 'forward')\n .catch(this.errorLogger.logError);\n }\n\n public addSpace() {\n this.analyticsService.logEvent('addSpace');\n const title = this.spaceName.trim();\n if (!title) {\n this.toastController\n .create({\n position: 'middle',\n message: 'Space name is required',\n color: 'tertiary',\n duration: 5000,\n keyboardClose: true,\n buttons: [{ role: 'cancel', text: 'OK' }],\n })\n .then((toast) =>\n toast\n .present()\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to present toast'),\n ),\n )\n .catch((err) =>\n this.errorLogger.logError(err, 'Faile to create toast'),\n );\n return;\n }\n if (this.spaces?.find((t) => t.brief.title === title)) {\n this.toastController\n .create({\n message: 'You already have a team with the same name',\n color: 'danger',\n buttons: ['close'],\n position: 'middle',\n animated: true,\n duration: 3000,\n })\n .then((toast) => {\n toast\n .present()\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to present toast'),\n );\n })\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to create toast'),\n );\n return;\n }\n const request: ICreateSpaceRequest = {\n type: 'team',\n // memberType: TeamMemberType.creator,\n title,\n };\n this.adding = true;\n this.spaceService.createSpace(request).subscribe({\n next: (space) => {\n this.analyticsService.logEvent('spaceCreated', { space: space.id });\n const userTeamBrief2: IUserSpaceBrief = {\n userContactID: 'TODO: populate userContactID',\n title: space?.dbo?.title || space.id,\n roles: ['creator'],\n // memberType: request.memberType,\n type: space?.dbo?.type || 'unknown',\n };\n if (userTeamBrief2 && !this.spaces?.find((t) => t.id === space.id)) {\n this.spaces?.push({ id: space.id, brief: userTeamBrief2 });\n }\n this.adding = false;\n this.spaceName = '';\n this.goSpace(space);\n },\n error: (err) => {\n this.errorLogger.logError(err, 'Failed to create new team record');\n this.adding = false;\n },\n });\n }\n\n public startAddingSpace(): void {\n this.showAdd = true;\n setTimeout(() => {\n if (!this.addSpaceInput) {\n this.errorLogger.logError('addTeamInput is not set');\n return;\n }\n this.addSpaceInput\n .setFocus()\n .catch((err) =>\n this.errorLogger.logError(\n err,\n 'Failed to set focus to \"addTeamInput\"',\n ),\n );\n }, 200);\n }\n\n public leaveSpace(space: IIdAndBrief<IUserSpaceBrief>, event?: Event): void {\n if (event) {\n event.stopPropagation();\n event.preventDefault();\n }\n if (!confirm(`Are you sure you want to leave team ${space.brief.title}?`)) {\n return;\n }\n const userID = this.userService.currentUserID;\n if (!userID) {\n this.errorLogger.logError('Failed to get current user ID');\n return;\n }\n this.spaceService.leaveSpace({ spaceID: space.id }).subscribe({\n next: () => console.log('left space'),\n error: (err: unknown) =>\n this.errorLogger.logError(\n err,\n `Failed to leave a space: ${space.brief.title}`,\n ),\n });\n }\n\n private watchUserRecord(): void {\n this.userService.userState.pipe(takeUntil(this.destroyed)).subscribe({\n next: (userState) => {\n // console.log('SpacesCardComponent => user state changed:', userState);\n if (userState.status === 'authenticating') {\n if (this.loadingState === 'Authenticating') {\n this.loadingState = 'Loading';\n }\n }\n const uid = userState.user?.uid;\n this.spaces = undefined;\n if (!uid) {\n this.unsubscribe('user signed out');\n return;\n }\n this.subscriptions.push(\n this.userService.userState.subscribe({\n next: this.setUser,\n error: (err) =>\n this.errorLogger.logError(err, 'Failed to get user record'),\n }),\n );\n },\n error: (err) => this.errorLogger.logError(err, 'Failed to get user ID'),\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private unsubscribe(_reason?: string): void {\n // console.log(`SpacesCardComponent.unsubscribe(reason: ${reason})`);\n this.subscriptions.forEach((s) => s.unsubscribe());\n this.subscriptions = [];\n }\n\n private setUser = (userState: ISneatUserState): void => {\n // console.log('SpacesCardComponent => user:', userState);\n const user = userState.record;\n if (user) {\n this.spaces = Object.entries(user?.spaces ? user.spaces : {}).map(\n ([id, team]) => ({ id, brief: team }),\n );\n this.spaces.sort((a, b) => (a.brief.title > b.brief.title ? 1 : -1));\n this.showAdd = !this.spaces?.length;\n if (this.showAdd) {\n this.startAddingSpace();\n }\n } else {\n this.spaces = undefined;\n }\n };\n}\n","<ion-card>\n <ion-item>\n <ion-label>\n <ion-card-title color=\"medium\">Spaces</ion-card-title>\n </ion-label>\n <ion-buttons slot=\"end\" (click)=\"startAddingSpace()\">\n @if (!showAdd) {\n <ion-button color=\"primary\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n @if (spaces) {\n <ion-list>\n @for (space of spaces; track space.id) {\n <ion-item-sliding>\n <ion-item tappable detail (click)=\"goSpace(space)\">\n <ion-label>{{ space.brief.title }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"leaveSpace(space, $event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n <ion-item-options side=\"start\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n <ion-item-options side=\"end\">\n <ion-item-option color=\"danger\" (click)=\"leaveSpace(space)\"\n >Leave team\n </ion-item-option>\n </ion-item-options>\n </ion-item-sliding>\n }\n </ion-list>\n } @else {\n <ion-list>\n <ion-item>\n <ion-spinner name=\"\" slot=\"start\" color=\"medium\" />\n <ion-buttons slot=\"start\">\n <ion-button disabled=\"disabled\" style=\"text-transform: none\"\n >{{ loadingState }}...\n </ion-button>\n </ion-buttons>\n <ion-skeleton-text animated />\n </ion-item>\n </ion-list>\n }\n\n @if (showAdd) {\n <ion-item [disabled]=\"adding\">\n <ion-input\n (keyup.enter)=\"addSpace()\"\n #addTeamInput\n [(ngModel)]=\"spaceName\"\n (keyup.escape)=\"showAdd = false\"\n placeholder=\"New team name\"\n />\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" fill=\"solid\" (click)=\"addSpace()\">\n <ion-label>Create</ion-label>\n </ion-button>\n @if (!!spaces?.length) {\n <ion-button (click)=\"showAdd = false\" color=\"medium\" title=\"Cancel\">\n @if (adding) {\n <ion-spinner />\n } @else {\n <ion-icon name=\"close-outline\" />\n }\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (showAdd) {\n <ion-card-content>\n <p>Enter team name and click \"Create\" button to add a new team.</p>\n </ion-card-content>\n }\n</ion-card>\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/spaces-list/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './spaces-list.component';\n"]}
|