Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chart component #2081

Merged
merged 28 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e1bbae9
Initial chart prop setup
apedroferreira May 24, 2023
396a1ba
Set up nested bindings for data series
apedroferreira May 26, 2023
3c706f3
Nested binding support (WIP) (broken)
apedroferreira Jun 1, 2023
a3b9bd0
Working nested bindings (still needs cleanup and refactor)
apedroferreira Jun 1, 2023
07bdee4
Cleanup, refactor
apedroferreira Jun 2, 2023
f9cfe3e
Merge remote-tracking branch 'upstream/master' into chart-component
apedroferreira Jun 2, 2023
bd54b84
Update schema to new format
apedroferreira Jun 2, 2023
1a2efd4
Fixes
apedroferreira Jun 2, 2023
4e93c33
typo
apedroferreira Jun 2, 2023
94fdb34
Merge remote-tracking branch 'upstream/master' into chart-component
apedroferreira Jul 6, 2023
3bc07f9
Merge fixes
apedroferreira Jul 6, 2023
e9f0f2f
New DOM format fixes
apedroferreira Jul 6, 2023
7ee5dac
Controls for other data series properties
apedroferreira Jul 6, 2023
be59656
wip
apedroferreira Jul 6, 2023
a486bcd
Working line chart with colors
apedroferreira Jul 7, 2023
92074ac
Make height resizable
apedroferreira Jul 7, 2023
a51dd63
Working bar charts and other kinds
apedroferreira Jul 11, 2023
acf310a
Use ColorPicker component
apedroferreira Jul 11, 2023
661406e
Merge remote-tracking branch 'upstream/master' into chart-component
apedroferreira Jul 11, 2023
b9eeea4
Fix nested bindings + add chart test
apedroferreira Jul 12, 2023
233743d
Cleanup
apedroferreira Jul 12, 2023
32aef6c
Merge remote-tracking branch 'upstream/master' into chart-component
apedroferreira Jul 12, 2023
a7050d3
Build API docs
apedroferreira Jul 12, 2023
ec4b35d
Changing color but not sure why tests faild
apedroferreira Jul 12, 2023
968f5b2
Some review fixes
apedroferreira Jul 13, 2023
cc22304
Fix cyclical dependencies due to prop controls
apedroferreira Jul 13, 2023
492df00
Merge remote-tracking branch 'upstream/master' into chart-component
apedroferreira Jul 13, 2023
b43c3e8
oops
apedroferreira Jul 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/data/toolpad/reference/components/chart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- This file has been auto-generated using `yarn docs:build:api`. -->

# Chart

<p class="description">API docs for the Toolpad Chart component.</p>

## Properties

