Added multiple location option to package management dialog (#9790)

* Added multiple location option to package management dialog
This commit is contained in:
Leila Lali
2020-04-01 13:33:45 -07:00
committed by GitHub
parent 0bfbdc62ed
commit dd56908a06
25 changed files with 728 additions and 231 deletions

View File

@@ -147,7 +147,7 @@ export class AddNewPackageTab {
let pipPackage: PipPackageOverview;
pipPackage = await this.dialog.model.getPackageOverview(packageName);
if (!pipPackage.versions || pipPackage.versions.length === 0) {
if (!pipPackage?.versions || pipPackage.versions.length === 0) {
this.dialog.showErrorMessage(
localize('managePackages.noVersionsFound',
"Could not find any valid versions for the specified package"));

View File

@@ -20,11 +20,13 @@ export class InstalledPackagesTab {
private installedPkgTab: azdata.window.DialogTab;
private packageTypeDropdown: azdata.DropDownComponent;
private locationComponent: azdata.TextComponent;
private locationComponent: azdata.Component;
private installedPackageCount: azdata.TextComponent;
private installedPackagesTable: azdata.TableComponent;
private installedPackagesLoader: azdata.LoadingComponent;
private uninstallPackageButton: azdata.ButtonComponent;
private view: azdata.ModelView | undefined;
private formBuilder: azdata.FormBuilder;
constructor(private dialog: ManagePackagesDialog, private jupyterInstallation: JupyterServerInstallation) {
this.prompter = new CodeAdapter();
@@ -32,14 +34,7 @@ export class InstalledPackagesTab {
this.installedPkgTab = azdata.window.createTab(localize('managePackages.installedTabTitle', "Installed"));
this.installedPkgTab.registerContent(async view => {
// TODO: only supporting single location for now. We should add a drop down for multi locations mode
//
let locationTitle = await this.dialog.model.getLocationTitle();
this.locationComponent = view.modelBuilder.text().withProperties({
value: locationTitle
}).component();
this.view = view;
let dropdownValues = this.dialog.model.getPackageTypes().map(x => {
return {
name: x.providerId,
@@ -52,11 +47,17 @@ export class InstalledPackagesTab {
value: defaultPackageType
}).component();
this.dialog.changeProvider(defaultPackageType.providerId);
this.packageTypeDropdown.onValueChanged(() => {
this.dialog.resetPages((<azdata.CategoryValue>this.packageTypeDropdown.value).name)
.catch(err => {
this.dialog.showErrorMessage(utils.getErrorMessage(err));
});
this.packageTypeDropdown.onValueChanged(async () => {
this.dialog.changeProvider((<azdata.CategoryValue>this.packageTypeDropdown.value).name);
try {
await this.resetLocations();
await this.dialog.resetPages();
}
catch (err) {
this.dialog.showErrorMessage(utils.getErrorMessage(err));
}
});
this.installedPackageCount = view.modelBuilder.text().withProperties({
@@ -81,11 +82,8 @@ export class InstalledPackagesTab {
}).component();
this.uninstallPackageButton.onDidClick(() => this.doUninstallPackage());
let formModel = view.modelBuilder.formContainer()
this.formBuilder = view.modelBuilder.formContainer()
.withFormItems([{
component: this.locationComponent,
title: localize('managePackages.location', "Location")
}, {
component: this.packageTypeDropdown,
title: localize('managePackages.packageType', "Package Type")
}, {
@@ -97,10 +95,11 @@ export class InstalledPackagesTab {
}, {
component: this.uninstallPackageButton,
title: ''
}]).component();
}]);
await this.resetLocations();
this.installedPackagesLoader = view.modelBuilder.loadingComponent()
.withItem(formModel)
.withItem(this.formBuilder.component())
.withProperties({
loading: true
}).component();
@@ -112,6 +111,68 @@ export class InstalledPackagesTab {
});
}
private async resetLocations(): Promise<void> {
if (this.view) {
if (this.locationComponent) {
this.formBuilder.removeFormItem({
component: this.locationComponent,
title: localize('managePackages.location', "Location")
});
}
this.locationComponent = await InstalledPackagesTab.getLocationComponent(this.view, this.dialog);
this.formBuilder.insertFormItem({
component: this.locationComponent,
title: localize('managePackages.location', "Location")
}, 1);
}
}
/**
* Creates a component for package locations
* @param view Model view
* @param dialog Manage package dialog
*/
public static async getLocationComponent(view: azdata.ModelView, dialog: ManagePackagesDialog): Promise<azdata.Component> {
const locations = await dialog.model.getLocations();
let component: azdata.Component;
if (locations && locations.length === 1) {
component = view.modelBuilder.text().withProperties({
value: locations[0].displayName
}).component();
} else if (locations) {
let dropdownValues = locations.map(x => {
return {
name: x.name,
displayName: x.displayName
};
});
let locationDropDown = view.modelBuilder.dropDown().withProperties({
values: dropdownValues,
value: dropdownValues[0]
}).component();
locationDropDown.onValueChanged(async () => {
dialog.changeLocation((<azdata.CategoryValue>locationDropDown.value).name);
try {
await dialog.resetPages();
}
catch (err) {
dialog.showErrorMessage(utils.getErrorMessage(err));
}
});
component = locationDropDown;
} else {
component = view.modelBuilder.text().withProperties({
}).component();
}
if (locations && locations.length > 0) {
dialog.changeLocation(locations[0].name);
}
return component;
}
public get tab(): azdata.window.DialogTab {
return this.installedPkgTab;
}

View File

@@ -67,14 +67,17 @@ export class ManagePackagesDialog {
}
/**
* Resets the tabs for given provider Id
* @param providerId Package Management Provider Id
* Changes the current location
* @param location location name
*/
public async resetPages(providerId: string): Promise<void> {
public changeLocation(location: string): void {
this.model.changeLocation(location);
}
// Change the provider in the model
//
this.changeProvider(providerId);
/**
* Resets the tabs for given provider Id
*/
public async resetPages(): Promise<void> {
// Load packages for given provider
//

View File

@@ -4,10 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { JupyterServerInstallation } from '../../jupyter/jupyterServerInstallation';
import { IPackageManageProvider, IPackageDetails, IPackageOverview } from '../../types';
import { IPackageManageProvider, IPackageDetails, IPackageOverview, IPackageLocation } from '../../types';
export interface ManagePackageDialogOptions {
multiLocations: boolean;
defaultLocation?: string;
defaultProviderId?: string;
}
@@ -23,11 +22,12 @@ export interface ProviderPackageType {
export class ManagePackagesDialogModel {
private _currentProvider: string;
private _currentLocation: string;
/**
* A set for locations
*/
private _locations: Set<string> = new Set<string>();
private _locationTypes: Set<string> = new Set<string>();
/**
* Map of locations to providers
@@ -77,15 +77,10 @@ export class ManagePackagesDialogModel {
if (this._options.defaultProviderId && !this._packageManageProviders.has(this._options.defaultProviderId)) {
throw new Error(`Invalid default provider id '${this._options.defaultProviderId}`);
}
if (!this._options.multiLocations && !this.defaultLocation) {
throw new Error('Default location not specified for single location mode');
}
}
private get defaultOptions(): ManagePackageDialogOptions {
return {
multiLocations: true,
defaultLocation: undefined,
defaultProviderId: undefined
};
@@ -120,13 +115,6 @@ export class ManagePackagesDialogModel {
return undefined;
}
/**
* Returns true if multi locations mode is enabled
*/
public get multiLocationMode(): boolean {
return this.options.multiLocations;
}
/**
* Returns options
*/
@@ -135,17 +123,17 @@ export class ManagePackagesDialogModel {
}
/**
* returns the array of target locations
* returns the array of target location types
*/
public get targetLocations(): string[] {
return Array.from(this._locations.keys());
public get targetLocationTypes(): string[] {
return Array.from(this._locationTypes.keys());
}
/**
* Returns the default location
*/
public get defaultLocation(): string {
return this.options.defaultLocation || this.targetLocations[0];
return this.options.defaultLocation || this.targetLocationTypes[0];
}
/**
@@ -164,8 +152,8 @@ export class ManagePackagesDialogModel {
for (let index = 0; index < keyArray.length; index++) {
const element = this.packageManageProviders.get(keyArray[index]);
if (await element.canUseProvider()) {
if (!this._locations.has(element.packageTarget.location)) {
this._locations.add(element.packageTarget.location);
if (!this._locationTypes.has(element.packageTarget.location)) {
this._locationTypes.add(element.packageTarget.location);
}
if (!this._packageTypes.has(element.packageTarget.location)) {
this._packageTypes.set(element.packageTarget.location, []);
@@ -205,7 +193,7 @@ export class ManagePackagesDialogModel {
public async listPackages(): Promise<IPackageDetails[]> {
let provider = this.currentPackageManageProvider;
if (provider) {
return await provider.listPackages();
return await provider.listPackages(this._currentLocation);
} else {
throw new Error('Current Provider is not set');
}
@@ -222,6 +210,13 @@ export class ManagePackagesDialogModel {
}
}
/**
* Changes the current location
*/
public changeLocation(location: string): void {
this._currentLocation = location;
}
/**
* Installs given packages using current provider
* @param packages Packages to install
@@ -229,7 +224,7 @@ export class ManagePackagesDialogModel {
public async installPackages(packages: IPackageDetails[]): Promise<void> {
let provider = this.currentPackageManageProvider;
if (provider) {
await provider.installPackages(packages, false);
await provider.installPackages(packages, false, this._currentLocation);
} else {
throw new Error('Current Provider is not set');
}
@@ -238,10 +233,10 @@ export class ManagePackagesDialogModel {
/**
* Returns the location title for current provider
*/
public async getLocationTitle(): Promise<string | undefined> {
public async getLocations(): Promise<IPackageLocation[] | undefined> {
let provider = this.currentPackageManageProvider;
if (provider) {
return await provider.getLocationTitle();
return await provider.getLocations();
}
return Promise.resolve(undefined);
}
@@ -253,7 +248,7 @@ export class ManagePackagesDialogModel {
public async uninstallPackages(packages: IPackageDetails[]): Promise<void> {
let provider = this.currentPackageManageProvider;
if (provider) {
await provider.uninstallPackages(packages);
await provider.uninstallPackages(packages, this._currentLocation);
} else {
throw new Error('Current Provider is not set');
}