mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
add severity support for issues (#18761)
* add severity support for issues * vbump STS * pr comments
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "3.0.0-release.214",
|
"version": "3.0.0-release.216",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-net6.0.zip",
|
"Windows_86": "win-x86-net6.0.zip",
|
||||||
"Windows_64": "win-x64-net6.0.zip",
|
"Windows_64": "win-x64-net6.0.zip",
|
||||||
|
|||||||
12
src/sql/azdata.proposed.d.ts
vendored
12
src/sql/azdata.proposed.d.ts
vendored
@@ -1061,6 +1061,14 @@ declare module 'azdata' {
|
|||||||
*/
|
*/
|
||||||
export type DesignerEditPath = (string | number)[];
|
export type DesignerEditPath = (string | number)[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Severity of the messages returned by the provider after processing an edit.
|
||||||
|
* 'error': The issue must be fixed in order to commit the changes.
|
||||||
|
* 'warning': Inform the user the potential risks with the current state. e.g. Having multiple edge constraints is only useful as a temporary state.
|
||||||
|
* 'information': Informational message.
|
||||||
|
*/
|
||||||
|
export type DesignerIssueSeverity = 'error' | 'warning' | 'information';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The result returned by the table designer provider after handling an edit request.
|
* The result returned by the table designer provider after handling an edit request.
|
||||||
*/
|
*/
|
||||||
@@ -1078,9 +1086,9 @@ declare module 'azdata' {
|
|||||||
*/
|
*/
|
||||||
isValid: boolean;
|
isValid: boolean;
|
||||||
/**
|
/**
|
||||||
* Error messages of current state, and the property the caused the error.
|
* Issues of current state.
|
||||||
*/
|
*/
|
||||||
errors?: { message: string, propertyPath?: DesignerEditPath }[];
|
issues?: { severity: DesignerIssueSeverity, description: string, propertyPath?: DesignerEditPath }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||||
import { DesignerMessagesTabPanelView } from 'sql/workbench/browser/designer/designerMessagesTabPanelView';
|
import { DesignerIssuesTabPanelView } from 'sql/workbench/browser/designer/designerIssuesTabPanelView';
|
||||||
import { DesignerScriptEditorTabPanelView } from 'sql/workbench/browser/designer/designerScriptEditorTabPanelView';
|
import { DesignerScriptEditorTabPanelView } from 'sql/workbench/browser/designer/designerScriptEditorTabPanelView';
|
||||||
import { DesignerPropertyPathValidator } from 'sql/workbench/browser/designer/designerPropertyPathValidator';
|
import { DesignerPropertyPathValidator } from 'sql/workbench/browser/designer/designerPropertyPathValidator';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
@@ -70,7 +70,7 @@ interface DesignerTableCellContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ScriptTabId = 'scripts';
|
const ScriptTabId = 'scripts';
|
||||||
const MessagesTabId = 'messages';
|
const IssuesTabId = 'issues';
|
||||||
|
|
||||||
export class Designer extends Disposable implements IThemable {
|
export class Designer extends Disposable implements IThemable {
|
||||||
private _loadingSpinner: LoadingSpinner;
|
private _loadingSpinner: LoadingSpinner;
|
||||||
@@ -95,7 +95,7 @@ export class Designer extends Disposable implements IThemable {
|
|||||||
private _inputDisposable: DisposableStore;
|
private _inputDisposable: DisposableStore;
|
||||||
private _loadingTimeoutHandle: any;
|
private _loadingTimeoutHandle: any;
|
||||||
private _groupHeaders: HTMLElement[] = [];
|
private _groupHeaders: HTMLElement[] = [];
|
||||||
private _messagesView: DesignerMessagesTabPanelView;
|
private _issuesView: DesignerIssuesTabPanelView;
|
||||||
private _scriptEditorView: DesignerScriptEditorTabPanelView;
|
private _scriptEditorView: DesignerScriptEditorTabPanelView;
|
||||||
private _onStyleChangeEventEmitter = new Emitter<void>();
|
private _onStyleChangeEventEmitter = new Emitter<void>();
|
||||||
|
|
||||||
@@ -152,8 +152,8 @@ export class Designer extends Disposable implements IThemable {
|
|||||||
onDidChange: Event.None
|
onDidChange: Event.None
|
||||||
}, Sizing.Distribute);
|
}, Sizing.Distribute);
|
||||||
this._scriptTabbedPannel = new TabbedPanel(this._editorContainer);
|
this._scriptTabbedPannel = new TabbedPanel(this._editorContainer);
|
||||||
this._messagesView = this._instantiationService.createInstance(DesignerMessagesTabPanelView);
|
this._issuesView = this._instantiationService.createInstance(DesignerIssuesTabPanelView);
|
||||||
this._register(this._messagesView.onMessageSelected((path) => {
|
this._register(this._issuesView.onIssueSelected((path) => {
|
||||||
if (path && path.length > 0) {
|
if (path && path.length > 0) {
|
||||||
this.selectProperty(path);
|
this.selectProperty(path);
|
||||||
}
|
}
|
||||||
@@ -332,14 +332,14 @@ export class Designer extends Disposable implements IThemable {
|
|||||||
private handleEditProcessedEvent(args: DesignerEditProcessedEventArgs): void {
|
private handleEditProcessedEvent(args: DesignerEditProcessedEventArgs): void {
|
||||||
const edit = args.edit;
|
const edit = args.edit;
|
||||||
this._supressEditProcessing = true;
|
this._supressEditProcessing = true;
|
||||||
if (!args.result.isValid) {
|
if (args.result.issues?.length > 0) {
|
||||||
alert(localize('designer.errorCountAlert', "{0} validation errors found.", args.result.errors.length));
|
alert(localize('designer.issueCountAlert', "{0} validation issues found.", args.result.issues.length));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (args.result.refreshView) {
|
if (args.result.refreshView) {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
if (!args.result.isValid) {
|
if (!args.result.isValid) {
|
||||||
this._scriptTabbedPannel.showTab(MessagesTabId);
|
this._scriptTabbedPannel.showTab(IssuesTabId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.updateComponentValues();
|
this.updateComponentValues();
|
||||||
@@ -466,7 +466,7 @@ export class Designer extends Disposable implements IThemable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateComponentValues(): void {
|
private updateComponentValues(): void {
|
||||||
this.updateMessagesTab();
|
this.updateIssuesTab();
|
||||||
const viewModel = this._input.viewModel;
|
const viewModel = this._input.viewModel;
|
||||||
const scriptProperty = viewModel[ScriptProperty] as InputBoxProperties;
|
const scriptProperty = viewModel[ScriptProperty] as InputBoxProperties;
|
||||||
if (scriptProperty) {
|
if (scriptProperty) {
|
||||||
@@ -477,23 +477,24 @@ export class Designer extends Disposable implements IThemable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateMessagesTab(): void {
|
private updateIssuesTab(): void {
|
||||||
if (!this._input) {
|
if (!this._input) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._scriptTabbedPannel.contains(MessagesTabId)) {
|
if (this._scriptTabbedPannel.contains(IssuesTabId)) {
|
||||||
this._scriptTabbedPannel.removeTab(MessagesTabId);
|
this._scriptTabbedPannel.removeTab(IssuesTabId);
|
||||||
}
|
}
|
||||||
if (this._input.validationErrors === undefined || this._input.validationErrors.length === 0) {
|
|
||||||
|
if (this._input.issues === undefined || this._input.issues.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._scriptTabbedPannel.pushTab({
|
this._scriptTabbedPannel.pushTab({
|
||||||
title: localize('designer.messagesTabTitle', "Errors ({0})", this._input.validationErrors.length),
|
title: localize('designer.issuesTabTitle', "Issues ({0})", this._input.issues.length),
|
||||||
identifier: MessagesTabId,
|
identifier: IssuesTabId,
|
||||||
view: this._messagesView
|
view: this._issuesView
|
||||||
});
|
});
|
||||||
this._scriptTabbedPannel.showTab(MessagesTabId);
|
this._scriptTabbedPannel.showTab(IssuesTabId);
|
||||||
this._messagesView.updateMessages(this._input.validationErrors);
|
this._issuesView.updateIssues(this._input.issues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectProperty(path: DesignerPropertyPath, view?: DesignerUIArea, highlight: boolean = true): void {
|
private selectProperty(path: DesignerPropertyPath, view?: DesignerUIArea, highlight: boolean = true): void {
|
||||||
|
|||||||
143
src/sql/workbench/browser/designer/designerIssuesTabPanelView.ts
Normal file
143
src/sql/workbench/browser/designer/designerIssuesTabPanelView.ts
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||||
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
import { DesignerPropertyPath, DesignerIssue } from 'sql/workbench/browser/designer/interfaces';
|
||||||
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
|
import { IListAccessibilityProvider, List } from 'vs/base/browser/ui/list/listWidget';
|
||||||
|
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||||
|
import { localize } from 'vs/nls';
|
||||||
|
import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
||||||
|
import { problemsErrorIconForeground, problemsInfoIconForeground, problemsWarningIconForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||||
|
import { Codicon } from 'vs/base/common/codicons';
|
||||||
|
|
||||||
|
export class DesignerIssuesTabPanelView extends Disposable implements IPanelView {
|
||||||
|
private _container: HTMLElement;
|
||||||
|
private _onIssueSelected = new Emitter<DesignerPropertyPath>();
|
||||||
|
private _issueList: List<DesignerIssue>;
|
||||||
|
|
||||||
|
public readonly onIssueSelected: Event<DesignerPropertyPath> = this._onIssueSelected.event;
|
||||||
|
|
||||||
|
constructor(@IThemeService private _themeService: IThemeService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(container: HTMLElement): void {
|
||||||
|
this._container = container.appendChild(DOM.$('.issues-container'));
|
||||||
|
this._issueList = new List<DesignerIssue>('designerIssueList', this._container, new DesignerIssueListDelegate(), [new TableFilterListRenderer()], {
|
||||||
|
multipleSelectionSupport: false,
|
||||||
|
keyboardSupport: true,
|
||||||
|
mouseSupport: true,
|
||||||
|
accessibilityProvider: new DesignerIssueListAccessibilityProvider()
|
||||||
|
});
|
||||||
|
this._register(this._issueList.onDidChangeSelection((e) => {
|
||||||
|
if (e.elements && e.elements.length === 1) {
|
||||||
|
this._onIssueSelected.fire(e.elements[0].propertyPath);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this._register(attachListStyler(this._issueList, this._themeService));
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(dimension: DOM.Dimension): void {
|
||||||
|
this._issueList.layout(dimension.height, dimension.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateIssues(errors: DesignerIssue[]) {
|
||||||
|
if (this._issueList) {
|
||||||
|
this._issueList.splice(0, this._issueList.length, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
|
||||||
|
const errorForegroundColor = theme.getColor(problemsErrorIconForeground);
|
||||||
|
const warningForegroundColor = theme.getColor(problemsWarningIconForeground);
|
||||||
|
const informationalForegroundColor = theme.getColor(problemsInfoIconForeground);
|
||||||
|
if (errorForegroundColor) {
|
||||||
|
collector.addRule(`
|
||||||
|
.designer-component .issues-container .issue-item .issue-icon.codicon-error {
|
||||||
|
color: ${errorForegroundColor};
|
||||||
|
}
|
||||||
|
.designer-component .issues-container .issue-item .issue-icon.codicon-warning {
|
||||||
|
color: ${warningForegroundColor};
|
||||||
|
}
|
||||||
|
.designer-component .issues-container .issue-item .issue-icon.codicon-info {
|
||||||
|
color: ${informationalForegroundColor};
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const DesignerIssueListTemplateId = 'DesignerIssueListTemplate';
|
||||||
|
class DesignerIssueListDelegate implements IListVirtualDelegate<DesignerIssue> {
|
||||||
|
getHeight(element: DesignerIssue): number {
|
||||||
|
return 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplateId(element: DesignerIssue): string {
|
||||||
|
return DesignerIssueListTemplateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DesignerIssueListItemTemplate {
|
||||||
|
issueText: HTMLDivElement;
|
||||||
|
issueIcon: HTMLDivElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TableFilterListRenderer implements IListRenderer<DesignerIssue, DesignerIssueListItemTemplate> {
|
||||||
|
renderTemplate(container: HTMLElement): DesignerIssueListItemTemplate {
|
||||||
|
const data: DesignerIssueListItemTemplate = Object.create(null);
|
||||||
|
const issueItem = container.appendChild(DOM.$('.issue-item'));
|
||||||
|
data.issueIcon = issueItem.appendChild(DOM.$(''));
|
||||||
|
data.issueText = issueItem.appendChild(DOM.$('.issue-text'));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderElement(element: DesignerIssue, index: number, templateData: DesignerIssueListItemTemplate, height: number): void {
|
||||||
|
templateData.issueText.innerText = element.description;
|
||||||
|
templateData.issueText.title = element.description;
|
||||||
|
let iconClass;
|
||||||
|
switch (element.severity) {
|
||||||
|
case 'warning':
|
||||||
|
iconClass = Codicon.warning.classNames;
|
||||||
|
break;
|
||||||
|
case 'information':
|
||||||
|
iconClass = Codicon.info.classNames;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
iconClass = Codicon.error.classNames;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
templateData.issueIcon.className = `issue-icon ${iconClass}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public disposeTemplate(templateData: DesignerIssueListItemTemplate): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public get templateId(): string {
|
||||||
|
return DesignerIssueListTemplateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DesignerIssueListAccessibilityProvider implements IListAccessibilityProvider<DesignerIssue> {
|
||||||
|
getAriaLabel(element: DesignerIssue): string {
|
||||||
|
return element.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidgetAriaLabel(): string {
|
||||||
|
return localize('designer.IssueListAriaLabel', "Issues");
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidgetRole() {
|
||||||
|
return 'listbox';
|
||||||
|
}
|
||||||
|
|
||||||
|
getRole(element: DesignerIssue): string {
|
||||||
|
return 'option';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
|
||||||
import { DesignerPropertyPath, DesignerValidationError } from 'sql/workbench/browser/designer/interfaces';
|
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
|
||||||
import { IListAccessibilityProvider, List } from 'vs/base/browser/ui/list/listWidget';
|
|
||||||
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
|
||||||
import { localize } from 'vs/nls';
|
|
||||||
import { IColorTheme, ICssStyleCollector, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
|
||||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
|
||||||
import { problemsErrorIconForeground } from 'vs/platform/theme/common/colorRegistry';
|
|
||||||
import { Codicon } from 'vs/base/common/codicons';
|
|
||||||
|
|
||||||
export class DesignerMessagesTabPanelView extends Disposable implements IPanelView {
|
|
||||||
private _container: HTMLElement;
|
|
||||||
private _onMessageSelected = new Emitter<DesignerPropertyPath>();
|
|
||||||
private _messageList: List<DesignerValidationError>;
|
|
||||||
|
|
||||||
public readonly onMessageSelected: Event<DesignerPropertyPath> = this._onMessageSelected.event;
|
|
||||||
|
|
||||||
constructor(@IThemeService private _themeService: IThemeService) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
render(container: HTMLElement): void {
|
|
||||||
this._container = container.appendChild(DOM.$('.messages-container'));
|
|
||||||
this._messageList = new List<DesignerValidationError>('designerMessageList', this._container, new DesignerMessageListDelegate(), [new TableFilterListRenderer()], {
|
|
||||||
multipleSelectionSupport: false,
|
|
||||||
keyboardSupport: true,
|
|
||||||
mouseSupport: true,
|
|
||||||
accessibilityProvider: new DesignerMessagesListAccessibilityProvider()
|
|
||||||
});
|
|
||||||
this._register(this._messageList.onDidChangeSelection((e) => {
|
|
||||||
if (e.elements && e.elements.length === 1) {
|
|
||||||
this._onMessageSelected.fire(e.elements[0].propertyPath);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
this._register(attachListStyler(this._messageList, this._themeService));
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(dimension: DOM.Dimension): void {
|
|
||||||
this._messageList.layout(dimension.height, dimension.width);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMessages(errors: DesignerValidationError[]) {
|
|
||||||
if (this._messageList) {
|
|
||||||
this._messageList.splice(0, this._messageList.length, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
|
|
||||||
const errorForegroundColor = theme.getColor(problemsErrorIconForeground);
|
|
||||||
if (errorForegroundColor) {
|
|
||||||
collector.addRule(`
|
|
||||||
.designer-component .messages-container .message-item .message-icon {
|
|
||||||
color: ${errorForegroundColor};
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const DesignerMessageListTemplateId = 'DesignerMessageListTemplate';
|
|
||||||
class DesignerMessageListDelegate implements IListVirtualDelegate<DesignerValidationError> {
|
|
||||||
getHeight(element: DesignerValidationError): number {
|
|
||||||
return 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTemplateId(element: DesignerValidationError): string {
|
|
||||||
return DesignerMessageListTemplateId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DesignerMessageListItemTemplate {
|
|
||||||
messageText: HTMLDivElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TableFilterListRenderer implements IListRenderer<DesignerValidationError, DesignerMessageListItemTemplate> {
|
|
||||||
renderTemplate(container: HTMLElement): DesignerMessageListItemTemplate {
|
|
||||||
const data: DesignerMessageListItemTemplate = Object.create(null);
|
|
||||||
const messageItem = container.appendChild(DOM.$('.message-item'));
|
|
||||||
messageItem.appendChild(DOM.$(`.message-icon${Codicon.error.cssSelector}`));
|
|
||||||
data.messageText = messageItem.appendChild(DOM.$('.message-text'));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderElement(element: DesignerValidationError, index: number, templateData: DesignerMessageListItemTemplate, height: number): void {
|
|
||||||
templateData.messageText.innerText = element.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
disposeElement?(element: DesignerValidationError, index: number, templateData: DesignerMessageListItemTemplate, height: number): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
public disposeTemplate(templateData: DesignerMessageListItemTemplate): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
public get templateId(): string {
|
|
||||||
return DesignerMessageListTemplateId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DesignerMessagesListAccessibilityProvider implements IListAccessibilityProvider<DesignerValidationError> {
|
|
||||||
getAriaLabel(element: DesignerValidationError): string {
|
|
||||||
return element.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
getWidgetAriaLabel(): string {
|
|
||||||
return localize('designer.MessageListAriaLabel', "Errors");
|
|
||||||
}
|
|
||||||
|
|
||||||
getWidgetRole() {
|
|
||||||
return 'listbox';
|
|
||||||
}
|
|
||||||
|
|
||||||
getRole(element: DesignerValidationError): string {
|
|
||||||
return 'option';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,9 +44,9 @@ export interface DesignerComponentInput {
|
|||||||
readonly viewModel: DesignerViewModel;
|
readonly viewModel: DesignerViewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the validation errors.
|
* Gets the issues.
|
||||||
*/
|
*/
|
||||||
readonly validationErrors: DesignerValidationError[] | undefined;
|
readonly issues: DesignerIssue[] | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start initilizing the designer input object.
|
* Start initilizing the designer input object.
|
||||||
@@ -229,12 +229,13 @@ export type DesignerUIArea = 'PropertiesView' | 'ScriptView' | 'TopContentView'
|
|||||||
export type DesignerPropertyPath = (string | number)[];
|
export type DesignerPropertyPath = (string | number)[];
|
||||||
export const DesignerRootObjectPath: DesignerPropertyPath = [];
|
export const DesignerRootObjectPath: DesignerPropertyPath = [];
|
||||||
|
|
||||||
export type DesignerValidationError = { message: string, propertyPath?: DesignerPropertyPath };
|
export type DesignerIssueSeverity = 'error' | 'warning' | 'information';
|
||||||
|
export type DesignerIssue = { description: string, propertyPath?: DesignerPropertyPath, severity: DesignerIssueSeverity };
|
||||||
|
|
||||||
export interface DesignerEditResult {
|
export interface DesignerEditResult {
|
||||||
isValid: boolean;
|
isValid: boolean;
|
||||||
refreshView?: boolean;
|
refreshView?: boolean;
|
||||||
errors?: DesignerValidationError[];
|
issues?: DesignerIssue[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DesignerTextEditor {
|
export interface DesignerTextEditor {
|
||||||
|
|||||||
@@ -29,24 +29,27 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.designer-component .messages-container {
|
.designer-component .issues-container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.designer-component .messages-container .message-item {
|
.designer-component .issues-container .issue-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.designer-component .messages-container .message-item .message-icon {
|
.designer-component .issues-container .issue-item .issue-icon {
|
||||||
margin: 0px 6px;
|
margin: 0px 6px;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.designer-component .messages-container .message-item .message-text {
|
.designer-component .issues-container .issue-item .issue-text {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.designer-component .tabbed-panel-container {
|
.designer-component .tabbed-panel-container {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { DesignerViewModel, DesignerEdit, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerEditProcessedEventArgs, DesignerAction, DesignerStateChangedEventArgs, DesignerPropertyPath, DesignerValidationError, ScriptProperty } from 'sql/workbench/browser/designer/interfaces';
|
import { DesignerViewModel, DesignerEdit, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerEditProcessedEventArgs, DesignerAction, DesignerStateChangedEventArgs, DesignerPropertyPath, DesignerIssue, ScriptProperty } from 'sql/workbench/browser/designer/interfaces';
|
||||||
import { TableDesignerProvider } from 'sql/workbench/services/tableDesigner/common/interface';
|
import { TableDesignerProvider } from 'sql/workbench/services/tableDesigner/common/interface';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { designers } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { designers } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
@@ -22,7 +22,7 @@ const ErrorDialogTitle: string = localize('tableDesigner.ErrorDialogTitle', "Tab
|
|||||||
export class TableDesignerComponentInput implements DesignerComponentInput {
|
export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||||
|
|
||||||
private _viewModel: DesignerViewModel;
|
private _viewModel: DesignerViewModel;
|
||||||
private _validationErrors?: DesignerValidationError[];
|
private _issues?: DesignerIssue[];
|
||||||
private _view: DesignerView;
|
private _view: DesignerView;
|
||||||
private _valid: boolean = true;
|
private _valid: boolean = true;
|
||||||
private _dirty: boolean = false;
|
private _dirty: boolean = false;
|
||||||
@@ -76,8 +76,8 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
|||||||
return this._viewModel;
|
return this._viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
get validationErrors(): DesignerValidationError[] | undefined {
|
get issues(): DesignerIssue[] | undefined {
|
||||||
return this._validationErrors;
|
return this._issues;
|
||||||
}
|
}
|
||||||
|
|
||||||
processEdit(edit: DesignerEdit): void {
|
processEdit(edit: DesignerEdit): void {
|
||||||
@@ -93,14 +93,14 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
|||||||
if (result.view) {
|
if (result.view) {
|
||||||
this.setDesignerView(result.view);
|
this.setDesignerView(result.view);
|
||||||
}
|
}
|
||||||
this._validationErrors = result.errors;
|
this._issues = result.issues;
|
||||||
this.updateState(result.isValid, this.isDirty(), undefined);
|
this.updateState(result.isValid, this.isDirty(), undefined);
|
||||||
|
|
||||||
this._onEditProcessed.fire({
|
this._onEditProcessed.fire({
|
||||||
edit: edit,
|
edit: edit,
|
||||||
result: {
|
result: {
|
||||||
isValid: result.isValid,
|
isValid: result.isValid,
|
||||||
errors: result.errors,
|
issues: result.issues,
|
||||||
refreshView: !!result.view
|
refreshView: !!result.view
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -372,7 +372,8 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
|||||||
description: localize('designer.column.description.precision', "For numeric data, the maximum number of decimal digits that can be stored in this database object."),
|
description: localize('designer.column.description.precision', "For numeric data, the maximum number of decimal digits that can be stored in this database object."),
|
||||||
componentProperties: {
|
componentProperties: {
|
||||||
title: localize('tableDesigner.columnPrecisionTitle', "Precision"),
|
title: localize('tableDesigner.columnPrecisionTitle', "Precision"),
|
||||||
width: 60
|
width: 60,
|
||||||
|
inputType: 'number'
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
componentType: 'input',
|
componentType: 'input',
|
||||||
@@ -380,7 +381,8 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
|||||||
description: localize('designer.column.description.scale', "For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point."),
|
description: localize('designer.column.description.scale', "For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point."),
|
||||||
componentProperties: {
|
componentProperties: {
|
||||||
title: localize('tableDesigner.columnScaleTitle', "Scale"),
|
title: localize('tableDesigner.columnScaleTitle', "Scale"),
|
||||||
width: 60
|
width: 60,
|
||||||
|
inputType: 'number'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user