Skip to content

Commit

Permalink
refactor(labware-creator): split apart sections into separate components
Browse files Browse the repository at this point in the history
  • Loading branch information
shlokamin committed Apr 28, 2021
1 parent e036897 commit 12ce1d4
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as React from 'react'
import { useFormikContext } from 'formik'
import cx from 'classnames'
import { PrimaryButton } from '@opentrons/components'
import { Dropdown } from '../../components/Dropdown'
import { labwareTypeOptions } from '../../fields'
import { getFormAlerts } from '../utils/getFormAlerts'
import { SectionBody } from './SectionBody'

import styles from '../../styles.css'
import type { LabwareFields } from '../../fields'

interface Props {
showDropDownOptions: boolean
disabled: boolean
labwareTypeChildFields: any
onClick: () => void
}

const getContent = (props: Props): JSX.Element => {
const {
disabled,
labwareTypeChildFields,
onClick,
showDropDownOptions,
} = props
return (
<div className={styles.labware_type_fields}>
{showDropDownOptions && (
<>
<Dropdown name="labwareType" options={labwareTypeOptions} />
{labwareTypeChildFields}
</>
)}

<PrimaryButton
className={styles.start_creating_btn}
disabled={disabled}
onClick={onClick}
>
start creating labware
</PrimaryButton>
</div>
)
}

