@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
package/esm2022/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/space/components/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC","sourcesContent":["export * from './lib';\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
2
|
+
import { IonImg } from '@ionic/angular/standalone';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class AvatarComponent {
|
|
5
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.0", type: AvatarComponent, isStandalone: true, selector: "sneat-avatar", inputs: { avatar: "avatar" }, ngImport: i0, template: "<ion-img\n title=\"avatar\"\n [src]=\"\n avatar?.external ? '' : '//www.gravatar.com/avatar/' + avatar?.gravatar\n \"\n/>\n", dependencies: [{ kind: "component", type: IonImg, selector: "ion-img", inputs: ["alt", "src"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7
|
+
}
|
|
8
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
9
|
+
type: Component,
|
|
10
|
+
args: [{ selector: 'sneat-avatar', imports: [IonImg], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-img\n title=\"avatar\"\n [src]=\"\n avatar?.external ? '' : '//www.gravatar.com/avatar/' + avatar?.gravatar\n \"\n/>\n" }]
|
|
11
|
+
}], propDecorators: { avatar: [{
|
|
12
|
+
type: Input,
|
|
13
|
+
args: [{ required: true }]
|
|
14
|
+
}] } });
|
|
15
|
+
//# sourceMappingURL=avatar.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.component.js","sourceRoot":"","sources":["../../../../../../../libs/space/components/src/lib/avatar/avatar.component.ts","../../../../../../../libs/space/components/src/lib/avatar/avatar.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;;AASnD,MAAM,OAAO,eAAe;8GAAf,eAAe;kGAAf,eAAe,sGCV5B,mIAMA,4CDCY,MAAM;;2FAGL,eAAe;kBAN3B,SAAS;+BACE,cAAc,WAEf,CAAC,MAAM,CAAC,mBACA,uBAAuB,CAAC,MAAM;;sBAG9C,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE","sourcesContent":["import { ChangeDetectionStrategy, Component, Input } from '@angular/core';\nimport { IonImg } from '@ionic/angular/standalone';\nimport { IAvatar } from '@sneat/auth-models';\n\n@Component({\n selector: 'sneat-avatar',\n templateUrl: './avatar.component.html',\n imports: [IonImg],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AvatarComponent {\n @Input({ required: true }) avatar?: IAvatar;\n}\n","<ion-img\n title=\"avatar\"\n [src]=\"\n avatar?.external ? '' : '//www.gravatar.com/avatar/' + avatar?.gravatar\n \"\n/>\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './avatar/avatar.component';
|
|
2
|
+
export * from './space-menu';
|
|
3
|
+
export * from './spaces-menu';
|
|
4
|
+
export * from './space-page-title/space-page-title.component';
|
|
5
|
+
export * from './space-page-base-component.service';
|
|
6
|
+
export * from './space-component-base-params.service';
|
|
7
|
+
export * from './space-item-page-base.component';
|
|
8
|
+
export * from './space-items-base.component';
|
|
9
|
+
export * from './spaces-list';
|
|
10
|
+
export * from './spaces-card';
|
|
11
|
+
export * from './space-module-base.component';
|
|
12
|
+
export * from './space-base-component.directive';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,+CAA+C,CAAC;AAC9D,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC","sourcesContent":["export * from './avatar/avatar.component';\nexport * from './space-menu';\nexport * from './spaces-menu';\nexport * from './space-page-title/space-page-title.component';\nexport * from './space-page-base-component.service';\nexport * from './space-component-base-params.service';\nexport * from './space-item-page-base.component';\nexport * from './space-items-base.component';\nexport * from './spaces-list';\nexport * from './spaces-card';\nexport * from './space-module-base.component';\nexport * from './space-base-component.directive';\n"]}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { computed, Directive, effect, inject, signal, } from '@angular/core';
|
|
2
|
+
import { ActivatedRoute } from '@angular/router';
|
|
3
|
+
import { NavController } from '@ionic/angular/standalone';
|
|
4
|
+
import { equalSpaceRefs } from '@sneat/core';
|
|
5
|
+
import { equalSpaceBriefs } from '@sneat/dto';
|
|
6
|
+
import { SpaceService, trackSpaceIdAndTypeFromRouteParameter, } from '@sneat/space-services';
|
|
7
|
+
import { SneatBaseComponent } from '@sneat/ui';
|
|
8
|
+
import { distinctUntilChanged, map, shareReplay, Subject, } from 'rxjs';
|
|
9
|
+
import { takeUntil } from 'rxjs/operators';
|
|
10
|
+
import { SpaceComponentBaseParams } from './space-component-base-params.service';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
export class SpaceBaseComponent extends SneatBaseComponent {
|
|
13
|
+
takeUntilSpaceIdChanged() {
|
|
14
|
+
return takeUntil(this.spaceIDChanged$);
|
|
15
|
+
}
|
|
16
|
+
get space() {
|
|
17
|
+
// TODO: Document why we do not allow undefined
|
|
18
|
+
return this.$space() || { id: '' };
|
|
19
|
+
}
|
|
20
|
+
get preloader() {
|
|
21
|
+
return this.spaceParams.preloader;
|
|
22
|
+
}
|
|
23
|
+
get spaceNav() {
|
|
24
|
+
return this.spaceParams.spaceNavService;
|
|
25
|
+
}
|
|
26
|
+
get currentUserId() {
|
|
27
|
+
return this.userService.currentUserID;
|
|
28
|
+
}
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
this.$spaceRef = signal(undefined, ...(ngDevMode ? [{ debugName: "$spaceRef" }] : []));
|
|
32
|
+
this.$spaceBrief = signal(undefined, ...(ngDevMode ? [{ debugName: "$spaceBrief" }] : []));
|
|
33
|
+
this.$spaceDbo = signal(undefined, ...(ngDevMode ? [{ debugName: "$spaceDbo" }] : []));
|
|
34
|
+
// private readonly $_spaceID = signal<string | undefined>(undefined);
|
|
35
|
+
// protected readonly $spaceID = this.$_spaceID.asReadonly();
|
|
36
|
+
this.$spaceID = computed(() => this.$spaceRef()?.id, ...(ngDevMode ? [{ debugName: "$spaceID" }] : []));
|
|
37
|
+
// private readonly $_spaceType = signal<SpaceType | undefined>(undefined);
|
|
38
|
+
// protected readonly $spaceType = this.$_spaceType.asReadonly();
|
|
39
|
+
this.$spaceType = computed(() => this.$spaceRef()?.type, ...(ngDevMode ? [{ debugName: "$spaceType" }] : []));
|
|
40
|
+
this.$space = computed(() => {
|
|
41
|
+
return {
|
|
42
|
+
...(this.$spaceRef() || { id: '' }),
|
|
43
|
+
brief: this.$spaceBrief(),
|
|
44
|
+
dbo: this.$spaceDbo(),
|
|
45
|
+
};
|
|
46
|
+
}, ...(ngDevMode ? [{ debugName: "$space" }] : []));
|
|
47
|
+
this.spaceIDChanged = new Subject();
|
|
48
|
+
this.spaceTypeChanged = new Subject();
|
|
49
|
+
this.noPermissions = false;
|
|
50
|
+
this.spaceBriefChanged = new Subject();
|
|
51
|
+
this.spaceDboChanged = new Subject();
|
|
52
|
+
// protected spaceContext?: ISpaceContext;
|
|
53
|
+
this.spaceChanged = new Subject();
|
|
54
|
+
this.spaceChanged$ = this.spaceChanged
|
|
55
|
+
.asObservable()
|
|
56
|
+
.pipe(this.takeUntilDestroyed());
|
|
57
|
+
this.navController = inject(NavController);
|
|
58
|
+
// protected readonly communeService: ICommuneService;
|
|
59
|
+
this.spaceService = inject(SpaceService);
|
|
60
|
+
this.spaceIDChanged$ = this.spaceIDChanged.asObservable().pipe(this.takeUntilDestroyed(), distinctUntilChanged());
|
|
61
|
+
this.spaceTypeChanged$ = this.spaceTypeChanged.pipe(this.takeUntilDestroyed(), distinctUntilChanged(),
|
|
62
|
+
// tap(v => console.log('spaceTypeChanged$ before replay =>', v)),
|
|
63
|
+
shareReplay(1));
|
|
64
|
+
this.spaceBriefChanged$ = this.spaceBriefChanged
|
|
65
|
+
.asObservable()
|
|
66
|
+
.pipe(this.takeUntilDestroyed(), distinctUntilChanged(equalSpaceBriefs));
|
|
67
|
+
this.spaceDboChanged$ = this.spaceDboChanged
|
|
68
|
+
.asObservable()
|
|
69
|
+
.pipe(this.takeUntilDestroyed(), distinctUntilChanged());
|
|
70
|
+
this.$defaultBackUrlSpacePath = signal('', ...(ngDevMode ? [{ debugName: "$defaultBackUrlSpacePath" }] : []));
|
|
71
|
+
// Intentionally not readonly, but might reconsider
|
|
72
|
+
this.$defaultBackUrl = computed(() => {
|
|
73
|
+
const space = this.$space();
|
|
74
|
+
const path = this.$defaultBackUrlSpacePath();
|
|
75
|
+
let url = space ? `/space/${space.type}/${space.id}` : '';
|
|
76
|
+
url = url && this.defaultBackPage ? url + '/' + this.defaultBackPage : url;
|
|
77
|
+
if (path) {
|
|
78
|
+
url = url + '/' + path;
|
|
79
|
+
}
|
|
80
|
+
return url;
|
|
81
|
+
}, ...(ngDevMode ? [{ debugName: "$defaultBackUrl" }] : []));
|
|
82
|
+
this.route = inject(ActivatedRoute);
|
|
83
|
+
this.spaceParams = inject(SpaceComponentBaseParams);
|
|
84
|
+
this.onSpaceIdChangedInUrl = (space) => {
|
|
85
|
+
const prevSpace = this.$space();
|
|
86
|
+
this.log(`${this.className}:SpaceBaseComponent.onSpaceIdChangedInUrl(): prevSpace.id: ${prevSpace?.id} => ${space?.id}`);
|
|
87
|
+
if (space === prevSpace ||
|
|
88
|
+
(space?.id === prevSpace?.id && space?.type === prevSpace?.type)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (space && prevSpace?.id === space?.id) {
|
|
92
|
+
space = { ...prevSpace, ...space };
|
|
93
|
+
}
|
|
94
|
+
this.setSpaceContext(space);
|
|
95
|
+
};
|
|
96
|
+
this.onSpaceContextChanged = (space) => {
|
|
97
|
+
const isDboChanged = space.dbo !== this.$space()?.dbo;
|
|
98
|
+
// this.log(
|
|
99
|
+
// `${this.className}:SpaceBaseComponent.onSpaceContextChanged() => dtoChanged=${dtoChanged}, space:`,
|
|
100
|
+
// space,
|
|
101
|
+
// );
|
|
102
|
+
if (!space.brief && space.dbo) {
|
|
103
|
+
space = { ...space, brief: space.dbo };
|
|
104
|
+
}
|
|
105
|
+
if (!space.type) {
|
|
106
|
+
if (space.brief?.type) {
|
|
107
|
+
space = { ...space, type: space.brief.type };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.setSpaceContext(space);
|
|
111
|
+
if (isDboChanged) {
|
|
112
|
+
this.onSpaceDboChanged();
|
|
113
|
+
}
|
|
114
|
+
// this.log(`${this.className} => loaded team record:`, newTeam);
|
|
115
|
+
// if (newSpace.id === this.spaceContext?.id) {
|
|
116
|
+
// this.setNewSpaceContext({ ...this.spaceContext, ...newSpace });
|
|
117
|
+
// // this.spaceContext = ;
|
|
118
|
+
// } else { // Whe should never end up here as should unsubscribe on leaving page or ID change
|
|
119
|
+
// this.errorLogger.logError(`got team record after space context changed: received id=${newSpace.id}, current id=${this.spaceContext?.id}`);
|
|
120
|
+
// }
|
|
121
|
+
};
|
|
122
|
+
let prevSpaceID;
|
|
123
|
+
effect(() => {
|
|
124
|
+
const spaceID = this.$spaceID();
|
|
125
|
+
if (spaceID === prevSpaceID) {
|
|
126
|
+
// This seems to be a bag or a strange feature in Angular signals?
|
|
127
|
+
// this happens if we call this.spaceIDChanged.next(spaceID);
|
|
128
|
+
// Giving up for now so not logging as a warning
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
prevSpaceID = spaceID;
|
|
132
|
+
this.spaceIDChanged.next(spaceID); // This should be BEFORE onSpaceIdChanged()!
|
|
133
|
+
this.onSpaceIdChanged(); // This should be AFTER spaceIDChanged.next()!
|
|
134
|
+
this.unsubscribe('$spaceID() changed');
|
|
135
|
+
this.$spaceBrief.set(undefined);
|
|
136
|
+
this.$spaceDbo.set(undefined);
|
|
137
|
+
if (spaceID) {
|
|
138
|
+
setTimeout(() => this.subscribeForSpaceChanges(spaceID), 1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// this.spaceIDChanged$
|
|
142
|
+
// .pipe(this.takeUntilDestroyed(), distinctUntilChanged())
|
|
143
|
+
// .subscribe((spaceID) => {
|
|
144
|
+
// if (spaceID) {
|
|
145
|
+
// // !!! Be careful to migrate this to signal effect - can cause dead cycles!
|
|
146
|
+
// setTimeout(() => this.subscribeForSpaceChanges(spaceID), 1);
|
|
147
|
+
// }
|
|
148
|
+
// });
|
|
149
|
+
effect(() => {
|
|
150
|
+
this.spaceTypeChanged.next(this.$spaceType());
|
|
151
|
+
});
|
|
152
|
+
try {
|
|
153
|
+
// this.navController = spaceParams.navController;
|
|
154
|
+
this.userService = this.spaceParams.userService;
|
|
155
|
+
this.logger = this.spaceParams.loggerFactory.getLogger(this.className);
|
|
156
|
+
this.getSpaceContextFromRouteState();
|
|
157
|
+
this.cleanupOnUserLogout();
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
this.errorLogger.logError(e, `Failed in ${this.className}:SpaceBaseComponent.constructor()`);
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
ngOnInit() {
|
|
165
|
+
// We can't call this in constructor as some members of the child class may not be initialized yet
|
|
166
|
+
this.trackRouteParamMap(this.route.paramMap.pipe(this.takeUntilDestroyed()));
|
|
167
|
+
}
|
|
168
|
+
// public ionViewWillLeave(): void {
|
|
169
|
+
// // console.log(`${this.className}:SpaceBaseComponent.ionViewWillLeave()`);
|
|
170
|
+
// this.willLeave.next();
|
|
171
|
+
// }
|
|
172
|
+
onUserIdChanged() {
|
|
173
|
+
if (!this.currentUserId) {
|
|
174
|
+
this.subs.unsubscribe();
|
|
175
|
+
if (this.space && this.space.dbo) {
|
|
176
|
+
this.setSpaceContext({
|
|
177
|
+
...this.space,
|
|
178
|
+
brief: undefined,
|
|
179
|
+
dbo: undefined,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
navigateForwardToSpacePage(page, navOptions) {
|
|
185
|
+
if (!this.space) {
|
|
186
|
+
return Promise.reject('no space context');
|
|
187
|
+
}
|
|
188
|
+
return this.spaceParams.spaceNavService.navigateForwardToSpacePage(this.space, page, navOptions);
|
|
189
|
+
}
|
|
190
|
+
// TODO: Consider removing this method as it is fragile.
|
|
191
|
+
// It is easy go get it wrong and server similar purpose as spaceIDChanged$.
|
|
192
|
+
onSpaceIdChanged() {
|
|
193
|
+
// this.log(
|
|
194
|
+
// `${this.className}:SpaceBaseComponent.onSpaceIdChanged() spaceID=${this.space?.id}`,
|
|
195
|
+
// );
|
|
196
|
+
}
|
|
197
|
+
onSpaceDboChanged() {
|
|
198
|
+
// this.log(
|
|
199
|
+
// `${this.className}:SpaceBaseComponent.onSpaceDboChanged(): ` +
|
|
200
|
+
// JSON.stringify(this.space.dbo),
|
|
201
|
+
// );
|
|
202
|
+
}
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
|
204
|
+
onRouteParamsChanged(params) { }
|
|
205
|
+
trackRouteParamMap(paramMap$) {
|
|
206
|
+
this.trackSpaceIdFromRouteParams(paramMap$);
|
|
207
|
+
paramMap$.subscribe({
|
|
208
|
+
next: (paramMap) => this.onRouteParamsChanged(paramMap),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
trackSpaceIdFromRouteParams(paramMap$) {
|
|
212
|
+
trackSpaceIdAndTypeFromRouteParameter(paramMap$)
|
|
213
|
+
// .pipe(
|
|
214
|
+
// tap((v) => this.log('trackSpaceIdFromRouteParams 1', v)),
|
|
215
|
+
// distinctUntilChanged(
|
|
216
|
+
// (previous, current) => previous?.id === current?.id,
|
|
217
|
+
// ),
|
|
218
|
+
// tap((v) => this.log('trackSpaceIdFromRouteParams 3', v)),
|
|
219
|
+
// )
|
|
220
|
+
.subscribe({
|
|
221
|
+
next: this.onSpaceIdChangedInUrl,
|
|
222
|
+
error: this.logErrorHandler,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
subscribeForSpaceChanges(spaceID) {
|
|
226
|
+
this.spaceService
|
|
227
|
+
.watchSpace(spaceID)
|
|
228
|
+
.pipe(this.takeUntilDestroyed(), takeUntil(this.spaceIDChanged$), map((space) => {
|
|
229
|
+
return { ...space, type: space.dbo?.type };
|
|
230
|
+
}))
|
|
231
|
+
.subscribe({
|
|
232
|
+
next: this.onSpaceContextChanged,
|
|
233
|
+
error: (err) => {
|
|
234
|
+
if (err.code === 'permission-denied') {
|
|
235
|
+
this.log('subscribeForSpaceChanges() => permission denied to read space record');
|
|
236
|
+
this.noPermissions = true;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
this.errorLogger.logError('failed to get team record');
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
getSpaceContextFromRouteState() {
|
|
244
|
+
const space = history.state?.team;
|
|
245
|
+
this.log(`${this.className}:SpaceBaseComponent.getSpaceContextFromRouteState()`, space);
|
|
246
|
+
if (!space?.id) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// TODO: document why not to set team context immediately
|
|
250
|
+
setTimeout(() => this.setSpaceContext(space), 1);
|
|
251
|
+
}
|
|
252
|
+
cleanupOnUserLogout() {
|
|
253
|
+
try {
|
|
254
|
+
this.userService.userChanged.pipe(this.takeUntilDestroyed()).subscribe({
|
|
255
|
+
next: (uid) => {
|
|
256
|
+
if (!uid) {
|
|
257
|
+
this.unsubscribe('user signed out');
|
|
258
|
+
this.setSpaceContext(undefined);
|
|
259
|
+
}
|
|
260
|
+
this.onUserIdChanged();
|
|
261
|
+
},
|
|
262
|
+
error: (e) => this.logError(e, 'Failed to get user record'),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
this.logError(e, 'Failed to subscribe a hook on page cleanup on user logout');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// private updateExistingSpaceContext(spaceContext: ISpaceContext): void {
|
|
270
|
+
// const dtoChanged = this.spaceContext?.dto != spaceContext.dto;
|
|
271
|
+
// this.spaceContext = spaceContext;
|
|
272
|
+
// if (dtoChanged) {
|
|
273
|
+
// this.onSpaceDtoChanged();
|
|
274
|
+
// }
|
|
275
|
+
// }
|
|
276
|
+
setSpaceRef(spaceRef) {
|
|
277
|
+
let idChanged = false;
|
|
278
|
+
let typeChanged = false;
|
|
279
|
+
this.$spaceRef.update((prev) => {
|
|
280
|
+
if (prev === spaceRef) {
|
|
281
|
+
return prev;
|
|
282
|
+
}
|
|
283
|
+
idChanged = prev?.id !== spaceRef?.id;
|
|
284
|
+
typeChanged = prev?.type !== spaceRef?.type;
|
|
285
|
+
if (!idChanged && !typeChanged) {
|
|
286
|
+
return prev;
|
|
287
|
+
}
|
|
288
|
+
if (!spaceRef) {
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
if (equalSpaceRefs(spaceRef, prev)) {
|
|
292
|
+
return prev;
|
|
293
|
+
}
|
|
294
|
+
const keys = Object.keys(spaceRef || {});
|
|
295
|
+
return (keys.length === 1 && keys[0] === 'id') ||
|
|
296
|
+
(keys.length === 2 && keys.includes('id') && keys.includes('type'))
|
|
297
|
+
? spaceRef
|
|
298
|
+
: spaceRef.type || (prev?.type && prev.id !== spaceRef.id)
|
|
299
|
+
? { id: spaceRef.id, type: spaceRef.type || prev?.type }
|
|
300
|
+
: { id: spaceRef.id };
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
setSpaceContext(spaceContext) {
|
|
304
|
+
const prevSpace = this.$space();
|
|
305
|
+
this.log(`${this.className}:SpaceBaseComponent.setSpaceContext(id=${spaceContext?.id}), previous id=${prevSpace.id}`, spaceContext);
|
|
306
|
+
if (!equalSpaceRefs(spaceContext, this.$spaceRef())) {
|
|
307
|
+
this.setSpaceRef(spaceContext);
|
|
308
|
+
}
|
|
309
|
+
if (prevSpace == spaceContext) {
|
|
310
|
+
this.console.warn('Duplicate call to SpaceBaseComponent.setSpaceContext() with same spaceContext:', spaceContext);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const idChanged = prevSpace?.id != spaceContext?.id;
|
|
314
|
+
const briefChanged = !equalSpaceBriefs(prevSpace?.brief, spaceContext?.brief);
|
|
315
|
+
const dboChanged = prevSpace?.dbo != spaceContext?.dbo;
|
|
316
|
+
this.log(`${this.className}:SpaceBaseComponent.setSpaceContext(id=${spaceContext?.id}) => idChanged=${idChanged}, briefChanged=${briefChanged}, dtoChanged=${dboChanged}`);
|
|
317
|
+
if (briefChanged) {
|
|
318
|
+
this.$spaceBrief.set(spaceContext?.brief);
|
|
319
|
+
this.spaceBriefChanged.next(spaceContext?.brief);
|
|
320
|
+
}
|
|
321
|
+
if (dboChanged) {
|
|
322
|
+
this.$spaceDbo.set(spaceContext?.dbo);
|
|
323
|
+
this.spaceDboChanged.next(spaceContext?.dbo);
|
|
324
|
+
}
|
|
325
|
+
if (spaceContext) {
|
|
326
|
+
this.spaceChanged.next(spaceContext);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
saveNotes(event) {
|
|
330
|
+
event.preventDefault();
|
|
331
|
+
event.stopPropagation();
|
|
332
|
+
// alert('Saving noes is not implemented yet');
|
|
333
|
+
}
|
|
334
|
+
spacePageUrl(page) {
|
|
335
|
+
return spacePageUrl(this.$space(), page) || '';
|
|
336
|
+
}
|
|
337
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
338
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: SpaceBaseComponent, isStandalone: true, usesInheritance: true, ngImport: i0 }); }
|
|
339
|
+
}
|
|
340
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceBaseComponent, decorators: [{
|
|
341
|
+
type: Directive
|
|
342
|
+
}], ctorParameters: () => [] });
|
|
343
|
+
export const spacePageUrl = (team, page) => {
|
|
344
|
+
return team?.id
|
|
345
|
+
? page
|
|
346
|
+
? `/space/${team.type}/${team.id}/${page}`
|
|
347
|
+
: `/space/${team.type}/${team.id}`
|
|
348
|
+
: undefined;
|
|
349
|
+
};
|
|
350
|
+
//# sourceMappingURL=space-base-component.directive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-base-component.directive.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-base-component.directive.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computed,\n Directive,\n effect,\n inject,\n OnInit,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, ParamMap } from '@angular/router';\nimport { NavController } from '@ionic/angular/standalone';\nimport { equalSpaceRefs, ILogger, ISpaceRef, SpaceType } from '@sneat/core';\n\ntype NavigationOptions = NonNullable<\n Parameters<NavController['navigateRoot']>[1]\n>;\nimport { equalSpaceBriefs, ISpaceBrief, ISpaceDbo } from '@sneat/dto';\nimport { ISpaceContext } from '@sneat/space-models';\nimport {\n SpaceService,\n trackSpaceIdAndTypeFromRouteParameter,\n} from '@sneat/space-services';\nimport { SneatUserService } from '@sneat/auth-core';\nimport { SneatBaseComponent } from '@sneat/ui';\nimport {\n distinctUntilChanged,\n map,\n MonoTypeOperatorFunction,\n Observable,\n shareReplay,\n Subject,\n} from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SpaceComponentBaseParams } from './space-component-base-params.service';\n\n@Directive() // The @Directive is required by Angular as we are implementing OnInit\nexport abstract class SpaceBaseComponent\n extends SneatBaseComponent\n implements OnInit\n{\n protected readonly $spaceRef = signal<ISpaceRef | undefined | null>(\n undefined,\n );\n private readonly $spaceBrief = signal<ISpaceBrief | undefined | null>(\n undefined,\n );\n private readonly $spaceDbo = signal<ISpaceDbo | undefined | null>(undefined);\n\n // private readonly $_spaceID = signal<string | undefined>(undefined);\n // protected readonly $spaceID = this.$_spaceID.asReadonly();\n protected readonly $spaceID = computed(() => this.$spaceRef()?.id);\n\n // private readonly $_spaceType = signal<SpaceType | undefined>(undefined);\n // protected readonly $spaceType = this.$_spaceType.asReadonly();\n protected readonly $spaceType = computed(() => this.$spaceRef()?.type);\n\n protected readonly $space = computed<ISpaceContext>(() => {\n return {\n ...(this.$spaceRef() || { id: '' }),\n brief: this.$spaceBrief(),\n dbo: this.$spaceDbo(),\n };\n });\n\n private readonly spaceIDChanged = new Subject<string | undefined>();\n private readonly spaceTypeChanged = new Subject<SpaceType | undefined>();\n\n protected takeUntilSpaceIdChanged<T>(): MonoTypeOperatorFunction<T> {\n return takeUntil(this.spaceIDChanged$);\n }\n\n protected noPermissions = false;\n\n protected readonly spaceBriefChanged = new Subject<\n ISpaceBrief | undefined | null\n >();\n protected readonly spaceDboChanged = new Subject<\n ISpaceDbo | undefined | null\n >();\n\n // protected spaceContext?: ISpaceContext;\n\n private readonly spaceChanged = new Subject<ISpaceContext>();\n protected readonly spaceChanged$ = this.spaceChanged\n .asObservable()\n .pipe(this.takeUntilDestroyed());\n\n protected readonly navController = inject(NavController);\n // protected readonly activeCommuneService: IActiveCommuneService;\n protected readonly userService: SneatUserService;\n // protected readonly communeService: ICommuneService;\n protected readonly spaceService = inject(SpaceService);\n // protected readonly authStateService: IAuthStateService;\n protected readonly logger: ILogger;\n // protected readonly willLeave = new Subject<void>();\n protected defaultBackPage?: string;\n\n protected readonly spaceIDChanged$ = this.spaceIDChanged.asObservable().pipe(\n this.takeUntilDestroyed(),\n distinctUntilChanged(),\n // tap((id) => console.log(this.className + '=> spaceIDChanged$: ' + id)),\n );\n\n protected readonly spaceTypeChanged$: Observable<SpaceType | undefined> =\n this.spaceTypeChanged.pipe(\n this.takeUntilDestroyed(),\n distinctUntilChanged(),\n // tap(v => console.log('spaceTypeChanged$ before replay =>', v)),\n shareReplay(1),\n // tap(v => console.log('spaceTypeChanged$ after replay =>', v)),\n );\n\n protected readonly spaceBriefChanged$ = this.spaceBriefChanged\n .asObservable()\n .pipe(this.takeUntilDestroyed(), distinctUntilChanged(equalSpaceBriefs));\n\n public readonly spaceDboChanged$ = this.spaceDboChanged\n .asObservable()\n .pipe(this.takeUntilDestroyed(), distinctUntilChanged());\n\n protected get space(): ISpaceContext {\n // TODO: Document why we do not allow undefined\n return this.$space() || ({ id: '' } as ISpaceContext);\n }\n\n protected get preloader() {\n return this.spaceParams.preloader;\n }\n\n protected get spaceNav() {\n return this.spaceParams.spaceNavService;\n }\n\n protected get currentUserId() {\n return this.userService.currentUserID;\n }\n\n protected readonly $defaultBackUrlSpacePath = signal('');\n\n // Intentionally not readonly, but might reconsider\n protected $defaultBackUrl = computed<string>(() => {\n const space = this.$space();\n const path = this.$defaultBackUrlSpacePath();\n let url = space ? `/space/${space.type}/${space.id}` : '';\n url = url && this.defaultBackPage ? url + '/' + this.defaultBackPage : url;\n if (path) {\n url = url + '/' + path;\n }\n return url;\n });\n\n protected readonly route = inject(ActivatedRoute);\n protected readonly spaceParams = inject(SpaceComponentBaseParams);\n\n public constructor() {\n super();\n\n let prevSpaceID: string | undefined;\n\n effect(() => {\n const spaceID = this.$spaceID();\n\n if (spaceID === prevSpaceID) {\n // This seems to be a bag or a strange feature in Angular signals?\n // this happens if we call this.spaceIDChanged.next(spaceID);\n // Giving up for now so not logging as a warning\n return;\n }\n prevSpaceID = spaceID;\n this.spaceIDChanged.next(spaceID); // This should be BEFORE onSpaceIdChanged()!\n this.onSpaceIdChanged(); // This should be AFTER spaceIDChanged.next()!\n this.unsubscribe('$spaceID() changed');\n this.$spaceBrief.set(undefined);\n this.$spaceDbo.set(undefined);\n if (spaceID) {\n setTimeout(() => this.subscribeForSpaceChanges(spaceID), 1);\n }\n });\n\n // this.spaceIDChanged$\n // \t.pipe(this.takeUntilDestroyed(), distinctUntilChanged())\n // \t.subscribe((spaceID) => {\n // \t\tif (spaceID) {\n // \t\t\t// !!! Be careful to migrate this to signal effect - can cause dead cycles!\n // \t\t\tsetTimeout(() => this.subscribeForSpaceChanges(spaceID), 1);\n // \t\t}\n // \t});\n\n effect(() => {\n this.spaceTypeChanged.next(this.$spaceType());\n });\n\n try {\n // this.navController = spaceParams.navController;\n this.userService = this.spaceParams.userService;\n this.logger = this.spaceParams.loggerFactory.getLogger(this.className);\n this.getSpaceContextFromRouteState();\n this.cleanupOnUserLogout();\n } catch (e) {\n this.errorLogger.logError(\n e,\n `Failed in ${this.className}:SpaceBaseComponent.constructor()`,\n );\n throw e;\n }\n }\n\n public ngOnInit(): void {\n // We can't call this in constructor as some members of the child class may not be initialized yet\n this.trackRouteParamMap(\n this.route.paramMap.pipe(this.takeUntilDestroyed()),\n );\n }\n\n // public ionViewWillLeave(): void {\n // \t// console.log(`${this.className}:SpaceBaseComponent.ionViewWillLeave()`);\n // \tthis.willLeave.next();\n // }\n\n protected onUserIdChanged(): void {\n if (!this.currentUserId) {\n this.subs.unsubscribe();\n if (this.space && this.space.dbo) {\n this.setSpaceContext({\n ...this.space,\n brief: undefined,\n dbo: undefined,\n });\n }\n }\n }\n\n protected navigateForwardToSpacePage(\n page: string,\n navOptions?: NavigationOptions,\n ) {\n if (!this.space) {\n return Promise.reject('no space context');\n }\n return this.spaceParams.spaceNavService.navigateForwardToSpacePage(\n this.space,\n page,\n navOptions,\n );\n }\n\n // TODO: Consider removing this method as it is fragile.\n // It is easy go get it wrong and server similar purpose as spaceIDChanged$.\n protected onSpaceIdChanged(): void {\n // this.log(\n // \t`${this.className}:SpaceBaseComponent.onSpaceIdChanged() spaceID=${this.space?.id}`,\n // );\n }\n\n protected onSpaceDboChanged(): void {\n // this.log(\n // \t`${this.className}:SpaceBaseComponent.onSpaceDboChanged(): ` +\n // \t\tJSON.stringify(this.space.dbo),\n // );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function\n protected onRouteParamsChanged(params: ParamMap): void {}\n\n protected trackRouteParamMap(paramMap$: Observable<ParamMap>): void {\n this.trackSpaceIdFromRouteParams(paramMap$);\n paramMap$.subscribe({\n next: (paramMap) => this.onRouteParamsChanged(paramMap),\n });\n }\n\n private trackSpaceIdFromRouteParams(paramMap$: Observable<ParamMap>): void {\n trackSpaceIdAndTypeFromRouteParameter(paramMap$)\n // .pipe(\n // \ttap((v) => this.log('trackSpaceIdFromRouteParams 1', v)),\n // \tdistinctUntilChanged(\n // \t\t(previous, current) => previous?.id === current?.id,\n // \t),\n // \ttap((v) => this.log('trackSpaceIdFromRouteParams 3', v)),\n // )\n .subscribe({\n next: this.onSpaceIdChangedInUrl,\n error: this.logErrorHandler,\n });\n }\n\n private readonly onSpaceIdChangedInUrl = (space?: ISpaceContext): void => {\n const prevSpace = this.$space();\n this.log(\n `${this.className}:SpaceBaseComponent.onSpaceIdChangedInUrl(): prevSpace.id: ${prevSpace?.id} => ${space?.id}`,\n );\n if (\n space === prevSpace ||\n (space?.id === prevSpace?.id && space?.type === prevSpace?.type)\n ) {\n return;\n }\n if (space && prevSpace?.id === space?.id) {\n space = { ...prevSpace, ...space };\n }\n this.setSpaceContext(space);\n };\n\n private subscribeForSpaceChanges(spaceID: string): void {\n this.spaceService\n .watchSpace(spaceID)\n .pipe(\n this.takeUntilDestroyed(),\n takeUntil(this.spaceIDChanged$),\n map((space) => {\n return { ...space, type: space.dbo?.type };\n }),\n )\n .subscribe({\n next: this.onSpaceContextChanged,\n error: (err) => {\n if (err.code === 'permission-denied') {\n this.log(\n 'subscribeForSpaceChanges() => permission denied to read space record',\n );\n this.noPermissions = true;\n return;\n }\n this.errorLogger.logError('failed to get team record');\n },\n });\n }\n\n private getSpaceContextFromRouteState(): void {\n const space = history.state?.team as ISpaceContext;\n this.log(\n `${this.className}:SpaceBaseComponent.getSpaceContextFromRouteState()`,\n space,\n );\n if (!space?.id) {\n return;\n }\n // TODO: document why not to set team context immediately\n setTimeout(() => this.setSpaceContext(space), 1);\n }\n\n private cleanupOnUserLogout(): void {\n try {\n this.userService.userChanged.pipe(this.takeUntilDestroyed()).subscribe({\n next: (uid) => {\n if (!uid) {\n this.unsubscribe('user signed out');\n this.setSpaceContext(undefined);\n }\n this.onUserIdChanged();\n },\n error: (e) => this.logError(e, 'Failed to get user record'),\n });\n } catch (e) {\n this.logError(\n e,\n 'Failed to subscribe a hook on page cleanup on user logout',\n );\n }\n }\n\n // private updateExistingSpaceContext(spaceContext: ISpaceContext): void {\n // \tconst dtoChanged = this.spaceContext?.dto != spaceContext.dto;\n // \tthis.spaceContext = spaceContext;\n // \tif (dtoChanged) {\n // \t\tthis.onSpaceDtoChanged();\n // \t}\n // }\n\n protected setSpaceRef(spaceRef?: ISpaceRef): void {\n let idChanged = false;\n let typeChanged = false;\n this.$spaceRef.update((prev) => {\n if (prev === spaceRef) {\n return prev;\n }\n idChanged = prev?.id !== spaceRef?.id;\n typeChanged = prev?.type !== spaceRef?.type;\n if (!idChanged && !typeChanged) {\n return prev;\n }\n if (!spaceRef) {\n return undefined;\n }\n if (equalSpaceRefs(spaceRef, prev)) {\n return prev;\n }\n const keys = Object.keys(spaceRef || {});\n return (keys.length === 1 && keys[0] === 'id') ||\n (keys.length === 2 && keys.includes('id') && keys.includes('type'))\n ? spaceRef\n : spaceRef.type || (prev?.type && prev.id !== spaceRef.id)\n ? { id: spaceRef.id, type: spaceRef.type || prev?.type }\n : { id: spaceRef.id };\n });\n }\n\n private setSpaceContext(spaceContext?: ISpaceContext): void {\n const prevSpace = this.$space();\n this.log(\n `${this.className}:SpaceBaseComponent.setSpaceContext(id=${spaceContext?.id}), previous id=${prevSpace.id}`,\n spaceContext,\n );\n if (!equalSpaceRefs(spaceContext, this.$spaceRef())) {\n this.setSpaceRef(spaceContext);\n }\n if (prevSpace == spaceContext) {\n this.console.warn(\n 'Duplicate call to SpaceBaseComponent.setSpaceContext() with same spaceContext:',\n spaceContext,\n );\n return;\n }\n const idChanged = prevSpace?.id != spaceContext?.id;\n const briefChanged = !equalSpaceBriefs(\n prevSpace?.brief,\n spaceContext?.brief,\n );\n const dboChanged = prevSpace?.dbo != spaceContext?.dbo;\n this.log(\n `${this.className}:SpaceBaseComponent.setSpaceContext(id=${spaceContext?.id}) => idChanged=${idChanged}, briefChanged=${briefChanged}, dtoChanged=${dboChanged}`,\n );\n if (briefChanged) {\n this.$spaceBrief.set(spaceContext?.brief);\n this.spaceBriefChanged.next(spaceContext?.brief);\n }\n if (dboChanged) {\n this.$spaceDbo.set(spaceContext?.dbo);\n this.spaceDboChanged.next(spaceContext?.dbo);\n }\n if (spaceContext) {\n this.spaceChanged.next(spaceContext);\n }\n }\n\n private readonly onSpaceContextChanged = (space: ISpaceContext): void => {\n const isDboChanged = space.dbo !== this.$space()?.dbo;\n // this.log(\n // \t`${this.className}:SpaceBaseComponent.onSpaceContextChanged() => dtoChanged=${dtoChanged}, space:`,\n // \tspace,\n // );\n if (!space.brief && space.dbo) {\n space = { ...space, brief: space.dbo };\n }\n if (!space.type) {\n if (space.brief?.type) {\n space = { ...space, type: space.brief.type };\n }\n }\n this.setSpaceContext(space);\n if (isDboChanged) {\n this.onSpaceDboChanged();\n }\n // this.log(`${this.className} => loaded team record:`, newTeam);\n // if (newSpace.id === this.spaceContext?.id) {\n // \tthis.setNewSpaceContext({ ...this.spaceContext, ...newSpace });\n // \t// this.spaceContext = ;\n // } else { // Whe should never end up here as should unsubscribe on leaving page or ID change\n // \tthis.errorLogger.logError(`got team record after space context changed: received id=${newSpace.id}, current id=${this.spaceContext?.id}`);\n // }\n };\n\n protected saveNotes(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n // alert('Saving noes is not implemented yet');\n }\n\n protected spacePageUrl(page: string): string {\n return spacePageUrl(this.$space(), page) || '';\n }\n}\n\nexport const spacePageUrl = (\n team?: ISpaceContext,\n page?: string,\n): string | undefined => {\n return team?.id\n ? page\n ? `/space/${team.type}/${team.id}/${page}`\n : `/space/${team.type}/${team.id}`\n : undefined;\n};\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { APP_INFO, LOGGER_FACTORY, NgModulePreloaderService, } from '@sneat/core';
|
|
3
|
+
import { ErrorLogger } from '@sneat/core';
|
|
4
|
+
import { SpaceNavService } from '@sneat/space-services';
|
|
5
|
+
import { SneatUserService } from '@sneat/auth-core';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
export class SpaceComponentBaseParams {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.errorLogger = inject(ErrorLogger);
|
|
10
|
+
this.loggerFactory = inject(LOGGER_FACTORY);
|
|
11
|
+
this.appService = inject(APP_INFO);
|
|
12
|
+
this.userService = inject(SneatUserService);
|
|
13
|
+
this.spaceNavService = inject(SpaceNavService);
|
|
14
|
+
this.preloader = inject(NgModulePreloaderService);
|
|
15
|
+
}
|
|
16
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceComponentBaseParams, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
17
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceComponentBaseParams }); }
|
|
18
|
+
}
|
|
19
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceComponentBaseParams, decorators: [{
|
|
20
|
+
type: Injectable
|
|
21
|
+
}] });
|
|
22
|
+
//# sourceMappingURL=space-component-base-params.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-component-base-params.service.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-component-base-params.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACL,QAAQ,EAGR,cAAc,EACd,wBAAwB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;;AAGpD,MAAM,OAAO,wBAAwB;IADrC;QAEW,gBAAW,GAAG,MAAM,CAAe,WAAW,CAAC,CAAC;QAChD,kBAAa,GAAG,MAAM,CAAiB,cAAc,CAAC,CAAC;QAC7C,eAAU,GAAG,MAAM,CAAW,QAAQ,CAAC,CAAC;QAClD,gBAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACvC,oBAAe,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;QAC1C,cAAS,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC;KACvD;8GAPY,wBAAwB;kHAAxB,wBAAwB;;2FAAxB,wBAAwB;kBADpC,UAAU","sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport {\n APP_INFO,\n IAppInfo,\n ILoggerFactory,\n LOGGER_FACTORY,\n NgModulePreloaderService,\n} from '@sneat/core';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { SpaceNavService } from '@sneat/space-services';\nimport { SneatUserService } from '@sneat/auth-core';\n\n@Injectable()\nexport class SpaceComponentBaseParams {\n readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n readonly loggerFactory = inject<ILoggerFactory>(LOGGER_FACTORY);\n protected readonly appService = inject<IAppInfo>(APP_INFO);\n readonly userService = inject(SneatUserService);\n readonly spaceNavService = inject(SpaceNavService);\n readonly preloader = inject(NgModulePreloaderService);\n}\n"]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { computed, signal } from '@angular/core';
|
|
2
|
+
import { distinctUntilChanged, filter, map, Subject, tap, throwError, } from 'rxjs';
|
|
3
|
+
import { takeUntil } from 'rxjs/operators';
|
|
4
|
+
import { SpacePageBaseComponent } from './space-page-base-component.service';
|
|
5
|
+
// type watchByIdFunc<Brief, Dto> = (params: ParamMap, itemId: string, teamId?: string) => Observable<INavContext<Brief, Dto>>;
|
|
6
|
+
export class SpaceItemPageBaseComponent extends SpacePageBaseComponent {
|
|
7
|
+
constructor(defaultBackPage, itemName, spaceItemService) {
|
|
8
|
+
super();
|
|
9
|
+
this.itemName = itemName;
|
|
10
|
+
this.spaceItemService = spaceItemService;
|
|
11
|
+
// protected item?: INavContext<Brief, Dbo>;
|
|
12
|
+
this.$item = signal({
|
|
13
|
+
id: '',
|
|
14
|
+
space: { id: '' },
|
|
15
|
+
}, ...(ngDevMode ? [{ debugName: "$item" }] : []));
|
|
16
|
+
this.$itemID = computed(() => this.$item()?.id, ...(ngDevMode ? [{ debugName: "$itemID" }] : []));
|
|
17
|
+
this.defaultBackPage = defaultBackPage;
|
|
18
|
+
const item = window.history.state?.[itemName];
|
|
19
|
+
if (item) {
|
|
20
|
+
this.setItemContext(item);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
setItemContext(item) {
|
|
24
|
+
const prevItem = this.$item();
|
|
25
|
+
if (item && prevItem?.id === item?.id && item !== prevItem) {
|
|
26
|
+
item = {
|
|
27
|
+
id: item.id,
|
|
28
|
+
space: this.$space() || { id: '' },
|
|
29
|
+
brief: item.brief || item.dbo || prevItem.brief,
|
|
30
|
+
dbo: item.dbo || prevItem.dbo,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
this.$item.set(item || { id: '', space: { id: '' } });
|
|
34
|
+
}
|
|
35
|
+
// Caller of this method will track changing of team & item IDs in route and close observable
|
|
36
|
+
watchItemChanges() {
|
|
37
|
+
const itemID = this.$itemID();
|
|
38
|
+
if (!itemID) {
|
|
39
|
+
throw throwError(() => 'no item ID');
|
|
40
|
+
}
|
|
41
|
+
const space = this.$space();
|
|
42
|
+
return this.spaceItemService.watchSpaceItemByIdWithSpaceRef(space, itemID);
|
|
43
|
+
}
|
|
44
|
+
trackRouteParamMap(paramMap$) {
|
|
45
|
+
super.trackRouteParamMap(paramMap$);
|
|
46
|
+
this.trackRouteParamItemID(paramMap$);
|
|
47
|
+
}
|
|
48
|
+
trackRouteParamItemID(paramMap$) {
|
|
49
|
+
if (!this.itemName) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Direct call like that does not work as are unsubscribing from observable once item ID changed
|
|
53
|
+
// this.trackItem(this.getItemID$(paramMap$).pipe(distinctUntilChanged()));
|
|
54
|
+
const itemID$ = new Subject();
|
|
55
|
+
itemID$
|
|
56
|
+
.asObservable()
|
|
57
|
+
.pipe(tap((itemID) => console.log(`itemID$ changed to "${itemID}"`)), this.takeUntilDestroyed())
|
|
58
|
+
.subscribe({
|
|
59
|
+
next: (itemID) => this.onItemIDChanged(itemID, itemID$),
|
|
60
|
+
error: (err) => this.logError(err, 'failed to get paramMap'),
|
|
61
|
+
});
|
|
62
|
+
this.getItemID$(paramMap$)
|
|
63
|
+
.pipe(
|
|
64
|
+
// tap((itemID) => console.log('itemID$ pre-distinct:', itemID)),
|
|
65
|
+
distinctUntilChanged())
|
|
66
|
+
.subscribe(itemID$);
|
|
67
|
+
}
|
|
68
|
+
getItemID$(paramMap$) {
|
|
69
|
+
return paramMap$.pipe(map((params) => params.get(this.itemName + 'ID') || ''));
|
|
70
|
+
}
|
|
71
|
+
onItemIDChanged(itemID, itemID$) {
|
|
72
|
+
if (!itemID) {
|
|
73
|
+
this.setItemContext(undefined);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const item = this.$item();
|
|
77
|
+
if (item?.id !== itemID || !this.itemSubscription) {
|
|
78
|
+
const space = this.$space();
|
|
79
|
+
this.setItemContext({ ...item, id: itemID, space });
|
|
80
|
+
this.setBriefFromSpace(itemID);
|
|
81
|
+
this.itemSubscription?.unsubscribe();
|
|
82
|
+
this.itemSubscription = this.watchItemChanges()
|
|
83
|
+
.pipe(this.takeUntilDestroyed(), takeUntil(this.spaceIDChanged$.pipe(
|
|
84
|
+
// TODO: the below filter is a workaround for a bug in our implementation
|
|
85
|
+
filter((spaceID) => spaceID !== space.id),
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
87
|
+
tap((_spaceID) => {
|
|
88
|
+
// Space ID changed
|
|
89
|
+
}))), takeUntil(itemID$.pipe(
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
91
|
+
tap((_itemID) => {
|
|
92
|
+
// Item ID changed
|
|
93
|
+
}))))
|
|
94
|
+
.subscribe({
|
|
95
|
+
next: (item) => {
|
|
96
|
+
const currentSpaceRef = this.$spaceRef();
|
|
97
|
+
if (currentSpaceRef?.id == space.id) {
|
|
98
|
+
this.setItemContext({
|
|
99
|
+
...item,
|
|
100
|
+
space: currentSpaceRef.type ? currentSpaceRef : space,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
error: (err) => this.logError(err, 'failed to get item by ID'),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
setBriefFromSpace(id) {
|
|
109
|
+
const item = this.$item();
|
|
110
|
+
if (item && !item.brief) {
|
|
111
|
+
const briefs = this.briefs();
|
|
112
|
+
if (briefs) {
|
|
113
|
+
const brief = briefs[id];
|
|
114
|
+
if (brief) {
|
|
115
|
+
this.setItemContext({ ...item, brief });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=space-item-page-base.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-item-page-base.component.js","sourceRoot":"","sources":["../../../../../../libs/space/components/src/lib/space-item-page-base.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { computed, signal } from '@angular/core';\nimport { ParamMap } from '@angular/router';\nimport { INavContext, SpaceItem } from '@sneat/core';\nimport { ISpaceItemNavContext } from '@sneat/space-models';\nimport { ModuleSpaceItemService } from '@sneat/space-services';\nimport {\n distinctUntilChanged,\n filter,\n map,\n Observable,\n Subject,\n Subscription,\n tap,\n throwError,\n} from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SpacePageBaseComponent } from './space-page-base-component.service';\n\n// type watchByIdFunc<Brief, Dto> = (params: ParamMap, itemId: string, teamId?: string) => Observable<INavContext<Brief, Dto>>;\n\nexport abstract class SpaceItemPageBaseComponent<\n Brief,\n Dbo extends Brief,\n> extends SpacePageBaseComponent {\n // protected item?: INavContext<Brief, Dbo>;\n protected readonly $item = signal<ISpaceItemNavContext<Brief, Dbo>>({\n id: '',\n space: { id: '' },\n });\n\n protected readonly $itemID = computed(() => this.$item()?.id);\n\n protected constructor(\n defaultBackPage: string,\n private readonly itemName: SpaceItem,\n protected readonly spaceItemService: ModuleSpaceItemService<Brief, Dbo>,\n ) {\n super();\n this.defaultBackPage = defaultBackPage;\n const item = window.history.state?.[itemName] as ISpaceItemNavContext<\n Brief,\n Dbo\n >;\n if (item) {\n this.setItemContext(item);\n }\n }\n\n protected setItemContext(item?: ISpaceItemNavContext<Brief, Dbo>): void {\n const prevItem = this.$item();\n if (item && prevItem?.id === item?.id && item !== prevItem) {\n item = {\n id: item.id,\n space: this.$space() || { id: '' },\n brief: item.brief || item.dbo || prevItem.brief,\n dbo: item.dbo || prevItem.dbo,\n };\n }\n this.$item.set(item || { id: '', space: { id: '' } });\n }\n\n protected abstract briefs(): Readonly<Record<string, Brief>> | undefined;\n\n private itemSubscription?: Subscription;\n\n // Caller of this method will track changing of team & item IDs in route and close observable\n protected watchItemChanges(): Observable<INavContext<Brief, Dbo>> {\n const itemID = this.$itemID();\n if (!itemID) {\n throw throwError(() => 'no item ID');\n }\n const space = this.$space();\n return this.spaceItemService.watchSpaceItemByIdWithSpaceRef(space, itemID);\n }\n\n protected override trackRouteParamMap(paramMap$: Observable<ParamMap>): void {\n super.trackRouteParamMap(paramMap$);\n this.trackRouteParamItemID(paramMap$);\n }\n\n protected trackRouteParamItemID(paramMap$: Observable<ParamMap>): void {\n if (!this.itemName) {\n return;\n }\n // Direct call like that does not work as are unsubscribing from observable once item ID changed\n // this.trackItem(this.getItemID$(paramMap$).pipe(distinctUntilChanged()));\n const itemID$ = new Subject<string>();\n itemID$\n .asObservable()\n .pipe(\n tap((itemID) => console.log(`itemID$ changed to \"${itemID}\"`)),\n this.takeUntilDestroyed(),\n )\n .subscribe({\n next: (itemID) => this.onItemIDChanged(itemID, itemID$),\n error: (err) => this.logError(err, 'failed to get paramMap'),\n });\n this.getItemID$(paramMap$)\n .pipe(\n // tap((itemID) => console.log('itemID$ pre-distinct:', itemID)),\n distinctUntilChanged(),\n // tap((itemID) => console.log('itemID$ post-distinct:', itemID)),\n )\n .subscribe(itemID$);\n }\n\n protected getItemID$(paramMap$: Observable<ParamMap>): Observable<string> {\n return paramMap$.pipe(\n map((params) => params.get(this.itemName + 'ID') || ''),\n );\n }\n\n private onItemIDChanged(itemID: string, itemID$: Observable<string>): void {\n if (!itemID) {\n this.setItemContext(undefined);\n return;\n }\n const item = this.$item();\n\n if (item?.id !== itemID || !this.itemSubscription) {\n const space = this.$space();\n this.setItemContext({ ...item, id: itemID, space });\n this.setBriefFromSpace(itemID);\n this.itemSubscription?.unsubscribe();\n this.itemSubscription = this.watchItemChanges()\n .pipe(\n this.takeUntilDestroyed(),\n takeUntil(\n this.spaceIDChanged$.pipe(\n // TODO: the below filter is a workaround for a bug in our implementation\n filter((spaceID) => spaceID !== space.id),\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n tap((_spaceID) => {\n // Space ID changed\n }),\n ),\n ),\n takeUntil(\n itemID$.pipe(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n tap((_itemID) => {\n // Item ID changed\n }),\n ),\n ),\n )\n .subscribe({\n next: (item) => {\n const currentSpaceRef = this.$spaceRef();\n if (currentSpaceRef?.id == space.id) {\n this.setItemContext({\n ...item,\n space: currentSpaceRef.type ? currentSpaceRef : space,\n });\n }\n },\n error: (err) => this.logError(err, 'failed to get item by ID'),\n });\n }\n }\n\n private setBriefFromSpace(id: string): void {\n const item = this.$item();\n if (item && !item.brief) {\n const briefs = this.briefs();\n if (briefs) {\n const brief = briefs[id];\n if (brief) {\n this.setItemContext({ ...item, brief });\n }\n }\n }\n }\n}\n"]}
|