Canvas: refactor layer editor (#42562)

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Nathan Marrs
2021-12-02 15:54:45 -08:00
committed by GitHub
parent c80e7764d8
commit e07abd76c0
21 changed files with 372 additions and 316 deletions

View File

@@ -1,9 +1,7 @@
import React, { PureComponent } from 'react';
import { css, cx } from '@emotion/css';
import { Button, HorizontalGroup, Icon, IconButton, stylesFactory, ValuePicker } from '@grafana/ui';
import { AppEvents, GrafanaTheme, SelectableValue, StandardEditorProps } from '@grafana/data';
import { config } from '@grafana/runtime';
import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd';
import { Button, HorizontalGroup } from '@grafana/ui';
import { AppEvents, SelectableValue, StandardEditorProps } from '@grafana/data';
import { DropResult } from 'react-beautiful-dnd';
import { PanelOptions } from '../models.gen';
import { LayerActionID } from '../types';
@@ -15,12 +13,12 @@ import { GroupState } from 'app/features/canvas/runtime/group';
import { LayerEditorProps } from './layerEditor';
import { SelectionParams } from 'app/features/canvas/runtime/scene';
import { ShowConfirmModalEvent } from 'app/types/events';
import { LayerDragDropList } from 'app/core/components/Layers/LayerDragDropList';
import { AddLayerButton } from 'app/core/components/Layers/AddLayerButton';
type Props = StandardEditorProps<any, LayerEditorProps, PanelOptions>;
export class LayerElementListEditor extends PureComponent<Props> {
style = getLayerDragStyles(config.theme);
getScene = () => {
const { settings } = this.props.item;
if (!settings?.layer) {
@@ -86,10 +84,6 @@ export class LayerElementListEditor extends PureComponent<Props> {
layer.scene.clearCurrentSelection();
};
getRowStyle = (sel: boolean) => {
return sel ? `${this.style.row} ${this.style.sel}` : this.style.row;
};
onDragEnd = (result: DropResult) => {
if (!result.destination) {
return;
@@ -133,7 +127,7 @@ export class LayerElementListEditor extends PureComponent<Props> {
const { layer } = settings;
layer.elements.forEach((element: ElementState) => {
layer.parent?.doAction(LayerActionID.Duplicate, element);
layer.parent?.doAction(LayerActionID.Duplicate, element, false);
});
this.deleteGroup();
};
@@ -201,8 +195,27 @@ export class LayerElementListEditor extends PureComponent<Props> {
return <div>Missing layer?</div>;
}
const styles = this.style;
const selection: number[] = settings.selected ? settings.selected.map((v) => v.UID) : [];
const onDelete = (element: ElementState) => {
layer.doAction(LayerActionID.Delete, element);
};
const onDuplicate = (element: ElementState) => {
layer.doAction(LayerActionID.Duplicate, element);
};
const getLayerInfo = (element: ElementState) => {
return element.options.type;
};
const onNameChange = (element: ElementState, name: string) => {
element.onChange({ ...element.options, name });
};
const isGroup = (element: ElementState) => {
return element instanceof GroupState;
};
const selection: string[] = settings.selected ? settings.selected.map((v) => v.getName()) : [];
return (
<>
{!layer.isRoot() && (
@@ -221,78 +234,24 @@ export class LayerElementListEditor extends PureComponent<Props> {
</Button>
</>
)}
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{(() => {
// reverse order
const rows: any = [];
for (let i = layer.elements.length - 1; i >= 0; i--) {
const element = layer.elements[i];
rows.push(
<Draggable key={element.UID} draggableId={`${element.UID}`} index={rows.length}>
{(provided, snapshot) => (
<div
className={this.getRowStyle(selection.includes(element.UID))}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
onMouseDown={() => this.onSelect(element)}
>
<span className={styles.typeWrapper}>{element.item.name}</span>
<div className={styles.textWrapper}>
&nbsp; {element.UID} ({i})
</div>
{element.item.id !== 'group' && (
<>
<IconButton
name="copy"
title={'Duplicate'}
className={styles.actionIcon}
onClick={() => layer.doAction(LayerActionID.Duplicate, element)}
surface="header"
/>
<IconButton
name="trash-alt"
title={'Remove'}
className={cx(styles.actionIcon, styles.dragIcon)}
onClick={() => layer.doAction(LayerActionID.Delete, element)}
surface="header"
/>
<Icon
title="Drag and drop to reorder"
name="draggabledots"
size="lg"
className={styles.dragIcon}
/>
</>
)}
</div>
)}
</Draggable>
);
}
return rows;
})()}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
<LayerDragDropList
onDragEnd={this.onDragEnd}
onSelect={this.onSelect}
onDelete={onDelete}
onDuplicate={onDuplicate}
getLayerInfo={getLayerInfo}
onNameChange={onNameChange}
isGroup={isGroup}
layers={layer.elements}
selection={selection}
/>
<br />
<HorizontalGroup>
<ValuePicker
icon="plus"
label="Add item"
variant="secondary"
options={canvasElementRegistry.selectOptions().options}
<AddLayerButton
onChange={this.onAddItem}
isFullWidth={false}
options={canvasElementRegistry.selectOptions().options}
label={'Add item'}
/>
{selection.length > 0 && (
<Button size="sm" variant="secondary" onClick={this.onClearSelection}>
@@ -309,51 +268,3 @@ export class LayerElementListEditor extends PureComponent<Props> {
);
}
}
export const getLayerDragStyles = stylesFactory((theme: GrafanaTheme) => ({
wrapper: css`
margin-bottom: ${theme.spacing.md};
`,
row: css`
padding: ${theme.spacing.xs} ${theme.spacing.sm};
border-radius: ${theme.border.radius.sm};
background: ${theme.colors.bg2};
min-height: ${theme.spacing.formInputHeight}px;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 3px;
cursor: pointer;
border: 1px solid ${theme.colors.formInputBorder};
&:hover {
border: 1px solid ${theme.colors.formInputBorderHover};
}
`,
sel: css`
border: 1px solid ${theme.colors.formInputBorderActive};
&:hover {
border: 1px solid ${theme.colors.formInputBorderActive};
}
`,
dragIcon: css`
cursor: drag;
`,
actionIcon: css`
color: ${theme.colors.textWeak};
&:hover {
color: ${theme.colors.text};
}
`,
typeWrapper: css`
color: ${theme.colors.textBlue};
margin-right: 5px;
`,
textWrapper: css`
display: flex;
align-items: center;
flex-grow: 1;
overflow: hidden;
margin-right: ${theme.spacing.sm};
`,
}));

View File

@@ -68,6 +68,7 @@ export function getElementEditor(opts: CanvasEditorOptions): NestedPanelOptions<
currentOptions = {
...layer.getNewOptions(options),
type: layer.id,
name: `Element ${Date.now()}.${Math.floor(Math.random() * 100)}`,
};
}
const ctx = { ...context, options: currentOptions };