Merge branch '19421-restore-old-redirect-key' into main. Closes #19421
[arvados.git] / src / services / favorite-service / favorite-service.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { LinkService } from "../link-service/link-service";
6 import { GroupsService, GroupContentsResource } from "../groups-service/groups-service";
7 import { LinkClass } from "models/link";
8 import { FilterBuilder, joinFilters } from "services/api/filter-builder";
9 import { ListResults } from 'services/common-service/common-service';
10
11 export interface FavoriteListArguments {
12     limit?: number;
13     offset?: number;
14     filters?: string;
15     linkOrder?: string;
16     contentOrder?: string;
17 }
18
19 export class FavoriteService {
20     constructor(
21         private linkService: LinkService,
22         private groupsService: GroupsService,
23     ) { }
24
25     create(data: { userUuid: string; resource: { uuid: string; name: string } }) {
26         return this.linkService.create({
27             ownerUuid: data.userUuid,
28             tailUuid: data.userUuid,
29             headUuid: data.resource.uuid,
30             linkClass: LinkClass.STAR,
31             name: data.resource.name
32         });
33     }
34
35     delete(data: { userUuid: string; resourceUuid: string; }) {
36         return this.linkService
37             .list({
38                 filters: new FilterBuilder()
39                     .addEqual('owner_uuid', data.userUuid)
40                     .addEqual('head_uuid', data.resourceUuid)
41                     .addEqual('link_class', LinkClass.STAR)
42                     .getFilters()
43             })
44             .then(results => Promise.all(
45                 results.items.map(item => this.linkService.delete(item.uuid))));
46     }
47
48     list(userUuid: string, { filters, limit, offset, linkOrder, contentOrder }: FavoriteListArguments = {}, showOnlyOwned: boolean = true): Promise<ListResults<GroupContentsResource>> {
49         const listFilters = new FilterBuilder()
50             .addEqual('owner_uuid', userUuid)
51             .addEqual('link_class', LinkClass.STAR)
52             .getFilters();
53
54         return this.linkService
55             .list({
56                 filters: joinFilters(filters || '', listFilters),
57                 limit,
58                 offset,
59                 order: linkOrder
60             })
61             .then(results => {
62                 const uuids = results.items.map(item => item.headUuid);
63                 return this.groupsService.contents(showOnlyOwned ? userUuid : '', {
64                     limit,
65                     offset,
66                     order: contentOrder,
67                     filters: new FilterBuilder().addIn('uuid', uuids).getFilters(),
68                     recursive: true
69                 });
70             });
71     }
72
73     checkPresenceInFavorites(userUuid: string, resourceUuids: string[]): Promise<Record<string, boolean>> {
74         return this.linkService
75             .list({
76                 filters: new FilterBuilder()
77                     .addIn("head_uuid", resourceUuids)
78                     .addEqual("owner_uuid", userUuid)
79                     .addEqual("link_class", LinkClass.STAR)
80                     .getFilters()
81             })
82             .then(({ items }) => resourceUuids.reduce((results, uuid) => {
83                 const isFavorite = items.some(item => item.headUuid === uuid);
84                 return { ...results, [uuid]: isFavorite };
85             }, {}));
86     }
87
88 }