Skip to content

Commit

Permalink
fix(protocol-designer): format export modal mesasge for repeat module…
Browse files Browse the repository at this point in the history
…s and 96-channel (#15249)

Closes RQA-2762

Consolidate modules of the same type into a single plural noun rather
than 'and'-joined repeated modules. Remove mount side for 96-channel
pipette.
  • Loading branch information
ncdiehl11 authored and ryanthecoder committed May 28, 2024
1 parent ec34a0c commit a5ff3a5
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 4 deletions.
49 changes: 45 additions & 4 deletions protocol-designer/src/components/FileSidebar/FileSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,53 @@ function getWarningContent({
}

const pipettesDetails = pipettesWithoutStep
.map(pipette => `${pipette.mount} ${pipette.spec.displayName}`)
.map(pipette =>
pipette.spec.channels === 96
? `${pipette.spec.displayName} pipette`
: `${pipette.mount} ${pipette.spec.displayName} pipette`
)
.join(' and ')

const modulesDetails = modulesWithoutStep
.map(moduleOnDeck => t(`modules:module_long_names.${moduleOnDeck.type}`))
.join(' and ')
const unusedModuleCounts = modulesWithoutStep.reduce<{
[key: string]: number
}>((acc, mod) => {
if (!(mod.type in acc)) {
return { ...acc, [mod.type]: 1 }
} else {
return { ...acc, [mod.type]: acc[mod.type] + 1 }
}
}, {})

const modulesDetails = Object.keys(unusedModuleCounts)
// sorting by module count
.sort((k1, k2) => {
if (unusedModuleCounts[k1] < unusedModuleCounts[k2]) {
return 1
} else if (unusedModuleCounts[k1] > unusedModuleCounts[k2]) {
return -1
} else {
return 0
}
})
.map(modType =>
unusedModuleCounts[modType] === 1
? t(`modules:module_long_names.${modType}`)
: `${t(`modules:module_long_names.${modType}`)}s`
)
// transform list of modules with counts to string
.reduce((acc, modName, index, arr) => {
if (arr.length > 2) {
if (index === arr.length - 1) {
return `${acc} and ${modName}`
} else {
return `${acc}${modName}, `
}
} else if (arr.length === 2) {
return index === 0 ? `${modName} and ` : `${acc}${modName}`
} else {
return modName
}
}, '')

if (pipettesWithoutStep.length && modulesWithoutStep.length) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,58 @@ describe('FileSidebar', () => {
'One or more modules specified in your protocol in Slot(s) A1,B1 are not currently used in any step. In order to run this protocol you will need to power up and connect the modules to your robot.'
)
})
it('renders the formatted unused pipettes and modules warning sorted by count', () => {
vi.mocked(getInitialDeckSetup).mockReturnValue({
modules: {
moduleId1: {
slot: 'A1',
moduleState: {} as any,
id: 'moduleId',
type: 'thermocyclerModuleType',
model: 'thermocyclerModuleV2',
},
moduleId2: {
slot: 'C3',
moduleState: {} as any,
id: 'moduleId1',
type: 'temperatureModuleType',
model: 'temperatureModuleV2',
},
moduleId3: {
slot: 'D3',
moduleState: {} as any,
id: 'moduleId2',
type: 'temperatureModuleType',
model: 'temperatureModuleV2',
},
moduleId4: {
slot: 'C1',
moduleState: {} as any,
id: 'moduleId3',
type: 'heaterShakerModuleType',
model: 'heaterShakerModuleV1',
},
},
pipettes: {
pipetteId: {
mount: 'left',
name: 'p1000_96',
id: 'pipetteId',
tiprackLabwareDef: [fixtureTiprack300ul as LabwareDefinition2],
tiprackDefURI: ['mockDefUri'],
spec: {
displayName: 'mock display name',
channels: 96,
} as any,
},
},
additionalEquipmentOnDeck: {},
labware: {},
})
render()
fireEvent.click(screen.getByRole('button', { name: 'Export' }))
screen.getByText(
'The mock display name pipette and Temperature modules, Thermocycler module, and Heater-Shaker module in your protocol are not currently used in any step. In order to run this protocol you will need to attach this pipette as well as power up and connect the module to your robot.'
)
})
})

0 comments on commit a5ff3a5

Please sign in to comment.