[ARVADOS-WORKBENCH2] created: 1.2.0-636-g375bef1

Git user git at public.curoverse.com
Fri Oct 12 10:07:25 EDT 2018


        at  375bef1554bb6c85068608b7c8f6c69622c04323 (commit)


commit 375bef1554bb6c85068608b7c8f6c69622c04323
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Fri Oct 12 16:06:54 2018 +0200

    search-results-view
    
    Feature #14277
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --git a/src/routes/route-change-handlers.ts b/src/routes/route-change-handlers.ts
index af3bdab..ef9e9eb 100644
--- a/src/routes/route-change-handlers.ts
+++ b/src/routes/route-change-handlers.ts
@@ -4,10 +4,10 @@
 
 import { History, Location } from 'history';
 import { RootStore } from '~/store/store';
-import { matchProcessRoute, matchProcessLogRoute, matchProjectRoute, matchCollectionRoute, matchFavoritesRoute, matchTrashRoute, matchRootRoute, matchSharedWithMeRoute, matchRunProcessRoute, matchWorkflowRoute } from './routes';
+import { matchProcessRoute, matchProcessLogRoute, matchProjectRoute, matchCollectionRoute, matchFavoritesRoute, matchTrashRoute, matchRootRoute, matchSharedWithMeRoute, matchRunProcessRoute, matchWorkflowRoute, matchSearchResultsRoute } from './routes';
 import { loadProject, loadCollection, loadFavorites, loadTrash, loadProcess, loadProcessLog } from '~/store/workbench/workbench-actions';
 import { navigateToRootProject } from '~/store/navigation/navigation-action';
-import { loadSharedWithMe, loadRunProcess, loadWorkflow } from '../store/workbench/workbench-actions';
+import { loadSharedWithMe, loadRunProcess, loadWorkflow, loadSearchResults } from '~//store/workbench/workbench-actions';
 
 export const addRouteChangeHandlers = (history: History, store: RootStore) => {
     const handler = handleLocationChange(store);
@@ -23,6 +23,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
     const trashMatch = matchTrashRoute(pathname);
     const processMatch = matchProcessRoute(pathname);
     const processLogMatch = matchProcessLogRoute(pathname);
+    const searchResultsMatch = matchSearchResultsRoute(pathname);
     const sharedWithMeMatch = matchSharedWithMeRoute(pathname);
     const runProcessMatch = matchRunProcessRoute(pathname);
     const workflowMatch = matchWorkflowRoute(pathname);
@@ -47,5 +48,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
         store.dispatch(loadRunProcess);
     } else if (workflowMatch) {
         store.dispatch(loadWorkflow);
+    } else if (searchResultsMatch) {
+        store.dispatch(loadSearchResults);
     }
 };