export const CreateNewDefinition = (props: Props): JSX.Element => {
const fieldList: Array<keyof LabwareFields> = [
'labwareType',
'tubeRackInsertLoadName',
'aluminumBlockType',
'aluminumBlockChildType',
]
const { values, errors, touched } = useFormikContext<LabwareFields>()

return (
<div className={styles.new_definition_section}>
<SectionBody
label="Create a new definition"
headingClassName={cx(styles.setup_heading, {
[styles.disabled_section]: !props.showDropDownOptions,
})}
>
<>
{getFormAlerts({ values, touched, errors, fieldList })}
{getContent({ ...props })}
</>
</SectionBody>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react'
import { useFormikContext } from 'formik'
import { yesNoOptions } from '../../fields'
import { getFormAlerts } from '../utils/getFormAlerts'
import { RadioField } from '../RadioField'
import { SectionBody } from './SectionBody'

import styles from '../../styles.css'
import type { LabwareFields } from '../../fields'

export const Regularity = (): JSX.Element => {
const fieldList: Array<keyof LabwareFields> = ['homogeneousWells']
const { values, errors, touched } = useFormikContext<LabwareFields>()

const ret = (
<SectionBody label="Regularity">
<>
{getFormAlerts({ values, touched, errors, fieldList })}
<div className={styles.flex_row}>
<div className={styles.homogenous_wells_section}>
<RadioField name="homogeneousWells" options={yesNoOptions} />
</div>
</div>
</>
</SectionBody>
)
return ret
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from 'react'
import styles from '../Section.css'

interface Props {
children: JSX.Element
headingClassName?: string
label: string
}

export const SectionBody = (props: Props): JSX.Element => (
<div className={styles.section_wrapper}>
<h2 className={props.headingClassName || styles.section_header}>
{props.label}
</h2>
{props.children}
</div>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as React from 'react'
import { PrimaryButton } from '@opentrons/components'
import { ImportLabware } from '../ImportLabware'
import styles from '../../styles.css'

interface Props {
disabled: boolean
labwareTypeChildFields: any
lastUploaded: any
onClick: () => void
onUpload: (
event:
| React.DragEvent<HTMLLabelElement>
| React.ChangeEvent<HTMLInputElement>
) => void
}

export const UploadExisting = (props: Props): JSX.Element => {
const {
disabled,
labwareTypeChildFields,
lastUploaded,
onClick,
onUpload,
} = props
return (
<div className={styles.upload_existing_section}>
<h2 className={styles.setup_heading}>
Edit a file you’ve built with our labware creator omg!
</h2>
{lastUploaded === null ? (
<ImportLabware onUpload={onUpload} />
) : (
<div className={styles.labware_type_fields}>
{labwareTypeChildFields}
<PrimaryButton
className={styles.start_creating_btn}
onClick={onClick}
disabled={disabled}
>
start editing labware
</PrimaryButton>
</div>
)}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from 'react'
import compact from 'lodash/compact'
import uniq from 'lodash/uniq'
import { AlertItem } from '@opentrons/components'
import { getIsHidden } from '../../formSelectors'
import { IRREGULAR_LABWARE_ERROR, LINK_CUSTOM_LABWARE_FORM } from '../../fields'
import { LinkOut } from '../LinkOut'

import type { FormikTouched, FormikErrors } from 'formik'
import type { LabwareFields } from '../../fields'

interface Props {
values: LabwareFields
fieldList: Array<keyof LabwareFields>
touched: FormikTouched<LabwareFields>
errors: FormikErrors<LabwareFields>
}

export const getFormAlerts = (props: Props): JSX.Element[] | null => {
const { values, fieldList, touched, errors } = props
if (fieldList != null && fieldList.length > 0) {
const numFieldsHidden = fieldList
.map(field => getIsHidden(field, values))
.filter(Boolean).length

if (numFieldsHidden === fieldList.length) {
// all fields are hidden, don't render this Section
return null
}
}

// show Formik errors (from Yup) as WARNINGs for all dirty fields within this Section
const dirtyFieldNames = fieldList.filter(name => touched[name])
const allErrors: string[] = uniq(
compact(dirtyFieldNames.map(name => errors[name]))
)

return allErrors.map(error => {
if (error === IRREGULAR_LABWARE_ERROR) {
return (
<AlertItem
key={error}
type="error"
title={
<>
Your labware is not compatible with the Labware Creator. Please
fill out{' '}
<LinkOut href={LINK_CUSTOM_LABWARE_FORM}>this form</LinkOut> to
request a custom labware definition.
</>
}
/>
)
}
return <AlertItem key={error} type="warning" title={error} />
})
}
83 changes: 17 additions & 66 deletions labware-library/src/labware-creator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { AlertItem, AlertModal, PrimaryButton } from '@opentrons/components'
import labwareSchema from '@opentrons/shared-data/labware/schemas/2.json'
import { makeMaskToDecimal, maskToInteger, maskLoadName } from './fieldMasks'
import {
labwareTypeOptions,
tubeRackInsertOptions,
aluminumBlockAutofills,
aluminumBlockTypeOptions,
Expand Down Expand Up @@ -42,7 +41,6 @@ import { RadioField } from './components/RadioField'
import { Section } from './components/Section'
import { TextField } from './components/TextField'
import { HeightGuidingText } from './components/HeightGuidingText'
import { ImportLabware } from './components/ImportLabware'
import { ImportErrorModal } from './components/ImportErrorModal'
import {
HeightImg,
Expand All @@ -65,6 +63,9 @@ import type {
LabwareFields,
ProcessedLabwareFields,
} from './fields'
import { CreateNewDefinition } from './components/sections/CreateNewDefinition'
import { UploadExisting } from './components/sections/UploadExisting'
import { Regularity } from './components/sections/Regularity'

const ajv = new Ajv()
const validateLabwareSchema = ajv.compile(labwareSchema)
Expand Down Expand Up @@ -495,75 +496,25 @@ export const LabwareCreator = (): JSX.Element => {
<h2>Custom Labware Creator BETA</h2>
<IntroCopy />
<div className={styles.flex_row}>
<div className={styles.new_definition_section}>
<Section
label="Create a new definition"
fieldList={[
'labwareType',
'tubeRackInsertLoadName',
'aluminumBlockType',
'aluminumBlockChildType',
]}
headingClassName={cx(styles.setup_heading, {
[styles.disabled_section]: lastUploaded !== null,
})}
>
<div className={styles.labware_type_fields}>
{lastUploaded === null ? (
<>
<Dropdown
name="labwareType"
options={labwareTypeOptions}
/>
{labwareTypeChildFields}
</>
) : null}

<PrimaryButton
className={styles.start_creating_btn}
disabled={!canProceedToForm || lastUploaded !== null}
onClick={scrollToForm}
>
start creating labware
</PrimaryButton>
</div>
</Section>
</div>
<div className={styles.upload_existing_section}>
<h2 className={styles.setup_heading}>
Edit a file you’ve built with our labware creator
</h2>
{lastUploaded === null ? (
<ImportLabware onUpload={onUpload} />
) : (
<div className={styles.labware_type_fields}>
{labwareTypeChildFields}
<PrimaryButton
className={styles.start_creating_btn}
onClick={scrollToForm}
disabled={!canProceedToForm}
>
start editing labware
</PrimaryButton>
</div>
)}
</div>
<CreateNewDefinition
showDropDownOptions={lastUploaded === null}
disabled={!canProceedToForm || lastUploaded !== null}
labwareTypeChildFields={labwareTypeChildFields}
onClick={scrollToForm}
/>
<UploadExisting
disabled={!canProceedToForm}
labwareTypeChildFields={labwareTypeChildFields}
lastUploaded={lastUploaded}
onClick={scrollToForm}
onUpload={onUpload}
/>
</div>
<div ref={scrollRef} />
{showCreatorForm && (
<>
{/* PAGE 1 - Labware */}
<Section label="Regularity" fieldList={['homogeneousWells']}>
{/* tubeRackSides: Array<string> maybe?? */}
<div className={styles.flex_row}>
<div className={styles.homogenous_wells_section}>
<RadioField
name="homogeneousWells"
options={yesNoOptions}
/>
</div>
</div>
</Section>
<Regularity />
<Section
label="Footprint"
fieldList={['footprintXDimension', 'footprintYDimension']}
Expand Down

0 comments on commit 12ce1d4

Please sign in to comment.