Files
azuredatastudio/extensions/notebook/src/dialog/remoteBookDialog.ts
Charles Gagnon 76e01fee60 Fix rest of notebook unhandled promises (#16933)
* Fix rest of notebook unhandled promises

* add rule

* fix some tests
2021-08-30 14:14:48 -07:00

297 lines
9.2 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as loc from '../common/localizedConstants';
import { RemoteBookController, IAsset } from '../book/remoteBookController';
import * as utils from '../common/utils';
import * as vscode from 'vscode';
const defaultRepos = ['repos/microsoft/tigertoolbox', 'repos/azure-samples/synapse'];
const urlGithubRE = /^(?:https:\/\/(?:github\.com|api\.github\.com\/repos)|(?:\/)?(?:\/)?repos)([\w-.?!=&%*+:@\/]*)/g;
function apiGitHub(url: string): string {
return `https://api.github.com/${url}/releases`;
}
function getRemoteLocationCategory(name: string): azdata.CategoryValue {
if (name === loc.onGitHub) {
return { name: name, displayName: loc.onGitHub };
}
return { name: name, displayName: loc.onSharedFile };
}
export class RemoteBookDialog {
private dialog: azdata.window.Dialog;
public view: azdata.ModelView;
private formModel: azdata.FormContainer;
private githubRepoDropdown: azdata.DropDownComponent;
private remoteLocationDropdown: azdata.DropDownComponent;
public releaseDropdown: azdata.DropDownComponent;
private searchButton: azdata.ButtonComponent;
public bookDropdown: azdata.DropDownComponent;
public versionDropdown: azdata.DropDownComponent;
public languageDropdown: azdata.DropDownComponent;
private _remoteTypes: azdata.CategoryValue[];
constructor(public controller: RemoteBookController) {
}
public async createDialog(): Promise<void> {
this.dialog = azdata.window.createModelViewDialog(loc.addRemoteBook);
this.dialog.registerContent(async view => {
this.view = view;
this.remoteLocationDropdown = this.view.modelBuilder.dropDown().withProps({
values: this.remoteLocationCategories,
value: '',
editable: false,
}).component();
this.remoteLocationDropdown.onValueChanged(e => this.onRemoteLocationChanged());
this.githubRepoDropdown = this.view.modelBuilder.dropDown().withProps({
values: defaultRepos,
value: '',
editable: true,
fireOnTextChange: true,
}).component();
this.searchButton = this.view.modelBuilder.button().withProps({
label: loc.search,
title: loc.search,
width: '200px',
secondary: true
}).component();
this.searchButton.onDidClick(async () => await this.validate());
this.releaseDropdown = this.view.modelBuilder.dropDown()
.withProps({
values: [],
value: '',
enabled: false
}).component();
this.releaseDropdown.onValueChanged(async () => await this.getAssets());
this.bookDropdown = this.view.modelBuilder.dropDown().withProps({
values: [],
value: '',
editable: false,
}).component();
this.bookDropdown.onValueChanged(async () => await this.fillVersionDropdown());
this.versionDropdown = this.view.modelBuilder.dropDown().withProps({
values: [],
value: '',
editable: false,
}).component();
this.versionDropdown.onValueChanged(async () => await this.fillLanguageDropdown());
this.languageDropdown = this.view.modelBuilder.dropDown().withProps({
values: [],
value: '',
editable: false,
}).component();
this.languageDropdown.onValueChanged(async () => this.checkValues());
await this.setFieldsToEmpty();
this.formModel = this.view.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: this.remoteLocationDropdown,
title: loc.location,
required: true
},
{
component: this.githubRepoDropdown,
title: loc.repoUrl,
required: true
},
{
component: this.searchButton,
title: ''
},
{
component: this.releaseDropdown,
title: loc.releases,
},
{
component: this.bookDropdown,
title: loc.book,
required: true
},
{
component: this.versionDropdown,
title: loc.version,
required: true
},
{
component: this.languageDropdown,
title: loc.language,
required: true
},
],
title: ''
}]).withLayout({ width: '100%' }).component();
await this.view.initializeModel(this.formModel);
});
this.dialog.okButton.enabled = false;
this.dialog.okButton.label = loc.add;
this.dialog.cancelButton.label = loc.close;
this.dialog.registerCloseValidator(async () => await this.download());
azdata.window.openDialog(this.dialog);
}
private async setFieldsToEmpty(): Promise<void> {
await this.bookDropdown.updateProperties({
values: [loc.invalidTextPlaceholder],
value: loc.invalidTextPlaceholder
});
await this.versionDropdown.updateProperties({
values: [loc.invalidTextPlaceholder],
value: loc.invalidTextPlaceholder
});
await this.languageDropdown.updateProperties({
values: [loc.invalidTextPlaceholder],
value: loc.invalidTextPlaceholder
});
this.dialog.okButton.enabled = false;
}
private get remoteLocationValue(): string {
return (<azdata.CategoryValue>this.remoteLocationDropdown.value).name;
}
public onRemoteLocationChanged(): void {
if (this.controller.getReleases() !== undefined && this.remoteLocationValue === loc.onGitHub) {
this.releaseDropdown.enabled = true;
} else {
this.releaseDropdown.enabled = false;
}
}
public async validate(): Promise<void> {
try {
let url = utils.getDropdownValue(this.githubRepoDropdown);
url = url.trim().toLowerCase();
if (this.remoteLocationValue === loc.onGitHub && url.length > 0) {
//get the first group to extract /owner/repo/releases format
let groupsRe = url.match(urlGithubRE);
if (groupsRe?.length > 0) {
url = apiGitHub(groupsRe[0]);
let releases = await this.controller.getReleases(vscode.Uri.parse(url));
if (releases) {
this.releaseDropdown.enabled = true;
await this.fillReleasesDropdown();
await this.setFieldsToEmpty();
}
} else {
throw new Error(loc.urlGithubError);
}
}
}
catch (error) {
await this.fillReleasesDropdown();
await this.setFieldsToEmpty();
this.showErrorMessage(error.message);
}
}
public async getAssets(): Promise<void> {
try {
if (this.remoteLocationValue === loc.onGitHub) {
let releases = await this.controller.getReleases();
let selected_release = releases.filter(release =>
release.name === this.releaseDropdown.value);
let assets = await this.controller.getAssets(selected_release[0]);
if (assets?.length > 0) {
this.bookDropdown.values = ['-'].concat([...new Set(assets.map(asset => asset.book))]);
}
this.checkValues();
}
}
catch (error) {
await this.setFieldsToEmpty();
this.showErrorMessage(error.message);
}
}
public async download(): Promise<boolean> {
try {
if (this.remoteLocationValue === loc.onGitHub) {
let selected_asset = await this.getSelectedAsset();
if (!selected_asset) {
throw new Error(loc.msgUndefinedAssetError);
}
await this.controller.setRemoteBook(selected_asset.url, this.remoteLocationValue, selected_asset);
} else {
let url = utils.getDropdownValue(this.githubRepoDropdown);
let newUrl = vscode.Uri.parse(url);
await this.controller.setRemoteBook(newUrl, this.remoteLocationValue);
}
return true;
}
catch (error) {
this.showErrorMessage(error.message);
return false;
}
}
public async fillReleasesDropdown(): Promise<void> {
this.releaseDropdown.values = ['-'].concat((await this.controller.getReleases()).map(release => release.name));
}
public async fillVersionDropdown(): Promise<void> {
const assets = await this.controller.getAssets();
let filtered_assets = assets.filter(asset => asset.book === this.bookDropdown.value);
this.versionDropdown.values = ['-'].concat(filtered_assets.map(asset => asset.version));
this.checkValues();
}
public async fillLanguageDropdown(): Promise<void> {
const assets = await this.controller.getAssets();
let filtered_assets = assets.filter(asset => asset.book === this.bookDropdown.value &&
asset.version === this.versionDropdown.value);
this.languageDropdown.values = ['-'].concat(filtered_assets.map(asset => asset.language));
this.checkValues();
}
public async getSelectedAsset(): Promise<IAsset> {
let lang = this.languageDropdown.value;
let book = this.bookDropdown.value;
let version = this.versionDropdown.value;
return (await this.controller.getAssets()).filter(asset => asset.book === book && asset.version === version && asset.language === lang)[0];
}
public checkValues(): void {
if (this.languageDropdown.value !== loc.invalidTextPlaceholder && this.versionDropdown.value !== loc.invalidTextPlaceholder &&
this.bookDropdown.value !== loc.invalidTextPlaceholder) {
this.dialog.okButton.enabled = true;
} else {
this.dialog.okButton.enabled = false;
}
}
public get remoteLocationCategories(): azdata.CategoryValue[] {
if (!this._remoteTypes) {
this._remoteTypes = [getRemoteLocationCategory(loc.onGitHub)];
}
return this._remoteTypes;
}
public showErrorMessage(message: string): void {
this.dialog.message = {
text: message,
level: azdata.window.MessageLevel.Error
};
}
}