mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 01:25:39 -05:00
ML - Added model management dialog to edit and delete models (#10125)
* ML - Added model management dialog to edit and delete models
This commit is contained in:
@@ -34,4 +34,10 @@ export interface AzureModelResource extends AzureWorkspaceResource {
|
||||
model?: WorkspaceModel;
|
||||
}
|
||||
|
||||
export interface IComponentSettings {
|
||||
multiSelect?: boolean;
|
||||
editable?: boolean;
|
||||
selectable?: boolean;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,11 +10,13 @@ import { AzureResourceFilterComponent } from './azureResourceFilterComponent';
|
||||
import { AzureModelsTable } from './azureModelsTable';
|
||||
import { IDataComponent, AzureModelResource } from '../interfaces';
|
||||
import { ModelArtifact } from './prediction/modelArtifact';
|
||||
import { AzureSignInComponent } from './azureSignInComponent';
|
||||
|
||||
export class AzureModelsComponent extends ModelViewBase implements IDataComponent<AzureModelResource[]> {
|
||||
|
||||
public azureModelsTable: AzureModelsTable | undefined;
|
||||
public azureFilterComponent: AzureResourceFilterComponent | undefined;
|
||||
public azureSignInComponent: AzureSignInComponent | undefined;
|
||||
|
||||
private _loader: azdata.LoadingComponent | undefined;
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
@@ -34,6 +36,7 @@ export class AzureModelsComponent extends ModelViewBase implements IDataComponen
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this.azureFilterComponent = new AzureResourceFilterComponent(this._apiWrapper, modelBuilder, this);
|
||||
this.azureModelsTable = new AzureModelsTable(this._apiWrapper, modelBuilder, this, this._multiSelect);
|
||||
this.azureSignInComponent = new AzureSignInComponent(this._apiWrapper, modelBuilder, this);
|
||||
this._loader = modelBuilder.loadingComponent()
|
||||
.withItem(this.azureModelsTable.component)
|
||||
.withProperties({
|
||||
@@ -63,6 +66,20 @@ export class AzureModelsComponent extends ModelViewBase implements IDataComponen
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
this.removeComponents(formBuilder);
|
||||
if (this.azureFilterComponent?.data?.account) {
|
||||
this.addAzureComponents(formBuilder);
|
||||
} else {
|
||||
this.addAzureSignInComponents(formBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
this.removeAzureComponents(formBuilder);
|
||||
this.removeAzureSignInComponents(formBuilder);
|
||||
}
|
||||
|
||||
private addAzureComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this.azureFilterComponent && this._loader) {
|
||||
this.azureFilterComponent.addComponents(formBuilder);
|
||||
|
||||
@@ -73,7 +90,7 @@ export class AzureModelsComponent extends ModelViewBase implements IDataComponen
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
private removeAzureComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this.azureFilterComponent && this._loader) {
|
||||
this.azureFilterComponent.removeComponents(formBuilder);
|
||||
formBuilder.removeFormItem({
|
||||
@@ -83,6 +100,18 @@ export class AzureModelsComponent extends ModelViewBase implements IDataComponen
|
||||
}
|
||||
}
|
||||
|
||||
private addAzureSignInComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this.azureSignInComponent) {
|
||||
this.azureSignInComponent.addComponents(formBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private removeAzureSignInComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this.azureSignInComponent) {
|
||||
this.azureSignInComponent.removeComponents(formBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private async onLoading(): Promise<void> {
|
||||
if (this._loader) {
|
||||
await this._loader.updateProperties({ loading: true });
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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, SignInToAzureEventName } from './modelViewBase';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import * as constants from '../../common/constants';
|
||||
|
||||
/**
|
||||
* View to render filters to pick an azure resource
|
||||
*/
|
||||
const componentWidth = 300;
|
||||
export class AzureSignInComponent extends ModelViewBase {
|
||||
|
||||
private _form: azdata.FormContainer;
|
||||
private _signInButton: azdata.ButtonComponent;
|
||||
|
||||
/**
|
||||
* Creates a new view
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, private _modelBuilder: azdata.ModelBuilder, parent: ModelViewBase) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
this._signInButton = this._modelBuilder.button().withProperties({
|
||||
width: componentWidth,
|
||||
label: constants.azureSignIn,
|
||||
}).component();
|
||||
this._signInButton.onDidClick(() => {
|
||||
this.sendRequest(SignInToAzureEventName);
|
||||
});
|
||||
|
||||
this._form = this._modelBuilder.formContainer().withFormItems([{
|
||||
title: constants.azureAccount,
|
||||
component: this._signInButton
|
||||
}]).component();
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._signInButton) {
|
||||
formBuilder.addFormItems([{
|
||||
title: constants.azureAccount,
|
||||
component: this._signInButton
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._signInButton) {
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.azureAccount,
|
||||
component: this._signInButton
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the created component
|
||||
*/
|
||||
public get component(): azdata.Component {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
/**
|
||||
* refreshes the view
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,9 @@ import * as constants from '../../../common/constants';
|
||||
import { ModelViewBase } from '../modelViewBase';
|
||||
import { CurrentModelsTable } from './currentModelsTable';
|
||||
import { ApiWrapper } from '../../../common/apiWrapper';
|
||||
import { IPageView } from '../../interfaces';
|
||||
import { IPageView, IComponentSettings } from '../../interfaces';
|
||||
import { TableSelectionComponent } from '../tableSelectionComponent';
|
||||
import { RegisteredModel } from '../../../modelManagement/interfaces';
|
||||
import { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
|
||||
/**
|
||||
* View to render current registered models
|
||||
@@ -27,7 +27,7 @@ export class CurrentModelsComponent extends ModelViewBase implements IPageView {
|
||||
* @param apiWrapper Creates new view
|
||||
* @param parent page parent
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _multiSelect: boolean = false) {
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _settings: IComponentSettings) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export class CurrentModelsComponent extends ModelViewBase implements IPageView {
|
||||
this._tableSelectionComponent.onSelectedChanged(async () => {
|
||||
await this.onTableSelected();
|
||||
});
|
||||
this._dataTable = new CurrentModelsTable(this._apiWrapper, this, this._multiSelect);
|
||||
this._dataTable = new CurrentModelsTable(this._apiWrapper, this, this._settings);
|
||||
this._dataTable.registerComponent(modelBuilder);
|
||||
this._tableComponent = this._dataTable.component;
|
||||
|
||||
@@ -102,7 +102,7 @@ export class CurrentModelsComponent extends ModelViewBase implements IPageView {
|
||||
}
|
||||
}
|
||||
|
||||
public get data(): RegisteredModel[] | undefined {
|
||||
public get data(): ImportedModel[] | undefined {
|
||||
return this._dataTable?.data;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,20 +6,21 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as constants from '../../../common/constants';
|
||||
import { ModelViewBase } from '../modelViewBase';
|
||||
import { ModelViewBase, DeleteModelEventName, EditModelEventName } from '../modelViewBase';
|
||||
import { ApiWrapper } from '../../../common/apiWrapper';
|
||||
import { RegisteredModel } from '../../../modelManagement/interfaces';
|
||||
import { IDataComponent } from '../../interfaces';
|
||||
import { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
import { IDataComponent, IComponentSettings } from '../../interfaces';
|
||||
import { ModelArtifact } from '../prediction/modelArtifact';
|
||||
import * as utils from '../../../common/utils';
|
||||
|
||||
/**
|
||||
* View to render registered models table
|
||||
*/
|
||||
export class CurrentModelsTable extends ModelViewBase implements IDataComponent<RegisteredModel[]> {
|
||||
export class CurrentModelsTable extends ModelViewBase implements IDataComponent<ImportedModel[]> {
|
||||
|
||||
private _table: azdata.DeclarativeTableComponent | undefined;
|
||||
private _modelBuilder: azdata.ModelBuilder | undefined;
|
||||
private _selectedModel: RegisteredModel[] = [];
|
||||
private _selectedModel: ImportedModel[] = [];
|
||||
private _loader: azdata.LoadingComponent | undefined;
|
||||
private _downloadedFile: ModelArtifact | undefined;
|
||||
private _onModelSelectionChanged: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
||||
@@ -28,7 +29,7 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
/**
|
||||
* Creates new view
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _multiSelect: boolean = true) {
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _settings: IComponentSettings) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
@@ -38,62 +39,66 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this._modelBuilder = modelBuilder;
|
||||
let columns = [
|
||||
{ // Name
|
||||
displayName: constants.modelName,
|
||||
ariaLabel: constants.modelName,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: 150,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
},
|
||||
{ // Created
|
||||
displayName: constants.modelCreated,
|
||||
ariaLabel: constants.modelCreated,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: 150,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
},
|
||||
{ // Action
|
||||
displayName: '',
|
||||
valueType: azdata.DeclarativeDataType.component,
|
||||
isReadOnly: true,
|
||||
width: 50,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
}
|
||||
];
|
||||
if (this._settings.editable) {
|
||||
columns.push(
|
||||
{ // Action
|
||||
displayName: '',
|
||||
valueType: azdata.DeclarativeDataType.component,
|
||||
isReadOnly: true,
|
||||
width: 50,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
this._table = modelBuilder.declarativeTable()
|
||||
.withProperties<azdata.DeclarativeTableProperties>(
|
||||
{
|
||||
columns: [
|
||||
{ // Artifact name
|
||||
displayName: constants.modelArtifactName,
|
||||
ariaLabel: constants.modelArtifactName,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: 150,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
},
|
||||
{ // Name
|
||||
displayName: constants.modelName,
|
||||
ariaLabel: constants.modelName,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: 150,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
},
|
||||
{ // Created
|
||||
displayName: constants.modelCreated,
|
||||
ariaLabel: constants.modelCreated,
|
||||
valueType: azdata.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: 150,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
},
|
||||
{ // Action
|
||||
displayName: '',
|
||||
valueType: azdata.DeclarativeDataType.component,
|
||||
isReadOnly: true,
|
||||
width: 50,
|
||||
headerCssStyles: {
|
||||
...constants.cssStyles.tableHeader
|
||||
},
|
||||
rowCssStyles: {
|
||||
...constants.cssStyles.tableRow
|
||||
},
|
||||
}
|
||||
],
|
||||
columns: columns,
|
||||
data: [],
|
||||
ariaLabel: constants.mlsConfigTitle
|
||||
})
|
||||
@@ -132,7 +137,7 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
public async loadData(): Promise<void> {
|
||||
await this.onLoading();
|
||||
if (this._table) {
|
||||
let models: RegisteredModel[] | undefined;
|
||||
let models: ImportedModel[] | undefined;
|
||||
|
||||
if (this.importTable) {
|
||||
models = await this.listModels(this.importTable);
|
||||
@@ -163,11 +168,28 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
}
|
||||
}
|
||||
|
||||
private createTableRow(model: RegisteredModel): any[] {
|
||||
private createTableRow(model: ImportedModel): any[] {
|
||||
let row: any[] = [model.modelName, model.created];
|
||||
if (this._modelBuilder) {
|
||||
let selectModelButton: azdata.Component;
|
||||
const selectButton = this.createSelectButton(model);
|
||||
if (selectButton) {
|
||||
row.push(selectButton);
|
||||
}
|
||||
const editButtons = this.createEditButtons(model);
|
||||
if (editButtons && editButtons.length > 0) {
|
||||
row = row.concat(editButtons);
|
||||
}
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
private createSelectButton(model: ImportedModel): azdata.Component | undefined {
|
||||
let selectModelButton: azdata.Component | undefined = undefined;
|
||||
if (this._modelBuilder && this._settings.selectable) {
|
||||
|
||||
let onSelectItem = (checked: boolean) => {
|
||||
if (!this._multiSelect) {
|
||||
if (!this._settings.multiSelect) {
|
||||
this._selectedModel = [];
|
||||
}
|
||||
const foundItem = this._selectedModel.find(x => x === model);
|
||||
@@ -178,7 +200,7 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
}
|
||||
this.onModelSelected();
|
||||
};
|
||||
if (this._multiSelect) {
|
||||
if (this._settings.multiSelect) {
|
||||
const checkbox = this._modelBuilder.checkBox().withProperties({
|
||||
name: 'amlModel',
|
||||
value: model.id,
|
||||
@@ -203,11 +225,53 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
});
|
||||
selectModelButton = radioButton;
|
||||
}
|
||||
|
||||
return [model.artifactName, model.title, model.created, selectModelButton];
|
||||
}
|
||||
return selectModelButton;
|
||||
}
|
||||
|
||||
return [];
|
||||
private createEditButtons(model: ImportedModel): azdata.Component[] | undefined {
|
||||
let dropButton: azdata.ButtonComponent | undefined = undefined;
|
||||
let editButton: azdata.ButtonComponent | undefined = undefined;
|
||||
if (this._modelBuilder && this._settings.editable) {
|
||||
dropButton = this._modelBuilder.button().withProperties({
|
||||
label: '',
|
||||
title: constants.deleteTitle,
|
||||
iconPath: {
|
||||
dark: this.asAbsolutePath('images/dark/delete_inverse.svg'),
|
||||
light: this.asAbsolutePath('images/light/delete.svg')
|
||||
},
|
||||
width: 15,
|
||||
height: 15
|
||||
}).component();
|
||||
dropButton.onDidClick(async () => {
|
||||
try {
|
||||
const confirm = await utils.promptConfirm(constants.confirmDeleteModel(model.modelName), this._apiWrapper);
|
||||
if (confirm) {
|
||||
await this.sendDataRequest(DeleteModelEventName, model);
|
||||
if (this.parent) {
|
||||
await this.parent?.refresh();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.showErrorMessage(`${constants.updateModelFailedError} ${constants.getErrorMessage(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
editButton = this._modelBuilder.button().withProperties({
|
||||
label: '',
|
||||
title: constants.deleteTitle,
|
||||
iconPath: {
|
||||
dark: this.asAbsolutePath('images/dark/edit_inverse.svg'),
|
||||
light: this.asAbsolutePath('images/light/edit.svg')
|
||||
},
|
||||
width: 15,
|
||||
height: 15
|
||||
}).component();
|
||||
editButton.onDidClick(async () => {
|
||||
await this.sendDataRequest(EditModelEventName, model);
|
||||
});
|
||||
}
|
||||
return editButton && dropButton ? [editButton, dropButton] : undefined;
|
||||
}
|
||||
|
||||
private async onModelSelected(): Promise<void> {
|
||||
@@ -221,7 +285,7 @@ export class CurrentModelsTable extends ModelViewBase implements IDataComponent<
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
public get data(): RegisteredModel[] | undefined {
|
||||
public get data(): ImportedModel[] | undefined {
|
||||
return this._selectedModel;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ModelViewBase, UpdateModelEventName } from '../modelViewBase';
|
||||
import * as constants from '../../../common/constants';
|
||||
import { ApiWrapper } from '../../../common/apiWrapper';
|
||||
import { DialogView } from '../../dialogView';
|
||||
import { ModelDetailsEditPage } from './modelDetailsEditPage';
|
||||
import { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
|
||||
/**
|
||||
* Dialog to render registered model views
|
||||
*/
|
||||
export class EditModelDialog extends ModelViewBase {
|
||||
|
||||
constructor(
|
||||
apiWrapper: ApiWrapper,
|
||||
root: string,
|
||||
private _parentView: ModelViewBase | undefined,
|
||||
private _model: ImportedModel) {
|
||||
super(apiWrapper, root);
|
||||
this.dialogView = new DialogView(this._apiWrapper);
|
||||
}
|
||||
public dialogView: DialogView;
|
||||
public editModelPage: ModelDetailsEditPage | undefined;
|
||||
|
||||
/**
|
||||
* Opens a dialog to edit models.
|
||||
*/
|
||||
public open(): void {
|
||||
|
||||
this.editModelPage = new ModelDetailsEditPage(this._apiWrapper, this, this._model);
|
||||
|
||||
let registerModelButton = this._apiWrapper.createButton(constants.extLangSaveButtonText);
|
||||
registerModelButton.onClick(async () => {
|
||||
if (this.editModelPage) {
|
||||
const valid = await this.editModelPage.validate();
|
||||
if (valid) {
|
||||
try {
|
||||
await this.sendDataRequest(UpdateModelEventName, this.editModelPage?.data);
|
||||
this.showInfoMessage(constants.modelUpdatedSuccessfully);
|
||||
if (this._parentView) {
|
||||
await this._parentView.refresh();
|
||||
}
|
||||
} catch (error) {
|
||||
this.showInfoMessage(`${constants.modelUpdateFailedError} ${constants.getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let dialog = this.dialogView.createDialog(constants.editModelTitle, [this.editModelPage]);
|
||||
dialog.customButtons = [registerModelButton];
|
||||
this.mainViewPanel = dialog;
|
||||
dialog.okButton.hidden = true;
|
||||
dialog.cancelButton.label = constants.extLangDoneButtonText;
|
||||
|
||||
dialog.registerCloseValidator(() => {
|
||||
return false; // Blocks Enter key from closing dialog.
|
||||
});
|
||||
|
||||
this._apiWrapper.openDialog(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the tabs for given provider Id
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
if (this.dialogView) {
|
||||
this.dialogView.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { WizardView } from '../../wizardView';
|
||||
import { ModelSourcePage } from '../modelSourcePage';
|
||||
import { ModelDetailsPage } from '../modelDetailsPage';
|
||||
import { ModelBrowsePage } from '../modelBrowsePage';
|
||||
import { ModelImportLocationPage } from './modelmportLocationPage';
|
||||
import { ModelImportLocationPage } from './modelImportLocationPage';
|
||||
|
||||
/**
|
||||
* Wizard to register a model
|
||||
|
||||
@@ -29,7 +29,10 @@ export class ManageModelsDialog extends ModelViewBase {
|
||||
*/
|
||||
public open(): void {
|
||||
|
||||
this.currentLanguagesTab = new CurrentModelsComponent(this._apiWrapper, this);
|
||||
this.currentLanguagesTab = new CurrentModelsComponent(this._apiWrapper, this, {
|
||||
editable: true,
|
||||
selectable: false
|
||||
});
|
||||
|
||||
let registerModelButton = this._apiWrapper.createButton(constants.importModelTitle);
|
||||
registerModelButton.onClick(async () => {
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { IDataComponent } from '../../interfaces';
|
||||
import { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
|
||||
/**
|
||||
* View to render filters to pick an azure resource
|
||||
*/
|
||||
export class ModelDetailsComponent extends ModelViewBase implements IDataComponent<ImportedModel> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _nameComponent: azdata.InputBoxComponent | undefined;
|
||||
private _descriptionComponent: azdata.InputBoxComponent | undefined;
|
||||
private _createdComponent: azdata.Component | undefined;
|
||||
private _deployedComponent: azdata.Component | undefined;
|
||||
private _frameworkComponent: azdata.Component | undefined;
|
||||
private _frameworkVersionComponent: azdata.Component | undefined;
|
||||
/**
|
||||
* Creates a new view
|
||||
*/
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _model: ImportedModel) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register components
|
||||
* @param modelBuilder model builder
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
this._createdComponent = modelBuilder.text().withProperties({
|
||||
value: this._model.created
|
||||
}).component();
|
||||
this._deployedComponent = modelBuilder.text().withProperties({
|
||||
value: this._model.deploymentTime
|
||||
}).component();
|
||||
this._frameworkComponent = modelBuilder.text().withProperties({
|
||||
value: this._model.framework
|
||||
}).component();
|
||||
this._frameworkVersionComponent = modelBuilder.text().withProperties({
|
||||
value: this._model.frameworkVersion
|
||||
}).component();
|
||||
this._nameComponent = modelBuilder.inputBox().withProperties({
|
||||
width: this.componentMaxLength,
|
||||
value: this._model.modelName
|
||||
}).component();
|
||||
this._descriptionComponent = modelBuilder.inputBox().withProperties({
|
||||
width: this.componentMaxLength,
|
||||
value: this._model.description,
|
||||
multiline: true,
|
||||
height: 50
|
||||
}).component();
|
||||
|
||||
this._form = modelBuilder.formContainer().withFormItems([{
|
||||
title: '',
|
||||
component: this._nameComponent
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
component: this._descriptionComponent
|
||||
}]).component();
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public addComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._nameComponent && this._descriptionComponent && this._createdComponent && this._deployedComponent && this._frameworkComponent && this._frameworkVersionComponent) {
|
||||
formBuilder.addFormItems([{
|
||||
title: constants.modelName,
|
||||
component: this._nameComponent
|
||||
}, {
|
||||
title: constants.modelCreated,
|
||||
component: this._createdComponent
|
||||
},
|
||||
{
|
||||
title: constants.modelDeployed,
|
||||
component: this._deployedComponent
|
||||
}, {
|
||||
title: constants.modelFramework,
|
||||
component: this._frameworkComponent
|
||||
}, {
|
||||
title: constants.modelFrameworkVersion,
|
||||
component: this._frameworkVersionComponent
|
||||
}, {
|
||||
title: constants.modelDescription,
|
||||
component: this._descriptionComponent
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
public removeComponents(formBuilder: azdata.FormBuilder) {
|
||||
if (this._nameComponent && this._descriptionComponent && this._createdComponent && this._deployedComponent && this._frameworkComponent && this._frameworkVersionComponent) {
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelCreated,
|
||||
component: this._createdComponent
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelCreated,
|
||||
component: this._frameworkComponent
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelCreated,
|
||||
component: this._frameworkVersionComponent
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelCreated,
|
||||
component: this._deployedComponent
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelName,
|
||||
component: this._nameComponent
|
||||
});
|
||||
formBuilder.removeFormItem({
|
||||
title: constants.modelDescription,
|
||||
component: this._descriptionComponent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the created component
|
||||
*/
|
||||
public get component(): azdata.Component | undefined {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
public get data(): ImportedModel | undefined {
|
||||
let model = Object.assign({}, this._model);
|
||||
model.modelName = this._nameComponent?.value || '';
|
||||
model.description = this._descriptionComponent?.value || '';
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* loads data in the components
|
||||
*/
|
||||
public async loadData(): Promise<void> {
|
||||
}
|
||||
|
||||
/**
|
||||
* refreshes the view
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
await this.loadData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
import { ModelDetailsComponent } from './modelDetailsComponent';
|
||||
|
||||
/**
|
||||
* View to pick model source
|
||||
*/
|
||||
export class ModelDetailsEditPage extends ModelViewBase implements IPageView, IDataComponent<ImportedModel> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _formBuilder: azdata.FormBuilder | undefined;
|
||||
public modelDetailsComponent: ModelDetailsComponent | undefined;
|
||||
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase, private _model: ImportedModel) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param modelBuilder Register components
|
||||
*/
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
|
||||
this._formBuilder = modelBuilder.formContainer();
|
||||
this.modelDetailsComponent = new ModelDetailsComponent(this._apiWrapper, this, this._model);
|
||||
|
||||
this.modelDetailsComponent.registerComponent(modelBuilder);
|
||||
this.modelDetailsComponent.addComponents(this._formBuilder);
|
||||
this._form = this._formBuilder.component();
|
||||
return this._form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selected data
|
||||
*/
|
||||
public get data(): ImportedModel | undefined {
|
||||
return this.modelDetailsComponent?.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component
|
||||
*/
|
||||
public get component(): azdata.Component | undefined {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the view
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
if (this.modelDetailsComponent) {
|
||||
await this.modelDetailsComponent.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?.modelName) {
|
||||
validated = true;
|
||||
} else {
|
||||
this.showErrorMessage(constants.modelNameRequiredError);
|
||||
}
|
||||
return validated;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,6 @@ export class ModelImportLocationPage extends ModelViewBase implements IPageView,
|
||||
private async onTableSelected(): Promise<void> {
|
||||
if (this.tableSelectionComponent?.data) {
|
||||
this.importTable = this.tableSelectionComponent?.data;
|
||||
//this.sendRequest(StoreImportTableEventName, this.importTable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { CurrentModelsComponent } from './manageModels/currentModelsComponent';
|
||||
export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataComponent<ModelViewData[]> {
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _title: string = constants.modelSourcePageTitle;
|
||||
private _title: string = constants.localModelPageTitle;
|
||||
private _formBuilder: azdata.FormBuilder | undefined;
|
||||
public localModelsComponent: LocalModelsComponent | undefined;
|
||||
public azureModelsComponent: AzureModelsComponent | undefined;
|
||||
@@ -40,7 +40,11 @@ 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 CurrentModelsComponent(this._apiWrapper, this, this._multiSelect);
|
||||
this.registeredModelsComponent = new CurrentModelsComponent(this._apiWrapper, this, {
|
||||
selectable: true,
|
||||
multiSelect: this._multiSelect,
|
||||
editable: false
|
||||
});
|
||||
this.registeredModelsComponent.registerComponent(modelBuilder);
|
||||
this.refresh();
|
||||
this._form = this._formBuilder.component();
|
||||
@@ -96,12 +100,12 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
|
||||
private loadTitle(): void {
|
||||
if (this.modelSourceType === ModelSourceType.Local) {
|
||||
this._title = 'Upload model file';
|
||||
this._title = constants.localModelPageTitle;
|
||||
} else if (this.modelSourceType === ModelSourceType.Azure) {
|
||||
this._title = 'Import from Azure Machine Learning';
|
||||
this._title = constants.azureModelPageTitle;
|
||||
|
||||
} else if (this.modelSourceType === ModelSourceType.RegisteredModels) {
|
||||
this._title = 'Select imported model';
|
||||
this._title = constants.importedModelsPageTitle;
|
||||
} else {
|
||||
this._title = constants.modelSourcePageTitle;
|
||||
}
|
||||
@@ -111,6 +115,7 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
* Returns page title
|
||||
*/
|
||||
public get title(): string {
|
||||
this.loadTitle();
|
||||
return this._title;
|
||||
}
|
||||
|
||||
@@ -144,7 +149,7 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
return {
|
||||
modelData: x,
|
||||
modelDetails: {
|
||||
title: fileName,
|
||||
modelName: fileName,
|
||||
fileName: fileName
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
@@ -164,8 +169,11 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
model: x.model
|
||||
},
|
||||
modelDetails: {
|
||||
title: x.model?.name || '',
|
||||
fileName: x.model?.name
|
||||
modelName: x.model?.name || '',
|
||||
fileName: x.model?.name,
|
||||
framework: x.model?.framework,
|
||||
frameworkVersion: x.model?.frameworkVersion,
|
||||
created: x.model?.createdTime
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
};
|
||||
@@ -178,7 +186,7 @@ export class ModelBrowsePage extends ModelViewBase implements IPageView, IDataCo
|
||||
return {
|
||||
modelData: x,
|
||||
modelDetails: {
|
||||
title: ''
|
||||
modelName: ''
|
||||
},
|
||||
targetImportTable: this.importTable
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ModelViewBase, ModelViewData } from './modelViewBase';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import * as constants from '../../common/constants';
|
||||
import { IPageView, IDataComponent } from '../interfaces';
|
||||
import { ModelDetailsComponent } from './modelDetailsComponent';
|
||||
import { ModelsDetailsTableComponent } from './modelsDetailsTableComponent';
|
||||
|
||||
/**
|
||||
* View to pick model details
|
||||
@@ -17,7 +17,7 @@ export class ModelDetailsPage extends ModelViewBase implements IPageView, IDataC
|
||||
|
||||
private _form: azdata.FormContainer | undefined;
|
||||
private _formBuilder: azdata.FormBuilder | undefined;
|
||||
public modelDetails: ModelDetailsComponent | undefined;
|
||||
public modelDetails: ModelsDetailsTableComponent | undefined;
|
||||
|
||||
constructor(apiWrapper: ApiWrapper, parent: ModelViewBase) {
|
||||
super(apiWrapper, parent.root, parent);
|
||||
@@ -30,7 +30,7 @@ export class ModelDetailsPage extends ModelViewBase implements IPageView, IDataC
|
||||
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
|
||||
this._formBuilder = modelBuilder.formContainer();
|
||||
this.modelDetails = new ModelDetailsComponent(this._apiWrapper, modelBuilder, this);
|
||||
this.modelDetails = new ModelsDetailsTableComponent(this._apiWrapper, modelBuilder, this);
|
||||
this.modelDetails.registerComponent(modelBuilder);
|
||||
this.modelDetails.addComponents(this._formBuilder);
|
||||
this.refresh();
|
||||
@@ -73,7 +73,7 @@ export class ModelDetailsPage extends ModelViewBase implements IPageView, IDataC
|
||||
}
|
||||
|
||||
public validate(): Promise<boolean> {
|
||||
if (this.data && this.data.length > 0 && !this.data.find(x => !x.modelDetails?.title)) {
|
||||
if (this.data && this.data.length > 0 && !this.data.find(x => !x.modelDetails?.modelName)) {
|
||||
return Promise.resolve(true);
|
||||
} else {
|
||||
this.showErrorMessage(constants.modelNameRequiredError);
|
||||
|
||||
@@ -9,7 +9,7 @@ import { azureResource } from '../../typings/azure-resource';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import { AzureModelRegistryService } from '../../modelManagement/azureModelRegistryService';
|
||||
import { Workspace } from '@azure/arm-machinelearningservices/esm/models';
|
||||
import { RegisteredModel, WorkspaceModel, ModelParameters } from '../../modelManagement/interfaces';
|
||||
import { ImportedModel, WorkspaceModel, ModelParameters } from '../../modelManagement/interfaces';
|
||||
import { PredictParameters, DatabaseTable, TableColumn } from '../../prediction/interfaces';
|
||||
import { DeployedModelService } from '../../modelManagement/deployedModelService';
|
||||
import { ManageModelsDialog } from './manageModels/manageModelsDialog';
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
AzureResourceEventArgs, ListAzureModelsEventName, ListSubscriptionsEventName, ListModelsEventName, ListWorkspacesEventName,
|
||||
ListGroupsEventName, ListAccountsEventName, RegisterLocalModelEventName, RegisterAzureModelEventName,
|
||||
ModelViewBase, SourceModelSelectedEventName, RegisterModelEventName, DownloadAzureModelEventName,
|
||||
ListDatabaseNamesEventName, ListTableNamesEventName, ListColumnNamesEventName, PredictModelEventName, PredictModelEventArgs, DownloadRegisteredModelEventName, LoadModelParametersEventName, ModelSourceType, ModelViewData, StoreImportTableEventName, VerifyImportTableEventName
|
||||
ListDatabaseNamesEventName, ListTableNamesEventName, ListColumnNamesEventName, PredictModelEventName, PredictModelEventArgs, DownloadRegisteredModelEventName, LoadModelParametersEventName, ModelSourceType, ModelViewData, StoreImportTableEventName, VerifyImportTableEventName, EditModelEventName, UpdateModelEventName, DeleteModelEventName, SignInToAzureEventName
|
||||
} from './modelViewBase';
|
||||
import { ControllerBase } from '../controllerBase';
|
||||
import { ImportModelWizard } from './manageModels/importModelWizard';
|
||||
@@ -26,6 +26,7 @@ import * as constants from '../../common/constants';
|
||||
import { PredictWizard } from './prediction/predictWizard';
|
||||
import { AzureModelResource } from '../interfaces';
|
||||
import { PredictService } from '../../prediction/predictService';
|
||||
import { EditModelDialog } from './manageModels/editModelDialog';
|
||||
|
||||
/**
|
||||
* Model management UI controller
|
||||
@@ -71,6 +72,24 @@ export class ModelManagementController extends ControllerBase {
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the dialog to edit model
|
||||
*/
|
||||
public async editModel(model: ImportedModel, parent?: ModelViewBase, controller?: ModelManagementController, apiWrapper?: ApiWrapper, root?: string): Promise<ModelViewBase> {
|
||||
controller = controller || this;
|
||||
apiWrapper = apiWrapper || this._apiWrapper;
|
||||
root = root || this._root;
|
||||
let view = new EditModelDialog(apiWrapper, root, parent, model);
|
||||
|
||||
controller.registerEvents(view);
|
||||
|
||||
// Open view
|
||||
//
|
||||
await view.open();
|
||||
await view.refresh();
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the wizard for prediction
|
||||
*/
|
||||
@@ -136,6 +155,18 @@ export class ModelManagementController extends ControllerBase {
|
||||
const importTable = <DatabaseTable>args;
|
||||
await this.executeAction(view, RegisterModelEventName, this.registerModel, importTable, view, this, this._apiWrapper, this._root);
|
||||
});
|
||||
view.on(EditModelEventName, async (args) => {
|
||||
const model = <ImportedModel>args;
|
||||
await this.executeAction(view, EditModelEventName, this.editModel, model, view, this, this._apiWrapper, this._root);
|
||||
});
|
||||
view.on(UpdateModelEventName, async (args) => {
|
||||
const model = <ImportedModel>args;
|
||||
await this.executeAction(view, UpdateModelEventName, this.updateModel, this._registeredModelService, model);
|
||||
});
|
||||
view.on(DeleteModelEventName, async (args) => {
|
||||
const model = <ImportedModel>args;
|
||||
await this.executeAction(view, DeleteModelEventName, this.deleteModel, this._registeredModelService, model);
|
||||
});
|
||||
view.on(RegisterAzureModelEventName, async (arg) => {
|
||||
let models = <ModelViewData[]>arg;
|
||||
await this.executeAction(view, RegisterAzureModelEventName, this.registerAzureModel, this._amlService, this._registeredModelService,
|
||||
@@ -164,7 +195,7 @@ export class ModelManagementController extends ControllerBase {
|
||||
predictArgs, predictArgs.model, predictArgs.filePath);
|
||||
});
|
||||
view.on(DownloadRegisteredModelEventName, async (arg) => {
|
||||
let model = <RegisteredModel>arg;
|
||||
let model = <ImportedModel>arg;
|
||||
await this.executeAction(view, DownloadRegisteredModelEventName, this.downloadRegisteredModel, this._registeredModelService,
|
||||
model);
|
||||
});
|
||||
@@ -178,9 +209,13 @@ export class ModelManagementController extends ControllerBase {
|
||||
await this.executeAction(view, VerifyImportTableEventName, this.verifyImportTable, this._registeredModelService,
|
||||
importTable);
|
||||
});
|
||||
view.on(SourceModelSelectedEventName, (arg) => {
|
||||
view.on(SourceModelSelectedEventName, async (arg) => {
|
||||
view.modelSourceType = <ModelSourceType>arg;
|
||||
view.refresh();
|
||||
await view.refresh();
|
||||
});
|
||||
view.on(SignInToAzureEventName, async () => {
|
||||
await this.executeAction(view, SignInToAzureEventName, this.signInToAzure, this._amlService);
|
||||
await view.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -206,6 +241,10 @@ export class ModelManagementController extends ControllerBase {
|
||||
return view;
|
||||
}
|
||||
|
||||
private async signInToAzure(service: AzureModelRegistryService): Promise<void> {
|
||||
return await service.signInToAzure();
|
||||
}
|
||||
|
||||
private async getAzureAccounts(service: AzureModelRegistryService): Promise<azdata.Account[]> {
|
||||
return await service.getAccounts();
|
||||
}
|
||||
@@ -225,7 +264,7 @@ export class ModelManagementController extends ControllerBase {
|
||||
return await service.getWorkspaces(account, subscription, group);
|
||||
}
|
||||
|
||||
private async getRegisteredModels(registeredModelService: DeployedModelService, table: DatabaseTable): Promise<RegisteredModel[]> {
|
||||
private async getRegisteredModels(registeredModelService: DeployedModelService, table: DatabaseTable): Promise<ImportedModel[]> {
|
||||
return registeredModelService.getDeployedModels(table);
|
||||
}
|
||||
|
||||
@@ -258,6 +297,22 @@ export class ModelManagementController extends ControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateModel(service: DeployedModelService, model: ImportedModel | undefined): Promise<void> {
|
||||
if (model) {
|
||||
await service.updateModel(model);
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteModel(service: DeployedModelService, model: ImportedModel | undefined): Promise<void> {
|
||||
if (model) {
|
||||
await service.deleteModel(model);
|
||||
} else {
|
||||
throw Error(constants.invalidModelToRegisterError);
|
||||
}
|
||||
}
|
||||
|
||||
private async registerAzureModel(
|
||||
azureService: AzureModelRegistryService,
|
||||
service: DeployedModelService,
|
||||
@@ -306,7 +361,7 @@ export class ModelManagementController extends ControllerBase {
|
||||
private async generatePredictScript(
|
||||
predictService: PredictService,
|
||||
predictParams: PredictParameters,
|
||||
registeredModel: RegisteredModel | undefined,
|
||||
registeredModel: ImportedModel | undefined,
|
||||
filePath: string | undefined
|
||||
): Promise<string> {
|
||||
if (!predictParams) {
|
||||
@@ -334,7 +389,7 @@ export class ModelManagementController extends ControllerBase {
|
||||
|
||||
private async downloadRegisteredModel(
|
||||
registeredModelService: DeployedModelService,
|
||||
model: RegisteredModel | undefined): Promise<string> {
|
||||
model: ImportedModel | undefined): Promise<string> {
|
||||
if (!model) {
|
||||
throw Error(constants.invalidModelToPredictError);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as azdata from 'azdata';
|
||||
import { azureResource } from '../../typings/azure-resource';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import { ViewBase } from '../viewBase';
|
||||
import { RegisteredModel, WorkspaceModel, RegisteredModelDetails, ModelParameters } from '../../modelManagement/interfaces';
|
||||
import { ImportedModel, WorkspaceModel, ImportedModelDetails, ModelParameters } from '../../modelManagement/interfaces';
|
||||
import { PredictParameters, DatabaseTable, TableColumn } from '../../prediction/interfaces';
|
||||
import { Workspace } from '@azure/arm-machinelearningservices/esm/models';
|
||||
import { AzureWorkspaceResource, AzureModelResource } from '../interfaces';
|
||||
@@ -18,11 +18,11 @@ export interface AzureResourceEventArgs extends AzureWorkspaceResource {
|
||||
}
|
||||
|
||||
export interface RegisterModelEventArgs extends AzureWorkspaceResource {
|
||||
details?: RegisteredModelDetails
|
||||
details?: ImportedModelDetails
|
||||
}
|
||||
|
||||
export interface PredictModelEventArgs extends PredictParameters {
|
||||
model?: RegisteredModel;
|
||||
model?: ImportedModel;
|
||||
filePath?: string;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ export enum ModelSourceType {
|
||||
|
||||
export interface ModelViewData {
|
||||
modelFile?: string;
|
||||
modelData: AzureModelResource | string | RegisteredModel;
|
||||
modelDetails?: RegisteredModelDetails;
|
||||
modelData: AzureModelResource | string | ImportedModel;
|
||||
modelDetails?: ImportedModelDetails;
|
||||
targetImportTable?: DatabaseTable;
|
||||
}
|
||||
|
||||
@@ -57,10 +57,14 @@ export const DownloadAzureModelEventName = 'downloadAzureLocalModel';
|
||||
export const DownloadRegisteredModelEventName = 'downloadRegisteredModel';
|
||||
export const PredictModelEventName = 'predictModel';
|
||||
export const RegisterModelEventName = 'registerModel';
|
||||
export const EditModelEventName = 'editModel';
|
||||
export const UpdateModelEventName = 'updateModel';
|
||||
export const DeleteModelEventName = 'deleteModel';
|
||||
export const SourceModelSelectedEventName = 'sourceModelSelected';
|
||||
export const LoadModelParametersEventName = 'loadModelParameters';
|
||||
export const StoreImportTableEventName = 'storeImportTable';
|
||||
export const VerifyImportTableEventName = 'verifyImportTable';
|
||||
export const SignInToAzureEventName = 'signInToAzure';
|
||||
|
||||
/**
|
||||
* Base class for all model management views
|
||||
@@ -94,7 +98,11 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
DownloadRegisteredModelEventName,
|
||||
LoadModelParametersEventName,
|
||||
StoreImportTableEventName,
|
||||
VerifyImportTableEventName]);
|
||||
VerifyImportTableEventName,
|
||||
EditModelEventName,
|
||||
UpdateModelEventName,
|
||||
DeleteModelEventName,
|
||||
SignInToAzureEventName]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +123,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
/**
|
||||
* list registered models
|
||||
*/
|
||||
public async listModels(table: DatabaseTable): Promise<RegisteredModel[]> {
|
||||
public async listModels(table: DatabaseTable): Promise<ImportedModel[]> {
|
||||
return await this.sendDataRequest(ListModelsEventName, table);
|
||||
}
|
||||
|
||||
@@ -170,7 +178,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
* downloads registered model
|
||||
* @param model model to download
|
||||
*/
|
||||
public async downloadRegisteredModel(model: RegisteredModel | undefined): Promise<string> {
|
||||
public async downloadRegisteredModel(model: ImportedModel | undefined): Promise<string> {
|
||||
return await this.sendDataRequest(DownloadRegisteredModelEventName, model);
|
||||
}
|
||||
|
||||
@@ -215,7 +223,7 @@ export abstract class ModelViewBase extends ViewBase {
|
||||
* registers azure model
|
||||
* @param args azure resource
|
||||
*/
|
||||
public async generatePredictScript(model: RegisteredModel | undefined, filePath: string | undefined, params: PredictParameters | undefined): Promise<void> {
|
||||
public async generatePredictScript(model: ImportedModel | undefined, filePath: string | undefined, params: PredictParameters | undefined): Promise<void> {
|
||||
const args: PredictModelEventArgs = Object.assign({}, params, {
|
||||
model: model,
|
||||
filePath: filePath,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IDataComponent } from '../interfaces';
|
||||
/**
|
||||
* View to pick local models file
|
||||
*/
|
||||
export class ModelDetailsComponent extends ModelViewBase implements IDataComponent<ModelViewData[]> {
|
||||
export class ModelsDetailsTableComponent extends ModelViewBase implements IDataComponent<ModelViewData[]> {
|
||||
private _table: azdata.DeclarativeTableComponent | undefined;
|
||||
|
||||
/**
|
||||
@@ -127,7 +127,7 @@ export class ModelDetailsComponent extends ModelViewBase implements IDataCompone
|
||||
private createTableRow(model: ModelViewData | undefined): any[] {
|
||||
if (this._modelBuilder && model && model.modelDetails) {
|
||||
const nameComponent = this._modelBuilder.inputBox().withProperties({
|
||||
value: model.modelDetails.title,
|
||||
value: model.modelDetails.modelName,
|
||||
width: this.componentMaxLength - 100,
|
||||
required: true
|
||||
}).component();
|
||||
@@ -142,7 +142,7 @@ export class ModelDetailsComponent extends ModelViewBase implements IDataCompone
|
||||
});
|
||||
nameComponent.onTextChanged(() => {
|
||||
if (model.modelDetails) {
|
||||
model.modelDetails.title = nameComponent.value || '';
|
||||
model.modelDetails.modelName = nameComponent.value || '';
|
||||
}
|
||||
});
|
||||
let deleteButton = this._modelBuilder.button().withProperties({
|
||||
@@ -13,7 +13,7 @@ import * as constants from '../../../common/constants';
|
||||
import { WizardView } from '../../wizardView';
|
||||
import { ModelSourcePage } from '../modelSourcePage';
|
||||
import { ColumnsSelectionPage } from './columnsSelectionPage';
|
||||
import { RegisteredModel } from '../../../modelManagement/interfaces';
|
||||
import { ImportedModel } from '../../../modelManagement/interfaces';
|
||||
import { ModelArtifact } from './modelArtifact';
|
||||
import { ModelBrowsePage } from '../modelBrowsePage';
|
||||
|
||||
@@ -124,7 +124,7 @@ export class PredictWizard extends ModelViewBase {
|
||||
private async predict(): Promise<boolean> {
|
||||
try {
|
||||
let modelFilePath: string | undefined;
|
||||
let registeredModel: RegisteredModel | undefined = undefined;
|
||||
let registeredModel: ImportedModel | undefined = undefined;
|
||||
if (this.modelResources && this.modelResources.data && this.modelResources.data === ModelSourceType.RegisteredModels
|
||||
&& this.modelBrowsePage && this.modelBrowsePage.registeredModelsComponent) {
|
||||
const data = this.modelBrowsePage?.registeredModelsComponent?.data;
|
||||
|
||||
@@ -168,7 +168,7 @@ export class TableSelectionComponent extends ModelViewBase implements IDataCompo
|
||||
this._selectedTableName = this.getTableFullName(selectedTable);
|
||||
this._tables.value = this.getTableFullName(selectedTable);
|
||||
} else {
|
||||
this._selectedTableName = this.getTableFullName(this._tableNames[0]);
|
||||
this._selectedTableName = this._editable ? this.getTableFullName(this.importTable) : this.getTableFullName(this._tableNames[0]);
|
||||
}
|
||||
} else {
|
||||
this._selectedTableName = this.getTableFullName(this._tableNames[0]);
|
||||
|
||||
@@ -35,13 +35,14 @@ export class WizardView extends MainViewBase {
|
||||
*/
|
||||
public addWizardPage(page: IPageView, index: number): void {
|
||||
if (this._wizard) {
|
||||
this.addPage(page, index);
|
||||
this._wizard.removePage(index);
|
||||
if (!page.viewPanel) {
|
||||
const currentPage = this._wizard.currentPage;
|
||||
if (page && currentPage < index) {
|
||||
this.addPage(page, index);
|
||||
this._wizard.removePage(index);
|
||||
this.createWizardPage(page.title || '', page);
|
||||
this._wizard.addPage(<azdata.window.WizardPage>page.viewPanel, index);
|
||||
this._wizard.setCurrentPage(currentPage);
|
||||
}
|
||||
this._wizard.addPage(<azdata.window.WizardPage>page.viewPanel, index);
|
||||
this._wizard.setCurrentPage(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,4 +110,14 @@ export class WizardView extends MainViewBase {
|
||||
public get wizard(): azdata.window.Wizard | undefined {
|
||||
return this._wizard;
|
||||
}
|
||||
|
||||
public async refresh(): Promise<void> {
|
||||
for (let index = 0; index < this._pages.length; index++) {
|
||||
const page = this._pages[index];
|
||||
if (this._wizard?.pages[index]?.title !== page.title) {
|
||||
this.addWizardPage(page, index);
|
||||
}
|
||||
}
|
||||
await super.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user