Merge branch 'main' of git.arvados.org:arvados-workbench2 into 16073-process-io-panels
authorStephen Smith <stephen@curii.com>
Fri, 21 Oct 2022 14:14:28 +0000 (10:14 -0400)
committerStephen Smith <stephen@curii.com>
Fri, 21 Oct 2022 14:14:28 +0000 (10:14 -0400)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

1  2 
src/components/collection-panel-files/collection-panel-files.tsx
src/components/icon/icon.tsx
src/views-components/data-explorer/renderers.tsx
src/views-components/projects-tree-picker/generic-projects-tree-picker.tsx
yarn.lock

index 4f234743028f23cf2fd73464d3af2ad47e1a05f0,06c3504ac52400ee13e0592d6e64fd326ddf95eb..cf0b5e46e8b98f2f89dc9e5783a679736894bbcb
@@@ -154,8 -154,8 +154,8 @@@ const styles: StyleRulesCallback<CssRul
          marginTop: '-15px',
      },
      pathPanel: {
 -        padding: '1rem',
 -        marginBottom: '1rem',
 +        padding: '0.5rem',
 +        marginBottom: '0.5rem',
          backgroundColor: '#fff',
          boxShadow: '0px 1px 3px 0px rgb(0 0 0 / 20%), 0px 1px 1px 0px rgb(0 0 0 / 14%), 0px 2px 1px -1px rgb(0 0 0 / 12%)',
      },
      },
      leftPanel: {
          flex: 0,
 -        padding: '1rem',
 +        padding: '0 1rem 1rem',
          marginRight: '1rem',
          whiteSpace: 'nowrap',
          position: 'relative',
      rightPanel: {
          flex: '50%',
          padding: '1rem',
 -        paddingTop: '2rem',
 -        marginTop: '-1rem',
 +        paddingTop: '0.5rem',
 +        marginTop: '-0.5rem',
          position: 'relative',
          backgroundColor: '#fff',
          boxShadow: '0px 3px 3px 0px rgb(0 0 0 / 20%), 0px 3px 1px 0px rgb(0 0 0 / 14%), 0px 3px 1px -1px rgb(0 0 0 / 12%)',
@@@ -328,12 -328,7 +328,7 @@@ export const CollectionPanelFiles = wit
      const currentPDH = (collectionPanel.item || {}).portableDataHash;
      React.useEffect(() => {
          if (currentPDH) {
-             // Avoid fetching the same content level twice
-             if (leftKey !== rightKey) {
-                 fetchData([leftKey, rightKey], true);
-             } else {
-                 fetchData(rightKey, true);
-             }
+             fetchData([leftKey, rightKey], true);
          }
      }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps
  
                      : <div className={classes.rowEmpty}>No directories available</div>
                      }}
                  </AutoSizer>
-                 : <div className={classes.row}><CircularProgress className={classes.loader} size={30} /></div> }
+                 : <div data-cy="collection-loader" className={classes.row}><CircularProgress className={classes.loader} size={30} /></div> }
                  </div>
              </div>
              <div className={classes.rightPanel} data-cy="collection-files-right-panel">
index 6eda97dc778c312fadfa84375a439f3e473d7bdf,9ddc2aa2997c54a810b2e06df174916e37535d15..daa776a06c3b269d5f51dbbf2aec73400ec0fef1
@@@ -3,7 -3,7 +3,7 @@@
  // SPDX-License-Identifier: AGPL-3.0
  
  import React from 'react';
 -import { Badge, Tooltip } from '@material-ui/core';
 +import { Badge, SvgIcon, Tooltip } from '@material-ui/core';
  import Add from '@material-ui/icons/Add';
  import ArrowBack from '@material-ui/icons/ArrowBack';
  import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
@@@ -34,7 -34,6 +34,7 @@@ import Help from '@material-ui/icons/He
  import HelpOutline from '@material-ui/icons/HelpOutline';
  import History from '@material-ui/icons/History';
  import Inbox from '@material-ui/icons/Inbox';
 +import MoveToInbox from '@material-ui/icons/MoveToInbox';
  import Info from '@material-ui/icons/Info';
  import Input from '@material-ui/icons/Input';
  import InsertDriveFile from '@material-ui/icons/InsertDriveFile';
