refactor: migrate UI components and remove chakra

migrate pin page
migrate copy tag
migrate pin input
migrate dropdown menus
migrate radio buttons
migrate switch
migrate select
migrate textarea
migrate colour picker
migrate select
migrate context menu
migrate viewparams
remove chakra
This commit is contained in:
Carlos Valente
2025-07-08 20:50:49 +02:00
committed by Carlos Valente
parent 4d359445a7
commit e1e8410ba4
100 changed files with 1222 additions and 1990 deletions
@@ -13,11 +13,6 @@
gap: 0.5rem;
}
.matchRadio {
display: flex;
gap: 1rem;
}
.ruleSection {
display: flex;
flex-direction: column;
@@ -1,7 +1,6 @@
import { useEffect, useMemo } from 'react';
import { Controller, useFieldArray, useForm } from 'react-hook-form';
import { useFieldArray, useForm } from 'react-hook-form';
import { IoAdd, IoTrash } from 'react-icons/io5';
import { Radio, RadioGroup, Select } from '@chakra-ui/react';
import {
Automation,
AutomationDTO,
@@ -20,6 +19,8 @@ import IconButton from '../../../../common/components/buttons/IconButton';
import Info from '../../../../common/components/info/Info';
import Input from '../../../../common/components/input/input/Input';
import ExternalLink from '../../../../common/components/link/external-link/ExternalLink';
import RadioGroup from '../../../../common/components/radio-group/RadioGroup';
import Select from '../../../../common/components/select/Select';
import Tag from '../../../../common/components/tag/Tag';
import useAutomationSettings from '../../../../common/hooks-query/useAutomationSettings';
import useCustomFields from '../../../../common/hooks-query/useCustomFields';
@@ -214,15 +215,14 @@ export default function AutomationForm(props: AutomationFormProps) {
<div className={style.ruleSection}>
<label>
Trigger outputs if
<Controller
name='filterRule'
control={control}
render={({ field }) => (
<RadioGroup {...field} size='sm' className={style.matchRadio} variant='ontime'>
<Radio value='all'>All filters pass</Radio>
<Radio value='any'>Any filter passes</Radio>
</RadioGroup>
)}
<RadioGroup
orientation='horizontal'
value={watch('filterRule')}
onValueChange={(value) => setValue('filterRule', value, { shouldDirty: true })}
items={[
{ value: 'all', label: 'All filters pass' },
{ value: 'any', label: 'Any filter passes' },
]}
/>
</label>
{fieldFilters.map((field, index) => {
@@ -232,43 +232,29 @@ export default function AutomationForm(props: AutomationFormProps) {
<label>
Runtime data source
<Select
{...register(`filters.${index}.field`, { required: { value: true, message: 'Required field' } })}
size='sm'
variant='ontime'
>
<option selected hidden disabled value=''>
Event field
</option>
{fieldList.map(({ value, label }, localIndex) => {
const key = `filters.${index}.field.${localIndex}`;
return (
<option key={key} value={value}>
{label}
</option>
);
})}
</Select>
value={watch(`filters.${index}.field`)}
onValueChange={(value) => setValue(`filters.${index}.field`, value, { shouldDirty: true })}
options={fieldList.map(({ value, label }) => ({ value, label }))}
aria-label='Event field'
/>
<Panel.Error>{errors.filters?.[index]?.field?.message}</Panel.Error>
</label>
<label>
Matching condition
<Select
{...register(`filters.${index}.operator`, { required: { value: true, message: 'Required field' } })}
size='sm'
variant='ontime'
>
<option selected hidden disabled value=''>
Operator
</option>
<option value='equals'>equals</option>
<option value='not_equals'>not equals</option>
<option value='contains'>contains</option>
{/*
We dont currently offer a data source where these operators would make sense
<option value='greater_than'>greater than</option>
<option value='less_than'>less than</option>
*/}
</Select>
value={watch(`filters.${index}.operator`)}
onValueChange={(value) =>
setValue(`filters.${index}.operator`, value as 'equals' | 'not_equals' | 'contains', {
shouldDirty: true,
})
}
options={[
{ value: 'equals', label: 'equals' },
{ value: 'not_equals', label: 'not equals' },
{ value: 'contains', label: 'contains' },
]}
aria-label='Operator'
/>
<Panel.Error>{errors.filters?.[index]?.operator?.message}</Panel.Error>
</label>
<label>
@@ -1,5 +1,4 @@
import { Controller, useForm } from 'react-hook-form';
import { Switch } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { editAutomationSettings } from '../../../../common/api/automation';
import { maybeAxiosError } from '../../../../common/api/utils';
@@ -7,6 +6,7 @@ import Button from '../../../../common/components/buttons/Button';
import Info from '../../../../common/components/info/Info';
import Input from '../../../../common/components/input/input/Input';
import ExternalLink from '../../../../common/components/link/external-link/ExternalLink';
import Switch from '../../../../common/components/switch/Switch';
import { preventEscape } from '../../../../common/utils/keyEvent';
import { isOnlyNumbers } from '../../../../common/utils/regex';
import { isOntimeCloud } from '../../../../externals';
@@ -24,11 +24,12 @@ export default function AutomationSettingsForm(props: AutomationSettingsProps) {
const { enabledAutomations, enabledOscIn, oscPortIn } = props;
const {
control,
handleSubmit,
reset,
register,
setError,
watch,
setValue,
formState: { errors, isSubmitting, isDirty, isValid },
} = useForm<AutomationSettingsProps>({
mode: 'onChange',
@@ -103,12 +104,10 @@ export default function AutomationSettingsForm(props: AutomationSettingsProps) {
description='Allow Ontime to send messages on lifecycle triggers'
error={errors.enabledAutomations?.message}
/>
<Controller
control={control}
name='enabledAutomations'
render={({ field: { onChange, value, ref } }) => (
<Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
)}
<Switch
size='large'
checked={watch('enabledAutomations')}
onCheckedChange={(value: boolean) => setValue('enabledAutomations', value, { shouldDirty: true })}
/>
</Panel.ListItem>
</Panel.ListGroup>
@@ -123,12 +122,10 @@ export default function AutomationSettingsForm(props: AutomationSettingsProps) {
description='Allow control of Ontime through OSC'
error={errors.enabledOscIn?.message}
/>
<Controller
control={control}
name='enabledOscIn'
render={({ field: { onChange, value, ref } }) => (
<Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
)}
<Switch
size='large'
checked={watch('enabledOscIn')}
onCheckedChange={(value: boolean) => setValue('enabledOscIn', value, { shouldDirty: true })}
/>
</Panel.ListItem>
<Panel.ListItem>
@@ -1,12 +1,12 @@
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { Select } from '@chakra-ui/react';
import { NormalisedAutomation, TimerLifeCycle, TriggerDTO } from 'ontime-types';
import { addTrigger, editTrigger } from '../../../../common/api/automation';
import { maybeAxiosError } from '../../../../common/api/utils';
import Button from '../../../../common/components/buttons/Button';
import Input from '../../../../common/components/input/input/Input';
import Select from '../../../../common/components/select/Select';
import { preventEscape } from '../../../../common/utils/keyEvent';
import * as Panel from '../../panel-utils/PanelUtils';
@@ -29,6 +29,8 @@ export default function TriggerForm(props: TriggerFormProps) {
register,
setFocus,
setError,
watch,
setValue,
formState: { errors, isSubmitting, isValid, isDirty },
} = useForm<TriggerDTO>({
defaultValues: {
@@ -44,8 +46,7 @@ export default function TriggerForm(props: TriggerFormProps) {
// give initial focus to the title field
useEffect(() => {
setFocus('title');
// eslint-disable-next-line react-hooks/exhaustive-deps -- focus on mount
}, []);
}, [setFocus]);
const onSubmit = async (values: TriggerDTO) => {
// if we were passed an ID we are editing a Trigger
@@ -97,33 +98,21 @@ export default function TriggerForm(props: TriggerFormProps) {
<label>
Lifecycle trigger
<Select
size='sm'
variant='ontime'
defaultValue={initialTrigger}
{...register('trigger', { required: { value: true, message: 'Required field' } })}
>
{cycles.map((cycle) => (
<option key={cycle.id} value={cycle.value}>
{cycle.label}
</option>
))}
</Select>
value={watch('trigger')}
onValueChange={(value) => setValue('trigger', value as TimerLifeCycle, { shouldDirty: true })}
options={cycles.map((cycle) => ({ value: cycle.value, label: cycle.label }))}
aria-label='Lifecycle trigger'
/>
<Panel.Error>{errors.trigger?.message}</Panel.Error>
</label>
<label>
Automation title
<Select
size='sm'
variant='ontime'
defaultValue={initialAutomationId}
{...register('automationId', { required: { value: true, message: 'Required field' } })}
>
{automationSelect.map((automation) => (
<option key={automation.value} value={automation.value}>
{automation.label}
</option>
))}
</Select>
value={watch('automationId')}
onValueChange={(value) => setValue('automationId', value, { shouldDirty: true })}
options={automationSelect}
aria-label='Automation title'
/>
<Panel.Error>{errors.automationId?.message}</Panel.Error>
</label>
<Panel.InlineElements align='end'>