diff --git a/extensions/schema-compare/package.json b/extensions/schema-compare/package.json index df8d765a7b..aaa1da84db 100644 --- a/extensions/schema-compare/package.json +++ b/extensions/schema-compare/package.json @@ -1,7 +1,7 @@ { "name": "schema-compare", - "displayName": "SQL Server Schema Compare", - "description": "SQL Server Schema Compare for Azure Data Studio supports comparing the schemas of databases and dacpacs.", + "displayName": "%displayName%", + "description": "%description%", "version": "0.3.0", "publisher": "Microsoft", "preview": true, @@ -27,13 +27,27 @@ "commands": [ { "command": "schemaCompare.start", - "title": "Schema Compare", + "title": "%schemaCompare.start%", "icon": { "light": "./images/light_icon.svg", "dark": "./images/dark_icon.svg" } } ], + "languages": [ + { + "id": "scmp", + "filenames": [ + "Schema Compare" + ], + "extensions": [ + ".scmp" + ], + "aliases": [ + "scmp" + ] + } + ], "menus": { "objectExplorer/item/context": [ { diff --git a/extensions/schema-compare/package.nls.json b/extensions/schema-compare/package.nls.json new file mode 100644 index 0000000000..1415ebe994 --- /dev/null +++ b/extensions/schema-compare/package.nls.json @@ -0,0 +1,5 @@ +{ + "displayName": "SQL Server Schema Compare", + "description": "SQL Server Schema Compare for Azure Data Studio supports comparing the schemas of databases and dacpacs.", + "schemaCompare.start": "Schema Compare" +} \ No newline at end of file diff --git a/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts b/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts index c0ce483bcd..f02ad933af 100644 --- a/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts +++ b/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts @@ -421,7 +421,8 @@ export class SchemaCompareDialog { this.sourceServerDropdown.onValueChanged(async (value) => { if (this.sourceServerDropdown.values.findIndex(x => this.matchesValue(x, value)) === -1) { this.sourceDatabaseDropdown.updateProperties({ - values: [] + values: [], + value: ' ' }); } else { @@ -445,7 +446,8 @@ export class SchemaCompareDialog { this.targetServerDropdown.onValueChanged(async (value) => { if (this.targetServerDropdown.values.findIndex(x => this.matchesValue(x, value)) === -1) { this.targetDatabaseDropdown.updateProperties({ - values: [] + values: [], + value: ' ' }); } else { @@ -463,9 +465,12 @@ export class SchemaCompareDialog { let currentDropdown = isTarget ? this.targetServerDropdown : this.sourceServerDropdown; let values = await this.getServerValues(); - currentDropdown.updateProperties({ - values: values - }); + if (values && values.length > 0) { + currentDropdown.updateProperties({ + values: values, + value: values[0] + }); + } } protected async getServerValues(): Promise<{ connection: azdata.connection.Connection, displayName: string, name: string }[]> { @@ -562,12 +567,15 @@ export class SchemaCompareDialog { protected async populateDatabaseDropdown(connectionId: string, isTarget: boolean): Promise { let currentDropdown = isTarget ? this.targetDatabaseDropdown : this.sourceDatabaseDropdown; - currentDropdown.updateProperties({ values: [] }); + currentDropdown.updateProperties({ values: [], value: null }); let values = await this.getDatabaseValues(connectionId); - currentDropdown.updateProperties({ - values: values - }); + if (values && values.length > 0) { + currentDropdown.updateProperties({ + values: values, + value: values[0], + }); + } } protected async getDatabaseValues(connectionId: string): Promise<{ displayName, name }[]> { diff --git a/extensions/schema-compare/src/schemaCompareResult.ts b/extensions/schema-compare/src/schemaCompareResult.ts index 682e8ce038..cc968e30a8 100644 --- a/extensions/schema-compare/src/schemaCompareResult.ts +++ b/extensions/schema-compare/src/schemaCompareResult.ts @@ -19,6 +19,10 @@ const generateScriptEnabledMessage = localize('schemaCompare.generateScriptEnabl const generateScriptNoChangesMessage = localize('schemaCompare.generateScriptNoChanges', 'No changes to script'); const applyEnabledMessage = localize('schemaCompare.applyButtonEnabledTitle', 'Apply changes to target'); const applyNoChangesMessage = localize('schemaCompare.applyNoChanges', 'No changes to apply'); +// Do not localize this, this is used to decide the icon for the editor. +// TODO : In future icon should be decided based on language id (scmp) and not resource name +const schemaCompareResourceName = 'Schema Compare'; + export class SchemaCompareResult { private differencesTable: azdata.TableComponent; @@ -53,7 +57,7 @@ export class SchemaCompareResult { this.SchemaCompareActionMap[azdata.SchemaUpdateAction.Change] = localize('schemaCompare.changeAction', 'Change'); this.SchemaCompareActionMap[azdata.SchemaUpdateAction.Add] = localize('schemaCompare.addAction', 'Add'); - this.editor = azdata.workspace.createModelViewEditor(localize('schemaCompare.Title', 'Schema Compare'), { retainContextWhenHidden: true, supportsSave: true }); + this.editor = azdata.workspace.createModelViewEditor(localize('schemaCompare.Title', 'Schema Compare'), { retainContextWhenHidden: true, supportsSave: true, resourceName: schemaCompareResourceName }); this.GetDefaultDeploymentOptions(); this.editor.registerContent(async view => { @@ -178,10 +182,15 @@ export class SchemaCompareResult { } // only for test - public getComparisionResult(): azdata.SchemaCompareResult { + public getComparisonResult(): azdata.SchemaCompareResult { return this.comparisonResult; } + // only for test + public getDeploymentOptions(): azdata.DeploymentOptions { + return this.deploymentOptions; + } + public async execute(): Promise { if (this.schemaCompareOptionDialog && this.schemaCompareOptionDialog.deploymentOptions) { // take updates if any diff --git a/extensions/schema-compare/src/test/schemaCompare.test.ts b/extensions/schema-compare/src/test/schemaCompare.test.ts index 7807a2e202..cf321ce8f4 100644 --- a/extensions/schema-compare/src/test/schemaCompare.test.ts +++ b/extensions/schema-compare/src/test/schemaCompare.test.ts @@ -69,10 +69,10 @@ describe('SchemaCompareResult.start', function(): void { await promise; await result.start(); - should(result.getComparisionResult() === undefined); + should(result.getComparisonResult() === undefined); await result.execute(); - should(result.getComparisionResult() !== undefined); - should(result.getComparisionResult().operationId !== undefined); + should(result.getComparisonResult() !== undefined); + should(result.getComparisonResult().operationId !== undefined); }); }); diff --git a/extensions/theme-seti/icons/images/scmp.svg b/extensions/theme-seti/icons/images/scmp.svg new file mode 100644 index 0000000000..7e1e638ad6 --- /dev/null +++ b/extensions/theme-seti/icons/images/scmp.svg @@ -0,0 +1,5 @@ + +SchemaCompare + + + \ No newline at end of file diff --git a/extensions/theme-seti/icons/images/scmp_inverse.svg b/extensions/theme-seti/icons/images/scmp_inverse.svg new file mode 100644 index 0000000000..a6f201ebca --- /dev/null +++ b/extensions/theme-seti/icons/images/scmp_inverse.svg @@ -0,0 +1,10 @@ + + +SchemaCompare + + + diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index 06fe72e59f..6b8fa8f54b 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1247,6 +1247,12 @@ }, "notebook_dark": { "iconPath": "./images/notebook_inverse.svg" + }, + "scmp": { + "iconPath": "./images/scmp.svg" + }, + "scmp_dark": { + "iconPath": "./images/scmp_inverse.svg" } }, "file": "_default", @@ -1431,7 +1437,8 @@ "cert": "_lock", "ds_store": "_ignored", // {{SQL CARBON EDIT}} - "ipynb": "notebook_dark" + "ipynb": "notebook_dark", + "scmp": "scmp_dark" }, "fileNames": { "mix": "_hex", @@ -1480,7 +1487,8 @@ "todo": "_todo", "npm-debug.log": "_npm_ignored", "dashboard": "_shell", - "profiler": "_csv" + "profiler": "_csv", + "Schema Compare": "scmp_dark", }, "languageIds": { "bat": "_windows", @@ -1542,7 +1550,8 @@ "vala": "_vala", "todo": "_todo", // {{SQL CARBON EDIT}} - "notebook": "notebook_dark" + "notebook": "notebook_dark", + "scmp": "scmp_dark" }, "light": { "file": "_default_light", @@ -1727,7 +1736,8 @@ "cert": "_lock_light", "ds_store": "_ignored_light", // {{SQL CARBON EDIT}} - "ipynb": "notebook" + "ipynb": "notebook", + "scmp": "scmp" }, "languageIds": { "bat": "_windows_light", @@ -1788,7 +1798,8 @@ "stylus": "_stylus_light", "vala": "_vala_light", // {{SQL CARBON EDIT}} - "notebook": "notebook" + "notebook": "notebook", + "scmp": "scmp" }, "fileNames": { "mix": "_hex_light", @@ -1836,7 +1847,8 @@ "procfile": "_heroku_light", "npm-debug.log": "_npm_ignored_light", "dashboard": "_shell_light", - "profiler": "_csv_light" + "profiler": "_csv_light", + "Schema Compare": "scmp" } }, "version": "https://github.com/jesseweed/seti-ui/commit/89175d7f9e0c70cd325b80a18a3c77fc8eb7c798" diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 25a9b52583..8f8816a76c 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -3992,6 +3992,13 @@ declare module 'azdata' { * Does this model view editor support save? */ readonly supportsSave?: boolean; + + /** + * Resource name for this editor + * File icons might depend on file extension, language id or resource name + * Resource name field needs to be set explitly if file icon for a particular Model View Editor depends on editor resource name + */ + readonly resourceName?: string; } export enum DataProviderType { diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index 6bce817b3b..f1be903dd5 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -484,7 +484,7 @@ export abstract class ExtHostDataProtocolShape { /** - * Schema comapre Include node + * Schema compare Include node */ $schemaCompareIncludeExcludeNode(handle: number, operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable { throw ni(); } } diff --git a/src/sql/workbench/electron-browser/modelComponents/componentBase.ts b/src/sql/workbench/electron-browser/modelComponents/componentBase.ts index a04828fbcc..b33ac39454 100644 --- a/src/sql/workbench/electron-browser/modelComponents/componentBase.ts +++ b/src/sql/workbench/electron-browser/modelComponents/componentBase.ts @@ -268,6 +268,9 @@ export abstract class ContainerBase extends ComponentBase { /// IComponent container-related implementation public addToContainer(componentDescriptor: IComponentDescriptor, config: any, index?: number): void { + if (!componentDescriptor) { + return; + } if (this.items.some(item => item.descriptor.id === componentDescriptor.id && item.descriptor.type === componentDescriptor.type)) { return; } @@ -288,6 +291,9 @@ export abstract class ContainerBase extends ComponentBase { } public removeFromContainer(componentDescriptor: IComponentDescriptor): boolean { + if (!componentDescriptor) { + return false; + } let index = this.items.findIndex(item => item.descriptor.id === componentDescriptor.id && item.descriptor.type === componentDescriptor.type); if (index >= 0) { this.items.splice(index, 1); diff --git a/src/sql/workbench/electron-browser/modelComponents/modelViewInput.ts b/src/sql/workbench/electron-browser/modelComponents/modelViewInput.ts index 845d6a9de3..6faa0cd2b2 100644 --- a/src/sql/workbench/electron-browser/modelComponents/modelViewInput.ts +++ b/src/sql/workbench/electron-browser/modelComponents/modelViewInput.ts @@ -14,6 +14,7 @@ import { DialogPane } from 'sql/platform/dialog/dialogPane'; import { Emitter, Event } from 'vs/base/common/event'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { URI } from 'vs/base/common/uri'; export type ModeViewSaveHandler = (handle: number) => Thenable; @@ -50,6 +51,7 @@ export class ModelViewInputModel extends EditorModel { export class ModelViewInput extends EditorInput { public static ID: string = 'workbench.editorinputs.ModelViewEditorInput'; + public static Scheme: string = 'ModelViewEditorScheme'; private _container: HTMLElement; private _dialogPaneContainer: HTMLElement; private _dialogPane: DialogPane; @@ -87,6 +89,13 @@ export class ModelViewInput extends EditorInput { return this._title; } + public getResource(): URI { + if (this._options.resourceName) { + return URI.from({ scheme: ModelViewInput.Scheme, path: this._options.resourceName }); + } + return super.getResource(); + } + public get container(): HTMLElement { return this._container; }