diff --git a/src/routes/routes.ts b/src/routes/routes.ts
index 432cf75..34eea4f 100644
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@ -18,7 +18,8 @@ export const Routes = {
     PROCESS_LOGS: `/process-logs/:id(${RESOURCE_UUID_PATTERN})`,
     SHARED_WITH_ME: '/shared-with-me',
     RUN_PROCESS: '/run-process',
-    WORKFLOWS: '/workflows'
+    WORKFLOWS: '/workflows',
+    SEARCH_RESULTS: '/q'
 };
 
 export const getResourceUrl = (uuid: string) => {
@@ -72,3 +73,6 @@ export const matchRunProcessRoute = (route: string) =>
     
 export const matchWorkflowRoute = (route: string) =>
     matchPath<ResourceRouteParams>(route, { path: Routes.WORKFLOWS });
+
+export const matchSearchResultsRoute = (route: string) =>
+    matchPath<ResourceRouteParams>(route, { path: Routes.SEARCH_RESULTS });
diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index 59770cc..2f30e02 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -10,6 +10,7 @@ import { ServiceRepository } from '~/services/services';
 import { FilterBuilder } from "~/services/api/filter-builder";
 import { ResourceKind } from '~/models/resource';
 import { GroupClass } from '~/models/group';
+import { SearchView } from '~/store/search-bar/search-bar-reducer';
 
 export const searchBarActions = unionize({
     SET_CURRENT_VIEW: ofType<string>(),
@@ -67,6 +68,7 @@ export const deleteSavedQuery = (id: number) =>
 export const openSearchView = () =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
         dispatch(searchBarActions.OPEN_SEARCH_VIEW());
+        dispatch(searchBarActions.SET_CURRENT_VIEW(SearchView.BASIC));
         const savedSearchQueries = services.searchService.getSavedQueries();
         dispatch(searchBarActions.SET_SAVED_QUERIES(savedSearchQueries));
     };
diff --git a/src/store/search-bar/search-bar-reducer.ts b/src/store/search-bar/search-bar-reducer.ts
index ce2a77c..7e119d2 100644
--- a/src/store/search-bar/search-bar-reducer.ts
+++ b/src/store/search-bar/search-bar-reducer.ts
@@ -24,7 +24,7 @@ const initialState: SearchBar = {
     open: false,
     searchResults: [],
     searchValue: '',
-    savedQueries: ['']
+    savedQueries: []
 };
 
 export const searchBarReducer = (state = initialState, action: SearchBarActions): SearchBar =>
diff --git a/src/store/search-results-panel/search-results-middleware-service.ts b/src/store/search-results-panel/search-results-middleware-service.ts
new file mode 100644
index 0000000..2ae2dee
--- /dev/null
+++ b/src/store/search-results-panel/search-results-middleware-service.ts
@@ -0,0 +1,81 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ServiceRepository } from '~/services/services';
+import { MiddlewareAPI, Dispatch } from 'redux';
+import { DataExplorerMiddlewareService, dataExplorerToListParams, listResultsToDataExplorerItemsMeta } from '~/store/data-explorer/data-explorer-middleware-service';
+import { RootState } from '~/store/store';
+import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
+import { DataExplorer, getDataExplorer } from '~/store/data-explorer/data-explorer-reducer';
+import { updateResources } from '~/store/resources/resources-actions';
+import { FilterBuilder } from '~/services/api/filter-builder';
+import { SortDirection } from '~/components/data-table/data-column';
+import { SearchResultsPanelColumnNames } from '~/views/search-results-panel/search-results-panel-view';
+import { OrderDirection, OrderBuilder } from '~/services/api/order-builder';
+import { GroupContentsResource, GroupContentsResourcePrefix } from "~/services/groups-service/groups-service";
+import { ListResults } from '~/services/common-service/common-resource-service';
+import { searchResultsPanelActions } from '~/store/search-results-panel/search-results-panel-actions';
+
+export class SearchResultsMiddlewareService extends DataExplorerMiddlewareService {
+    constructor(private services: ServiceRepository, id: string) {
+        super(id);
+    }
+
+    async requestItems(api: MiddlewareAPI<Dispatch, RootState>) {
+        const state = api.getState();
+        const userUuid = state.auth.user!.uuid;
+        const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
+        try {
+            const response = await this.services.groupsService.contents(userUuid, getParams(dataExplorer));
+            api.dispatch(updateResources(response.items));
+            api.dispatch(setItems(response));
+        } catch {
+            api.dispatch(couldNotFetchWorkflows());
+        }
+    }
+}
+
+export const getParams = (dataExplorer: DataExplorer) => ({
+    ...dataExplorerToListParams(dataExplorer),
+    order: getOrder(dataExplorer),
+    filters: getFilters(dataExplorer)
+});
+
+export const getFilters = (dataExplorer: DataExplorer) => {
+    const filters = new FilterBuilder()
+        .addILike("name", dataExplorer.searchValue)
+        .getFilters();
+    return filters;
+};
+
+export const getOrder = (dataExplorer: DataExplorer) => {
+    const sortColumn = dataExplorer.columns.find(c => c.sortDirection !== SortDirection.NONE);
+    const order = new OrderBuilder<GroupContentsResource>();
+    if (sortColumn) {
+        const sortDirection = sortColumn && sortColumn.sortDirection === SortDirection.ASC
+            ? OrderDirection.ASC
+            : OrderDirection.DESC;
+        const columnName = sortColumn && sortColumn.name === SearchResultsPanelColumnNames.NAME ? "name" : "modifiedAt";
+        return order
+            .addOrder(sortDirection, columnName)
+            .addOrder(sortDirection, "name", GroupContentsResourcePrefix.COLLECTION)
+            .addOrder(sortDirection, "name", GroupContentsResourcePrefix.PROCESS)
+            .addOrder(sortDirection, "name", GroupContentsResourcePrefix.PROJECT)
+            .getOrder();
+    } else {
+    return order.getOrder();
+}
+};
+
+export const setItems = (listResults: ListResults<GroupContentsResource>) =>
+    searchResultsPanelActions.SET_ITEMS({
+        ...listResultsToDataExplorerItemsMeta(listResults),
+        items: listResults.items.map(resource => resource.uuid),
+    });
+
+const couldNotFetchWorkflows = () =>
+    snackbarActions.OPEN_SNACKBAR({
+        message: 'Could not fetch workflows.',
+        kind: SnackbarKind.ERROR
+    });
\ No newline at end of file
diff --git a/src/store/search-results-panel/search-results-panel-actions.ts b/src/store/search-results-panel/search-results-panel-actions.ts
new file mode 100644
index 0000000..05da5b3
--- /dev/null
+++ b/src/store/search-results-panel/search-results-panel-actions.ts
@@ -0,0 +1,16 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
+import { bindDataExplorerActions } from '~/store/data-explorer/data-explorer-action';
+
+export const SEARCH_RESULTS_PANEL_ID = "searchResultsPanel";
+export const searchResultsPanelActions = bindDataExplorerActions(SEARCH_RESULTS_PANEL_ID);
+
+export const loadSearchResultsPanel = () =>
+    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        dispatch(searchResultsPanelActions.REQUEST_ITEMS());
+    };
\ No newline at end of file
diff --git a/src/store/trash/trash-actions.ts b/src/store/trash/trash-actions.ts
index b59276c..92d0158 100644
--- a/src/store/trash/trash-actions.ts
+++ b/src/store/trash/trash-actions.ts
@@ -10,8 +10,8 @@ import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
 import { activateSidePanelTreeItem, loadSidePanelTreeProjects } from "~/store/side-panel-tree/side-panel-tree-actions";
 import { projectPanelActions } from "~/store/project-panel/project-panel-action";
 import { ResourceKind } from "~/models/resource";
