Move all state services under a common base class

pull/10760/head
Oliver Günther 2 years ago
parent 99ad19fe62
commit 9d1d1cc8c6
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 38
      frontend/src/app/core/state/attachments/attachments.service.ts
  2. 17
      frontend/src/app/core/state/capabilities/capabilities.service.ts
  3. 15
      frontend/src/app/core/state/collection-store.ts
  4. 32
      frontend/src/app/core/state/file-links/file-links.service.ts
  5. 10
      frontend/src/app/core/state/principals/principals.query.ts
  6. 58
      frontend/src/app/core/state/principals/principals.service.ts
  7. 30
      frontend/src/app/core/state/projects/projects.service.ts
  8. 32
      frontend/src/app/core/state/resource-collection.service.ts
  9. 41
      frontend/src/app/core/state/storages/storages.service.ts
  10. 67
      frontend/src/app/core/state/views/views.service.ts
  11. 4
      frontend/src/app/features/in-app-notifications/center/menu/menu.component.ts
  12. 54
      frontend/src/app/features/in-app-notifications/center/menu/state/ian-menu.query.ts
  13. 40
      frontend/src/app/features/in-app-notifications/center/menu/state/ian-menu.service.ts
  14. 7
      frontend/src/app/features/in-app-notifications/center/state/ian-center.service.ts
  15. 2
      frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts
  16. 4
      frontend/src/app/shared/components/attachments/attachment-list/attachment-list-item.component.ts
  17. 9
      frontend/src/app/shared/components/attachments/attachment-list/attachment-list.component.ts

