-
Notifications
You must be signed in to change notification settings - Fork 179
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(app): split labware location from display location
- Loading branch information
Showing
5 changed files
with
206 additions
and
152 deletions.
There are no files selected for viewing
202 changes: 55 additions & 147 deletions
202
app/src/local-resources/labware/utils/getLabwareDisplayLocation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,180 +1,88 @@ | ||
import { | ||
getLabwareDefURI, | ||
getLabwareDisplayName, | ||
getModuleDisplayName, | ||
getModuleType, | ||
getOccludedSlotCountForModule, | ||
} from '@opentrons/shared-data' | ||
|
||
import { | ||
getModuleModel, | ||
getModuleDisplayLocation, | ||
} from '/app/local-resources/modules' | ||
import { getLabwareLocation } from './getLabwareLocation' | ||
|
||
import type { TFunction } from 'i18next' | ||
import type { | ||
LabwareDefinition2, | ||
LabwareLocation, | ||
RobotType, | ||
} from '@opentrons/shared-data' | ||
import type { LoadedLabwares } from '/app/local-resources/labware' | ||
import type { LoadedModules } from '/app/local-resources/modules' | ||
LocationSlotOnlyParams, | ||
LocationFullParams, | ||
} from './getLabwareLocation' | ||
|
||
interface LabwareDisplayLocationBaseParams { | ||
location: LabwareLocation | null | ||
loadedModules: LoadedModules | ||
loadedLabwares: LoadedLabwares | ||
robotType: RobotType | ||
export interface DisplayLocationSlotOnlyParams extends LocationSlotOnlyParams { | ||
t: TFunction | ||
isOnDevice?: boolean | ||
} | ||
|
||
export interface LabwareDisplayLocationSlotOnly | ||
extends LabwareDisplayLocationBaseParams { | ||
detailLevel: 'slot-only' | ||
} | ||
|
||
export interface LabwareDisplayLocationFull | ||
extends LabwareDisplayLocationBaseParams { | ||
detailLevel?: 'full' | ||
allRunDefs: LabwareDefinition2[] | ||
export interface DisplayLocationFullParams extends LocationFullParams { | ||
t: TFunction | ||
isOnDevice?: boolean | ||
} | ||
|
||
export type LabwareDisplayLocationParams = | ||
| LabwareDisplayLocationSlotOnly | ||
| LabwareDisplayLocationFull | ||
export type DisplayLocationParams = | ||
| DisplayLocationSlotOnlyParams | ||
| DisplayLocationFullParams | ||
|
||
// detailLevel applies to nested labware. If 'full', return copy that includes the actual peripheral that nests the | ||
// labware, ex, "in module XYZ in slot C1". | ||
// If 'slot-only', return only the slot name, ex "in slot C1". | ||
export function getLabwareDisplayLocation( | ||
params: LabwareDisplayLocationParams | ||
params: DisplayLocationParams | ||
): string { | ||
const { | ||
loadedLabwares, | ||
loadedModules, | ||
location, | ||
robotType, | ||
t, | ||
isOnDevice = false, | ||
detailLevel = 'full', | ||
} = params | ||
const { t, isOnDevice = false } = params | ||
const locationResult = getLabwareLocation(params) | ||
|
||
if (location == null) { | ||
console.error('Cannot get labware display location. No location provided.') | ||
if (locationResult == null) { | ||
return '' | ||
} else if (location === 'offDeck') { | ||
return t('off_deck') | ||
} else if ('slotName' in location) { | ||
return isOnDevice | ||
? location.slotName | ||
: t('slot', { slot_name: location.slotName }) | ||
} else if ('addressableAreaName' in location) { | ||
return isOnDevice | ||
? location.addressableAreaName | ||
: t('slot', { slot_name: location.addressableAreaName }) | ||
} else if ('moduleId' in location) { | ||
const moduleModel = getModuleModel(loadedModules, location.moduleId) | ||
if (moduleModel == null) { | ||
console.error('labware is located on an unknown module model') | ||
return '' | ||
} | ||
const slotName = getModuleDisplayLocation(loadedModules, location.moduleId) | ||
} | ||
|
||
if (detailLevel === 'slot-only') { | ||
return t('slot', { slot_name: slotName }) | ||
} | ||
const { slotName, moduleModel, adapterName } = locationResult | ||
|
||
return isOnDevice | ||
? `${getModuleDisplayName(moduleModel)}, ${slotName}` | ||
: t('module_in_slot', { | ||
count: getOccludedSlotCountForModule( | ||
getModuleType(moduleModel), | ||
robotType | ||
), | ||
module: getModuleDisplayName(moduleModel), | ||
slot_name: slotName, | ||
}) | ||
} else if ('labwareId' in location) { | ||
if (!Array.isArray(loadedLabwares)) { | ||
console.error('Cannot get display location from loaded labwares object') | ||
return '' | ||
if (slotName === 'offDeck') { | ||
return t('off_deck') | ||
} | ||
// Simple slot location | ||
else if (moduleModel == null && adapterName == null) { | ||
return isOnDevice ? slotName : t('slot', { slot_name: slotName }) | ||
} | ||
// Module location without adapter | ||
else if (moduleModel != null && adapterName == null) { | ||
if (params.detailLevel === 'slot-only') { | ||
return t('slot', { slot_name: slotName }) | ||
} else { | ||
return isOnDevice | ||
? `${getModuleDisplayName(moduleModel)}, ${slotName}` | ||
: t('module_in_slot', { | ||
count: getOccludedSlotCountForModule( | ||
getModuleType(moduleModel), | ||
params.robotType | ||
), | ||
module: getModuleDisplayName(moduleModel), | ||
slot_name: slotName, | ||
}) | ||
} | ||
const adapter = loadedLabwares.find(lw => lw.id === location.labwareId) | ||
|
||
if (adapter == null) { | ||
console.error('labware is located on an unknown adapter') | ||
return '' | ||
} else if (detailLevel === 'slot-only') { | ||
return getLabwareDisplayLocation({ | ||
...params, | ||
location: adapter.location, | ||
} | ||
// Adapter locations | ||
else if (adapterName != null) { | ||
if (moduleModel == null) { | ||
return t('adapter_in_slot', { | ||
adapter: adapterName, | ||
slot: slotName, | ||
}) | ||
} else if (detailLevel === 'full') { | ||
const { allRunDefs } = params as LabwareDisplayLocationFull | ||
const adapterDef = allRunDefs.find( | ||
def => getLabwareDefURI(def) === adapter?.definitionUri | ||
) | ||
const adapterDisplayName = | ||
adapterDef != null ? getLabwareDisplayName(adapterDef) : '' | ||
|
||
if (adapter.location === 'offDeck') { | ||
return t('off_deck') | ||
} else if ( | ||
'slotName' in adapter.location || | ||
'addressableAreaName' in adapter.location | ||
) { | ||
const slotName = | ||
'slotName' in adapter.location | ||
? adapter.location.slotName | ||
: adapter.location.addressableAreaName | ||
return t('adapter_in_slot', { | ||
adapter: adapterDisplayName, | ||
slot: slotName, | ||
}) | ||
} else if ('moduleId' in adapter.location) { | ||
const moduleIdUnderAdapter = adapter.location.moduleId | ||
|
||
if (!Array.isArray(loadedModules)) { | ||
console.error( | ||
'Cannot get display location from loaded modules object' | ||
) | ||
return '' | ||
} | ||
|
||
const moduleModel = loadedModules.find( | ||
module => module.id === moduleIdUnderAdapter | ||
)?.model | ||
if (moduleModel == null) { | ||
console.error('labware is located on an adapter on an unknown module') | ||
return '' | ||
} | ||
const slotName = getModuleDisplayLocation( | ||
loadedModules, | ||
adapter.location.moduleId | ||
) | ||
|
||
return t('adapter_in_mod_in_slot', { | ||
count: getOccludedSlotCountForModule( | ||
getModuleType(moduleModel), | ||
robotType | ||
), | ||
module: getModuleDisplayName(moduleModel), | ||
adapter: adapterDisplayName, | ||
slot: slotName, | ||
}) | ||
} else { | ||
console.error( | ||
'Unhandled adapter location for determining display location.' | ||
) | ||
return '' | ||
} | ||
} else { | ||
console.error('Unhandled detail level for determining display location.') | ||
return '' | ||
return t('adapter_in_mod_in_slot', { | ||
count: getOccludedSlotCountForModule( | ||
getModuleType(moduleModel), | ||
params.robotType | ||
), | ||
module: getModuleDisplayName(moduleModel), | ||
adapter: adapterName, | ||
slot: slotName, | ||
}) | ||
} | ||
} else { | ||
console.error('display location could not be established: ', location) | ||
return '' | ||
} | ||
} |
147 changes: 147 additions & 0 deletions
147
app/src/local-resources/labware/utils/getLabwareLocation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { getLabwareDefURI, getLabwareDisplayName } from '@opentrons/shared-data' | ||
|
||
import { | ||
getModuleDisplayLocation, | ||
getModuleModel, | ||
} from '/app/local-resources/modules' | ||
|
||
import type { | ||
LabwareDefinition2, | ||
LabwareLocation, | ||
ModuleModel, | ||
RobotType, | ||
} from '@opentrons/shared-data' | ||
import type { LoadedLabwares } from '/app/local-resources/labware' | ||
import type { LoadedModules } from '/app/local-resources/modules' | ||
|
||
export interface LocationResult { | ||
slotName: string | ||
moduleModel?: ModuleModel | ||
adapterName?: string | ||
} | ||
|
||
interface BaseParams { | ||
location: LabwareLocation | null | ||
loadedModules: LoadedModules | ||
loadedLabwares: LoadedLabwares | ||
robotType: RobotType | ||
} | ||
|
||
export interface LocationSlotOnlyParams extends BaseParams { | ||
detailLevel: 'slot-only' | ||
} | ||
|
||
export interface LocationFullParams extends BaseParams { | ||
allRunDefs: LabwareDefinition2[] | ||
detailLevel?: 'full' | ||
} | ||
|
||
export type GetLabwareLocationParams = | ||
| LocationSlotOnlyParams | ||
| LocationFullParams | ||
|
||
// detailLevel returns additional information about the module and adapter in the same location, if applicable. | ||
// if 'slot-only', returns the underlying slot location. | ||
export function getLabwareLocation( | ||
params: GetLabwareLocationParams | ||
): LocationResult | null { | ||
const { | ||
loadedLabwares, | ||
loadedModules, | ||
location, | ||
detailLevel = 'full', | ||
} = params | ||
|
||
if (location == null) { | ||
return null | ||
} else if (location === 'offDeck') { | ||
return { slotName: 'offDeck' } | ||
} else if ('slotName' in location) { | ||
return { slotName: location.slotName } | ||
} else if ('addressableAreaName' in location) { | ||
return { slotName: location.addressableAreaName } | ||
} else if ('moduleId' in location) { | ||
const moduleModel = getModuleModel(loadedModules, location.moduleId) | ||
if (moduleModel == null) { | ||
console.error('labware is located on an unknown module model') | ||
return null | ||
} | ||
const slotName = getModuleDisplayLocation(loadedModules, location.moduleId) | ||
|
||
return { | ||
slotName, | ||
moduleModel, | ||
} | ||
} else if ('labwareId' in location) { | ||
if (!Array.isArray(loadedLabwares)) { | ||
console.error('Cannot get location from loaded labwares object') | ||
return null | ||
} | ||
|
||
const adapter = loadedLabwares.find(lw => lw.id === location.labwareId) | ||
|
||
if (adapter == null) { | ||
console.error('labware is located on an unknown adapter') | ||
return null | ||
} else if (detailLevel === 'slot-only') { | ||
return getLabwareLocation({ | ||
...params, | ||
location: adapter.location, | ||
}) | ||
} else if (detailLevel === 'full') { | ||
const { allRunDefs } = params as LocationFullParams | ||
const adapterDef = allRunDefs.find( | ||
def => getLabwareDefURI(def) === adapter?.definitionUri | ||
) | ||
const adapterName = | ||
adapterDef != null ? getLabwareDisplayName(adapterDef) : '' | ||
|
||
if (adapter.location === 'offDeck') { | ||
return { slotName: 'offDeck', adapterName } | ||
} else if ( | ||
'slotName' in adapter.location || | ||
'addressableAreaName' in adapter.location | ||
) { | ||
const slotName = | ||
'slotName' in adapter.location | ||
? adapter.location.slotName | ||
: adapter.location.addressableAreaName | ||
return { slotName, adapterName } | ||
} else if ('moduleId' in adapter.location) { | ||
const moduleIdUnderAdapter = adapter.location.moduleId | ||
|
||
if (!Array.isArray(loadedModules)) { | ||
console.error('Cannot get location from loaded modules object') | ||
return null | ||
} | ||
|
||
const moduleModel = loadedModules.find( | ||
module => module.id === moduleIdUnderAdapter | ||
)?.model | ||
|
||
if (moduleModel == null) { | ||
console.error('labware is located on an adapter on an unknown module') | ||
return null | ||
} | ||
|
||
const slotName = getModuleDisplayLocation( | ||
loadedModules, | ||
adapter.location.moduleId | ||
) | ||
|
||
return { | ||
slotName, | ||
moduleModel, | ||
adapterName, | ||
} | ||
} else { | ||
return null | ||
} | ||
} else { | ||
console.error('Unhandled detailLevel.') | ||
return null | ||
} | ||
} else { | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.