37c1380b6a6856eea91f43b17784e976601782d4
[arvados-workbench2.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         const l = this.linkService.create({
27             // If this is for the all users group, it must be owned by
28             // the system user.
29             ownerUuid: (data.userUuid.substr(-22) === "-j7d0g-fffffffffffffff" ?
30                 data.userUuid.substr(0, 5) + "-tpzed-000000000000000"
31                 : data.userUuid),
32             tailUuid: data.userUuid,
33             headUuid: data.resource.uuid,
34             linkClass: LinkClass.STAR,
35             name: data.resource.name
36         });
37
38         if (data.userUuid.substr(-22) === "-j7d0g-fffffffffffffff") {
39             // If this is for the all users group, we need to create a
40             // permission link as well.
41             l.then(result =>
42                 this.linkService.create({
43                     tailUuid: data.userUuid,
44                     headUuid: result.uuid,
45                     linkClass: LinkClass.PERMISSION,
46                     name: "can_read"
47                 }));
48         }
49
50         return l;
51     }
52
53     delete(data: { userUuid: string; resourceUuid: string; }) {
54         return this.linkService
55             .list({
56                 filters: new FilterBuilder()
57                     .addEqual('tail_uuid', data.userUuid)
58                     .addEqual('head_uuid', data.resourceUuid)
59                     .addEqual('link_class', LinkClass.STAR)
60                     .getFilters()
61             })
62             .then(results => Promise.all(
63                 results.items.map(item => this.linkService.delete(item.uuid))));
64     }
65
66     list(userUuid: string, { filters, limit, offset, linkOrder, contentOrder }: FavoriteListArguments = {}): Promise<ListResults<GroupContentsResource>> {
67         const listFilters = new FilterBuilder()
68             .addEqual('owner_uuid', userUuid)
69             .addEqual('link_class', LinkClass.STAR)
70             .getFilters();
71
72         return this.linkService
73             .list({
74                 filters: joinFilters(filters || '', listFilters),
75                 limit,
76                 offset,
77                 order: linkOrder
78             })
79             .then(results => {
80                 const uuids = results.items.map(item => item.headUuid);
81                 return this.groupsService.contents(userUuid, {
82                     limit,
83                     offset,
84                     order: contentOrder,
85                     filters: new FilterBuilder().addIn('uuid', uuids).getFilters(),
86                     recursive: true
87                 });
88             });
89     }
90
91     checkPresenceInFavorites(userUuid: string, resourceUuids: string[]): Promise<Record<string, boolean>> {
92         return this.linkService
93             .list({
94                 filters: new FilterBuilder()
95                     .addIn("head_uuid", resourceUuids)
96                     .addEqual("tail_uuid", userUuid)
97                     .addEqual("link_class", LinkClass.STAR)
98                     .getFilters()
99             })
100             .then(({ items }) => resourceUuids.reduce((results, uuid) => {
101                 const isFavorite = items.some(item => item.headUuid === uuid);
102                 return { ...results, [uuid]: isFavorite };
103             }, {}));
104     }
105
106 }