diff --git a/app-shell/src/protocol-storage/file-system.ts b/app-shell/src/protocol-storage/file-system.ts index fac01d9aa24..cf3c36f3c5f 100644 --- a/app-shell/src/protocol-storage/file-system.ts +++ b/app-shell/src/protocol-storage/file-system.ts @@ -24,8 +24,13 @@ import { analyzeProtocolSource } from '../protocol-analysis' * │ ├─ analysis/ * │ │ ├─ 1646303906.json */ - -export const PROTOCOLS_DIRECTORY_NAME = 'protocols' +// TODO(jh, 2023-09-11): remove OLD_PROTOCOLS_DIRECTORY_PATH after +// OT-2 parity work is completed and move all protocols back to "protocols" directory. +export const OLD_PROTOCOLS_DIRECTORY_PATH = path.join( + app.getPath('userData'), + 'protocols' +) +export const PROTOCOLS_DIRECTORY_NAME = 'protocols_v7.0-supported' export const PROTOCOLS_DIRECTORY_PATH = path.join( app.getPath('userData'), PROTOCOLS_DIRECTORY_NAME diff --git a/app-shell/src/protocol-storage/index.ts b/app-shell/src/protocol-storage/index.ts index a7c1a71e492..2a03d82ce47 100644 --- a/app-shell/src/protocol-storage/index.ts +++ b/app-shell/src/protocol-storage/index.ts @@ -42,11 +42,65 @@ export const getProtocolSrcFilePaths = ( }) } +// TODO(jh, 2023-09-11): remove migrateProtocolsToNewDirectory after +// OT-2 parity work is completed. +const migrateProtocols = migrateProtocolsToNewDirectory() +function migrateProtocolsToNewDirectory(): () => Promise { + let hasCheckedForMigration = false + return function (): Promise { + return new Promise((resolve, reject) => { + if (hasCheckedForMigration) resolve() + hasCheckedForMigration = true + console.log( + `Performing protocol migration to ${FileSystem.PROTOCOLS_DIRECTORY_NAME}...` + ) + copyProtocols( + FileSystem.OLD_PROTOCOLS_DIRECTORY_PATH, + FileSystem.PROTOCOLS_DIRECTORY_PATH + ) + .then(() => { + console.log('Protocol migration complete.') + resolve() + }) + .catch(e => { + console.log( + `Error migrating protocols to ${FileSystem.PROTOCOLS_DIRECTORY_NAME}: ${e}` + ) + resolve() + }) + }) + } + + function copyProtocols(src: string, dest: string): Promise { + return fse + .stat(src) + .then(doesSrcExist => { + if (!doesSrcExist.isDirectory()) return Promise.resolve() + + return fse.readdir(src).then(items => { + const protocols = items.map(item => { + const srcItem = path.join(src, item) + const destItem = path.join(dest, item) + + return fse.copy(srcItem, destItem, { + overwrite: false, + }) + }) + return Promise.all(protocols).then(() => Promise.resolve()) + }) + }) + .catch(e => { + return Promise.reject(e) + }) + } +} + export const fetchProtocols = ( dispatch: Dispatch, source: ListSource ): Promise => { return ensureDir(FileSystem.PROTOCOLS_DIRECTORY_PATH) + .then(() => migrateProtocols()) .then(() => FileSystem.readDirectoriesWithinDirectory( FileSystem.PROTOCOLS_DIRECTORY_PATH diff --git a/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx b/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx index 7a5866c2e5a..0b94bf6fbc2 100644 --- a/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx +++ b/app/src/organisms/ProtocolsLanding/ProtocolCard.tsx @@ -3,6 +3,7 @@ import { format } from 'date-fns' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { useHistory } from 'react-router-dom' +import { ErrorBoundary } from 'react-error-boundary' import { getModuleType, @@ -55,7 +56,6 @@ interface ProtocolCardProps { handleSendProtocolToOT3: (storedProtocolData: StoredProtocolData) => void storedProtocolData: StoredProtocolData } - export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null { const history = useHistory() const { @@ -78,6 +78,16 @@ export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null { mostRecentAnalysis ) + const UNKNOWN_ATTACHMENT_ERROR = `${protocolDisplayName} protocol uses + instruments or modules from a future version of the app. Please update + the app to the most recent version to run this protocol.` + + const UnknownAttachmentError = ( + + {UNKNOWN_ATTACHMENT_ERROR} + + ) + return ( history.push(`/protocols/${protocolKey}`)} css={BORDERS.cardOutlineBorder} > - + + +