mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 19:48:37 -05:00
initial PR for table designer feature (#17200)
* wip * wire up e2e * hook up styler and add as dataprotocal feature * designer child component rendering * table component updates * styler and selectbox column editor * fix editor size and dupe component creation issue * fix checkbox column and add more testing data * properties pane * only rerender when needed * properties pane update * update commands * cleanup for PR * revert unwanted changes * Adding a few tests for Add SQL binding (#17079) * initial changes * add a couple more tests * LEGO: check in for main to temporary branch. (#17089) * LEGO: check in for main to temporary branch. (#17091) Co-authored-by: kburtram <karlb@microsoft.com> * Adds autorest-based SQL Project generation to SQL Database Projects extension (#17078) * Initial changes * checkpoint * Constructing project with post deployment script * Correcting to intentionally read from cached list of projects * Adding activation event, fixing fresh workspace bug * Convert netcoreTool and autorestHelper to share a helper class for streamed command * Include npm package version to force update * test checkpoint * Unit tests * Added contextual quickpicks for autorest dialogs * Adding projectController test * Added projectController test, some refactoring for testability * Merge branch 'main' into benjin/autorest * Fixing 'which' import * PR feedback * Fixing tests * Adding additional information for when project provider tests fail * Hopefully fixing failing tests (unable to repro locally) * Adding Generate Project item to workspace menu * PR feedback * LEGO: check in for main to temporary branch. (#17097) * added sql database projects strings (#17100) * Set kernelAlias in startSession when isValidConnection is truthy (#17102) * PR follow-up comments (#17113) * Change recompare message after changing options to modal (#17103) * Change recompare message to modal * change options to yes and no * Remove commented code block in git extension (#17116) * Remove commented code block in git extension * Add SQL CARBON EDIT tag * [Loc] Small change to generatingProjectFailed (#17118) * Add Null Shortcut and added NULL text for default NULL value. (#17085) * added test key event * added null function to tryHandleKeyEvent * added null formatting * added working null insert. * added editDataGridPanel string null support * Bump nth-check from 2.0.0 to 2.0.1 in /build (#17115) Bumps [nth-check](https://github.com/fb55/nth-check) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/fb55/nth-check/releases) - [Commits](https://github.com/fb55/nth-check/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: nth-check dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add excludeFlags to extenson marketplace query (#17121) * Add excludeFlags to extenson marketplace query * Remove dead code * Remove extraneous blank line * Address code review feedback * Adding Derived Columns to ADS Flatfile Import (#16795) * Adding derived column boilerplate * brandan preliminary frontend changes * empty commit * added new param * updating contracts, dialogue changes * utils changes, saving timeout attempt * pushing for aasim * Cleaning up code and fixing the issue in theory * changing button, did not solve independent scroll * Fixing the scroll bar issue * updating flat file service * adding override keyword to overrriden method * improving UI * pushing changes associated with resolved comments * localizing strings, editing comments * all comments resolved * Fixing a test * updating import package Updating azure MFA bug * Clearing navigation validator Fixing broken table name change * fixed prose test * removing unused code from tests * Fixed PR comments * Fixing some PR comments * WIP * Fixing transformation code and create derived column dialog styling * removing unused code * Adding comment for console log * fixed table styling * Adding some aria labels * Fixed some code cleanup issues * update import service Co-authored-by: Aasim Khan <aasimkhan30@gmail.com> Co-authored-by: bnhoule <t-bhoule@microsoft.com> * Change keybindings for copying query with Results (#17127) Co-authored-by: Monica Gupta <mogupt@microsoft.com> * sql proj - publish to docker improvements (#17124) * Add AAD token expiration handling for query runner (#17117) * Add AAD token refresh for notebook * move token refresh to query management and remove previous refresh calls * Add guids to RunAll and RunCell events (#17123) Add guids to RunAll and RunCell events * add error banner for failed migration cutover and cancel migration (#17106) * [Loc] update to sql migration, database projects and import extension strings (#17130) * Apply optional storage class settings in sql mi create command (#17129) * Make storage classes optional * Fix notebook to use storage class options Co-authored-by: Charmaine Chan <chachan@microsoft.com> * Add support for adding new setting in local.settings.json in add SQL binding quickpick (#17093) * be able to add new setting in local.settings.json * cleanup * addressing comments * remove todo comment * addressing comments * update some strings to uris * bump version of sqltoolsservice (#17133) * mark schema compare tests as unstable (#17140) * [Loc] Update for arc and sql-database-projects (#17148) * ML extension vbump (#17143) * Configure docker image and web smoke tests for ADSWeb. (#17136) * Adjusts timeout period * Revert "Adjusts timeout period" This reverts commit 0f372eae2a4611554093b6c09f1ff6c451132e19. * Adds firefox as browser option * Corrects yaml smoke test script * Resets args array to original values * Corrects build path * Resolves ignoring browser option error * continue even after writing to stderr * Adjusts smoke test (browser) script * More adjustments to smoke test script * Corrects server path * Uses build variable directly in build path * Specifies browser type since cannot be ignored error * Adds browser option * Updates web build image and corrects smoke test exe command * Removes commented out task * Updates dockerfile to support web smoketests * Removes failOnStderr flag * Use curl instead of wget in Dockerfile * Fixed a bug with cancling publish (#17160) * Save And Close Functionality (#17000) * save and close * wip * working save and close * cleanup * pr changes * pr changes * fix capitalization * fix build * pr fix * Added dynamic options for SQL MIAA Deployment Wizard and updated checkbox field (#17119) * Dynamic enablement * Added new package.json field for dynamic options and corresponding functions and classes. * Enabled dynamic options non-generalized and changed formatting of checkbox to have label on the left. * Added setOptions under InputComponentInfo for generalization, comments under checkbox component, and changed Replicas to High Availability to reflect parity in portal. * fix unit test Co-authored-by: Candice Ye <canye@microsoft.com> Co-authored-by: Alan Ren <alanren@microsoft.com> * LEGO: check in for main to temporary branch. (#17168) * [Loc] added new arc strings and fix for sql-database-projects lcl file for Japanese (#17171) * [Loc] added new arc strings and fix for sql-database-projects xlf * removed newline * Port of Vscode fix for colors too close (#17146) * default light colors list.focusHighlightForeground too close to list.activeSelectionBackground. Fixes #127597 * remove activeSelectionBackground from theme-carbon as it conflicts with vscode. * remove dark carbon background Co-authored-by: Martin Aeschlimann <martinae@microsoft.com> * Markdown Horizontal Scrollbar Fix (#17083) * dynamically change horizontal scrollbar * working horizontal scrollbar * created new event to handle both scrollbar and mouse wheel * only show scrollbar when needed * LEGO: check in for main to temporary branch. (#17181) * Bump axios to 0.21.4 (#17161) * Kusto version bump to 0.5.6 (#17114) * Bumped Kusto toolsservice version to 125 and bumped version to 0.5.6 * Changed netcoreapp3.1 to net5.0 in Kusto config.json * AzureMonitor bump ToolService version and extension version. (#17174) * Bump concat-with-sourcemaps from 1.0.4 to 1.1.0 (#17158) Bumps [concat-with-sourcemaps](https://github.com/floridoo/concat-with-sourcemaps) from 1.0.4 to 1.1.0. - [Release notes](https://github.com/floridoo/concat-with-sourcemaps/releases) - [Commits](https://github.com/floridoo/concat-with-sourcemaps/commits) --- updated-dependencies: - dependency-name: concat-with-sourcemaps dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update service downloader to 0.2.3 (#17186) * Notebook Views grid fixes (#17170) * update data workspace restart ADS to open workspace message (#17188) * update message * update string * Add back "Remove Project" (#17178) * remove project working with full paths * use relative paths * const * addressing comments * Bump github-auth axios to 0.21.4 (#17189) * LEGO: check in for main to temporary branch. (#17192) * LEGO: check in for main to temporary branch. (#17190) Co-authored-by: kburtram <karlb@microsoft.com> * [Loc] Add a small change to dataworkspace (#17194) * added bump to sqltoolsservice version (#17195) * Check if file is dirty before adding sql binding (#17175) * check if file is dirty before adding sql binding * Addressing comments * Add vertical scroll bar to Preview in Split View (#17164) * reset max height * add editor height * set md editor height * Split up NotebookProvider into separate providers for handling file serialization and cell execution. (#17176) * fix floating promises * pr comments * reuse component definition * comments * fix error Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com> Co-authored-by: csigs <csigs@users.noreply.github.com> Co-authored-by: kburtram <karlb@microsoft.com> Co-authored-by: Benjin Dubishar <benjin.dubishar@gmail.com> Co-authored-by: Alex Ma <alma1@microsoft.com> Co-authored-by: Justin M <63619224+JustinMDotNet@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: bnhoule <52506119+bnhoule@users.noreply.github.com> Co-authored-by: Aasim Khan <aasimkhan30@gmail.com> Co-authored-by: bnhoule <t-bhoule@microsoft.com> Co-authored-by: Monica Gupta <scorpio90m@gmail.com> Co-authored-by: Monica Gupta <mogupt@microsoft.com> Co-authored-by: Leila Lali <llali@microsoft.com> Co-authored-by: Hai Cao <hacao@microsoft.com> Co-authored-by: Daniel Grajeda <dagrajed@microsoft.com> Co-authored-by: brian-harris <61598682+brian-harris@users.noreply.github.com> Co-authored-by: Charmaine Chan <69230572+charmainewkchan@users.noreply.github.com> Co-authored-by: Charmaine Chan <chachan@microsoft.com> Co-authored-by: Lewis Sanchez <87730006+lewis-sanchez@users.noreply.github.com> Co-authored-by: Christopher Suh <chsuh@microsoft.com> Co-authored-by: Candice Ye <candiceye@berkeley.edu> Co-authored-by: Candice Ye <canye@microsoft.com> Co-authored-by: Martin Aeschlimann <martinae@microsoft.com> Co-authored-by: Vasu Bhog <vabhog@microsoft.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> Co-authored-by: Barbara Valdez <34872381+barbaravaldez@users.noreply.github.com> Co-authored-by: Cory Rivera <corivera@microsoft.com>
This commit is contained in:
480
src/sql/base/browser/ui/designer/designer.ts
Normal file
480
src/sql/base/browser/ui/designer/designer.ts
Normal file
@@ -0,0 +1,480 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DesignerComponentInput, DesignerEditType, DesignerTab, DesignerEdit, DesignerEditIdentifier, DesignerData, DesignerDataPropertyInfo, DesignerTableComponentRowData, DesignerTableProperties, InputBoxProperties, DropDownProperties, CheckBoxProperties, DesignerComponentTypeName } from 'sql/base/browser/ui/designer/interfaces';
|
||||
import { IPanelTab, ITabbedPanelStyles, TabbedPanel } from 'sql/base/browser/ui/panel/panel';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInputBoxStyles, InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import 'vs/css!./media/designer';
|
||||
import { ITableStyles } from 'sql/base/browser/ui/table/interfaces';
|
||||
import { IThemable } from 'vs/base/common/styler';
|
||||
import { Checkbox, ICheckboxStyles } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||
import { Table } from 'sql/base/browser/ui/table/table';
|
||||
import { ISelectBoxStyles, SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||
import { localize } from 'vs/nls';
|
||||
import { TableCellEditorFactory } from 'sql/base/browser/ui/table/tableCellEditorFactory';
|
||||
import { CheckBoxColumn } from 'sql/base/browser/ui/table/plugins/checkboxColumn.plugin';
|
||||
import { DesignerTabPanelView } from 'sql/base/browser/ui/designer/designerTabPanelView';
|
||||
import { DesignerPropertiesPane, PropertiesPaneObjectContext } from 'sql/base/browser/ui/designer/designerPropertiesPane';
|
||||
|
||||
export interface IDesignerStyle {
|
||||
tabbedPanelStyles?: ITabbedPanelStyles;
|
||||
inputBoxStyles?: IInputBoxStyles;
|
||||
tableStyles?: ITableStyles;
|
||||
selectBoxStyles?: ISelectBoxStyles;
|
||||
checkboxStyles?: ICheckboxStyles;
|
||||
}
|
||||
|
||||
export type DesignerUIComponent = InputBox | Checkbox | Table<Slick.SlickData> | SelectBox;
|
||||
|
||||
export type CreateComponentFunc = (container: HTMLElement, component: DesignerDataPropertyInfo, editIdentifier: DesignerEditIdentifier) => DesignerUIComponent;
|
||||
export type SetComponentValueFunc = (definition: DesignerDataPropertyInfo, component: DesignerUIComponent, data: DesignerData) => void;
|
||||
|
||||
export class Designer extends Disposable implements IThemable {
|
||||
|
||||
private _horizontalSplitViewContainer: HTMLElement;
|
||||
private _verticalSplitViewContainer: HTMLElement;
|
||||
private _tabbedPanelContainer: HTMLElement;
|
||||
private _editorContainer: HTMLElement;
|
||||
private _horizontalSplitView: SplitView;
|
||||
private _verticalSplitView: SplitView;
|
||||
private _tabbedPanel: TabbedPanel;
|
||||
private _contentContainer: HTMLElement;
|
||||
private _topContentContainer: HTMLElement;
|
||||
private _propertiesPaneContainer: HTMLElement;
|
||||
private _styles: IDesignerStyle = {};
|
||||
private _supressEditProcessing: boolean = false;
|
||||
private _componentMap = new Map<string, { defintion: DesignerDataPropertyInfo, component: DesignerUIComponent }>();
|
||||
private _input: DesignerComponentInput;
|
||||
private _tableCellEditorFactory: TableCellEditorFactory;
|
||||
private _propertiesPane: DesignerPropertiesPane;
|
||||
|
||||
constructor(private readonly _container: HTMLElement,
|
||||
private readonly _contextViewProvider: IContextViewProvider) {
|
||||
super();
|
||||
this._tableCellEditorFactory = new TableCellEditorFactory(
|
||||
{
|
||||
valueGetter: (item, column): string => {
|
||||
return item[column.field].value;
|
||||
},
|
||||
valueSetter: async (context: string, row: number, item: DesignerTableComponentRowData, column: Slick.Column<Slick.SlickData>, value: string): Promise<void> => {
|
||||
await this.handleEdit({
|
||||
type: DesignerEditType.Update,
|
||||
property: {
|
||||
parentProperty: context,
|
||||
index: row,
|
||||
property: column.field
|
||||
},
|
||||
value: value
|
||||
});
|
||||
},
|
||||
optionsGetter: (item, column): string[] => {
|
||||
return item[column.field].options;
|
||||
},
|
||||
editorStyler: (component) => {
|
||||
this.styleComponent(component);
|
||||
}
|
||||
}, this._contextViewProvider
|
||||
);
|
||||
this._verticalSplitViewContainer = DOM.$('.designer-component');
|
||||
this._horizontalSplitViewContainer = DOM.$('.container');
|
||||
this._contentContainer = DOM.$('.content-container');
|
||||
this._topContentContainer = DOM.$('.top-content-container.components-grid');
|
||||
this._tabbedPanelContainer = DOM.$('.tabbed-panel-container');
|
||||
this._editorContainer = DOM.$('.editor-container');
|
||||
this._propertiesPaneContainer = DOM.$('.properties-container');
|
||||
this._verticalSplitView = new SplitView(this._verticalSplitViewContainer, { orientation: Orientation.VERTICAL });
|
||||
this._horizontalSplitView = new SplitView(this._horizontalSplitViewContainer, { orientation: Orientation.HORIZONTAL });
|
||||
this._tabbedPanel = new TabbedPanel(this._tabbedPanelContainer);
|
||||
this._container.appendChild(this._verticalSplitViewContainer);
|
||||
this._contentContainer.appendChild(this._topContentContainer);
|
||||
this._contentContainer.appendChild(this._tabbedPanelContainer);
|
||||
this._verticalSplitView.addView({
|
||||
element: this._horizontalSplitViewContainer,
|
||||
layout: size => {
|
||||
this.layoutTabbedPanel();
|
||||
},
|
||||
minimumSize: 200,
|
||||
maximumSize: Number.POSITIVE_INFINITY,
|
||||
onDidChange: Event.None
|
||||
}, Sizing.Distribute);
|
||||
|
||||
this._verticalSplitView.addView({
|
||||
element: this._editorContainer,
|
||||
layout: size => { },
|
||||
minimumSize: 100,
|
||||
maximumSize: Number.POSITIVE_INFINITY,
|
||||
onDidChange: Event.None
|
||||
}, Sizing.Distribute);
|
||||
|
||||
this._horizontalSplitView.addView({
|
||||
element: this._contentContainer,
|
||||
layout: size => {
|
||||
this.layoutTabbedPanel();
|
||||
},
|
||||
minimumSize: 200,
|
||||
maximumSize: Number.POSITIVE_INFINITY,
|
||||
onDidChange: Event.None
|
||||
}, Sizing.Distribute);
|
||||
|
||||
this._horizontalSplitView.addView({
|
||||
element: this._propertiesPaneContainer,
|
||||
layout: size => { },
|
||||
minimumSize: 200,
|
||||
maximumSize: Number.POSITIVE_INFINITY,
|
||||
onDidChange: Event.None
|
||||
}, Sizing.Distribute);
|
||||
|
||||
this._propertiesPane = new DesignerPropertiesPane(this._propertiesPaneContainer, (container, component, identifier) => {
|
||||
return this.createComponent(container, component, identifier, false, false);
|
||||
}, (definition, component, data) => {
|
||||
this.setComponentValue(definition, component, data);
|
||||
}, (component) => {
|
||||
this.styleComponent(component);
|
||||
});
|
||||
const editor = DOM.$('div');
|
||||
editor.innerText = 'script pane placeholder';
|
||||
this._editorContainer.appendChild(editor);
|
||||
}
|
||||
|
||||
private styleComponent(component: TabbedPanel | InputBox | Checkbox | Table<Slick.SlickData> | SelectBox): void {
|
||||
if (component instanceof InputBox) {
|
||||
component.style(this._styles.inputBoxStyles);
|
||||
} else if (component instanceof Checkbox) {
|
||||
component.style(this._styles.checkboxStyles);
|
||||
} else if (component instanceof TabbedPanel) {
|
||||
component.style(this._styles.tabbedPanelStyles);
|
||||
} else if (component instanceof Table) {
|
||||
component.style(this._styles.tableStyles);
|
||||
} else {
|
||||
component.style(this._styles.selectBoxStyles);
|
||||
}
|
||||
}
|
||||
public style(styles: IDesignerStyle): void {
|
||||
this._styles = styles;
|
||||
this._componentMap.forEach((value, key, map) => {
|
||||
if (value.component.style) {
|
||||
this.styleComponent(value.component);
|
||||
}
|
||||
});
|
||||
this._propertiesPane.style();
|
||||
this._verticalSplitView.style({
|
||||
separatorBorder: styles.selectBoxStyles.selectBorder
|
||||
});
|
||||
|
||||
this._horizontalSplitView.style({
|
||||
separatorBorder: styles.selectBoxStyles.selectBorder
|
||||
});
|
||||
}
|
||||
|
||||
public layout(dimension: DOM.Dimension) {
|
||||
this._verticalSplitView.layout(dimension.height);
|
||||
this._horizontalSplitView.layout(dimension.width);
|
||||
}
|
||||
|
||||
|
||||
public async setInput(input: DesignerComponentInput): Promise<void> {
|
||||
this._input = input;
|
||||
await this.initializeDesignerView();
|
||||
}
|
||||
|
||||
private async initializeDesignerView(): Promise<void> {
|
||||
this._propertiesPane.clear();
|
||||
DOM.clearNode(this._topContentContainer);
|
||||
const view = await this._input.getView();
|
||||
if (view.components) {
|
||||
view.components.forEach(component => {
|
||||
this.createComponent(this._topContentContainer, component, component.propertyName, true, true);
|
||||
});
|
||||
}
|
||||
this._tabbedPanel.clearTabs();
|
||||
view.tabs.forEach(tab => {
|
||||
this._tabbedPanel.pushTab(this.createTabView(tab));
|
||||
});
|
||||
this.layoutTabbedPanel();
|
||||
await this.updateComponentValues();
|
||||
}
|
||||
|
||||
private layoutTabbedPanel() {
|
||||
this._tabbedPanel.layout(new DOM.Dimension(this._tabbedPanelContainer.clientWidth, this._tabbedPanelContainer.clientHeight));
|
||||
}
|
||||
|
||||
private async updateComponentValues(): Promise<void> {
|
||||
const data = await this._input.getData();
|
||||
// data[ScriptPropertyName] -- todo- set the script editor
|
||||
this._componentMap.forEach((value) => {
|
||||
this.setComponentValue(value.defintion, value.component, data);
|
||||
});
|
||||
|
||||
let type: string;
|
||||
let components: DesignerDataPropertyInfo[];
|
||||
let inputData: DesignerData;
|
||||
let context: PropertiesPaneObjectContext;
|
||||
const currentContext = this._propertiesPane.context;
|
||||
if (currentContext === 'root' || currentContext === undefined) {
|
||||
context = 'root';
|
||||
components = [];
|
||||
this._componentMap.forEach(value => {
|
||||
components.push(value.defintion);
|
||||
});
|
||||
type = this._input.objectTypeDisplayName;
|
||||
inputData = data;
|
||||
} else {
|
||||
context = currentContext;
|
||||
const tableData = data[currentContext.parentProperty] as DesignerTableProperties;
|
||||
const tableProperties = this._componentMap.get(currentContext.parentProperty).defintion.componentProperties as DesignerTableProperties;
|
||||
inputData = tableData.data[currentContext.index] as DesignerData;
|
||||
components = tableProperties.itemProperties;
|
||||
type = tableProperties.objectTypeDisplayName;
|
||||
}
|
||||
this._propertiesPane.show({
|
||||
context: context,
|
||||
type: type,
|
||||
components: components,
|
||||
data: inputData
|
||||
});
|
||||
}
|
||||
|
||||
private async handleEdit(edit: DesignerEdit): Promise<void> {
|
||||
if (this._supressEditProcessing) {
|
||||
return;
|
||||
}
|
||||
await this.applyEdit(edit);
|
||||
const result = await this._input.processEdit(edit);
|
||||
if (result.isValid) {
|
||||
this._supressEditProcessing = true;
|
||||
await this.updateComponentValues();
|
||||
this._supressEditProcessing = false;
|
||||
} else {
|
||||
//TODO: add error notification
|
||||
}
|
||||
}
|
||||
|
||||
private async applyEdit(edit: DesignerEdit): Promise<void> {
|
||||
const data = await this._input.getData();
|
||||
switch (edit.type) {
|
||||
case DesignerEditType.Update:
|
||||
if (typeof edit.property === 'string') {
|
||||
// if the type of the property is string then the property is a top level property
|
||||
const componentData = data[edit.property];
|
||||
const componentType = this._componentMap.get(edit.property).defintion.componentType;
|
||||
this.setComponentData(componentType, componentData, edit.value);
|
||||
} else {
|
||||
const columnPropertyName = edit.property.property;
|
||||
const tableInfo = this._componentMap.get(edit.property.parentProperty).defintion.componentProperties as DesignerTableProperties;
|
||||
const tableProperties = data[edit.property.parentProperty] as DesignerTableProperties;
|
||||
const componentData = tableProperties.data[edit.property.index][columnPropertyName];
|
||||
const itemProperty = tableInfo.itemProperties.find(property => property.propertyName === columnPropertyName);
|
||||
if (itemProperty) {
|
||||
this.setComponentData(itemProperty.componentType, componentData, edit.value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private setComponentData(componentType: DesignerComponentTypeName, componentData: any, value: any): void {
|
||||
switch (componentType) {
|
||||
case 'checkbox':
|
||||
(<CheckBoxProperties>componentData).checked = value;
|
||||
break;
|
||||
case 'dropdown':
|
||||
(<DropDownProperties>componentData).value = value;
|
||||
break;
|
||||
case 'input':
|
||||
(<InputBoxProperties>componentData).value = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private createTabView(tab: DesignerTab): IPanelTab {
|
||||
const view = new DesignerTabPanelView(tab, (container, component, identifier) => {
|
||||
return this.createComponent(container, component, identifier, true, false);
|
||||
});
|
||||
return {
|
||||
identifier: tab.title,
|
||||
title: tab.title,
|
||||
view: view
|
||||
};
|
||||
}
|
||||
|
||||
private setComponentValue(definition: DesignerDataPropertyInfo, component: DesignerUIComponent, data: DesignerData): void {
|
||||
this._supressEditProcessing = true;
|
||||
switch (definition.componentType) {
|
||||
case 'input':
|
||||
const input = component as InputBox;
|
||||
const inputData = data[definition.propertyName] as InputBoxProperties;
|
||||
input.setEnabled(inputData.enabled ?? true);
|
||||
input.value = inputData.value?.toString() ?? '';
|
||||
break;
|
||||
case 'table':
|
||||
const table = component as Table<Slick.SlickData>;
|
||||
const tableDataView = table.getData() as TableDataView<Slick.SlickData>;
|
||||
tableDataView.clear();
|
||||
tableDataView.push((data[definition.propertyName] as DesignerTableProperties).data);
|
||||
table.rerenderGrid();
|
||||
break;
|
||||
case 'checkbox':
|
||||
const checkbox = component as Checkbox;
|
||||
const checkboxData = data[definition.propertyName] as CheckBoxProperties;
|
||||
if (checkboxData.enabled === false) {
|
||||
checkbox.disable();
|
||||
} else {
|
||||
checkbox.enable();
|
||||
}
|
||||
checkbox.checked = checkboxData.checked;
|
||||
break;
|
||||
case 'dropdown':
|
||||
const dropdown = component as SelectBox;
|
||||
const defaultDropdownData = definition.componentProperties as DropDownProperties;
|
||||
const dropdownData = data[definition.propertyName] as DropDownProperties;
|
||||
if (dropdownData.enabled === false) {
|
||||
dropdown.disable();
|
||||
} else {
|
||||
dropdown.enable();
|
||||
}
|
||||
const options = (dropdownData.values || defaultDropdownData.values || []) as string[];
|
||||
dropdown.setOptions(options);
|
||||
const idx = options?.indexOf(dropdownData.value as string);
|
||||
if (idx > -1) {
|
||||
dropdown.select(idx);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this._supressEditProcessing = false;
|
||||
}
|
||||
|
||||
private createComponent(container: HTMLElement, componentDefinition: DesignerDataPropertyInfo, editIdentifier: DesignerEditIdentifier, addToComponentMap: boolean, setWidth: boolean): DesignerUIComponent {
|
||||
const componentContainerClass = componentDefinition.componentType === 'table' ? '.full-row' : '';
|
||||
const labelContainer = container.appendChild(DOM.$(componentContainerClass));
|
||||
labelContainer.appendChild(DOM.$('span.component-label')).innerText = (componentDefinition.componentType === 'checkbox' || componentDefinition.componentProperties?.title === undefined) ? '' : componentDefinition.componentProperties.title;
|
||||
const componentDiv = container.appendChild(DOM.$(componentContainerClass));
|
||||
let component: DesignerUIComponent;
|
||||
switch (componentDefinition.componentType) {
|
||||
case 'input':
|
||||
const inputProperties = componentDefinition.componentProperties as InputBoxProperties;
|
||||
const input = new InputBox(componentDiv, this._contextViewProvider, {
|
||||
ariaLabel: inputProperties.title,
|
||||
type: inputProperties.inputType,
|
||||
});
|
||||
input.onDidChange(async (newValue) => {
|
||||
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: newValue });
|
||||
});
|
||||
if (setWidth && inputProperties.width !== undefined) {
|
||||
input.width = inputProperties.width as number;
|
||||
}
|
||||
component = input;
|
||||
break;
|
||||
case 'dropdown':
|
||||
const dropdownProperties = componentDefinition.componentProperties as DropDownProperties;
|
||||
const dropdown = new SelectBox(dropdownProperties.values as string[], undefined, this._contextViewProvider, undefined);
|
||||
dropdown.render(componentDiv);
|
||||
dropdown.selectElem.style.height = '25px';
|
||||
dropdown.onDidSelect(async (e) => {
|
||||
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: e.selected });
|
||||
});
|
||||
component = dropdown;
|
||||
break;
|
||||
case 'checkbox':
|
||||
const checkboxProperties = componentDefinition.componentProperties as CheckBoxProperties;
|
||||
const checkbox = new Checkbox(componentDiv, {
|
||||
label: checkboxProperties.title
|
||||
});
|
||||
checkbox.onChange(async (newValue) => {
|
||||
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: newValue });
|
||||
});
|
||||
component = checkbox;
|
||||
break;
|
||||
case 'table':
|
||||
const tableProperties = componentDefinition.componentProperties as DesignerTableProperties;
|
||||
const table = new Table(componentDiv, {
|
||||
dataProvider: new TableDataView()
|
||||
}, {
|
||||
editable: true,
|
||||
autoEdit: true,
|
||||
dataItemColumnValueExtractor: (data: any, column: Slick.Column<Slick.SlickData>): string => {
|
||||
return data[column.field].value;
|
||||
}
|
||||
}
|
||||
);
|
||||
table.columns = tableProperties.columns.map(propName => {
|
||||
const propertyDefinition = tableProperties.itemProperties.find(item => item.propertyName === propName);
|
||||
switch (propertyDefinition.componentType) {
|
||||
case 'checkbox':
|
||||
const checkboxColumn = new CheckBoxColumn({
|
||||
field: propertyDefinition.propertyName,
|
||||
name: propertyDefinition.componentProperties.title,
|
||||
width: propertyDefinition.componentProperties.width as number
|
||||
});
|
||||
table.registerPlugin(checkboxColumn);
|
||||
checkboxColumn.onChange(async (e) => {
|
||||
await this.handleEdit({
|
||||
type: DesignerEditType.Update,
|
||||
property: {
|
||||
parentProperty: componentDefinition.propertyName,
|
||||
index: e.row,
|
||||
property: propertyDefinition.propertyName
|
||||
},
|
||||
value: e.value
|
||||
});
|
||||
});
|
||||
return checkboxColumn.definition;
|
||||
case 'dropdown':
|
||||
const dropdownProperties = propertyDefinition.componentProperties as DropDownProperties;
|
||||
return {
|
||||
name: dropdownProperties.title,
|
||||
field: propertyDefinition.propertyName,
|
||||
editor: this._tableCellEditorFactory.getSelectBoxEditorClass(componentDefinition.propertyName, dropdownProperties.values as string[]),
|
||||
width: dropdownProperties.width as number
|
||||
};
|
||||
default:
|
||||
const inputProperties = propertyDefinition.componentProperties as InputBoxProperties;
|
||||
return {
|
||||
name: inputProperties.title,
|
||||
field: propertyDefinition.propertyName,
|
||||
editor: this._tableCellEditorFactory.getTextEditorClass(componentDefinition.propertyName, inputProperties.inputType),
|
||||
width: inputProperties.width as number
|
||||
};
|
||||
}
|
||||
});
|
||||
table.layout(new DOM.Dimension(container.clientWidth, container.clientHeight));
|
||||
table.grid.onBeforeEditCell.subscribe((e, data): boolean => {
|
||||
return data.item[data.column.field].enabled !== false;
|
||||
});
|
||||
table.grid.onActiveCellChanged.subscribe((e, data) => {
|
||||
this._propertiesPane.show({
|
||||
context: {
|
||||
parentProperty: componentDefinition.propertyName,
|
||||
index: data.row
|
||||
},
|
||||
type: tableProperties.objectTypeDisplayName,
|
||||
components: tableProperties.itemProperties,
|
||||
data: table.getData().getItem(data.row)
|
||||
});
|
||||
});
|
||||
component = table;
|
||||
break;
|
||||
default:
|
||||
throw new Error(localize('tableDesigner.unknownComponentType', "The component type: {0} is not supported", componentDefinition.componentType));
|
||||
}
|
||||
if (addToComponentMap) {
|
||||
this._componentMap.set(componentDefinition.propertyName, {
|
||||
defintion: componentDefinition,
|
||||
component: component
|
||||
});
|
||||
}
|
||||
this.styleComponent(component);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user