1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { Dispatch, Middleware } from 'redux';
7 import { RootStore, RootState } from 'store/store';
8 import { ResourcesState } from 'store/resources/resources';
9 import { Location } from 'history';
10 import { ServiceRepository } from "services/services";
12 export type ElementListReducer = (startingList: React.ReactElement[], itemClass?: string) => React.ReactElement[];
13 export type CategoriesListReducer = (startingList: string[]) => string[];
14 export type NavigateMatcher = (dispatch: Dispatch, getState: () => RootState, uuid: string) => boolean;
15 export type LocationChangeMatcher = (store: RootStore, pathname: string) => boolean;
16 export type EnableNew = (location: Location, currentItemId: string, currentUserUUID: string | undefined, resources: ResourcesState) => boolean;
17 export type MiddlewareListReducer = (startingList: Middleware[], services: ServiceRepository) => Middleware[];
19 /* Workbench Plugin API
21 Code to your plugin should go into a subdirectory of 'plugins/'.
23 Your plugin should implement a "register" function, which will be
24 called with an object with the PluginConfig interface described
25 below. The register function may make in-place modifications to
26 the pluginConfig object, but to preserve composability, it is
27 strongly advised this should be limited to push()ing new values
28 onto the various lists of hooks.
30 To enable a plugin, edit 'plugins.tsx', import the register
31 function exported by the plugin, and add a call to the register
32 function following the examples in the comments. Then, build a new
33 Workbench package that includes the plugin.
35 Be aware that because plugins heavily leverage workbench, and in
36 fact must be compiled together, they are considered "derived works"
37 and so _must_ be license-compatible with AGPL-3.0.
41 export interface PluginConfig {
43 /* During initialization, each
44 * function in the callback list will be called with the list of
45 * react - router "Route" components that will be used select what should
46 * be displayed in the central panel based on the navigation bar.
48 * The callback function may add, edit, or remove items from this list,
49 * and return a new list of components, which will be passed to the next
50 * function in `centerPanelList`.
52 * The hooks are applied in `views/workbench/workbench.tsx`.
54 centerPanelList: ElementListReducer[];
56 /* During initialization, each
57 * function in the callback list will be called with the list of strings
58 * that are the top-level categories in the left hand navigation tree.
60 * The callback function may add, edit, or remove items from this list,
61 * and return a new list of strings, which will be passed to the next
62 * function in `sidePanelCategories`.
64 * The hooks are applied in `store/side-panel-tree/side-panel-tree-actions.ts`.
66 sidePanelCategories: CategoriesListReducer[];
68 /* This is a list of additional dialog box components.
69 * Dialogs are components that are wrapped using the "withDialog()" method.
71 * These are added to the list in `views/workbench/workbench.tsx`.
73 dialogs: React.ReactElement[];
75 /* This is a list of additional navigation matchers.
76 * These are callbacks that are called by the navigateTo(uuid) method to
77 * set the path in the navigation bar to display the desired resource.
78 * Each handler should return "true" if the uuid was handled and "false or "undefined" if not.
80 * These are used in `store/navigation/navigation-action.tsx`.
82 navigateToHandlers: NavigateMatcher[];
84 /* This is a list of additional location change matchers.
85 * These are callbacks called when the URL in the navigation bar changes
86 * (this could be in response to "navigateTo()" or due to the user
87 * entering/changing the URL directly).
89 * The Route components in centerPanelList should
90 * automatically change in response to navigation. The
91 * purpose of these handlers is trigger additional loading,
92 * such as fetching the object contents that will be
95 * Each handler should return "true" if the path was handled and "false or "undefined" if not.
97 * These are used in `routes/route-change-handlers.ts`.
99 locationChangeHandlers: LocationChangeMatcher[];
101 /* Replace the left side of the app bar. Normally, this displays
104 * Note: unlike most of the other hooks, this is not composable.
105 * This completely replaces that section of the app bar. Multiple
106 * plugins setting this value will conflict.
108 * Used in 'views-components/main-app-bar/main-app-bar.tsx'
110 appBarLeft?: React.ReactElement;
112 /* Replace the middle part of the app bar. Normally, this displays
115 * Note: unlike most of the other hooks, this is not composable.
116 * This completely replaces that section of the app bar. Multiple
117 * plugins setting this value will conflict.
119 * Used in 'views-components/main-app-bar/main-app-bar.tsx'
121 appBarMiddle?: React.ReactElement;
123 /* Replace the right part of the app bar. Normally, this displays
124 * the admin menu and help menu.
125 * (Note: the user menu can be customized separately using accountMenuList)
127 * Note: unlike most of the other hooks, this is not composable.
128 * This completely replaces that section of the app bar. Multiple
129 * plugins setting this value will conflict.
131 * Used in 'views-components/main-app-bar/main-app-bar.tsx'
133 appBarRight?: React.ReactElement;
135 /* During initialization, each
136 * function in the callback list will be called with the menu items that
137 * will appear in the "user account" menu.
139 * The callback function may add, edit, or remove items from this list,
140 * and return a new list of menu items, which will be passed to the next
141 * function in `accountMenuList`.
143 * The hooks are applied in 'views-components/main-app-bar/account-menu.tsx'.
145 accountMenuList: ElementListReducer[];
147 /* Each function in this list is called to determine if the the "NEW" button
148 * should be enabled or disabled. If any function returns "true", the button
149 * (and corresponding drop-down menu) will be enabled.
151 * The hooks are applied in 'views-components/side-panel-button/side-panel-button.tsx'.
153 enableNewButtonMatchers: EnableNew[];
155 /* During initialization, each
156 * function in the callback list will be called with the menu items that
157 * will appear in the "NEW" dropdown menu.
159 * The callback function may add, edit, or remove items from this list,
160 * and return a new list of menu items, which will be passed to the next
161 * function in `newButtonMenuList`.
163 * The hooks are applied in 'views-components/side-panel-button/side-panel-button.tsx'.
165 newButtonMenuList: ElementListReducer[];
167 /* Add Middlewares to the Redux store.
169 * Middlewares intercept redux actions before they get to the reducer, and
170 * may produce side effects. For example, the REQUEST_ITEMS action is intercepted by a middleware to
171 * trigger a load of data table contents.
173 * https://redux.js.org/tutorials/fundamentals/part-4-store#middleware
175 * Used in 'store/store.ts'
177 middlewares: MiddlewareListReducer[];