@sneat/space-services 0.1.2 → 0.1.4

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.
Files changed (51) hide show
  1. package/esm2022/index.js +8 -0
  2. package/esm2022/index.js.map +1 -0
  3. package/esm2022/lib/components/with-space-input.directive.js +37 -0
  4. package/esm2022/lib/components/with-space-input.directive.js.map +1 -0
  5. package/esm2022/lib/services/space-context.service.js +26 -0
  6. package/esm2022/lib/services/space-context.service.js.map +1 -0
  7. package/esm2022/lib/services/space-item.service.js +132 -0
  8. package/esm2022/lib/services/space-item.service.js.map +1 -0
  9. package/esm2022/lib/services/space-module.service.js +35 -0
  10. package/esm2022/lib/services/space-module.service.js.map +1 -0
  11. package/esm2022/lib/services/space-nav.service.js +97 -0
  12. package/esm2022/lib/services/space-nav.service.js.map +1 -0
  13. package/esm2022/lib/services/space-service.module.js +15 -0
  14. package/esm2022/lib/services/space-service.module.js.map +1 -0
  15. package/esm2022/lib/services/space.service.js +209 -0
  16. package/esm2022/lib/services/space.service.js.map +1 -0
  17. package/esm2022/sneat-space-services.js +5 -0
  18. package/esm2022/sneat-space-services.js.map +1 -0
  19. package/{src/index.ts → index.d.ts} +0 -1
  20. package/lib/components/with-space-input.directive.d.ts +20 -0
  21. package/lib/services/space-context.service.d.ts +9 -0
  22. package/lib/services/space-item.service.d.ts +43 -0
  23. package/lib/services/space-module.service.d.ts +10 -0
  24. package/lib/services/space-nav.service.d.ts +32 -0
  25. package/lib/services/space-service.module.d.ts +6 -0
  26. package/lib/services/space.service.d.ts +33 -0
  27. package/package.json +14 -2
  28. package/sneat-space-services.d.ts +5 -0
  29. package/eslint.config.js +0 -7
  30. package/ng-package.json +0 -7
  31. package/project.json +0 -38
  32. package/src/lib/components/with-space-input.directive.spec.ts +0 -41
  33. package/src/lib/components/with-space-input.directive.ts +0 -40
  34. package/src/lib/services/space-context.service.spec.ts +0 -16
  35. package/src/lib/services/space-context.service.ts +0 -45
  36. package/src/lib/services/space-item.service.spec.ts +0 -179
  37. package/src/lib/services/space-item.service.ts +0 -308
  38. package/src/lib/services/space-module.service.spec.ts +0 -48
  39. package/src/lib/services/space-module.service.ts +0 -69
  40. package/src/lib/services/space-nav-service.service.spec.ts +0 -32
  41. package/src/lib/services/space-nav.service.ts +0 -175
  42. package/src/lib/services/space-service.module.spec.ts +0 -46
  43. package/src/lib/services/space-service.module.ts +0 -7
  44. package/src/lib/services/space.service.spec.ts +0 -44
  45. package/src/lib/services/space.service.ts +0 -291
  46. package/src/test-setup.ts +0 -3
  47. package/tsconfig.json +0 -13
  48. package/tsconfig.lib.json +0 -19
  49. package/tsconfig.lib.prod.json +0 -7
  50. package/tsconfig.spec.json +0 -31
  51. package/vite.config.mts +0 -10
