@sneat/space-services 0.1.3 → 0.1.6
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 +8 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/lib/components/with-space-input.directive.js +37 -0
- package/esm2022/lib/components/with-space-input.directive.js.map +1 -0
- package/esm2022/lib/services/space-context.service.js +26 -0
- package/esm2022/lib/services/space-context.service.js.map +1 -0
- package/esm2022/lib/services/space-item.service.js +132 -0
- package/esm2022/lib/services/space-item.service.js.map +1 -0
- package/esm2022/lib/services/space-module.service.js +35 -0
- package/esm2022/lib/services/space-module.service.js.map +1 -0
- package/esm2022/lib/services/space-nav.service.js +97 -0
- package/esm2022/lib/services/space-nav.service.js.map +1 -0
- package/esm2022/lib/services/space-service.module.js +15 -0
- package/esm2022/lib/services/space-service.module.js.map +1 -0
- package/esm2022/lib/services/space.service.js +209 -0
- package/esm2022/lib/services/space.service.js.map +1 -0
- package/esm2022/sneat-space-services.js +5 -0
- package/esm2022/sneat-space-services.js.map +1 -0
- package/{src/index.ts → index.d.ts} +0 -1
- package/lib/components/with-space-input.directive.d.ts +20 -0
- package/lib/services/space-context.service.d.ts +9 -0
- package/lib/services/space-item.service.d.ts +43 -0
- package/lib/services/space-module.service.d.ts +10 -0
- package/lib/services/space-nav.service.d.ts +32 -0
- package/lib/services/space-service.module.d.ts +6 -0
- package/lib/services/space.service.d.ts +33 -0
- package/package.json +14 -2
- package/sneat-space-services.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
- package/eslint.config.js +0 -7
- package/ng-package.json +0 -7
- package/project.json +0 -38
- package/src/lib/components/with-space-input.directive.spec.ts +0 -41
- package/src/lib/components/with-space-input.directive.ts +0 -40
- package/src/lib/services/space-context.service.spec.ts +0 -16
- package/src/lib/services/space-context.service.ts +0 -45
- package/src/lib/services/space-item.service.spec.ts +0 -179
- package/src/lib/services/space-item.service.ts +0 -308
- package/src/lib/services/space-module.service.spec.ts +0 -48
- package/src/lib/services/space-module.service.ts +0 -69
- package/src/lib/services/space-nav-service.service.spec.ts +0 -32
- package/src/lib/services/space-nav.service.ts +0 -175
- package/src/lib/services/space-service.module.spec.ts +0 -46
- package/src/lib/services/space-service.module.ts +0 -7
- package/src/lib/services/space.service.spec.ts +0 -44
- package/src/lib/services/space.service.ts +0 -291
- package/src/test-setup.ts +0 -3
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -19
- package/tsconfig.lib.prod.json +0 -7
- package/tsconfig.spec.json +0 -31
- package/vite.config.mts +0 -10
package/eslint.config.js
DELETED
package/ng-package.json
DELETED
package/project.json
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "space-services",
|
|
3
|
-
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"projectType": "library",
|
|
5
|
-
"sourceRoot": "libs/space/services/src",
|
|
6
|
-
"prefix": "sneat",
|
|
7
|
-
"targets": {
|
|
8
|
-
"build": {
|
|
9
|
-
"executor": "@nx/angular:ng-packagr-lite",
|
|
10
|
-
"outputs": [
|
|
11
|
-
"{workspaceRoot}/dist/libs/space/services"
|
|
12
|
-
],
|
|
13
|
-
"options": {
|
|
14
|
-
"project": "libs/space/services/ng-package.json",
|
|
15
|
-
"tsConfig": "libs/space/services/tsconfig.lib.json"
|
|
16
|
-
},
|
|
17
|
-
"configurations": {
|
|
18
|
-
"production": {
|
|
19
|
-
"tsConfig": "libs/space/services/tsconfig.lib.prod.json"
|
|
20
|
-
},
|
|
21
|
-
"development": {}
|
|
22
|
-
},
|
|
23
|
-
"defaultConfiguration": "production"
|
|
24
|
-
},
|
|
25
|
-
"test": {
|
|
26
|
-
"executor": "@nx/vitest:test",
|
|
27
|
-
"outputs": [
|
|
28
|
-
"{workspaceRoot}/coverage/libs/space/services"
|
|
29
|
-
],
|
|
30
|
-
"options": {
|
|
31
|
-
"tsConfig": "libs/space/services/tsconfig.spec.json"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"lint": {
|
|
35
|
-
"executor": "@nx/eslint:lint"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
import { NavController } from '@ionic/angular';
|
|
3
|
-
import { AnalyticsService, ErrorLogger } from '@sneat/core';
|
|
4
|
-
import { SpaceNavService } from '../services/space-nav.service';
|
|
5
|
-
|
|
6
|
-
// Simplified test - complex component testing skipped for now
|
|
7
|
-
describe('WithSpaceInput', () => {
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
TestBed.configureTestingModule({
|
|
10
|
-
providers: [
|
|
11
|
-
{
|
|
12
|
-
provide: SpaceNavService,
|
|
13
|
-
useValue: {
|
|
14
|
-
navigateToSpace: vi.fn(),
|
|
15
|
-
navigateToSpaces: vi.fn(),
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
provide: NavController,
|
|
20
|
-
useValue: {
|
|
21
|
-
navigateRoot: vi.fn().mockResolvedValue(true),
|
|
22
|
-
navigateForward: vi.fn().mockResolvedValue(true),
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
provide: AnalyticsService,
|
|
27
|
-
useValue: { logEvent: vi.fn() },
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
provide: ErrorLogger,
|
|
31
|
-
useValue: { logError: vi.fn(), logErrorHandler: () => vi.fn() },
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should have SpaceNavService available', () => {
|
|
38
|
-
const service = TestBed.inject(SpaceNavService);
|
|
39
|
-
expect(service).toBeTruthy();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { computed, Directive, effect, inject, input } from '@angular/core';
|
|
2
|
-
import { ISpaceContext } from '@sneat/space-models';
|
|
3
|
-
import { SneatBaseComponent } from '@sneat/ui';
|
|
4
|
-
import { BehaviorSubject, distinctUntilChanged } from 'rxjs';
|
|
5
|
-
import { SpaceNavService } from '../services/space-nav.service';
|
|
6
|
-
|
|
7
|
-
@Directive()
|
|
8
|
-
export abstract class WithSpaceInput extends SneatBaseComponent {
|
|
9
|
-
protected readonly spaceNavService = inject(SpaceNavService);
|
|
10
|
-
|
|
11
|
-
public readonly $space = input.required<ISpaceContext>();
|
|
12
|
-
|
|
13
|
-
protected readonly $spaceID = computed(() => this.$space().id);
|
|
14
|
-
private readonly spaceIDChanged = new BehaviorSubject<string | undefined>(
|
|
15
|
-
undefined,
|
|
16
|
-
);
|
|
17
|
-
protected spaceID$ = this.spaceIDChanged
|
|
18
|
-
.asObservable()
|
|
19
|
-
.pipe(this.takeUntilDestroyed(), distinctUntilChanged());
|
|
20
|
-
|
|
21
|
-
protected readonly $spaceType = computed(() => this.$space().type);
|
|
22
|
-
protected readonly $spaceRef = computed(() => ({
|
|
23
|
-
id: this.$spaceID(),
|
|
24
|
-
type: this.$spaceType(),
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
constructor() {
|
|
28
|
-
super();
|
|
29
|
-
effect(() => {
|
|
30
|
-
const spaceID = this.$spaceID();
|
|
31
|
-
if (spaceID !== this.spaceIDChanged.value) {
|
|
32
|
-
this.onSpaceIdChanged(spaceID);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
protected onSpaceIdChanged(spaceID: string): void {
|
|
38
|
-
this.spaceIDChanged.next(spaceID);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { SpaceContextService } from './space-context.service';
|
|
4
|
-
|
|
5
|
-
describe('SpaceContextService', () => {
|
|
6
|
-
let service: SpaceContextService;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
TestBed.configureTestingModule({});
|
|
10
|
-
service = TestBed.inject(SpaceContextService);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should be created', () => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { ParamMap } from '@angular/router';
|
|
3
|
-
import { distinctUntilChanged, Observable } from 'rxjs';
|
|
4
|
-
import { map } from 'rxjs/operators';
|
|
5
|
-
import { ISpaceContext } from '@sneat/space-models';
|
|
6
|
-
import { SpaceType } from '@sneat/core';
|
|
7
|
-
|
|
8
|
-
@Injectable({
|
|
9
|
-
providedIn: 'root',
|
|
10
|
-
})
|
|
11
|
-
export class SpaceContextService {
|
|
12
|
-
// public trackUrl(
|
|
13
|
-
// route: ActivatedRoute,
|
|
14
|
-
// paramName: string,
|
|
15
|
-
// ): Observable<ISpaceContext | undefined> {
|
|
16
|
-
// return route.paramMap.pipe(
|
|
17
|
-
// map(params => {
|
|
18
|
-
// const id = params.get('spaceID') || undefined;
|
|
19
|
-
// const spaceContext: ISpaceContext | undefined = id ? { id } : undefined;
|
|
20
|
-
// return spaceContext;
|
|
21
|
-
// }),
|
|
22
|
-
// );
|
|
23
|
-
// }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function trackSpaceIdAndTypeFromRouteParameter(
|
|
27
|
-
paramMap$: Observable<ParamMap>,
|
|
28
|
-
): Observable<ISpaceContext | undefined> {
|
|
29
|
-
return paramMap$.pipe(
|
|
30
|
-
map((params) => {
|
|
31
|
-
const id = params.get('spaceID'),
|
|
32
|
-
type = params.get('spaceType') as SpaceType;
|
|
33
|
-
// console.log('trackSpaceIdAndTypeFromRouteParameter', params, id, type);
|
|
34
|
-
const spaceContext: ISpaceContext | undefined = id
|
|
35
|
-
? { id: id, type: type || undefined }
|
|
36
|
-
: undefined;
|
|
37
|
-
// console.log('trackSpaceIdAndTypeFromRouteParameter() => spaceContext:', spaceContext)
|
|
38
|
-
return spaceContext;
|
|
39
|
-
}),
|
|
40
|
-
distinctUntilChanged(
|
|
41
|
-
(previous, current) =>
|
|
42
|
-
previous?.id === current?.id && previous?.type == current?.type,
|
|
43
|
-
),
|
|
44
|
-
);
|
|
45
|
-
}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
import { Injector } from '@angular/core';
|
|
3
|
-
import { Firestore, collection } from '@angular/fire/firestore';
|
|
4
|
-
import { SneatApiService } from '@sneat/api';
|
|
5
|
-
import { firstValueFrom, of } from 'rxjs';
|
|
6
|
-
import {
|
|
7
|
-
GlobalSpaceItemService,
|
|
8
|
-
ModuleSpaceItemService,
|
|
9
|
-
} from './space-item.service';
|
|
10
|
-
|
|
11
|
-
// Mock collection function
|
|
12
|
-
vi.mock('@angular/fire/firestore', async () => {
|
|
13
|
-
const actual = await vi.importActual('@angular/fire/firestore');
|
|
14
|
-
return {
|
|
15
|
-
...actual,
|
|
16
|
-
collection: vi.fn(() => ({ id: 'mock-collection' })),
|
|
17
|
-
};
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('GlobalSpaceItemService', () => {
|
|
21
|
-
let service: GlobalSpaceItemService<unknown, unknown>;
|
|
22
|
-
let mockInjector: Injector;
|
|
23
|
-
let mockFirestore: Firestore;
|
|
24
|
-
let mockSneatApiService: SneatApiService;
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
mockInjector = TestBed.inject(Injector);
|
|
28
|
-
mockFirestore = {
|
|
29
|
-
type: 'Firestore',
|
|
30
|
-
toJSON: () => ({}),
|
|
31
|
-
} as unknown as Firestore;
|
|
32
|
-
mockSneatApiService = {
|
|
33
|
-
post: vi.fn(),
|
|
34
|
-
delete: vi.fn(),
|
|
35
|
-
} as unknown as SneatApiService;
|
|
36
|
-
|
|
37
|
-
service = new GlobalSpaceItemService(
|
|
38
|
-
mockInjector,
|
|
39
|
-
'test-collection',
|
|
40
|
-
mockFirestore,
|
|
41
|
-
mockSneatApiService,
|
|
42
|
-
);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should be created', () => {
|
|
46
|
-
expect(service).toBeTruthy();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should throw error if collectionName is not provided', () => {
|
|
50
|
-
expect(() => {
|
|
51
|
-
new GlobalSpaceItemService(
|
|
52
|
-
mockInjector,
|
|
53
|
-
'',
|
|
54
|
-
mockFirestore,
|
|
55
|
-
mockSneatApiService,
|
|
56
|
-
);
|
|
57
|
-
}).toThrow('collectionName is required');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should have correct collection name', () => {
|
|
61
|
-
expect(service.collectionName).toBe('test-collection');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should delete space item', async () => {
|
|
65
|
-
const mockResponse = { success: true };
|
|
66
|
-
vi.spyOn(mockSneatApiService, 'delete').mockReturnValue(of(mockResponse));
|
|
67
|
-
|
|
68
|
-
const request = { spaceID: 'space1' };
|
|
69
|
-
const response = await firstValueFrom(
|
|
70
|
-
service.deleteSpaceItem('test-endpoint', request),
|
|
71
|
-
);
|
|
72
|
-
expect(response).toEqual(mockResponse);
|
|
73
|
-
expect(mockSneatApiService.delete).toHaveBeenCalledWith(
|
|
74
|
-
'test-endpoint',
|
|
75
|
-
undefined,
|
|
76
|
-
request,
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should create space item', async () => {
|
|
81
|
-
const mockResponse = {
|
|
82
|
-
id: 'item1',
|
|
83
|
-
dbo: { name: 'Test Item' },
|
|
84
|
-
};
|
|
85
|
-
vi.spyOn(mockSneatApiService, 'post').mockReturnValue(of(mockResponse));
|
|
86
|
-
|
|
87
|
-
const spaceRef = { id: 'space1', type: 'team' as const };
|
|
88
|
-
const request = { spaceID: 'space1', data: { name: 'Test' } };
|
|
89
|
-
|
|
90
|
-
const item = await firstValueFrom(
|
|
91
|
-
service.createSpaceItem('create-endpoint', spaceRef, request),
|
|
92
|
-
);
|
|
93
|
-
expect(item.id).toBe('item1');
|
|
94
|
-
expect(item.space).toEqual(spaceRef);
|
|
95
|
-
expect(item.dbo).toEqual(mockResponse.dbo);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should throw error if create response is empty', async () => {
|
|
99
|
-
vi.spyOn(mockSneatApiService, 'post').mockReturnValue(of(null as unknown));
|
|
100
|
-
|
|
101
|
-
const spaceRef = { id: 'space1', type: 'team' as const };
|
|
102
|
-
const request = { spaceID: 'space1' };
|
|
103
|
-
|
|
104
|
-
await expect(
|
|
105
|
-
firstValueFrom(
|
|
106
|
-
service.createSpaceItem('create-endpoint', spaceRef, request),
|
|
107
|
-
),
|
|
108
|
-
).rejects.toThrow('create team item response is empty');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should throw error if create response has no ID', async () => {
|
|
112
|
-
const mockResponse = { dbo: { name: 'Test' } };
|
|
113
|
-
vi.spyOn(mockSneatApiService, 'post').mockReturnValue(of(mockResponse));
|
|
114
|
-
|
|
115
|
-
const spaceRef = { id: 'space1', type: 'team' as const };
|
|
116
|
-
const request = { spaceID: 'space1' };
|
|
117
|
-
|
|
118
|
-
await expect(
|
|
119
|
-
firstValueFrom(
|
|
120
|
-
service.createSpaceItem('create-endpoint', spaceRef, request),
|
|
121
|
-
),
|
|
122
|
-
).rejects.toThrow('create team item response have no ID');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('ModuleSpaceItemService', () => {
|
|
127
|
-
let service: ModuleSpaceItemService<unknown, unknown>;
|
|
128
|
-
let mockInjector: Injector;
|
|
129
|
-
let mockFirestore: Firestore;
|
|
130
|
-
let mockSneatApiService: SneatApiService;
|
|
131
|
-
|
|
132
|
-
beforeEach(() => {
|
|
133
|
-
mockInjector = TestBed.inject(Injector);
|
|
134
|
-
mockFirestore = {
|
|
135
|
-
type: 'Firestore',
|
|
136
|
-
toJSON: () => ({}),
|
|
137
|
-
} as unknown as Firestore;
|
|
138
|
-
mockSneatApiService = {
|
|
139
|
-
post: vi.fn(),
|
|
140
|
-
} as unknown as SneatApiService;
|
|
141
|
-
|
|
142
|
-
vi.mocked(collection).mockReturnValue({ id: 'spaces' } as unknown);
|
|
143
|
-
|
|
144
|
-
service = new ModuleSpaceItemService(
|
|
145
|
-
mockInjector,
|
|
146
|
-
'test-module',
|
|
147
|
-
'items',
|
|
148
|
-
mockFirestore,
|
|
149
|
-
mockSneatApiService,
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should be created', () => {
|
|
154
|
-
expect(service).toBeTruthy();
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should throw error if moduleID is not provided', () => {
|
|
158
|
-
expect(() => {
|
|
159
|
-
new ModuleSpaceItemService(
|
|
160
|
-
mockInjector,
|
|
161
|
-
'',
|
|
162
|
-
'items',
|
|
163
|
-
mockFirestore,
|
|
164
|
-
mockSneatApiService,
|
|
165
|
-
);
|
|
166
|
-
}).toThrow('moduleID is required');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('should have correct moduleID', () => {
|
|
170
|
-
expect(service.moduleID).toBe('test-module');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should throw error when creating collection ref without spaceID', () => {
|
|
174
|
-
expect(() => {
|
|
175
|
-
// Access protected method via unknown cast for testing
|
|
176
|
-
(service as unknown as { collectionRef: (spaceID: string) => unknown }).collectionRef('');
|
|
177
|
-
}).toThrow('spaceID is required');
|
|
178
|
-
});
|
|
179
|
-
});
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { Injector, runInInjectionContext } from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
Firestore as AngularFirestore,
|
|
4
|
-
doc,
|
|
5
|
-
collection,
|
|
6
|
-
CollectionReference,
|
|
7
|
-
} from '@angular/fire/firestore';
|
|
8
|
-
import { QuerySnapshot } from '@firebase/firestore-types';
|
|
9
|
-
import { IQueryArgs, SneatApiService, SneatFirestoreService } from '@sneat/api';
|
|
10
|
-
import {
|
|
11
|
-
IIdAndBriefAndDbo,
|
|
12
|
-
IIdAndOptionalBriefAndOptionalDbo,
|
|
13
|
-
ISpaceItemWithBriefAndDbo,
|
|
14
|
-
ISpaceRef,
|
|
15
|
-
} from '@sneat/core';
|
|
16
|
-
import { ISpaceDbo } from '@sneat/dto';
|
|
17
|
-
import { ISpaceItemNavContext, ISpaceRequest } from '@sneat/space-models';
|
|
18
|
-
import { Observable } from 'rxjs';
|
|
19
|
-
import { map } from 'rxjs/operators';
|
|
20
|
-
|
|
21
|
-
type ICreateSpaceItemResponse<
|
|
22
|
-
Brief,
|
|
23
|
-
Dbo extends Brief,
|
|
24
|
-
> = ISpaceItemWithBriefAndDbo<Brief, Dbo>;
|
|
25
|
-
|
|
26
|
-
abstract class SpaceItemBaseService<Brief, Dbo extends Brief> {
|
|
27
|
-
protected readonly sfs: SneatFirestoreService<Brief, Dbo>;
|
|
28
|
-
|
|
29
|
-
protected constructor(
|
|
30
|
-
protected readonly injector: Injector,
|
|
31
|
-
public readonly collectionName: string,
|
|
32
|
-
public readonly afs: AngularFirestore,
|
|
33
|
-
public readonly sneatApiService: SneatApiService,
|
|
34
|
-
) {
|
|
35
|
-
if (!this.collectionName) {
|
|
36
|
-
throw new Error('collectionName is required');
|
|
37
|
-
}
|
|
38
|
-
this.sfs = new SneatFirestoreService<Brief, Dbo>(this.injector);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private _collectionRef?: CollectionReference<Dbo>;
|
|
42
|
-
|
|
43
|
-
protected abstract collectionRef<Dbo2 extends Dbo>(
|
|
44
|
-
spaceID: string,
|
|
45
|
-
): CollectionReference<Dbo2>;
|
|
46
|
-
|
|
47
|
-
public watchSpaceItemByIdWithSpaceRef<Dbo2 extends Dbo>(
|
|
48
|
-
space: ISpaceRef,
|
|
49
|
-
itemID: string,
|
|
50
|
-
): Observable<ISpaceItemNavContext<Brief, Dbo2>> {
|
|
51
|
-
|
|
52
|
-
if (!space.id) {
|
|
53
|
-
throw new Error('spaceID is required');
|
|
54
|
-
}
|
|
55
|
-
let collectionRef: CollectionReference<Dbo2>;
|
|
56
|
-
if (this._collectionRef?.id == space.id) {
|
|
57
|
-
collectionRef = this._collectionRef as CollectionReference<Dbo2>;
|
|
58
|
-
} else {
|
|
59
|
-
collectionRef = this.collectionRef<Dbo2>(space.id);
|
|
60
|
-
this._collectionRef = collectionRef;
|
|
61
|
-
}
|
|
62
|
-
return runInInjectionContext(this.injector, () =>
|
|
63
|
-
this.sfs
|
|
64
|
-
.watchByID(collectionRef, itemID)
|
|
65
|
-
.pipe(map((o) => ({ space, ...o }))),
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
protected queryItems<Dbo2 extends Dbo>(
|
|
70
|
-
collectionRef: CollectionReference<Dbo2>,
|
|
71
|
-
queryArgs?: IQueryArgs,
|
|
72
|
-
): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {
|
|
73
|
-
const $querySnapshot = this.sfs.watchSnapshotsByFilter<Dbo2>(
|
|
74
|
-
collectionRef,
|
|
75
|
-
queryArgs,
|
|
76
|
-
);
|
|
77
|
-
return $querySnapshot.pipe(
|
|
78
|
-
map((querySnapshot) => {
|
|
79
|
-
return this.mapQueryItem<Dbo2>(
|
|
80
|
-
querySnapshot as unknown as QuerySnapshot<Dbo2>,
|
|
81
|
-
);
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
protected mapQueryItem<Dbo2 extends Dbo>(
|
|
87
|
-
querySnapshot: QuerySnapshot<Dbo2>,
|
|
88
|
-
): IIdAndBriefAndDbo<Brief, Dbo2>[] {
|
|
89
|
-
return querySnapshot.docs.map((docSnapshot) => {
|
|
90
|
-
const dto = docSnapshot.data();
|
|
91
|
-
const { id } = docSnapshot;
|
|
92
|
-
const brief: Brief = dto;
|
|
93
|
-
return { id, brief, dbo: dto };
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public deleteSpaceItem<Response>(
|
|
98
|
-
endpoint: string,
|
|
99
|
-
request: ISpaceRequest,
|
|
100
|
-
): Observable<Response> {
|
|
101
|
-
return this.sneatApiService.delete<Response>(endpoint, undefined, request);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
public createSpaceItem<Brief, Dbo extends Brief>(
|
|
105
|
-
endpoint: string,
|
|
106
|
-
spaceRef: ISpaceRef,
|
|
107
|
-
request: ISpaceRequest,
|
|
108
|
-
): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo>> {
|
|
109
|
-
return this.sneatApiService
|
|
110
|
-
.post<ICreateSpaceItemResponse<Brief, Dbo>>(endpoint, request)
|
|
111
|
-
.pipe(
|
|
112
|
-
map((response) => {
|
|
113
|
-
if (!response) {
|
|
114
|
-
throw new Error('create team item response is empty');
|
|
115
|
-
}
|
|
116
|
-
if (!response.id) {
|
|
117
|
-
throw new Error('create team item response have no ID');
|
|
118
|
-
}
|
|
119
|
-
const item: ISpaceItemWithBriefAndDbo<Brief, Dbo> = {
|
|
120
|
-
space: spaceRef,
|
|
121
|
-
id: response.id,
|
|
122
|
-
dbo: response.dbo,
|
|
123
|
-
brief: { id: response.id, ...response.dbo } as unknown as Brief,
|
|
124
|
-
};
|
|
125
|
-
return item;
|
|
126
|
-
}),
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// At the moment reserved to `happenings` only
|
|
132
|
-
export class GlobalSpaceItemService<
|
|
133
|
-
Brief,
|
|
134
|
-
Dbo extends Brief,
|
|
135
|
-
> extends SpaceItemBaseService<Brief, Dbo> {
|
|
136
|
-
protected override collectionRef<
|
|
137
|
-
Dbo2 extends Dbo,
|
|
138
|
-
>(): CollectionReference<Dbo2> {
|
|
139
|
-
return runInInjectionContext(
|
|
140
|
-
this.injector,
|
|
141
|
-
() =>
|
|
142
|
-
collection(this.afs, this.collectionName) as CollectionReference<Dbo2>,
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public watchGlobalItems<Dbo2 extends Dbo>(
|
|
147
|
-
queryArgs: IQueryArgs,
|
|
148
|
-
): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {
|
|
149
|
-
const collectionRef = this.collectionRef<Dbo2>();
|
|
150
|
-
return this.queryItems<Dbo2>(collectionRef, queryArgs);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
public watchGlobalSpaceItemsWithSpaceRef<Dbo2 extends Dbo>(
|
|
154
|
-
space: ISpaceRef,
|
|
155
|
-
queryArgs: IQueryArgs,
|
|
156
|
-
): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo2>[]> {
|
|
157
|
-
return this.watchGlobalSpaceItems<Dbo2>(space.id, queryArgs).pipe(
|
|
158
|
-
map((items) => items.map((item) => ({ ...item, space }))),
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public watchGlobalSpaceItems<Dbo2 extends Dbo>(
|
|
163
|
-
spaceID: string,
|
|
164
|
-
queryArgs: IQueryArgs,
|
|
165
|
-
): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {
|
|
166
|
-
queryArgs = {
|
|
167
|
-
...queryArgs,
|
|
168
|
-
filter: [
|
|
169
|
-
...(queryArgs?.filter || []),
|
|
170
|
-
{ field: 'spaceIDs', operator: '==', value: spaceID },
|
|
171
|
-
],
|
|
172
|
-
};
|
|
173
|
-
const collectionRef = this.collectionRef<Dbo2>();
|
|
174
|
-
return this.queryItems<Dbo2>(collectionRef, queryArgs);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// intentionally not abstract
|
|
179
|
-
export class ModuleSpaceItemService<
|
|
180
|
-
Brief,
|
|
181
|
-
Dbo extends Brief,
|
|
182
|
-
> extends SpaceItemBaseService<Brief, Dbo> {
|
|
183
|
-
protected readonly spacesCollection: CollectionReference<ISpaceDbo>;
|
|
184
|
-
|
|
185
|
-
constructor(
|
|
186
|
-
injector: Injector,
|
|
187
|
-
public readonly moduleID: string,
|
|
188
|
-
collectionName: string,
|
|
189
|
-
afs: AngularFirestore,
|
|
190
|
-
sneatApiService: SneatApiService,
|
|
191
|
-
) {
|
|
192
|
-
super(injector, collectionName, afs, sneatApiService);
|
|
193
|
-
if (!moduleID) {
|
|
194
|
-
throw new Error('moduleID is required');
|
|
195
|
-
}
|
|
196
|
-
this.spacesCollection = collection(
|
|
197
|
-
this.afs,
|
|
198
|
-
'spaces',
|
|
199
|
-
) as CollectionReference<ISpaceDbo>;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
protected readonly dto2brief = (id: string, dto: Dbo) => ({ id, ...dto });
|
|
203
|
-
|
|
204
|
-
// protected teamCollection(spaceID: string): AngularFirestoreCollection<ITeamDto> {
|
|
205
|
-
// return this.afs.collection('spaces');
|
|
206
|
-
// }
|
|
207
|
-
|
|
208
|
-
protected override collectionRef<Dbo2 extends Dbo>(
|
|
209
|
-
spaceID: string,
|
|
210
|
-
): CollectionReference<Dbo2> {
|
|
211
|
-
if (!spaceID) {
|
|
212
|
-
throw new Error('spaceID is required');
|
|
213
|
-
}
|
|
214
|
-
return runInInjectionContext(
|
|
215
|
-
this.injector,
|
|
216
|
-
() =>
|
|
217
|
-
collection(
|
|
218
|
-
this.spacesCollection,
|
|
219
|
-
spaceID,
|
|
220
|
-
'ext',
|
|
221
|
-
this.moduleID,
|
|
222
|
-
this.collectionName,
|
|
223
|
-
) as CollectionReference<Dbo2>,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private readonly spaceRef = (id: string) => doc(this.spacesCollection, id);
|
|
228
|
-
|
|
229
|
-
public watchModuleSpaceItem<Dbo2 extends Dbo>(
|
|
230
|
-
space: ISpaceRef,
|
|
231
|
-
itemID: string,
|
|
232
|
-
): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>> {
|
|
233
|
-
const collection = this.collectionRef<Dbo2>(space.id);
|
|
234
|
-
return this.sfs.watchByID<Dbo2>(collection, itemID);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
public watchModuleSpaceItemsWithSpaceRef<Dbo2 extends Dbo>(
|
|
238
|
-
space: ISpaceRef,
|
|
239
|
-
queryArgs?: IQueryArgs,
|
|
240
|
-
): Observable<ISpaceItemWithBriefAndDbo<Brief, Dbo2>[]> {
|
|
241
|
-
return this.watchModuleSpaceItems<Dbo2>(space.id, queryArgs).pipe(
|
|
242
|
-
map((items) => items.map((item) => ({ ...item, space }))),
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
public watchModuleSpaceItems<Dbo2 extends Dbo>(
|
|
247
|
-
spaceID: string,
|
|
248
|
-
queryArgs?: IQueryArgs,
|
|
249
|
-
): Observable<IIdAndBriefAndDbo<Brief, Dbo2>[]> {
|
|
250
|
-
// filter = [
|
|
251
|
-
// ...(filter || []),
|
|
252
|
-
// // { field: 'spaceIDs', operator: '==', value: spaceID },
|
|
253
|
-
// ];
|
|
254
|
-
return runInInjectionContext(this.injector, () => {
|
|
255
|
-
const collectionRef = this.collectionRef<Dbo2>(spaceID);
|
|
256
|
-
return this.queryItems<Dbo2>(collectionRef, queryArgs);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// private readonly mapItemTeamItemContext = <
|
|
261
|
-
// Brief2 extends Brief,
|
|
262
|
-
// Dbo2 extends Dto,
|
|
263
|
-
// >(
|
|
264
|
-
// space: ISpaceContext,
|
|
265
|
-
// item: IIdAndBrief<Brief2, Dbo2>,
|
|
266
|
-
// ) => {
|
|
267
|
-
// return querySnapshot.docs.map((docSnapshot) => {
|
|
268
|
-
// const dto = docSnapshot.data();
|
|
269
|
-
// const { id } = docSnapshot;
|
|
270
|
-
// const brief: Brief2 = { id, ...dto } as unknown as Brief2;
|
|
271
|
-
// const c: ISpaceItemContext<Brief2, Dbo2> = { id, team, dto, brief };
|
|
272
|
-
// return c;
|
|
273
|
-
// });
|
|
274
|
-
// };
|
|
275
|
-
|
|
276
|
-
// public watchSpaceItems<Brief2 extends Brief, Dbo2 extends Dto>(
|
|
277
|
-
// spaceID: string,
|
|
278
|
-
// filter?: readonly IFilter[],
|
|
279
|
-
// ): Observable<IIdAndBriefAndDto<Brief2, Dbo2>[]> {
|
|
280
|
-
// console.log('watchSpaceItems()', spaceID, this.collectionName);
|
|
281
|
-
// const collectionRef = collection(
|
|
282
|
-
// this.teamRef(spaceID),
|
|
283
|
-
// this.collectionName,
|
|
284
|
-
// );
|
|
285
|
-
// const querySnapshots = this.sfs.watchSnapshotsByFilter<Dbo2>(
|
|
286
|
-
// collectionRef as CollectionReference<Dbo2>,
|
|
287
|
-
// filter || [],
|
|
288
|
-
// );
|
|
289
|
-
// return querySnapshots.pipe(
|
|
290
|
-
// map(a => this.mapQueryItem(a)),
|
|
291
|
-
// );
|
|
292
|
-
// }
|
|
293
|
-
|
|
294
|
-
// public watchTeamItemsWithSpaceContext<Brief2 extends Brief, Dbo2 extends Dto>(
|
|
295
|
-
// space: ISpaceRef,
|
|
296
|
-
// filter?: readonly IFilter[],
|
|
297
|
-
// ): Observable<ISpaceItemContext<Brief2, Dbo2>[]> {
|
|
298
|
-
// const querySnapshots = this.watchTeamItems(space.id, filter);
|
|
299
|
-
// return querySnapshots.pipe(
|
|
300
|
-
// map((querySnapshot) =>
|
|
301
|
-
// this.mapItemSpaceItemContext(
|
|
302
|
-
// team,
|
|
303
|
-
// querySnapshot as unknown as QuerySnapshot<Dbo2>,
|
|
304
|
-
// ),
|
|
305
|
-
// ),
|
|
306
|
-
// );
|
|
307
|
-
// }
|
|
308
|
-
}
|