ML extension - Improving predict parameter mapping experience (#10264)

This commit is contained in:
Leila Lali
2020-05-10 18:10:17 -07:00
committed by GitHub
parent f6e7b56946
commit 3d2d791f18
44 changed files with 782 additions and 388 deletions

View File

@@ -74,6 +74,18 @@ export class ColumnsSelectionPage extends ModelViewBase implements IPageView, ID
}
}
public async validate(): Promise<boolean> {
const data = this.data;
const validated = data !== undefined && data.databaseName !== undefined && data.inputColumns !== undefined && data.outputColumns !== undefined
&& data.tableName !== undefined && data.databaseName !== constants.selectDatabaseTitle && data.tableName !== constants.selectTableTitle
&& !data.inputColumns.find(x => x.columnName === constants.selectColumnTitle);
if (!validated) {
this.showErrorMessage(constants.invalidModelParametersError);
}
return Promise.resolve(validated);
}
public async onEnter(): Promise<void> {
await this.inputColumnsComponent?.onLoading();
await this.outputColumnsComponent?.onLoading();

View File

@@ -173,7 +173,12 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
if (this._table) {
if (this._forInput) {
const columns = await this.listColumnNames(table);
let columns: TableColumn[];
try {
columns = await this.listColumnNames(table);
} catch {
columns = [];
}
if (modelParameters?.inputs && columns) {
tableData = tableData.concat(modelParameters.inputs.map(input => this.createInputTableRow(input, columns)));
}
@@ -212,6 +217,10 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
const dataType = dataTypes.find(x => x === modelParameter.type);
if (dataType) {
nameInput.value = dataType;
} else {
// Output type not supported
//
modelParameter.type = dataTypes[0];
}
this._parameters.push({ columnName: name, paramName: name, dataType: modelParameter.type });
@@ -234,7 +243,7 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
selectedRow.columnName = displayNameInput.value || name;
}
});
return [`${name}(${modelParameter.type ? modelParameter.type : constants.unsupportedModelParameterType})`, displayNameInput, nameInput];
return [`${name}(${modelParameter.originalType ? modelParameter.originalType : constants.unsupportedModelParameterType})`, displayNameInput, nameInput];
}
return [];
@@ -242,7 +251,11 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
private createInputTableRow(modelParameter: ModelParameter, columns: TableColumn[] | undefined): any[] {
if (this._modelBuilder && columns) {
const values = columns.map(c => { return { name: c.columnName, displayName: `${c.columnName}(${c.dataType})` }; });
let values = columns.map(c => { return { name: c.columnName, displayName: `${c.columnName}(${c.dataType})` }; });
if (columns.length > 0 && columns[0].columnName !== constants.selectColumnTitle) {
values = [{ displayName: constants.selectColumnTitle, name: '' }].concat(values);
}
let nameInput = this._modelBuilder.dropDown().withProperties({
values: values,
width: this.componentMaxLength
@@ -250,11 +263,28 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
const name = modelParameter.name;
let column = values.find(x => x.name === modelParameter.name);
if (!column) {
column = values[0];
column = values.length > 0 ? values[0] : undefined;
}
const currentColumn = columns.find(x => x.columnName === column?.name);
nameInput.value = column;
this._parameters.push({ columnName: column.name, paramName: name });
if (column) {
this._parameters.push({ columnName: column.name, paramName: name, paramType: modelParameter.type });
}
const inputContainer = this._modelBuilder.flexContainer().withLayout({
flexFlow: 'row',
width: this.componentMaxLength + 20,
justifyContent: 'flex-start'
}).component();
const warningButton = this.createWarningButton();
warningButton.onDidClick(() => {
});
const css = {
'padding-top': '5px',
'padding-right': '5px',
'margin': '0px'
};
nameInput.onValueChanged(() => {
const selectedColumn = nameInput.value;
@@ -264,12 +294,36 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
if (selectedRow) {
selectedRow.columnName = value || '';
}
const currentColumn = columns.find(x => x.columnName === value);
if (currentColumn && modelParameter.type === currentColumn?.dataType) {
inputContainer.removeItem(warningButton);
} else {
inputContainer.addItem(warningButton, {
CSSStyles: css
});
}
});
const label = this._modelBuilder.inputBox().withProperties({
value: `${name}(${modelParameter.type ? modelParameter.type : constants.unsupportedModelParameterType})`,
value: `${name}(${modelParameter.originalType ? modelParameter.originalType : constants.unsupportedModelParameterType})`,
enabled: false,
width: this.componentMaxLength
}).component();
inputContainer.addItem(label, {
CSSStyles: {
'padding': '0px',
'padding-right': '5px',
'margin': '0px'
}
});
if (currentColumn && modelParameter.type !== currentColumn?.dataType) {
inputContainer.addItem(warningButton, {
CSSStyles: css
});
}
const image = this._modelBuilder.image().withProperties({
width: 50,
height: 50,
@@ -281,12 +335,28 @@ export class ColumnsTable extends ModelViewBase implements IDataComponent<Predic
iconHeight: 20,
title: 'maps'
}).component();
return [nameInput, image, label];
return [nameInput, image, inputContainer];
}
return [];
}
private createWarningButton(): azdata.ButtonComponent {
const warningButton = this._modelBuilder.button().withProperties({
width: '10px',
height: '10px',
title: constants.columnDataTypeMismatchWarning,
iconPath: {
dark: this.asAbsolutePath('images/dark/warning_notification_inverse.svg'),
light: this.asAbsolutePath('images/light/warning_notification.svg'),
},
iconHeight: '10px',
iconWidth: '10px'
}).component();
return warningButton;
}
/**
* Returns selected data
*/

View File

@@ -35,8 +35,8 @@ export class InputColumnsComponent extends ModelViewBase implements IDataCompone
* @param modelBuilder model builder
*/
public registerComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
this._tableSelectionComponent = new TableSelectionComponent(this._apiWrapper, this, false);
this._tableSelectionComponent.registerComponent(modelBuilder);
this._tableSelectionComponent = new TableSelectionComponent(this._apiWrapper, this, { editable: false, preSelected: false });
this._tableSelectionComponent.registerComponent(modelBuilder, constants.columnDatabase, constants.columnTable);
this._tableSelectionComponent.onSelectedChanged(async () => {
await this.onTableSelected();
});

View File

@@ -62,7 +62,7 @@ export class PredictWizard extends ModelViewBase {
});
wizard.registerNavigationValidator(async (pageInfo: azdata.window.WizardPageChangeInfo) => {
let validated: boolean = true;
if (pageInfo.newPage > pageInfo.lastPage) {
if (pageInfo.newPage === undefined || pageInfo.newPage > pageInfo.lastPage) {
validated = this.wizardView ? await this.wizardView.validate(pageInfo) : false;
}
if (validated) {
@@ -94,7 +94,7 @@ export class PredictWizard extends ModelViewBase {
private refreshButtons(loading: boolean): void {
if (this.wizardView && this.wizardView.wizard) {
this.wizardView.wizard.cancelButton.enabled = !loading;
this.wizardView.wizard.cancelButton.enabled = !loading;
this.wizardView.wizard.backButton.enabled = !loading;
}
}