[arvados-workbench2] updated: 2.4.0-146-g5a2f4597

git repository hosting git at public.arvados.org
Thu Jun 30 10:42:21 UTC 2022


Summary of changes:
 cypress/integration/collection.spec.js             |  62 +++-
 cypress/integration/create-workflow.spec.js        |  16 +-
 cypress/integration/favorites.spec.js              |  14 +-
 cypress/integration/group-manage.spec.js           |   1 +
 cypress/integration/project.spec.js                |  49 ++-
 cypress/integration/search.spec.js                 |  22 ++
 cypress/integration/sharing.spec.js                |  50 ++-
 cypress/integration/side-panel.spec.js             |   1 -
 cypress/support/commands.js                        |  59 ++-
 package.json                                       |   3 +
 src/common/config.ts                               |   8 +
 src/common/labels.ts                               |   2 +
 src/common/redirect-to.test.ts                     |   8 +-
 src/common/redirect-to.ts                          |  57 ++-
 src/components/autocomplete/autocomplete.tsx       |   2 +-
 src/components/breadcrumbs/breadcrumbs.tsx         |   6 +-
 .../collection-panel-files.tsx                     | 401 +++++++++++----------
 src/components/data-explorer/data-explorer.tsx     |  10 +-
 .../data-table-default-view.tsx                    |   5 +-
 .../data-table-filters-popover.tsx                 |  64 ++--
 .../data-table-filters/data-table-filters-tree.tsx |  17 +-
 src/components/data-table/data-table.tsx           |  19 +-
 src/components/default-view/default-view.tsx       |   3 +-
 src/components/file-tree/file-thumbnail.tsx        |   2 +-
 src/components/file-tree/file-tree-item.tsx        |  66 +---
 src/components/file-tree/file-tree.tsx             |  57 ---
 src/components/tree/tree.tsx                       |   3 +
 src/index.tsx                                      |   2 +
 src/models/collection.ts                           |   1 +
 src/models/details.ts                              |   3 +-
 src/models/project.ts                              |   1 +
 src/models/tree.ts                                 |  15 +-
 src/models/user.test.ts                            |   2 +-
 src/models/user.ts                                 |  10 +-
 src/models/workflow.ts                             |   4 +-
 src/routes/route-change-handlers.ts                |   3 -
 .../api-client-authorization-service.test.ts       |  87 +++++
 .../api-client-authorization-service.ts            |  36 +-
 src/services/api/filter-builder.ts                 |   2 +-
 src/store/breadcrumbs/breadcrumbs-middleware.ts    |  21 ++
 .../collection-panel/collection-panel-action.ts    |  21 +-
 .../collection-panel-files-actions.ts              |  26 --
 .../collection-panel/collection-panel-reducer.ts   |   5 -
 src/store/collections/collection-update-actions.ts |   2 +-
 src/store/collections/collection-upload-actions.ts |   9 +-
 src/store/context-menu/context-menu-actions.ts     |   4 +-
 src/store/navigation/navigation-action.ts          |   7 +-
 src/store/processes/processes-actions.ts           |   5 +-
 .../resource-type-filters.test.ts                  |  45 ++-
 .../resource-type-filters/resource-type-filters.ts |  44 ++-
 .../run-process-panel-actions.test.ts              |  26 +-
 .../run-process-panel/run-process-panel-actions.ts |  17 +-
 src/store/sharing-dialog/sharing-dialog-actions.ts | 191 +++++-----
 .../side-panel-tree/side-panel-tree-actions.ts     |   2 -
 src/store/store.ts                                 |   2 +
 .../virtual-machines/virtual-machines-actions.ts   |  32 +-
 src/store/workbench/workbench-actions.ts           |  14 +-
 .../workflow-panel/workflow-panel-actions.test.ts  |   1 -
 src/store/workflow-panel/workflow-panel-actions.ts |  26 +-
 .../collection-panel-files.ts                      |  71 +---
 .../create-collection-properties-form.tsx          |   5 +-
 .../update-collection-properties-form.tsx          |   5 +-
 .../action-sets/workflow-action-set.ts             |  15 +
 .../actions/copy-to-clipboard-action.tsx           |   4 +-
 .../context-menu/actions/helpers.test.ts           |   4 +-
 .../context-menu/actions/helpers.ts                |   6 +-
 .../context-menu/actions/lock-action.tsx           |  14 +-
 src/views-components/context-menu/context-menu.tsx |   3 +-
 src/views-components/data-explorer/renderers.tsx   | 111 +++---
 .../details-panel/details-panel.tsx                |  15 +-
 .../details-panel/project-details.tsx              |  36 +-
 .../details-panel/workflow-details.tsx             |  87 +++++
 .../create-project-properties-form.tsx             |   5 +-
 .../update-project-properties-form.tsx             |   5 +-
 .../property-field-common.tsx                      |   1 +
 .../property-key-field.tsx                         |  10 +-
 .../resource-properties-form.tsx                   |   7 +-
 .../sharing-dialog/advanced-view-switch.tsx        |  25 --
 .../sharing-dialog/participant-select.tsx          |  15 +-
 .../sharing-dialog-component.test.tsx              |  71 ++++
 .../sharing-dialog/sharing-dialog-component.tsx    | 190 ++++++++--
 .../sharing-dialog/sharing-dialog-content.tsx      |  28 --
 .../sharing-dialog/sharing-dialog.tsx              |  77 ++--
 .../sharing-management-form-component.tsx          |   7 +-
 .../sharing-public-access-form-component.tsx       |   1 +
 .../sharing-dialog/sharing-public-access-form.tsx  |   5 +-
 .../sharing-dialog/sharing-urls-component.test.tsx |  72 ++++
 .../sharing-dialog/sharing-urls-component.tsx      |  95 +++++
 .../sharing-dialog/sharing-urls.tsx                |  53 +++
 .../sharing-dialog/visibility-level-select.tsx     |   1 +
 .../side-panel-button/side-panel-button.tsx        |   2 +-
 .../side-panel-tree/side-panel-tree.tsx            |   5 +-
 .../virtual-machines-dialog/add-login-dialog.tsx   |  41 ++-
 .../all-processes-panel/all-processes-panel.tsx    |   7 +-
 .../api-client-authorization-panel-root.tsx        |  11 +-
 .../collection-content-address-panel.tsx           |  11 +-
 src/views/collection-panel/collection-panel.tsx    |  45 +--
 src/views/favorite-panel/favorite-panel.tsx        |  10 +-
 .../group-details-panel/group-details-panel.tsx    |  97 ++---
 src/views/link-panel/link-panel-root.tsx           |  11 +-
 .../process-panel/process-details-attributes.tsx   |  28 +-
 src/views/project-panel/project-panel.tsx          |  11 +-
 .../public-favorites-panel.tsx                     |   9 +-
 .../{directory-input.tsx => project-input.tsx}     |  91 +++--
 .../run-process-panel/run-process-basic-form.tsx   |  16 +-
 .../run-process-panel/run-process-panel-root.tsx   |  55 +--
 .../run-process-panel/run-process-second-step.tsx  |  11 +-
 .../shared-with-me-panel/shared-with-me-panel.tsx  |   9 +-
 .../subprocess-panel/subprocess-panel-root.tsx     |  10 +-
 src/views/trash-panel/trash-panel.tsx              |   9 +-
 src/views/user-panel/user-panel.tsx                |   8 +-
 .../user-profile-panel/user-profile-panel-root.tsx |   8 +-
 .../workflow-panel/workflow-description-card.tsx   |  26 +-
 src/views/workflow-panel/workflow-panel-view.tsx   |   4 +-
 tools/arvados_config.yml                           |   1 +
 yarn.lock                                          |  91 ++++-
 116 files changed, 2108 insertions(+), 1236 deletions(-)
 delete mode 100644 src/components/file-tree/file-tree.tsx
 create mode 100644 src/services/api-client-authorization-service/api-client-authorization-service.test.ts
 create mode 100644 src/store/breadcrumbs/breadcrumbs-middleware.ts
 create mode 100644 src/views-components/context-menu/action-sets/workflow-action-set.ts
 create mode 100644 src/views-components/details-panel/workflow-details.tsx
 delete mode 100644 src/views-components/sharing-dialog/advanced-view-switch.tsx
 create mode 100644 src/views-components/sharing-dialog/sharing-dialog-component.test.tsx
 delete mode 100644 src/views-components/sharing-dialog/sharing-dialog-content.tsx
 create mode 100644 src/views-components/sharing-dialog/sharing-urls-component.test.tsx
 create mode 100644 src/views-components/sharing-dialog/sharing-urls-component.tsx
 create mode 100644 src/views-components/sharing-dialog/sharing-urls.tsx
 copy src/views/run-process-panel/inputs/{directory-input.tsx => project-input.tsx} (60%)

       via  5a2f4597393f94b9fa7984f4445d4b599c139f27 (commit)
       via  a672dd5efb4c8ef394f61a7e7a5e513f80bf1427 (commit)
       via  cb2699f27ab6ea2587b7842e28cbd0941ea03535 (commit)
       via  9876549a482c2c330143f5c9eebc8ab47cb8fa1d (commit)
       via  92bab47864916d852ef1c8f9579dafe8ae40f124 (commit)
       via  95bba613751af0c9371e15dc8d2d1612079a6fe5 (commit)
       via  52b5bb0ea3c28cd2095837fea61509a70eb792fb (commit)
       via  765f6475a53ac7e635b737642ef375459324a117 (commit)
       via  c21c6582a12fe3968e3ef3a4786de5dfacce3b18 (commit)
       via  6c42bd0ca04911ece6403af74852a1e34d483c8f (commit)
       via  4c0099ec3509061ca3f507658689bf3bba77e5ea (commit)
       via  7b94876543bd53cf2ab676e3f6dab0f9e4fffd3f (commit)
       via  5550460d7ca90ad69b325ec58897cb0d55210bca (commit)
       via  b7f56fcd62b9b91e6c806707a5fd12f03d88a92a (commit)
       via  67543767e81f22686d3216700813714349f15f49 (commit)
       via  e1e17729d024637f9f3392611c9a59dc31e5db23 (commit)
       via  9a59fad2b6a97af963728a5111395f9caa71802f (commit)
       via  24d11ff837843675b37f1a844152ca0e74a12dea (commit)
       via  65ad44ac98393e9e7a7f3da8732b536fc051cf51 (commit)
       via  ede9027245c18871358536ebf7d5e39a9291926f (commit)
       via  148f9fba3eede1027ceb07657c4c7eaaa244d6d8 (commit)
       via  16ac6823842cbb5fcc27903476e3ab673ebd7077 (commit)
       via  58800bbe6e474679dcfbc03735541a578280dd85 (commit)
       via  852a6a393297d03ca5259ddb6aa7aedff4a000ea (commit)
       via  10465af2a9575f004b8f516d8c74b50413531972 (commit)
       via  f0f1a84dcd35f11214f0c534f8490f6a4f648b48 (commit)
       via  05010c44073b52c0e414d180cfc21bae215c4d33 (commit)
       via  bc0466c49bb8adab2f162d05c83fb30ed005bd6d (commit)
       via  b3b92e78c7da8fc6a2f4db78746cbc10bb11cc86 (commit)
       via  f1e1967ba28a81ff43b7229dbee27dd5e0ba6c13 (commit)
       via  d892b953431e67c2c8df25c4387f2111b88b820f (commit)
       via  ed5eba6574a98f8acfe4f1fc0c063b9347b656c1 (commit)
       via  198ae2eb95d997550d1d647916b38bb8b3f536e9 (commit)
       via  00dd0a8f134729754f01f24f642fe82c08873dae (commit)
       via  e868a45a2a187dca9812c5e6e201503f3e427e08 (commit)
       via  970c338729ef7490f380b82c4a0acdb33a8fbe98 (commit)
       via  614e5664c62ac01307744e29072ca1804cb7e676 (commit)
       via  d6a28995f22dc04688444c0098b185717f7d4ed4 (commit)
       via  0721e16721a598a2d0eea501e7efd265219f134f (commit)
       via  555a6df1236e6c36a2552ee6100225c389f4c884 (commit)
       via  89a2555cc00f750dfa07dc57a2908059fc52c935 (commit)
       via  2903199054f8ac49ff15386fa576a0765032fa25 (commit)
       via  c69c6d43021b29186717ad30bea95cf50ee8c1e6 (commit)
       via  0537bee45712945bd97d28f6d28118f7589a6840 (commit)
       via  96fdc9e2e344e86378dd156593d8166f309ea1af (commit)
       via  bf6ffb898a38a806ea0dd98daca7b3801923b62f (commit)
       via  1a49d9366053df6119bf855d3bfcbc5373744101 (commit)
       via  d7f25e0db329c2fb8c2325f7ff28ce7a99cc2467 (commit)
       via  4ff4d54006bc6c619616f6fc229b4374c5d83879 (commit)
       via  e3064da256b0c0f78e97bfe53825a5c0bf11a4cb (commit)
       via  ea78e1afd181e1e6bf667cce24ad101e39d78b78 (commit)
       via  46c5d0d6ab1e39af6a8c12a7d620e0b03cde8a53 (commit)
       via  d1c2611350e47527730f6d3b226b998abf15a607 (commit)
       via  2d230988f0c91d088e68bc0aecb1fd91d52c1f1f (commit)
       via  851262322c7c5b35f4052b0351b77f190def77b0 (commit)
       via  2129d2a8fc553a0e89b374bdad2226ff3b3d377e (commit)
       via  6fbb4eca48ea5907887e61d60b60987cf2d1c8ca (commit)
       via  0bd774be1714eb7bb815cef3d44803eac6c735ec (commit)
       via  f912f003853b42c745041796220e28536629a548 (commit)
       via  8c5147b7367e994e897357766a85e9b7b8e28f24 (commit)
       via  ae6892150bb19c974d8af4cb323760f52a2ea19e (commit)
       via  d416c9aa7b70da4f8998792a42616b991d882f26 (commit)
       via  0e3d1681d9ed60bae0b91b368efb1325f5aee239 (commit)
       via  3c3d3d40033879249cd8e8f483f30cfa565d31bd (commit)
       via  cc9e1b294ee50dbb25d68e89538ac1a7a3643396 (commit)
       via  b375eb7f05d9862716f5c27ef8450043453c52ba (commit)
       via  015c7956121aceeade3d92243022c51e552d7a32 (commit)
       via  3c3126fed9f0d045644402b8ad4f6bc35a05db80 (commit)
       via  4f26fc6e11a411c11fc481b937c2e073f4858081 (commit)
       via  6cba13dd33c09ab8255b847aa4a614d3cf6eee8a (commit)
       via  d5fd29f0a82ca2df47b1b382f705a6df287f926e (commit)
       via  8dce1fa34833d40dad114eed8895fd5e6d7df28d (commit)
       via  056e5b954c34946428c2b9fcbc3c49c2670ec305 (commit)
       via  684419a1bede6b57e8c6bc384e1664b8ed73d930 (commit)
       via  66adcf8ab86e764a8829fbd604e27df53d6f24a1 (commit)
       via  709996fdd46c5993944753fab7919676e0cbd60d (commit)
       via  a4c96d2e98d9f2971e9268355bd31331c2b6a5e2 (commit)
       via  a51d9df296fa297f2b21201d497ed48b4639c8e9 (commit)
       via  f0ecfdc83d1807bfd81b285b76351e48db2ff992 (commit)
       via  07bcb7d7b574ce4dfd5d335618f683e6fb1c7d4f (commit)
       via  f55d7e31aa315de4eece3139c4fa1df7d6eb929e (commit)
       via  5124df4b34de48cdf5387197e7b728b7590e8ae8 (commit)
       via  4ee084a36d4adf2740f84875c47d81de566ec7b1 (commit)
       via  efda60590a2ed0942a8091d978d73fb047bd4a26 (commit)
       via  63539b816f355df818e4205d5da0b7b7416c9966 (commit)
       via  57e121908bd6a8767cb9e29288d71e51bf1c6911 (commit)
       via  add44b50131fc6a1e982a1af333f0e1f26803b3f (commit)
       via  282606d6586ed26675ef27f9f53cfeb0375dafc8 (commit)
       via  e239324108497e94222407d62b9c70ddffa42ab4 (commit)
       via  8e191ecaf0e507dd1d685ca3ebeab954652d8e9e (commit)
       via  a89c34e7cba3d8381302ff142c37e1a8b39ca80e (commit)
       via  9ec7a1bf9888c2e517c7f9e0bf595c70795d5da8 (commit)
       via  eb23ad3ba751b675858ef20ade568cd8c8688caa (commit)
       via  38e6956f75e723cf5c442188c0e570e282d04395 (commit)
       via  8da1b3425ad850194d473df1436ac61b6312d452 (commit)
       via  a4a67b0a5436effb92f682c6edb512700420c374 (commit)
       via  93926d5be6b62da8d8bedea1c9c3a63fd4e71b31 (commit)
       via  5248f137a53e981e6c6207c212688fbd08e2cdc9 (commit)
       via  d918b7408326b3d1193fc49c8049b5dbbc93a767 (commit)
       via  042f8362da7b7e835d2451169eecafc5ea4d258d (commit)
       via  7baacecfced2112da01ae9b9709109d63f4dfcc3 (commit)
      from  f1158a80eae96784f909ad496487f5604fe95329 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 5a2f4597393f94b9fa7984f4445d4b599c139f27
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Thu Jun 30 12:41:29 2022 +0200

    19153: Use server configuration
    
    Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>

