diff --git a/extensions/sql-assessment/resources/dark/status_info.svg b/extensions/sql-assessment/resources/dark/status_info.svg
new file mode 100644
index 0000000000..c998075774
--- /dev/null
+++ b/extensions/sql-assessment/resources/dark/status_info.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extensions/sql-assessment/resources/light/status_info.svg b/extensions/sql-assessment/resources/light/status_info.svg
new file mode 100644
index 0000000000..b1c0cbd521
--- /dev/null
+++ b/extensions/sql-assessment/resources/light/status_info.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extensions/sql-assessment/src/assessmentResultGrid.ts b/extensions/sql-assessment/src/assessmentResultGrid.ts
index b3a4a6eac2..3676a5949d 100644
--- a/extensions/sql-assessment/src/assessmentResultGrid.ts
+++ b/extensions/sql-assessment/src/assessmentResultGrid.ts
@@ -30,7 +30,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
private asmtType!: AssessmentType;
private targetTypeIcon: { [targetType: number]: azdata.IconColumnCellValue };
-
private readonly checkIdColOrder = 5;
private readonly targetColOrder = 1;
private readonly messageColOrder = 3;
@@ -81,7 +80,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
headerFilter: true
}).component();
-
this.toDispose.push(
this.table.onRowSelected(async () => {
if (this.table.selectedRows?.length !== 1) {
@@ -90,7 +88,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
await this.showDetails(this.table.selectedRows[0]);
}));
-
this.rootContainer = view.modelBuilder.flexContainer()
.withItems([this.table], {
flex: '1 1 auto',
@@ -109,7 +106,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
flex: '0 0 200px',
order: 2,
CSSStyles: {
- 'padding-bottom': '15px',
'visibility': 'hidden'
}
});
@@ -132,17 +128,21 @@ export class AssessmentResultGrid implements vscode.Disposable {
this.rootContainer.setItemLayout(this.table, {
flex: '1 1 auto',
CSSStyles: {
- 'height': '100%'
+ 'height': '100%',
+ 'border-bottom': '3px solid rgb(221, 221, 221)'
}
});
await this.table.updateProperties({
'height': '100%'
});
-
- this.detailsPanel.updateCssStyles({
- 'visibility': 'hidden'
- });
+ if (this.dataItems.length > 0) {
+ this.table.selectedRows = [0];
+ } else {
+ await this.detailsPanel.updateCssStyles({
+ 'visibility': 'hidden'
+ });
+ }
}
// we need to filter out warnings and error results since we don't have an appropriate way of displaying such messages.
@@ -196,8 +196,6 @@ export class AssessmentResultGrid implements vscode.Disposable {
});
}
-
-
private createDetailsPanel(view: azdata.ModelView): azdata.FlexContainer {
const root = view.modelBuilder.flexContainer()
@@ -206,8 +204,7 @@ export class AssessmentResultGrid implements vscode.Disposable {
height: '200px',
}).withProperties({
CSSStyles: {
- 'padding': '20px',
- 'border-top': '3px solid rgb(221, 221, 221)'
+ 'padding': '0px 10px'
}
}).component();
const cssNoMarginFloatLeft = { 'margin': '0px', 'float': 'left' };
@@ -285,6 +282,7 @@ export class AssessmentResultGrid implements vscode.Disposable {
return root;
}
+
private clearOutDefaultRuleset(tags: string[]): string[] {
let idx = tags.findIndex(item => item.toUpperCase() === 'DEFAULTRULESET');
if (idx > -1) {
diff --git a/extensions/sql-assessment/src/tabs/assessmentMainTab.ts b/extensions/sql-assessment/src/tabs/assessmentMainTab.ts
index f3af36d64e..8b3e42acff 100644
--- a/extensions/sql-assessment/src/tabs/assessmentMainTab.ts
+++ b/extensions/sql-assessment/src/tabs/assessmentMainTab.ts
@@ -14,13 +14,15 @@ import { HTMLReportBuilder } from '../htmlReportGenerator';
import { AssessmentResultGrid } from '../assessmentResultGrid';
import { LocalizedStrings } from '../localized';
import { TelemetryReporter, SqlAssessmentTelemetryView, SqlTelemetryActions } from '../telemetry';
+import { EOL } from 'os';
const localize = nls.loadMessageBundle();
export class SqlAssessmentMainTab extends SqlAssessmentTab {
- private assessmentPropertiesContainer!: azdata.PropertiesContainerComponent;
private apiVersionPropItem: azdata.PropertiesContainerItem;
private defaultRulesetPropItem: azdata.PropertiesContainerItem;
+ private serverProps: azdata.PropertiesContainerItem[] = [];
+
private invokeAssessmentLabel: string = localize('invokeAssessmentLabelServer', "Invoke assessment");
private getItemsLabel: string = localize('getAssessmentItemsServer', "View applicable rules");
private btnExportAsScript!: azdata.ButtonComponent;
@@ -31,7 +33,6 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
private resultGrid!: AssessmentResultGrid;
-
public constructor(extensionContext: vscode.ExtensionContext, engine: AssessmentEngine) {
super(extensionContext, LocalizedStrings.ASSESSMENT_TAB_NAME, 'MainTab', {
dark: extensionContext.asAbsolutePath('resources/dark/server.svg'),
@@ -64,12 +65,11 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
height: '100%',
}).component();
+ await this.createServerProperties(view);
- rootContainer.addItem(await this.createPropertiesSection(view), { flex: '0 0 auto' });
rootContainer.addItem(await this.createToolbar(view), {
flex: '0 0 auto', CSSStyles: {
'border-top': '3px solid rgb(221, 221, 221)',
- 'margin-top': '20px',
'height': '32px'
}
});
@@ -78,74 +78,22 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
rootContainer.addItem(this.resultGrid.component, {
flex: '1 1 auto',
CSSStyles: {
- 'padding-bottom': '15px'
+ 'padding-bottom': '10px'
}
});
return rootContainer;
}
- private async createPropertiesSection(view: azdata.ModelView): Promise {
+ private async createServerProperties(view: azdata.ModelView): Promise {
const serverInfo = await azdata.connection.getServerInfo(view.connection.connectionId);
const connectionProfile = await azdata.connection.getCurrentConnection();
-
- 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({
- 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({
- propertyItems: [
- { displayName: LocalizedStrings.SERVER_VERSION, value: serverInfo.serverVersion },
- { displayName: LocalizedStrings.SERVER_INSTANCENAME, value: connectionProfile.serverName },
- { displayName: LocalizedStrings.SERVER_EDITION, value: serverInfo.serverEdition },
- { 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;
+ this.serverProps = [
+ { displayName: LocalizedStrings.SERVER_VERSION, value: serverInfo.serverVersion },
+ { displayName: LocalizedStrings.SERVER_INSTANCENAME, value: connectionProfile.serverName },
+ { displayName: LocalizedStrings.SERVER_EDITION, value: serverInfo.serverEdition },
+ { displayName: LocalizedStrings.SERVER_OSVERSION, value: serverInfo.osVersion },
+ ];
}
private async createToolbar(view: azdata.ModelView): Promise {
@@ -279,6 +227,42 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/sql-assessment-api'));
}));
+ let btnAPIDetails = view.modelBuilder.button()
+ .withProperties({
+ 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()
.withToolbarItems(
[
@@ -286,7 +270,8 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
{ component: btnGetAssessmentItemsLoading },
{ component: this.btnExportAsScript },
{ component: this.btnHTMLExport },
- { component: btnViewSamples }
+ { component: btnViewSamples },
+ { component: btnAPIDetails }
]
).component();
}
@@ -294,10 +279,6 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
private displayResults(result: azdata.SqlAssessmentResult, assessmentType: AssessmentType): void {
this.apiVersionPropItem.value = result.apiVersion;
this.defaultRulesetPropItem.value = result.items?.length > 0 ? result.items[0].rulesetVersion : '';
- this.assessmentPropertiesContainer.propertyItems = [
- this.apiVersionPropItem,
- this.defaultRulesetPropItem
- ];
this.resultGrid.displayResult(result, assessmentType);
this.btnExportAsScript.enabled = this.btnHTMLExport.enabled = assessmentType === AssessmentType.InvokeAssessment;
diff --git a/extensions/sql-assessment/src/tabs/historyTab.ts b/extensions/sql-assessment/src/tabs/historyTab.ts
index 356de7e12e..a7e1ec4c03 100644
--- a/extensions/sql-assessment/src/tabs/historyTab.ts
+++ b/extensions/sql-assessment/src/tabs/historyTab.ts
@@ -88,7 +88,11 @@ export class SqlAssessmentHistoryTab extends SqlAssessmentTab {
this.resultGrid.displayResult(historyResult.result, AssessmentType.InvokeAssessment);
title.value = localize('asmt.history.resultsTitle', "Assessment Results from {0}", new Date(historyResult.dateUpdated).toLocaleString());
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 = [];
}