-import { navigateToTrash } from '../navigation/navigation-action';
-import { matchTrashRoute, matchCollectionRoute } from '../../routes/routes';
+import { navigateToTrash } from '~/store/navigation/navigation-action';
+import { matchCollectionRoute } from '~/routes/routes';
 
 export const toggleProjectTrashed = (uuid: string, ownerUuid: string, isTrashed: boolean) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts
index bc2a9ed..1f31656 100644
--- a/src/store/workbench/workbench-actions.ts
+++ b/src/store/workbench/workbench-actions.ts
@@ -51,6 +51,8 @@ import { loadCollectionFiles } from '~/store/collection-panel/collection-panel-f
 import { SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { collectionPanelActions } from "~/store/collection-panel/collection-panel-action";
 import { CollectionResource } from "~/models/collection";
+import { searchResultsPanelActions, loadSearchResultsPanel } from '~/store/search-results-panel/search-results-panel-actions';
+import { searchResultsPanelColumns } from '~/views/search-results-panel/search-results-panel-view';
 
 export const WORKBENCH_LOADING_SCREEN = 'workbenchLoadingScreen';
 
@@ -84,6 +86,7 @@ export const loadWorkbench = () =>
                 dispatch(trashPanelActions.SET_COLUMNS({ columns: trashPanelColumns }));
                 dispatch(sharedWithMePanelActions.SET_COLUMNS({ columns: projectPanelColumns }));
                 dispatch(workflowPanelActions.SET_COLUMNS({ columns: workflowPanelColumns }));
+                dispatch(searchResultsPanelActions.SET_COLUMNS({ columns: searchResultsPanelColumns }));
                 dispatch<any>(initSidePanelTree());
                 if (router.location) {
                     const match = matchRootRoute(router.location.pathname);
@@ -373,6 +376,11 @@ export const loadWorkflow = handleFirstTimeLoad(async (dispatch: Dispatch<any>)
     dispatch(setSidePanelBreadcrumbs(SidePanelTreeCategory.WORKFLOWS));
 });
 
+export const loadSearchResults = handleFirstTimeLoad(
+    async (dispatch: Dispatch<any>) => {
+        await dispatch(loadSearchResultsPanel());
+    });
+
 const finishLoadingProject = (project: GroupContentsResource | string) =>
     async (dispatch: Dispatch<any>) => {
         const uuid = typeof project === 'string' ? project : project.uuid;
diff --git a/src/views-components/search-bar/search-bar-view.tsx b/src/views-components/search-bar/search-bar-view.tsx
index 59fe410..f394084 100644
--- a/src/views-components/search-bar/search-bar-view.tsx
+++ b/src/views-components/search-bar/search-bar-view.tsx
@@ -116,7 +116,7 @@ export const SearchBarView = withStyles(styles)(
 
         render() {
             const { classes, currentView, openSearchView, closeView, isPopoverOpen } = this.props;
-            return <ClickAwayListener onClickAway={() => closeView()}>
+            return <ClickAwayListener onClickAway={closeView}>
                 <Paper className={isPopoverOpen ? classes.containerSearchViewOpened : classes.container} >
                     <form onSubmit={this.handleSubmit}>
                         <Input
diff --git a/src/views/favorite-panel/favorite-panel.tsx b/src/views/favorite-panel/favorite-panel.tsx
index 4ba967c..948885f 100644
--- a/src/views/favorite-panel/favorite-panel.tsx
+++ b/src/views/favorite-panel/favorite-panel.tsx
@@ -30,7 +30,6 @@ import { navigateTo } from '~/store/navigation/navigation-action';
 import { ContainerRequestState } from "~/models/container-request";
 import { FavoritesState } from '../../store/favorites/favorites-reducer';
 import { RootState } from '~/store/store';
-import { PanelDefaultView } from '~/components/panel-default-view/panel-default-view';
 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
 
 type CssRules = "toolbar" | "button";
diff --git a/src/views/search-results-panel/search-results-panel-view.tsx b/src/views/search-results-panel/search-results-panel-view.tsx
new file mode 100644
index 0000000..2f1f889
--- /dev/null
+++ b/src/views/search-results-panel/search-results-panel-view.tsx
@@ -0,0 +1,128 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { SortDirection } from '~/components/data-table/data-column';
+import { DataColumns } from '~/components/data-table/data-table';
+import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
+import { ResourceKind } from '~/models/resource';
+import { ContainerRequestState } from '~/models/container-request';
+import { resourceLabel } from '~/common/labels';
+import { SearchBarAdvanceFormData } from '~/store/search-bar/search-bar-actions';
+import { SEARCH_RESULTS_PANEL_ID } from '~/store/search-results-panel/search-results-panel-actions';
+import { DataExplorer } from '~/views-components/data-explorer/data-explorer';
+import {
+    ProcessStatus,
+    ResourceFileSize,
+    ResourceLastModifiedDate,
+    ResourceName,
+    ResourceOwner,
+    ResourceType
+} from '~/views-components/data-explorer/renderers';
+
+export enum SearchResultsPanelColumnNames {
+    NAME = "Name",
+    PROJECT = "Project",
+    STATUS = "Status",
+    TYPE = 'Type',
+    OWNER = "Owner",
+    FILE_SIZE = "File size",
+    LAST_MODIFIED = "Last modified"
+}
+
+export interface SearchResultsPanelDataProps {
+    data: SearchBarAdvanceFormData;
+}
+
+export interface SearchResultsPanelActionProps {
+    onItemClick: (item: string) => void;
+    onContextMenu: (event: React.MouseEvent<HTMLElement>, item: string) => void;
+    onDialogOpen: (ownerUuid: string) => void;
+    onItemDoubleClick: (item: string) => void;
+}
+
+export type SearchResultsPanelProps = SearchResultsPanelDataProps & SearchResultsPanelActionProps;
+
+export interface WorkflowPanelFilter extends DataTableFilterItem {
+    type: ResourceKind | ContainerRequestState;
+}
+
+export const searchResultsPanelColumns: DataColumns<string, WorkflowPanelFilter> = [
+    {
+        name: SearchResultsPanelColumnNames.NAME,
+        selected: true,
+        configurable: true,
+        sortDirection: SortDirection.ASC,
+        filters: [],
+        render: (uuid: string) => <ResourceName uuid={uuid} />
+    },
+    {
+        name: SearchResultsPanelColumnNames.PROJECT,
+        selected: true,
+        configurable: true,
+        filters: [],
+        render: uuid => <ResourceName uuid={uuid} />
+    },
+    {
+        name: SearchResultsPanelColumnNames.STATUS,
+        selected: true,
+        configurable: true,
+        filters: [],
+        render: uuid => <ProcessStatus uuid={uuid} />
+    },
+    {
+        name: SearchResultsPanelColumnNames.TYPE,
+        selected: true,
+        configurable: true,
+        filters: [
+            {
+                name: resourceLabel(ResourceKind.COLLECTION),
+                selected: true,
+                type: ResourceKind.COLLECTION
+            },
+            {
+                name: resourceLabel(ResourceKind.PROCESS),
+                selected: true,
+                type: ResourceKind.PROCESS
+            },
+            {
+                name: resourceLabel(ResourceKind.PROJECT),
+                selected: true,
+                type: ResourceKind.PROJECT
+            }
+        ],
+        render: (uuid: string) => <ResourceType uuid={uuid} />,
+    },
+    {
+        name: SearchResultsPanelColumnNames.OWNER,
+        selected: true,
+        configurable: true,
+        filters: [],
+        render: uuid => <ResourceOwner uuid={uuid} />
+    },
+    {
+        name: SearchResultsPanelColumnNames.FILE_SIZE,
+        selected: true,
+        configurable: true,
+        filters: [],
+        render: uuid => <ResourceFileSize uuid={uuid} />
+    },
+    {
+        name: SearchResultsPanelColumnNames.LAST_MODIFIED,
+        selected: true,
+        configurable: true,
+        sortDirection: SortDirection.NONE,
+        filters: [],
+        render: uuid => <ResourceLastModifiedDate uuid={uuid} />
+    }
+];
+
+export const SearchResultsPanelView = (props: SearchResultsPanelProps) => {
+    return <DataExplorer
+        id={SEARCH_RESULTS_PANEL_ID}
+        onRowClick={props.onItemClick}
+        onRowDoubleClick={props.onItemDoubleClick}
+        onContextMenu={props.onContextMenu}
+        contextMenuColumn={true} />;
+};
\ No newline at end of file
diff --git a/src/views/search-results-panel/search-results-panel.tsx b/src/views/search-results-panel/search-results-panel.tsx
new file mode 100644
index 0000000..8b01ca3
--- /dev/null
+++ b/src/views/search-results-panel/search-results-panel.tsx
@@ -0,0 +1,47 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from "redux";
+import { connect } from "react-redux";
+import { navigateTo } from '~/store/navigation/navigation-action';
+import { SearchResultsPanelActionProps, SearchResultsPanelDataProps } from './search-results-panel-view';
+import { RootState } from '~/store/store';
+import { openContextMenu, resourceKindToContextMenuKind } from '~/store/context-menu/context-menu-actions';
+import { ResourceKind } from '~/models/resource';
+import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
+import { SearchResultsPanelView } from '~/views/search-results-panel/search-results-panel-view';
+
+const mapStateToProps = (state: RootState): SearchResultsPanelDataProps => ({
+    data: {
+        inTrash: false,
+        dataFrom: '',
+        dataTo: '',
+        saveQuery: false,
+        searchQuery: ''
+    }
+});
+
+const mapDispatchToProps = (dispatch: Dispatch): SearchResultsPanelActionProps => ({
+    onContextMenu: (event, resourceUuid) => {
+        const kind = resourceKindToContextMenuKind(resourceUuid);
+        if (kind) {
+            dispatch<any>(openContextMenu(event, {
+                name: '',
+                uuid: resourceUuid,
+                ownerUuid: '',
+                kind: ResourceKind.NONE,
+                menuKind: kind
+            }));
+        }
+    },
+    onDialogOpen: (ownerUuid: string) => { return; },
+    onItemClick: (resourceUuid: string) => {
+        dispatch<any>(loadDetailsPanel(resourceUuid));
+    },
+    onItemDoubleClick: uuid => {
+        dispatch<any>(navigateTo(uuid));
+    }
+});
+
+export const SearchResultsPanel = connect(mapStateToProps, mapDispatchToProps)(SearchResultsPanelView);
\ No newline at end of file
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index f26d50f..ade9a4e 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -41,10 +41,7 @@ import { SharedWithMePanel } from '~/views/shared-with-me-panel/shared-with-me-p
 import { RunProcessPanel } from '~/views/run-process-panel/run-process-panel';
 import SplitterLayout from 'react-splitter-layout';
 import { WorkflowPanel } from '~/views/workflow-panel/workflow-panel';
-import { HomeTreePicker } from '~/views-components/projects-tree-picker/home-tree-picker';
-import { SharedTreePicker } from '~/views-components/projects-tree-picker/shared-tree-picker';
-import { FavoritesTreePicker } from '../../views-components/projects-tree-picker/favorites-tree-picker';
-import { ProjectsTreePicker } from '~/views-components/projects-tree-picker/projects-tree-picker';
+import { SearchResultsPanel } from '~/views/search-results-panel/search-results-panel';
 
 type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
 
@@ -102,6 +99,7 @@ export const WorkbenchPanel =
                                 <Route path={Routes.SHARED_WITH_ME} component={SharedWithMePanel} />
                                 <Route path={Routes.RUN_PROCESS} component={RunProcessPanel} />
                                 <Route path={Routes.WORKFLOWS} component={WorkflowPanel} />
+                                <Route path={Routes.SEARCH_RESULTS} component={SearchResultsPanel} />
                             </Switch>
                         </Grid>
                     </Grid>
diff --git a/src/views/workflow-panel/workflow-panel-view.tsx b/src/views/workflow-panel/workflow-panel-view.tsx
index 57654bc..cccdce8 100644
--- a/src/views/workflow-panel/workflow-panel-view.tsx
+++ b/src/views/workflow-panel/workflow-panel-view.tsx
@@ -6,7 +6,7 @@ import * as React from 'react';
 import { DataExplorer } from "~/views-components/data-explorer/data-explorer";
 import { WorkflowIcon } from '~/components/icon/icon';
 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
-import { WORKFLOW_PANEL_ID, workflowPanelActions } from '~/store/workflow-panel/workflow-panel-actions';
+import { WORKFLOW_PANEL_ID } from '~/store/workflow-panel/workflow-panel-actions';
 import {
     ResourceLastModifiedDate,
     RosurceWorkflowName,

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list