diff --git a/cypress/integration/project.spec.js b/cypress/integration/project.spec.js
index 0ad8da56..26b4a150 100644
--- a/cypress/integration/project.spec.js
+++ b/cypress/integration/project.spec.js
@@ -338,7 +338,7 @@ describe('Project tests', function() {
             });
         });
 
-        it('should not be able to froze not owned project', () => {
+        it('should be able to froze not owned project', () => {
             cy.getAll('@adminProject').then(([adminProject]) => {
                 cy.loginAs(activeUser);
 
@@ -346,11 +346,7 @@ describe('Project tests', function() {
 
                 cy.get('main').contains(adminProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Freeze').click();
-
-                cy.get('main').contains(adminProject.name).rightclick();
-
-                cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
+                cy.get('[data-cy=context-menu]').contains('Freeze').should('not.exist');
             });
         });
 
diff --git a/src/common/config.ts b/src/common/config.ts
index 2954d704..574445df 100644
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@ -13,6 +13,9 @@ interface WorkbenchConfig {
 }
 
 export interface ClusterConfigJSON {
+    API: {
+        UnfreezeProjectRequiresAdmin: boolean
+    },
     ClusterID: string;
     RemoteClusters: {
         [key: string]: {
@@ -222,6 +225,9 @@ export const mapRemoteHosts = (clusterConfigJSON: ClusterConfigJSON, config: Con
 };
 
 export const mockClusterConfigJSON = (config: Partial<ClusterConfigJSON>): ClusterConfigJSON => ({
+    API: {
+        UnfreezeProjectRequiresAdmin: false,
+    },
     ClusterID: "",
     RemoteClusters: {},
     Services: {
diff --git a/src/models/project.ts b/src/models/project.ts
index b490864d..04dae4d2 100644
--- a/src/models/project.ts
+++ b/src/models/project.ts
@@ -6,6 +6,7 @@ import { GroupClass, GroupResource } from "./group";
 
 export interface ProjectResource extends GroupResource {
     frozenByUuid: null|string;
+    canManage: boolean;
     groupClass: GroupClass.PROJECT | GroupClass.FILTER | GroupClass.ROLE;
 }
 
diff --git a/src/views-components/context-menu/actions/lock-action.tsx b/src/views-components/context-menu/actions/lock-action.tsx
index 9e667630..785de583 100644
--- a/src/views-components/context-menu/actions/lock-action.tsx
+++ b/src/views-components/context-menu/actions/lock-action.tsx
@@ -11,13 +11,15 @@ import { ProjectResource } from "models/project";
 import { withRouter, RouteComponentProps } from "react-router";
 
 const mapStateToProps = (state: RootState, props: { onClick: () => {} }) => ({
-    isAdmin: state.auth.user!.isAdmin,
+    isAdmin: !!state.auth.user?.isAdmin,
     isLocked: !!(state.resources[state.contextMenu.resource!.uuid] as ProjectResource).frozenByUuid,
+    canManage: (state.resources[state.contextMenu.resource!.uuid] as ProjectResource).canManage,
+    canUnfreeze: !state.auth.remoteHostsConfig[state.auth.homeCluster]?.clusterConfig?.API?.UnfreezeProjectRequiresAdmin,
     onClick: props.onClick
 });
 
-export const ToggleLockAction = withRouter(connect(mapStateToProps)((props: { isLocked: boolean, isAdmin: boolean, onClick: () => void } & RouteComponentProps) =>
-    props.isLocked && !props.isAdmin ? null :
+export const ToggleLockAction = withRouter(connect(mapStateToProps)((props: { state: RootState, isAdmin: boolean, isLocked: boolean, canManage: boolean, canUnfreeze: boolean, onClick: () => void } & RouteComponentProps) =>
+    (props.canManage && !props.isLocked) || (props.isLocked && props.canManage && (props.canUnfreeze || props.isAdmin))  ? 
         < ListItem
             button
             onClick={props.onClick} >
@@ -31,4 +33,4 @@ export const ToggleLockAction = withRouter(connect(mapStateToProps)((props: { is
                     ? <>Unfreeze project</>
                     : <>Freeze project</>}
             </ListItemText>
-        </ListItem >));
+        </ListItem > : null));

commit a672dd5efb4c8ef394f61a7e7a5e513f80bf1427
Merge: 65ad44ac cb2699f2
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Thu Jun 23 14:36:25 2022 +0200

    Merge branch 'main' into 18692-frozen-projects-workbench-support
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>

diff --cc cypress/integration/project.spec.js
index 520ad26a,c4983e3e..0ad8da56
--- a/cypress/integration/project.spec.js
+++ b/cypress/integration/project.spec.js
@@@ -260,100 -278,4 +278,101 @@@ describe('Project tests', function() 
                  });
          });
      });
 +
 +    describe('Frozen projects', () => {
 +        beforeEach(() => {  
 +            cy.createGroup(activeUser.token, {
 +                name: `Main project ${Math.floor(Math.random() * 999999)}`,
 +                group_class: 'project',
 +            }).as('mainProject');
 +    
 +            cy.createGroup(adminUser.token, {
 +                name: `Admin project ${Math.floor(Math.random() * 999999)}`,
 +                group_class: 'project',
 +            }).as('adminProject').then((mainProject) => {
 +                cy.shareWith(adminUser.token, activeUser.user.uuid, mainProject.uuid, 'can_write');
 +            });
 +
 +            cy.get('@mainProject').then((mainProject) => {
 +                cy.createGroup(adminUser.token, {
 +                    name : `Sub project ${Math.floor(Math.random() * 999999)}`,
 +                    group_class: 'project',
 +                    owner_uuid: mainProject.uuid,
 +                }).as('subProject');
 +
 +                cy.createCollection(adminUser.token, {
 +                    name: `Main collection ${Math.floor(Math.random() * 999999)}`,
 +                    owner_uuid: mainProject.uuid,
 +                    manifest_text: "./subdir 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo\n. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
 +                }).as('mainCollection');        
 +            });
 +        });
 +
 +        it('should be able to froze own project', () => {
 +            cy.getAll('@mainProject').then(([mainProject]) => {
 +                cy.loginAs(activeUser);
 +
 +                cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 +
 +                cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').should('not.exist');
 +            });
 +        });
 +
 +        it('should not be able to modify items within the frozen project', () => {
 +            cy.getAll('@mainProject', '@mainCollection').then(([mainProject, mainCollection]) => {
 +                cy.loginAs(activeUser);
 +
 +                cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 +
 +                cy.get('[data-cy=project-panel]').contains(mainProject.name).click();
 +
 +                cy.get('[data-cy=project-panel]').contains(mainCollection.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Move to trash').should('not.exist');
 +            });
 +        });
 +
 +        it('should not be able to froze not owned project', () => {
 +            cy.getAll('@adminProject').then(([adminProject]) => {
 +                cy.loginAs(activeUser);
 +
 +                cy.get('[data-cy=side-panel-tree]').contains('Shared with me').click();
 +
 +                cy.get('main').contains(adminProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 +
 +                cy.get('main').contains(adminProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
 +            });
 +        });
 +
 +        it('should be able to unfroze project if user is an admin', () => {
 +            cy.getAll('@adminProject').then(([adminProject]) => {
 +                cy.loginAs(adminUser);
 +
 +                cy.get('main').contains(adminProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 +
 +                cy.wait(1000);
 +
 +                cy.get('main').contains(adminProject.name).rightclick();
 +
 +                cy.get('[data-cy=context-menu]').contains('Unfreeze').click();
 +
 +                cy.get('main').contains(adminProject.name).rightclick();
 +                
 +                cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
 +            });
 +        });
 +    });
- });
+ });
++
diff --cc src/index.tsx
index 4dde654c,03840d49..066b520c
--- a/src/index.tsx
+++ b/src/index.tsx
@@@ -100,14 -101,9 +101,15 @@@ addMenuActionSet(ContextMenuKind.GROUP_
  addMenuActionSet(ContextMenuKind.COLLECTION_ADMIN, collectionAdminActionSet);
  addMenuActionSet(ContextMenuKind.PROCESS_ADMIN, processResourceAdminActionSet);
  addMenuActionSet(ContextMenuKind.PROJECT_ADMIN, projectAdminActionSet);
 +addMenuActionSet(ContextMenuKind.FROZEN_PROJECT, [
 +    [
 +        ...frozenActionSet.reduce((prev, next) => prev.concat(next), []),
 +        ...readOnlyProjectActionSet.reduce((prev, next) => prev.concat(next), []),
 +    ]
 +]);
  addMenuActionSet(ContextMenuKind.FILTER_GROUP_ADMIN, filterGroupAdminActionSet);
  addMenuActionSet(ContextMenuKind.PERMISSION_EDIT, permissionEditActionSet);
+ addMenuActionSet(ContextMenuKind.WORKFLOW, workflowActionSet);
  
  storeRedirects();
  
diff --cc src/views-components/data-explorer/renderers.tsx
index 245a6597,7822bdc6..c955ebec
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@@ -755,9 -739,13 +762,13 @@@ const _resourceWithName 
              </Typography>;
          });
  
+ export const ResourceOwnerWithName = ownerFromResourceId(_resourceWithName);
+ 
+ export const ResourceWithName = userFromID(_resourceWithName);
+ 
  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 === '') {
diff --cc src/views/project-panel/project-panel.tsx
index f98f3a1a,ccb40d53..d9d14ae3
--- a/src/views/project-panel/project-panel.tsx
+++ b/src/views/project-panel/project-panel.tsx
@@@ -184,11 -180,9 +181,11 @@@ export const ProjectPanel = withStyles(
                          name: resource.name,
                          uuid: resource.uuid,
                          ownerUuid: resource.ownerUuid,
-                         isTrashed: ('isTrashed' in resource) ? resource.isTrashed: false,
+                         isTrashed: ('isTrashed' in resource) ? resource.isTrashed : false,
                          kind: resource.kind,
                          menuKind,
 +                        isAdmin,
 +                        isFrozen: resourceIsFrozen(resource, resources),
                          description: resource.description,
                          storageClassesDesired: (resource as CollectionResource).storageClassesDesired,
                          properties: ('properties' in resource) ? resource.properties : {},

commit 65ad44ac98393e9e7a7f3da8732b536fc051cf51
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Fri Jun 3 08:47:24 2022 +0200

    18692: added lock iton to the breadcrumbs
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>

diff --git a/cypress/integration/project.spec.js b/cypress/integration/project.spec.js
index 5929fb90..520ad26a 100644
--- a/cypress/integration/project.spec.js
+++ b/cypress/integration/project.spec.js
@@ -261,7 +261,7 @@ describe('Project tests', function() {
         });
     });
 
-    describe.only('Frozen projects', () => {
+    describe('Frozen projects', () => {
         beforeEach(() => {  
             cy.createGroup(activeUser.token, {
                 name: `Main project ${Math.floor(Math.random() * 999999)}`,
@@ -296,11 +296,11 @@ describe('Project tests', function() {
 
                 cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').click();
+                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 
                 cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').should('not.exist');
+                cy.get('[data-cy=context-menu]').contains('Freeze').should('not.exist');
             });
         });
 
@@ -310,7 +310,7 @@ describe('Project tests', function() {
 
                 cy.get('[data-cy=project-panel]').contains(mainProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').click();
+                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 
                 cy.get('[data-cy=project-panel]').contains(mainProject.name).click();
 
@@ -328,11 +328,11 @@ describe('Project tests', function() {
 
                 cy.get('main').contains(adminProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').click();
+                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 
                 cy.get('main').contains(adminProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').should('exist');
+                cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
             });
         });
 
@@ -342,17 +342,17 @@ describe('Project tests', function() {
 
                 cy.get('main').contains(adminProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Lock').click();
+                cy.get('[data-cy=context-menu]').contains('Freeze').click();
 
                 cy.wait(1000);
 
                 cy.get('main').contains(adminProject.name).rightclick();
 
-                cy.get('[data-cy=context-menu]').contains('Unlock').click();
+                cy.get('[data-cy=context-menu]').contains('Unfreeze').click();
 
                 cy.get('main').contains(adminProject.name).rightclick();
                 
-                cy.get('[data-cy=context-menu]').contains('Lock').should('exist');
+                cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
             });
         });
     });
diff --git a/src/components/breadcrumbs/breadcrumbs.tsx b/src/components/breadcrumbs/breadcrumbs.tsx
index 3d668856..c081c314 100644
--- a/src/components/breadcrumbs/breadcrumbs.tsx
+++ b/src/components/breadcrumbs/breadcrumbs.tsx
@@ -7,12 +7,13 @@ import { Button, Grid, StyleRulesCallback, WithStyles, Typography, Tooltip } fro
 import ChevronRightIcon from '@material-ui/icons/ChevronRight';
 import { withStyles } from '@material-ui/core';
 import { IllegalNamingWarning } from '../warning/warning';
-import { IconType } from 'components/icon/icon';
+import { IconType, LockIcon } from 'components/icon/icon';
 import grey from '@material-ui/core/colors/grey';
 
 export interface Breadcrumb {
     label: string;
     icon?: IconType;
+    isFrozen?: boolean;
 }
 
 type CssRules = "item" | "currentItem" | "label" | "icon";
@@ -63,6 +64,9 @@ export const Breadcrumbs = withStyles(styles)(
                             onClick={() => onClick(item)}
                             onContextMenu={event => onContextMenu(event, item)}>
                             <Icon className={classes.icon} />
+                            {
+                                item.isFrozen ? <LockIcon className={classes.icon} /> : null
+                            }
                             <Typography
                                 noWrap
                                 color="inherit"
diff --git a/src/store/breadcrumbs/breadcrumbs-middleware.ts b/src/store/breadcrumbs/breadcrumbs-middleware.ts
new file mode 100644
index 00000000..df8dd007
--- /dev/null
+++ b/src/store/breadcrumbs/breadcrumbs-middleware.ts
@@ -0,0 +1,21 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { propertiesActions } from "store/properties/properties-actions";
+import { BREADCRUMBS } from "./breadcrumbs-actions";
+
+export const breadcrumbsMiddleware = store => next => action => {
+    propertiesActions.match(action, {
+        SET_PROPERTY: () => {
+
+            if (action.payload.key === BREADCRUMBS && Array.isArray(action.payload.value)) {
+                action.payload.value = action.payload
+                    .value.map((value)=> ({ ...value, isFrozen: !!store.getState().resources[value.uuid]?.frozenByUuid }));
+            }
+
+            next(action);
+        },
+        default: () => next(action)
+    });
+};
diff --git a/src/store/store.ts b/src/store/store.ts
index 94f110a0..7bc28ff4 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -73,6 +73,7 @@ import { ALL_PROCESSES_PANEL_ID } from './all-processes-panel/all-processes-pane
 import { Config } from 'common/config';
 import { pluginConfig } from 'plugins';
 import { MiddlewareListReducer } from 'common/plugintypes';
+import { breadcrumbsMiddleware } from './breadcrumbs/breadcrumbs-middleware';
 
 declare global {
     interface Window {
@@ -174,6 +175,7 @@ export function configureStore(history: History, services: ServiceRepository, co
         publicFavoritesMiddleware,
         collectionsContentAddress,
         subprocessMiddleware,
+        breadcrumbsMiddleware,
     ];
 
     const reduceMiddlewaresFn: (a: Middleware[],
diff --git a/src/views-components/context-menu/actions/lock-action.tsx b/src/views-components/context-menu/actions/lock-action.tsx
index aa867ded..9e667630 100644
--- a/src/views-components/context-menu/actions/lock-action.tsx
+++ b/src/views-components/context-menu/actions/lock-action.tsx
@@ -28,7 +28,7 @@ export const ToggleLockAction = withRouter(connect(mapStateToProps)((props: { is
             </ListItemIcon>
             <ListItemText style={{ textDecoration: 'none' }}>
                 {props.isLocked
-                    ? <>Unlock project</>
-                    : <>Lock project</>}
+                    ? <>Unfreeze project</>
+                    : <>Freeze project</>}
             </ListItemText>
         </ListItem >));

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list