diff --git a/app/src/local-resources/labware/hooks/index.ts b/app/src/local-resources/labware/hooks/index.ts new file mode 100644 index 000000000000..86c1116e2706 --- /dev/null +++ b/app/src/local-resources/labware/hooks/index.ts @@ -0,0 +1 @@ +export * from './useAllLabware' diff --git a/app/src/local-resources/labware/hooks/useAllLabware.ts b/app/src/local-resources/labware/hooks/useAllLabware.ts new file mode 100644 index 000000000000..28d4325b2ebf --- /dev/null +++ b/app/src/local-resources/labware/hooks/useAllLabware.ts @@ -0,0 +1,50 @@ +import { useSelector } from 'react-redux' +import { getValidCustomLabware } from '/app/redux/custom-labware' +import { getAllDefinitions } from '../utils' +import type { LabwareSort, LabwareFilter, LabwareDefAndDate } from '../types' + +export function useAllLabware( + sortBy: LabwareSort, + filterBy: LabwareFilter +): LabwareDefAndDate[] { + const fullLabwareList: LabwareDefAndDate[] = [] + const labwareDefinitions = getAllDefinitions() + labwareDefinitions.forEach(def => fullLabwareList.push({ definition: def })) + const customLabwareList = useSelector(getValidCustomLabware) + customLabwareList.forEach(customLabware => + 'definition' in customLabware + ? fullLabwareList.push({ + modified: customLabware.modified, + definition: customLabware.definition, + filename: customLabware.filename, + }) + : null + ) + const sortLabware = (a: LabwareDefAndDate, b: LabwareDefAndDate): number => { + if ( + a.definition.metadata.displayName.toUpperCase() < + b.definition.metadata.displayName.toUpperCase() + ) { + return sortBy === 'alphabetical' ? -1 : 1 + } + if ( + a.definition.metadata.displayName.toUpperCase() > + b.definition.metadata.displayName.toUpperCase() + ) { + return sortBy === 'alphabetical' ? 1 : -1 + } + return 0 + } + + if (filterBy === 'customLabware') { + return (customLabwareList as LabwareDefAndDate[]).sort(sortLabware) + } + fullLabwareList.sort(sortLabware) + if (filterBy !== 'all') { + return fullLabwareList.filter( + labwareItem => + labwareItem.definition.metadata.displayCategory === filterBy + ) + } + return fullLabwareList +} diff --git a/app/src/local-resources/labware/index.ts b/app/src/local-resources/labware/index.ts new file mode 100644 index 000000000000..505591b29091 --- /dev/null +++ b/app/src/local-resources/labware/index.ts @@ -0,0 +1,3 @@ +export * from './hooks' +export * from './utils' +export type * from './types' diff --git a/app/src/local-resources/labware/types.ts b/app/src/local-resources/labware/types.ts new file mode 100644 index 000000000000..99ea299573db --- /dev/null +++ b/app/src/local-resources/labware/types.ts @@ -0,0 +1,37 @@ +import type { + LabwareDefinition2 as LabwareDefinition, + LabwareWellShapeProperties, + LabwareWellGroupMetadata, + LabwareBrand, +} from '@opentrons/shared-data' + +export interface LabwareDefAndDate { + definition: LabwareDefinition + modified?: number + filename?: string +} + +export type LabwareFilter = + | 'all' + | 'wellPlate' + | 'tipRack' + | 'tubeRack' + | 'reservoir' + | 'aluminumBlock' + | 'customLabware' + | 'adapter' + +export type LabwareSort = 'alphabetical' | 'reverse' + +export interface LabwareWellGroupProperties { + xOffsetFromLeft: number + yOffsetFromTop: number + xSpacing: number | null + ySpacing: number | null + wellCount: number + shape: LabwareWellShapeProperties | null + depth: number | null + totalLiquidVolume: number | null + metadata: LabwareWellGroupMetadata + brand: LabwareBrand | null +} diff --git a/app/src/local-resources/labware/utils/getAllDefinitions.ts b/app/src/local-resources/labware/utils/getAllDefinitions.ts new file mode 100644 index 000000000000..db25fde06a18 --- /dev/null +++ b/app/src/local-resources/labware/utils/getAllDefinitions.ts @@ -0,0 +1,34 @@ +import groupBy from 'lodash/groupBy' +import { LABWAREV2_DO_NOT_LIST } from '@opentrons/shared-data' +import type { LabwareDefinition2 } from '@opentrons/shared-data' +import { getAllDefs } from './getAllDefs' + +export const getOnlyLatestDefs = ( + labwareList: LabwareDefinition2[] +): LabwareDefinition2[] => { + // group by namespace + loadName + const labwareDefGroups: { + [groupKey: string]: LabwareDefinition2[] + } = groupBy( + labwareList, + d => `${d.namespace}/${d.parameters.loadName}` + ) + return Object.keys(labwareDefGroups).map((groupKey: string) => { + const group = labwareDefGroups[groupKey] + const allVersions = group.map(d => d.version) + const highestVersionNum = Math.max(...allVersions) + const resultIdx = group.findIndex(d => d.version === highestVersionNum) + return group[resultIdx] + }) +} + +export function getAllDefinitions(): LabwareDefinition2[] { + const allDefs = getAllDefs().filter( + (d: LabwareDefinition2) => + // eslint-disable-next-line @typescript-eslint/prefer-includes + LABWAREV2_DO_NOT_LIST.indexOf(d.parameters.loadName) === -1 + ) + const definitions = getOnlyLatestDefs(allDefs) + + return definitions +} diff --git a/app/src/local-resources/labware/utils/getAllDefs.ts b/app/src/local-resources/labware/utils/getAllDefs.ts new file mode 100644 index 000000000000..58ccbae8b741 --- /dev/null +++ b/app/src/local-resources/labware/utils/getAllDefs.ts @@ -0,0 +1,6 @@ +import { getAllDefinitions } from '@opentrons/shared-data' +import type { LabwareDefinition2 } from '@opentrons/shared-data' + +export function getAllDefs(): LabwareDefinition2[] { + return Object.values(getAllDefinitions()) +} diff --git a/app/src/local-resources/labware/utils/index.ts b/app/src/local-resources/labware/utils/index.ts new file mode 100644 index 000000000000..f1368b03c6f2 --- /dev/null +++ b/app/src/local-resources/labware/utils/index.ts @@ -0,0 +1 @@ +export * from './getAllDefinitions'