Dashboards: Select objects after adding them (#101609)
* Dashboards: Select newly added object * Add tests * Update
This commit is contained in:
@@ -15,7 +15,6 @@ import {
|
|||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { isInCloneChain } from '../utils/clone';
|
import { isInCloneChain } from '../utils/clone';
|
||||||
import { getDashboardSceneFor } from '../utils/utils';
|
|
||||||
|
|
||||||
import { DashboardAddPane } from './DashboardAddPane';
|
import { DashboardAddPane } from './DashboardAddPane';
|
||||||
import { DashboardOutline } from './DashboardOutline';
|
import { DashboardOutline } from './DashboardOutline';
|
||||||
@@ -72,22 +71,20 @@ export class DashboardEditPane extends SceneObjectBase<DashboardEditPaneState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public selectObject(obj: SceneObject, id: string, multi?: boolean) {
|
public selectObject(obj: SceneObject, id: string, multi?: boolean) {
|
||||||
if (!this.state.selection) {
|
const prevItem = this.state.selection?.getFirstObject();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const prevItem = this.state.selection.getFirstObject();
|
|
||||||
if (prevItem === obj && !multi) {
|
if (prevItem === obj && !multi) {
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multi && this.state.selection.hasValue(id)) {
|
if (multi && this.state.selection?.hasValue(id)) {
|
||||||
this.removeMultiSelectedObject(id);
|
this.removeMultiSelectedObject(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { selection, contextItems: selected } = this.state.selection.getStateWithValue(id, obj, !!multi);
|
const elementSelection = this.state.selection ?? new ElementSelection([[id, obj.getRef()]]);
|
||||||
|
|
||||||
|
const { selection, contextItems: selected } = elementSelection.getStateWithValue(id, obj, !!multi);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selection: new ElementSelection(selection),
|
selection: new ElementSelection(selection),
|
||||||
@@ -120,14 +117,12 @@ export class DashboardEditPane extends SceneObjectBase<DashboardEditPaneState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public clearSelection() {
|
public clearSelection() {
|
||||||
const dashboard = getDashboardSceneFor(this);
|
if (!this.state.selection) {
|
||||||
|
|
||||||
if (this.state.selection?.getFirstObject() === dashboard) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selection: new ElementSelection([[dashboard.state.uid!, dashboard.getRef()]]),
|
selection: undefined,
|
||||||
selectionContext: {
|
selectionContext: {
|
||||||
...this.state.selectionContext,
|
...this.state.selectionContext,
|
||||||
selected: [],
|
selected: [],
|
||||||
@@ -138,6 +133,14 @@ export class DashboardEditPane extends SceneObjectBase<DashboardEditPaneState> {
|
|||||||
public onChangeTab = (tab: EditPaneTab) => {
|
public onChangeTab = (tab: EditPaneTab) => {
|
||||||
this.setState({ tab });
|
this.setState({ tab });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public newObjectAddedToCanvas(obj: SceneObject) {
|
||||||
|
this.selectObject(obj, obj.state.key!, false);
|
||||||
|
|
||||||
|
if (this.state.tab !== 'configure') {
|
||||||
|
this.onChangeTab('configure');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@@ -153,13 +156,6 @@ export interface Props {
|
|||||||
export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleCollapse, openOverlay }: Props) {
|
export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleCollapse, openOverlay }: Props) {
|
||||||
// Activate the edit pane
|
// Activate the edit pane
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editPane.state.selection) {
|
|
||||||
const dashboard = getDashboardSceneFor(editPane);
|
|
||||||
editPane.setState({
|
|
||||||
selection: new ElementSelection([[dashboard.state.uid!, dashboard.getRef()]]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
editPane.enableSelection();
|
editPane.enableSelection();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -168,7 +164,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla
|
|||||||
}, [editPane]);
|
}, [editPane]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isCollapsed && editPane.state.selection?.getSelectionEntries().length) {
|
if (isCollapsed) {
|
||||||
editPane.clearSelection();
|
editPane.clearSelection();
|
||||||
}
|
}
|
||||||
}, [editPane, isCollapsed]);
|
}, [editPane, isCollapsed]);
|
||||||
@@ -176,7 +172,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla
|
|||||||
const { selection, tab = 'configure' } = useSceneObjectState(editPane, { shouldActivateOrKeepAlive: true });
|
const { selection, tab = 'configure' } = useSceneObjectState(editPane, { shouldActivateOrKeepAlive: true });
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const paneRef = useRef<HTMLDivElement>(null);
|
const paneRef = useRef<HTMLDivElement>(null);
|
||||||
const editableElement = useEditableElement(selection);
|
const editableElement = useEditableElement(selection, editPane);
|
||||||
|
|
||||||
if (!editableElement) {
|
if (!editableElement) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -2,17 +2,21 @@ import { useMemo } from 'react';
|
|||||||
|
|
||||||
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
import { EditableDashboardElement } from '../scene/types/EditableDashboardElement';
|
||||||
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
import { MultiSelectedEditableDashboardElement } from '../scene/types/MultiSelectedEditableDashboardElement';
|
||||||
|
import { getDashboardSceneFor } from '../utils/utils';
|
||||||
|
|
||||||
|
import { DashboardEditPane } from './DashboardEditPane';
|
||||||
import { ElementSelection } from './ElementSelection';
|
import { ElementSelection } from './ElementSelection';
|
||||||
|
|
||||||
export function useEditableElement(
|
export function useEditableElement(
|
||||||
selection: ElementSelection | undefined
|
selection: ElementSelection | undefined,
|
||||||
|
editPane: DashboardEditPane
|
||||||
): EditableDashboardElement | MultiSelectedEditableDashboardElement | undefined {
|
): EditableDashboardElement | MultiSelectedEditableDashboardElement | undefined {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
return undefined;
|
const dashboard = getDashboardSceneFor(editPane);
|
||||||
|
return new ElementSelection([[dashboard.state.uid!, dashboard.getRef()]]).createSelectionElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
return selection.createSelectionElement();
|
return selection.createSelectionElement();
|
||||||
}, [selection]);
|
}, [selection, editPane]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,6 +452,21 @@ describe('DashboardScene', () => {
|
|||||||
expect(panel.state.key).toBe('panel-7');
|
expect(panel.state.key).toBe('panel-7');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should select new panel', () => {
|
||||||
|
const panel = scene.onCreateNewPanel();
|
||||||
|
expect(scene.state.editPane.state.selection?.getFirstObject()).toBe(panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should select new row', () => {
|
||||||
|
const row = scene.onCreateNewRow();
|
||||||
|
expect(scene.state.editPane.state.selection?.getFirstObject()).toBe(row);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should select new tab', () => {
|
||||||
|
const tab = scene.onCreateNewTab();
|
||||||
|
expect(scene.state.editPane.state.selection?.getFirstObject()).toBe(tab);
|
||||||
|
});
|
||||||
|
|
||||||
it('Should fail to copy a panel if it does not have a grid item parent', () => {
|
it('Should fail to copy a panel if it does not have a grid item parent', () => {
|
||||||
const vizPanel = new VizPanel({
|
const vizPanel = new VizPanel({
|
||||||
title: 'Panel Title',
|
title: 'Panel Title',
|
||||||
|
|||||||
@@ -488,7 +488,10 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> impleme
|
|||||||
this.onEnterEditMode();
|
this.onEnterEditMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add panel to layout
|
||||||
this.state.body.addPanel(vizPanel);
|
this.state.body.addPanel(vizPanel);
|
||||||
|
// Select panel
|
||||||
|
this.state.editPane.newObjectAddedToCanvas(vizPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public createLibraryPanel(panelToReplace: VizPanel, libPanel: LibraryPanel) {
|
public createLibraryPanel(panelToReplace: VizPanel, libPanel: LibraryPanel) {
|
||||||
@@ -596,18 +599,20 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onCreateNewRow() {
|
public onCreateNewRow() {
|
||||||
addNewRowTo(this.state.body);
|
const newRow = addNewRowTo(this.state.body);
|
||||||
|
this.state.editPane.newObjectAddedToCanvas(newRow);
|
||||||
|
return newRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onCreateNewTab() {
|
public onCreateNewTab() {
|
||||||
addNewTabTo(this.state.body);
|
const tab = addNewTabTo(this.state.body);
|
||||||
|
this.state.editPane.newObjectAddedToCanvas(tab);
|
||||||
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onCreateNewPanel(): VizPanel {
|
public onCreateNewPanel(): VizPanel {
|
||||||
const vizPanel = getDefaultVizPanel();
|
const vizPanel = getDefaultVizPanel();
|
||||||
|
|
||||||
this.addPanel(vizPanel);
|
this.addPanel(vizPanel);
|
||||||
|
|
||||||
return vizPanel;
|
return vizPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { Alert, Input, Switch, TextLink } from '@grafana/ui';
|
import { Alert, Input, RadioButtonGroup, Switch, TextLink } from '@grafana/ui';
|
||||||
import { t, Trans } from 'app/core/internationalization';
|
import { t, Trans } from 'app/core/internationalization';
|
||||||
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor';
|
||||||
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor';
|
||||||
@@ -22,19 +23,25 @@ export function getEditOptions(model: RowItem): OptionsPaneCategoryDescriptor[]
|
|||||||
const dashboard = getDashboardSceneFor(model);
|
const dashboard = getDashboardSceneFor(model);
|
||||||
|
|
||||||
const editPaneHeaderOptions = new OptionsPaneCategoryDescriptor({
|
const editPaneHeaderOptions = new OptionsPaneCategoryDescriptor({
|
||||||
title: t('dashboard.rows-layout.row-options.title', 'Row'),
|
title: t('dashboard.rows-layout.item-name', 'Row'),
|
||||||
id: 'row-options',
|
id: 'row-options',
|
||||||
isOpenable: false,
|
isOpenable: false,
|
||||||
renderTitle: () => (
|
renderTitle: () => (
|
||||||
<EditPaneHeader title={t('dashboard.rows-layout.row-options.title', 'Row')} onDelete={() => model.onDelete()} />
|
<EditPaneHeader title={t('dashboard.rows-layout.item-name', 'Row')} onDelete={() => model.onDelete()} />
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
.addItem(
|
.addItem(
|
||||||
new OptionsPaneItemDescriptor({
|
new OptionsPaneItemDescriptor({
|
||||||
title: t('dashboard.rows-layout.row-options.title-option', 'Title'),
|
title: t('dashboard.rows-layout.option.title', 'Title'),
|
||||||
render: () => <RowTitleInput row={model} />,
|
render: () => <RowTitleInput row={model} />,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.addItem(
|
||||||
|
new OptionsPaneItemDescriptor({
|
||||||
|
title: t('dashboard.rows-layout.option.height', 'Height'),
|
||||||
|
render: () => <RowHeightSelect row={model} />,
|
||||||
|
})
|
||||||
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
new OptionsPaneItemDescriptor({
|
new OptionsPaneItemDescriptor({
|
||||||
title: t('dashboard.layout.common.layout', 'Layout'),
|
title: t('dashboard.layout.common.layout', 'Layout'),
|
||||||
@@ -51,13 +58,13 @@ export function getEditOptions(model: RowItem): OptionsPaneCategoryDescriptor[]
|
|||||||
editPaneHeaderOptions
|
editPaneHeaderOptions
|
||||||
.addItem(
|
.addItem(
|
||||||
new OptionsPaneItemDescriptor({
|
new OptionsPaneItemDescriptor({
|
||||||
title: t('dashboard.rows-layout.row-options.repeat.variable.title', 'Repeat for'),
|
title: t('dashboard.rows-layout.option.repeat', 'Repeat for'),
|
||||||
render: () => <RowRepeatSelect row={model} dashboard={dashboard} />,
|
render: () => <RowRepeatSelect row={model} dashboard={dashboard} />,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
new OptionsPaneItemDescriptor({
|
new OptionsPaneItemDescriptor({
|
||||||
title: t('dashboard.rows-layout.row-options.height.hide-row-header', 'Hide row header'),
|
title: t('dashboard.rows-layout.option.hide-header', 'Hide row header'),
|
||||||
render: () => <RowHeaderSwitch row={model} />,
|
render: () => <RowHeaderSwitch row={model} />,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -86,6 +93,17 @@ function RowHeaderSwitch({ row }: { row: RowItem }) {
|
|||||||
return <Switch value={isHeaderHidden} onChange={() => row.onHeaderHiddenToggle()} />;
|
return <Switch value={isHeaderHidden} onChange={() => row.onHeaderHiddenToggle()} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function RowHeightSelect({ row }: { row: RowItem }) {
|
||||||
|
const { height = 'min' } = row.useState();
|
||||||
|
|
||||||
|
const options: Array<SelectableValue<'expand' | 'min'>> = [
|
||||||
|
{ label: t('dashboard.rows-layout.options.height-expand', 'Expand'), value: 'expand' },
|
||||||
|
{ label: t('dashboard.rows-layout.options.height-min', 'Min'), value: 'min' },
|
||||||
|
];
|
||||||
|
|
||||||
|
return <RadioButtonGroup options={options} value={height} onChange={(option) => row.onChangeHeight(option)} />;
|
||||||
|
}
|
||||||
|
|
||||||
function RowRepeatSelect({ row, dashboard }: { row: RowItem; dashboard: DashboardScene }) {
|
function RowRepeatSelect({ row, dashboard }: { row: RowItem; dashboard: DashboardScene }) {
|
||||||
const { layout } = row.useState();
|
const { layout } = row.useState();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { RowItem } from './RowItem';
|
|||||||
import { RowItemMenu } from './RowItemMenu';
|
import { RowItemMenu } from './RowItemMenu';
|
||||||
|
|
||||||
export function RowItemRenderer({ model }: SceneComponentProps<RowItem>) {
|
export function RowItemRenderer({ model }: SceneComponentProps<RowItem>) {
|
||||||
const { layout, title, isCollapsed, height = 'expand', isHeaderHidden, key } = model.useState();
|
const { layout, title, isCollapsed, height = 'min', isHeaderHidden, key } = model.useState();
|
||||||
const isClone = useMemo(() => isClonedKey(key!), [key]);
|
const isClone = useMemo(() => isClonedKey(key!), [key]);
|
||||||
const dashboard = getDashboardSceneFor(model);
|
const dashboard = getDashboardSceneFor(model);
|
||||||
const { isEditing, showHiddenElements } = dashboard.useState();
|
const { isEditing, showHiddenElements } = dashboard.useState();
|
||||||
|
|||||||
@@ -69,8 +69,10 @@ export class RowsLayoutManager extends SceneObjectBase<RowsLayoutManagerState> i
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public addNewRow() {
|
public addNewRow(): RowItem {
|
||||||
this.setState({ rows: [...this.state.rows, new RowItem()] });
|
const row = new RowItem();
|
||||||
|
this.setState({ rows: [...this.state.rows, row] });
|
||||||
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
public editModeChanged(isEditing: boolean) {
|
public editModeChanged(isEditing: boolean) {
|
||||||
|
|||||||
@@ -86,8 +86,9 @@ export class TabsLayoutManager extends SceneObjectBase<TabsLayoutManagerState> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addNewTab() {
|
public addNewTab() {
|
||||||
const currentTab = new TabItem();
|
const newTab = new TabItem();
|
||||||
this.setState({ tabs: [...this.state.tabs, currentTab], currentTabIndex: this.state.tabs.length });
|
this.setState({ tabs: [...this.state.tabs, newTab], currentTabIndex: this.state.tabs.length });
|
||||||
|
return newTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public editModeChanged(isEditing: boolean) {
|
public editModeChanged(isEditing: boolean) {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { SceneObject } from '@grafana/scenes';
|
import { SceneGridRow, SceneObject } from '@grafana/scenes';
|
||||||
|
|
||||||
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager';
|
||||||
|
import { RowItem } from '../layout-rows/RowItem';
|
||||||
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
import { RowsLayoutManager } from '../layout-rows/RowsLayoutManager';
|
||||||
|
import { TabItem } from '../layout-tabs/TabItem';
|
||||||
import { TabsLayoutManager } from '../layout-tabs/TabsLayoutManager';
|
import { TabsLayoutManager } from '../layout-tabs/TabsLayoutManager';
|
||||||
import { isLayoutParent } from '../types/LayoutParent';
|
import { isLayoutParent } from '../types/LayoutParent';
|
||||||
|
|
||||||
export function addNewTabTo(sceneObject: SceneObject) {
|
export function addNewTabTo(sceneObject: SceneObject): TabItem {
|
||||||
if (sceneObject instanceof TabsLayoutManager) {
|
if (sceneObject instanceof TabsLayoutManager) {
|
||||||
sceneObject.addNewTab();
|
return sceneObject.addNewTab();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const layoutParent = sceneObject.parent!;
|
const layoutParent = sceneObject.parent!;
|
||||||
@@ -16,24 +17,24 @@ export function addNewTabTo(sceneObject: SceneObject) {
|
|||||||
throw new Error('Parent layout is not a LayoutParent');
|
throw new Error('Parent layout is not a LayoutParent');
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutParent.switchLayout(TabsLayoutManager.createFromLayout(layoutParent.getLayout()));
|
const tabsLayout = TabsLayoutManager.createFromLayout(layoutParent.getLayout());
|
||||||
|
layoutParent.switchLayout(tabsLayout);
|
||||||
|
|
||||||
|
return tabsLayout.state.tabs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addNewRowTo(sceneObject: SceneObject) {
|
export function addNewRowTo(sceneObject: SceneObject): RowItem | SceneGridRow {
|
||||||
if (sceneObject instanceof RowsLayoutManager) {
|
if (sceneObject instanceof RowsLayoutManager) {
|
||||||
sceneObject.addNewRow();
|
return sceneObject.addNewRow();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sceneObject instanceof DefaultGridLayoutManager) {
|
if (sceneObject instanceof DefaultGridLayoutManager) {
|
||||||
sceneObject.addNewRow();
|
return sceneObject.addNewRow();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sceneObject instanceof TabsLayoutManager) {
|
if (sceneObject instanceof TabsLayoutManager) {
|
||||||
const currentTab = sceneObject.getCurrentTab();
|
const currentTab = sceneObject.getCurrentTab();
|
||||||
addNewRowTo(currentTab.state.layout);
|
return addNewRowTo(currentTab.state.layout);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const layoutParent = sceneObject.parent!;
|
const layoutParent = sceneObject.parent!;
|
||||||
@@ -41,5 +42,8 @@ export function addNewRowTo(sceneObject: SceneObject) {
|
|||||||
throw new Error('Parent layout is not a LayoutParent');
|
throw new Error('Parent layout is not a LayoutParent');
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutParent.switchLayout(RowsLayoutManager.createFromLayout(layoutParent.getLayout()));
|
const rowsLayout = RowsLayoutManager.createFromLayout(layoutParent.getLayout());
|
||||||
|
layoutParent.switchLayout(rowsLayout);
|
||||||
|
|
||||||
|
return rowsLayout.state.rows[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1214,7 +1214,18 @@
|
|||||||
},
|
},
|
||||||
"rows-layout": {
|
"rows-layout": {
|
||||||
"description": "Rows layout",
|
"description": "Rows layout",
|
||||||
|
"item-name": "Row",
|
||||||
"name": "Rows",
|
"name": "Rows",
|
||||||
|
"option": {
|
||||||
|
"height": "Height",
|
||||||
|
"hide-header": "Hide row header",
|
||||||
|
"repeat": "Repeat for",
|
||||||
|
"title": "Title"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"height-expand": "Expand",
|
||||||
|
"height-min": "Min"
|
||||||
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"collapse": "Collapse row",
|
"collapse": "Collapse row",
|
||||||
"expand": "Expand row",
|
"expand": "Expand row",
|
||||||
@@ -1234,15 +1245,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"row-options": {
|
"row-options": {
|
||||||
"height": {
|
|
||||||
"hide-row-header": "Hide row header"
|
|
||||||
},
|
|
||||||
"repeat": {
|
|
||||||
"variable": {
|
|
||||||
"title": "Repeat for"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"title": "Row",
|
|
||||||
"title-option": "Title"
|
"title-option": "Title"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1214,7 +1214,18 @@
|
|||||||
},
|
},
|
||||||
"rows-layout": {
|
"rows-layout": {
|
||||||
"description": "Ŗőŵş ľäyőūŧ",
|
"description": "Ŗőŵş ľäyőūŧ",
|
||||||
|
"item-name": "Ŗőŵ",
|
||||||
"name": "Ŗőŵş",
|
"name": "Ŗőŵş",
|
||||||
|
"option": {
|
||||||
|
"height": "Ħęįģĥŧ",
|
||||||
|
"hide-header": "Ħįđę řőŵ ĥęäđęř",
|
||||||
|
"repeat": "Ŗępęäŧ ƒőř",
|
||||||
|
"title": "Ŧįŧľę"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"height-expand": "Ēχpäʼnđ",
|
||||||
|
"height-min": "Mįʼn"
|
||||||
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"collapse": "Cőľľäpşę řőŵ",
|
"collapse": "Cőľľäpşę řőŵ",
|
||||||
"expand": "Ēχpäʼnđ řőŵ",
|
"expand": "Ēχpäʼnđ řőŵ",
|
||||||
@@ -1234,15 +1245,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"row-options": {
|
"row-options": {
|
||||||
"height": {
|
|
||||||
"hide-row-header": "Ħįđę řőŵ ĥęäđęř"
|
|
||||||
},
|
|
||||||
"repeat": {
|
|
||||||
"variable": {
|
|
||||||
"title": "Ŗępęäŧ ƒőř"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"title": "Ŗőŵ",
|
|
||||||
"title-option": "Ŧįŧľę"
|
"title-option": "Ŧįŧľę"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user