@@@ -44,6 -43,7 +44,6 @@@ import ListAlt from '@material-ui/icons
  import Menu from '@material-ui/icons/Menu';
  import MoreVert from '@material-ui/icons/MoreVert';
  import Mail from '@material-ui/icons/Mail';
 -import MoveToInbox from '@material-ui/icons/MoveToInbox';
  import Notifications from '@material-ui/icons/Notifications';
  import OpenInNew from '@material-ui/icons/OpenInNew';
  import People from '@material-ui/icons/People';
@@@ -59,8 -59,6 +59,6 @@@ import SettingsEthernet from '@material
  import Star from '@material-ui/icons/Star';
  import StarBorder from '@material-ui/icons/StarBorder';
  import Warning from '@material-ui/icons/Warning';
- import Visibility from '@material-ui/icons/Visibility';
- import VisibilityOff from '@material-ui/icons/VisibilityOff';
  import VpnKey from '@material-ui/icons/VpnKey';
  import LinkOutlined from '@material-ui/icons/LinkOutlined';
  import RemoveRedEye from '@material-ui/icons/RemoveRedEye';
@@@ -73,7 -71,6 +71,7 @@@ import ExitToApp from '@material-ui/ico
  import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
  import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline';
  import NotInterested from '@material-ui/icons/NotInterested';
 +import Image from '@material-ui/icons/Image';
  
  // Import FontAwesome icons
  import { library } from '@fortawesome/fontawesome-svg-core';
@@@ -86,6 -83,20 +84,20 @@@ library.add
      faEllipsisH,
  );
  
+ export const FreezeIcon = (props: any) =>
+     <span {...props}>
+         <span className='fas fa-snowflake' />
+     </span>
+ export const UnfreezeIcon = (props: any) =>
+     <div {...props}>
+         <div className="fa-layers fa-1x fa-fw">
+             <span className="fas fa-slash"
+                 data-fa-mask="fas fa-snowflake" data-fa-transform="down-1.5" />
+             <span className="fas fa-slash" />
+         </div>
+     </div>;
  export const PendingIcon = (props: any) =>
      <span {...props}>
          <span className='fas fa-ellipsis-h' />
@@@ -112,18 -123,6 +124,18 @@@ export const CollectionOldVersionIcon 
          </Badge>
      </Tooltip>;
  
 +// https://materialdesignicons.com/icon/image-off
 +export const ImageOffIcon = (props: any) =>
 +    <SvgIcon {...props}>
 +        <path d="M21 17.2L6.8 3H19C20.1 3 21 3.9 21 5V17.2M20.7 22L19.7 21H5C3.9 21 3 20.1 3 19V4.3L2 3.3L3.3 2L22 20.7L20.7 22M16.8 18L12.9 14.1L11 16.5L8.5 13.5L5 18H16.8Z" />
 +    </SvgIcon>;
 +
 +// https://materialdesignicons.com/icon/inbox-arrow-up
 +export const OutputIcon: IconType = (props: any) =>
 +    <SvgIcon {...props}>
 +        <path d="M14,14H10V11H8L12,7L16,11H14V14M16,11M5,15V5H19V15H15A3,3 0 0,1 12,18A3,3 0 0,1 9,15H5M19,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3" />
 +    </SvgIcon>;
 +
  export type IconType = React.SFC<{ className?: string, style?: object }>;
  
  export const AddIcon: IconType = (props) => <Add {...props} />;
