table designer improvements (#18206)

* new table experience

* new table info for existing table

* allow delete confirmation

* fix editor lock isue

* vbump sts

* PR feedback
This commit is contained in:
Alan Ren
2022-02-02 18:46:09 -08:00
committed by GitHub
parent c35eae5969
commit c535c2dbde
14 changed files with 164 additions and 111 deletions

View File

@@ -36,6 +36,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { DesignerScriptEditor } from 'sql/workbench/browser/designer/designerScriptEditor';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
export interface IDesignerStyle {
tabbedPanelStyles?: ITabbedPanelStyles;
@@ -53,7 +54,7 @@ export type DesignerUIComponent = InputBox | Checkbox | Table<Slick.SlickData> |
export type CreateComponentsFunc = (container: HTMLElement, components: DesignerDataPropertyInfo[], parentPath: DesignerEditPath) => DesignerUIComponent[];
export type SetComponentValueFunc = (definition: DesignerDataPropertyInfo, component: DesignerUIComponent, data: DesignerViewModel) => void;
const TableRowHeight = 23;
const TableRowHeight = 25;
const TableHeaderRowHeight = 28;
type DesignerUIArea = 'PropertiesView' | 'ScriptView' | 'TopContentView' | 'TabsView';
@@ -85,7 +86,8 @@ export class Designer extends Disposable implements IThemable {
constructor(private readonly _container: HTMLElement,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IContextViewService private readonly _contextViewProvider: IContextViewService,
@INotificationService private readonly _notificationService: INotificationService) {
@INotificationService private readonly _notificationService: INotificationService,
@IDialogService private readonly _dialogService: IDialogService) {
super();
this._tableCellEditorFactory = new TableCellEditorFactory(
{
@@ -303,11 +305,23 @@ export class Designer extends Disposable implements IThemable {
const propertyName = edit.path[0] as string;
const tableData = this._input.viewModel[propertyName] as DesignerTableProperties;
const table = this._componentMap.get(propertyName).component as Table<Slick.SlickData>;
table.setActiveCell(tableData.data.length - 1, 0);
try {
table.setActiveCell(tableData.data.length - 1, 0);
}
catch {
// Ignore the slick grid error when setting active cell.
}
} else {
this.updatePropertiesPane(this._propertiesPane.objectPath);
}
} else if (edit.type === DesignerEditType.Update) {
// for edit, update the properties pane with new values of current object.
this.updatePropertiesPane(this._propertiesPane.objectPath);
} else if (edit.type === DesignerEditType.Remove) {
// removing the secondary level entities, the properties pane needs to be updated to reflect the changes.
if (edit.path.length === 4) {
this.updatePropertiesPane(this._propertiesPane.objectPath);
}
}
} catch (err) {
this._notificationService.error(err);
@@ -330,7 +344,7 @@ export class Designer extends Disposable implements IThemable {
let message;
let timeout;
switch (action) {
case 'save':
case 'publish':
message = showLoading ? localize('designer.publishingChanges', "Publishing changes...") : localize('designer.publishChangesCompleted', "Changes have been published");
timeout = 0;
break;
@@ -693,7 +707,17 @@ export class Designer extends Disposable implements IThemable {
resizable: false,
isFontIcon: true
});
deleteRowColumn.onClick((e) => {
deleteRowColumn.onClick(async (e) => {
if (tableProperties.showRemoveRowConfirmation) {
const confirmMessage = tableProperties.removeRowConfirmationMessage || localize('designer.defaultRemoveRowConfirmationMessage', "Are you sure you want to remove the row?");
const result = await this._dialogService.confirm({
type: 'question',
message: confirmMessage
});
if (!result.confirmed) {
return;
}
}
this.handleEdit({
type: DesignerEditType.Remove,
path: [...propertyPath, e.row]

View File

@@ -74,7 +74,7 @@ export interface DesignerUIState {
activeTabId: PanelTabIdentifier;
}
export type DesignerAction = 'save' | 'initialize' | 'processEdit' | 'generateScript' | 'generateReport';
export type DesignerAction = 'publish' | 'initialize' | 'processEdit' | 'generateScript' | 'generateReport';
export interface DesignerEditProcessedEventArgs {
result: DesignerEditResult;
@@ -154,22 +154,18 @@ export interface DesignerTableProperties extends ComponentProperties {
* the name of the properties to be displayed, properties not in this list will be accessible in details view.
*/
columns?: string[];
/**
* The display name of the object type.
*/
objectTypeDisplayName: string;
/**
* The properties of the table data item.
*/
itemProperties?: DesignerDataPropertyInfo[];
/**
* The data to be displayed.
*/
data?: DesignerTableComponentRowData[];
/**
* Whether user can add new rows to the table. The default value is true.
*/
@@ -179,6 +175,14 @@ export interface DesignerTableProperties extends ComponentProperties {
* Whether user can remove rows from the table. The default value is true.
*/
canRemoveRows?: boolean;
/**
* Whether to show confirmation when user removes a row. The default value is false.
*/
showRemoveRowConfirmation?: boolean;
/**
* The confirmation message to be displayed when user removes a row.
*/
removeRowConfirmationMessage?: string;
}
export interface DesignerTableComponentRowData {

View File

@@ -26,30 +26,23 @@ export class TableDesignerInput extends EditorInput {
constructor(
private _provider: TableDesignerProvider,
private _tableInfo: azdata.designers.TableInfo,
tableInfo: azdata.designers.TableInfo,
telemetryInfo: { [key: string]: string },
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IEditorService editorService: IEditorService,
@IEditorService private readonly _editorService: IEditorService,
@INotificationService private readonly _notificationService: INotificationService) {
super();
this._designerComponentInput = this._instantiationService.createInstance(TableDesignerComponentInput, this._provider, this._tableInfo, telemetryInfo);
this._designerComponentInput = this._instantiationService.createInstance(TableDesignerComponentInput, this._provider, tableInfo, telemetryInfo);
this._register(this._designerComponentInput.onStateChange((e) => {
if (e.previousState.pendingAction === 'publish') {
this.setEditorLabel();
this._onDidChangeLabel.fire();
}
if (e.currentState.dirty !== e.previousState.dirty) {
this._onDidChangeDirty.fire();
}
}));
if (this._tableInfo.isNewTable) {
const existingNames = editorService.editors.map(editor => editor.getName());
// Find the next available unique name for the new table designer
let idx = 1;
do {
this._name = `${NewTable} ${idx}`;
idx++;
} while (existingNames.indexOf(this._name) !== -1);
} else {
this._name = `${this._tableInfo.schema}.${this._tableInfo.name}`;
}
this._title = `${this._tableInfo.server}.${this._tableInfo.database} - ${this._name}`;
this.setEditorLabel();
}
get typeId(): string {
@@ -80,7 +73,7 @@ export class TableDesignerInput extends EditorInput {
}
override isSaving(): boolean {
return this._designerComponentInput.pendingAction === 'save';
return this._designerComponentInput.pendingAction === 'publish';
}
override async save(group: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
@@ -99,11 +92,27 @@ export class TableDesignerInput extends EditorInput {
override matches(otherInput: any): boolean {
return otherInput instanceof TableDesignerInput
&& this._provider.providerId === otherInput._provider.providerId
&& this._tableInfo.id === otherInput._tableInfo.id;
&& this._designerComponentInput.tableInfo.id === otherInput._designerComponentInput.tableInfo.id;
}
override dispose(): void {
super.dispose();
this._provider.disposeTableDesigner(this._tableInfo).then(undefined, err => onUnexpectedError(err));
this._provider.disposeTableDesigner(this._designerComponentInput.tableInfo).then(undefined, err => onUnexpectedError(err));
}
private setEditorLabel(): void {
const tableInfo = this._designerComponentInput.tableInfo;
if (tableInfo.isNewTable) {
const existingNames = this._editorService.editors.map(editor => editor.getName());
// Find the next available unique name for the new table designer
let idx = 1;
do {
this._name = `${NewTable} ${idx}`;
idx++;
} while (existingNames.indexOf(this._name) !== -1);
} else {
this._name = `${tableInfo.schema}.${tableInfo.name}`;
}
this._title = `${tableInfo.server}.${tableInfo.database} - ${this._name}`;
}
}