grafana/public/app/features/scenes/core/SceneComponentEditWrapper.tsx

83 lines
2.1 KiB
TypeScript
Raw Normal View History

Scene: POC for a future dashboard model and runtime (#50980) * Playing around * This is getting interesting * Updates * Updated * Observable experiments * This is tricky * VizPanel panel renderer * New model progress * Maybe this could be something * Updated * Rename * updates * Updated * Query runners? not sure * Updated * updates * flex box layout starting to work * Testing * Tested an action * Parent context sort of working * Progress * Progress * Updated * Starting to work * Things are working * Scene list, nested scene demo * Progress on repeats * Moving things * Pretty big progress * More things working * Great progress * Progress * Name changing * Minor tweaks * Simplified sizing * Move toggleDirection to SceneFlexLayout * add feature flag (#50990) * removed new useObservable hook * Rename folder and feature toggle to scenes * Caching scenes so you can go back to another scene without having to re-query data * Fix issue with subs on re-mount * Fixing test * Added SceneCanvasText to play around with layout elements with size based on content * Scene: Edit mode and component edit wrapper that handles selection (#51078) * First step for scene variables * Started playing around with a scene edit mode * Better way to set component * Progress on edit mode * Update * Progress on edit mode * Progress on editor * Progress on editor * Updates * More working * Progress * Minor update * removed unnessary file * Moving things around * Updated * Making time range separate from time picker * minor rename of methods * The most basic variable start * Minor renames * Fixed interpolate issue if not found at closest level * An embryo of event model and url sync handling * Update url sync types * Removed unnessary any type arg Co-authored-by: Ryan McKinley <ryantxu@gmail.com> Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
2022-07-07 01:53:02 -05:00
import { css } from '@emotion/css';
import React, { CSSProperties } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
import { SceneObjectBase } from './SceneObjectBase';
import { SceneComponentProps } from './types';
export function SceneComponentEditWrapper<T extends SceneObjectBase<any>>({
model,
isEditing,
}: SceneComponentProps<T>) {
const Component = (model as any).constructor['Component'] ?? EmptyRenderer;
const inner = <Component model={model} isEditing={isEditing} />;
model.useMount();
if (!isEditing) {
return inner;
}
return <SceneComponentEditingWrapper model={model}>{inner}</SceneComponentEditingWrapper>;
}
export function SceneComponentEditingWrapper<T extends SceneObjectBase<any>>({
model,
children,
}: {
model: T;
children: React.ReactNode;
}) {
const styles = useStyles2(getStyles);
const editor = model.getSceneEditor();
const { hoverObject, selectedObject } = editor.useState();
const onMouseEnter = () => editor.onMouseEnterObject(model);
const onMouseLeave = () => editor.onMouseLeaveObject(model);
const onClick = (evt: React.MouseEvent) => {
evt.stopPropagation();
editor.onSelectObject(model);
};
const style: CSSProperties = {};
let className = styles.wrapper;
if (hoverObject?.ref === model) {
className += ' ' + styles.hover;
}
if (selectedObject?.ref === model) {
className += ' ' + styles.selected;
}
return (
<div style={style} className={className} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onClick}>
{children}
</div>
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
wrapper: css({
display: 'flex',
flexGrow: 1,
padding: 8,
border: `1px dashed ${theme.colors.primary.main}`,
cursor: 'pointer',
}),
hover: css({
border: `1px solid ${theme.colors.primary.border}`,
}),
selected: css({
border: `1px solid ${theme.colors.error.border}`,
}),
};
};
function EmptyRenderer<T>(_: SceneComponentProps<T>): React.ReactElement | null {
return null;
}