diff --git a/extensions/sql-assessment/README.md b/extensions/sql-assessment/README.md index 5d3c214c58..be145ad7c0 100644 --- a/extensions/sql-assessment/README.md +++ b/extensions/sql-assessment/README.md @@ -4,16 +4,21 @@ SQL Assessment for Azure Data Studio provides a mechanism to evaluate the config - Assess a SQL Server or Azure SQL Managed Instance and its databases with built-in rules (Invoke Assessment) - Get a list of all built-in rules applicable to an instance and its databases (View applicable rules) -- Export assessment results and list of applicable rules as script to further store it in a SQL table +- Export assessment results and the list of applicable rules as a script to store it in a SQL table (Export as script) +- Create HTML reports on assessments results (Create HTML Report) + +![SqlAssessmentPic](https://user-images.githubusercontent.com/61055430/102236901-1aaf1400-3f05-11eb-9ffd-da9ab9b5d146.png) -![SqlAssessmentPic](https://user-images.githubusercontent.com/61055430/87181263-ad121280-c2ea-11ea-9361-19fa6d3c1ea1.png) ### How do I start SQL Assessment? -SQL Assessment adds its own tab on the main dashboard – you will find it in the General section after installing the extension. Pick the tab and click “Invoke Assessment” to assess the current SQL Server instance and all its databases. Once the results on the grid, you can use the filtering and sorting features of the column headers to display them your own way. Click “Export as Script” to get the results in an insert-into-table format on a new tab. -If the dashboard is opened for a database, the “Invoke Assessment” button runs an assessment for this database only. - -Some assessment rules are for particular SQL Server configurations and some for others. The same is true for database rules. For example, there are rules that are applicable only to SQL Server 2016 or the tempdb database. “View applicable rules” button displays those assessment rules that this current object, either a server or database, will be checked by, when you click “Invoke Assessment.” +After you install the SQL Assessment extension, open the list with your servers, right-click a server or database that you want to assess and select **Manage**. Then, in the **General** section, select **SQL Assessment**. +On the **Assessment** tab, click **Invoke Assessment** to perform assessment of the selected SQL Server or SQL Database. Once the results are available, you can use the filtering and sorting features. +Click **Export as Script** to get the results in an insert-into-table format. You can also click **Create HTML Report** to save the assessment results as an HTML file. +Some assessment rules are intended for particular SQL Server configurations and some for others. The same is true for database rules. For example, there are rules that are applicable only to SQL Server 2016 or the tempdb database. +The **View applicable rules** button displays the assessment rules that are used to perform assessment of your servers and databases after you click **Invoke Assessment**. +To view information about SQL Server and SQL Assessment API, click **Info**. +Assessment session results can be reviewed on the **History** tab. ## Code of Conduct This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/extensions/sql-assessment/package.json b/extensions/sql-assessment/package.json index 899b5f7dca..8341b960c0 100644 --- a/extensions/sql-assessment/package.json +++ b/extensions/sql-assessment/package.json @@ -2,7 +2,7 @@ "name": "sql-assessment", "displayName": "%displayName%", "description": "%description%", - "version": "0.5.0", + "version": "0.6.0", "publisher": "Microsoft", "preview": true, "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt", diff --git a/extensions/sql-assessment/src/localized.ts b/extensions/sql-assessment/src/localized.ts index 9fa67b4052..bb6a9b40c8 100644 --- a/extensions/sql-assessment/src/localized.ts +++ b/extensions/sql-assessment/src/localized.ts @@ -7,7 +7,7 @@ import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); export const LocalizedStrings = { - SECTION_TITLE_API: localize('asmt.section.api.title', "API information"), + SECTION_TITLE_API: localize('asmt.section.api.title', "Info"), API_VERSION: localize('asmt.apiversion', "API Version"), DEFAULT_RULESET_VERSION: localize('asmt.rulesetversion', "Default Ruleset"), SECTION_TITLE_SQL_SERVER: localize('asmt.section.instance.title', "SQL Server Instance Details"), diff --git a/extensions/sql-assessment/src/tabs/assessmentMainTab.ts b/extensions/sql-assessment/src/tabs/assessmentMainTab.ts index dfb5a3ead0..8bbbd2a51b 100644 --- a/extensions/sql-assessment/src/tabs/assessmentMainTab.ts +++ b/extensions/sql-assessment/src/tabs/assessmentMainTab.ts @@ -9,7 +9,7 @@ import * as nls from 'vscode-nls'; import { SqlAssessmentTab } from './sqlAssessmentTab'; import { AssessmentEngine, AssessmentType } from '../engine'; import { promises as fs } from 'fs'; -import { suggestReportFile } from '../utils'; +import { suggestReportFile, limitLongName } from '../utils'; import { HTMLReportBuilder } from '../htmlReportGenerator'; import { AssessmentResultGrid } from '../assessmentResultGrid'; import { LocalizedStrings } from '../localized'; @@ -69,8 +69,7 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { rootContainer.addItem(await this.createToolbar(view), { flex: '0 0 auto', CSSStyles: { - 'border-top': '3px solid rgb(221, 221, 221)', - 'height': '32px' + 'border-top': '3px solid rgb(221, 221, 221)' } }); @@ -96,8 +95,9 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { ]; } - private async createToolbar(view: azdata.ModelView): Promise { + + private async createToolbar(view: azdata.ModelView): Promise { const targetIconPath = this.engine.isServerConnection ? { dark: this.extensionContext.asAbsolutePath('resources/dark/server.svg'), @@ -107,18 +107,22 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { light: this.extensionContext.asAbsolutePath('resources/light/database.svg') }; const iconSize: number = 16; + const btnHeight: string = '26px'; + const maxNameLength: number = 40; const btnInvokeAssessment = view.modelBuilder.button() .withProperties({ - label: this.invokeAssessmentLabel, + label: limitLongName(this.invokeAssessmentLabel, maxNameLength), iconPath: targetIconPath, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight + }).component(); const btnInvokeAssessmentLoading = view.modelBuilder.loadingComponent() .withItem(btnInvokeAssessment) .withProperties({ - loadingText: this.invokeAssessmentLabel, + loadingText: limitLongName(this.invokeAssessmentLabel, maxNameLength), showText: true, loading: false }).component(); @@ -142,15 +146,16 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { const btnGetAssessmentItems = view.modelBuilder.button() .withProperties({ - label: this.getItemsLabel, + label: limitLongName(this.getItemsLabel, maxNameLength), iconPath: targetIconPath, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight }).component(); const btnGetAssessmentItemsLoading = view.modelBuilder.loadingComponent() .withItem(btnGetAssessmentItems) .withProperties({ - loadingText: this.getItemsLabel, + loadingText: limitLongName(this.getItemsLabel, maxNameLength), showText: true, loading: false }).component(); @@ -181,7 +186,8 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { light: this.extensionContext.asAbsolutePath('resources/light/newquery.svg') }, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight }).component(); this.toDispose.push(this.btnExportAsScript.onDidClick(async () => { this.engine.generateAssessmentScript(); @@ -196,7 +202,8 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { light: this.extensionContext.asAbsolutePath('resources/light/book.svg') }, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight }).component(); this.toDispose.push(this.btnHTMLExport.onDidClick(async () => { @@ -224,13 +231,15 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { let btnViewSamples = view.modelBuilder.button() .withProperties({ - label: localize('btnViewSamples', "View all rules and learn more on GitHub"), + label: localize('btnViewSamplesShort', "View all on GitHub"), iconPath: { dark: this.extensionContext.asAbsolutePath('resources/dark/configuredashboard_inverse.svg'), light: this.extensionContext.asAbsolutePath('resources/light/configuredashboard.svg') }, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight, + title: localize('btnViewSamples', "View all rules and learn more on GitHub"), }).component(); this.toDispose.push(btnViewSamples.onDidClick(() => { @@ -246,7 +255,8 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab { light: this.extensionContext.asAbsolutePath('resources/light/status_info.svg') }, iconHeight: iconSize, - iconWidth: iconSize + iconWidth: iconSize, + height: btnHeight }).component(); this.toDispose.push(btnAPIDetails.onDidClick(async () => { let infoArray: azdata.PropertiesContainerItem[] = []; diff --git a/extensions/sql-assessment/src/utils.ts b/extensions/sql-assessment/src/utils.ts index e47f05b42f..cf3c93d62e 100644 --- a/extensions/sql-assessment/src/utils.ts +++ b/extensions/sql-assessment/src/utils.ts @@ -96,3 +96,12 @@ export function htmlEscape(html: string): string { function escapeFileName(str: string): string { return str.replace(/\*/g, '_'); } + +export function limitLongName(name: string, maxLength: number): string { + if (name.length > maxLength) { + return name.slice(0, maxLength) + '...'; + } + return name; +} + +