From: Stephen Smith Date: Thu, 11 May 2023 16:25:08 +0000 (-0400) Subject: Merge branch 'main' of git.arvados.org:arvados-workbench2 into 20377-dataexplorer... X-Git-Tag: 2.6.2~1^2~2 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/228200078ce8c5abd6bd2070fe89bdb6fbaa5d05?hp=1c3da825ed0a2c7ca95eb4bf91aebfe56109dd33 Merge branch 'main' of git.arvados.org:arvados-workbench2 into 20377-dataexplorer-paging-bug Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- diff --git a/cypress/integration/project.spec.js b/cypress/integration/project.spec.js index 68a90133..eff4d4e9 100644 --- a/cypress/integration/project.spec.js +++ b/cypress/integration/project.spec.js @@ -135,6 +135,7 @@ describe('Project tests', function() { }); }); cy.get('[data-cy=form-submit-btn]').click(); + cy.get('[data-cy=form-dialog]').should('not.exist'); const editProjectDescription = (name, type) => { cy.get('[data-cy=side-panel-tree]').contains('Home Projects').click(); @@ -545,7 +546,10 @@ describe('Project tests', function() { cy.get('[data-cy=form-submit-btn]').click(); }); cy.get('[data-cy=form-dialog]').should("not.exist"); + cy.get('[data-cy=snackbar]').contains('created'); + cy.get('[data-cy=snackbar]').should("not.exist"); cy.get('[data-cy=side-panel-tree]').contains('Projects').click(); + cy.waitForDom(); cy.get('[data-cy=project-panel]').contains(projectName).should('be.visible').rightclick(); cy.get('[data-cy=context-menu]').contains('Copy to clipboard').click(); cy.window().then((win) => ( diff --git a/package.json b/package.json index c17fc917..0a10da78 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "react-virtualized-auto-sizer": "1.0.2", "react-window": "1.8.5", "redux": "4.0.3", + "redux-devtools-extension": "^2.13.9", "redux-form": "7.4.2", "redux-thunk": "2.3.0", "reselect": "4.0.0", diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx index b75f3018..ddf30364 100644 --- a/src/components/collection-panel-files/collection-panel-files.tsx +++ b/src/components/collection-panel-files/collection-panel-files.tsx @@ -39,7 +39,7 @@ import { setCollectionFiles } from 'store/collection-panel/collection-panel-file import { sortBy } from 'lodash'; import { formatFileSize } from 'common/formatters'; import { getInlineFileUrl, sanitizeToken } from 'views-components/context-menu/actions/helpers'; -import { extractUuidObjectType, ResourceObjectType } from 'models/resource'; +import { extractUuidKind, ResourceKind } from 'models/resource'; export interface CollectionPanelFilesProps { isWritable: boolean; @@ -261,7 +261,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState const rightData = pathData[rightKey]; React.useEffect(() => { - if (props.currentItemUuid && extractUuidObjectType(props.currentItemUuid) == ResourceObjectType.COLLECTION) { + if (props.currentItemUuid && extractUuidKind(props.currentItemUuid) === ResourceKind.COLLECTION) { setPathData({}); setPath([props.currentItemUuid]); } diff --git a/src/routes/route-change-handlers.ts b/src/routes/route-change-handlers.ts index cded6d65..eef52058 100644 --- a/src/routes/route-change-handlers.ts +++ b/src/routes/route-change-handlers.ts @@ -11,6 +11,7 @@ import { dialogActions } from 'store/dialog/dialog-actions'; import { contextMenuActions } from 'store/context-menu/context-menu-actions'; import { searchBarActions } from 'store/search-bar/search-bar-actions'; import { pluginConfig } from 'plugins'; +import { openProjectPanel } from 'store/project-panel/project-panel-action'; export const addRouteChangeHandlers = (history: History, store: RootStore) => { const handler = handleLocationChange(store); @@ -60,7 +61,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => { } if (projectMatch) { - store.dispatch(WorkbenchActions.loadProject(projectMatch.params.id)); + store.dispatch(openProjectPanel(projectMatch.params.id)); } else if (collectionMatch) { store.dispatch(WorkbenchActions.loadCollection(collectionMatch.params.id)); } else if (favoriteMatch) { diff --git a/src/services/groups-service/groups-service.ts b/src/services/groups-service/groups-service.ts index cdbe8bab..fc603300 100644 --- a/src/services/groups-service/groups-service.ts +++ b/src/services/groups-service/groups-service.ts @@ -56,7 +56,7 @@ export class GroupsService< select: select ? JSON.stringify(select.map(sel => { const sp = sel.split("."); - return sp.length == 2 ? (sp[0] + "." + snakeCase(sp[1])) : snakeCase(sel); + return sp.length === 2 ? (sp[0] + "." + snakeCase(sp[1])) : snakeCase(sel); })) : undefined }; diff --git a/src/store/project-panel/project-panel-action.ts b/src/store/project-panel/project-panel-action.ts index 3b30f4aa..7ad18b67 100644 --- a/src/store/project-panel/project-panel-action.ts +++ b/src/store/project-panel/project-panel-action.ts @@ -7,6 +7,7 @@ import { bindDataExplorerActions } from "store/data-explorer/data-explorer-actio import { propertiesActions } from "store/properties/properties-actions"; import { RootState } from 'store/store'; import { getProperty } from "store/properties/properties"; +import { loadProject } from "store/workbench/workbench-actions"; export const PROJECT_PANEL_ID = "projectPanel"; export const PROJECT_PANEL_CURRENT_UUID = "projectPanelCurrentUuid"; @@ -14,7 +15,8 @@ export const IS_PROJECT_PANEL_TRASHED = 'isProjectPanelTrashed'; export const projectPanelActions = bindDataExplorerActions(PROJECT_PANEL_ID); export const openProjectPanel = (projectUuid: string) => - (dispatch: Dispatch) => { + async (dispatch: Dispatch) => { + await dispatch(loadProject(projectUuid)); dispatch(propertiesActions.SET_PROPERTY({ key: PROJECT_PANEL_CURRENT_UUID, value: projectUuid })); dispatch(projectPanelActions.RESET_EXPLORER_SEARCH_VALUE()); dispatch(projectPanelActions.REQUEST_ITEMS()); diff --git a/src/store/store.ts b/src/store/store.ts index 1501fd4f..ec673d62 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -77,17 +77,7 @@ import { MiddlewareListReducer } from 'common/plugintypes'; import { tooltipsMiddleware } from './tooltips/tooltips-middleware'; import { sidePanelReducer } from './side-panel/side-panel-reducer' import { bannerReducer } from './banner/banner-reducer'; - -declare global { - interface Window { - __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose; - } -} - -const composeEnhancers = - (process.env.NODE_ENV === 'development' && - window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || - compose; +import { composeWithDevTools } from 'redux-devtools-extension'; export type RootState = ReturnType>; @@ -187,7 +177,7 @@ export function configureStore(history: History, services: ServiceRepository, co middlewares = pluginConfig.middlewares.reduce(reduceMiddlewaresFn, middlewares); - const enhancer = composeEnhancers(applyMiddleware(redirectToMiddleware, ...middlewares)); + const enhancer = composeWithDevTools({/* options */ })(applyMiddleware(redirectToMiddleware, ...middlewares)); return createStore(rootReducer, enhancer); } diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts index 52433779..a3c3a096 100644 --- a/src/store/workbench/workbench-actions.ts +++ b/src/store/workbench/workbench-actions.ts @@ -13,7 +13,6 @@ import { } from 'store/favorite-panel/favorite-panel-action'; import { getProjectPanelCurrentUuid, - openProjectPanel, projectPanelActions, setIsProjectPanelTrashed, } from 'store/project-panel/project-panel-action'; @@ -866,7 +865,6 @@ const finishLoadingProject = (project: GroupContentsResource | string) => async (dispatch: Dispatch) => { const uuid = typeof project === 'string' ? project : project.uuid; - dispatch(openProjectPanel(uuid)); dispatch(loadDetailsPanel(uuid)); if (typeof project !== 'string') { dispatch(updateResources([project])); diff --git a/src/views/process-panel/process-io-card.tsx b/src/views/process-panel/process-io-card.tsx index 43be9240..c0dcb7f0 100644 --- a/src/views/process-panel/process-io-card.tsx +++ b/src/views/process-panel/process-io-card.tsx @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0 -import React, { ReactElement, useState } from 'react'; +import React, { ReactElement, memo, useState } from 'react'; import { Dispatch } from 'redux'; import { StyleRulesCallback, @@ -384,7 +384,7 @@ interface ProcessIOPreviewDataProps { type ProcessIOPreviewProps = ProcessIOPreviewDataProps & WithStyles; -const ProcessIOPreview = withStyles(styles)( +const ProcessIOPreview = memo(withStyles(styles)( ({ classes, data, showImagePreview, valueLabel }: ProcessIOPreviewProps) => { const showLabel = data.some((param: ProcessIOParameter) => param.label); return @@ -441,7 +441,7 @@ const ProcessIOPreview = withStyles(styles)( })}
; - }); + })); interface ProcessValuePreviewProps { value: ProcessIOValue; @@ -588,16 +588,16 @@ export const getIOParamDisplayValue = (auth: AuthState, input: CommandInputParam const fileArrayMainFiles = ((input as FileArrayCommandInputParameter).value || []); const firstMainFilePdh = (fileArrayMainFiles.length > 0 && fileArrayMainFiles[0]) ? getResourcePdhUrl(fileArrayMainFiles[0], pdh) : ""; - // Convert each main file into separate arrays of ProcessIOValue to preserve secondaryFile grouping - const fileArrayValues = fileArrayMainFiles.map((mainFile: File, i): ProcessIOValue[] => { - const secondaryFiles = ((mainFile as unknown) as FileWithSecondaryFiles)?.secondaryFiles || []; - return [ + // Convert each main and secondaryFiles into array of ProcessIOValue preserving ordering + let fileArrayValues: ProcessIOValue[] = []; + for(let i = 0; i < fileArrayMainFiles.length; i++) { + const secondaryFiles = ((fileArrayMainFiles[i] as unknown) as FileWithSecondaryFiles)?.secondaryFiles || []; + fileArrayValues.push( // Pass firstMainFilePdh to secondary files and every main file besides the first to hide pdh if equal - ...(mainFile ? [fileToProcessIOValue(mainFile, false, auth, pdh, i > 0 ? firstMainFilePdh : "")] : []), + ...(fileArrayMainFiles[i] ? [fileToProcessIOValue(fileArrayMainFiles[i], false, auth, pdh, i > 0 ? firstMainFilePdh : "")] : []), ...(secondaryFiles.map(file => fileToProcessIOValue(file, true, auth, pdh, firstMainFilePdh))) - ]; - // Reduce each mainFile/secondaryFile group into single array preserving ordering - }).reduce((acc: ProcessIOValue[], mainFile: ProcessIOValue[]) => (acc.concat(mainFile)), []); + ); + } return fileArrayValues.length ? fileArrayValues : diff --git a/yarn.lock b/yarn.lock index a60a7dec..20bbc46b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3811,6 +3811,7 @@ __metadata: react-window: 1.8.5 redux: 4.0.3 redux-devtools: 3.4.1 + redux-devtools-extension: ^2.13.9 redux-form: 7.4.2 redux-mock-store: 1.5.4 redux-thunk: 2.3.0 @@ -15448,6 +15449,15 @@ __metadata: languageName: node linkType: hard +"redux-devtools-extension@npm:^2.13.9": + version: 2.13.9 + resolution: "redux-devtools-extension@npm:2.13.9" + peerDependencies: + redux: ^3.1.0 || ^4.0.0 + checksum: 603d48fd6acf3922ef373b251ab3fdbb990035e90284191047b29d25b06ea18122bc4ef01e0704ccae495acb27ab5e47b560937e98213605dd88299470025db9 + languageName: node + linkType: hard + "redux-devtools-instrument@npm:^1.0.1": version: 1.10.0 resolution: "redux-devtools-instrument@npm:1.10.0"