@ -31,10 +31,7 @@ import {
HttpClient,
HttpHeaders,
} from '@angular/common/http';
import {
applyTransaction,
QueryEntity,
} from '@datorama/akita';
import { applyTransaction } from '@datorama/akita';
import {
from,
Observable,
@ -42,7 +39,6 @@ import {
import {
catchError,
map,
switchMap,
tap,
} from 'rxjs/operators';
import { AttachmentsStore } from 'core-app/core/state/attachments/attachments.store';
@ -61,13 +57,13 @@ import { HalLink } from 'core-app/features/hal/hal-link/hal-link';
import isNewResource, { HAL_NEW_RESOURCE_ID } from 'core-app/features/hal/helpers/is-new-resource';
import { ConfigurationService } from 'core-app/core/config/configuration.service';
import { insertCollectionIntoState } from 'core-app/core/state/collection-store';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@Injectable()
export class AttachmentsResourceService {
protected store = new AttachmentsStore();
public query = new QueryEntity(this.store);
export class AttachmentsResourceService extends ResourceCollectionService<IAttachment> {
constructor(
private readonly I18n:I18nService,
private readonly http:HttpClient,
@ -76,7 +72,9 @@ export class AttachmentsResourceService {
private readonly directFileUploadService:OpenProjectDirectFileUploadService,
private readonly configurationService:ConfigurationService,
private readonly toastService:ToastService,
) { }
) {
super();
}
/**
* This method ensures that a specific collection is fetched, if not available.
@ -91,20 +89,6 @@ export class AttachmentsResourceService {
this.fetchAttachments(key).subscribe();
}
/**
* Returns an observable of all attachments in a collection identified by the collection key.
*
* @param key the collection key
*/
collection(key:string):Observable<IAttachment[]> {
return this.query
.select()
.pipe(
map((state) => state.collections[key]?.ids),
switchMap((attachmentIds) => this.query.selectMany(attachmentIds)),
);
}
/**
* Fetches attachments by the attachment collection self link.
* This link is used as key to store the result collection in the resource store.
@ -273,4 +257,8 @@ export class AttachmentsResourceService {
const attachments = resource.attachments as unknown&{ href?:string };
return attachments?.href || null;
}
protected createStore():CollectionStore<IAttachment> {
return new AttachmentsStore();
}
}

@ -4,7 +4,6 @@ import {
tap,
} from 'rxjs/operators';
import { Observable } from 'rxjs';
import { ID } from '@datorama/akita';
import { HttpClient } from '@angular/common/http';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
@ -16,14 +15,13 @@ import {
} from 'core-app/core/state/collection-store';
import { ICapability } from 'core-app/core/state/capabilities/capability.model';
import { CapabilitiesStore } from 'core-app/core/state/capabilities/capabilities.store';
import { CapabilitiesQuery } from 'core-app/core/state/capabilities/capabilities.query';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@Injectable()
export class CapabilitiesResourceService {
protected store = new CapabilitiesStore();
readonly query = new CapabilitiesQuery(this.store);
export class CapabilitiesResourceService extends ResourceCollectionService<ICapability> {
private get capabilitiesPath():string {
return this
.apiV3Service
@ -36,6 +34,7 @@ export class CapabilitiesResourceService {
private apiV3Service:ApiV3Service,
private toastService:ToastService,
) {
super();
}
fetchCapabilities(params:ApiV3ListParameters):Observable<IHALCollection<ICapability>> {
@ -53,7 +52,7 @@ export class CapabilitiesResourceService {
);
}
update(id:ID, project:Partial<ICapability>):void {
this.store.update(id, project);
protected createStore():CollectionStore<ICapability> {
return new CapabilitiesStore();
}
}

@ -82,3 +82,18 @@ export function insertCollectionIntoState<T extends { id:ID }>(
));
});
}
export function collectionFrom<T>(elements:T[]):IHALCollection<T> {
const count = elements.length;
return {
_type: 'Collection',
count,
total: count,
pageSize: count,
offset: 1,
_embedded: {
elements,
},
};
}

@ -28,10 +28,14 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { QueryEntity } from '@datorama/akita';
import { from, Observable } from 'rxjs';
import { from } from 'rxjs';
import {
catchError, groupBy, map, mergeMap, reduce, switchMap, tap,
catchError,
groupBy,
mergeMap,
reduce,
switchMap,
tap,
} from 'rxjs/operators';
import { IFileLink } from 'core-app/core/state/file-links/file-link.model';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
@ -39,15 +43,19 @@ import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { FileLinksStore } from 'core-app/core/state/file-links/file-links.store';
import { insertCollectionIntoState } from 'core-app/core/state/collection-store';
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@Injectable()
export class FileLinksResourceService {
private store = new FileLinksStore();
export class FileLinksResourceService extends ResourceCollectionService<IFileLink> {
constructor(
private readonly http:HttpClient,
private readonly toastService:ToastService,
) {}
) {
super();
}
updateCollectionsForWorkPackage(fileLinksSelfLink:string):void {
this.http
@ -79,13 +87,7 @@ export class FileLinksResourceService {
});
}
collection(key:string):Observable<IFileLink[]> {
const query = new QueryEntity(this.store);
return query
.select()
.pipe(
map((state) => state.collections[key]?.ids),
switchMap((fileLinkIds) => query.selectMany(fileLinkIds)),
);
protected createStore():CollectionStore<IFileLink> {
return new FileLinksStore();
}
}

@ -1,10 +0,0 @@
import { QueryEntity } from '@datorama/akita';
import { Observable } from 'rxjs';
import { IPrincipal } from './principal.model';
import { PrincipalsState } from './principals.store';
export class PrincipalsQuery extends QueryEntity<PrincipalsState> {
public byIds(ids:string[]):Observable<IPrincipal[]> {
return this.selectMany(ids);
}
}

@ -4,35 +4,29 @@ import {
tap,
} from 'rxjs/operators';
import { Observable } from 'rxjs';
import {
applyTransaction,
ID,
} from '@datorama/akita';
import { applyTransaction } from '@datorama/akita';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
import { HttpClient } from '@angular/common/http';
import { PrincipalsQuery } from 'core-app/core/state/principals/principals.query';
import { ApiV3ListParameters } from 'core-app/core/apiv3/paths/apiv3-list-resource.interface';
import {
collectionKey,
insertCollectionIntoState,
} from 'core-app/core/state/collection-store';
import {
EffectHandler,
} from 'core-app/core/state/effects/effect-handler.decorator';
import { EffectHandler } from 'core-app/core/state/effects/effect-handler.decorator';
import { ActionsService } from 'core-app/core/state/actions/actions.service';
import { PrincipalsStore } from './principals.store';
import { IPrincipal } from './principal.model';
import { IUser } from 'core-app/core/state/principals/user.model';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@EffectHandler
@Injectable()
export class PrincipalsResourceService {
protected store = new PrincipalsStore();
readonly query = new PrincipalsQuery(this.store);
export class PrincipalsResourceService extends ResourceCollectionService<IPrincipal> {
private get principalsPath():string {
return this
.apiV3Service
@ -45,7 +39,9 @@ export class PrincipalsResourceService {
private http:HttpClient,
private apiV3Service:ApiV3Service,
private toastService:ToastService,
) { }
) {
super();
}
fetchUser(id:string|number):Observable<IUser> {
return this.http
@ -78,37 +74,7 @@ export class PrincipalsResourceService {
);
}
update(id:ID, principal:Partial<IPrincipal>):void {
this.store.update(id, principal);
}
modifyCollection(params:ApiV3ListParameters, callback:(collection:ID[]) => ID[]):void {
const key = collectionKey(params);
this.store.update(({ collections }) => (
{
collections: {
...collections,
[key]: {
...collections[key],
ids: [...callback(collections[key]?.ids || [])],
},
},
}
));
}
removeFromCollection(params:ApiV3ListParameters, ids:ID[]):void {
const key = collectionKey(params);
this.store.update(({ collections }) => (
{
collections: {
...collections,
[key]: {
...collections[key],
ids: (collections[key]?.ids || []).filter((id) => !ids.includes(id)),
},
},
}
));
protected createStore():CollectionStore<IPrincipal> {
return new PrincipalsStore();
}
}

@ -27,32 +27,29 @@
//++
import { Injectable } from '@angular/core';
import { catchError, filter, tap } from 'rxjs/operators';
import {
catchError,
tap,
} from 'rxjs/operators';
import { Observable } from 'rxjs';
import { ID } from '@datorama/akita';
import { HttpClient } from '@angular/common/http';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
import { ProjectsQuery } from 'core-app/core/state/projects/projects.query';
import { ApiV3ListParameters } from 'core-app/core/apiv3/paths/apiv3-list-resource.interface';
import {
collectionKey,
insertCollectionIntoState,
} from 'core-app/core/state/collection-store';
import { ProjectsStore } from './projects.store';
import { IProject } from './project.model';
export function isIProject(input:IProject|undefined):input is IProject {
return input !== undefined;
}
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
import { ProjectsStore } from 'core-app/core/state/projects/projects.store';
@Injectable()
export class ProjectsResourceService {
protected store = new ProjectsStore();
readonly query = new ProjectsQuery(this.store);
export class ProjectsResourceService extends ResourceCollectionService<IProject> {
private get projectsPath():string {
return this
.apiV3Service
@ -65,6 +62,7 @@ export class ProjectsResourceService {
private apiV3Service:ApiV3Service,
private toastService:ToastService,
) {
super();
}
fetchProjects(params:ApiV3ListParameters):Observable<IHALCollection<IProject>> {
@ -91,9 +89,7 @@ export class ProjectsResourceService {
);
}
lookup(id:ID):Observable<IProject> {
return this.query
.selectEntity(id)
.pipe(filter(isIProject));
protected createStore():CollectionStore<IProject> {
return new ProjectsStore();
}
}

@ -74,6 +74,38 @@ export abstract class ResourceCollectionService<T> {
) as Observable<T>;
}
/**
* Lookup multiple entities from the store
*/
lookupMany(ids:ID[]):Observable<T[]> {
return this
.query
.selectMany(ids);
}
/**
* Lookup a single entity from the store
* @param id
*/
lookupMultiple(id:ID):Observable<T> {
return this
.query
.selectEntity(id)
.pipe(
filter((entity) => entity !== undefined),
) as Observable<T>;
}
/**
* Update a single entity in the store
*
* @param id The id to update
* @param entity A section of the entity to update
*/
update(id:ID, entity:Partial<T>):void {
this.store.update(id, entity);
}
/**
* Create a new instance of this resource service's underyling store.
* @protected

@ -28,42 +28,21 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { forkJoin, Observable } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { forkJoin } from 'rxjs';
import { IStorage } from 'core-app/core/state/storages/storage.model';
import { StoragesStore } from 'core-app/core/state/storages/storages.store';
import { StoragesQuery } from 'core-app/core/state/storages/storages.query';
import { insertCollectionIntoState } from 'core-app/core/state/collection-store';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
import { IHalResourceLink } from 'core-app/core/state/hal-resource';
export function isIStorage(input:IStorage|undefined):input is IStorage {
return input !== undefined;
}
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@Injectable()
export class StoragesResourceService {
private readonly store = new StoragesStore();
private readonly query = new StoragesQuery(this.store);
constructor(private readonly http:HttpClient) {}
collection(key:string):Observable<IStorage[]> {
return this
.query
.select()
.pipe(
map((state) => state.collections[key]?.ids),
switchMap((ids) => this.query.selectMany(ids)),
);
}
lookup(id:string):Observable<IStorage> {
return this
.query
.selectEntity(id)
.pipe(filter(isIStorage));
export class StoragesResourceService extends ResourceCollectionService<IStorage> {
constructor(private readonly http:HttpClient) {
super();
}
updateCollection(key:string, storageLinks:IHalResourceLink[]):void {
@ -74,4 +53,8 @@ export class StoragesResourceService {
insertCollectionIntoState(this.store, storageCollection, key);
});
}
protected createStore():CollectionStore<IStorage> {
return new StoragesStore();
}
}

@ -11,7 +11,10 @@ import {
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
import { HttpClient } from '@angular/common/http';
import { collectionKey } from 'core-app/core/state/collection-store';
import {
collectionKey,
insertCollectionIntoState,
} from 'core-app/core/state/collection-store';
import {
EffectHandler,
} from 'core-app/core/state/effects/effect-handler.decorator';
@ -22,14 +25,14 @@ import { IView } from 'core-app/core/state/views/view.model';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { ApiV3ListParameters } from 'core-app/core/apiv3/paths/apiv3-list-resource.interface';
import { addParamToHref } from 'core-app/shared/helpers/url-helpers';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
@EffectHandler
@Injectable()
export class ViewsResourceService {
protected store = new ViewsStore();
readonly query = new ViewsQuery(this.store);
export class ViewsResourceService extends ResourceCollectionService<IView> {
private get viewsPath():string {
return this
.apiV3Service
@ -43,6 +46,7 @@ export class ViewsResourceService {
private apiV3Service:ApiV3Service,
private toastService:ToastService,
) {
super();
}
fetchViews(params:ApiV3ListParameters):Observable<IHALCollection<IView>> {
@ -52,22 +56,7 @@ export class ViewsResourceService {
.http
.get<IHALCollection<IView>>(addParamToHref(this.viewsPath + collectionURL, { pageSize: '-1' }))
.pipe(
tap((events) => {
applyTransaction(() => {
this.store.upsertMany(events._embedded.elements);
this.store.update(({ collections }) => (
{
collections: {
...collections,
[collectionURL]: {
...collections[collectionURL],
ids: events._embedded.elements.map((el) => el.id),
},
},
}
));
});
}),
tap((collection) => insertCollectionIntoState(this.store, collection, collectionURL)),
catchError((error) => {
this.toastService.addError(error);
throw error;
@ -75,37 +64,7 @@ export class ViewsResourceService {
);
}
update(id:ID, view:Partial<IView>):void {
this.store.update(id, view);
}
modifyCollection(params:ApiV3ListParameters, callback:(collection:ID[]) => ID[]):void {
const key = collectionKey(params);
this.store.update(({ collections }) => (
{
collections: {
...collections,
[key]: {
...collections[key],
ids: [...callback(collections[key]?.ids || [])],
},
},
}
));
}
removeFromCollection(params:ApiV3ListParameters, ids:ID[]):void {
const key = collectionKey(params);
this.store.update(({ collections }) => (
{
collections: {
...collections,
[key]: {
...collections[key],
ids: (collections[key]?.ids || []).filter((id) => !ids.includes(id)),
},
},
}
));
protected createStore():CollectionStore<IView> {
return new ViewsStore();
}
}

@ -94,7 +94,7 @@ export class IanMenuComponent implements OnInit {
},
];
notificationsByProject$ = this.ianMenuService.query.notificationsByProject$.pipe(
notificationsByProject$ = this.ianMenuService.notificationsByProject$.pipe(
map((items) => items
.map((item) => ({
...item,
@ -110,7 +110,7 @@ export class IanMenuComponent implements OnInit {
})),
);
notificationsByReason$ = this.ianMenuService.query.notificationsByReason$.pipe(
notificationsByReason$ = this.ianMenuService.notificationsByReason$.pipe(
map((items) => this.reasonMenuItems.map((reason) => ({
...items.find((item) => item.value === reason.key),
...reason,

@ -1,54 +0,0 @@
import { Query } from '@datorama/akita';
import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
import { InAppNotificationsResourceService } from 'core-app/core/state/in-app-notifications/in-app-notifications.service';
import { ProjectsResourceService } from 'core-app/core/state/projects/projects.service';
import { IProject } from 'core-app/core/state/projects/project.model';
import { collectionKey } from 'core-app/core/state/collection-store';
import {
IanMenuState,
IanMenuStore,
} from './ian-menu.store';
export class IanMenuQuery extends Query<IanMenuState> {
projectsFilter$ = this.select('projectsFilter');
projectsForNotifications$ = combineLatest([
this.projectsFilter$,
this.projectsResourceService.query.select(),
]).pipe(
map(([filterParams, collectionData]) => {
const key = collectionKey(filterParams);
const collection = collectionData.collections[key];
const ids = collection?.ids || [];
return ids
.map((id:string) => this.projectsResourceService.query.getEntity(id))
.filter((item:IProject|undefined) => !!item) as IProject[];
}),
);
notificationsByProject$ = combineLatest([
this.select('notificationsByProject'),
this.projectsForNotifications$,
]).pipe(
map(([notifications, projects]) => notifications.map((notification) => {
const project = projects.find((p) => p.id.toString() === idFromLink(notification._links.valueLink[0].href));
return {
...notification,
projectHasParent: !!project?._links.parent.href,
};
})),
);
notificationsByReason$ = this.select('notificationsByReason');
constructor(
protected store:IanMenuStore,
protected resourceService:InAppNotificationsResourceService,
protected projectsResourceService:ProjectsResourceService,
) {
super(store);
}
}

@ -3,8 +3,8 @@ import {
Injector,
} from '@angular/core';
import {
notificationsMarkedRead,
notificationCountIncreased,
notificationsMarkedRead,
} from 'core-app/core/state/in-app-notifications/in-app-notifications.actions';
import {
EffectCallback,
@ -16,12 +16,18 @@ import { ApiV3ListParameters } from 'core-app/core/apiv3/paths/apiv3-list-resour
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
import { InAppNotificationsResourceService } from 'core-app/core/state/in-app-notifications/in-app-notifications.service';
import { ProjectsResourceService } from 'core-app/core/state/projects/projects.service';
import { IanMenuQuery } from './ian-menu.query';
import {
IanMenuStore,
IAN_MENU_PROJECT_FILTERS,
IAN_MENU_REASON_FILTERS,
IanMenuStore,
} from './ian-menu.store';
import { Query } from '@datorama/akita';
import {
map,
switchMap,
} from 'rxjs/operators';
import { collectionKey } from 'core-app/core/state/collection-store';
import { combineLatest } from 'rxjs';
@Injectable()
@EffectHandler
@ -30,7 +36,33 @@ export class IanMenuService {
readonly store = new IanMenuStore();
readonly query = new IanMenuQuery(this.store, this.ianResourceService, this.projectsResourceService);
readonly query = new Query(this.store);
projectsFilter$ = this.query.select('projectsFilter');
projectsForNotifications$ = this
.projectsFilter$
.pipe(
switchMap((filterParams) => {
const key = collectionKey(filterParams);
return this.projectsResourceService.collection(key);
}),
);
notificationsByProject$ = combineLatest([
this.query.select('notificationsByProject'),
this.projectsForNotifications$,
]).pipe(
map(([notifications, projects]) => notifications.map((notification) => {
const project = projects.find((p) => p.id.toString() === idFromLink(notification._links.valueLink[0].href));
return {
...notification,
projectHasParent: !!project?._links.parent.href,
};
})),
);
notificationsByReason$ = this.query.select('notificationsByReason');
constructor(
readonly injector:Injector,

@ -4,6 +4,7 @@ import {
} from '@angular/core';
import {
debounceTime,
defaultIfEmpty,
distinctUntilChanged,
map,
mapTo,
@ -85,7 +86,11 @@ export class IanCenterService extends UntilDestroyedMixin {
selectNotifications$:Observable<INotification[]> = this
.activeCollection$
.pipe(
switchMap((collection) => forkJoin(collection.ids.map((id) => this.resourceService.lookup(id)))),
switchMap((collection) => {
const lookupId = (id:ID) => this.resourceService.lookup(id).pipe(take(1));
return forkJoin(collection.ids.map(lookupId))
.pipe(defaultIfEmpty([]));
}),
);
aggregatedCenterNotifications$ = this

@ -266,7 +266,7 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit,
principals$ = this.principalIds$
.pipe(
this.untilDestroyed(),
mergeMap((ids:string[]) => this.principalsResourceService.query.byIds(ids)),
mergeMap((ids:string[]) => this.principalsResourceService.lookupMany(ids)),
debounceTime(50),
distinctUntilChanged((prev, curr) => prev.length === curr.length && prev.length === 0),
shareReplay(1),

@ -77,7 +77,9 @@ export class AttachmentListItemComponent implements OnInit {
ngOnInit():void {
const authorId = idFromLink(this.attachment._links.author.href);
this.author$ = this.principalsResourceService.query.selectEntity(authorId)
this.author$ = this
.principalsResourceService
.lookup(authorId)
.pipe(
switchMap((user) => (user ? of(user) : this.principalsResourceService.fetchUser(authorId))),
map((user) => user as IUser),

@ -37,7 +37,7 @@ import { HalResource } from 'core-app/features/hal/resources/hal-resource';
import { IAttachment } from 'core-app/core/state/attachments/attachment.model';
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
import { AttachmentsResourceService } from 'core-app/core/state/attachments/attachments.service';
import { map, switchMap, tap } from 'rxjs/operators';
import { tap } from 'rxjs/operators';
import isNewResource from 'core-app/features/hal/helpers/is-new-resource';
import { Observable } from 'rxjs';
@ -72,12 +72,11 @@ export class AttachmentListComponent extends UntilDestroyedMixin implements OnIn
this.attachmentsResourceService.requireCollection(this.attachmentsSelfLink);
}
this.$attachments = this.attachmentsResourceService.query.select()
this.$attachments = this
.attachmentsResourceService
.collection(this.collectionKey)
.pipe(
this.untilDestroyed(),
map((state) => state.collections[this.collectionKey]?.ids),
switchMap((attachmentIds) => this.attachmentsResourceService.query.selectMany(attachmentIds)),
// store attachments for new resources directly into the resource. This way, the POST request to create the
// resource embeds the attachments and the backend reroutes the anonymous attachments to the resource.
tap((attachments) => {

Loading…
Cancel
Save