Merge branch '21705-go-deps-update-all'
[arvados.git] / services / workbench2 / src / views-components / context-menu / actions / file-viewer-actions.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from "react";
6 import { ListItemText, ListItem, ListItemIcon, Icon } from "@material-ui/core";
7 import { RootState } from 'store/store';
8 import { getNodeValue } from 'models/tree';
9 import { CollectionDirectory, CollectionFile, CollectionFileType } from 'models/collection-file';
10 import { FileViewerList, FileViewer } from 'models/file-viewers-config';
11 import { getFileViewers } from 'store/file-viewers/file-viewers-selectors';
12 import { connect } from 'react-redux';
13 import { OpenIcon } from 'components/icon/icon';
14
15 interface FileViewerActionProps {
16     fileUrl: string;
17     viewers: FileViewerList;
18 }
19
20 const mapStateToProps = (state: RootState): FileViewerActionProps => {
21     const { resource } = state.contextMenu;
22     if (resource) {
23         const file = getNodeValue(resource.uuid)(state.collectionPanelFiles);
24         if (file) {
25             const fileViewers = getFileViewers(state.properties);
26             return {
27                 fileUrl: file.url,
28                 viewers: fileViewers.filter(enabledViewers(file)),
29             };
30         }
31     }
32     return {
33         fileUrl: '',
34         viewers: [],
35     };
36 };
37
38 const enabledViewers = (file: CollectionFile | CollectionDirectory) =>
39     ({ extensions, collections }: FileViewer) => {
40         if (collections && file.type === CollectionFileType.DIRECTORY) {
41             return true;
42         } else if (extensions) {
43             return extensions.some(extension => file.name.endsWith(extension));
44         } else {
45             return true;
46         }
47     };
48
49 const fillViewerUrl = (fileUrl: string, { url, filePathParam }: FileViewer) => {
50     const viewerUrl = new URL(url);
51     viewerUrl.searchParams.append(filePathParam, fileUrl);
52     return viewerUrl.href;
53 };
54
55 export const FileViewerActions = connect(mapStateToProps)(
56     ({ fileUrl, viewers, onClick }: FileViewerActionProps & { onClick: () => void }) =>
57         <>
58             {viewers.map(viewer =>
59                 <ListItem
60                     button
61                     component='a'
62                     key={viewer.name}
63                     style={{ textDecoration: 'none' }}
64                     href={fillViewerUrl(fileUrl, viewer)}
65                     onClick={onClick}
66                     rel="noopener"
67                     target='_blank'>
68                     <ListItemIcon>
69                         {
70                             viewer.iconUrl
71                                 ? <Icon>
72                                     <img src={viewer.iconUrl} />
73                                 </Icon>
74                                 : <OpenIcon />
75                         }
76                     </ListItemIcon>
77                     <ListItemText>
78                         {viewer.name}
79                     </ListItemText>
80                 </ListItem>
81             )}
82         </>);