From 304bc635e4c80f17cf65e4c52cb0d834f30205b8 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Thu, 11 Mar 2021 16:03:23 -0500 Subject: [PATCH] 17426: Can add plugin middlewares and context menus Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- src/common/plugintypes.ts | 6 +- src/models/link.ts | 5 +- src/plugins.tsx | 11 +-- .../context-menu/context-menu-actions.ts | 4 +- src/store/store.ts | 9 ++- .../form-fields/project-form-fields.tsx | 3 +- .../project-properties-dialog.tsx | 70 +++++++++---------- 7 files changed, 61 insertions(+), 47 deletions(-) diff --git a/src/common/plugintypes.ts b/src/common/plugintypes.ts index 00cc1e36..2ce0bb12 100644 --- a/src/common/plugintypes.ts +++ b/src/common/plugintypes.ts @@ -3,16 +3,18 @@ // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; -import { Dispatch } from 'redux'; +import { Dispatch, Middleware } from 'redux'; import { RootStore, RootState } from '~/store/store'; import { ResourcesState } from '~/store/resources/resources'; import { Location } from 'history'; +import { ServiceRepository } from "~/services/services"; export type ElementListReducer = (startingList: React.ReactElement[], itemClass?: string) => React.ReactElement[]; export type CategoriesListReducer = (startingList: string[]) => string[]; export type NavigateMatcher = (dispatch: Dispatch, getState: () => RootState, uuid: string) => boolean; export type LocationChangeMatcher = (store: RootStore, pathname: string) => boolean; export type EnableNew = (location: Location, currentItemId: string, currentUserUUID: string | undefined, resources: ResourcesState) => boolean; +export type MiddlewareListReducer = (startingList: Middleware[], services: ServiceRepository) => Middleware[]; export interface PluginConfig { // Customize the list of possible center panels by adding or removing Route components. @@ -42,4 +44,6 @@ export interface PluginConfig { enableNewButtonMatchers: EnableNew[]; newButtonMenuList: ElementListReducer[]; + + middlewares: MiddlewareListReducer[]; } diff --git a/src/models/link.ts b/src/models/link.ts index 785d531c..1c82fe58 100644 --- a/src/models/link.ts +++ b/src/models/link.ts @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { TagProperty } from "~/models/tag"; import { Resource, ResourceKind } from '~/models/resource'; export interface LinkResource extends Resource { @@ -12,7 +11,7 @@ export interface LinkResource extends Resource { tailKind: string; linkClass: string; name: string; - properties: TagProperty; + properties: any; kind: ResourceKind.LINK; } @@ -21,4 +20,4 @@ export enum LinkClass { TAG = 'tag', PERMISSION = 'permission', PRESET = 'preset', -} \ No newline at end of file +} diff --git a/src/plugins.tsx b/src/plugins.tsx index a7d033dd..1880e62d 100644 --- a/src/plugins.tsx +++ b/src/plugins.tsx @@ -15,15 +15,18 @@ export const pluginConfig: PluginConfig = { appBarRight: undefined, accountMenuList: [], enableNewButtonMatchers: [], - newButtonMenuList: [] + newButtonMenuList: [], + middlewares: [] }; // Starting here, import and register your Workbench 2 plugins. // // import { register as blankUIPluginRegister } from '~/plugins/blank/index'; -import { register as examplePluginRegister, routePath as exampleRoutePath } from '~/plugins/example/index'; +import { register as sampleTrackerPluginRegister } from '~/plugins/sample-tracker/index'; +import { studyListRoutePath } from '~/plugins/sample-tracker/studyList'; +// import { register as examplePluginRegister, routePath as exampleRoutePath } from '~/plugins/example/index'; import { register as rootRedirectRegister } from '~/plugins/root-redirect/index'; // blankUIPluginRegister(pluginConfig); -examplePluginRegister(pluginConfig); -rootRedirectRegister(pluginConfig, exampleRoutePath); +sampleTrackerPluginRegister(pluginConfig); +rootRedirectRegister(pluginConfig, studyListRoutePath); diff --git a/src/store/context-menu/context-menu-actions.ts b/src/store/context-menu/context-menu-actions.ts index 83335f83..1997b2a6 100644 --- a/src/store/context-menu/context-menu-actions.ts +++ b/src/store/context-menu/context-menu-actions.ts @@ -34,7 +34,7 @@ export type ContextMenuResource = { ownerUuid: string; description?: string; kind: ResourceKind, - menuKind: ContextMenuKind; + menuKind: ContextMenuKind | string; isTrashed?: boolean; isEditable?: boolean; outputUuid?: string; @@ -167,7 +167,7 @@ export const openProjectContextMenu = (event: React.MouseEvent, res kind: res.kind, menuKind, ownerUuid: res.ownerUuid, - isTrashed: ('isTrashed' in res) ? res.isTrashed: false, + isTrashed: ('isTrashed' in res) ? res.isTrashed : false, })); } }; diff --git a/src/store/store.ts b/src/store/store.ts index 517368aa..f236d029 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -70,6 +70,8 @@ import { SubprocessMiddlewareService } from '~/store/subprocess-panel/subprocess import { SUBPROCESS_PANEL_ID } from '~/store/subprocess-panel/subprocess-panel-actions'; import { ALL_PROCESSES_PANEL_ID } from './all-processes-panel/all-processes-panel-action'; import { Config } from '~/common/config'; +import { pluginConfig } from '~/plugins'; +import { MiddlewareListReducer } from '~/common/plugintypes'; const composeEnhancers = (process.env.NODE_ENV === 'development' && @@ -142,7 +144,7 @@ export function configureStore(history: History, services: ServiceRepository, co return next(action); }; - const middlewares: Middleware[] = [ + let middlewares: Middleware[] = [ routerMiddleware(history), thunkMiddleware.withExtraArgument(services), authMiddleware(services), @@ -164,6 +166,11 @@ export function configureStore(history: History, services: ServiceRepository, co subprocessMiddleware, ]; + const reduceMiddlewaresFn: (a: Middleware[], + b: MiddlewareListReducer) => Middleware[] = (a, b) => b(a, services); + + middlewares = pluginConfig.middlewares.reduce(reduceMiddlewaresFn, middlewares); + const enhancer = composeEnhancers(applyMiddleware(redirectToMiddleware, ...middlewares)); return createStore(rootReducer, enhancer); } diff --git a/src/views-components/form-fields/project-form-fields.tsx b/src/views-components/form-fields/project-form-fields.tsx index dc1e1612..3f576ab1 100644 --- a/src/views-components/form-fields/project-form-fields.tsx +++ b/src/views-components/form-fields/project-form-fields.tsx @@ -11,6 +11,7 @@ import { RootState } from "~/store/store"; interface ProjectNameFieldProps { validate: Validator[]; + label?: string; } // Validation behavior depends on the value of ForwardSlashNameSubstitution. @@ -32,7 +33,7 @@ export const ProjectNameField = connect( name='name' component={TextField} validate={props.validate} - label="Project Name" + label={props.label || "Project Name"} autoFocus={true} /> ); diff --git a/src/views-components/project-properties-dialog/project-properties-dialog.tsx b/src/views-components/project-properties-dialog/project-properties-dialog.tsx index e1874d95..c2982b3d 100644 --- a/src/views-components/project-properties-dialog/project-properties-dialog.tsx +++ b/src/views-components/project-properties-dialog/project-properties-dialog.tsx @@ -40,42 +40,42 @@ const mapDispatchToProps = (dispatch: Dispatch): ProjectPropertiesDialogActionPr handleDelete: (key: string, value: string) => () => dispatch(deleteProjectProperty(key, value)), }); -type ProjectPropertiesDialogProps = ProjectPropertiesDialogDataProps & ProjectPropertiesDialogActionProps & WithDialogProps<{}> & WithStyles; +type ProjectPropertiesDialogProps = ProjectPropertiesDialogDataProps & ProjectPropertiesDialogActionProps & WithDialogProps<{}> & WithStyles; export const ProjectPropertiesDialog = connect(mapStateToProps, mapDispatchToProps)( withStyles(styles)( - withDialog(PROJECT_PROPERTIES_DIALOG_NAME)( - ({ classes, open, closeDialog, handleDelete, project }: ProjectPropertiesDialogProps) => - - Properties - - - {project && project.properties && - Object.keys(project.properties).map(k => - Array.isArray(project.properties[k]) - ? project.properties[k].map((v: string) => - getPropertyChip( - k, v, - handleDelete(k, v), - classes.tag)) - : getPropertyChip( - k, project.properties[k], - handleDelete(k, project.properties[k]), - classes.tag) - ) - } - - - - - - ) -)); \ No newline at end of file + + + ) + )); -- 2.30.2