Update attributes panel layout for axes

This commit is contained in:
Ilfat Galiev 2021-09-15 18:13:58 +03:00
Родитель 7ed4845a58
Коммит 39310735fd
6 изменённых файлов: 324 добавлений и 240 удалений

Просмотреть файл

@ -19,12 +19,13 @@ export const CollapsiblePanel: React.FunctionComponent<{
header: string | IRenderFunction<IGroupHeaderProps>;
widgets: JSX.Element[];
isCollapsed?: boolean;
}> = ({ header, widgets, isCollapsed }) => {
alignVertically?: boolean;
}> = ({ header, widgets, isCollapsed, alignVertically }) => {
const [groupState, setIsCollapsed] = React.useState<boolean>(
isCollapsed === undefined ? false : isCollapsed
);
return (
<FluentGroupedList>
<FluentGroupedList marginLeft={alignVertically ? 0 : null}>
<GroupedList
groupProps={{
onRenderHeader: (props?: IGroupHeaderProps): JSX.Element => {

Просмотреть файл

@ -16,13 +16,22 @@ import {
} from "@fluentui/react";
import styled from "styled-components";
export const defultBindButtonSize = {
height: "24px",
width: "24px",
};
export const FluentButton = styled.div<{
marginTop?: string;
marginLeft?: string;
paddingRight?: string;
}>`
margin-top: ${({ marginTop }) => marginTop || "24px"};
margin-left: ${({ marginLeft }) => marginLeft || "unset"};
display: inline-block;
padding: 0px ${({ paddingRight }) => paddingRight || "4px"} 0px 0px;
height: ${defultBindButtonSize.height};
line-height: ${defultBindButtonSize.height};
button {
padding: 4px;
}
@ -113,9 +122,10 @@ export const NestedChartButtonsWrapper = styled.div`
margin-top: 5px;
`;
export const FluentGroupedList = styled.div`
export const FluentGroupedList = styled.div<{ marginLeft?: number }>`
.charticulator__widget-collapsible-panel-item {
margin-left: 25px;
margin-left: ${({ marginLeft }) =>
marginLeft != null ? marginLeft : "25px"};
margin-right: 15px;
min-width: 270px;
}
@ -128,12 +138,6 @@ export const FluentGroupedList = styled.div`
min-height: 24px;
}
`;
export const defultBindButtonSize = {
height: "24px",
width: "24px",
};
export const defultComponentsHeight = {
height: "24px",
lineHeight: "unset",

Просмотреть файл

@ -85,6 +85,7 @@ import {
defultComponentsHeight,
FluentButton,
FluentCheckbox,
FluentColumnLayout,
FluentDatePickerWrapper,
FluentDropdown,
FluentDropdownWrapper,
@ -422,6 +423,13 @@ export class FluentUIWidgetManager
let prevKey: string = options.value ?? "";
return (
<TextField
styles={{
...(defaultStyle as any),
field: {
...defaultStyle.field,
height: null,
},
}}
key={this.getKeyFromProperty(property)}
value={
options.value
@ -430,6 +438,7 @@ export class FluentUIWidgetManager
}
placeholder={options.placeholder}
label={options.label}
disabled={options.disabled}
onRenderLabel={labelRender}
onChange={(event, value) => {
options.updateProperty
@ -724,7 +733,8 @@ export class FluentUIWidgetManager
options: Prototypes.Controls.InputExpressionOptions = {}
) {
const value = this.getPropertyValue(property) as string;
return (
const inputExpression = (
<FluentInputExpression
key={this.getKeyFromProperty(property)}
label={options.label}
@ -754,6 +764,32 @@ export class FluentUIWidgetManager
}}
/>
);
if (options.dropzone) {
return (
<DropZoneView
key={options.label}
filter={(data) => data instanceof DragData.DataExpression}
onDrop={(data: DragData.DataExpression) => {
new Actions.BindDataToAxis(
this.objectClass.object as Specification.PlotSegment,
options.dropzone.property,
null,
data,
true
).dispatch(this.store.dispatcher);
}}
className="charticulator__widget-section-header charticulator__widget-section-header-dropzone"
draggingHint={() => (
<span className="el-dropzone-hint">{options.dropzone?.prompt}</span>
)}
>
{inputExpression}
</DropZoneView>
);
} else {
return inputExpression;
}
}
public inputColor(
@ -995,79 +1031,79 @@ export class FluentUIWidgetManager
): JSX.Element {
let container: HTMLSpanElement;
return (
<span
<FluentButton
ref={(e) => (container = e)}
key={this.getKeyFromProperty(property)}
marginTop={"0px"}
paddingRight={"0px"}
>
<FluentButton marginTop={"0px"} paddingRight={"0px"}>
<DefaultButton
styles={{
root: {
minWidth: "unset",
...defultComponentsHeight,
<DefaultButton
styles={{
root: {
minWidth: "unset",
...defultComponentsHeight,
},
}}
iconProps={{
iconName: "SortLines",
}}
onClick={() => {
globals.popupController.popupAt(
(context) => {
const items = options.items
? options.items
: (this.getPropertyValue(property) as string[]);
return (
<PopupView context={context}>
<ReorderStringsValue
items={items}
onConfirm={(items) => {
this.emitSetProperty(property, items);
context.close();
}}
onReset={() => {
const axisDataBinding = {
...(this.objectClass.object.properties[
property.property
] as any),
};
axisDataBinding.table = this.store.chartManager.getTable(
(this.objectClass.object as any).table
);
axisDataBinding.metadata = {
kind: axisDataBinding.dataKind,
orderMode: "order",
};
const groupBy: Specification.Types.GroupBy = this.store.getGroupingExpression(
this.objectClass.object
);
const values = this.store.chartManager.getGroupedExpressionVector(
(this.objectClass.object as any).table,
groupBy,
axisDataBinding.expression
);
const {
categories,
} = this.store.getCategoriesForDataBinding(
axisDataBinding.metadata,
axisDataBinding.type,
values
);
return categories;
}}
{...options}
/>
</PopupView>
);
},
}}
iconProps={{
iconName: "SortLines",
}}
onClick={() => {
globals.popupController.popupAt(
(context) => {
const items = options.items
? options.items
: (this.getPropertyValue(property) as string[]);
return (
<PopupView context={context}>
<ReorderStringsValue
items={items}
onConfirm={(items) => {
this.emitSetProperty(property, items);
context.close();
}}
onReset={() => {
const axisDataBinding = {
...(this.objectClass.object.properties[
property.property
] as any),
};
axisDataBinding.table = this.store.chartManager.getTable(
(this.objectClass.object as any).table
);
axisDataBinding.metadata = {
kind: axisDataBinding.dataKind,
orderMode: "order",
};
const groupBy: Specification.Types.GroupBy = this.store.getGroupingExpression(
this.objectClass.object
);
const values = this.store.chartManager.getGroupedExpressionVector(
(this.objectClass.object as any).table,
groupBy,
axisDataBinding.expression
);
const {
categories,
} = this.store.getCategoriesForDataBinding(
axisDataBinding.metadata,
axisDataBinding.type,
values
);
return categories;
}}
{...options}
/>
</PopupView>
);
},
{ anchor: container }
);
}}
/>
</FluentButton>
</span>
{ anchor: container }
);
}}
/>
</FluentButton>
);
}
@ -1272,11 +1308,13 @@ export class FluentUIWidgetManager
<span className="el-dropzone-hint">{options.dropzone.prompt}</span>
)}
>
<FluentLabelHeader>
<Label>{title}</Label>
</FluentLabelHeader>
{title ? (
<FluentLabelHeader>
<Label>{title}</Label>
</FluentLabelHeader>
) : null}
{widget}
<FluentButton marginTop={"0px"}>
<FluentButton marginTop={"0px"} marginLeft={"6px"}>
<DefaultButton
key={title}
iconProps={{
@ -1506,6 +1544,7 @@ export class FluentUIWidgetManager
header={options.header}
widgets={widgets}
isCollapsed={options.isCollapsed}
alignVertically={options.alignVertically}
/>
);
}

Просмотреть файл

@ -56,6 +56,7 @@ export interface InputTextOptions {
borderless?: boolean;
styles?: CSSProperties;
emitMappingAction?: boolean;
disabled?: boolean;
}
export interface InputBooleanOptions {
@ -163,6 +164,7 @@ export interface TableOptions {}
export interface VerticalGroupOptions {
isCollapsed?: boolean;
header: string;
alignVertically?: boolean;
}
export const enum PanelMode {
@ -214,6 +216,12 @@ export interface ScrollListOptions {
export interface InputExpressionOptions {
table?: string;
label?: string;
dropzone?: {
type: "axis-data-binding";
prompt?: string;
property?: string;
defineCategories?: boolean;
};
}
export interface InputFormatOptions {

Просмотреть файл

@ -1177,25 +1177,6 @@ export function buildAxisAppearanceWidgets(
return [
manager.vertical(
manager.verticalGroup(
{
header: strings.objects.general,
},
[
manager.inputFormat(
{
property: axisProperty,
field: "tickFormat",
},
{
blank: strings.core.auto,
isDateField: false,
label: strings.objects.axes.tickFormat,
}
),
]
),
manager.verticalGroup(
{
header: strings.objects.appearance,
@ -1246,6 +1227,17 @@ export function buildAxisAppearanceWidgets(
labelKey: strings.objects.axes.tickColor,
}
),
manager.inputFormat(
{
property: axisProperty,
field: "tickFormat",
},
{
blank: strings.core.auto,
isDateField: false,
label: strings.objects.axes.tickFormat,
}
),
manager.inputNumber(
{
property: axisProperty,
@ -1333,22 +1325,29 @@ export function buildAxisWidgets(
widgets.push(
manager.verticalGroup(
{
header: axisName + strings.objects.axes.numericalSuffix,
header: strings.objects.general,
},
[
manager.sectionHeader(
axisName + strings.objects.axes.numericalSuffix,
manager.clearButton({ property: axisProperty }, null, true),
dropzoneOptions
),
manager.inputExpression(
{
property: axisProperty,
field: "expression",
},
{
label: strings.objects.axes.data,
}
// manager.sectionHeader(
// axisName + strings.objects.axes.numericalSuffix,
// manager.clearButton({ property: axisProperty }, null, true),
// dropzoneOptions
// ),
manager.label(strings.objects.axes.data),
manager.horizontal(
[1, 0],
manager.sectionHeader(
null,
manager.inputExpression(
{
property: axisProperty,
field: "expression",
},
{}
),
dropzoneOptions
),
manager.clearButton({ property: axisProperty }, null, true)
),
data.valueType === "date"
? manager.label(strings.objects.dataAxis.range)
@ -1514,127 +1513,34 @@ export function buildAxisWidgets(
widgets.push(
manager.verticalGroup(
{
header: axisName + strings.objects.axes.categoricalSuffix,
header: strings.objects.general,
},
[
manager.sectionHeader(
"Data",
manager.clearButton({ property: axisProperty }, null, true),
dropzoneOptions
),
manager.vertical(
manager.label("Data"),
manager.horizontal(
[1, 0],
manager.inputExpression({
property: axisProperty,
field: "expression",
}),
manager.reorderWidget(
{ property: axisProperty, field: "categories" },
{ allowReset: true }
)
),
manager.inputNumber(
{ property: axisProperty, field: "gapRatio" },
{
minimum: 0,
maximum: 1,
percentage: true,
showSlider: true,
label: "Gap",
}
),
data.valueType === "date"
? (manager.inputExpression(
{
property: axisProperty,
field: "tickDataExpression",
},
{
label: strings.objects.axes.tickData,
}
),
manager.row(
strings.objects.axes.tickFormat,
manager.inputFormat(
{
property: axisProperty,
field: "tickFormat",
},
{
blank: strings.core.auto,
isDateField:
data.numericalMode === NumericalMode.Temporal ||
data.valueType === DataType.Date,
}
)
))
: null,
manager.label(strings.objects.dataAxis.scrolling),
manager.inputBoolean(
{
property: axisProperty,
field: "allowScrolling",
},
{
type: "checkbox",
label: strings.objects.dataAxis.allowScrolling,
observerConfig: {
isObserver: true,
properties: {
property: axisProperty,
field: "windowSize",
},
value: 10,
// manager.sectionHeader(
// strings.objects.axes.data,
// manager.clearButton({ property: axisProperty }, null, true),
// dropzoneOptions
// ),
// manager.vertical(
manager.label(strings.objects.axes.data),
manager.horizontal(
[1, 0],
manager.sectionHeader(
null,
manager.inputExpression(
{
property: axisProperty,
field: "expression",
},
}
{}
),
dropzoneOptions
),
data.allowScrolling
? manager.inputNumber(
{
property: axisProperty,
field: "windowSize",
},
{
maximum: 1000000,
minimum: 1,
label: strings.objects.dataAxis.windowSize,
}
)
: null,
data.allowScrolling
? manager.inputNumber(
{
property: axisProperty,
field: "barOffset",
},
{
maximum: 1000000,
minimum: -1000000,
label: strings.objects.dataAxis.barOffset,
}
)
: null
),
]
)
);
widgets.push(makeAppearance());
}
break;
case "default":
{
widgets.push(
manager.verticalGroup(
{
header: axisName + strings.objects.axes.stackingSuffix,
},
[
manager.sectionHeader(
axisName + strings.objects.axes.stackingSuffix,
manager.clearButton({ property: axisProperty }, null, true),
dropzoneOptions
manager.reorderWidget(
{ property: axisProperty, field: "categories" },
{ allowReset: true }
)
),
manager.inputNumber(
{ property: axisProperty, field: "gapRatio" },
@ -1646,9 +1552,103 @@ export function buildAxisWidgets(
label: "Gap",
}
),
data.valueType === "date"
? (manager.inputExpression(
{
property: axisProperty,
field: "tickDataExpression",
},
{
label: strings.objects.axes.tickData,
}
),
manager.row(
strings.objects.axes.tickFormat,
manager.inputFormat(
{
property: axisProperty,
field: "tickFormat",
},
{
blank: strings.core.auto,
isDateField:
data.numericalMode === NumericalMode.Temporal ||
data.valueType === DataType.Date,
}
)
))
: null,
manager.label(strings.objects.dataAxis.scrolling),
manager.inputBoolean(
{
property: axisProperty,
field: "allowScrolling",
},
{
type: "checkbox",
label: strings.objects.dataAxis.allowScrolling,
observerConfig: {
isObserver: true,
properties: {
property: axisProperty,
field: "windowSize",
},
value: 10,
},
}
),
data.allowScrolling
? manager.inputNumber(
{
property: axisProperty,
field: "windowSize",
},
{
maximum: 1000000,
minimum: 1,
label: strings.objects.dataAxis.windowSize,
}
)
: null,
data.allowScrolling
? manager.inputNumber(
{
property: axisProperty,
field: "barOffset",
},
{
maximum: 1000000,
minimum: -1000000,
label: strings.objects.dataAxis.barOffset,
}
)
: null,
// )
]
)
);
widgets.push(makeAppearance());
}
break;
case "default":
{
widgets.push(
manager.sectionHeader(
axisName + strings.objects.axes.stackingSuffix,
manager.clearButton({ property: axisProperty }, null, true),
dropzoneOptions
),
manager.inputNumber(
{ property: axisProperty, field: "gapRatio" },
{
minimum: 0,
maximum: 1,
percentage: true,
showSlider: true,
label: "Gap",
}
)
);
}
break;
}
@ -1683,10 +1683,34 @@ export function buildAxisWidgets(
);
} else {
widgets.push(
manager.sectionHeader(
axisName + ": " + strings.core.none,
null,
dropzoneOptions
// manager.sectionHeader(
// axisName + ": " + strings.core.none,
// null,
// dropzoneOptions
// )
manager.verticalGroup(
{
header: strings.objects.general,
},
[
manager.label(strings.objects.axes.data),
manager.horizontal(
[1, 0, 0, 0],
manager.sectionHeader(
null,
manager.inputText(
{
property: null,
},
{
disabled: true,
value: strings.core.none,
}
),
dropzoneOptions
)
),
]
)
);
}

Просмотреть файл

@ -2725,7 +2725,7 @@ export class Region2DConstraintBuilder {
}
public buildAxisWidgets(
m: Controls.WidgetManager,
manager: Controls.WidgetManager,
axisName: string,
axis: "x" | "y"
): Controls.Widget[] {
@ -2736,8 +2736,16 @@ export class Region2DConstraintBuilder {
? PlotSegmentAxisPropertyNames.xData
: PlotSegmentAxisPropertyNames.yData;
return [
...buildAxisWidgets(data, axisProperty, m, axisName),
...this.plotSegment.buildGridLineWidgets(data, m, axisProperty),
manager.verticalGroup(
{
header: axisName + strings.objects.axes.numericalSuffix,
alignVertically: true,
},
[
...buildAxisWidgets(data, axisProperty, manager, axisName),
...this.plotSegment.buildGridLineWidgets(data, manager, axisProperty),
]
),
];
}