Project

General

Profile

Actions

Feature #22159

open

Refactor Data-Explorer and renderers.tsx

Added by Lisa Knox 3 months ago. Updated about 21 hours ago.

Status:
In Progress
Priority:
Normal
Assigned To:
Category:
Workbench2
Target version:
Story points:
-

Description

Currently, the data-table is passed a list of UUIDs which are extracted from resources stored in the redux store. It then passes each UUID to a table row, which is then passed to renderer function for each column, which returns a connected react component that makes its own call to the redux store to get the specific value to be rendered. This adds unneeded complexity and unneeded computational overhead in extra calls to redux and extra react re-rendering checks. We should refactor so that there is one call to redux for each resource in the data table and each table cell calls a render function that only handles the styling, unless the specific contents require more complex logic to work.

Proposed steps:
  1. Convert data-table to accept an array of resource objects (as "items") instead of an array of UUIDs, and to pass each resource object (instead of the UUID) to each table row
  2. Go through each data-explorer and determine which table cells can be displayed as simple JSX vs those that must require a child component due to additional logic being necessary for rendering
  3. refactor the rendering functions to be as simple as possible, eliminating extra calls to the redux store and returning only JSX wherever possible

This should all be done with every intention of not changing what is visibly rendered to the user in any way. The result should be a faster First Contentful Paint on each render, making workbench as a whole feel snappier.


Subtasks 1 (1 open0 closed)

Task #22180: Review 22159-data-explorer-refactorIn ProgressStephen Smith12/20/2024Actions
Actions #1

Updated by Peter Amstutz 2 months ago

  • Target version changed from Development 2024-10-09 sprint to Development 2024-10-23 sprint
Actions #2

Updated by Peter Amstutz 2 months ago

  • Target version changed from Development 2024-10-23 sprint to Development 2024-11-06 sprint
Actions #3

Updated by Lisa Knox about 2 months ago

  • Status changed from New to In Progress
Actions #4

Updated by Peter Amstutz about 2 months ago

  • Target version changed from Development 2024-11-06 sprint to Development 2024-11-20
Actions #5

Updated by Lisa Knox about 1 month ago

22159-data-explorer-refactor @ a8f1f6be7f963739a078e609e4630559da8f0610

developer-run-tests-services-workbench2: #1360

  • ✅ All agreed upon points are implemented / addressed.
  • ✅ Anything not implemented (discovered or discussed during work) has a follow-up story.
    https://dev.arvados.org/issues/22300
    https://dev.arvados.org/issues/22328
  • ✅ Code is tested and passing, both automated and manual, what manual testing was done is described
    Manually tested by comparing each data table with the same table on main branch
  • - New or changed UX/UX and has gotten feedback from stakeholders.
    n/a
  • - Documentation has been updated.
    n/a
  • ✅ Behaves appropriately at the intended scale (describe intended scale).
    No changes to intended scale
  • ✅ Considered backwards and forwards compatibility issues between client and server.
    No changes
  • ✅ Follows our coding standards and GUI style guidelines.
Notes:
  • I took the opportunity to rearrange renderers.tsx for readability.
  • I was able to consolidate several render functions which did the same job (e.g. rendering a typography-wrapped string)
  • I also removed several functions in renderers.tsx that were not referenced anywhere else, so were unused
Actions #6

Updated by Peter Amstutz about 1 month ago

  • Target version changed from Development 2024-11-20 to Development 2024-12-04
Actions #7

Updated by Stephen Smith 25 days ago

