diff --git a/extensions/machine-learning/src/packageManagement/packageManageProviderBase.ts b/extensions/machine-learning/src/packageManagement/packageManageProviderBase.ts index 633244d1fa..377697ae6d 100644 --- a/extensions/machine-learning/src/packageManagement/packageManageProviderBase.ts +++ b/extensions/machine-learning/src/packageManagement/packageManageProviderBase.ts @@ -35,6 +35,14 @@ export abstract class SqlPackageManageProviderBase { return []; } + /** + * Returns database name as current location + */ + public async getCurrentLocation(): Promise { + let connection = await this.getCurrentConnection(); + return connection?.databaseName; + } + protected async getCurrentConnection(): Promise { return await this._apiWrapper.getCurrentConnection(); } diff --git a/extensions/machine-learning/src/typings/notebookServices.d.ts b/extensions/machine-learning/src/typings/notebookServices.d.ts index 9cb855abd7..43879c8693 100644 --- a/extensions/machine-learning/src/typings/notebookServices.d.ts +++ b/extensions/machine-learning/src/typings/notebookServices.d.ts @@ -99,6 +99,11 @@ export interface IPackageManageProvider { */ getLocations(): Promise; + /** + * Get the current location + */ + getCurrentLocation(): Promise; + /** * Returns Package Overview * @param packageName package name diff --git a/extensions/notebook/src/dialog/managePackages/installedPackagesTab.ts b/extensions/notebook/src/dialog/managePackages/installedPackagesTab.ts index c2ac82857a..20affa7a17 100644 --- a/extensions/notebook/src/dialog/managePackages/installedPackagesTab.ts +++ b/extensions/notebook/src/dialog/managePackages/installedPackagesTab.ts @@ -170,16 +170,18 @@ export class InstalledPackagesTab { component = view.modelBuilder.text().withProperties({ value: locations[0].displayName }).component(); - } else if (locations) { + } else if (locations && locations.length > 1) { let dropdownValues = locations.map(x => { return { name: x.name, displayName: x.displayName }; }); + const currentLocation = await dialog.model.getCurrentLocation(); + const selectedLocation = dropdownValues.find(x => x.name === currentLocation); let locationDropDown = view.modelBuilder.dropDown().withProperties({ values: dropdownValues, - value: dropdownValues[0] + value: selectedLocation || dropdownValues[0] }).component(); locationDropDown.onValueChanged(async () => { diff --git a/extensions/notebook/src/dialog/managePackages/managePackagesDialogModel.ts b/extensions/notebook/src/dialog/managePackages/managePackagesDialogModel.ts index d9b101aa76..c7ebd0cfc5 100644 --- a/extensions/notebook/src/dialog/managePackages/managePackagesDialogModel.ts +++ b/extensions/notebook/src/dialog/managePackages/managePackagesDialogModel.ts @@ -213,7 +213,9 @@ export class ManagePackagesDialogModel { * Changes the current location */ public changeLocation(location: string): void { - this._currentLocation = location; + if (location) { + this._currentLocation = location; + } } /** @@ -240,6 +242,19 @@ export class ManagePackagesDialogModel { return Promise.resolve(undefined); } + /** + * Returns the current location for current provider + */ + public async getCurrentLocation(): Promise { + if (!this._currentLocation) { + let provider = this.currentPackageManageProvider; + if (provider) { + return await provider.getCurrentLocation(); + } + } + return Promise.resolve(this._currentLocation); + } + /** * UnInstalls given packages using current provider * @param packages Packages to install diff --git a/extensions/notebook/src/jupyter/localCondaPackageManageProvider.ts b/extensions/notebook/src/jupyter/localCondaPackageManageProvider.ts index a0746218cd..bbb636a311 100644 --- a/extensions/notebook/src/jupyter/localCondaPackageManageProvider.ts +++ b/extensions/notebook/src/jupyter/localCondaPackageManageProvider.ts @@ -48,6 +48,13 @@ export class LocalCondaPackageManageProvider implements IPackageManageProvider { return this.jupyterInstallation.installCondaPackages(packages, useMinVersion); } + /** + * Returns current location + */ + public async getCurrentLocation(): Promise { + return Promise.resolve(constants.localhostName); + } + /** * Uninstalls given packages * @param packages Packages to uninstall diff --git a/extensions/notebook/src/jupyter/localPipPackageManageProvider.ts b/extensions/notebook/src/jupyter/localPipPackageManageProvider.ts index b071b41313..62199b663e 100644 --- a/extensions/notebook/src/jupyter/localPipPackageManageProvider.ts +++ b/extensions/notebook/src/jupyter/localPipPackageManageProvider.ts @@ -66,6 +66,13 @@ export class LocalPipPackageManageProvider implements IPackageManageProvider { return Promise.resolve(true); } + /** + * Returns current location + */ + public async getCurrentLocation(): Promise { + return Promise.resolve(constants.localhostName); + } + /** * Returns location title */ diff --git a/extensions/notebook/src/test/managePackages/managePackagesDialogModel.test.ts b/extensions/notebook/src/test/managePackages/managePackagesDialogModel.test.ts index 152eb66dd7..924e4e9da4 100644 --- a/extensions/notebook/src/test/managePackages/managePackagesDialogModel.test.ts +++ b/extensions/notebook/src/test/managePackages/managePackagesDialogModel.test.ts @@ -49,7 +49,7 @@ describe('Manage Packages', () => { should.equal(model.defaultLocation, undefined, 'Default Location should be undefined'); should.equal(model.defaultProviderId, provider.providerId, 'Default Provider ID should be correct'); should.deepEqual(model.getPackageTypes(), [], 'Undefined location should return empty array when calling getPackageTypes'); - should.deepEqual(model.getPackageTypes('location1'), [],'Valid location should return empty array when calling getPackageTypes'); + should.deepEqual(model.getPackageTypes('location1'), [], 'Valid location should return empty array when calling getPackageTypes'); should.equal(model.getDefaultPackageType(), undefined, 'Default Package Type should be undefined'); should.deepEqual(await model.listPackages(), [], 'Packages list should be empty'); await should(model.installPackages([])).rejected(); @@ -138,6 +138,34 @@ describe('Manage Packages', () => { should.equal(model.jupyterInstallation, jupyterServerInstallation); }); + it('CurrentLocation should return provider current location if specified', async function (): Promise { + let testContext1 = createContext(); + testContext1.provider.providerId = 'providerId1'; + testContext1.provider.packageTarget = { + location: 'location1', + packageType: 'package-type1' + }; + + let testContext2 = createContext(); + testContext2.provider.providerId = 'providerId2'; + testContext2.provider.packageTarget = { + location: 'location1', + packageType: 'package-type2' + }; + let providers = new Map(); + providers.set(testContext1.provider.providerId, createProvider(testContext1)); + providers.set(testContext2.provider.providerId, createProvider(testContext2)); + + let model = new ManagePackagesDialogModel(jupyterServerInstallation, providers, undefined); + + await model.init(); + let actual = await model.getCurrentLocation(); + should.equal(actual, 'location2'); + model.changeLocation('location1'); + actual = await model.getCurrentLocation(); + should.equal(actual, 'location1'); + }); + it('Should create a cache for multiple providers successfully', async function (): Promise { let testContext1 = createContext(); testContext1.provider.providerId = 'providerId1'; @@ -168,8 +196,8 @@ describe('Manage Packages', () => { await model.init(); should.equal(model.defaultLocation, testContext1.provider.packageTarget.location); - should.deepEqual(model.getPackageTypes('location1'), [{ providerId: 'providerId1', packageType: 'package-type1'}, {providerId: 'providerId2', packageType: 'package-type2'}]); - should.deepEqual(model.getPackageTypes('location2'), [{providerId: 'providerId3', packageType: 'package-type1'}]); + should.deepEqual(model.getPackageTypes('location1'), [{ providerId: 'providerId1', packageType: 'package-type1' }, { providerId: 'providerId2', packageType: 'package-type2' }]); + should.deepEqual(model.getPackageTypes('location2'), [{ providerId: 'providerId3', packageType: 'package-type1' }]); }); it('Should not include a provider that can not be used in current context', async function (): Promise { @@ -196,7 +224,7 @@ describe('Manage Packages', () => { await model.init(); should.equal(model.defaultLocation, testContext1.provider.packageTarget.location); - should.deepEqual(model.getPackageTypes('location1'), [{providerId: 'providerId1', packageType: 'package-type1'}]); + should.deepEqual(model.getPackageTypes('location1'), [{ providerId: 'providerId1', packageType: 'package-type1' }]); }); it('Should set default location to one set in given options', async function (): Promise { @@ -226,13 +254,13 @@ describe('Manage Packages', () => { await model.init(); should.equal(model.defaultLocation, testContext2.provider.packageTarget.location); - should.deepEqual(model.getPackageTypes('location1'), [{providerId: 'providerId1', packageType: 'package-type1'}]); + should.deepEqual(model.getPackageTypes('location1'), [{ providerId: 'providerId1', packageType: 'package-type1' }]); }); it('changeProvider should change current provider successfully', async function (): Promise { let testContext1 = createContext(); testContext1.provider.providerId = 'providerId1'; - testContext1.provider.getLocations = () => Promise.resolve([{displayName: 'location title 1', name: 'location1'}]); + testContext1.provider.getLocations = () => Promise.resolve([{ displayName: 'location title 1', name: 'location1' }]); testContext1.provider.packageTarget = { location: 'location1', packageType: 'package-type1' @@ -240,7 +268,7 @@ describe('Manage Packages', () => { let testContext2 = createContext(); testContext2.provider.providerId = 'providerId2'; - testContext2.provider.getLocations = () => Promise.resolve([{displayName: 'location title 2', name: 'location2'}]); + testContext2.provider.getLocations = () => Promise.resolve([{ displayName: 'location title 2', name: 'location2' }]); testContext2.provider.packageTarget = { location: 'location2', packageType: 'package-type2' @@ -254,7 +282,7 @@ describe('Manage Packages', () => { await model.init(); model.changeProvider('providerId2'); - should.deepEqual(await model.getLocations(), [{displayName: 'location title 2', name: 'location2'}]); + should.deepEqual(await model.getLocations(), [{ displayName: 'location title 2', name: 'location2' }]); }); it('changeProvider should throw exception given invalid provider', async function (): Promise { @@ -320,7 +348,7 @@ describe('Manage Packages', () => { let testContext2 = createContext(); testContext2.provider.providerId = 'providerId2'; - testContext2.provider.getLocations = () => Promise.resolve([{displayName: 'location title 2', name: 'location2'}]); + testContext2.provider.getLocations = () => Promise.resolve([{ displayName: 'location title 2', name: 'location2' }]); testContext2.provider.packageTarget = { location: 'location2', packageType: 'package-type2' @@ -358,7 +386,7 @@ describe('Manage Packages', () => { await should(model.installPackages(packages)).resolved(); await should(model.uninstallPackages(packages)).resolved(); await should(model.getPackageOverview('p1')).resolved(); - await should(model.getLocations()).resolvedWith([{displayName: 'location title 2', name: 'location2'}]); + await should(model.getLocations()).resolvedWith([{ displayName: 'location title 2', name: 'location2' }]); }); it('listPackages should return packages for current location', async function (): Promise { @@ -385,7 +413,7 @@ describe('Manage Packages', () => { }]; testContext.provider.listPackages = (location) => { if (location === 'location1') { - return Promise.resolve(packages1); + return Promise.resolve(packages1); } else { return Promise.resolve(packages2); } @@ -413,8 +441,9 @@ describe('Manage Packages', () => { packageType: 'package-type' }, canUseProvider: () => { return Promise.resolve(true); }, - getLocations: () => { return Promise.resolve([{displayName: 'location-title', name: 'location'}]); }, - installPackages:() => { return Promise.resolve(); }, + getLocations: () => { return Promise.resolve([{ displayName: 'location-title', name: 'location' }, { displayName: 'location2-title', name: 'location2' }]); }, + getCurrentLocation: () => { return Promise.resolve('location2'); }, + installPackages: () => { return Promise.resolve(); }, uninstallPackages: (packages: IPackageDetails[]) => { return Promise.resolve(); }, listPackages: () => { return Promise.resolve([]); }, getPackageOverview: (name: string) => { return Promise.resolve(undefined); }, @@ -426,6 +455,7 @@ describe('Manage Packages', () => { let mockProvider = TypeMoq.Mock.ofType(LocalPipPackageManageProvider); mockProvider.setup(x => x.canUseProvider()).returns(() => testContext.provider.canUseProvider()); mockProvider.setup(x => x.getLocations()).returns(() => testContext.provider.getLocations()); + mockProvider.setup(x => x.getCurrentLocation()).returns(() => testContext.provider.getCurrentLocation()); mockProvider.setup(x => x.installPackages(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((packages, useMinVersion) => testContext.provider.installPackages(packages, useMinVersion)); mockProvider.setup(x => x.uninstallPackages(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((packages) => testContext.provider.uninstallPackages(packages)); mockProvider.setup(x => x.listPackages(TypeMoq.It.isAny())).returns(() => testContext.provider.listPackages()); diff --git a/extensions/notebook/src/types.d.ts b/extensions/notebook/src/types.d.ts index bcab72eca4..01c6ce45a8 100644 --- a/extensions/notebook/src/types.d.ts +++ b/extensions/notebook/src/types.d.ts @@ -138,6 +138,11 @@ export interface IPackageManageProvider { */ getLocations(): Promise; + /** + * Get the current location + */ + getCurrentLocation(): Promise; + /** * Returns Package Overview * @param packageName package name