Merge branch '17426-plug-ins' refs #17426
[arvados-workbench2.git] / src / common / plugintypes.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as 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";
11
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[];
18
19 /* Workbench Plugin API
20
21    Code to your plugin should go into a subdirectory of '~/plugins'.
22
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.
29
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.
34
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.
38
39  */
40
41 export interface PluginConfig {
42
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.
47      *
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`.
51      *
52      * The hooks are applied in `views/workbench/workbench.tsx`.
53      *  */
54     centerPanelList: ElementListReducer[];
55
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.
59      *
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`.
63      *
64      * The hooks are applied in `store/side-panel-tree/side-panel-tree-actions.ts`.
65      *  */
66     sidePanelCategories: CategoriesListReducer[];
67
68     /* This is a list of additional dialog box components.
69      * Dialogs are components that are wrapped using the "withDialog()" method.
70      *
71      * These are added to the list in `views/workbench/workbench.tsx`.
72      *  */
73     dialogs: React.ReactElement[];
74
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.
79      *
80      * These are used in `store/navigation/navigation-action.tsx`.
81      *  */
82     navigateToHandlers: NavigateMatcher[];
83
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).
88      *
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
93      * displayed.
94      *
95      * Each handler should return "true" if the path was handled and "false or "undefined" if not.
96      *
97      * These are used in `routes/route-change-handlers.ts`.
98      */
99     locationChangeHandlers: LocationChangeMatcher[];
100
101     /* Replace the left side of the app bar.  Normally, this displays
102      * the site banner.
103      *
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.
107      *
108      * Used in 'views-components/main-app-bar/main-app-bar.tsx'
109      */
110     appBarLeft?: React.ReactElement;
111
112     /* Replace the middle part of the app bar.  Normally, this displays
113      * the search bar.
114      *
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.
118      *
119      * Used in 'views-components/main-app-bar/main-app-bar.tsx'
120      */
121     appBarMiddle?: React.ReactElement;
122
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)
126      *
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.
130      *
131      * Used in 'views-components/main-app-bar/main-app-bar.tsx'
132      */
133     appBarRight?: React.ReactElement;
134
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.
138      *
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`.
142      *
143      * The hooks are applied in 'views-components/main-app-bar/account-menu.tsx'.
144      *  */
145     accountMenuList: ElementListReducer[];
146
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.
150      *
151      * The hooks are applied in 'views-components/side-panel-button/side-panel-button.tsx'.
152      *  */
153     enableNewButtonMatchers: EnableNew[];
154
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.
158      *
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`.
162      *
163      * The hooks are applied in 'views-components/side-panel-button/side-panel-button.tsx'.
164      *  */
165     newButtonMenuList: ElementListReducer[];
166
167     /* Add Middlewares to the Redux store.
168      *
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.
172      *
173      * https://redux.js.org/tutorials/fundamentals/part-4-store#middleware
174      *
175      * Used in 'store/store.ts'
176      *  */
177     middlewares: MiddlewareListReducer[];
178 }