mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 03:58:33 -05:00
ML - Target import table selectable by user (#10071)
ML - Target import table selectable by user
This commit is contained in:
@@ -10,21 +10,24 @@ import { ModelViewBase } from '../modelViewBase';
|
||||
import { CurrentModelsTable } from './currentModelsTable';
|
||||
import { ApiWrapper } from '../../../common/apiWrapper';
|
||||
import { IPageView } from '../../interfaces';
|
||||
import { TableSelectionComponent } from '../tableSelectionComponent';
|
||||
import { RegisteredModel } from '../../../modelManagement/interfaces';
|
||||
|
||||
/**
|
||||
* View to render current registered models
|
||||
*/
|
||||
export class CurrentModelsPage extends ModelViewBase implements IPageView {
|
||||
export class CurrentModelsComponent extends ModelViewBase implements IPageView {
|
||||
private _tableComponent: azdata.Component | undefined;
|
||||
private _dataTable: CurrentModelsTable | undefined;
|
||||
private _loader: azdata.LoadingComponent | undefined;
|
||||
private _tableSelectionComponent: TableSelectionComponent | undefined;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param apiWrapper Creates new view
|
||||
* @param parent page parent
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase) {
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _multiSelect: boolean = false) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
@@ -33,11 +36,17 @@ export class CurrentModelsPage extends ModelViewBase implements IPageView {
|
||||
* @param modelBuilder register the components
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this._dataTable = new CurrentModelsTable(this._apiWrapper, this, false);
|
||||
this._tableSelectionComponent = new TableSelectionComponent(this._apiWrapper, this, false);
|
||||
this._tableSelectionComponent.registerComponent(modelBuilder);
|
||||
this._tableSelectionComponent.onSelectedChanged(async () => {
|
||||
await this.onTableSelected();
|
||||
});
|
||||
this._dataTable = new CurrentModelsTable(this._apiWrapper, this, this._multiSelect);
|
||||
this._dataTable.registerComponent(modelBuilder);
|
||||
this._tableComponent = this._dataTable.component;
|
||||
|
||||
let formModelBuilder = modelBuilder.formContainer();
|
||||
this._tableSelectionComponent.addComponents(formModelBuilder);
|
||||
|
||||
if (this._tableComponent) {
|
||||
formModelBuilder.addFormItem({
|
||||
@@ -54,6 +63,20 @@ export class CurrentModelsPage extends ModelViewBase implements IPageView {
|
||||
return this._loader;
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._tableSelectionComponent && this._dataTable) {
|
||||
this._tableSelectionComponent.addComponents(formBuilder);
|
||||
this._dataTable.addComponents(formBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._tableSelectionComponent && this._dataTable) {
|
||||
this._tableSelectionComponent.removeComponents(formBuilder);
|
||||
this._dataTable.removeComponents(formBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component
|
||||
*/
|
||||
@@ -68,6 +91,9 @@ export class CurrentModelsPage extends ModelViewBase implements IPageView {
|
||||
await this.onLoading();
|
||||
|
||||
try {
|
||||
if (this._tableSelectionComponent) {
|
||||
this._tableSelectionComponent.refresh();
|
||||
}
|
||||
await this._dataTable?.refresh();
|
||||
} catch (err) {
|
||||
this.showErrorMessage(constants.getErrorMessage(err));
|
||||
@@ -76,6 +102,31 @@ export class CurrentModelsPage extends ModelViewBase implements IPageView {
|
||||
}
|
||||
}
|
||||
|
||||
public get data(): RegisteredModel[] | undefined {
|
||||
return this._dataTable?.data;
|
||||
}
|
||||
|
||||
private async onTableSelected(): Promise<void> {
|
||||
if (this._tableSelectionComponent?.data) {
|
||||
this.importTable = this._tableSelectionComponent?.data;
|
||||
await this.storeImportConfigTable();
|
||||
await this._dataTable?.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public get modelTable(): CurrentModelsTable | undefined {
|
||||
return this._dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* disposes the view
|
||||
*/
|
||||
public async disposeComponent(): Promise<void> {
|
||||
if (this._dataTable) {
|
||||
await this._dataTable.disposeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the title of the page
|
||||
*/
|
||||
@@ -134,7 +134,11 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
if (this._table) {
|
||||
let models: RegisteredModel[] | undefined;
|
||||
|
||||
models = await this.listModels();
|
||||
if (this.importTable) {
|
||||
models = await this.listModels(this.importTable);
|
||||
} else {
|
||||
this.showErrorMessage('No import table');
|
||||
}
|
||||
let tableData: any[][] = [];
|
||||
|
||||
if (models) {
|
||||
@@ -14,15 +14,17 @@ import { WizardView } from '../../wizardView';
|
||||
import { ModelSourcePage } from '../modelSourcePage';
|
||||
import { ModelDetailsPage } from '../modelDetailsPage';
|
||||
import { ModelBrowsePage } from '../modelBrowsePage';
|
||||
import { ModelImportLocationPage } from './modelmportLocationPage';
|
||||
|
||||
/**
|
||||
* Wizard to register a model
|
||||
*/
|
||||
export class RegisterModelWizard extends ModelViewBase {
|
||||
export class ImportModelWizard extends ModelViewBase {
|
||||
|
||||
public modelSourcePage: ModelSourcePage | undefined;
|
||||
public modelBrowsePage: ModelBrowsePage | undefined;
|
||||
public modelDetailsPage: ModelDetailsPage | undefined;
|
||||
public modelImportTargetPage: ModelImportLocationPage | undefined;
|
||||
public wizardView: WizardView | undefined;
|
||||
private _parentView: ModelViewBase | undefined;
|
||||
|
||||
@@ -41,9 +43,10 @@ export class RegisterModelWizard extends ModelViewBase {
|
||||
this.modelSourcePage = new ModelSourcePage(this._apiWrapper, this);
|
||||
this.modelDetailsPage = new ModelDetailsPage(this._apiWrapper, this);
|
||||
this.modelBrowsePage = new ModelBrowsePage(this._apiWrapper, this);
|
||||
this.modelImportTargetPage = new ModelImportLocationPage(this._apiWrapper, this);
|
||||
this.wizardView = new WizardView(this._apiWrapper);
|
||||
|
||||
let wizard = this.wizardView.createWizard(constants.registerModelTitle, [this.modelSourcePage, this.modelBrowsePage, this.modelDetailsPage]);
|
||||
let wizard = this.wizardView.createWizard(constants.registerModelTitle, [this.modelImportTargetPage, this.modelSourcePage, this.modelBrowsePage, this.modelDetailsPage]);
|
||||
|
||||
this.mainViewPanel = wizard;
|
||||
wizard.doneButton.label = constants.azureRegisterModel;
|
||||
@@ -61,7 +64,8 @@ export class RegisterModelWizard extends ModelViewBase {
|
||||
wizard.cancelButton.enabled = true;
|
||||
wizard.backButton.enabled = true;
|
||||
if (this._parentView) {
|
||||
await this._parentView?.refresh();
|
||||
this._parentView.importTable = this.importTable;
|
||||
await this._parentView.refresh();
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -87,10 +91,11 @@ export class RegisterModelWizard extends ModelViewBase {
|
||||
private async registerModel(): Promise<boolean> {
|
||||
try {
|
||||
if (this.modelResources && this.localModelsComponent && this.modelResources.data === ModelSourceType.Local) {
|
||||
await this.registerLocalModel(this.modelsViewData);
|
||||
await this.importLocalModel(this.modelsViewData);
|
||||
} else {
|
||||
await this.registerAzureModel(this.modelsViewData);
|
||||
await this.importAzureModel(this.modelsViewData);
|
||||
}
|
||||
await this.storeImportConfigTable();
|
||||
this.showInfoMessage(constants.modelRegisteredSuccessfully);
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CurrentModelsPage } from './currentModelsPage';
|
||||
import { CurrentModelsComponent } from './currentModelsComponent';
|
||||
|
||||
import { ModelViewBase, RegisterModelEventName } from '../modelViewBase';
|
||||
import * as constants from '../../../common/constants';
|
||||
@@ -13,7 +13,7 @@ import { DialogView } from '../../dialogView';
|
||||
/**
|
||||
* Dialog to render registered model views
|
||||
*/
|
||||
export class RegisteredModelsDialog extends ModelViewBase {
|
||||
export class ManageModelsDialog extends ModelViewBase {
|
||||
|
||||
constructor(
|
||||
apiWrapper: ApiWrapper,
|
||||
@@ -22,18 +22,18 @@ export class RegisteredModelsDialog extends ModelViewBase {
|
||||
this.dialogView = new DialogView(this._apiWrapper);
|
||||
}
|
||||
public dialogView: DialogView;
|
||||
public currentLanguagesTab: CurrentModelsPage | undefined;
|
||||
public currentLanguagesTab: CurrentModelsComponent | undefined;
|
||||
|
||||
/**
|
||||
* Opens a dialog to manage packages used by notebooks.
|
||||
*/
|
||||
public open(): void {
|
||||
|
||||
this.currentLanguagesTab = new CurrentModelsPage(this._apiWrapper, this);
|
||||
this.currentLanguagesTab = new CurrentModelsComponent(this._apiWrapper, this);
|
||||
|
||||
let registerModelButton = this._apiWrapper.createButton(constants.importModelTitle);
|
||||
registerModelButton.onClick(async () => {
|
||||
await this.sendDataRequest(RegisterModelEventName);
|
||||
await this.sendDataRequest(RegisterModelEventName, this.currentLanguagesTab?.modelTable?.importTable);
|
||||
});
|
||||
|
||||
let dialog = this.dialogView.createDialog(constants.registerModelTitle, [this.currentLanguagesTab]);
|
||||
@@ -0,0 +1,98 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { ModelViewBase } from '../modelViewBase';
|
||||
import { ApiWrapper } from '../../../common/apiWrapper';
|
||||
import * as constants from '../../../common/constants';
|
||||
import { IPageView, IDataComponent } from '../../interfaces';
|
||||
import { TableSelectionComponent } from '../tableSelectionComponent';
|
||||
import { DatabaseTable } from '../../../prediction/interfaces';
|
||||
|
||||
/**
|
||||
* View to pick model source
|
||||
*/
|
||||
export class ModelImportLocationPage extends ModelViewBase implements IPageView, IDataComponent<DatabaseTable> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _formBuilder: azdata.FormBuilder | undefined;
|
||||
public tableSelectionComponent: TableSelectionComponent | undefined;
|
||||
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param modelBuilder Register components
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
|
||||
this._formBuilder = modelBuilder.formContainer();
|
||||
this.tableSelectionComponent = new TableSelectionComponent(this._apiWrapper, this, true);
|
||||
this.tableSelectionComponent.onSelectedChanged(async () => {
|
||||
await this.onTableSelected();
|
||||
});
|
||||
this.tableSelectionComponent.registerComponent(modelBuilder);
|
||||
this.tableSelectionComponent.addComponents(this._formBuilder);
|
||||
this._form = this._formBuilder.component();
|
||||
return this._form;
|
||||
}
|
||||
|
||||
private async onTableSelected(): Promise<void> {
|
||||
if (this.tableSelectionComponent?.data) {
|
||||
this.importTable = this.tableSelectionComponent?.data;
|
||||
//this.sendRequest(StoreImportTableEventName, this.importTable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
public get data(): DatabaseTable | undefined {
|
||||
return this.tableSelectionComponent?.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component
|
||||
*/
|
||||
public get component(): azdata.Component | undefined {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the view
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
if (this.tableSelectionComponent) {
|
||||
await this.tableSelectionComponent.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns page title
|
||||
*/
|
||||
public get title(): string {
|
||||
return constants.modelImportTargetPageTitle;
|
||||
}
|
||||
|
||||
public async disposePage(): Promise<void> {
|
||||
}
|
||||
|
||||
public async validate(): Promise<boolean> {
|
||||
let validated = false;
|
||||
|
||||
if (this.data?.databaseName && this.data?.tableName) {
|
||||
validated = true;
|
||||
validated = await this.verifyImportConfigTable(this.data);
|
||||
if (!validated) {
|
||||
this.showErrorMessage(constants.invalidImportTableSchemaError(this.data?.databaseName, this.data?.tableName));
|
||||
}
|
||||
} else {
|
||||
this.showErrorMessage(constants.invalidImportTableError(this.data?.databaseName, this.data?.tableName));
|
||||
}
|
||||
return validated;
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import * as constants from '../../common/constants';
|
||||
import { IPageView, IDataComponent } from '../interfaces';
|
||||
import { LocalModelsComponent } from './localModelsComponent';
|
||||
import { AzureModelsComponent } from './azureModelsComponent';
|
||||
import { CurrentModelsTable } from './registerModels/currentModelsTable';
|
||||
import * as utils from '../../common/utils';
|
||||
import { CurrentModelsComponent } from './manageModels/currentModelsComponent';
|
||||
|
||||
/**
|
||||
* View to pick model source
|
||||
@@ -19,10 +19,11 @@ import * as utils from '../../common/utils';
|
||||
export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataComponent<ModelViewData[]> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _title: string = constants.modelSourcePageTitle;
|
||||
private _formBuilder: azdata.FormBuilder | undefined;
|
||||
public localModelsComponent: LocalModelsComponent | undefined;
|
||||
public azureModelsComponent: AzureModelsComponent | undefined;
|
||||
public registeredModelsComponent: CurrentModelsTable | undefined;
|
||||
public registeredModelsComponent: CurrentModelsComponent | undefined;
|
||||
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _multiSelect: boolean = true) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
@@ -39,7 +40,7 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
this.localModelsComponent.registerComponent(modelBuilder);
|
||||
this.azureModelsComponent = new AzureModelsComponent(this._apiWrapper, this, this._multiSelect);
|
||||
this.azureModelsComponent.registerComponent(modelBuilder);
|
||||
this.registeredModelsComponent = new CurrentModelsTable(this._apiWrapper, this, this._multiSelect);
|
||||
this.registeredModelsComponent = new CurrentModelsComponent(this._apiWrapper, this, this._multiSelect);
|
||||
this.registeredModelsComponent.registerComponent(modelBuilder);
|
||||
this.refresh();
|
||||
this._form = this._formBuilder.component();
|
||||
@@ -88,16 +89,29 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
this.registeredModelsComponent.addComponents(this._formBuilder);
|
||||
await this.registeredModelsComponent.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
this.loadTitle();
|
||||
}
|
||||
|
||||
private loadTitle(): void {
|
||||
if (this.modelSourceType === ModelSourceType.Local) {
|
||||
this._title = 'Upload model file';
|
||||
} else if (this.modelSourceType === ModelSourceType.Azure) {
|
||||
this._title = 'Import from Azure Machine Learning';
|
||||
|
||||
} else if (this.modelSourceType === ModelSourceType.RegisteredModels) {
|
||||
this._title = 'Select imported model';
|
||||
} else {
|
||||
this._title = constants.modelSourcePageTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns page title
|
||||
*/
|
||||
public get title(): string {
|
||||
return constants.modelSourcePageTitle;
|
||||
return this._title;
|
||||
}
|
||||
|
||||
public validate(): Promise<boolean> {
|
||||
@@ -117,6 +131,10 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
return Promise.resolve(validated);
|
||||
}
|
||||
|
||||
public onEnter(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public async onLeave(): Promise<void> {
|
||||
this.modelsViewData = [];
|
||||
if (this.modelSourceType === ModelSourceType.Local && this.localModelsComponent) {
|
||||
@@ -128,7 +146,8 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
modelDetails: {
|
||||
title: fileName,
|
||||
fileName: fileName
|
||||
}
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -147,7 +166,8 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
modelDetails: {
|
||||
title: x.model?.name || '',
|
||||
fileName: x.model?.name
|
||||
}
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -159,7 +179,8 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
modelData: x,
|
||||
modelDetails: {
|
||||
title: ''
|
||||
}
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,15 +12,15 @@ import { Workspace } from '@azure/arm-machinelearningservices/esm/models';
|
||||
import { RegisteredModel, WorkspaceModel, ModelParameters } from '../../modelManagement/interfaces';
|
||||
import { PredictParameters, DatabaseTable, TableColumn } from '../../prediction/interfaces';
|
||||
import { DeployedModelService } from '../../modelManagement/deployedModelService';
|
||||
import { RegisteredModelsDialog } from './registerModels/registeredModelsDialog';
|
||||
import { ManageModelsDialog } from './manageModels/manageModelsDialog';
|
||||
import {
|
||||
AzureResourceEventArgs, ListAzureModelsEventName, ListSubscriptionsEventName, ListModelsEventName, ListWorkspacesEventName,
|
||||
ListGroupsEventName, ListAccountsEventName, RegisterLocalModelEventName, RegisterAzureModelEventName,
|
||||
ModelViewBase, SourceModelSelectedEventName, RegisterModelEventName, DownloadAzureModelEventName,
|
||||
ListDatabaseNamesEventName, ListTableNamesEventName, ListColumnNamesEventName, PredictModelEventName, PredictModelEventArgs, DownloadRegisteredModelEventName, LoadModelParametersEventName, ModelSourceType, ModelViewData
|
||||
ListDatabaseNamesEventName, ListTableNamesEventName, ListColumnNamesEventName, PredictModelEventName, PredictModelEventArgs, DownloadRegisteredModelEventName, LoadModelParametersEventName, ModelSourceType, ModelViewData, StoreImportTableEventName, VerifyImportTableEventName
|
||||
} from './modelViewBase';
|
||||
import { ControllerBase } from '../controllerBase';
|
||||
import { RegisterModelWizard } from './registerModels/registerModelWizard';
|
||||
import { ImportModelWizard } from './manageModels/importModelWizard';
|
||||
import * as fs from 'fs';
|
||||
import * as constants from '../../common/constants';
|
||||
import { PredictWizard } from './prediction/predictWizard';
|
||||
@@ -51,11 +51,16 @@ export class ModelManagementController extends ControllerBase {
|
||||
* @param apiWrapper apiWrapper
|
||||
* @param root root folder path
|
||||
*/
|
||||
public async registerModel(parent?: ModelViewBase, controller?: ModelManagementController, apiWrapper?: ApiWrapper, root?: string): Promise<ModelViewBase> {
|
||||
public async registerModel(importTable: DatabaseTable | undefined, parent?: ModelViewBase, controller?: ModelManagementController, apiWrapper?: ApiWrapper, root?: string): Promise<ModelViewBase> {
|
||||
controller = controller || this;
|
||||
apiWrapper = apiWrapper || this._apiWrapper;
|
||||
root = root || this._root;
|
||||
let view = new RegisterModelWizard(apiWrapper, root, parent);
|
||||
let view = new ImportModelWizard(apiWrapper, root, parent);
|
||||
if (importTable) {
|
||||
view.importTable = importTable;
|
||||
} else {
|
||||
view.importTable = await controller._registeredModelService.getRecentImportTable();
|
||||
}
|
||||
|
||||
controller.registerEvents(view);
|
||||
|
||||
@@ -72,6 +77,7 @@ export class ModelManagementController extends ControllerBase {
|
||||
public async predictModel(): Promise<ModelViewBase> {
|
||||
|
||||
let view = new PredictWizard(this._apiWrapper, this._root);
|
||||
view.importTable = await this._registeredModelService.getRecentImportTable();
|
||||
|
||||
this.registerEvents(view);
|
||||
view.on(LoadModelParametersEventName, async () => {
|
||||
@@ -117,17 +123,18 @@ export class ModelManagementController extends ControllerBase {
|
||||
await this.executeAction(view, ListAzureModelsEventName, this.getAzureModels, this._amlService
|
||||
, azureArgs.account, azureArgs.subscription, azureArgs.group, azureArgs.workspace);
|
||||
});
|
||||
|
||||
view.on(ListModelsEventName, async () => {
|
||||
await this.executeAction(view, ListModelsEventName, this.getRegisteredModels, this._registeredModelService);
|
||||
view.on(ListModelsEventName, async (args) => {
|
||||
const table = <DatabaseTable>args;
|
||||
await this.executeAction(view, ListModelsEventName, this.getRegisteredModels, this._registeredModelService, table);
|
||||
});
|
||||
view.on(RegisterLocalModelEventName, async (arg) => {
|
||||
let models = <ModelViewData[]>arg;
|
||||
await this.executeAction(view, RegisterLocalModelEventName, this.registerLocalModel, this._registeredModelService, models);
|
||||
view.refresh();
|
||||
});
|
||||
view.on(RegisterModelEventName, async () => {
|
||||
await this.executeAction(view, RegisterModelEventName, this.registerModel, view, this, this._apiWrapper, this._root);
|
||||
view.on(RegisterModelEventName, async (args) => {
|
||||
const importTable = <DatabaseTable>args;
|
||||
await this.executeAction(view, RegisterModelEventName, this.registerModel, importTable, view, this, this._apiWrapper, this._root);
|
||||
});
|
||||
view.on(RegisterAzureModelEventName, async (arg) => {
|
||||
let models = <ModelViewData[]>arg;
|
||||
@@ -161,6 +168,16 @@ export class ModelManagementController extends ControllerBase {
|
||||
await this.executeAction(view, DownloadRegisteredModelEventName, this.downloadRegisteredModel, this._registeredModelService,
|
||||
model);
|
||||
});
|
||||
view.on(StoreImportTableEventName, async (arg) => {
|
||||
let importTable = <DatabaseTable>arg;
|
||||
await this.executeAction(view, StoreImportTableEventName, this.storeImportTable, this._registeredModelService,
|
||||
importTable);
|
||||
});
|
||||
view.on(VerifyImportTableEventName, async (arg) => {
|
||||
let importTable = <DatabaseTable>arg;
|
||||
await this.executeAction(view, VerifyImportTableEventName, this.verifyImportTable, this._registeredModelService,
|
||||
importTable);
|
||||
});
|
||||
view.on(SourceModelSelectedEventName, (arg) => {
|
||||
view.modelSourceType = <ModelSourceType>arg;
|
||||
view.refresh();
|
||||
@@ -170,8 +187,14 @@ export class ModelManagementController extends ControllerBase {
|
||||
/**
|
||||
* Opens the dialog for model management
|
||||
*/
|
||||
public async manageRegisteredModels(): Promise<ModelViewBase> {
|
||||
let view = new RegisteredModelsDialog(this._apiWrapper, this._root);
|
||||
public async manageRegisteredModels(importTable?: DatabaseTable): Promise<ModelViewBase> {
|
||||
let view = new ManageModelsDialog(this._apiWrapper, this._root);
|
||||
|
||||
if (importTable) {
|
||||
view.importTable = importTable;
|
||||
} else {
|
||||
view.importTable = await this._registeredModelService.getRecentImportTable();
|
||||
}
|
||||
|
||||
// Register events
|
||||
//
|
||||
@@ -202,8 +225,8 @@ export class ModelManagementController extends ControllerBase {
|
||||
return await service.getWorkspaces(account, subscription, group);
|
||||
}
|
||||
|
||||
private async getRegisteredModels(registeredModelService: DeployedModelService): Promise<RegisteredModel[]> {
|
||||
return registeredModelService.getDeployedModels();
|
||||
private async getRegisteredModels(registeredModelService: DeployedModelService, table: DatabaseTable): Promise<RegisteredModel[]> {
|
||||
return registeredModelService.getDeployedModels(table);
|
||||
}
|
||||
|
||||
private async getAzureModels(
|
||||
@@ -221,9 +244,13 @@ export class ModelManagementController extends ControllerBase {
|
||||
private async registerLocalModel(service: DeployedModelService, models: ModelViewData[] | undefined): Promise<void> {
|
||||
if (models) {
|
||||
await Promise.all(models.map(async (model) => {
|
||||
const localModel = <string>model.modelData;
|
||||
if (localModel) {
|
||||
await service.deployLocalModel(localModel, model.modelDetails);
|
||||
if (model && model.targetImportTable) {
|
||||
const localModel = <string>model.modelData;
|
||||
if (localModel) {
|
||||
await service.deployLocalModel(localModel, model.modelDetails, model.targetImportTable);
|
||||
}
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
@@ -240,35 +267,39 @@ export class ModelManagementController extends ControllerBase {
|
||||
}
|
||||
|
||||
await Promise.all(models.map(async (model) => {
|
||||
const azureModel = <AzureModelResource>model.modelData;
|
||||
if (azureModel && azureModel.account && azureModel.subscription && azureModel.group && azureModel.workspace && azureModel.model) {
|
||||
let filePath: string | undefined;
|
||||
try {
|
||||
const filePath = await azureService.downloadModel(azureModel.account, azureModel.subscription, azureModel.group,
|
||||
azureModel.workspace, azureModel.model);
|
||||
if (filePath) {
|
||||
await service.deployLocalModel(filePath, model.modelDetails);
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
} finally {
|
||||
if (filePath) {
|
||||
await fs.promises.unlink(filePath);
|
||||
if (model && model.targetImportTable) {
|
||||
const azureModel = <AzureModelResource>model.modelData;
|
||||
if (azureModel && azureModel.account && azureModel.subscription && azureModel.group && azureModel.workspace && azureModel.model) {
|
||||
let filePath: string | undefined;
|
||||
try {
|
||||
const filePath = await azureService.downloadModel(azureModel.account, azureModel.subscription, azureModel.group,
|
||||
azureModel.workspace, azureModel.model);
|
||||
if (filePath) {
|
||||
await service.deployLocalModel(filePath, model.modelDetails, model.targetImportTable);
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
} finally {
|
||||
if (filePath) {
|
||||
await fs.promises.unlink(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public async getDatabaseList(predictService: PredictService): Promise<string[]> {
|
||||
private async getDatabaseList(predictService: PredictService): Promise<string[]> {
|
||||
return await predictService.getDatabaseList();
|
||||
}
|
||||
|
||||
public async getTableList(predictService: PredictService, databaseName: string): Promise<DatabaseTable[]> {
|
||||
private async getTableList(predictService: PredictService, databaseName: string): Promise<DatabaseTable[]> {
|
||||
return await predictService.getTableList(databaseName);
|
||||
}
|
||||
|
||||
public async getTableColumnsList(predictService: PredictService, databaseTable: DatabaseTable): Promise<TableColumn[]> {
|
||||
private async getTableColumnsList(predictService: PredictService, databaseTable: DatabaseTable): Promise<TableColumn[]> {
|
||||
return await predictService.getTableColumnsList(databaseTable);
|
||||
}
|
||||
|
||||
@@ -285,6 +316,22 @@ export class ModelManagementController extends ControllerBase {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async storeImportTable(registeredModelService: DeployedModelService, table: DatabaseTable | undefined): Promise<void> {
|
||||
if (table) {
|
||||
await registeredModelService.storeRecentImportTable(table);
|
||||
} else {
|
||||
throw Error(constants.invalidImportTableError(undefined, undefined));
|
||||
}
|
||||
}
|
||||
|
||||
private async verifyImportTable(registeredModelService: DeployedModelService, table: DatabaseTable | undefined): Promise<boolean> {
|
||||
if (table) {
|
||||
return await registeredModelService.verifyConfigTable(table);
|
||||
} else {
|
||||
throw Error(constants.invalidImportTableError(undefined, undefined));
|
||||
}
|
||||
}
|
||||
|
||||
private async downloadRegisteredModel(
|
||||
registeredModelService: DeployedModelService,
|
||||
model: RegisteredModel | undefined): Promise<string> {
|
||||
|
||||
@@ -37,6 +37,7 @@ export interface ModelViewData {
|
||||
modelFile?: string;
|
||||
modelData: AzureModelResource | string | RegisteredModel;
|
||||
modelDetails?: RegisteredModelDetails;
|
||||
targetImportTable?: DatabaseTable;
|
||||
}
|
||||
|
||||
// Event names
|
||||
@@ -58,6 +59,8 @@ export const PredictModelEventName = 'predictModel';
|
||||
export const RegisterModelEventName = 'registerModel';
|
||||
export const SourceModelSelectedEventName = 'sourceModelSelected';
|
||||
export const LoadModelParametersEventName = 'loadModelParameters';
|
||||
export const StoreImportTableEventName = 'storeImportTable';
|
||||
export const VerifyImportTableEventName = 'verifyImportTable';
|
||||
|
||||
/**
|
||||
* Base class for all model management views
|
||||
@@ -66,6 +69,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
|
||||
private _modelSourceType: ModelSourceType = ModelSourceType.Local;
|
||||
private _modelsViewData: ModelViewData[] = [];
|
||||
private _importTable: DatabaseTable | undefined;
|
||||
|
||||
constructor(apiWrapper: ApiWrapper, root?: string, parent?: ModelViewBase) {
|
||||
super(apiWrapper, root, parent);
|
||||
@@ -88,7 +92,9 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
PredictModelEventName,
|
||||
DownloadAzureModelEventName,
|
||||
DownloadRegisteredModelEventName,
|
||||
LoadModelParametersEventName]);
|
||||
LoadModelParametersEventName,
|
||||
StoreImportTableEventName,
|
||||
VerifyImportTableEventName]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,8 +115,8 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
/**
|
||||
* list registered models
|
||||
*/
|
||||
public async listModels(): Promise<RegisteredModel[]> {
|
||||
return await this.sendDataRequest(ListModelsEventName);
|
||||
public async listModels(table: DatabaseTable): Promise<RegisteredModel[]> {
|
||||
return await this.sendDataRequest(ListModelsEventName, table);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +162,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
* registers local model
|
||||
* @param localFilePath local file path
|
||||
*/
|
||||
public async registerLocalModel(models: ModelViewData[]): Promise<void> {
|
||||
public async importLocalModel(models: ModelViewData[]): Promise<void> {
|
||||
return await this.sendDataRequest(RegisterLocalModelEventName, models);
|
||||
}
|
||||
|
||||
@@ -187,10 +193,24 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
* registers azure model
|
||||
* @param args azure resource
|
||||
*/
|
||||
public async registerAzureModel(models: ModelViewData[]): Promise<void> {
|
||||
public async importAzureModel(models: ModelViewData[]): Promise<void> {
|
||||
return await this.sendDataRequest(RegisterAzureModelEventName, models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the name of the table as recent config table for importing models
|
||||
*/
|
||||
public async storeImportConfigTable(): Promise<void> {
|
||||
await this.sendRequest(StoreImportTableEventName, this.importTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if table is valid to import models to
|
||||
*/
|
||||
public async verifyImportConfigTable(table: DatabaseTable): Promise<boolean> {
|
||||
return await this.sendDataRequest(VerifyImportTableEventName, table);
|
||||
}
|
||||
|
||||
/**
|
||||
* registers azure model
|
||||
* @param args azure resource
|
||||
@@ -240,7 +260,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets model source type
|
||||
* Sets model data
|
||||
*/
|
||||
public set modelsViewData(value: ModelViewData[]) {
|
||||
if (this.parent) {
|
||||
@@ -251,7 +271,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns model source type
|
||||
* Returns model data
|
||||
*/
|
||||
public get modelsViewData(): ModelViewData[] {
|
||||
if (this.parent) {
|
||||
@@ -261,6 +281,28 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets import table
|
||||
*/
|
||||
public set importTable(value: DatabaseTable | undefined) {
|
||||
if (this.parent) {
|
||||
this.parent.importTable = value;
|
||||
} else {
|
||||
this._importTable = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns import table
|
||||
*/
|
||||
public get importTable(): DatabaseTable | undefined {
|
||||
if (this.parent) {
|
||||
return this.parent.importTable;
|
||||
} else {
|
||||
return this._importTable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lists azure workspaces
|
||||
* @param account azure account
|
||||
|
||||
@@ -11,6 +11,7 @@ import { IDataComponent } from '../../interfaces';
|
||||
import { PredictColumn, PredictInputParameters, DatabaseTable } from '../../../prediction/interfaces';
|
||||
import { ModelParameters } from '../../../modelManagement/interfaces';
|
||||
import { ColumnsTable } from './columnsTable';
|
||||
import { TableSelectionComponent } from '../tableSelectionComponent';
|
||||
|
||||
/**
|
||||
* View to render filters to pick an azure resource
|
||||
@@ -18,14 +19,10 @@ import { ColumnsTable } from './columnsTable';
|
||||
export class InputColumnsComponent extends ModelViewBase implements IDataComponent<PredictInputParameters> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _databases: azdata.DropDownComponent | undefined;
|
||||
private _tables: azdata.DropDownComponent | undefined;
|
||||
private _tableSelectionComponent: TableSelectionComponent | undefined;
|
||||
private _columns: ColumnsTable | undefined;
|
||||
private _dbNames: string[] = [];
|
||||
private _tableNames: DatabaseTable[] = [];
|
||||
private _modelParameters: ModelParameters | undefined;
|
||||
private _dbTableComponent: azdata.FlexContainer | undefined;
|
||||
private tableMaxLength = this.componentMaxLength * 2 + 70;
|
||||
|
||||
/**
|
||||
* Creates a new view
|
||||
*/
|
||||
@@ -38,53 +35,15 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
|
||||
* @param modelBuilder model builder
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this._databases = modelBuilder.dropDown().withProperties({
|
||||
width: this.componentMaxLength
|
||||
}).component();
|
||||
this._tables = modelBuilder.dropDown().withProperties({
|
||||
width: this.componentMaxLength
|
||||
}).component();
|
||||
this._columns = new ColumnsTable(this._apiWrapper, modelBuilder, this);
|
||||
|
||||
this._databases.onValueChanged(async () => {
|
||||
await this.onDatabaseSelected();
|
||||
});
|
||||
|
||||
this._tables.onValueChanged(async () => {
|
||||
this._tableSelectionComponent = new TableSelectionComponent(this._apiWrapper, this, false);
|
||||
this._tableSelectionComponent.registerComponent(modelBuilder);
|
||||
this._tableSelectionComponent.onSelectedChanged(async () => {
|
||||
await this.onTableSelected();
|
||||
});
|
||||
|
||||
|
||||
const databaseForm = modelBuilder.formContainer().withFormItems([{
|
||||
title: constants.columnDatabase,
|
||||
component: this._databases
|
||||
}]).withLayout({
|
||||
padding: '0px'
|
||||
}).component();
|
||||
const tableForm = modelBuilder.formContainer().withFormItems([{
|
||||
title: constants.columnTable,
|
||||
component: this._tables
|
||||
}]).withLayout({
|
||||
padding: '0px'
|
||||
}).component();
|
||||
this._dbTableComponent = modelBuilder.flexContainer().withItems([
|
||||
databaseForm,
|
||||
tableForm
|
||||
], {
|
||||
flex: '0 0 auto',
|
||||
CSSStyles: {
|
||||
'align-items': 'flex-start'
|
||||
}
|
||||
}).withLayout({
|
||||
flexFlow: 'row',
|
||||
justifyContent: 'space-between',
|
||||
width: this.tableMaxLength
|
||||
}).component();
|
||||
this._columns = new ColumnsTable(this._apiWrapper, modelBuilder, this);
|
||||
|
||||
this._form = modelBuilder.formContainer().withFormItems([{
|
||||
title: '',
|
||||
component: this._dbTableComponent
|
||||
}, {
|
||||
title: constants.inputColumns,
|
||||
component: this._columns.component
|
||||
}]).component();
|
||||
@@ -92,10 +51,10 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._columns && this._dbTableComponent) {
|
||||
if (this._columns && this._tableSelectionComponent && this._tableSelectionComponent.component) {
|
||||
formBuilder.addFormItems([{
|
||||
title: '',
|
||||
component: this._dbTableComponent
|
||||
component: this._tableSelectionComponent.component
|
||||
}, {
|
||||
title: constants.inputColumns,
|
||||
component: this._columns.component
|
||||
@@ -104,10 +63,10 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._columns && this._dbTableComponent) {
|
||||
if (this._columns && this._tableSelectionComponent && this._tableSelectionComponent.component) {
|
||||
formBuilder.removeFormItem({
|
||||
title: '',
|
||||
component: this._dbTableComponent
|
||||
component: this._tableSelectionComponent.component
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.inputColumns,
|
||||
@@ -136,12 +95,9 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
|
||||
* loads data in the components
|
||||
*/
|
||||
public async loadData(): Promise<void> {
|
||||
this._dbNames = await this.listDatabaseNames();
|
||||
if (this._databases && this._dbNames && this._dbNames.length > 0) {
|
||||
this._databases.values = this._dbNames;
|
||||
this._databases.value = this._dbNames[0];
|
||||
if (this._tableSelectionComponent) {
|
||||
this._tableSelectionComponent.refresh();
|
||||
}
|
||||
await this.onDatabaseSelected();
|
||||
}
|
||||
|
||||
public set modelParameters(value: ModelParameters) {
|
||||
@@ -167,31 +123,14 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
private async onDatabaseSelected(): Promise<void> {
|
||||
this._tableNames = await this.listTableNames(this.databaseName || '');
|
||||
if (this._tables && this._tableNames && this._tableNames.length > 0) {
|
||||
this._tables.values = this._tableNames.map(t => this.getTableFullName(t));
|
||||
this._tables.value = this.getTableFullName(this._tableNames[0]);
|
||||
}
|
||||
await this.onTableSelected();
|
||||
}
|
||||
|
||||
private getTableFullName(table: DatabaseTable): string {
|
||||
return `${table.schema}.${table.tableName}`;
|
||||
}
|
||||
|
||||
private async onTableSelected(): Promise<void> {
|
||||
this._columns?.loadInputs(this._modelParameters, this.databaseTable);
|
||||
}
|
||||
|
||||
private get databaseName(): string | undefined {
|
||||
return <string>this._databases?.value;
|
||||
}
|
||||
|
||||
private get databaseTable(): DatabaseTable {
|
||||
let selectedItem = this._tableNames.find(x => this.getTableFullName(x) === this._tables?.value);
|
||||
let selectedItem = this._tableSelectionComponent?.data;
|
||||
return {
|
||||
databaseName: this.databaseName,
|
||||
databaseName: selectedItem?.databaseName,
|
||||
tableName: selectedItem?.tableName,
|
||||
schema: selectedItem?.schema
|
||||
};
|
||||
|
||||
@@ -116,7 +116,7 @@ export class PredictWizard extends ModelViewBase {
|
||||
} else if (this.modelResources && this.azureModelsComponent && this.modelResources.data === ModelSourceType.Azure) {
|
||||
return await this.azureModelsComponent.getDownloadedModel();
|
||||
} else if (this.modelBrowsePage && this.modelBrowsePage.registeredModelsComponent) {
|
||||
return await this.modelBrowsePage.registeredModelsComponent.getDownloadedModel();
|
||||
return await this.modelBrowsePage.registeredModelsComponent.modelTable?.getDownloadedModel();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 vscode from 'vscode';
|
||||
import { ModelViewBase } from './modelViewBase';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import * as constants from '../../common/constants';
|
||||
import { IDataComponent } from '../interfaces';
|
||||
import { DatabaseTable } from '../../prediction/interfaces';
|
||||
|
||||
/**
|
||||
* View to render filters to pick an azure resource
|
||||
*/
|
||||
export class TableSelectionComponent extends ModelViewBase implements IDataComponent<DatabaseTable> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _databases: azdata.DropDownComponent | undefined;
|
||||
private _selectedTableName: string = '';
|
||||
private _tables: azdata.DropDownComponent | undefined;
|
||||
private _dbNames: string[] = [];
|
||||
private _tableNames: DatabaseTable[] = [];
|
||||
private _dbTableComponent: azdata.FlexContainer | undefined;
|
||||
private tableMaxLength = this.componentMaxLength * 2 + 70;
|
||||
private _onSelectedChanged: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
||||
public readonly onSelectedChanged: vscode.Event<void> = this._onSelectedChanged.event;
|
||||
|
||||
/**
|
||||
* Creates a new view
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _editable: boolean) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register components
|
||||
* @param modelBuilder model builder
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this._databases = modelBuilder.dropDown().withProperties({
|
||||
width: this.componentMaxLength,
|
||||
editable: this._editable,
|
||||
fireOnTextChange: this._editable
|
||||
}).component();
|
||||
this._tables = modelBuilder.dropDown().withProperties({
|
||||
width: this.componentMaxLength,
|
||||
editable: this._editable,
|
||||
fireOnTextChange: this._editable
|
||||
}).component();
|
||||
|
||||
this._databases.onValueChanged(async () => {
|
||||
await this.onDatabaseSelected();
|
||||
});
|
||||
|
||||
this._tables.onValueChanged(async (value) => {
|
||||
// There's an issue with dropdown doesn't set the value in editable mode. this is the workaround
|
||||
|
||||
if (this._tables && value) {
|
||||
this._selectedTableName = this._editable ? value : value.selected;
|
||||
}
|
||||
await this.onTableSelected();
|
||||
});
|
||||
|
||||
const databaseForm = modelBuilder.formContainer().withFormItems([{
|
||||
title: constants.columnDatabase,
|
||||
component: this._databases,
|
||||
}]).withLayout({
|
||||
padding: '0px'
|
||||
}).component();
|
||||
const tableForm = modelBuilder.formContainer().withFormItems([{
|
||||
title: constants.columnTable,
|
||||
component: this._tables
|
||||
}]).withLayout({
|
||||
padding: '0px'
|
||||
}).component();
|
||||
this._dbTableComponent = modelBuilder.flexContainer().withItems([
|
||||
databaseForm,
|
||||
tableForm
|
||||
], {
|
||||
flex: '0 0 auto',
|
||||
CSSStyles: {
|
||||
'align-items': 'flex-start'
|
||||
}
|
||||
}).withLayout({
|
||||
flexFlow: 'row',
|
||||
justifyContent: 'space-between',
|
||||
width: this.tableMaxLength
|
||||
}).component();
|
||||
|
||||
this._form = modelBuilder.formContainer().withFormItems([{
|
||||
title: '',
|
||||
component: this._dbTableComponent
|
||||
}]).component();
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._databases && this._tables) {
|
||||
formBuilder.addFormItems([{
|
||||
title: constants.databaseName,
|
||||
component: this._databases
|
||||
}, {
|
||||
title: constants.tableName,
|
||||
component: this._tables
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._databases && this._tables) {
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.databaseName,
|
||||
component: this._databases
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.tableName,
|
||||
component: this._tables
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the created component
|
||||
*/
|
||||
public get component(): azdata.Component | undefined {
|
||||
return this._dbTableComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
public get data(): DatabaseTable | undefined {
|
||||
return this.databaseTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* loads data in the components
|
||||
*/
|
||||
public async loadData(): Promise<void> {
|
||||
this._dbNames = await this.listDatabaseNames();
|
||||
if (this._databases && this._dbNames && this._dbNames.length > 0) {
|
||||
this._databases.values = this._dbNames;
|
||||
if (this.importTable) {
|
||||
this._databases.value = this.importTable.databaseName;
|
||||
} else {
|
||||
this._databases.value = this._dbNames[0];
|
||||
}
|
||||
}
|
||||
await this.onDatabaseSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* refreshes the view
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
private async onDatabaseSelected(): Promise<void> {
|
||||
this._tableNames = await this.listTableNames(this.databaseName || '');
|
||||
if (this._tables && this._tableNames && this._tableNames.length > 0) {
|
||||
this._tables.values = this._tableNames.map(t => this.getTableFullName(t));
|
||||
if (this.importTable) {
|
||||
const selectedTable = this._tableNames.find(t => t.tableName === this.importTable?.tableName && t.schema === this.importTable?.schema);
|
||||
if (selectedTable) {
|
||||
this._selectedTableName = this.getTableFullName(selectedTable);
|
||||
this._tables.value = this.getTableFullName(selectedTable);
|
||||
} else {
|
||||
this._selectedTableName = this.getTableFullName(this._tableNames[0]);
|
||||
}
|
||||
} else {
|
||||
this._selectedTableName = this.getTableFullName(this._tableNames[0]);
|
||||
}
|
||||
this._tables.value = this._selectedTableName;
|
||||
} else if (this._tables) {
|
||||
this._tables.values = [];
|
||||
this._tables.value = '';
|
||||
}
|
||||
await this.onTableSelected();
|
||||
}
|
||||
|
||||
private getTableFullName(table: DatabaseTable): string {
|
||||
return `${table.schema}.${table.tableName}`;
|
||||
}
|
||||
|
||||
private async onTableSelected(): Promise<void> {
|
||||
this._onSelectedChanged.fire();
|
||||
}
|
||||
|
||||
private get databaseName(): string | undefined {
|
||||
return <string>this._databases?.value;
|
||||
}
|
||||
|
||||
private get databaseTable(): DatabaseTable {
|
||||
let selectedItem = this._tableNames.find(x => this.getTableFullName(x) === this._selectedTableName);
|
||||
if (!selectedItem) {
|
||||
const value = this._selectedTableName;
|
||||
const parts = value ? value.split('.') : undefined;
|
||||
selectedItem = {
|
||||
databaseName: this.databaseName,
|
||||
tableName: parts && parts.length > 1 ? parts[1] : value,
|
||||
schema: parts && parts.length > 1 ? parts[0] : 'dbo',
|
||||
};
|
||||
}
|
||||
return {
|
||||
databaseName: this.databaseName,
|
||||
tableName: selectedItem?.tableName,
|
||||
schema: selectedItem?.schema
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -369,7 +369,7 @@ export class DashboardWidget {
|
||||
light: this.asAbsolutePath('images/makePredictions.svg'),
|
||||
},
|
||||
link: '',
|
||||
command: constants.mlImportModelCommand
|
||||
command: constants.mlManageModelsCommand
|
||||
};
|
||||
const importModelsButton = this.createTaskButton(view, importMetadata);
|
||||
const notebookMetadata: IActionMetadata = {
|
||||
|
||||
@@ -75,7 +75,7 @@ export class WizardView extends MainViewBase {
|
||||
}
|
||||
|
||||
public async validate(pageInfo: azdata.window.WizardPageChangeInfo): Promise<boolean> {
|
||||
if (pageInfo.lastPage !== undefined) {
|
||||
if (pageInfo?.lastPage !== undefined) {
|
||||
let idxLast = pageInfo.lastPage;
|
||||
let lastPage = this._pages[idxLast];
|
||||
if (lastPage && lastPage.validate) {
|
||||
@@ -86,16 +86,23 @@ export class WizardView extends MainViewBase {
|
||||
}
|
||||
|
||||
private async onWizardPageChanged(pageInfo: azdata.window.WizardPageChangeInfo) {
|
||||
let idxLast = pageInfo.lastPage;
|
||||
let lastPage = this._pages[idxLast];
|
||||
if (lastPage && lastPage.onLeave) {
|
||||
await lastPage.onLeave();
|
||||
if (pageInfo?.lastPage !== undefined) {
|
||||
let idxLast = pageInfo.lastPage;
|
||||
let lastPage = this._pages[idxLast];
|
||||
if (lastPage && lastPage.onLeave) {
|
||||
await lastPage.onLeave();
|
||||
}
|
||||
}
|
||||
|
||||
let idx = pageInfo.newPage;
|
||||
let page = this._pages[idx];
|
||||
if (page && page.onEnter) {
|
||||
await page.onEnter();
|
||||
if (pageInfo?.newPage !== undefined) {
|
||||
let idx = pageInfo.newPage;
|
||||
let page = this._pages[idx];
|
||||
if (page && page.onEnter) {
|
||||
if (this._wizard && this._wizard.pages.length > idx) {
|
||||
this._wizard.pages[idx].title = page.title;
|
||||
}
|
||||
await page.onEnter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user