fix(app): Add special casing for Stacker combination fixtures in deck conflict resolution#18988
fix(app): Add special casing for Stacker combination fixtures in deck conflict resolution#18988
Conversation
| const slotName = | ||
| getModuleType(module.model) === FLEX_STACKER_MODULE_TYPE | ||
| ? getStackerLocationFromSlotName(module.location.slotName) | ||
| : module.location.slotName |
There was a problem hiding this comment.
Is this right?
StackedItemsOnDeck is defined as:
export interface StackedItemsOnDeck {
[slotName: string]: StackItem[]
}Which reads to me like it should always be like "A1": [stackItem1, stackItem2, ...], where "A1" is guaranteed to be a slot ID in the deck definition.
But this looks like it will return something like "STACKER A": [stackItem1, stackItem2, ...], so I'd expect downstream things to have trouble when they try to look up "STACKER A" as a slot ID in the deck def.
There was a problem hiding this comment.
Yeah it is correct based on the implementation for this util which is created around UI concerns for protocol setup. Items represented under "STACKER A": [stackItem1, stackItem2, ...] are in the hopper location, which doesn't exist in the deck definition. Items under "A4" will be stacked on the shuttle location. All users of this util expect this format, but I can update the comment to document this!
There was a problem hiding this comment.
Is there any way this can be made more type-safe? Like this, roughly, instead of a string?
type LocationForStackedItemsOnDeck =
| {
type: "stackerHopper",
row: string // "A" - "D"
} | {
type: "offDeck"
} | {
type: "addressableAreaName"
aaName: string
}You couldn't use these as keys for an object, but you could use them as keys for a Map. Or, instead of returning an object, you could return an array of objects where each object has a location property.
If that's not within reach, then at a minimum, yeah, some doc comments authoritatively describing the full format would be helpful. And I guess slotName in the interface should be called something other than slotName.
There was a problem hiding this comment.
Yeah that's a good suggestion, I think the refactor is out of scope for this PR but I can make a follow up ticket to address this and for now rename the variable and add some better documentation!
| compatibleCutoutFixtureIds, | ||
| deckDef, | ||
| robotName, | ||
| fakeCutoutFixtureId, |
There was a problem hiding this comment.
can you explain what is this prop for? is it always a fake cutout fixture? can we combine it with the cutoutFixtureId?
There was a problem hiding this comment.
This prop is used in cases where we need to split a mag block combination fixture into two items, and represents the cutoutFixtureId that we should use for the display image and name in the UI. For example, if we have a flexStackerModuleV1WithMagneticBlockV1 fixture, we only want to render this as a magneticBlockV1 fixture on the UI but we want to maintain that the protocol requires the combination fixture in order to run, so we can't override the other props. I added this extra prop fakeCutoutFixtureId that in this case will equal magneticBlockV1 and if it exists, will be used for render purposes. Maybe a name like requiredCutoutFixtureIdForDisplay would make more sense here?
There was a problem hiding this comment.
Renamed to partialRequiredCutoutFixtureId - let me know what you think!
| // if the module is a flex stacker in D4, check if it needs a waste chute | ||
| // combo fixture | ||
| if ( | ||
| moduleDef.moduleType === FLEX_STACKER_MODULE_TYPE && |
There was a problem hiding this comment.
can we check that the cutoutId === WASTE_CHUTE_CUTOUT instead of slot name?
There was a problem hiding this comment.
We don't have access to the cutoutId here, we just have the slot name that the module is loaded into!
| const deckConfigCompatabilityD3 = deckConfigCompatibility?.find( | ||
| configItem => configItem.cutoutId === 'cutoutD3' | ||
| ) | ||
| if ( | ||
| deckConfigCompatabilityD3 != null && | ||
| WASTE_CHUTE_FLEX_STACKER_FIXTURES.includes( | ||
| deckConfigCompatabilityD3?.compatibleCutoutFixtureIds[0] | ||
| ) | ||
| ) { | ||
| const comboFixtureId = | ||
| deckConfigCompatabilityD3?.compatibleCutoutFixtureIds[0] | ||
| const comboFixtureConflict = !deckConfigCompatabilityD3?.compatibleCutoutFixtureIds.includes( | ||
| deckConfigCompatabilityD3.cutoutFixtureId | ||
| ) |
There was a problem hiding this comment.
we can use replaceCutoutFixtureWithComboFixture if its helpful?
| addressableAreaId: AddressableAreaNamesWithFakes, | ||
| deckDefinition: DeckDefinition | ||
| ): CutoutConfigMap[][] => { | ||
| if (providedFixtureOptions != null) { |
There was a problem hiding this comment.
why was this removed?
There was a problem hiding this comment.
This is what we were discussing yesterday - I was able to replace the usage of AddFixtureModal with NotConfiguredModal on ODD deck hardware setup. This was the only place that the providedFixtureOptions prop was used so I removed all of the logic related to it.
| ...existingCutoutConfig, | ||
| cutoutFixtureId: replacementCutoutFixtureId, | ||
| opentronsModuleSerialNumber: moduleSerialNumber, | ||
| if ( |
There was a problem hiding this comment.
nice! you can also use the combo fixture method but you will need the aa
| export const isFixtureCompatible = ( | ||
| cutoutFixtureId: CutoutFixtureId, | ||
| compatibleCutoutFixtureIds: CutoutFixtureId[], | ||
| fakeCutoutFixtureId?: CutoutFixtureId |
There was a problem hiding this comment.
im confused about this prop name can you elaborate?
There was a problem hiding this comment.
This is the same field as I described above -- here, cutoutFixtureId is the current CutoutFixtureId in the existing deck config, compatibleCutoutFixtureIds is an array that includes all possible CutoutFixtureId that can satisfy the protocol's hardware requirements, and fakeCutoutFixtureId if it exists will be the fixture id that for the current item assessing compatibility for.
For example, if a protocol requires a mag block with staging area combination fixture we'd need to determine compatibility for each the mag block and the staging area and show a status for them in hardware setup. If you had a staging area configured but no mag block, you'd see a connected status for the staging area item and a not configured status for the mag block.
The inputs/outputs of the function in this case would be as follows:
For Mag Block -
isFixtureCompatible('stagingAreaRightSlot', ['stagingAreaSlotWithMagneticBlockV1'], 'magneticBlockV1') will evaluate to false
For Staging Area -
isFixtureCompatible('stagingAreaRightSlot', ['stagingAreaSlotWithMagneticBlockV1'], 'stagingAreaRightSlot') will evaluate to true
There was a problem hiding this comment.
Added some clarifying comments to the functions here too
TamarZanzouri
left a comment
There was a problem hiding this comment.
overall looks great! had a few questions and suggestions
… for waste chute + stacker
…ure in odd conflict resolution
68ecd5a to
bdb0899
Compare
TamarZanzouri
left a comment
There was a problem hiding this comment.
looks great! thank you for addressing the comments!
closes RQA-4382, RQA-4319, EXEC-1416
Overview
This PR rounds out the necessary work for the modules & fixtures deck conflict resolution section of protocol setup on desktop and ODD. See changelog for specifics!
Test Plan and Hands on Testing
On both Desktop and ODD, check the following:
Changelog
FixtureTableandSetupFixtureListto utilities so we aren't duplicating this logic.patchDeckConfigForRequiredFixturethat enables us to add a fixture without removing a combination fixture. For example, if you have a waste chute in D3 and need to add a Flex Stacker, this will be patched into a waste chute flex stacker combination fixtureNotConfiguredModalinstead ofAddFixtureModalfor case in which you configure a non-conflicted fixture on ODD, which allows us to remove provided fixture logic inAddFixtureModaland remove deck config page of protocol setup, which seems to be a legacy page that was only shown under a modal in this specific instance. MoveNotConfiguredModalto a shared location to enable thisReview requests
Take a look at the logic, especially Tamar :)
Risk assessment
Medium, but its been thoroughly tested