Skip to main content

Hardware Components

Hardware components are loaded by the Hardware Object component. The type from the REST response tells the UI which component to load using the objMap lookup table. To add a new component import your component and extend this object.

import MyComponent from 'components/hardware/MyComponent';

export const objMap = {
...
mycomponent: MyComponent
}

Building a New Hardware Component

Components should be placed into src/components/hardware and export a single default component. New components should be built as React functional component using typescript.

To be consistent with other hardware objects components should make use of <HardwareTemplate>, <HardwareState>, and <TypeIcon>.

options should extend HardwareTypes.HardwareWidgetOptions and document its properties using jsdoc notation.

src/components/hardware/Component.tsx
import {
TypeIcon,
HardwareTemplate,
HardwareState,
HardwareTypes,
} from '@esrf/daiquiri-lib';

// Define the interface of the properties recieved from the REST API
export interface ComponentSchema extends HardwareTypes.Hardware {
properties: {
property: string;
property2: number;
};
}

// Define the interface of the component options
export interface ComponentOptions extends HardwareTypes.HardwareWidgetOptions {
/** Make the arrows large */
large?: number;
}

export function Component(
props: HardwareTypes.HardwareWidgetProps<ComponentSchema, ComponentOptions>
) {
const { hardware, options = {}, disabled } = props;
const { state } = hardware.properties;

return (
<HardwareTemplate
hardware={hardware}
widgetIcon={
<TypeIcon name="Component" icon="fa-cog" online={hardware.online} />
}
widgetState={
<HardwareState.HardwareState
state={state}
minWidth={6}
variant={state === 'READY' ? 'success' : 'warning'}
/>
}
widgetContent={
...
}
/>
);
}

Will render:

Props

Components will be passed a series of props:

<PropTable>: Couldn't find prop definition for `HWComponent`
HardwareTypes.EditableHardware<HWComponentSchema>
<PropTable>: Couldn't find prop definition for `HWComponentHardware`
HWComponentSchema

Schemas are defined by the server for properties and callables, both in standard JSONSchema format. These can be used for validation and automatic form creation with react-jsonschema-form

<PropTable>: Couldn't find prop definition for `HWComponentSchema`

Options

An example layout yaml from the server may look like:

layout.yml
- type: component
component: hardware
title: Diffractometer3
ids:
- id: omega
variant: small
step: 90
- id: robz
variant: small
precision: 3

variant, step, and precision will be passed as options into the specific hardware component.

TypeIcon

The <TypeIcon> component takes a few props

<PropTable>: Couldn't find prop definition for `TypeIcon`

Updating Components

The hardware.actions prop can be used to update the hardware object on the server. This function can be called in two ways, one to modify a property and the other to make a function call.

To update a property:

onClick = () => {
hardware.actions.setProperty('exposure', 0.5);
};

To call a function:

onClick = () => {
hardware.actions.call('move', 10);
};

Variants

For some components it is useful to specify different variants. For example a normal motor widget and a small one. Daiquiri UI provides some helper classes to implement this functionality easily.

For example the motor variant class:

import { HardwareVariant } from '@esrf/daiquiri-lib';

import MotorDefault from 'components/hardware/motor/MotorDefault';
import MotorSmall from 'components/hardware/motor/MotorSmall';

export default class Motor extends HardwareVariant {
variants = {
default: MotorDefault,
small: MotorSmall,
};
}

The HardwareVariant class responds to the variant option from the yaml config. If a variant is not found the component will use the default.

- type: component
component: hardware
title: Diffractometer3
options:
ids:
- id: omega
variant: small
step: 90

Documentation

Make sure to provide a component mockup, this should be placed into docusaurus/docs/ui-components/hardware/MyComponent.mdx and the json markup for the mock response should go in src/components/mocks/hardware/MyComponent.json.

The component should be wrapped in <DaiquiriHardwareObject> in the markdown documentation file and will be transformed into a component mockup, for example:

docasaurus/docs/ui-components/hardware/Component.mdx
import DaiquiriHardwareObject from '@site/src/DaiquiriHardwareObject';

import Shutter from 'daiquiri-ui/src/components/hardware/shutter';
import shutter from 'daiquiri-ui/src/components/mocks/shutter/BeamShutter.json';

<DaiquiriHardwareObject>
<Shutter hardware={shutter} options={{ extended: true }} />;
</DaiquiriHardwareObject>;

Will render:

Options Documentation

A dummy component can be created using only the options interface as its props. This can then be automatically used to generate a props table for the object. This component should be placed in the docusaurus/src/options folder as it serves no purpose in the application code base.

For example:

src/options/HWComponentOptions.tsx
export function HWComponentOptions(props: HWComponentOptions) {
return null;
}

Will generate a prop types definition for the options which can be loaded via:

docasaurus/docs/ui-components/hardware/Component.mdx
import PropTable from '@site/src/PropTable';

<PropTable component="HWComponentOptions" />;

Which will render:

<PropTable>: Couldn't find prop definition for `HWComponentOptions`