Overall this looks good, although we didn't get significant performance gains, this simplifies the data flow so I think it's still valuable.

  • Since the store is no longer used externally by dispatchAction, it would be good to revert 0e105a4c12901b4f67536415faa38cd7276e6c02 to un-export the store
  • In data-table.tsx, the checkBoxColumn method has HTMLDivElement as the second type parameters, but I think it should be any since it's related to the resource type that the DataTable holds.
  • I noticed some of the circular dependency fixes were reverted - it seems one part was left behind as there are still 2 instances of COLLECTION_CREATE_FORM_NAME. If that fix was unnecessary, then the one in dialog-collection-create.tsx looks to be the stray extra and hopefully can be returned to importing the one from collection-create-actions.ts.
  • The dispatchWrapper in renderers doesn't seem to be doing much, and since we use connect()(...) in lots of places I think it would be good to just stick with that for any connected renderers
  • In data-explorer.tsx:L35 you can preserve the Resource type of resourceItems by using getResource<Resource> and .filter((resource): resource is Resource => !!resource) (or Boolean(resource) instead of !!resource if you prefer)
  • There are a couple remaining type casts in shared-with-me-columns.tsx line 79 and 93 and trash-panel.tsx:L112 that can be removed or moved to the parameter type.
  • In renderers:
    • renderFileSize, I think it would be better to set it to accept just resource: GroupContentsResource and check for the fileSizeTotal parameter using formatFileSize('fileSizeTotal' in resource ? resource.fileSizeTotal : undefined) that way the type narrowing to those that have fileSizeTotal is more explicit - as it is now I think the type intersection is telling TS to just assume everything has a fileSizeTotal field as the incoming types are GroupContentsResource which may or may not have that property - which works fine but doesn't seem as explicit that it may be undefined and doesn't get TS to type narrow to CollectionResource.
    • Same for renderFileCount which could be changed to accept resource: GroupContentsResource and use {'fileCount' in resource ? resource.fileCount : "-"}
    • Same for renderVersion which has a type parameter for CollectionResource, but the column is used for projects too so it could be changed to GroupContentsResource and use {'version' in resource ? resource.version : "-"}
    • For renderModifiedByUserUuid, it the data explorer isn't actually passing a Process but ContainerRequestResource, so accessing containerRequest doesn't do anything. You can just accept resource: GroupContentsResource which includes ContainerRequestResource and directly do return renderUuidWithCopy({uuid: resource.modifiedByUserUuid}); since the property is the same for all relevant types - this does seem to change behavior since the previous implementation (fetching the process from the store) didn't work for non-process resources, so this would be an improvement since the modified by user column is present on projects/collections but doesn't work currently and now it will
    • renderUsername and renderEmail can also use the param type item: UserResource to simplify it
  • There seems to be some misalignment with the onClick, onContextMenu, and onDoubleClick handlers and signatures - in data-table.tsx, only onDoubleClick calls the handler with the uuid while the others call the handler with the resource. In some places like the collection-content-address-panel.tsx the item click handler accepts a uuid, which makes the right side details panel on the content address panel not update when a row is clicked. I would suggest changing the onDoubleClick function passed to TableRow in data-table.tsx:L484 to pass the resource instead of UUID (and perhaps changing the renderBodyRow item signature to T since that allows us to make it more specific if that doesn't cause any other issues), and check all the implementation of click / context menu handlers to make sure they accept the correct resource type for that panel - for example in subprocess-panel-root.tsx the SubprocessPanelActionProps items should be ProcessResource and the handlers in subprocess-panel.tsx should be updated accordingly, similarly for workflow process panel root
  • In data-table.tsx renderBodyRow, isRowSelected should be accessing the uuid to check for selected since item is a resource
  • In root-project-details.tsx, the type of RootProject should probably be UserResource since that's the only type that can be passed in
  • This might be best as a stretch goal, but now that all data tables are given resources instead of UUID strings, it's not really necessary to use item: I | R as the type signature for the render method data-column.tsx:L27 as none of the renderers accept strings anymore, so that could be changed to just item: R - doing this will simplify the column renderers of each panel a lot since the inferred type of all the render method arguments won't be item: string | Resource but just item: Resource, which eliminates the need for type parameters on most of the render methods as the resource parameter will automatically match the DataColumn type (eg DataColumns<ProjectResource>).
    • Here begins a rabbit hole unfortunately, we should technically be able to remove I entirely from the interface on data-column.tsx:L14, so that DataColumn only has 1 type parameter - which we could rename to T as the only type parameter. I previously added the second type parameter to hold the type that the DataColumn is for, and is used to restrict the keys used in sort to fields of the resource type, so we can use the same type parameter for both since they should be the same. But this seems to cause a lot of pain since you have to convert all the uses of DataColumn replacing DataColumn<string, ResourceType> with DataColumn<ResourceType> and DataColumn<T, any> with DataColumn<T> (removing the any instead of T for example in data-explorer.tsx since T is used for onRowClick and should line up with the resource type and not the string type parameter that is currently passed in as the first type parameter). This seems to break the use of DataTable in DataExplorer.tsx as it seems to think the columns, onFilterChange, and onSortToggle use DataColumns<unknown> instead of DataColumns<T>.
    • If you are able to figure that out then it would be great to make that change, since currently, the string type of DataColumns<string, ResourceType> should cause the data table click callbacks to technically be typed to accept a string - I'm not sure why it doesn't complain though...
Actions #8

Updated by Peter Amstutz 17 days ago

  • Target version changed from Development 2024-12-04 to Development 2025-01-08
Actions #9

Updated by Lisa Knox 11 days ago

22159-data-explorer-refactor @ 547d90da9d890e15a47fcf643f3688c3d72c504a

developer-run-tests-services-workbench2: #1375

  • Since the store is no longer used externally by dispatchAction...

done

  • In data-table.tsx, the checkBoxColumn method has HTMLDivElement...

fixed

  • I noticed some of the circular dependency fixes were reverted...

done

  • The dispatchWrapper in renderers doesn't seem to be doing much...

I had planned to use this in 10+ places but only wound up using it in 4. Removed

  • In data-explorer.tsx:L35 you can preserve the Resource type...

Very cool, done

  • There are a couple remaining type casts...

These were necessary during the transition but should have been removed afterwards. removed

  • In renderers:
  • renderFileSize, I think it would be better to set it to accept...

Good call, done

  • Same for renderFileCount which could be changed...

done

  • Same for renderVersion which has a type parameter for CollectionResource...

I am a bit surprised the compiler didn't catch that, fixed

  • For renderModifiedByUserUuid, it the data explorer isn't actually passing a Process...

fixed

  • renderUsername and renderEmail can also use the param type item: UserResource to simplify it

done

  • There seems to be some misalignment with the onClick, onContextMenu, and onDoubleClick...

fixed

  • In data-table.tsx renderBodyRow, isRowSelected should be accessing the uuid...

done

  • In root-project-details.tsx, the type of RootProject should probably be UserResource...

done

  • This might be best as a stretch goal...
    • Here begins a rabbit hole unfortunately...
    • If you are able to figure that out...

Done, although with some finagling to keep the compiler happy

I removed most of the render param type annotations, except a few on panels that can pass different resource types

I also removed some unused prop and function declarations (for example, two of the panel roots had onDialogOpen types and definitions from 6 years ago that only returned undefined and were never passed to the DataExplorer, which would have been unable to accept them anyway)

Actions #10

Updated by Stephen Smith 9 days ago

  • In root-project-details.tsx you can avoid the cast to UserResource by changing the rootProject definition in RootProjectDetailsComponentDataProps to UserResource instead of any
  • We can go ahead and remove the commented out const in dialog-collection-create
  • In project-panel-data I think it would be good to keep the column types as ProjectResource | CollectionResource, that way the parameter for renderVersion includes CollectionResource - it doesn't complain since renderVersion is using a type guard but it's nice for TS to know that it's not always passing only a ProjectResource to it
  • Same thing for shared-with-me-columns.tsx using ProjectResource | CollectionResource, since shared with me has projects and collections
  • Some context menu handler things:
    • In views-components/data-explorer/data-explorer.tsx the onContextMenu signature has any as the item type, could that be Resource as well?
    • In api-client-authorization-root.tsx, the onContextMenu type is item: string, and in api-client-authorization-panel.tsx, the onContextMenu passes the item to openApiClientAuthorizationContextMenu when I think it should be taking the resource and passing the uuid
    • In search-results-panel-view.tsx, the onItemClick useCallback resource.uuid is passed to props.onItemClick which accepts a resource instead of a uuid, so clicking on search results rows doesn't work, it would be good to add GroupContentsResource type to the useCallback resource parameter as well so it isn't any.
    • In subprocess-panel-root the right click handler doesn't work because onContextMenu in the SubprocessPanelActionProps should be resource: ProcessResource, and the onContextMenu definition in subprocess-panel.tsx should also be adjusted to index the uuid
    • In user-panel.tsx the context menu doesn't work since the handleContextMenu should accept resource instead of uuid - you may be able to just remove this.handleContextMenu and replace directly with this.props.handleContextMenu which has the correct signature already
  • Great job with the generic types on DataTable and using extends DataTableItem, I think we could tighten that down a bit more by replacing DataTableItem with extends Resource, since anything with a UUID is probably a descendant of the Resource type and codifies that DataTables are designed around holding resources.
Actions #11

Updated by Lisa Knox 4 days ago

22159-data-explorer-refactor @ c97fdbba513112761b39edfb41df376a13c53c8e

developer-run-tests-services-workbench2: #1377

  • In root-project-details.tsx you can avoid the cast to UserResource...

done

  • We can go ahead and remove the commented out const in dialog-collection-create

fixed, sorry

  • In project-panel-data I think it would be good to keep the column types...

cool, done

  • Same thing for shared-with-me-columns.tsx...

It's easy to focus on what makes the compiler happy vs what represents what is actually happening. fixed

  • In views-components/data-explorer/data-explorer.tsx the onContextMenu signature has any as the item type, could that be Resource as well?

Yes, and I changed all of the types affected this way to their proper types as well, which addressed the following bullet points:

  • In api-client-authorization-root.tsx, the onContextMenu...
  • In search-results-panel-view.tsx...
  • In subprocess-panel-root...
  • In user-panel.tsx...
  • Great job with the generic types on DataTable and using extends DataTableItem...

That is so much cleaner, awesome

Actions #12

Updated by Stephen Smith 4 days ago

  • In views-components/data-explorer/data-explorer.tsx:L24 it looks like there is a redundant resource param
  • We might as well change ProcessResource to ContainerRequestResource or the other way around in workflow-processes-panel-root for consistency since they are the same - I don't really have an opinion on which one is clearer but using the same one within a single file is preferable
  • To keep things in alignment I think it would be good to use ProcessResource instead of Resource in subprocess-panel-root.tsx:L95
    • This causes a slight issue because in the same file onContextMenu uses a closure to access resources state, so I looked into it and it seems we can get rid of that closure since the only reason we need the state is to fetch the Process tuple (ContainerRequestResource and Container), but this is kind of redundant because this is only done to satisfy openProcessContextMenu, which only then just accesses the ContainerRequestResource again.
    • 3 of the 4 uses of openProcessContextMenu already start with the ContainerRequestResource anyway, and the 4th case in process-panel-root starts with the Process, so you can just access the containerRequest and pass that directly to onContextMenu. This also nicely eliminates unnecessary store access
    • Here's a diff that I think achieves this if this helps to illustrate what I mean:
      diff --git a/services/workbench2/src/store/context-menu/context-menu-actions.ts b/services/workbench2/src/store/context-menu/context-menu-actions.ts
      index acf4c29d6e..4bfc28ee3c 100644
      --- a/services/workbench2/src/store/context-menu/context-menu-actions.ts
      +++ b/services/workbench2/src/store/context-menu/context-menu-actions.ts
      @@ -11,12 +11,11 @@ import { getResource, getResourceWithEditableStatus } from "../resources/resourc
       import { UserResource } from "models/user";
       import { isSidePanelTreeCategory } from "store/side-panel-tree/side-panel-tree-actions";
       import { extractUuidKind, ResourceKind, EditableResource, Resource } from "models/resource";
      -import { Process, isProcessCancelable } from "store/processes/process";
      +import { isProcessCancelable } from "store/processes/process";
       import { RepositoryResource } from "models/repositories";
       import { SshKeyResource } from "models/ssh-key";
       import { VirtualMachinesResource } from "models/virtual-machines";
       import { KeepServiceResource } from "models/keep-services";
      -import { ProcessResource } from "models/process";
       import { CollectionResource } from "models/collection";
       import { GroupClass, GroupResource } from "models/group";
       import { GroupContentsResource } from "services/groups-service/groups-service";
      @@ -27,6 +26,7 @@ import { getProcess } from "store/processes/process";
       import { filterCollectionFilesBySelection } from "store/collection-panel/collection-panel-files/collection-panel-files-state";
       import { selectOne, deselectAllOthers } from "store/multiselect/multiselect-actions";
       import { ApiClientAuthorization } from "models/api-client-authorization";
      +import { ContainerRequestResource } from "models/container-request";
      
       export const contextMenuActions = unionize({
           OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition; resource: ContextMenuResource }>(),
      @@ -205,19 +205,18 @@ export const openSidePanelContextMenu = (event: React.MouseEvent<HTMLElement>, i
           }
       };
      
      -export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>, process: Process) => (dispatch: Dispatch, getState: () => RootState) => {
      -    const res = getResource<ProcessResource>(process.containerRequest.uuid)(getState().resources);
      -    if (res) {
      -        const menuKind = dispatch<any>(resourceUuidToContextMenuKind(res.uuid));
      +export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>, containerRequest: ContainerRequestResource) => (dispatch: Dispatch, getState: () =>
       RootState) => {
      +    if (containerRequest) {
      +        const menuKind = dispatch<any>(resourceUuidToContextMenuKind(containerRequest.uuid));
               dispatch<any>(
                   openContextMenu(event, {
      -                uuid: res.uuid,
      -                ownerUuid: res.ownerUuid,
      +                uuid: containerRequest.uuid,
      +                ownerUuid: containerRequest.ownerUuid,
                       kind: menuKind,
      -                name: res.name,
      -                description: res.description,
      -                outputUuid: res.outputUuid || "",
      -                workflowUuid: res.properties.template_uuid || "",
      +                name: containerRequest.name,
      +                description: containerRequest.description,
      +                outputUuid: containerRequest.outputUuid || "",
      +                workflowUuid: containerRequest.properties.template_uuid || "",
                       menuKind
                   })
               );
      diff --git a/services/workbench2/src/views/all-processes-panel/all-processes-panel.tsx b/services/workbench2/src/views/all-processes-panel/all-processes-panel.tsx
      index 6946f6d54f..1061641cb6 100644
      --- a/services/workbench2/src/views/all-processes-panel/all-processes-panel.tsx
      +++ b/services/workbench2/src/views/all-processes-panel/all-processes-panel.tsx
      @@ -30,7 +30,6 @@ import { ContainerRequestResource, ContainerRequestState } from "models/containe
       import { RootState } from "store/store";
       import { createTree } from "models/tree";
       import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from "store/resource-type-filters/resource-type-filters";
      -import { getProcess } from "store/processes/process";
       import { ResourcesState } from "store/resources/resources";
       import { toggleOne, deselectAllOthers } from "store/multiselect/multiselect-actions";
      
      @@ -127,9 +126,8 @@ export const AllProcessesPanel = withStyles(styles)(
           connect(mapStateToProps)(
               class extends React.Component<AllProcessesPanelProps> {
                   handleContextMenu = (event: React.MouseEvent<HTMLElement>, resource: ContainerRequestResource) => {
      -                const process = getProcess(resource.uuid)(this.props.resources);
                       if (process) {
      -                    this.props.dispatch<any>(openProcessContextMenu(event, process));
      +                    this.props.dispatch<any>(openProcessContextMenu(event, resource));
                       }
                       this.props.dispatch<any>(loadDetailsPanel(resource.uuid));
                   };
      diff --git a/services/workbench2/src/views/process-panel/process-panel-root.tsx b/services/workbench2/src/views/process-panel/process-panel-root.tsx
      index 3b5ca85f92..f0c749197e 100644
      --- a/services/workbench2/src/views/process-panel/process-panel-root.tsx
      +++ b/services/workbench2/src/views/process-panel/process-panel-root.tsx
      @@ -51,7 +51,7 @@ export interface ProcessPanelRootDataProps {
       }
      
       export interface ProcessPanelRootActionProps {
      -    onContextMenu: (event: React.MouseEvent<HTMLElement>, process: Process) => void;
      +    onContextMenu: (event: React.MouseEvent<HTMLElement>, containerRequest: ContainerRequestResource) => void;
           onToggle: (status: string) => void;
           cancelProcess: (uuid: string) => void;
           startProcess: (uuid: string) => void;
      @@ -137,7 +137,7 @@ export const ProcessPanelRoot = withStyles(styles)(({
                           data-cy="process-details">
                           <ProcessDetailsCard
                               process={process}
      -                        onContextMenu={event => props.onContextMenu(event, process)}
      +                        onContextMenu={event => props.onContextMenu(event, process.containerRequest)}
                               cancelProcess={props.cancelProcess}
                               startProcess={props.startProcess}
                               resumeOnHoldWorkflow={props.resumeOnHoldWorkflow}
      diff --git a/services/workbench2/src/views/process-panel/process-panel.tsx b/services/workbench2/src/views/process-panel/process-panel.tsx
      index f305290cc0..2a7ddbeca9 100644
      --- a/services/workbench2/src/views/process-panel/process-panel.tsx
      +++ b/services/workbench2/src/views/process-panel/process-panel.tsx
      @@ -57,9 +57,9 @@ const mapDispatchToProps = (dispatch: Dispatch): ProcessPanelRootActionProps =>
                   })
               );
           },
      -    onContextMenu: (event, process) => {
      -        if (process) {
      -            dispatch<any>(openProcessContextMenu(event, process));
      +    onContextMenu: (event, containerRequest) => {
      +        if (containerRequest) {
      +            dispatch<any>(openProcessContextMenu(event, containerRequest));
               }
           },
           onToggle: status => {
      diff --git a/services/workbench2/src/views/subprocess-panel/subprocess-panel-root.tsx b/services/workbench2/src/views/subprocess-panel/subprocess-panel-root.tsx
      index 54edeeec83..3514dd848f 100644
      --- a/services/workbench2/src/views/subprocess-panel/subprocess-panel-root.tsx
      +++ b/services/workbench2/src/views/subprocess-panel/subprocess-panel-root.tsx
      @@ -23,7 +23,6 @@ import { ArvadosTheme } from 'common/custom-theme';
       import { ProcessResource } from 'models/process';
       import { SubprocessProgressBar } from 'components/subprocess-progress-bar/subprocess-progress-bar';
       import { Process } from 'store/processes/process';
      -import { Resource } from 'models/resource';
      
       type CssRules = 'iconHeader' | 'cardHeader';
      
      @@ -92,7 +91,7 @@ export interface SubprocessPanelDataProps {
      
       export interface SubprocessPanelActionProps {
           onRowClick: (resource: ProcessResource) => void;
      -    onContextMenu: (event: React.MouseEvent<HTMLElement>, item: Resource, resources: ResourcesState) => void;
      +    onContextMenu: (event: React.MouseEvent<HTMLElement>, resource: ProcessResource) => void;
           onItemDoubleClick: (resource: ProcessResource) => void;
       }
      
      @@ -120,7 +119,7 @@ export const SubprocessPanelRoot = (props: SubprocessPanelProps & MPVPanelProps)
               id={SUBPROCESS_PANEL_ID}
               onRowClick={props.onRowClick}
               onRowDoubleClick={props.onItemDoubleClick}
      -        onContextMenu={(event, item) => props.onContextMenu(event, item, props.resources)}
      +        onContextMenu={props.onContextMenu}
               contextMenuColumn={false}
               defaultViewIcon={ProcessIcon}
               defaultViewMessages={DEFAULT_VIEW_MESSAGES}
      diff --git a/services/workbench2/src/views/subprocess-panel/subprocess-panel.tsx b/services/workbench2/src/views/subprocess-panel/subprocess-panel.tsx
      index 047e9dd4d6..ed049e5f24 100644
      --- a/services/workbench2/src/views/subprocess-panel/subprocess-panel.tsx
      +++ b/services/workbench2/src/views/subprocess-panel/subprocess-panel.tsx
      @@ -9,15 +9,13 @@ import { SubprocessPanelRoot, SubprocessPanelActionProps, SubprocessPanelDataPro
       import { RootState } from "store/store";
       import { navigateTo } from "store/navigation/navigation-action";
       import { loadDetailsPanel } from "store/details-panel/details-panel-action";
      -import { getProcess } from "store/processes/process";
       import { toggleOne, deselectAllOthers } from 'store/multiselect/multiselect-actions';
       import { ProcessResource } from "models/process";
      
       const mapDispatchToProps = (dispatch: Dispatch): SubprocessPanelActionProps => ({
      -    onContextMenu: (event, resource, resources) => {
      -        const process = getProcess(resource.uuid)(resources);
      -        if (process) {
      -            dispatch<any>(openProcessContextMenu(event, process));
      +    onContextMenu: (event, resource) => {
      +        if (resource) {
      +            dispatch<any>(openProcessContextMenu(event, resource));
               }
           },
           onRowClick: ({uuid}: ProcessResource) => {
      diff --git a/services/workbench2/src/views/workflow-panel/workflow-processes-panel-root.tsx b/services/workbench2/src/views/workflow-panel/workflow-processes-panel-root.tsx
      index 22eb04506f..65e95e4eb1 100644
      --- a/services/workbench2/src/views/workflow-panel/workflow-processes-panel-root.tsx
      +++ b/services/workbench2/src/views/workflow-panel/workflow-processes-panel-root.tsx
      @@ -21,7 +21,6 @@ import { WithStyles } from '@mui/styles';
       import withStyles from '@mui/styles/withStyles';
       import { ArvadosTheme } from 'common/custom-theme';
       import { ProcessResource } from 'models/process';
      -import { ContainerRequestResource } from 'models/container-request';
      
       type CssRules = 'iconHeader' | 'cardHeader';
      
      @@ -89,7 +88,7 @@ export interface WorkflowProcessesPanelDataProps {
      
       export interface WorkflowProcessesPanelActionProps {
           onItemClick: (resource: ProcessResource) => void;
      -    onContextMenu: (event: React.MouseEvent<HTMLElement>, process: ContainerRequestResource, resources: ResourcesState) => void;
      +    onContextMenu: (event: React.MouseEvent<HTMLElement>, resource: ProcessResource) => void;
           onItemDoubleClick: (resource: ProcessResource) => void;
       }
      
      @@ -117,7 +116,7 @@ export const WorkflowProcessesPanelRoot = (props: WorkflowProcessesPanelProps &
               id={WORKFLOW_PROCESSES_PANEL_ID}
               onRowClick={props.onItemClick}
               onRowDoubleClick={props.onItemDoubleClick}
      -        onContextMenu={(event, item: ContainerRequestResource) => props.onContextMenu(event, item, props.resources)}
      +        onContextMenu={props.onContextMenu}
               contextMenuColumn={false}
               defaultViewIcon={ProcessIcon}
               defaultViewMessages={DEFAULT_VIEW_MESSAGES}
      diff --git a/services/workbench2/src/views/workflow-panel/workflow-processes-panel.tsx b/services/workbench2/src/views/workflow-panel/workflow-processes-panel.tsx
      index 0a206b352c..8c821c1836 100644
      --- a/services/workbench2/src/views/workflow-panel/workflow-processes-panel.tsx
      +++ b/services/workbench2/src/views/workflow-panel/workflow-processes-panel.tsx
      @@ -9,15 +9,13 @@ import { WorkflowProcessesPanelRoot, WorkflowProcessesPanelActionProps, Workflow
       import { RootState } from "store/store";
       import { navigateTo } from "store/navigation/navigation-action";
       import { loadDetailsPanel } from "store/details-panel/details-panel-action";
      -import { getProcess } from "store/processes/process";
       import { toggleOne, deselectAllOthers } from 'store/multiselect/multiselect-actions';
       import { ContainerRequestResource } from "models/container-request";
      
       const mapDispatchToProps = (dispatch: Dispatch): WorkflowProcessesPanelActionProps => ({
      -    onContextMenu: (event, resource, resources) => {
      -        const process = getProcess(resource.uuid)(resources);
      -        if (process) {
      -            dispatch<any>(openProcessContextMenu(event, process));
      +    onContextMenu: (event, resource) => {
      +        if (resource) {
      +            dispatch<any>(openProcessContextMenu(event, resource));
               }
           },
           onItemClick: (resource: ContainerRequestResource) => {
      
      
Actions #13

Updated by Lisa Knox 1 day ago

22159-data-explorer-refactor @ cd1968daf90146629f0fdd8a54c3d4d2fc6103b4

developer-run-tests-services-workbench2: #1379

Done and done. I also removed the if statements from the onContextMenu declarations, because it is no longer possible for the resource passed to be falsey. I am really liking how much cleaner this is.

Actions

Also available in: Atom PDF