Skip to content

Commit

Permalink
feat: track five most recent project models (#395)
Browse files Browse the repository at this point in the history
* feat: track most recent 5 models for project

* refactor: set recent model records count in constants

* style: remove empty line whitespaces

* style: remove eol whitespaces
  • Loading branch information
stew-ro authored Jul 9, 2020
1 parent abc6376 commit 0585060
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const constants = {
convertedImageFormat: "image/jpeg",
convertedImageQuality: 0.7,
convertedThumbnailQuality: 0.2,

recentModelRecordsCount: 5,
apiModelsPath: `/formrecognizer/${apiVersion}/custom/models`,

pdfjsWorkerSrc(version: string) {
Expand Down
1 change: 1 addition & 0 deletions src/common/mockFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export default class MockFactory {
apiUriBase: "localhost",
folderPath: "",
trainRecord: null,
recentModelRecords: [],
predictModelId: "",
};
}
Expand Down
13 changes: 13 additions & 0 deletions src/models/applicationState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export interface IProject {
apiKey?: string | ISecureString;
folderPath: string;
trainRecord: ITrainRecordProps;
recentModelRecords: IRecentModel[];
predictModelId: string;
}

Expand Down Expand Up @@ -281,6 +282,18 @@ export interface IFieldInfo {
fields: IField[];
}

export interface IRecentModel {
readonly composedTrainResults?: object;
readonly accuracies?: object;
readonly averageAccuracy?: number;
readonly modelInfo: {
readonly isComposed: boolean;
readonly modelId: string;
readonly createdDateTime: string;
readonly modelName: string;
};
}

/**
* Enum of supported error codes
*/
Expand Down
49 changes: 29 additions & 20 deletions src/react/components/pages/modelCompose/modelCompose.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from "react";
import {connect} from "react-redux";
import url from "url";
import { RouteComponentProps } from "react-router-dom";
import { IProject, IConnection, IAppSettings, IApplicationState, AppError, ErrorCode } from "../../../../models/applicationState";
import { IProject, IConnection, IAppSettings, IApplicationState, AppError, ErrorCode, IRecentModel } from "../../../../models/applicationState";
import { constants } from "../../../../common/constants";
import ServiceHelper from "../../../../services/serviceHelper";
import { IColumn,
Expand Down Expand Up @@ -341,10 +341,8 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
const composedModels = this.reloadComposedModel(this.state.composedModelList);

let composedModelIds = [];
let predictModelFlag = false;
if (this.state.composeModelId.length !== 0) {
composedModelIds = this.getComposedIds();
predictModelFlag = true;
if (composedModelIds.indexOf(this.state.composeModelId[0]) === -1) {
const idURL = constants.apiModelsPath + "/" + this.state.composeModelId[0];
composedModels.push(await this.getComposeModelByURl(idURL));
Expand All @@ -359,10 +357,6 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
models = models.filter((m) => composedModelIds.indexOf(m.modelId) === -1);

this.allModels = composedModels.concat(models);
if (predictModelFlag) {
const updatedProject = this.buildUpdatedProject(this.state.composeModelId[0]);
await this.props.actions.saveProject(updatedProject, false, false);
}
this.setState({
modelList: this.allModels,
nextLink: link,
Expand All @@ -377,10 +371,27 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
}
}

private buildUpdatedProject = (modelId: string): IProject => {
private buildUpdatedProject = (composedModel: object): IProject => {
const newTrainRecord = {
modelInfo: {
createdDateTime: composedModel["modelInfo"]["createdDateTime"],
modelId: composedModel["modelInfo"]["modelId"],
modelName: composedModel["modelInfo"]["modelName"],
isComposed: true,
},
composedTrainResults: composedModel["composedTrainResults"]
} as IRecentModel;
const recentModelRecords: IRecentModel[] = this.props.project.recentModelRecords ?
[...this.props.project.recentModelRecords] : [];
recentModelRecords.unshift(newTrainRecord);
if (recentModelRecords.length > constants.recentModelRecordsCount) {
recentModelRecords.pop();
}

return {
...this.props.project,
predictModelId: modelId,
recentModelRecords,
predictModelId: newTrainRecord.modelInfo.modelId,
};
}

Expand All @@ -399,7 +410,7 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
private getComposeModelByURl = async (idURL) => {
const composedRes = await this.getResponse(idURL);
const composedModel: IModel = composedRes.data.modelInfo;
composedModel.iconName = "combine";
composedModel.iconName = "Combine";
composedModel.key = composedModel.modelId;
return composedModel;
}
Expand Down Expand Up @@ -632,18 +643,23 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
modelIds: idList,
modelName: name,
};

const link = constants.apiModelsPath + "/compose";
const composeRes = await this.post(link, payload);
await this.waitUntilModelIsReady(composeRes["headers"]["location"]);
const composedModelId = this.getComposeModelId(composeRes);
const composedModel = await this.waitUntilModelIsReady(composeRes["headers"]["location"]);

const updatedProject = this.buildUpdatedProject(composedModel);
await this.props.actions.saveProject(updatedProject, false, false);

const newCols = this.state.columns;
newCols.forEach((ncol) => {
ncol.isSorted = false;
ncol.isSortedDescending = true;
});

this.setState({
isComposing: false,
composeModelId: [composedModelId],
composeModelId: [composedModel["modelInfo"]["modelId"]],
columns: newCols,
});
} catch (error) {
Expand All @@ -655,13 +671,6 @@ export default class ModelComposePage extends React.Component<IModelComposePageP
}, 5000);
}

/** get the model Id of new composed model */
private getComposeModelId = (composeRes: any): string => {
const location = composeRes["headers"]["location"];
const splitGroup = location.split("/");
return splitGroup[splitGroup.length - 1];
}

private async post(link, payload): Promise<any> {
const baseURL = url.resolve(
this.props.project.apiUriBase,
Expand Down
11 changes: 10 additions & 1 deletion src/react/components/pages/train/trainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import IProjectActions, * as projectActions from "../../../../redux/actions/proj
import IApplicationActions, * as applicationActions from "../../../../redux/actions/applicationActions";
import IAppTitleActions, * as appTitleActions from "../../../../redux/actions/appTitleActions";
import {
IApplicationState, IConnection, IProject, IAppSettings, FieldType,
IApplicationState, IConnection, IProject, IAppSettings, FieldType, IRecentModel,
} from "../../../../models/applicationState";
import TrainChart from "./trainChart";
import TrainPanel from "./trainPanel";
Expand Down Expand Up @@ -327,8 +327,16 @@ export default class TrainPage extends React.Component<ITrainPageProps, ITrainPa
}

private buildUpdatedProject = (newTrainRecord: ITrainRecordProps): IProject => {
const recentModelRecords: IRecentModel[] = this.props.project.recentModelRecords ?
[...this.props.project.recentModelRecords] : [];
recentModelRecords.unshift({...newTrainRecord, isComposed: false} as IRecentModel);
if (recentModelRecords.length > constants.recentModelRecordsCount) {
recentModelRecords.pop();
}

return {
...this.props.project,
recentModelRecords,
trainRecord: newTrainRecord,
predictModelId: newTrainRecord.modelInfo.modelId,
};
Expand Down Expand Up @@ -356,6 +364,7 @@ export default class TrainPage extends React.Component<ITrainPageProps, ITrainPa
modelId: response["modelInfo"]["modelId"],
createdDateTime: response["modelInfo"]["createdDateTime"],
modelName: response["modelInfo"]["modelName"],
isComposed: false,
},
averageAccuracy: response["trainResult"]["averageModelAccuracy"],
accuracies: this.buildAccuracies(response["trainResult"]["fields"]),
Expand Down
13 changes: 9 additions & 4 deletions src/react/components/pages/train/trainRecord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ITrainRecordProps {
accuracies?: object;
averageAccuracy: number;
modelInfo: {
isComposed?: boolean;
modelId: string;
createdDateTime: string;
modelName: string;
Expand All @@ -26,10 +27,14 @@ export default class TrainRecord extends React.Component<ITrainRecordProps, ITra
<p>
{this.props.modelInfo.modelId}
</p>
<h6> Model Name: </h6>
<p>
{this.props.modelInfo.modelName}
</p>
{this.props.modelInfo.modelName &&
[
<h6> Model Name: </h6>,
<p>
{this.props.modelInfo.modelName}
</p>
]
}
<h6> Created date and time: </h6>
<p>
{new Date(this.props.modelInfo.createdDateTime).toLocaleString()}
Expand Down

0 comments on commit 0585060

Please sign in to comment.