From 6057f1b8602262330db976db5470858b42007a5c Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Tue, 13 Sep 2022 12:03:33 +0000 Subject: [PATCH 1/9] added an option for different styles of model uploads. if user uploads just a model card this will be displayed to users on the corresponding model/deployment pages --- .eslintrc.js | 2 + pages/deployment/[uuid].tsx | 16 +++- pages/model/[uuid].tsx | 9 +- pages/model/[uuid]/new-version.tsx | 4 +- pages/upload.tsx | 4 +- server/models/Version.ts | 9 +- server/routes/v1/upload.ts | 76 +++++++++-------- server/services/deployment.ts | 4 +- src/Form/RenderFileTab.tsx | 129 +++++++++++++++++++++-------- src/RawModelExportList.tsx | 4 +- types/interfaces.ts | 6 ++ 11 files changed, 185 insertions(+), 78 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1faa22a46..934eedabf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,6 +33,8 @@ module.exports = { 'import/no-cycle': [0, { ignoreExternal: true }], '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: false, variables: true }], '@typescript-eslint/no-namespace': ['error', { allowDeclarations: true }], + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': ['error'], // IGNORED RULES '@typescript-eslint/no-var-requires': 'off', 'import/extensions': 'off', diff --git a/pages/deployment/[uuid].tsx b/pages/deployment/[uuid].tsx index 8d7f3b965..d248e0e19 100644 --- a/pages/deployment/[uuid].tsx +++ b/pages/deployment/[uuid].tsx @@ -1,7 +1,9 @@ +import { ObjectId } from 'mongoose' import Info from '@mui/icons-material/Info' import DownArrow from '@mui/icons-material/KeyboardArrowDownTwoTone' import UpArrow from '@mui/icons-material/KeyboardArrowUpTwoTone' import RestartAlt from '@mui/icons-material/RestartAltTwoTone' +import Alert from '@mui/material/Alert' import Button from '@mui/material/Button' import Dialog from '@mui/material/Dialog' import DialogContent from '@mui/material/DialogContent' @@ -39,6 +41,7 @@ import Wrapper from '../../src/Wrapper' import { createDeploymentComplianceFlow } from '../../utils/complianceFlow' import { postEndpoint } from '../../data/api' import RawModelExportList from '../../src/RawModelExportList' +import { VersionDoc } from '../../server/models/Version' const ComplianceFlow = dynamic(() => import('../../src/ComplianceFlow')) @@ -162,6 +165,10 @@ export default function Deployment() { await postEndpoint(`/api/v1/deployment/${deployment?.uuid}/reset-approvals`, {}).then((res) => res.json()) } + const initialVersionRequested: ObjectId | VersionDoc = deployment.versions.filter( + (version: any) => version.version === deployment.metadata.highLevelDetails.initialVersionRequested + )[0] as VersionDoc + return ( <> @@ -186,6 +193,9 @@ export default function Deployment() { > Actions + {initialVersionRequested.modelCardOnly !== undefined && initialVersionRequested.modelCardOnly && ( + This model version was uploaded as just a model card + )} @@ -207,7 +217,11 @@ export default function Deployment() { > - + diff --git a/pages/model/[uuid].tsx b/pages/model/[uuid].tsx index c77d510ea..5633bd329 100644 --- a/pages/model/[uuid].tsx +++ b/pages/model/[uuid].tsx @@ -188,6 +188,9 @@ function Model() { > Actions + {version.modelCardOnly !== undefined && version.modelCardOnly && ( + This model version was uploaded as just a model card + )} @@ -282,7 +285,11 @@ function Model() { > - + diff --git a/pages/model/[uuid]/new-version.tsx b/pages/model/[uuid]/new-version.tsx index dc2a10f71..ffb9bb770 100644 --- a/pages/model/[uuid]/new-version.tsx +++ b/pages/model/[uuid]/new-version.tsx @@ -12,7 +12,7 @@ import ModelExportAndSubmission from '../../../src/Form/ModelExportAndSubmission import { RenderButtonsInterface } from '../../../src/Form/RenderButtons' import SubmissionError from '../../../src/Form/SubmissionError' import Wrapper from '../../../src/Wrapper' -import { SplitSchema } from '../../../types/interfaces' +import { SplitSchema, ModelUploadType } from '../../../types/interfaces' import { createStep, getStepsData, getStepsFromSchema } from '../../../utils/formUtils' import useCacheVariable from '../../../utils/useCacheVariable' @@ -66,6 +66,7 @@ function Upload() { state: { binary: undefined, code: undefined, + uploadType: ModelUploadType.Zip, }, schemaRef: cModel.schemaRef, @@ -137,6 +138,7 @@ function Upload() { form.append('code', data.files.code) form.append('binary', data.files.binary) + form.append('uploadType', data.files.uploadType) delete data.files diff --git a/pages/upload.tsx b/pages/upload.tsx index 19ea8afb0..6c82e88ec 100644 --- a/pages/upload.tsx +++ b/pages/upload.tsx @@ -10,7 +10,7 @@ import RenderFileTab from '@/src/Form/RenderFileTab' import SchemaSelector from '@/src/Form/SchemaSelector' import SubmissionError from '@/src/Form/SubmissionError' import Wrapper from '@/src/Wrapper' -import { Schema, SplitSchema, User } from '@/types/interfaces' +import { Schema, SplitSchema, ModelUploadType, User } from '@/types/interfaces' import { createStep, getStepsData, getStepsFromSchema } from '@/utils/formUtils' import Box from '@mui/material/Box' import Grid from '@mui/material/Grid' @@ -85,6 +85,7 @@ function Upload() { state: { binary: undefined, code: undefined, + uploadType: ModelUploadType.Zip, }, schemaRef: reference, @@ -153,6 +154,7 @@ function Upload() { form.append('code', data.files.code) form.append('binary', data.files.binary) + form.append('uploadType', data.files.uploadType) delete data.files form.append('metadata', JSON.stringify(data)) diff --git a/server/models/Version.ts b/server/models/Version.ts index ce07658a3..01a5f3833 100644 --- a/server/models/Version.ts +++ b/server/models/Version.ts @@ -3,11 +3,6 @@ import logger from '../utils/logger' import { approvalStateOptions, ApprovalStates, LogStatement } from './Deployment' import { ModelDoc } from './Model' -interface FilePaths { - rawBinaryPath: string - rawCodePath: string -} - export interface Version { model: ModelDoc | Types.ObjectId version: string @@ -23,6 +18,8 @@ export interface Version { rawCodePath: string } + modelCardOnly?: boolean + state: any logs: Types.Array @@ -43,6 +40,8 @@ const VersionSchema = new Schema( files: { type: Schema.Types.Mixed, required: true }, + modelCardOnly: { type: Boolean }, + built: { type: Boolean, default: false }, managerApproved: { type: String, required: true, enum: approvalStateOptions, default: 'No Response' }, reviewerApproved: { type: String, required: true, enum: approvalStateOptions, default: 'No Response' }, diff --git a/server/routes/v1/upload.ts b/server/routes/v1/upload.ts index 2d5e30493..463b9c6d2 100644 --- a/server/routes/v1/upload.ts +++ b/server/routes/v1/upload.ts @@ -10,13 +10,14 @@ import { updateDeploymentVersions } from '../../services/deployment' import { createModel, findModelByUuid } from '../../services/model' import { createVersionRequests } from '../../services/request' import { findSchemaByRef } from '../../services/schema' -import { createVersion } from '../../services/version' +import { createVersion, markVersionBuilt } from '../../services/version' import MinioStore from '../../utils/MinioStore' import { getUploadQueue } from '../../utils/queues' import { BadReq, Conflict, GenericError } from '../../utils/result' import { ensureUserRole } from '../../utils/user' import { validateSchema } from '../../utils/validateSchema' import VersionModel from '../../models/Version' +import { ModelUploadType } from '@/types/interfaces' export interface MinioFile { [fieldname: string]: Array @@ -42,16 +43,17 @@ export const postUpload = [ const files = req.files as unknown as MinioFile const mode = req.query.mode as string const modelUuid = req.query.modelUuid as string + const uploadType = req.body.uploadType as ModelUploadType - if (!files.binary) { + if (uploadType === ModelUploadType.Zip && !files.binary) { throw BadReq({ code: 'binary_file_not_found' }, 'Unable to find binary file') } - if (!files.code) { + if (uploadType === ModelUploadType.Zip && !files.code) { throw BadReq({ code: 'code_file_not_found' }, 'Unable to find code file') } - if (!files.binary[0].originalname.toLowerCase().endsWith('.zip')) { + if (uploadType === ModelUploadType.Zip && !files.binary[0].originalname.toLowerCase().endsWith('.zip')) { req.log.warn( { code: 'binary_wrong_file_type', filename: files.binary[0].originalname }, 'Binary is not a zip file' @@ -61,7 +63,7 @@ export const postUpload = [ }) } - if (!files.code[0].originalname.toLowerCase().endsWith('.zip')) { + if (uploadType === ModelUploadType.Zip && !files.code[0].originalname.toLowerCase().endsWith('.zip')) { req.log.warn({ code: 'code_wrong_file_type', filename: files.code[0].originalname }, 'Code is not a zip file') return res.status(400).json({ message: `Unable to process code, file not a zip.`, @@ -178,7 +180,6 @@ export const postUpload = [ await model.save() version.model = model._id - await version.save() req.log.info({ code: 'created_model', model }, 'Created model document') @@ -190,38 +191,47 @@ export const postUpload = [ 'Successfully created requests for reviews' ) - const jobId = await ( - await getUploadQueue() - ).add({ - versionId: version._id, - userId: req.user?._id, - binary: createFileRef(files.binary[0], 'binary', version), - code: createFileRef(files.code[0], 'code', version), - }) + if (uploadType === ModelUploadType.ModelCard) { + version.modelCardOnly = true + await version.save() + await markVersionBuilt(version._id) + } else { + await version.save() + } - req.log.info({ code: 'created_upload_job', jobId }, 'Successfully created job in upload queue') + if (uploadType === ModelUploadType.Zip) { + const jobId = await ( + await getUploadQueue() + ).add({ + versionId: version._id, + userId: req.user?._id, + binary: createFileRef(files.binary[0], 'binary', version), + code: createFileRef(files.code[0], 'code', version), + }) + + req.log.info({ code: 'created_upload_job', jobId }, 'Successfully created job in upload queue') + + try { + const rawBinaryPath = `model/${model._id}/version/${version._id}/raw/binary/${files.binary[0].path}` + const client = getClient() + await copyFile(`${files.binary[0].bucket}/${files.binary[0].path}`, rawBinaryPath) + await client.removeObject(files.binary[0].bucket, files.binary[0].path) + const rawCodePath = `model/${model._id}/version/${version._id}/raw/code/${files.code[0].path}` + await copyFile(`${files.code[0].bucket}/${files.code[0].path}`, rawCodePath) + await client.removeObject(files.code[0].bucket, files.code[0].path) + await VersionModel.findOneAndUpdate({ _id: version._id }, { files: { rawCodePath, rawBinaryPath } }) + req.log.info( + { code: 'adding_file_paths', rawCodePath, rawBinaryPath }, + `Adding paths for raw model exports of files to version.` + ) + } catch (e: any) { + throw GenericError({}, 'Error uploading raw code and binary to Minio', 500) + } + } - // then return reference to user res.json({ uuid: model.uuid, }) - - try { - const rawBinaryPath = `model/${model._id}/version/${version._id}/raw/binary/${files.binary[0].path}` - const client = getClient() - await copyFile(`${files.binary[0].bucket}/${files.binary[0].path}`, rawBinaryPath) - await client.removeObject(files.binary[0].bucket, files.binary[0].path) - const rawCodePath = `model/${model._id}/version/${version._id}/raw/code/${files.code[0].path}` - await copyFile(`${files.code[0].bucket}/${files.code[0].path}`, rawCodePath) - await client.removeObject(files.code[0].bucket, files.code[0].path) - await VersionModel.findOneAndUpdate({ _id: version._id }, { files: { rawCodePath, rawBinaryPath } }) - req.log.info( - { code: 'adding_file_paths', rawCodePath, rawBinaryPath }, - `Adding paths for raw model exports of files to version.` - ) - } catch (e: any) { - throw GenericError({}, 'Error uploading raw code and binary to Minio', 500) - } }) }, ] diff --git a/server/services/deployment.ts b/server/services/deployment.ts index 522e6e4fc..84093bce6 100644 --- a/server/services/deployment.ts +++ b/server/services/deployment.ts @@ -33,9 +33,9 @@ export async function filterDeployment(user: UserDoc, unfiltered: T): Promise return Array.isArray(unfiltered) ? (filtered as unknown as T) : filtered[0] } -export async function findDeploymentByUuid(user: UserDoc, uuid: string, opts?: GetDeploymentOptions) { +export async function findDeploymentByUuid(user: UserDoc, uuid: string, _opts?: GetDeploymentOptions) { let deployment = DeploymentModel.findOne({ uuid }) - if (opts?.populate) deployment = deployment.populate('model') + deployment = deployment.populate('model', ['_id', 'uuid']).populate('versions', ['version', 'modelCardOnly']) return filterDeployment(user, await deployment) } diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 527dd640e..316fa5538 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -1,14 +1,50 @@ import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Divider from '@mui/material/Divider' +import FormControl from '@mui/material/FormControl' import Grid from '@mui/material/Grid' +import InputLabel from '@mui/material/InputLabel' +import MenuItem from '@mui/material/MenuItem' +import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { styled } from '@mui/system' -import { RenderInterface, Step } from '../../types/interfaces' +import React from 'react' +import { RenderInterface, Step, ModelUploadType } from '../../types/interfaces' import { setStepState } from '../../utils/formUtils' import FileInput from '../common/FileInput' +function RenderUploadType({ step, splitSchema, setSplitSchema }: RenderInterface) { + const { state } = step + const { uploadType } = state + + const handleUploadTypeChange = (event) => { + state.code = undefined + state.binary = undefined + setStepState(splitSchema, setSplitSchema, step, { ...state, uploadType: event.target.value }) + } + + return ( + + Upload Type + + + ) +} + export default function RenderFileTab({ step, splitSchema, setSplitSchema }: RenderInterface) { const { state } = step const { binary, code } = state @@ -36,38 +72,57 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } return ( - - - - - - - - - - - + <> + + + + + {state.uploadType === ModelUploadType.Zip && ( + + + + + + + + + + )} + {state.uploadType === ModelUploadType.ModelCard && ( + Uploading a model card without any code or binary files + )} + + ) } export function FileTabComplete(step: Step) { - return step.state.binary && step.state.code + return ( + (step.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || + step.state.uploadType === ModelUploadType.ModelCard + ) } export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: RenderInterface) { @@ -84,10 +139,18 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render return ( - - - - + + + + {state.uploadType === ModelUploadType.Zip && ( + + + + + )} + {state.uploadType === ModelUploadType.ModelCard && ( + Uploading a model card without any code or binary files + )} ) } diff --git a/src/RawModelExportList.tsx b/src/RawModelExportList.tsx index 9429b570c..576314b08 100644 --- a/src/RawModelExportList.tsx +++ b/src/RawModelExportList.tsx @@ -9,9 +9,11 @@ import Button from '@mui/material/Button' import { useGetModelById, useGetModelVersions } from '../data/model' import { Deployment } from '../types/interfaces' import EmptyBlob from './common/EmptyBlob' +import { ModelDoc } from '../server/models/Model' function RawModelExportList({ deployment }: { deployment: Deployment }) { - const { model } = useGetModelById(deployment.model.toString()) + const modelFromDeployment: ModelDoc = deployment.model as ModelDoc + const { model } = useGetModelById(modelFromDeployment._id.toString()) const { versions } = useGetModelVersions(model?.uuid) return ( diff --git a/types/interfaces.ts b/types/interfaces.ts index 22110eb23..c6e70e766 100644 --- a/types/interfaces.ts +++ b/types/interfaces.ts @@ -164,3 +164,9 @@ export type DocFile = { export type DocFileOrHeading = DocHeading | DocFile export type DocsMenuContent = DocFileOrHeading[] + +export enum ModelUploadType { + Zip = 'Upload code & binary', + ModelCard = 'Upload a model card', + Docker = 'Upload an exported Docker container', +} From d7bf0be0577c30e7c582ef170b3fd533f900ae9f Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Tue, 13 Sep 2022 12:24:00 +0000 Subject: [PATCH 2/9] linting --- server/routes/v1/upload.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/routes/v1/upload.ts b/server/routes/v1/upload.ts index 5dce01edc..48a16d2c1 100644 --- a/server/routes/v1/upload.ts +++ b/server/routes/v1/upload.ts @@ -17,7 +17,7 @@ import { BadReq, Conflict, GenericError } from '../../utils/result' import { ensureUserRole } from '../../utils/user' import { validateSchema } from '../../utils/validateSchema' import VersionModel from '../../models/Version' -import { ModelUploadType } from '@/types/interfaces' +import { ModelUploadType } from '../../../types/interfaces' export interface MinioFile { [fieldname: string]: Array @@ -227,7 +227,7 @@ export const postUpload = [ } } - res.json({ + return res.json({ uuid: model.uuid, }) }) From 9ab47ec5d4cd180f5a9b918a6166f451abf8924e Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Wed, 14 Sep 2022 10:39:00 +0000 Subject: [PATCH 3/9] moved the position of the alerts for model card only on model/deployment pages --- pages/deployment/[uuid].tsx | 34 ++++++++++++++++++++++++++-------- pages/model/[uuid].tsx | 10 +++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pages/deployment/[uuid].tsx b/pages/deployment/[uuid].tsx index d248e0e19..e664ae60e 100644 --- a/pages/deployment/[uuid].tsx +++ b/pages/deployment/[uuid].tsx @@ -172,11 +172,32 @@ export default function Deployment() { return ( <> - - - + {initialVersionRequested.modelCardOnly === undefined || + (!initialVersionRequested.modelCardOnly && ( + + + + ))} + {initialVersionRequested.modelCardOnly !== undefined && initialVersionRequested.modelCardOnly && ( + + + This model version was uploaded as just a model card + + + )} @@ -193,9 +214,6 @@ export default function Deployment() { > Actions - {initialVersionRequested.modelCardOnly !== undefined && initialVersionRequested.modelCardOnly && ( - This model version was uploaded as just a model card - )} diff --git a/pages/model/[uuid].tsx b/pages/model/[uuid].tsx index 5633bd329..6c26dea41 100644 --- a/pages/model/[uuid].tsx +++ b/pages/model/[uuid].tsx @@ -170,6 +170,13 @@ function Model() { return ( + {version.modelCardOnly !== undefined && version.modelCardOnly && ( + + + This model version was uploaded as just a model card + + + )} @@ -188,9 +195,6 @@ function Model() { > Actions - {version.modelCardOnly !== undefined && version.modelCardOnly && ( - This model version was uploaded as just a model card - )} From de1ca5345524f5995a6a5c898f1b9b98ca3b22aa Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Fri, 16 Sep 2022 13:13:29 +0000 Subject: [PATCH 4/9] added model upload type as a shcema property --- pages/deployment/[uuid].tsx | 45 +++++++------ pages/model/[uuid].tsx | 22 ++++--- pages/model/[uuid]/new-version.tsx | 4 +- pages/upload.tsx | 11 ++-- server/models/Version.ts | 4 -- server/routes/v1/upload.ts | 29 ++++---- .../minimal_upload_schema.json | 9 ++- server/services/deployment.ts | 2 +- src/Form/RenderFileTab.tsx | 66 ++++++------------- types/interfaces.ts | 4 +- 10 files changed, 90 insertions(+), 106 deletions(-) diff --git a/pages/deployment/[uuid].tsx b/pages/deployment/[uuid].tsx index c8889ddfa..827dccd94 100644 --- a/pages/deployment/[uuid].tsx +++ b/pages/deployment/[uuid].tsx @@ -42,6 +42,7 @@ import { createDeploymentComplianceFlow } from '../../utils/complianceFlow' import { postEndpoint } from '../../data/api' import RawModelExportList from '../../src/RawModelExportList' import { VersionDoc } from '../../server/models/Version' +import { ModelUploadType } from '../../types/interfaces' const ComplianceFlow = dynamic(() => import('../../src/ComplianceFlow')) @@ -172,32 +173,33 @@ export default function Deployment() { return ( <> - {initialVersionRequested.modelCardOnly === undefined || - (!initialVersionRequested.modelCardOnly && ( + {initialVersionRequested.metadata.buildOptions.uploadType === undefined || + (initialVersionRequested.metadata.buildOptions.uploadType !== ModelUploadType.ModelCard && ( ))} - {initialVersionRequested.modelCardOnly !== undefined && initialVersionRequested.modelCardOnly && ( - - + - This model version was uploaded as just a model card - - - )} + '& .MuiAlert-icon': { + color: '#fff', + }, + }} + > + This model version was uploaded as just a model card + + + )} diff --git a/pages/model/[uuid].tsx b/pages/model/[uuid].tsx index 983bd1e81..6f0f0ecb6 100644 --- a/pages/model/[uuid].tsx +++ b/pages/model/[uuid].tsx @@ -48,7 +48,7 @@ import ApprovalsChip from '../../src/common/ApprovalsChip' import EmptyBlob from '../../src/common/EmptyBlob' import MultipleErrorWrapper from '../../src/errors/MultipleErrorWrapper' import { lightTheme } from '../../src/theme' -import { Deployment, User, Version } from '../../types/interfaces' +import { Deployment, ModelUploadType, User, Version } from '../../types/interfaces' const ComplianceFlow = dynamic(() => import('../../src/ComplianceFlow')) @@ -170,13 +170,14 @@ function Model() { return ( - {version.modelCardOnly !== undefined && version.modelCardOnly && ( - - - This model version was uploaded as just a model card - - - )} + {version.metadata.buildOptions.uploadType !== undefined && + version.metadata.buildOptions.uploadType === ModelUploadType.ModelCard && ( + + + This model version was uploaded as just a model card + + + )} @@ -297,7 +298,10 @@ function Model() { diff --git a/pages/model/[uuid]/new-version.tsx b/pages/model/[uuid]/new-version.tsx index ffb9bb770..dc2a10f71 100644 --- a/pages/model/[uuid]/new-version.tsx +++ b/pages/model/[uuid]/new-version.tsx @@ -12,7 +12,7 @@ import ModelExportAndSubmission from '../../../src/Form/ModelExportAndSubmission import { RenderButtonsInterface } from '../../../src/Form/RenderButtons' import SubmissionError from '../../../src/Form/SubmissionError' import Wrapper from '../../../src/Wrapper' -import { SplitSchema, ModelUploadType } from '../../../types/interfaces' +import { SplitSchema } from '../../../types/interfaces' import { createStep, getStepsData, getStepsFromSchema } from '../../../utils/formUtils' import useCacheVariable from '../../../utils/useCacheVariable' @@ -66,7 +66,6 @@ function Upload() { state: { binary: undefined, code: undefined, - uploadType: ModelUploadType.Zip, }, schemaRef: cModel.schemaRef, @@ -138,7 +137,6 @@ function Upload() { form.append('code', data.files.code) form.append('binary', data.files.binary) - form.append('uploadType', data.files.uploadType) delete data.files diff --git a/pages/upload.tsx b/pages/upload.tsx index fd3862515..465b90995 100644 --- a/pages/upload.tsx +++ b/pages/upload.tsx @@ -1,3 +1,6 @@ +import axios from 'axios' +import { useRouter } from 'next/router' +import { useEffect, useState } from 'react' import { useGetDefaultSchema, useGetSchemas } from '@/data/schema' import { useGetCurrentUser } from '@/data/user' import LoadingBar from '@/src/common/LoadingBar' @@ -10,14 +13,11 @@ import RenderFileTab, { FileTabComplete, RenderBasicFileTab } from '@/src/Form/R import SchemaSelector from '@/src/Form/SchemaSelector' import SubmissionError from '@/src/Form/SubmissionError' import Wrapper from '@/src/Wrapper' -import { Schema, SplitSchema, ModelUploadType, User } from '@/types/interfaces' +import { Schema, SplitSchema, User } from '@/types/interfaces' import { createStep, getStepsData, getStepsFromSchema } from '@/utils/formUtils' import Box from '@mui/material/Box' import Grid from '@mui/material/Grid' import Paper from '@mui/material/Paper' -import axios from 'axios' -import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' function renderSubmissionTab({ splitSchema, @@ -84,7 +84,7 @@ function Upload() { state: { binary: undefined, code: undefined, - uploadType: ModelUploadType.Zip, + steps, }, schemaRef: reference, @@ -153,7 +153,6 @@ function Upload() { form.append('code', data.files.code) form.append('binary', data.files.binary) - form.append('uploadType', data.files.uploadType) delete data.files form.append('metadata', JSON.stringify(data)) diff --git a/server/models/Version.ts b/server/models/Version.ts index 35689c12f..3fbaef3da 100644 --- a/server/models/Version.ts +++ b/server/models/Version.ts @@ -19,8 +19,6 @@ export interface Version { rawCodePath: string } - modelCardOnly?: boolean - state: any logs: Types.Array @@ -41,8 +39,6 @@ const VersionSchema = new Schema( files: { type: Schema.Types.Mixed, required: true }, - modelCardOnly: { type: Boolean }, - built: { type: Boolean, default: false }, managerApproved: { type: String, required: true, enum: approvalStateOptions, default: 'No Response' }, reviewerApproved: { type: String, required: true, enum: approvalStateOptions, default: 'No Response' }, diff --git a/server/routes/v1/upload.ts b/server/routes/v1/upload.ts index a78efcae0..296a18ce2 100644 --- a/server/routes/v1/upload.ts +++ b/server/routes/v1/upload.ts @@ -43,9 +43,21 @@ export const postUpload = [ const files = req.files as unknown as MinioFile const mode = (req.query.mode as string) || UploadModes.NewModel const modelUuid = req.query.modelUuid as string - const uploadType = req.body.uploadType as ModelUploadType - if (uploadType === ModelUploadType.Zip && !files.binary) { + let metadata + + try { + metadata = JSON.parse(req.body.metadata) + } catch (e) { + req.log.warn({ code: 'metadata_invalid_json', metadata: req.body.metadata }, 'Metadata is not valid JSON') + return res.status(400).json({ + message: `Unable to parse schema as JSON`, + }) + } + + const uploadType = metadata.buildOptions.uploadType as ModelUploadType + + if (metadata.uploadType === ModelUploadType.Zip && !files.binary) { throw BadReq({ code: 'binary_file_not_found' }, 'Unable to find binary file') } @@ -77,17 +89,6 @@ export const postUpload = [ ) } - let metadata - - try { - metadata = JSON.parse(req.body.metadata) - } catch (e) { - req.log.warn({ code: 'metadata_invalid_json', metadata: req.body.metadata }, 'Metadata is not valid JSON') - return res.status(400).json({ - message: `Unable to parse schema as JSON`, - }) - } - const schema = await findSchemaByRef(metadata.schemaRef) if (!schema) { req.log.warn({ code: 'schema_not_found', schemaRef: metadata.schemaRef }, 'Schema not found') @@ -197,8 +198,6 @@ export const postUpload = [ ) if (uploadType === ModelUploadType.ModelCard) { - version.modelCardOnly = true - await version.save() await markVersionBuilt(version._id) } else { await version.save() diff --git a/server/scripts/example_schemas/minimal_upload_schema.json b/server/scripts/example_schemas/minimal_upload_schema.json index 566e6eb5a..ea17d4052 100644 --- a/server/scripts/example_schemas/minimal_upload_schema.json +++ b/server/scripts/example_schemas/minimal_upload_schema.json @@ -105,8 +105,15 @@ "title": "Export raw models", "description": "If enabled, allow raw uploaded model files to be downloaded by deployments.", "type": "boolean" + }, + "uploadType": { + "type": "string", + "title": "Upload type", + "description": "Select the type of model upload that you want", + "enum": ["Code and binaries", "Model card only"] } - } + }, + "required": ["uploadType"] } }, "required": ["timeStamp", "highLevelDetails"] diff --git a/server/services/deployment.ts b/server/services/deployment.ts index 9d2bd5eed..ad328da4f 100644 --- a/server/services/deployment.ts +++ b/server/services/deployment.ts @@ -35,7 +35,7 @@ export async function filterDeployment(user: UserDoc, unfiltered: T): Promise export async function findDeploymentByUuid(user: UserDoc, uuid: string, _opts?: GetDeploymentOptions) { let deployment = DeploymentModel.findOne({ uuid }) - deployment = deployment.populate('model', ['_id', 'uuid']).populate('versions', ['version', 'modelCardOnly']) + deployment = deployment.populate('model', ['_id', 'uuid']).populate('versions', ['version', 'metadata']) return filterDeployment(user, await deployment) } diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 316fa5538..7b8cb8070 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -14,37 +14,6 @@ import { RenderInterface, Step, ModelUploadType } from '../../types/interfaces' import { setStepState } from '../../utils/formUtils' import FileInput from '../common/FileInput' -function RenderUploadType({ step, splitSchema, setSplitSchema }: RenderInterface) { - const { state } = step - const { uploadType } = state - - const handleUploadTypeChange = (event) => { - state.code = undefined - state.binary = undefined - setStepState(splitSchema, setSplitSchema, step, { ...state, uploadType: event.target.value }) - } - - return ( - - Upload Type - - - ) -} - export default function RenderFileTab({ step, splitSchema, setSplitSchema }: RenderInterface) { const { state } = step const { binary, code } = state @@ -56,6 +25,10 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren display: 'none', }) + const buildOptionsStep: Step = splitSchema.steps.filter( + (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' + )[0] + const handleCodeChange = (e: any) => { setStepState(splitSchema, setSplitSchema, step, { ...state, code: e.target.files[0] }) } @@ -73,11 +46,8 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren return ( <> - - - - {state.uploadType === ModelUploadType.Zip && ( + {buildOptionsStep.state.uploadType === ModelUploadType.Zip && ( )} - {state.uploadType === ModelUploadType.ModelCard && ( + {buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( Uploading a model card without any code or binary files )} @@ -119,9 +89,12 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } export function FileTabComplete(step: Step) { + const buildOptionsStep: Step = step.state.steps.filter( + (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' + )[0] return ( - (step.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || - step.state.uploadType === ModelUploadType.ModelCard + (buildOptionsStep.state.uploadType === ModelUploadType.Zip && buildOptionsStep.state.binary && step.state.code) || + buildOptionsStep.state.uploadType === ModelUploadType.ModelCard ) } @@ -129,6 +102,10 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render const { state } = step const { binary, code } = state + const buildOptionsStep: Step = splitSchema.steps.filter( + (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' + )[0] + const handleCodeChange = (e: any) => { setStepState(splitSchema, setSplitSchema, step, { ...state, code: e.target.files[0] }) } @@ -139,18 +116,17 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render return ( - - - - {state.uploadType === ModelUploadType.Zip && ( + {(buildOptionsStep.state.uploadType === undefined || + buildOptionsStep.state.uploadType === ModelUploadType.Zip) && ( )} - {state.uploadType === ModelUploadType.ModelCard && ( - Uploading a model card without any code or binary files - )} + {buildOptionsStep.state.uploadType !== undefined && + buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( + Uploading a model card without any code or binary files + )} ) } diff --git a/types/interfaces.ts b/types/interfaces.ts index 3c3cf0647..906fff356 100644 --- a/types/interfaces.ts +++ b/types/interfaces.ts @@ -173,8 +173,8 @@ export type DocFileOrHeading = DocHeading | DocFile export type DocsMenuContent = DocFileOrHeading[] export enum ModelUploadType { - Zip = 'Upload code & binary', - ModelCard = 'Upload a model card', + Zip = 'Code and binaries', + ModelCard = 'Model card only', Docker = 'Upload an exported Docker container', } From e686e2ed7f07b119ef1c24800b67b80c721edbff Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Fri, 16 Sep 2022 14:25:02 +0000 Subject: [PATCH 5/9] fixed an issue where new versions would not build --- pages/model/[uuid]/new-version.tsx | 1 + server/routes/v1/upload.ts | 1 + src/Form/RenderFileTab.tsx | 74 +++++++++++++----------------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/pages/model/[uuid]/new-version.tsx b/pages/model/[uuid]/new-version.tsx index dc2a10f71..32b9822c4 100644 --- a/pages/model/[uuid]/new-version.tsx +++ b/pages/model/[uuid]/new-version.tsx @@ -66,6 +66,7 @@ function Upload() { state: { binary: undefined, code: undefined, + steps, }, schemaRef: cModel.schemaRef, diff --git a/server/routes/v1/upload.ts b/server/routes/v1/upload.ts index 296a18ce2..00424e7d4 100644 --- a/server/routes/v1/upload.ts +++ b/server/routes/v1/upload.ts @@ -199,6 +199,7 @@ export const postUpload = [ if (uploadType === ModelUploadType.ModelCard) { await markVersionBuilt(version._id) + await version.save() } else { await version.save() } diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 7b8cb8070..95aae8f13 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -45,46 +45,38 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } return ( - <> - - {buildOptionsStep.state.uploadType === ModelUploadType.Zip && ( - - - - - - - - - - )} - {buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( - Uploading a model card without any code or binary files - )} - - + + {buildOptionsStep.state.uploadType === ModelUploadType.Zip && ( + + + + + + + + + + )} + {buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( + Uploading a model card without any code or binary files + )} + ) } @@ -93,7 +85,7 @@ export function FileTabComplete(step: Step) { (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' )[0] return ( - (buildOptionsStep.state.uploadType === ModelUploadType.Zip && buildOptionsStep.state.binary && step.state.code) || + (buildOptionsStep.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || buildOptionsStep.state.uploadType === ModelUploadType.ModelCard ) } From 2565023e2f7a2944b15eaf37f8dc8ac2a29d4b71 Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Tue, 20 Sep 2022 12:31:51 +0000 Subject: [PATCH 6/9] added a small change to allow for upload existing tab to work without touching designer --- .../minimal_model/minimal_metadata.json | 3 ++- __tests__/selenium_tests/test_upload.ts | 5 +++++ .../minimal_upload_schema_examples.json | 3 ++- src/Form/RenderFileTab.tsx | 12 +++++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/__tests__/example_models/minimal_model/minimal_metadata.json b/__tests__/example_models/minimal_model/minimal_metadata.json index 385437ea1..1ffe93a89 100644 --- a/__tests__/example_models/minimal_model/minimal_metadata.json +++ b/__tests__/example_models/minimal_model/minimal_metadata.json @@ -12,6 +12,7 @@ "manager": "user" }, "buildOptions": { - "exportRawModel": true + "exportRawModel": true, + "uploadType": "Code and binaries" } } diff --git a/__tests__/selenium_tests/test_upload.ts b/__tests__/selenium_tests/test_upload.ts index eb88f2add..1ede0a5d8 100644 --- a/__tests__/selenium_tests/test_upload.ts +++ b/__tests__/selenium_tests/test_upload.ts @@ -86,6 +86,9 @@ describe('End to end test', () => { await driver.wait(until.urlContains('/model/')) const modelUrl = await driver.getCurrentUrl() const mName = modelUrl.match('/.*/model/(?[^/]*)')!.groups!.name + + logger.info(`model name is ${mName}`) + modelInfo.url = modelUrl modelInfo.name = mName @@ -263,6 +266,8 @@ describe('End to end test', () => { { silentErrors: true } ) + logger.info({modelInfo}, 'the model info') + logger.info('pulling container') await runCommand(`docker pull ${imageName}`, logger.debug.bind(logger), logger.error.bind(logger), { silentErrors: true, diff --git a/server/scripts/example_schemas/minimal_upload_schema_examples.json b/server/scripts/example_schemas/minimal_upload_schema_examples.json index 3ffe92e6f..c32d45840 100644 --- a/server/scripts/example_schemas/minimal_upload_schema_examples.json +++ b/server/scripts/example_schemas/minimal_upload_schema_examples.json @@ -30,7 +30,8 @@ "manager": "user" }, "buildOptions": { - "exportRawModel": true + "exportRawModel": true, + "uploadType": "Code and binaries" } }, { diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 95aae8f13..fad19df40 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -81,9 +81,13 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } export function FileTabComplete(step: Step) { + const buildOptionsStep: Step = step.state.steps.filter( (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' )[0] + if (buildOptionsStep.state.uploadType === undefined) { + return true + } return ( (buildOptionsStep.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || buildOptionsStep.state.uploadType === ModelUploadType.ModelCard @@ -124,5 +128,11 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render } export function BasicFileTabComplete(step: Step) { - return step.state.binary && step.state.code + const buildOptionsStep: Step = step.state.steps.filter( + (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' + )[0] + return ( + (buildOptionsStep.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || + buildOptionsStep.state.uploadType === ModelUploadType.ModelCard + ) } From f476a000da5888ebd9c93567ac8b8da435fc0f25 Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Tue, 20 Sep 2022 12:56:05 +0000 Subject: [PATCH 7/9] styling --- .eslintrc.js | 2 +- __tests__/selenium_tests/test_upload.ts | 2 +- src/Form/RenderFileTab.tsx | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ee907f122..313bf1031 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,7 +33,7 @@ module.exports = { 'import/no-cycle': [0, { ignoreExternal: true }], '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: false, variables: true }], '@typescript-eslint/no-namespace': ['error', { allowDeclarations: true }], - '@typescript-eslint/no-shadow': ['error'], + '@typescript-eslint/no-shadow': 'error', // IGNORED RULES '@typescript-eslint/no-var-requires': 'off', 'class-methods-use-this': 'off', diff --git a/__tests__/selenium_tests/test_upload.ts b/__tests__/selenium_tests/test_upload.ts index 1ede0a5d8..33f5bae8e 100644 --- a/__tests__/selenium_tests/test_upload.ts +++ b/__tests__/selenium_tests/test_upload.ts @@ -266,7 +266,7 @@ describe('End to end test', () => { { silentErrors: true } ) - logger.info({modelInfo}, 'the model info') + logger.info({ modelInfo }, 'the model info') logger.info('pulling container') await runCommand(`docker pull ${imageName}`, logger.debug.bind(logger), logger.error.bind(logger), { diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index fad19df40..7a6b51315 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -81,7 +81,6 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } export function FileTabComplete(step: Step) { - const buildOptionsStep: Step = step.state.steps.filter( (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' )[0] From abf7d0d085f205b58d0dc5bfd1734865d32c60fe Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Wed, 21 Sep 2022 09:48:37 +0000 Subject: [PATCH 8/9] changed how handle finding the buildoptions step --- pages/deployment/[uuid].tsx | 70 ++++++++++++++++++++++--------------- pages/model/[uuid].tsx | 24 ++++++------- src/Form/RenderFileTab.tsx | 61 ++++++++++++++++++-------------- 3 files changed, 86 insertions(+), 69 deletions(-) diff --git a/pages/deployment/[uuid].tsx b/pages/deployment/[uuid].tsx index 827dccd94..82b8cbfda 100644 --- a/pages/deployment/[uuid].tsx +++ b/pages/deployment/[uuid].tsx @@ -26,7 +26,7 @@ import Box from '@mui/system/Box' import dynamic from 'next/dynamic' import Link from 'next/link' import { useRouter } from 'next/router' -import React, { MouseEvent, useEffect, useState } from 'react' +import React, { MouseEvent, useEffect, useMemo, useState } from 'react' import { Elements } from 'react-flow-renderer' import { useGetDeployment } from '../../data/deployment' import { useGetUiConfig } from '../../data/uiConfig' @@ -88,6 +88,9 @@ function CodeLine({ line }) { ) } +const isVersionDoc = (value: unknown): value is VersionDoc => + !!value && (value as VersionDoc)._id && (value as VersionDoc).version + export default function Deployment() { const router = useRouter() const { uuid, tab }: { uuid?: string; tab?: TabOptions } = router.query @@ -105,10 +108,24 @@ export default function Deployment() { const theme: any = useTheme() || lightTheme + const initialVersionRequested = useMemo(() => { + if (!deployment) return undefined + const initialVersion = deployment.versions.find( + (version) => + isVersionDoc(version) && version.version === deployment.metadata.highLevelDetails.initialVersionRequested + ) + return isVersionDoc(initialVersion) ? initialVersion : undefined + }, [deployment]) + + const hasUploadType = useMemo( + () => initialVersionRequested !== undefined && !!initialVersionRequested.metadata.buildOptions.uploadType, + [initialVersionRequested] + ) + useEffect(() => { if (deployment?.metadata?.highLevelDetails !== undefined) { - const { modelID, initialVersionRequested } = deployment.metadata.highLevelDetails - setTag(`${modelID}:${initialVersionRequested}`) + const { modelID, versionRequested } = deployment.metadata.highLevelDetails + setTag(`${modelID}:${versionRequested}`) } }, [deployment]) @@ -166,40 +183,35 @@ export default function Deployment() { await postEndpoint(`/api/v1/deployment/${deployment?.uuid}/reset-approvals`, {}).then((res) => res.json()) } - const initialVersionRequested: ObjectId | VersionDoc = deployment.versions.filter( - (version: any) => version.version === deployment.metadata.highLevelDetails.initialVersionRequested - )[0] as VersionDoc - return ( <> - {initialVersionRequested.metadata.buildOptions.uploadType === undefined || - (initialVersionRequested.metadata.buildOptions.uploadType !== ModelUploadType.ModelCard && ( + {hasUploadType || + (initialVersionRequested?.metadata.buildOptions.uploadType !== ModelUploadType.ModelCard && ( ))} - {initialVersionRequested.metadata.buildOptions.uploadType !== undefined && - initialVersionRequested.metadata.buildOptions.uploadType === ModelUploadType.ModelCard && ( - - + - This model version was uploaded as just a model card - - - )} + }, + }} + > + This model version was uploaded as just a model card + + + )} diff --git a/pages/model/[uuid].tsx b/pages/model/[uuid].tsx index 6f0f0ecb6..b849f85a5 100644 --- a/pages/model/[uuid].tsx +++ b/pages/model/[uuid].tsx @@ -37,7 +37,7 @@ import { Types } from 'mongoose' import dynamic from 'next/dynamic' import Link from 'next/link' import { useRouter } from 'next/router' -import React, { MouseEvent, useEffect, useState } from 'react' +import React, { MouseEvent, useEffect, useMemo, useState } from 'react' import { Elements } from 'react-flow-renderer' import UserAvatar from 'src/common/UserAvatar' import ModelOverview from 'src/ModelOverview' @@ -82,6 +82,8 @@ function Model() { const { version, isVersionLoading, isVersionError, mutateVersion } = useGetModelVersion(uuid, selectedVersion) const { deployments, isDeploymentsLoading, isDeploymentsError } = useGetModelDeployments(uuid) + const hasUploadType = useMemo(() => version !== undefined && !!version.metadata.buildOptions.uploadType, [version]) + const onVersionChange = setTargetValue(setSelectedVersion) const theme: any = useTheme() || lightTheme @@ -170,14 +172,13 @@ function Model() { return ( - {version.metadata.buildOptions.uploadType !== undefined && - version.metadata.buildOptions.uploadType === ModelUploadType.ModelCard && ( - - - This model version was uploaded as just a model card - - - )} + {hasUploadType && version.metadata.buildOptions.uploadType === ModelUploadType.ModelCard && ( + + + This model version was uploaded as just a model card + + + )} @@ -298,10 +299,7 @@ function Model() { diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 7a6b51315..473bcc84e 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -1,15 +1,11 @@ import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Divider from '@mui/material/Divider' -import FormControl from '@mui/material/FormControl' import Grid from '@mui/material/Grid' -import InputLabel from '@mui/material/InputLabel' -import MenuItem from '@mui/material/MenuItem' -import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { styled } from '@mui/system' -import React from 'react' +import React, { useMemo } from 'react' import { RenderInterface, Step, ModelUploadType } from '../../types/interfaces' import { setStepState } from '../../utils/formUtils' import FileInput from '../common/FileInput' @@ -25,9 +21,10 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren display: 'none', }) - const buildOptionsStep: Step = splitSchema.steps.filter( - (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' - )[0] + const buildOptionsStep = useMemo( + () => splitSchema.steps.find((buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions'), + [splitSchema.steps] + ) const handleCodeChange = (e: any) => { setStepState(splitSchema, setSplitSchema, step, { ...state, code: e.target.files[0] }) @@ -46,7 +43,7 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren return ( - {buildOptionsStep.state.uploadType === ModelUploadType.Zip && ( + {buildOptionsStep !== undefined && buildOptionsStep.state.uploadType === ModelUploadType.Zip && ( )} - {buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( + {buildOptionsStep !== undefined && buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( Uploading a model card without any code or binary files )} @@ -81,14 +78,18 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren } export function FileTabComplete(step: Step) { - const buildOptionsStep: Step = step.state.steps.filter( + const buildOptionsStep = step.state.steps.find( (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' - )[0] - if (buildOptionsStep.state.uploadType === undefined) { + ) + const hasUploadType = useMemo(() => !!buildOptionsStep.state.uploadType, [buildOptionsStep]) + if (!hasUploadType) { return true } return ( - (buildOptionsStep.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || + (buildOptionsStep !== undefined && + buildOptionsStep.state.uploadType === ModelUploadType.Zip && + step.state.binary && + step.state.code) || buildOptionsStep.state.uploadType === ModelUploadType.ModelCard ) } @@ -97,9 +98,10 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render const { state } = step const { binary, code } = state - const buildOptionsStep: Step = splitSchema.steps.filter( - (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' - )[0] + const buildOptionsStep = useMemo( + () => step.state.steps.find((buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions'), + [step] + ) const handleCodeChange = (e: any) => { setStepState(splitSchema, setSplitSchema, step, { ...state, code: e.target.files[0] }) @@ -109,29 +111,34 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render setStepState(splitSchema, setSplitSchema, step, { ...state, binary: e.target.files[0] }) } + const hasUploadType = useMemo(() => !!buildOptionsStep.state.uploadType, [buildOptionsStep]) + return ( - {(buildOptionsStep.state.uploadType === undefined || - buildOptionsStep.state.uploadType === ModelUploadType.Zip) && ( + {(!hasUploadType || + (buildOptionsStep !== undefined && buildOptionsStep.state.uploadType === ModelUploadType.Zip)) && ( )} - {buildOptionsStep.state.uploadType !== undefined && - buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( - Uploading a model card without any code or binary files - )} + {hasUploadType && buildOptionsStep.state.uploadType === ModelUploadType.ModelCard && ( + Uploading a model card without any code or binary files + )} ) } export function BasicFileTabComplete(step: Step) { - const buildOptionsStep: Step = step.state.steps.filter( - (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' - )[0] + const buildOptionsStep = useMemo( + () => step.state.steps.find((buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions'), + [step] + ) return ( - (buildOptionsStep.state.uploadType === ModelUploadType.Zip && step.state.binary && step.state.code) || + (buildOptionsStep !== undefined && + buildOptionsStep.state.uploadType === ModelUploadType.Zip && + step.state.binary && + step.state.code) || buildOptionsStep.state.uploadType === ModelUploadType.ModelCard ) } From 5f672d76220047c477401390e44842a5e46de6ca Mon Sep 17 00:00:00 2001 From: ARADDCC002 Date: Wed, 21 Sep 2022 12:12:03 +0000 Subject: [PATCH 9/9] more pr ammendments --- pages/model/[uuid]/new-version.tsx | 4 ++-- pages/upload.tsx | 4 ++-- src/Form/RenderFileTab.tsx | 18 ++---------------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/pages/model/[uuid]/new-version.tsx b/pages/model/[uuid]/new-version.tsx index 32b9822c4..ba5b002d1 100644 --- a/pages/model/[uuid]/new-version.tsx +++ b/pages/model/[uuid]/new-version.tsx @@ -7,7 +7,7 @@ import { useGetSchema } from '../../../data/schema' import LoadingBar from '../../../src/common/LoadingBar' import MultipleErrorWrapper from '../../../src/errors/MultipleErrorWrapper' import Form from '../../../src/Form/Form' -import RenderFileTab, { RenderBasicFileTab, FileTabComplete } from '../../../src/Form/RenderFileTab' +import RenderFileTab, { RenderBasicFileTab, fileTabComplete } from '../../../src/Form/RenderFileTab' import ModelExportAndSubmission from '../../../src/Form/ModelExportAndSubmission' import { RenderButtonsInterface } from '../../../src/Form/RenderButtons' import SubmissionError from '../../../src/Form/SubmissionError' @@ -76,7 +76,7 @@ function Upload() { render: RenderFileTab, renderBasic: RenderBasicFileTab, - isComplete: FileTabComplete, + isComplete: fileTabComplete, }) ) diff --git a/pages/upload.tsx b/pages/upload.tsx index 465b90995..2eeae1af1 100644 --- a/pages/upload.tsx +++ b/pages/upload.tsx @@ -9,7 +9,7 @@ import MultipleErrorWrapper from '@/src/errors/MultipleErrorWrapper' import Form from '@/src/Form/Form' import ModelExportAndSubmission from '@/src/Form/ModelExportAndSubmission' import { RenderButtonsInterface } from '@/src/Form/RenderButtons' -import RenderFileTab, { FileTabComplete, RenderBasicFileTab } from '@/src/Form/RenderFileTab' +import RenderFileTab, { fileTabComplete, RenderBasicFileTab } from '@/src/Form/RenderFileTab' import SchemaSelector from '@/src/Form/SchemaSelector' import SubmissionError from '@/src/Form/SubmissionError' import Wrapper from '@/src/Wrapper' @@ -94,7 +94,7 @@ function Upload() { render: RenderFileTab, renderBasic: RenderBasicFileTab, - isComplete: FileTabComplete, + isComplete: fileTabComplete, }) ) diff --git a/src/Form/RenderFileTab.tsx b/src/Form/RenderFileTab.tsx index 473bcc84e..7788ce7cc 100644 --- a/src/Form/RenderFileTab.tsx +++ b/src/Form/RenderFileTab.tsx @@ -77,11 +77,11 @@ export default function RenderFileTab({ step, splitSchema, setSplitSchema }: Ren ) } -export function FileTabComplete(step: Step) { +export function fileTabComplete(step: Step) { const buildOptionsStep = step.state.steps.find( (buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions' ) - const hasUploadType = useMemo(() => !!buildOptionsStep.state.uploadType, [buildOptionsStep]) + const hasUploadType = !!buildOptionsStep.state.uploadType if (!hasUploadType) { return true } @@ -128,17 +128,3 @@ export function RenderBasicFileTab({ step, splitSchema, setSplitSchema }: Render ) } - -export function BasicFileTabComplete(step: Step) { - const buildOptionsStep = useMemo( - () => step.state.steps.find((buildOptionSchemaStep) => buildOptionSchemaStep.section === 'buildOptions'), - [step] - ) - return ( - (buildOptionsStep !== undefined && - buildOptionsStep.state.uploadType === ModelUploadType.Zip && - step.state.binary && - step.state.code) || - buildOptionsStep.state.uploadType === ModelUploadType.ModelCard - ) -}