1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { WithDialogProps } from 'store/dialog/with-dialog';
7 import { ServiceRepository } from "services/services";
8 import { Dispatch } from "redux";
9 import { RootState } from 'store/store';
10 import { initialize } from 'redux-form';
11 import { dialogActions } from "store/dialog/dialog-actions";
12 import { reduxForm, InjectedFormProps, Field, reset, startSubmit } from 'redux-form';
13 import { TextField } from "components/text-field/text-field";
14 import { FormDialog } from 'components/form-dialog/form-dialog';
15 import { withDialog } from "store/dialog/with-dialog";
16 import { compose } from "redux";
17 import { propertiesActions } from "store/properties/properties-actions";
18 import { DispatchProp, connect } from 'react-redux';
19 import { MenuItem } from "@material-ui/core";
20 import { Card, CardContent, Typography } from "@material-ui/core";
22 // This is the name of the dialog box. It in store actions that
23 // open/close the dialog box.
24 export const EXAMPLE_DIALOG_FORM_NAME = "exampleFormName";
26 // This is the name of the property that will be used to store the
28 export const propertyKey = "Example_menu_item_pressed_count";
30 // The model backing the form.
31 export interface ExampleFormDialogData {
32 pressedCount: number | string; // Supposed to start as a number but TextField seems to turn this into a string, unfortunately.
35 // The actual component with the editing fields. Enables editing
36 // the 'pressedCount' field.
37 const ExampleEditFields = () => <span>
40 component={TextField as any}
45 // Callback for when the form is submitted.
46 const submitEditedPressedCount = (data: ExampleFormDialogData) =>
47 (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
48 dispatch(startSubmit(EXAMPLE_DIALOG_FORM_NAME));
49 dispatch(propertiesActions.SET_PROPERTY({
50 key: propertyKey, value: parseInt(data.pressedCount as string, 10)
52 dispatch(dialogActions.CLOSE_DIALOG({ id: EXAMPLE_DIALOG_FORM_NAME }));
53 dispatch(reset(EXAMPLE_DIALOG_FORM_NAME));
56 // Props for the dialog component
57 type DialogExampleProps = WithDialogProps<{ updating: boolean }> & InjectedFormProps<ExampleFormDialogData>;
59 // This is the component that renders the dialog.
60 const DialogExample = (props: DialogExampleProps) =>
62 dialogTitle="Edit pressed count"
63 formFields={ExampleEditFields}
64 submitLabel="Update pressed count"
68 // This ties it all together, withDialog() determines if the dialog is
69 // visible based on state, and reduxForm manages the values of the
71 export const ExampleDialog = compose(
72 withDialog(EXAMPLE_DIALOG_FORM_NAME),
73 reduxForm<ExampleFormDialogData>({
74 form: EXAMPLE_DIALOG_FORM_NAME,
75 onSubmit: (data, dispatch) => {
76 dispatch(submitEditedPressedCount(data));
82 // Callback, dispatches an action to set the value of property
83 // "Example_menu_item_pressed_count"
84 const incrementPressedCount = (dispatch: Dispatch, pressedCount: number) => {
85 dispatch(propertiesActions.SET_PROPERTY({ key: propertyKey, value: pressedCount + 1 }));
88 // Callback, dispatches actions required to initialize and open the
90 export const openExampleDialog = (pressedCount: number) =>
91 (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
92 dispatch(initialize(EXAMPLE_DIALOG_FORM_NAME, { pressedCount }));
93 dispatch(dialogActions.OPEN_DIALOG({
94 id: EXAMPLE_DIALOG_FORM_NAME, data: {}
98 // Props definition used for menu items.
99 interface ExampleProps {
100 pressedCount: number;
104 // Called to get the props from the redux state for several of the
105 // following components.
106 // Gets the value of the property "Example_menu_item_pressed_count"
107 // from the state and puts it in 'pressedCount'
108 const exampleMapStateToProps = (state: RootState) => ({ pressedCount: state.properties[propertyKey] || 0 });
110 // Define component for the menu item that incremens the count each time it is pressed.
111 export const ExampleMenuComponent = connect(exampleMapStateToProps)(
112 ({ pressedCount, dispatch, className }: ExampleProps & DispatchProp<any>) =>
113 <MenuItem className={className} onClick={() => incrementPressedCount(dispatch, pressedCount)}>Example menu item</MenuItem >
116 // Define component for the menu item that opens the dialog box that lets you edit the count directly.
117 export const ExampleDialogMenuComponent = connect(exampleMapStateToProps)(
118 ({ pressedCount, dispatch, className }: ExampleProps & DispatchProp<any>) =>
119 <MenuItem className={className} onClick={() => dispatch(openExampleDialog(pressedCount))}>Open example dialog</MenuItem >
122 // The central panel. Displays the "pressed" count.
123 export const ExamplePluginMainPanel = connect(exampleMapStateToProps)(
124 ({ pressedCount }: ExampleProps) =>
128 This is a example main panel plugin. The example menu item has been pressed {pressedCount} times.