mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Sql-Assessment api info button (#13490)
This commit is contained in:
1
extensions/sql-assessment/resources/dark/status_info.svg
Normal file
1
extensions/sql-assessment/resources/dark/status_info.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-blue{fill:#424242;} .icon-white{fill:#FFFFFF;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 8c0-4.418 3.582-8 8-8s8 3.582 8 8-3.582 8-8 8-8-3.582-8-8z" id="outline"/><path class="icon-vs-blue" d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" id="iconBg"/><path class="icon-white" d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" id="iconFg"/></svg>
|
||||||
|
After Width: | Height: | Size: 624 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#212121;} .icon-vs-blue{fill:#FFFFFF;} .icon-white{fill:#212121;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 8c0-4.418 3.582-8 8-8s8 3.582 8 8-3.582 8-8 8-8-3.582-8-8z" id="outline"/><path class="icon-vs-blue" d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" id="iconBg"/><path class="icon-white" d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" id="iconFg"/></svg>
|
||||||
|
After Width: | Height: | Size: 624 B |
@@ -30,7 +30,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
private asmtType!: AssessmentType;
|
private asmtType!: AssessmentType;
|
||||||
private targetTypeIcon: { [targetType: number]: azdata.IconColumnCellValue };
|
private targetTypeIcon: { [targetType: number]: azdata.IconColumnCellValue };
|
||||||
|
|
||||||
|
|
||||||
private readonly checkIdColOrder = 5;
|
private readonly checkIdColOrder = 5;
|
||||||
private readonly targetColOrder = 1;
|
private readonly targetColOrder = 1;
|
||||||
private readonly messageColOrder = 3;
|
private readonly messageColOrder = 3;
|
||||||
@@ -81,7 +80,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
headerFilter: true
|
headerFilter: true
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
|
||||||
this.toDispose.push(
|
this.toDispose.push(
|
||||||
this.table.onRowSelected(async () => {
|
this.table.onRowSelected(async () => {
|
||||||
if (this.table.selectedRows?.length !== 1) {
|
if (this.table.selectedRows?.length !== 1) {
|
||||||
@@ -90,7 +88,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
await this.showDetails(this.table.selectedRows[0]);
|
await this.showDetails(this.table.selectedRows[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
this.rootContainer = view.modelBuilder.flexContainer()
|
this.rootContainer = view.modelBuilder.flexContainer()
|
||||||
.withItems([this.table], {
|
.withItems([this.table], {
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
@@ -109,7 +106,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
flex: '0 0 200px',
|
flex: '0 0 200px',
|
||||||
order: 2,
|
order: 2,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
'padding-bottom': '15px',
|
|
||||||
'visibility': 'hidden'
|
'visibility': 'hidden'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -132,18 +128,22 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
this.rootContainer.setItemLayout(this.table, {
|
this.rootContainer.setItemLayout(this.table, {
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
'height': '100%'
|
'height': '100%',
|
||||||
|
'border-bottom': '3px solid rgb(221, 221, 221)'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.table.updateProperties({
|
await this.table.updateProperties({
|
||||||
'height': '100%'
|
'height': '100%'
|
||||||
});
|
});
|
||||||
|
if (this.dataItems.length > 0) {
|
||||||
this.detailsPanel.updateCssStyles({
|
this.table.selectedRows = [0];
|
||||||
|
} else {
|
||||||
|
await this.detailsPanel.updateCssStyles({
|
||||||
'visibility': 'hidden'
|
'visibility': 'hidden'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we need to filter out warnings and error results since we don't have an appropriate way of displaying such messages.
|
// we need to filter out warnings and error results since we don't have an appropriate way of displaying such messages.
|
||||||
// have to redone this once required functionality will be added to the core.
|
// have to redone this once required functionality will be added to the core.
|
||||||
@@ -196,8 +196,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private createDetailsPanel(view: azdata.ModelView): azdata.FlexContainer {
|
private createDetailsPanel(view: azdata.ModelView): azdata.FlexContainer {
|
||||||
|
|
||||||
const root = view.modelBuilder.flexContainer()
|
const root = view.modelBuilder.flexContainer()
|
||||||
@@ -206,8 +204,7 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
height: '200px',
|
height: '200px',
|
||||||
}).withProperties({
|
}).withProperties({
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
'padding': '20px',
|
'padding': '0px 10px'
|
||||||
'border-top': '3px solid rgb(221, 221, 221)'
|
|
||||||
}
|
}
|
||||||
}).component();
|
}).component();
|
||||||
const cssNoMarginFloatLeft = { 'margin': '0px', 'float': 'left' };
|
const cssNoMarginFloatLeft = { 'margin': '0px', 'float': 'left' };
|
||||||
@@ -285,6 +282,7 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearOutDefaultRuleset(tags: string[]): string[] {
|
private clearOutDefaultRuleset(tags: string[]): string[] {
|
||||||
let idx = tags.findIndex(item => item.toUpperCase() === 'DEFAULTRULESET');
|
let idx = tags.findIndex(item => item.toUpperCase() === 'DEFAULTRULESET');
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
|
|||||||
@@ -14,13 +14,15 @@ import { HTMLReportBuilder } from '../htmlReportGenerator';
|
|||||||
import { AssessmentResultGrid } from '../assessmentResultGrid';
|
import { AssessmentResultGrid } from '../assessmentResultGrid';
|
||||||
import { LocalizedStrings } from '../localized';
|
import { LocalizedStrings } from '../localized';
|
||||||
import { TelemetryReporter, SqlAssessmentTelemetryView, SqlTelemetryActions } from '../telemetry';
|
import { TelemetryReporter, SqlAssessmentTelemetryView, SqlTelemetryActions } from '../telemetry';
|
||||||
|
import { EOL } from 'os';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
||||||
private assessmentPropertiesContainer!: azdata.PropertiesContainerComponent;
|
|
||||||
private apiVersionPropItem: azdata.PropertiesContainerItem;
|
private apiVersionPropItem: azdata.PropertiesContainerItem;
|
||||||
private defaultRulesetPropItem: azdata.PropertiesContainerItem;
|
private defaultRulesetPropItem: azdata.PropertiesContainerItem;
|
||||||
|
private serverProps: azdata.PropertiesContainerItem[] = [];
|
||||||
|
|
||||||
private invokeAssessmentLabel: string = localize('invokeAssessmentLabelServer', "Invoke assessment");
|
private invokeAssessmentLabel: string = localize('invokeAssessmentLabelServer', "Invoke assessment");
|
||||||
private getItemsLabel: string = localize('getAssessmentItemsServer', "View applicable rules");
|
private getItemsLabel: string = localize('getAssessmentItemsServer', "View applicable rules");
|
||||||
private btnExportAsScript!: azdata.ButtonComponent;
|
private btnExportAsScript!: azdata.ButtonComponent;
|
||||||
@@ -31,7 +33,6 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
private resultGrid!: AssessmentResultGrid;
|
private resultGrid!: AssessmentResultGrid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public constructor(extensionContext: vscode.ExtensionContext, engine: AssessmentEngine) {
|
public constructor(extensionContext: vscode.ExtensionContext, engine: AssessmentEngine) {
|
||||||
super(extensionContext, LocalizedStrings.ASSESSMENT_TAB_NAME, 'MainTab', {
|
super(extensionContext, LocalizedStrings.ASSESSMENT_TAB_NAME, 'MainTab', {
|
||||||
dark: extensionContext.asAbsolutePath('resources/dark/server.svg'),
|
dark: extensionContext.asAbsolutePath('resources/dark/server.svg'),
|
||||||
@@ -64,12 +65,11 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
height: '100%',
|
height: '100%',
|
||||||
|
|
||||||
}).component();
|
}).component();
|
||||||
|
await this.createServerProperties(view);
|
||||||
|
|
||||||
rootContainer.addItem(await this.createPropertiesSection(view), { flex: '0 0 auto' });
|
|
||||||
rootContainer.addItem(await this.createToolbar(view), {
|
rootContainer.addItem(await this.createToolbar(view), {
|
||||||
flex: '0 0 auto', CSSStyles: {
|
flex: '0 0 auto', CSSStyles: {
|
||||||
'border-top': '3px solid rgb(221, 221, 221)',
|
'border-top': '3px solid rgb(221, 221, 221)',
|
||||||
'margin-top': '20px',
|
|
||||||
'height': '32px'
|
'height': '32px'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -78,74 +78,22 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
rootContainer.addItem(this.resultGrid.component, {
|
rootContainer.addItem(this.resultGrid.component, {
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
'padding-bottom': '15px'
|
'padding-bottom': '10px'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return rootContainer;
|
return rootContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createPropertiesSection(view: azdata.ModelView): Promise<azdata.FlexContainer> {
|
private async createServerProperties(view: azdata.ModelView): Promise<void> {
|
||||||
const serverInfo = await azdata.connection.getServerInfo(view.connection.connectionId);
|
const serverInfo = await azdata.connection.getServerInfo(view.connection.connectionId);
|
||||||
const connectionProfile = await azdata.connection.getCurrentConnection();
|
const connectionProfile = await azdata.connection.getCurrentConnection();
|
||||||
|
this.serverProps = [
|
||||||
const propertiesContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({
|
|
||||||
flexFlow: 'row',
|
|
||||||
justifyContent: 'flex-start'
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const apiInformationContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({
|
|
||||||
flexFlow: 'column',
|
|
||||||
alignContent: 'flex-start'
|
|
||||||
}).component();
|
|
||||||
apiInformationContainer.addItem(
|
|
||||||
view.modelBuilder.text().withProperties({ value: LocalizedStrings.SECTION_TITLE_API }).component(), {
|
|
||||||
CSSStyles: { 'font-size': 'larger' }
|
|
||||||
});
|
|
||||||
|
|
||||||
this.assessmentPropertiesContainer = view.modelBuilder.propertiesContainer()
|
|
||||||
.withProperties<azdata.PropertiesContainerComponentProperties>({
|
|
||||||
propertyItems: [
|
|
||||||
this.apiVersionPropItem,
|
|
||||||
this.defaultRulesetPropItem]
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
apiInformationContainer.addItem(this.assessmentPropertiesContainer, {
|
|
||||||
CSSStyles: {
|
|
||||||
'margin-left': '20px'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const sqlServerContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({
|
|
||||||
flexFlow: 'column',
|
|
||||||
alignContent: 'flex-start'
|
|
||||||
}).component();
|
|
||||||
sqlServerContainer.addItem(
|
|
||||||
view.modelBuilder.text().withProperties({ value: LocalizedStrings.SECTION_TITLE_SQL_SERVER }).component(), {
|
|
||||||
CSSStyles: { 'font-size': 'larger' }
|
|
||||||
});
|
|
||||||
sqlServerContainer.addItem(
|
|
||||||
view.modelBuilder.propertiesContainer()
|
|
||||||
.withProperties<azdata.PropertiesContainerComponentProperties>({
|
|
||||||
propertyItems: [
|
|
||||||
{ displayName: LocalizedStrings.SERVER_VERSION, value: serverInfo.serverVersion },
|
{ displayName: LocalizedStrings.SERVER_VERSION, value: serverInfo.serverVersion },
|
||||||
{ displayName: LocalizedStrings.SERVER_INSTANCENAME, value: connectionProfile.serverName },
|
{ displayName: LocalizedStrings.SERVER_INSTANCENAME, value: connectionProfile.serverName },
|
||||||
{ displayName: LocalizedStrings.SERVER_EDITION, value: serverInfo.serverEdition },
|
{ displayName: LocalizedStrings.SERVER_EDITION, value: serverInfo.serverEdition },
|
||||||
{ displayName: LocalizedStrings.SERVER_OSVERSION, value: serverInfo.osVersion },
|
{ displayName: LocalizedStrings.SERVER_OSVERSION, value: serverInfo.osVersion },
|
||||||
]
|
];
|
||||||
}).component(), {
|
|
||||||
CSSStyles: {
|
|
||||||
'margin-left': '20px'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
propertiesContainer.addItem(apiInformationContainer, { flex: '0 0 300px', CSSStyles: { 'margin-left': '10px' } });
|
|
||||||
propertiesContainer.addItem(sqlServerContainer, { flex: '1 1 auto' });
|
|
||||||
|
|
||||||
return propertiesContainer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createToolbar(view: azdata.ModelView): Promise<azdata.ToolbarContainer> {
|
private async createToolbar(view: azdata.ModelView): Promise<azdata.ToolbarContainer> {
|
||||||
@@ -279,6 +227,42 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/sql-assessment-api'));
|
vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/sql-assessment-api'));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let btnAPIDetails = view.modelBuilder.button()
|
||||||
|
.withProperties<azdata.ButtonProperties>({
|
||||||
|
label: LocalizedStrings.SECTION_TITLE_API,
|
||||||
|
iconPath: {
|
||||||
|
dark: this.extensionContext.asAbsolutePath('resources/dark/status_info.svg'),
|
||||||
|
light: this.extensionContext.asAbsolutePath('resources/light/status_info.svg')
|
||||||
|
},
|
||||||
|
}).component();
|
||||||
|
this.toDispose.push(btnAPIDetails.onDidClick(async () => {
|
||||||
|
let infoArray: azdata.PropertiesContainerItem[] = [];
|
||||||
|
|
||||||
|
if (this.apiVersionPropItem.value) {
|
||||||
|
infoArray.push(this.apiVersionPropItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.defaultRulesetPropItem.value) {
|
||||||
|
infoArray.push(this.defaultRulesetPropItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
infoArray.push(...this.serverProps);
|
||||||
|
const message = localize('msgBoxAsmtInfo', "SQL Assessment Information") + EOL + EOL +
|
||||||
|
infoArray.map(v => `${v.displayName}: ${v.value}`).join(EOL);
|
||||||
|
|
||||||
|
const copy: vscode.MessageItem = { title: localize('msgBoxCopyBtn', "Copy") };
|
||||||
|
const ok: vscode.MessageItem = { isCloseAffordance: true, title: localize('ok', "OK") };
|
||||||
|
|
||||||
|
const response = await vscode.window.showInformationMessage(message, { modal: true }, copy, ok);
|
||||||
|
if (response === copy) {
|
||||||
|
await vscode.env.clipboard.writeText(message);
|
||||||
|
vscode.window.showInformationMessage(localize('msgBoxCopied', 'SQL Assessment Information copied'));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
btnGetAssessmentItemsLoading.loading = false;
|
||||||
|
btnInvokeAssessmentLoading.loading = false;
|
||||||
|
|
||||||
return view.modelBuilder.toolbarContainer()
|
return view.modelBuilder.toolbarContainer()
|
||||||
.withToolbarItems(
|
.withToolbarItems(
|
||||||
[
|
[
|
||||||
@@ -286,7 +270,8 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
{ component: btnGetAssessmentItemsLoading },
|
{ component: btnGetAssessmentItemsLoading },
|
||||||
{ component: this.btnExportAsScript },
|
{ component: this.btnExportAsScript },
|
||||||
{ component: this.btnHTMLExport },
|
{ component: this.btnHTMLExport },
|
||||||
{ component: btnViewSamples }
|
{ component: btnViewSamples },
|
||||||
|
{ component: btnAPIDetails }
|
||||||
]
|
]
|
||||||
).component();
|
).component();
|
||||||
}
|
}
|
||||||
@@ -294,10 +279,6 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
private displayResults(result: azdata.SqlAssessmentResult, assessmentType: AssessmentType): void {
|
private displayResults(result: azdata.SqlAssessmentResult, assessmentType: AssessmentType): void {
|
||||||
this.apiVersionPropItem.value = result.apiVersion;
|
this.apiVersionPropItem.value = result.apiVersion;
|
||||||
this.defaultRulesetPropItem.value = result.items?.length > 0 ? result.items[0].rulesetVersion : '';
|
this.defaultRulesetPropItem.value = result.items?.length > 0 ? result.items[0].rulesetVersion : '';
|
||||||
this.assessmentPropertiesContainer.propertyItems = [
|
|
||||||
this.apiVersionPropItem,
|
|
||||||
this.defaultRulesetPropItem
|
|
||||||
];
|
|
||||||
|
|
||||||
this.resultGrid.displayResult(result, assessmentType);
|
this.resultGrid.displayResult(result, assessmentType);
|
||||||
this.btnExportAsScript.enabled = this.btnHTMLExport.enabled = assessmentType === AssessmentType.InvokeAssessment;
|
this.btnExportAsScript.enabled = this.btnHTMLExport.enabled = assessmentType === AssessmentType.InvokeAssessment;
|
||||||
|
|||||||
@@ -88,7 +88,11 @@ export class SqlAssessmentHistoryTab extends SqlAssessmentTab {
|
|||||||
this.resultGrid.displayResult(historyResult.result, AssessmentType.InvokeAssessment);
|
this.resultGrid.displayResult(historyResult.result, AssessmentType.InvokeAssessment);
|
||||||
title.value = localize('asmt.history.resultsTitle', "Assessment Results from {0}", new Date(historyResult.dateUpdated).toLocaleString());
|
title.value = localize('asmt.history.resultsTitle', "Assessment Results from {0}", new Date(historyResult.dateUpdated).toLocaleString());
|
||||||
root.addItem(infoPanel, { flex: `0 0 50px` });
|
root.addItem(infoPanel, { flex: `0 0 50px` });
|
||||||
root.addItem(this.resultGrid.component);
|
root.addItem(this.resultGrid.component, {
|
||||||
|
flex: '1 1 auto', CSSStyles: {
|
||||||
|
'padding-bottom': '10px'
|
||||||
|
}
|
||||||
|
});
|
||||||
this.summaryTable.selectedRows = [];
|
this.summaryTable.selectedRows = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user