| Name | Type | Default | Description |
| :------------------------------------ | :------------------------------------ | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <span class="prop-name">data</span> | <span class="prop-type">array</span> | | The data to be displayed. |
| <span class="prop-name">height</span> | <span class="prop-type">number</span> | <span class="prop-default">400</span> | |
| <span class="prop-name">sx</span> | <span class="prop-type">object</span> | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. |
1 change: 1 addition & 0 deletions docs/data/toolpad/reference/components/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- [Autocomplete](/toolpad/reference/components/autocomplete/)
- [Button](/toolpad/reference/components/button/)
- [Chart](/toolpad/reference/components/chart/)
- [Container](/toolpad/reference/components/container/)
- [DataGrid](/toolpad/reference/components/data-grid/)
- [DatePicker](/toolpad/reference/components/date-picker/)
Expand Down
4 changes: 4 additions & 0 deletions docs/data/toolpad/reference/components/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"title": "Button",
"pathname": "/toolpad/reference/components/button"
},
{
"title": "Chart",
"pathname": "/toolpad/reference/components/chart"
},
{
"title": "Container",
"pathname": "/toolpad/reference/components/container"
Expand Down
9 changes: 9 additions & 0 deletions docs/pages/toolpad/reference/components/chart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* This file has been auto-generated using `yarn docs:build:api`. */

import * as React from 'react';
import MarkdownDocs from '@mui/monorepo/docs/src/modules/components/MarkdownDocs';
import * as pageProps from '../../../../data/toolpad/reference/components/chart.md?@mui/markdown';

export default function Page() {
return <MarkdownDocs {...pageProps} />;
}
1 change: 1 addition & 0 deletions packages/toolpad-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
"react-is": "18.2.0",
"react-router-dom": "6.3.0",
"react-split-pane": "0.1.92",
"recharts": "2.7.2",
"semver": "7.5.4",
"serialize-javascript": "6.0.1",
"ses": "0.18.4",
Expand Down
2 changes: 0 additions & 2 deletions packages/toolpad-app/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ export const SCHEDULE_DEMO_URL = 'https://calendly.com/prakhar-mui/toolpad';

export const TOOLPAD_BRIDGE_GLOBAL = '__TOOLPAD_BRIDGE__';

export const NON_BINDABLE_CONTROL_TYPES = ['GridColumns'];

export const VERSION_CHECK_INTERVAL = 1000 * 60 * 10;
4 changes: 2 additions & 2 deletions packages/toolpad-app/src/runtime/ToolpadApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import evalJsBindings, {
EvaluatedBinding,
ParsedBinding,
} from './evalJsBindings';
import { HTML_ID_EDITOR_OVERLAY, NON_BINDABLE_CONTROL_TYPES } from './constants';
import { HTML_ID_EDITOR_OVERLAY } from './constants';
import { layoutBoxArgTypes } from './toolpadComponents/layoutBox';
import { execDataSourceQuery, useDataQuery, UseFetch } from './useDataQuery';
import { NavigateToPage } from './CanvasHooksContext';
Expand Down Expand Up @@ -470,7 +470,7 @@ function parseBindings(
if (
componentId !== PAGE_ROW_COMPONENT_ID &&
!isResizableHeightProp &&
!NON_BINDABLE_CONTROL_TYPES.includes(argType?.control?.type as string)
argType?.control?.bindable !== false
) {
scopePath = `${elm.name}.${propName}`;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/toolpad-app/src/runtime/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export const HTML_ID_EDITOR_OVERLAY = 'editor-overlay';

export const NON_BINDABLE_CONTROL_TYPES = ['GridColumns'];
7 changes: 4 additions & 3 deletions packages/toolpad-app/src/runtime/evalJsBindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,13 @@ export default function evalJsBindings(
Array.isArray(value) ? `[${nestedPropName}]` : `.${nestedPropName}`
}`;

const nestedBindingResultValue = results[nestedBindingId]?.value;
if (nestedBindingResultValue) {
const nestedBindingResult = results[nestedBindingId];

if (nestedBindingResult) {
bindingResult = updatePath(
bindingResult,
`value.${nestedBindingId.replace(bindingId, '')}`,
nestedBindingResultValue,
nestedBindingResult.value,
apedroferreira marked this conversation as resolved.
Show resolved Hide resolved
);
} else {
mergeNestedBindings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const INTERNAL_COMPONENTS = new Map<string, ToolpadComponentDefinition>([
],
['Image', { displayName: 'Image', builtIn: 'Image' }],
['DataGrid', { displayName: 'Data Grid', builtIn: 'DataGrid' }],
['Chart', { displayName: 'Chart', builtIn: 'Chart' }],
['TextField', { displayName: 'Text Field', builtIn: 'TextField' }],
['DatePicker', { displayName: 'Date Picker', builtIn: 'DatePicker' }],
['FilePicker', { displayName: 'File Picker', builtIn: 'FilePicker' }],
Expand Down
3 changes: 2 additions & 1 deletion packages/toolpad-app/src/toolpad/AppEditor/BindingEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ import TabPanel from '../../components/TabPanel';

import { useDom } from '../AppState';
import * as appDom from '../../appDom';
import { getBindingType, getBindingValue } from '../../bindings';

// eslint-disable-next-line import/no-cycle
import BindableEditor from './PageEditor/BindableEditor';
import { getBindingType, getBindingValue } from '../../bindings';

interface BindingEditorContext {
label: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@ import {
EnvAttrValue,
} from '@mui/toolpad-core';
import { WithControlledProp } from '../../../utils/types';
import { getDefaultControl } from '../../propertyControls';
// eslint-disable-next-line import/no-cycle
import { BindingEditor } from '../BindingEditor';
import { getBindingType } from '../../../bindings';
import { getDefaultControl, usePropControlsContext } from '../../propertyControls';

function renderDefaultControl(params: RenderControlParams<any>) {
const Control = getDefaultControl(params.propType);
return Control ? <Control {...params} /> : null;
}
// eslint-disable-next-line import/no-cycle
import { BindingEditor } from '../BindingEditor';

export interface RenderControlParams<V> extends WithControlledProp<V> {
label: string;
Expand All @@ -44,7 +40,7 @@ export default function BindableEditor<V>({
bindable = true,
disabled,
propType,
renderControl = renderDefaultControl,
renderControl: renderControlProp,
value,
jsRuntime,
onChange,
Expand All @@ -54,6 +50,18 @@ export default function BindableEditor<V>({
envVarNames,
sx,
}: BindableEditorProps<V>) {
const propTypeControls = usePropControlsContext();

const renderDefaultControl = React.useCallback(
(params: RenderControlParams<any>) => {
const Control = getDefaultControl(propTypeControls, params.propType);
return Control ? <Control {...params} /> : null;
},
[propTypeControls],
);

const renderControl = renderControlProp || renderDefaultControl;

const handlePropConstChange = React.useCallback((newValue: V) => onChange(newValue), [onChange]);

const valueBindingType = value && getBindingType(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,41 @@ import {
import ElementContext from '../ElementContext';
import MarkdownTooltip from '../../../components/MarkdownTooltip';

import { PropControlsContextProvider, PropTypeControls } from '../../propertyControls';
import string from '../../propertyControls/string';
import boolean from '../../propertyControls/boolean';
import number from '../../propertyControls/number';
import select from '../../propertyControls/select';
import json from '../../propertyControls/json';
import markdown from '../../propertyControls/Markdown';
import event from '../../propertyControls/event';
import GridColumns from '../../propertyControls/GridColumns';
import SelectOptions from '../../propertyControls/SelectOptions';
import ChartData from '../../propertyControls/ChartData';
import RowIdFieldSelect from '../../propertyControls/RowIdFieldSelect';
import HorizontalAlign from '../../propertyControls/HorizontalAlign';
import VerticalAlign from '../../propertyControls/VerticalAlign';
import NumberFormat from '../../propertyControls/NumberFormat';
import ColorScale from '../../propertyControls/ColorScale';

const propTypeControls: PropTypeControls = {
string,
boolean,
number,
select,
json,
markdown,
event,
GridColumns,
SelectOptions,
ChartData,
RowIdFieldSelect,
HorizontalAlign,
VerticalAlign,
NumberFormat,
ColorScale,
};

const classes = {
control: 'Toolpad_Control',
sectionHeading: 'Toolpad_ControlsSectionHeading',
Expand Down Expand Up @@ -197,13 +232,15 @@ export default function ComponentEditor({ className }: ComponentEditorProps) {
const selectedNode = selectedNodeId ? appDom.getMaybeNode(dom, selectedNodeId) : null;

return (
<ComponentEditorRoot className={className} data-testid="component-editor">
{selectedNode && appDom.isElement(selectedNode) ? (
// Add key to make sure it mounts every time selected node changes
<SelectedNodeEditor key={selectedNode.id} node={selectedNode} />
) : (
<PageOptionsPanel />
)}
</ComponentEditorRoot>
<PropControlsContextProvider value={propTypeControls}>
<ComponentEditorRoot className={className} data-testid="component-editor">
{selectedNode && appDom.isElement(selectedNode) ? (
// Add key to make sure it mounts every time selected node changes
<SelectedNodeEditor key={selectedNode.id} node={selectedNode} />
) : (
<PageOptionsPanel />
)}
</ComponentEditorRoot>
</PropControlsContextProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import * as appDom from '../../../appDom';
import { useDomApi } from '../../AppState';
import BindableEditor from './BindableEditor';
import { usePageEditorState } from './PageEditorProvider';
import { getDefaultControl } from '../../propertyControls';
import { NON_BINDABLE_CONTROL_TYPES } from '../../../runtime/constants';
import { getDefaultControl, usePropControlsContext } from '../../propertyControls';

function buildScopeMeta(vm: ApplicationVm, bindingScope?: RuntimeScope): ScopeMeta {
if (bindingScope?.parentScope) {
Expand Down Expand Up @@ -63,16 +62,14 @@ export default function NodeAttributeEditor<P extends object>({

const scopeMeta = React.useMemo(() => buildScopeMeta(vm, bindingScope), [vm, bindingScope]);

const Control = getDefaultControl(argType, props);
const propTypeControls = usePropControlsContext();
const Control = getDefaultControl(propTypeControls, argType, props);

// NOTE: Doesn't make much sense to bind controlled props. In the future we might opt
// to make them bindable to other controlled props only
const isDisabled = !!argType.onChangeProp;

const isBindable =
!isDisabled &&
namespace !== 'layout' &&
!NON_BINDABLE_CONTROL_TYPES.includes(argType.control?.type as string);
const isBindable = !isDisabled && namespace !== 'layout' && argType.control?.bindable !== false;

const jsBrowserRuntime = useBrowserJsRuntime();

Expand Down
Loading