17426: Add dialog box with form to example plugin.
[arvados-workbench2.git] / src / plugins / example / index.tsx
index 36647fac3d274a9951370306bfa6779a8d247e52..f4bb27baa26be4a80fde6ba10f58bbd81a66e221 100644 (file)
@@ -2,71 +2,53 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-// Example plugin.
+// Example workbench plugin.  The entry point is the "register" method.
 
 import { PluginConfig } from '~/common/plugintypes';
 import * as React from 'react';
 import { Dispatch } from 'redux';
 import { RootState } from '~/store/store';
 import { push } from "react-router-redux";
 
 import { PluginConfig } from '~/common/plugintypes';
 import * as React from 'react';
 import { Dispatch } from 'redux';
 import { RootState } from '~/store/store';
 import { push } from "react-router-redux";
-import { Card, CardContent, Typography } from "@material-ui/core";
 import { Route, matchPath } from "react-router";
 import { RootStore } from '~/store/store';
 import { activateSidePanelTreeItem } from '~/store/side-panel-tree/side-panel-tree-actions';
 import { setSidePanelBreadcrumbs } from '~/store/breadcrumbs/breadcrumbs-actions';
 import { Route, matchPath } from "react-router";
 import { RootStore } from '~/store/store';
 import { activateSidePanelTreeItem } from '~/store/side-panel-tree/side-panel-tree-actions';
 import { setSidePanelBreadcrumbs } from '~/store/breadcrumbs/breadcrumbs-actions';
-import { DispatchProp, connect } from 'react-redux';
-import { MenuItem } from "@material-ui/core";
-import { propertiesActions } from '~/store/properties/properties-actions';
 import { Location } from 'history';
 import { handleFirstTimeLoad } from '~/store/workbench/workbench-actions';
 import { Location } from 'history';
 import { handleFirstTimeLoad } from '~/store/workbench/workbench-actions';
+import {
+    ExampleDialog,
+    ExamplePluginMainPanel,
+    ExampleMenuComponent,
+    ExampleDialogMenuComponent
+} from './exampleComponents';
 
 const categoryName = "Plugin Example";
 export const routePath = "/examplePlugin";
 
 const categoryName = "Plugin Example";
 export const routePath = "/examplePlugin";
-const propertyKey = "Example_menu_item_pressed_count";
-
-interface ExampleProps {
-    pressedCount: number;
-    className?: string;
-}
-
-const exampleMapStateToProps = (state: RootState) => ({ pressedCount: state.properties[propertyKey] || 0 });
-
-const incrementPressedCount = (dispatch: Dispatch, pressedCount: number) => {
-    dispatch(propertiesActions.SET_PROPERTY({ key: propertyKey, value: pressedCount + 1 }));
-};
-
-const ExampleMenuComponent = connect(exampleMapStateToProps)(
-    ({ pressedCount, dispatch, className }: ExampleProps & DispatchProp<any>) =>
-        <MenuItem className={className} onClick={() => incrementPressedCount(dispatch, pressedCount)}>Example menu item</MenuItem >
-);
-
-const ExamplePluginMainPanel = connect(exampleMapStateToProps)(
-    ({ pressedCount }: ExampleProps) =>
-        <Card>
-            <CardContent>
-                <Typography>
-                    This is a example main panel plugin.  The example menu item has been pressed {pressedCount} times.
-               </Typography>
-            </CardContent>
-        </Card>);
 
 export const register = (pluginConfig: PluginConfig) => {
 
 
 export const register = (pluginConfig: PluginConfig) => {
 
+    // Add this component to the main panel.  When the app navigates
+    // to '/examplePlugin' it will render ExamplePluginMainPanel.
     pluginConfig.centerPanelList.push((elms) => {
         elms.push(<Route path={routePath} component={ExamplePluginMainPanel} />);
         return elms;
     });
 
     pluginConfig.centerPanelList.push((elms) => {
         elms.push(<Route path={routePath} component={ExamplePluginMainPanel} />);
         return elms;
     });
 
+    // Add ExampleDialogMenuComponent to the upper-right user account menu
     pluginConfig.accountMenuList.push((elms, menuItemClass) => {
     pluginConfig.accountMenuList.push((elms, menuItemClass) => {
-        elms.push(<ExampleMenuComponent className={menuItemClass} />);
+        elms.push(<ExampleDialogMenuComponent className={menuItemClass} />);
         return elms;
     });
 
         return elms;
     });
 
+    // Add ExampleMenuComponent to the "New" button dropdown.
     pluginConfig.newButtonMenuList.push((elms, menuItemClass) => {
         elms.push(<ExampleMenuComponent className={menuItemClass} />);
         return elms;
     });
 
     pluginConfig.newButtonMenuList.push((elms, menuItemClass) => {
         elms.push(<ExampleMenuComponent className={menuItemClass} />);
         return elms;
     });
 
+    // Add a hook so that when the 'Plugin Example' entry in the left
+    // hand tree view is clicked, which calls navigateTo('Plugin Example'),
+    // it will be implemented by navigating to '/examplePlugin'
     pluginConfig.navigateToHandlers.push((dispatch: Dispatch, getState: () => RootState, uuid: string) => {
         if (uuid === categoryName) {
             dispatch(push(routePath));
     pluginConfig.navigateToHandlers.push((dispatch: Dispatch, getState: () => RootState, uuid: string) => {
         if (uuid === categoryName) {
             dispatch(push(routePath));
@@ -75,8 +57,12 @@ export const register = (pluginConfig: PluginConfig) => {
         return false;
     });
 
         return false;
     });
 
+    // Adds 'Plugin Example' to the left hand tree view.
     pluginConfig.sidePanelCategories.push((cats: string[]): string[] => { cats.push(categoryName); return cats; });
 
     pluginConfig.sidePanelCategories.push((cats: string[]): string[] => { cats.push(categoryName); return cats; });
 
+    // When the location changes to '/examplePlugin', make sure
+    // 'Plugin Example' in the left hand tree view is selected, and
+    // make sure the breadcrumbs are updated.
     pluginConfig.locationChangeHandlers.push((store: RootStore, pathname: string): boolean => {
         if (matchPath(pathname, { path: routePath, exact: true })) {
             store.dispatch(handleFirstTimeLoad(
     pluginConfig.locationChangeHandlers.push((store: RootStore, pathname: string): boolean => {
         if (matchPath(pathname, { path: routePath, exact: true })) {
             store.dispatch(handleFirstTimeLoad(
@@ -89,5 +75,11 @@ export const register = (pluginConfig: PluginConfig) => {
         return false;
     });
 
         return false;
     });
 
+    // The "New" button can enabled or disabled based on the current
+    // context or selection.  This adds a new callback to that will
+    // enable the "New" button when the location is '/examplePlugin'
     pluginConfig.enableNewButtonMatchers.push((location: Location) => (!!matchPath(location.pathname, { path: routePath, exact: true })));
     pluginConfig.enableNewButtonMatchers.push((location: Location) => (!!matchPath(location.pathname, { path: routePath, exact: true })));
+
+    // Add the example dialog box to the list of dialog box controls.
+    pluginConfig.dialogs.push(<ExampleDialog />);
 };
 };