1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { unionize, ofType, UnionOf } from 'common/unionize';
6 import { extractUuidKind, Resource, ResourceWithProperties } from 'models/resource';
7 import { Dispatch } from 'redux';
8 import { RootState } from 'store/store';
9 import { ServiceRepository } from 'services/services';
10 import { getResourceService } from 'services/services';
11 import { addProperty, deleteProperty } from 'lib/resource-properties';
12 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
13 import { getResource } from './resources';
14 import { TagProperty } from 'models/tag';
16 export const resourcesActions = unionize({
17 SET_RESOURCES: ofType<Resource[]>(),
18 DELETE_RESOURCES: ofType<string[]>()
21 export type ResourcesAction = UnionOf<typeof resourcesActions>;
23 export const updateResources = (resources: Resource[]) => resourcesActions.SET_RESOURCES(resources);
25 export const deleteResources = (resources: string[]) => resourcesActions.DELETE_RESOURCES(resources);
27 export const loadResource = (uuid: string, showErrors?: boolean) =>
28 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
30 const kind = extractUuidKind(uuid);
31 const service = getResourceService(kind)(services);
33 const resource = await service.get(uuid, showErrors);
34 dispatch<any>(updateResources([resource]));
41 export const deleteResourceProperty = (uuid: string, key: string, value: string) =>
42 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
43 const { resources } = getState();
45 const rsc = getResource(uuid)(resources) as ResourceWithProperties;
48 const kind = extractUuidKind(uuid);
49 const service = getResourceService(kind)(services);
50 if (!service) { return; }
52 const properties = Object.assign({}, rsc.properties);
55 let updatedRsc = await service.update(
57 properties: deleteProperty(properties, key, value),
59 updatedRsc = {...rsc, ...updatedRsc};
60 dispatch<any>(updateResources([updatedRsc]));
61 dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Property has been successfully deleted.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
63 dispatch(snackbarActions.OPEN_SNACKBAR({ message: e.errors[0], hideDuration: 2000, kind: SnackbarKind.ERROR }));
67 export const createResourceProperty = (data: TagProperty) =>
68 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
69 const { uuid } = data;
70 const { resources } = getState();
72 const rsc = getResource(uuid)(resources) as ResourceWithProperties;
75 const kind = extractUuidKind(uuid);
76 const service = getResourceService(kind)(services);
77 if (!service) { return; }
80 const key = data.keyID || data.key;
81 const value = data.valueID || data.value;
82 const properties = Object.assign({}, rsc.properties);
83 let updatedRsc = await service.update(
85 properties: addProperty(properties, key, value),
88 updatedRsc = {...rsc, ...updatedRsc};
89 dispatch<any>(updateResources([updatedRsc]));
90 dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Property has been successfully added.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
92 const errorMsg = e.errors && e.errors.length > 0 ? e.errors[0] : "Error while adding property";
93 dispatch(snackbarActions.OPEN_SNACKBAR({ message: errorMsg, hideDuration: 2000, kind: SnackbarKind.ERROR }));