@@@ -151,7 -150,7 +163,7 @@@ export const HelpIcon: IconType = (prop
  export const HelpOutlineIcon: IconType = (props) => <HelpOutline {...props} />;
  export const ImportContactsIcon: IconType = (props) => <ImportContacts {...props} />;
  export const InfoIcon: IconType = (props) => <Info {...props} />;
 -export const InputIcon: IconType = (props) => <InsertDriveFile {...props} />;
 +export const FileInputIcon: IconType = (props) => <InsertDriveFile {...props} />;
  export const KeyIcon: IconType = (props) => <VpnKey {...props} />;
  export const LogIcon: IconType = (props) => <SettingsEthernet {...props} />;
  export const MailIcon: IconType = (props) => <Mail {...props} />;
@@@ -161,7 -160,7 +173,7 @@@ export const MoveToIcon: IconType = (pr
  export const NewProjectIcon: IconType = (props) => <CreateNewFolder {...props} />;
  export const NotificationIcon: IconType = (props) => <Notifications {...props} />;
  export const OpenIcon: IconType = (props) => <OpenInNew {...props} />;
 -export const OutputIcon: IconType = (props) => <MoveToInbox {...props} />;
 +export const InputIcon: IconType = (props) => <MoveToInbox {...props} />;
  export const PaginationDownIcon: IconType = (props) => <ArrowDropDown {...props} />;
  export const PaginationLeftArrowIcon: IconType = (props) => <ChevronLeft {...props} />;
  export const PaginationRightArrowIcon: IconType = (props) => <ChevronRight {...props} />;
@@@ -184,8 -183,6 +196,6 @@@ export const SidePanelRightArrowIcon: I
  export const TrashIcon: IconType = (props) => <Delete {...props} />;
  export const UserPanelIcon: IconType = (props) => <Person {...props} />;
  export const UsedByIcon: IconType = (props) => <Folder {...props} />;
- export const VisibleIcon: IconType = (props) => <Visibility {...props} />;
- export const InvisibleIcon: IconType = (props) => <VisibilityOff {...props} />;
  export const WorkflowIcon: IconType = (props) => <Code {...props} />;
  export const WarningIcon: IconType = (props) => <Warning style={{ color: '#fbc02d', height: '30px', width: '30px' }} {...props} />;
  export const Link: IconType = (props) => <LinkOutlined {...props} />;
@@@ -203,4 -200,3 +213,4 @@@ export const LoginAsIcon: IconType = (p
  export const ActiveIcon: IconType = (props) => <CheckCircleOutline {...props} />;
  export const SetupIcon: IconType = (props) => <RemoveCircleOutline {...props} />;
  export const InactiveIcon: IconType = (props) => <NotInterested {...props} />;
 +export const ImageIcon: IconType = (props) => <Image {...props} />;
index 5d105577db9689c3f5b0da9c1f16220704485db2,e09160661b50a356422bc3d06a7e97434446573b..47e5b287ae7acb3fce265916da02964286b68748
@@@ -15,6 -15,7 +15,7 @@@ import 
  import { FavoriteStar, PublicFavoriteStar } from '../favorite-star/favorite-star';
  import { Resource, ResourceKind, TrashableResource } from 'models/resource';
  import {
+     FreezeIcon,
      ProjectIcon,
      FilterGroupIcon,
      CollectionIcon,
@@@ -59,6 -60,7 +60,7 @@@ import { openPermissionEditContextMenu 
  import { getUserUuid } from 'common/getuser';
  import { VirtualMachinesResource } from 'models/virtual-machines';
  import { CopyToClipboardSnackbar } from 'components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar';
+ import { ProjectResource } from 'models/project';
  
  const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
  
              <Typography variant="caption">
                  <FavoriteStar resourceUuid={item.uuid} />
                  <PublicFavoriteStar resourceUuid={item.uuid} />
+                 {
+                     item.kind === ResourceKind.PROJECT && <FrozenProject item={item} />
+                 }
              </Typography>
          </Grid>
      </Grid>;
  };
  
+ const FrozenProject = (props: {item: ProjectResource}) => {
+     const [fullUsername, setFullusername] = React.useState<any>(null);
+     const getFullName = React.useCallback(() => {
+         if (props.item.frozenByUuid) {
+             setFullusername(<UserNameFromID uuid={props.item.frozenByUuid} />);
+         }
+     }, [props.item, setFullusername])
+     if (props.item.frozenByUuid) {
+         return <Tooltip onOpen={getFullName} enterDelay={500} title={<span>Project was frozen by {fullUsername}</span>}>
+             <FreezeIcon style={{ fontSize: "inherit" }}/>
+         </Tooltip>;
+     } else {
+         return null;
+     }
+ }
  export const ResourceName = connect(
      (state: RootState, props: { uuid: string }) => {
          const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
@@@ -745,7 -768,7 +768,7 @@@ export const ResourceWithName = userFro
  
  export const UserNameFromID =
      compose(userFromID)(
-         (props: { uuid: string, userFullname: string, dispatch: Dispatch }) => {
+         (props: { uuid: string, displayAsText?: string, userFullname: string, dispatch: Dispatch }) => {
              const { uuid, userFullname, dispatch } = props;
  
              if (userFullname === '') {
@@@ -839,16 -862,6 +862,16 @@@ export const CollectionStatus = connect
          : <Typography>head version</Typography>
  );
  
 +export const CollectionName = connect((state: RootState, props: { uuid: string, className?: string }) => {
 +    return {
 +                collection: getResource<CollectionResource>(props.uuid)(state.resources),
 +                uuid: props.uuid,
 +                className: props.className,
 +            };
 +})((props: { collection: CollectionResource, uuid: string, className?: string }) =>
 +        <Typography className={props.className}>{props.collection?.name || props.uuid}</Typography>
 +);
 +
  export const ProcessStatus = compose(
      connect((state: RootState, props: { uuid: string }) => {
          return { process: getProcess(props.uuid)(state.resources) };
index 29c34e6726c5d993f964132351b7586a678c3307,d1c6fc6072c70ec8032623922e386c0904e78b97..dd6e63bfc87fd8d9a77f082e303bce94714554cc
@@@ -10,7 -10,7 +10,7 @@@ import { TreeItem, TreeItemStatus } fro
  import { ProjectResource } from "models/project";
  import { treePickerActions } from "store/tree-picker/tree-picker-actions";
  import { ListItemTextIcon } from "components/list-item-text-icon/list-item-text-icon";
 -import { ProjectIcon, InputIcon, IconType, CollectionIcon } from 'components/icon/icon';
 +import { ProjectIcon, FileInputIcon, IconType, CollectionIcon } from 'components/icon/icon';
  import { loadProject, loadCollection } from 'store/tree-picker/tree-picker-actions';
  import { GroupContentsResource } from 'services/groups-service/groups-service';
  import { CollectionDirectory, CollectionFile, CollectionFileType } from 'models/collection-file';
@@@ -66,7 -66,7 +66,7 @@@ const mapDispatchToProps = (dispatch: D
                  dispatch<any>(
                      data.kind === ResourceKind.COLLECTION
                          ? loadCollection(id, pickerId)
-                         : loadProject({ id, pickerId, includeCollections, includeFiles })
+                         : loadProject({ id, pickerId, includeCollections, includeFiles, options })
                  );
              } else if (!('type' in data) && loadRootItem) {
                  loadRootItem(item as TreeItem<ProjectsTreePickerRootItem>, pickerId, includeCollections, includeFiles, options);
@@@ -104,7 -104,7 +104,7 @@@ const getProjectPickerIcon = ({ data }
      } else if ('type' in data) {
          switch (data.type) {
              case CollectionFileType.FILE:
 -                return InputIcon;
 +                return FileInputIcon;
              default:
                  return ProjectIcon;
          }
diff --combined yarn.lock
index 64f25cc2e921d34644d2fad2d8b9a3a3cb10ec92,db7bf6ead1e30dba617cb653cd7cc9939e8d32af..924540208807fca8d7f7a489e8889919bddf28de
+++ b/yarn.lock
@@@ -3777,7 -3777,6 +3777,7 @@@ __metadata
      lodash.template: 4.5.0
      material-ui-pickers: ^2.2.4
      mem: 4.0.0
 +    mime: ^3.0.0
      moment: 2.29.1
      node-sass: ^4.9.4
      node-sass-chokidar: 1.5.0
    languageName: node
    linkType: hard
  
- "caniuse-lite@npm:1.0.30001299, caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001035, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001219":
+ "caniuse-lite@npm:1.0.30001299":
    version: 1.0.30001299
    resolution: "caniuse-lite@npm:1.0.30001299"
    checksum: c770f60ebf3e0cc8043ba4db0ebec12d7a595a6b50cb4437c3c5c55b04de9d2413f711f2828be761e8c37bb46b927a8abe6b199b8f0ffc1a34af0ebdee84be27
    languageName: node
    linkType: hard
  
+ "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001035, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001219":
+   version: 1.0.30001414
+   resolution: "caniuse-lite@npm:1.0.30001414"
+   checksum: 97210cfd15ded093b20c33d35bef9711a88402c3345411dad420c991a41a3e38ad17fd66721e8334c86e9b2e4aa2c1851d3631f1441afb73b92d93b2b8ca890d
+   languageName: node
+   linkType: hard
  "capture-exit@npm:^2.0.0":
    version: 2.0.0
    resolution: "capture-exit@npm:2.0.0"
    languageName: node
    linkType: hard
  
 +"mime@npm:^3.0.0":
 +  version: 3.0.0
 +  resolution: "mime@npm:3.0.0"
 +  bin:
 +    mime: cli.js
 +  checksum: f43f9b7bfa64534e6b05bd6062961681aeb406a5b53673b53b683f27fcc4e739989941836a355eef831f4478923651ecc739f4a5f6e20a76487b432bfd4db928
 +  languageName: node
 +  linkType: hard
 +
  "mimic-fn@npm:^1.0.0":
    version: 1.2.0
    resolution: "mimic-fn@npm:1.2.0"