@@ -0,0 +1,8 @@
1
+ export * from './lib/services/space-service.module';
2
+ export * from './lib/services/space-nav.service';
3
+ export * from './lib/services/space.service';
4
+ export * from './lib/services/space-item.service';
5
+ export * from './lib/services/space-context.service';
6
+ export * from './lib/services/space-module.service';
7
+ export * from './lib/components/with-space-input.directive';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/space/services/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AAEpD,cAAc,6CAA6C,CAAC","sourcesContent":["export * from './lib/services/space-service.module';\nexport * from './lib/services/space-nav.service';\nexport * from './lib/services/space.service';\nexport * from './lib/services/space-item.service';\nexport * from './lib/services/space-context.service';\nexport * from './lib/services/space-module.service';\n\nexport * from './lib/components/with-space-input.directive';\n"]}
@@ -0,0 +1,37 @@
1
+ import { computed, Directive, effect, inject, input } from '@angular/core';
2
+ import { SneatBaseComponent } from '@sneat/ui';
3
+ import { BehaviorSubject, distinctUntilChanged } from 'rxjs';
4
+ import { SpaceNavService } from '../services/space-nav.service';
5
+ import * as i0 from "@angular/core";
6
+ export class WithSpaceInput extends SneatBaseComponent {
7
+ constructor() {
8
+ super();
9
+ this.spaceNavService = inject(SpaceNavService);
10
+ this.$space = input.required(...(ngDevMode ? [{ debugName: "$space" }] : []));
11
+ this.$spaceID = computed(() => this.$space().id, ...(ngDevMode ? [{ debugName: "$spaceID" }] : []));
12
+ this.spaceIDChanged = new BehaviorSubject(undefined);
13
+ this.spaceID$ = this.spaceIDChanged
14
+ .asObservable()
15
+ .pipe(this.takeUntilDestroyed(), distinctUntilChanged());
16
+ this.$spaceType = computed(() => this.$space().type, ...(ngDevMode ? [{ debugName: "$spaceType" }] : []));
17
+ this.$spaceRef = computed(() => ({
18
+ id: this.$spaceID(),
19
+ type: this.$spaceType(),
20
+ }), ...(ngDevMode ? [{ debugName: "$spaceRef" }] : []));
21
+ effect(() => {
22
+ const spaceID = this.$spaceID();
23
+ if (spaceID !== this.spaceIDChanged.value) {
24
+ this.onSpaceIdChanged(spaceID);
25
+ }
26
+ });
27
+ }
28
+ onSpaceIdChanged(spaceID) {
29
+ this.spaceIDChanged.next(spaceID);
30
+ }
31
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: WithSpaceInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
32
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: WithSpaceInput, isStandalone: true, inputs: { $space: { classPropertyName: "$space", publicName: "$space", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); }
33
+ }
34
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: WithSpaceInput, decorators: [{
35
+ type: Directive
36
+ }], ctorParameters: () => [], propDecorators: { $space: [{ type: i0.Input, args: [{ isSignal: true, alias: "$space", required: true }] }] } });
37
+ //# sourceMappingURL=with-space-input.directive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-space-input.directive.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/components/with-space-input.directive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;;AAGhE,MAAM,OAAgB,cAAe,SAAQ,kBAAkB;IAmB7D;QACE,KAAK,EAAE,CAAC;QAnBS,oBAAe,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;QAE7C,WAAM,GAAG,KAAK,CAAC,QAAQ,iDAAiB,CAAC;QAEtC,aAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,oDAAC,CAAC;QAC9C,mBAAc,GAAG,IAAI,eAAe,CACnD,SAAS,CACV,CAAC;QACQ,aAAQ,GAAG,IAAI,CAAC,cAAc;aACrC,YAAY,EAAE;aACd,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAExC,eAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,sDAAC,CAAC;QAChD,cAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;YAC7C,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE;YACnB,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE;SACxB,CAAC,qDAAC,CAAC;QAIF,MAAM,CAAC,GAAG,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,OAAO,KAAK,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;gBAC1C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAES,gBAAgB,CAAC,OAAe;QACxC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;8GA/BmB,cAAc;kGAAd,cAAc;;2FAAd,cAAc;kBADnC,SAAS","sourcesContent":["import { computed, Directive, effect, inject, input } from '@angular/core';\nimport { ISpaceContext } from '@sneat/space-models';\nimport { SneatBaseComponent } from '@sneat/ui';\nimport { BehaviorSubject, distinctUntilChanged } from 'rxjs';\nimport { SpaceNavService } from '../services/space-nav.service';\n\n@Directive()\nexport abstract class WithSpaceInput extends SneatBaseComponent {\n protected readonly spaceNavService = inject(SpaceNavService);\n\n public readonly $space = input.required<ISpaceContext>();\n\n protected readonly $spaceID = computed(() => this.$space().id);\n private readonly spaceIDChanged = new BehaviorSubject<string | undefined>(\n undefined,\n );\n protected spaceID$ = this.spaceIDChanged\n .asObservable()\n .pipe(this.takeUntilDestroyed(), distinctUntilChanged());\n\n protected readonly $spaceType = computed(() => this.$space().type);\n protected readonly $spaceRef = computed(() => ({\n id: this.$spaceID(),\n type: this.$spaceType(),\n }));\n\n constructor() {\n super();\n effect(() => {\n const spaceID = this.$spaceID();\n if (spaceID !== this.spaceIDChanged.value) {\n this.onSpaceIdChanged(spaceID);\n }\n });\n }\n\n protected onSpaceIdChanged(spaceID: string): void {\n this.spaceIDChanged.next(spaceID);\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { distinctUntilChanged } from 'rxjs';
3
+ import { map } from 'rxjs/operators';
4
+ import * as i0 from "@angular/core";
5
+ export class SpaceContextService {
6
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceContextService, providedIn: 'root' }); }
8
+ }
9
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceContextService, decorators: [{
10
+ type: Injectable,
11
+ args: [{
12
+ providedIn: 'root',
13
+ }]
14
+ }] });
15
+ export function trackSpaceIdAndTypeFromRouteParameter(paramMap$) {
16
+ return paramMap$.pipe(map((params) => {
17
+ const id = params.get('spaceID'), type = params.get('spaceType');
18
+ // console.log('trackSpaceIdAndTypeFromRouteParameter', params, id, type);
19
+ const spaceContext = id
20
+ ? { id: id, type: type || undefined }
21
+ : undefined;
22
+ // console.log('trackSpaceIdAndTypeFromRouteParameter() => spaceContext:', spaceContext)
23
+ return spaceContext;
24
+ }), distinctUntilChanged((previous, current) => previous?.id === current?.id && previous?.type == current?.type));
25
+ }
26
+ //# sourceMappingURL=space-context.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-context.service.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/services/space-context.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,oBAAoB,EAAc,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;;AAOrC,MAAM,OAAO,mBAAmB;8GAAnB,mBAAmB;kHAAnB,mBAAmB,cAFlB,MAAM;;2FAEP,mBAAmB;kBAH/B,UAAU;mBAAC;oBACV,UAAU,EAAE,MAAM;iBACnB;;AAgBD,MAAM,UAAU,qCAAqC,CACnD,SAA+B;IAE/B,OAAO,SAAS,CAAC,IAAI,CACnB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACb,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAC9B,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAc,CAAC;QAC9C,0EAA0E;QAC1E,MAAM,YAAY,GAA8B,EAAE;YAChD,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,SAAS,EAAE;YACrC,CAAC,CAAC,SAAS,CAAC;QACd,wFAAwF;QACxF,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC,EACF,oBAAoB,CAClB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CACpB,QAAQ,EAAE,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI,QAAQ,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,CAClE,CACF,CAAC;AACJ,CAAC","sourcesContent":["import { Injectable } from '@angular/core';\nimport { ParamMap } from '@angular/router';\nimport { distinctUntilChanged, Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { ISpaceContext } from '@sneat/space-models';\nimport { SpaceType } from '@sneat/core';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SpaceContextService {\n // public trackUrl(\n // \troute: ActivatedRoute,\n // \tparamName: string,\n // ): Observable<ISpaceContext | undefined> {\n // \treturn route.paramMap.pipe(\n // \t\tmap(params => {\n // \t\t\tconst id = params.get('spaceID') || undefined;\n // \t\t\tconst spaceContext: ISpaceContext | undefined = id ? { id } : undefined;\n // \t\t\treturn spaceContext;\n // \t\t}),\n // \t);\n // }\n}\n\nexport function trackSpaceIdAndTypeFromRouteParameter(\n paramMap$: Observable<ParamMap>,\n): Observable<ISpaceContext | undefined> {\n return paramMap$.pipe(\n map((params) => {\n const id = params.get('spaceID'),\n type = params.get('spaceType') as SpaceType;\n // console.log('trackSpaceIdAndTypeFromRouteParameter', params, id, type);\n const spaceContext: ISpaceContext | undefined = id\n ? { id: id, type: type || undefined }\n : undefined;\n // console.log('trackSpaceIdAndTypeFromRouteParameter() => spaceContext:', spaceContext)\n return spaceContext;\n }),\n distinctUntilChanged(\n (previous, current) =>\n previous?.id === current?.id && previous?.type == current?.type,\n ),\n );\n}\n"]}
@@ -0,0 +1,132 @@
1
+ import { runInInjectionContext } from '@angular/core';
2
+ import { doc, collection, } from '@angular/fire/firestore';
3
+ import { SneatFirestoreService } from '@sneat/api';
4
+ import { map } from 'rxjs/operators';
5
+ class SpaceItemBaseService {
6
+ constructor(injector, collectionName, afs, sneatApiService) {
7
+ this.injector = injector;
8
+ this.collectionName = collectionName;
9
+ this.afs = afs;
10
+ this.sneatApiService = sneatApiService;
11
+ if (!this.collectionName) {
12
+ throw new Error('collectionName is required');
13
+ }
14
+ this.sfs = new SneatFirestoreService(this.injector);
15
+ }
16
+ watchSpaceItemByIdWithSpaceRef(space, itemID) {
17
+ if (!space.id) {
18
+ throw new Error('spaceID is required');
19
+ }
20
+ let collectionRef;
21
+ if (this._collectionRef?.id == space.id) {
22
+ collectionRef = this._collectionRef;
23
+ }
24
+ else {
25
+ collectionRef = this.collectionRef(space.id);
26
+ this._collectionRef = collectionRef;
27
+ }
28
+ return runInInjectionContext(this.injector, () => this.sfs
29
+ .watchByID(collectionRef, itemID)
30
+ .pipe(map((o) => ({ space, ...o }))));
31
+ }
32
+ queryItems(collectionRef, queryArgs) {
33
+ const $querySnapshot = this.sfs.watchSnapshotsByFilter(collectionRef, queryArgs);
34
+ return $querySnapshot.pipe(map((querySnapshot) => {
35
+ return this.mapQueryItem(querySnapshot);
36
+ }));
37
+ }
38
+ mapQueryItem(querySnapshot) {
39
+ return querySnapshot.docs.map((docSnapshot) => {
40
+ const dto = docSnapshot.data();
41
+ const { id } = docSnapshot;
42
+ const brief = dto;
43
+ return { id, brief, dbo: dto };
44
+ });
45
+ }
46
+ deleteSpaceItem(endpoint, request) {
47
+ return this.sneatApiService.delete(endpoint, undefined, request);
48
+ }
49
+ createSpaceItem(endpoint, spaceRef, request) {
50
+ return this.sneatApiService
51
+ .post(endpoint, request)
52
+ .pipe(map((response) => {
53
+ if (!response) {
54
+ throw new Error('create team item response is empty');
55
+ }
56
+ if (!response.id) {
57
+ throw new Error('create team item response have no ID');
58
+ }
59
+ const item = {
60
+ space: spaceRef,
61
+ id: response.id,
62
+ dbo: response.dbo,
63
+ brief: { id: response.id, ...response.dbo },
64
+ };
65
+ return item;
66
+ }));
67
+ }
68
+ }
69
+ // At the moment reserved to `happenings` only
70
+ export class GlobalSpaceItemService extends SpaceItemBaseService {
71
+ collectionRef() {
72
+ return runInInjectionContext(this.injector, () => collection(this.afs, this.collectionName));
73
+ }
74
+ watchGlobalItems(queryArgs) {
75
+ const collectionRef = this.collectionRef();
76
+ return this.queryItems(collectionRef, queryArgs);
77
+ }
78
+ watchGlobalSpaceItemsWithSpaceRef(space, queryArgs) {
79
+ return this.watchGlobalSpaceItems(space.id, queryArgs).pipe(map((items) => items.map((item) => ({ ...item, space }))));
80
+ }
81
+ watchGlobalSpaceItems(spaceID, queryArgs) {
82
+ queryArgs = {
83
+ ...queryArgs,
84
+ filter: [
85
+ ...(queryArgs?.filter || []),
86
+ { field: 'spaceIDs', operator: '==', value: spaceID },
87
+ ],
88
+ };
89
+ const collectionRef = this.collectionRef();
90
+ return this.queryItems(collectionRef, queryArgs);
91
+ }
92
+ }
93
+ // intentionally not abstract
94
+ export class ModuleSpaceItemService extends SpaceItemBaseService {
95
+ constructor(injector, moduleID, collectionName, afs, sneatApiService) {
96
+ super(injector, collectionName, afs, sneatApiService);
97
+ this.moduleID = moduleID;
98
+ this.dto2brief = (id, dto) => ({ id, ...dto });
99
+ this.spaceRef = (id) => doc(this.spacesCollection, id);
100
+ if (!moduleID) {
101
+ throw new Error('moduleID is required');
102
+ }
103
+ this.spacesCollection = collection(this.afs, 'spaces');
104
+ }
105
+ // protected teamCollection(spaceID: string): AngularFirestoreCollection<ITeamDto> {
106
+ // return this.afs.collection('spaces');
107
+ // }
108
+ collectionRef(spaceID) {
109
+ if (!spaceID) {
110
+ throw new Error('spaceID is required');
111
+ }
112
+ return runInInjectionContext(this.injector, () => collection(this.spacesCollection, spaceID, 'ext', this.moduleID, this.collectionName));
113
+ }
114
+ watchModuleSpaceItem(space, itemID) {
115
+ const collection = this.collectionRef(space.id);
116
+ return this.sfs.watchByID(collection, itemID);
117
+ }
118
+ watchModuleSpaceItemsWithSpaceRef(space, queryArgs) {
119
+ return this.watchModuleSpaceItems(space.id, queryArgs).pipe(map((items) => items.map((item) => ({ ...item, space }))));
120
+ }
121
+ watchModuleSpaceItems(spaceID, queryArgs) {
122
+ // filter = [
123
+ // ...(filter || []),
124
+ // // { field: 'spaceIDs', operator: '==', value: spaceID },
125
+ // ];
126
+ return runInInjectionContext(this.injector, () => {
127
+ const collectionRef = this.collectionRef(spaceID);
128
+ return this.queryItems(collectionRef, queryArgs);
129
+ });
130
+ }
131
+ }
132
+ //# sourceMappingURL=space-item.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-item.service.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/services/space-item.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injector, runInInjectionContext } from '@angular/core';\nimport {\n Firestore as AngularFirestore,\n doc,\n collection,\n CollectionReference,\n} from '@angular/fire/firestore';\nimport { QuerySnapshot } from '@firebase/firestore-types';\nimport { IQueryArgs, SneatApiService, SneatFirestoreService } from '@sneat/api';\nimport {\n IIdAndBriefAndDbo,\n IIdAndOptionalBriefAndOptionalDbo,\n ISpaceItemWithBriefAndDbo,\n ISpaceRef,\n} from '@sneat/core';\nimport { ISpaceDbo } from '@sneat/dto';\nimport { ISpaceItemNavContext, ISpaceRequest } from '@sneat/space-models';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\ntype ICreateSpaceItemResponse<\n Brief,\n Dbo extends Brief,\n> = ISpaceItemWithBriefAndDbo<Brief, Dbo>;\n\nabstract class SpaceItemBaseService<Brief, Dbo extends Brief> {\n protected readonly sfs: SneatFirestoreService<Brief, Dbo>;\n\n protected constructor(\n protected readonly injector: Injector,\n public readonly collectionName: string,\n public readonly afs: AngularFirestore,\n public readonly sneatApiService: SneatApiService,\n ) {\n if (!this.collectionName) {\n throw new Error('collectionName is required');\n }\n this.sfs = new SneatFirestoreService<Brief, Dbo>(this.injector);\n }\n\n private _collectionRef?: CollectionReference<Dbo>;\n\n protected abstract collectionRef<Dbo2 extends Dbo>(\n spaceID: string,\n ): CollectionReference<Dbo2>;\n\n public watchSpaceItemByIdWithSpaceRef<Dbo2 extends Dbo>(\n space: ISpaceRef,\n itemID: string,\n ): Observable<ISpaceItemNavContext<Brief, Dbo2>> {\n\n if (!space.id) {\n throw new Error('spaceID is required');\n }\n let collectionRef: CollectionReference<Dbo2>;\n if (this._collectionRef?.id == space.id) {\n collectionRef = this._collectionRef as CollectionReference<Dbo2>;\n } else {\n collectionRef = this.collectionRef<Dbo2>(space.id);\n this._collectionRef = collectionRef;\n }\n return runInInjectionContext(this.injector, () =>\n this.sfs\n .watchByID(collectionRef, itemID)\n .pipe(map((o) => ({ space, ...o }))),\n );\n }\n\n protected queryItems<Dbo2 extends Dbo>(\n collectionRef: CollectionReference<Dbo2>,\n queryArgs?: IQueryArgs,\n ): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {\n const $querySnapshot = this.sfs.watchSnapshotsByFilter<Dbo2>(\n collectionRef,\n queryArgs,\n );\n return $querySnapshot.pipe(\n map((querySnapshot) => {\n return this.mapQueryItem<Dbo2>(\n querySnapshot as unknown as QuerySnapshot<Dbo2>,\n );\n }),\n );\n }\n\n protected mapQueryItem<Dbo2 extends Dbo>(\n querySnapshot: QuerySnapshot<Dbo2>,\n ): IIdAndBriefAndDbo<Brief, Dbo2>[] {\n return querySnapshot.docs.map((docSnapshot) => {\n const dto = docSnapshot.data();\n const { id } = docSnapshot;\n const brief: Brief = dto;\n return { id, brief, dbo: dto };\n });\n }\n\n public deleteSpaceItem<Response>(\n endpoint: string,\n request: ISpaceRequest,\n ): Observable<Response> {\n return this.sneatApiService.delete<Response>(endpoint, undefined, request);\n }\n\n public createSpaceItem<Brief, Dbo extends Brief>(\n endpoint: string,\n spaceRef: ISpaceRef,\n request: ISpaceRequest,\n ): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo>> {\n return this.sneatApiService\n .post<ICreateSpaceItemResponse<Brief, Dbo>>(endpoint, request)\n .pipe(\n map((response) => {\n if (!response) {\n throw new Error('create team item response is empty');\n }\n if (!response.id) {\n throw new Error('create team item response have no ID');\n }\n const item: ISpaceItemWithBriefAndDbo<Brief, Dbo> = {\n space: spaceRef,\n id: response.id,\n dbo: response.dbo,\n brief: { id: response.id, ...response.dbo } as unknown as Brief,\n };\n return item;\n }),\n );\n }\n}\n\n// At the moment reserved to `happenings` only\nexport class GlobalSpaceItemService<\n Brief,\n Dbo extends Brief,\n> extends SpaceItemBaseService<Brief, Dbo> {\n protected override collectionRef<\n Dbo2 extends Dbo,\n >(): CollectionReference<Dbo2> {\n return runInInjectionContext(\n this.injector,\n () =>\n collection(this.afs, this.collectionName) as CollectionReference<Dbo2>,\n );\n }\n\n public watchGlobalItems<Dbo2 extends Dbo>(\n queryArgs: IQueryArgs,\n ): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {\n const collectionRef = this.collectionRef<Dbo2>();\n return this.queryItems<Dbo2>(collectionRef, queryArgs);\n }\n\n public watchGlobalSpaceItemsWithSpaceRef<Dbo2 extends Dbo>(\n space: ISpaceRef,\n queryArgs: IQueryArgs,\n ): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo2>[]> {\n return this.watchGlobalSpaceItems<Dbo2>(space.id, queryArgs).pipe(\n map((items) => items.map((item) => ({ ...item, space }))),\n );\n }\n\n public watchGlobalSpaceItems<Dbo2 extends Dbo>(\n spaceID: string,\n queryArgs: IQueryArgs,\n ): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {\n queryArgs = {\n ...queryArgs,\n filter: [\n ...(queryArgs?.filter || []),\n { field: 'spaceIDs', operator: '==', value: spaceID },\n ],\n };\n const collectionRef = this.collectionRef<Dbo2>();\n return this.queryItems<Dbo2>(collectionRef, queryArgs);\n }\n}\n\n// intentionally not abstract\nexport class ModuleSpaceItemService<\n Brief,\n Dbo extends Brief,\n> extends SpaceItemBaseService<Brief, Dbo> {\n protected readonly spacesCollection: CollectionReference<ISpaceDbo>;\n\n constructor(\n injector: Injector,\n public readonly moduleID: string,\n collectionName: string,\n afs: AngularFirestore,\n sneatApiService: SneatApiService,\n ) {\n super(injector, collectionName, afs, sneatApiService);\n if (!moduleID) {\n throw new Error('moduleID is required');\n }\n this.spacesCollection = collection(\n this.afs,\n 'spaces',\n ) as CollectionReference<ISpaceDbo>;\n }\n\n protected readonly dto2brief = (id: string, dto: Dbo) => ({ id, ...dto });\n\n // protected teamCollection(spaceID: string): AngularFirestoreCollection<ITeamDto> {\n // \treturn this.afs.collection('spaces');\n // }\n\n protected override collectionRef<Dbo2 extends Dbo>(\n spaceID: string,\n ): CollectionReference<Dbo2> {\n if (!spaceID) {\n throw new Error('spaceID is required');\n }\n return runInInjectionContext(\n this.injector,\n () =>\n collection(\n this.spacesCollection,\n spaceID,\n 'ext',\n this.moduleID,\n this.collectionName,\n ) as CollectionReference<Dbo2>,\n );\n }\n\n private readonly spaceRef = (id: string) => doc(this.spacesCollection, id);\n\n public watchModuleSpaceItem<Dbo2 extends Dbo>(\n space: ISpaceRef,\n itemID: string,\n ): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>> {\n const collection = this.collectionRef<Dbo2>(space.id);\n return this.sfs.watchByID<Dbo2>(collection, itemID);\n }\n\n public watchModuleSpaceItemsWithSpaceRef<Dbo2 extends Dbo>(\n space: ISpaceRef,\n queryArgs?: IQueryArgs,\n ): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo2>[]> {\n return this.watchModuleSpaceItems<Dbo2>(space.id, queryArgs).pipe(\n map((items) => items.map((item) => ({ ...item, space }))),\n );\n }\n\n public watchModuleSpaceItems<Dbo2 extends Dbo>(\n spaceID: string,\n queryArgs?: IQueryArgs,\n ): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {\n // filter = [\n // \t...(filter || []),\n // \t// { field: 'spaceIDs', operator: '==', value: spaceID },\n // ];\n return runInInjectionContext(this.injector, () => {\n const collectionRef = this.collectionRef<Dbo2>(spaceID);\n return this.queryItems<Dbo2>(collectionRef, queryArgs);\n });\n }\n\n // private readonly mapItemTeamItemContext = <\n // Brief2 extends Brief,\n // Dbo2 extends Dto,\n // >(\n // space: ISpaceContext,\n // item: IIdAndBrief<Brief2, Dbo2>,\n // ) => {\n // return querySnapshot.docs.map((docSnapshot) => {\n // const dto = docSnapshot.data();\n // const { id } = docSnapshot;\n // const brief: Brief2 = { id, ...dto } as unknown as Brief2;\n // const c: ISpaceItemContext<Brief2, Dbo2> = { id, team, dto, brief };\n // return c;\n // });\n // };\n\n // public watchSpaceItems<Brief2 extends Brief, Dbo2 extends Dto>(\n // spaceID: string,\n // filter?: readonly IFilter[],\n // ): Observable<IIdAndBriefAndDto<Brief2, Dbo2>[]> {\n // console.log('watchSpaceItems()', spaceID, this.collectionName);\n // const collectionRef = collection(\n // this.teamRef(spaceID),\n // this.collectionName,\n // );\n // const querySnapshots = this.sfs.watchSnapshotsByFilter<Dbo2>(\n // collectionRef as CollectionReference<Dbo2>,\n // filter || [],\n // );\n // return querySnapshots.pipe(\n // map(a => this.mapQueryItem(a)),\n // );\n // }\n\n // public watchTeamItemsWithSpaceContext<Brief2 extends Brief, Dbo2 extends Dto>(\n // space: ISpaceRef,\n // filter?: readonly IFilter[],\n // ): Observable<ISpaceItemContext<Brief2, Dbo2>[]> {\n // const querySnapshots = this.watchTeamItems(space.id, filter);\n // return querySnapshots.pipe(\n // map((querySnapshot) =>\n // this.mapItemSpaceItemContext(\n // team,\n // querySnapshot as unknown as QuerySnapshot<Dbo2>,\n // ),\n // ),\n // );\n // }\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { runInInjectionContext } from '@angular/core';
2
+ import { collection, } from '@angular/fire/firestore';
3
+ import { map } from 'rxjs/operators';
4
+ import { ModuleSpaceItemService } from './space-item.service';
5
+ // import firebase from "firebase/compat";
6
+ // import Item = firebase.analytics.Item;
7
+ export class SpaceModuleService extends ModuleSpaceItemService {
8
+ // protected readonly sfs: SneatFirestoreService<Brief, Dto>;
9
+ constructor(injector, moduleID, afs) {
10
+ // this.sfs = new SneatFirestoreService<Brief, Dto>(collectionName, afs);
11
+ super(injector, moduleID, 'ext', afs, undefined);
12
+ }
13
+ watchSpaceModuleRecord(spaceID) {
14
+ return runInInjectionContext(this.injector, () => {
15
+ const collectionRef = collection(this.spacesCollection, spaceID, 'ext');
16
+ // if (this.moduleID === 'trackus') {
17
+ // return throwError(() => new Error('test error'));
18
+ // }
19
+ return this.sfs
20
+ .watchByID(collectionRef, this.moduleID)
21
+ .pipe();
22
+ });
23
+ }
24
+ watchBriefs(spaceID, getBriefs) {
25
+ const o = this.watchSpaceModuleRecord(spaceID);
26
+ return o.pipe(map((teamModule) => {
27
+ const briefs = getBriefs(teamModule?.dbo || undefined);
28
+ const items = briefs
29
+ ? Object.keys(briefs).map((id) => ({ id, brief: briefs[id] }))
30
+ : [];
31
+ return items;
32
+ }));
33
+ }
34
+ }
35
+ //# sourceMappingURL=space-module.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-module.service.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/services/space-module.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EACL,UAAU,GAGX,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,0CAA0C;AAC1C,yCAAyC;AAEzC,MAAM,OAAgB,kBAAwB,SAAQ,sBAGrD;IACC,6DAA6D;IAC7D,YACE,QAAkB,EAClB,QAAgB,EAChB,GAAqB;QAErB,yEAAyE;QACzE,KAAK,CACH,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,GAAG,EACH,SAAuC,CACxC,CAAC;IACJ,CAAC;IAED,sBAAsB,CAAC,OAAe;QACpC,OAAO,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC/C,MAAM,aAAa,GAAG,UAAU,CAC9B,IAAI,CAAC,gBAAgB,EACrB,OAAO,EACP,KAAK,CACsB,CAAC;YAC9B,qCAAqC;YACrC,qDAAqD;YACrD,IAAI;YACJ,OAAO,IAAI,CAAC,GAAG;iBACZ,SAAS,CAAM,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC;iBAC5C,IAAI,EAEH,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW,CACT,OAAe,EACf,SAA6D;QAE7D,MAAM,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC,IAAI,CACX,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;YACjB,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC;YACvD,MAAM,KAAK,GAA6B,MAAM;gBAC5C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9D,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;CACF","sourcesContent":["import { Injector, runInInjectionContext } from '@angular/core';\nimport {\n collection,\n CollectionReference,\n Firestore as AngularFirestore,\n} from '@angular/fire/firestore';\nimport { SneatApiService } from '@sneat/api';\nimport { IIdAndBrief, IIdAndOptionalDbo } from '@sneat/core';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { ModuleSpaceItemService } from './space-item.service';\n\n// import firebase from \"firebase/compat\";\n// import Item = firebase.analytics.Item;\n\nexport abstract class SpaceModuleService<Dbo> extends ModuleSpaceItemService<\n Dbo,\n Dbo\n> {\n // protected readonly sfs: SneatFirestoreService<Brief, Dto>;\n protected constructor(\n injector: Injector,\n moduleID: string,\n afs: AngularFirestore,\n ) {\n // this.sfs = new SneatFirestoreService<Brief, Dto>(collectionName, afs);\n super(\n injector,\n moduleID,\n 'ext',\n afs,\n undefined as unknown as SneatApiService,\n );\n }\n\n watchSpaceModuleRecord(spaceID: string): Observable<IIdAndOptionalDbo<Dbo>> {\n return runInInjectionContext(this.injector, () => {\n const collectionRef = collection(\n this.spacesCollection,\n spaceID,\n 'ext',\n ) as CollectionReference<Dbo>;\n // if (this.moduleID === 'trackus') {\n // \treturn throwError(() => new Error('test error'));\n // }\n return this.sfs\n .watchByID<Dbo>(collectionRef, this.moduleID)\n .pipe\n // tap((o) => console.log(`${logPrefix} =>`, o)),\n ();\n });\n }\n\n watchBriefs<ItemBrief>(\n spaceID: string,\n getBriefs: (dto?: Dbo) => Readonly<Record<string, ItemBrief>>,\n ): Observable<IIdAndBrief<ItemBrief>[]> {\n const o = this.watchSpaceModuleRecord(spaceID);\n return o.pipe(\n map((teamModule) => {\n const briefs = getBriefs(teamModule?.dbo || undefined);\n const items: IIdAndBrief<ItemBrief>[] = briefs\n ? Object.keys(briefs).map((id) => ({ id, brief: briefs[id] }))\n : [];\n return items;\n }),\n );\n }\n}\n"]}
@@ -0,0 +1,97 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { NavController } from '@ionic/angular';
3
+ import { AnalyticsService } from '@sneat/core';
4
+ import { ErrorLogger } from '@sneat/core';
5
+ import * as i0 from "@angular/core";
6
+ export class SpaceNavService {
7
+ constructor() {
8
+ this.errorLogger = inject(ErrorLogger);
9
+ this.navController = inject(NavController);
10
+ this.analyticsService = inject(AnalyticsService);
11
+ this.navigateToAddMetric = (navController, team) => this.navToSpacePage(navController, team, 'add-metric', 'navigateToAddMetric');
12
+ this.navToSpacePage = (navController, space, url, eventName, params) => {
13
+ params = { ...params, space: space.id };
14
+ this.analyticsService.logEvent(eventName, params);
15
+ this.navForward(navController, url, { queryParams: params, state: { space } });
16
+ };
17
+ }
18
+ navigateToSpaces(animationDirection) {
19
+ this.analyticsService.logEvent('navigateToTeams');
20
+ this.navController
21
+ .navigateRoot('spaces', { animationDirection })
22
+ .catch((err) => this.errorLogger.logError(err, 'Failed to navigate to teams page'));
23
+ }
24
+ navigateToLogin(options) {
25
+ // Do not log `returnTo` as it might holds sensitive info
26
+ this.analyticsService.logEvent('navigateToLogin');
27
+ const navOptions = {
28
+ queryParams: options?.queryParams,
29
+ animationDirection: 'back',
30
+ };
31
+ if (options?.returnTo) {
32
+ navOptions.fragment = options.returnTo;
33
+ }
34
+ this.navController
35
+ .navigateRoot('login', navOptions)
36
+ .catch((err) => this.errorLogger.logError(err, 'Failed to navigate to login page'));
37
+ }
38
+ navigateToUserProfile() {
39
+ this.analyticsService.logEvent('navigateToUserProfile');
40
+ this.navController
41
+ .navigateRoot('user-profile')
42
+ .catch((err) => this.errorLogger.logError(err, 'Failed to naviage to user profile'));
43
+ }
44
+ navigateToSpace(space, animationDirection) {
45
+ this.analyticsService.logEvent('navigateToSpace', { spaceID: space.id });
46
+ const url = `space/${space.type || space.brief?.type}/${space.id}`;
47
+ return new Promise((resolve, reject) => {
48
+ this.navController
49
+ .navigateRoot(url, {
50
+ state: { space },
51
+ animationDirection,
52
+ })
53
+ .then(resolve)
54
+ .catch((err) => {
55
+ this.errorLogger.logError(err, 'Failed to navigate to team overview page with URL: ' + url);
56
+ reject(err);
57
+ });
58
+ });
59
+ }
60
+ navigateToMember(space, memberInfo) {
61
+ const id = `${space.id}:${memberInfo.id}`;
62
+ this.navForward(this.navController, 'member', {
63
+ queryParams: { id },
64
+ state: { space, memberInfo },
65
+ });
66
+ }
67
+ navigateBackToSpacePage(space, page, navOptions = {}) {
68
+ navOptions.animationDirection = 'back';
69
+ return this.navigateToSpacePage(space, page, navOptions);
70
+ }
71
+ navigateForwardToSpacePage(space, page, navOptions = {}) {
72
+ navOptions.animationDirection = 'forward';
73
+ return this.navigateToSpacePage(space, page, navOptions);
74
+ }
75
+ navigateToSpacePage(space, page, navOptions) {
76
+ const url = `space/${space?.type}/${space?.id}/${page}`;
77
+ const state = navOptions.state || {};
78
+ navOptions = { ...navOptions, state: { space, ...state } };
79
+ return this.navController.navigateForward(url, navOptions);
80
+ }
81
+ navForward(navController, url, navOptions) {
82
+ navController = navController || this.navController;
83
+ // this.analyticsService.logEvent(analyticsEvent.name, analyticsEvent.params);
84
+ navController
85
+ .navigateForward(url, navOptions)
86
+ .catch((err) => this.errorLogger.logError(err, 'Failed to navigate to: ' + url));
87
+ }
88
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceNavService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
89
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceNavService, providedIn: 'root' }); }
90
+ }
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceNavService, decorators: [{
92
+ type: Injectable,
93
+ args: [{
94
+ providedIn: 'root',
95
+ }]
96
+ }] });
97
+ //# sourceMappingURL=space-nav.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-nav.service.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/services/space-nav.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport { Params } from '@angular/router';\nimport { NavController } from '@ionic/angular';\nimport { AnalyticsService, IAnalyticsService, IIdAndBrief, ISpaceRef } from '@sneat/core';\nimport { IMemberBrief } from '@sneat/contactus-core';\n\ntype NavigationOptions = NonNullable<\n Parameters<NavController['navigateRoot']>[1]\n>;\nimport { IRecord } from '@sneat/data';\nimport { ISpaceDbo } from '@sneat/dto';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { ISpaceContext } from '@sneat/space-models';\n\nexport type ScrumPageTab = 'team' | 'my' | 'risks' | 'qna';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SpaceNavService {\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n private readonly navController = inject(NavController);\n private readonly analyticsService =\n inject<IAnalyticsService>(AnalyticsService);\n\n public navigateToSpaces(animationDirection?: 'forward' | 'back'): void {\n this.analyticsService.logEvent('navigateToTeams');\n this.navController\n .navigateRoot('spaces', { animationDirection })\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to navigate to teams page'),\n );\n }\n\n public navigateToLogin(options?: {\n returnTo?: string;\n queryParams?: Params;\n // fragment?: string;\n }): void {\n\n // Do not log `returnTo` as it might holds sensitive info\n this.analyticsService.logEvent('navigateToLogin');\n\n const navOptions: NavigationOptions = {\n queryParams: options?.queryParams,\n animationDirection: 'back',\n };\n if (options?.returnTo) {\n navOptions.fragment = options.returnTo;\n }\n this.navController\n .navigateRoot('login', navOptions)\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to navigate to login page'),\n );\n }\n\n public navigateToUserProfile(): void {\n this.analyticsService.logEvent('navigateToUserProfile');\n this.navController\n .navigateRoot('user-profile')\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to naviage to user profile'),\n );\n }\n\n public navigateToSpace(\n space: ISpaceContext,\n animationDirection?: 'forward' | 'back',\n ): Promise<boolean> {\n this.analyticsService.logEvent('navigateToSpace', { spaceID: space.id });\n const url = `space/${space.type || space.brief?.type}/${space.id}`;\n return new Promise<boolean>((resolve, reject) => {\n this.navController\n .navigateRoot(url, {\n state: { space },\n animationDirection,\n })\n .then(resolve)\n .catch((err) => {\n this.errorLogger.logError(\n err,\n 'Failed to navigate to team overview page with URL: ' + url,\n );\n reject(err);\n });\n });\n }\n\n public navigateToMember(\n space: ISpaceContext,\n memberInfo: IIdAndBrief<IMemberBrief>,\n ): void {\n const id = `${space.id}:${memberInfo.id}`;\n this.navForward(\n this.navController,\n 'member',\n {\n queryParams: { id },\n state: { space, memberInfo },\n },\n );\n }\n\n public navigateToAddMetric = (\n navController: NavController,\n team: IRecord<ISpaceDbo>,\n ): void =>\n this.navToSpacePage(\n navController,\n team,\n 'add-metric',\n 'navigateToAddMetric',\n );\n\n public navigateBackToSpacePage(\n space: ISpaceContext,\n page: string,\n navOptions: NavigationOptions = {},\n ): Promise<boolean> {\n navOptions.animationDirection = 'back';\n return this.navigateToSpacePage(space, page, navOptions);\n }\n\n public navigateForwardToSpacePage(\n space: ISpaceContext,\n page: string,\n navOptions: NavigationOptions = {},\n ): Promise<boolean> {\n navOptions.animationDirection = 'forward';\n return this.navigateToSpacePage(space, page, navOptions);\n }\n\n private navigateToSpacePage(\n space: ISpaceContext,\n page: string,\n navOptions: NavigationOptions,\n ): Promise<boolean> {\n const url = `space/${space?.type}/${space?.id}/${page}`;\n const state = navOptions.state || {};\n navOptions = { ...navOptions, state: { space, ...state } };\n return this.navController.navigateForward(url, navOptions);\n }\n\n private navForward(\n navController: NavController,\n url: string,\n navOptions: NavigationOptions,\n // _analyticsEvent: { name: string; params?: Record<string, unknown> },\n ): void {\n navController = navController || this.navController;\n // this.analyticsService.logEvent(analyticsEvent.name, analyticsEvent.params);\n navController\n .navigateForward(url, navOptions)\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to navigate to: ' + url),\n );\n }\n\n private navToSpacePage = (\n navController: NavController,\n space: ISpaceRef,\n url: string,\n eventName: string,\n params?: Record<string, unknown>,\n ): void => {\n params = { ...params, space: space.id };\n this.analyticsService.logEvent(eventName, params);\n this.navForward(\n navController,\n url,\n { queryParams: params, state: { space } },\n );\n };\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { SpaceService } from './space.service';
3
+ import * as i0 from "@angular/core";
4
+ export class SpaceServiceModule {
5
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceServiceModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: SpaceServiceModule }); }
7
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceServiceModule, providers: [SpaceService] }); }
8
+ }
9
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SpaceServiceModule, decorators: [{
10
+ type: NgModule,
11
+ args: [{
12
+ providers: [SpaceService],
13
+ }]
14
+ }] });
15
+ //# sourceMappingURL=space-service.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space-service.module.js","sourceRoot":"","sources":["../../../../../../../libs/space/services/src/lib/services/space-service.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AAK/C,MAAM,OAAO,kBAAkB;8GAAlB,kBAAkB;+GAAlB,kBAAkB;+GAAlB,kBAAkB,aAFlB,CAAC,YAAY,CAAC;;2FAEd,kBAAkB;kBAH9B,QAAQ;mBAAC;oBACR,SAAS,EAAE,CAAC,YAAY,CAAC;iBAC1B","sourcesContent":["import { NgModule } from '@angular/core';\nimport { SpaceService } from './space.service';\n\n@NgModule({\n providers: [SpaceService],\n})\nexport class SpaceServiceModule {}\n"]}