mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 05:45:22 +02:00
feat(edge/jobs): migrate item view to react [EE-2220] (#11887)
Some checks failed
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
ci / build_images (map[arch:arm platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:s390x platform:linux version:]) (push) Has been cancelled
/ triage (push) Has been cancelled
Lint / Run linters (push) Has been cancelled
Test / test-client (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:linux]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
Test / test-server (map[arch:arm64 platform:linux]) (push) Has been cancelled
ci / build_manifests (push) Has been cancelled
Some checks failed
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
ci / build_images (map[arch:arm platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:s390x platform:linux version:]) (push) Has been cancelled
/ triage (push) Has been cancelled
Lint / Run linters (push) Has been cancelled
Test / test-client (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:linux]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
Test / test-server (map[arch:arm64 platform:linux]) (push) Has been cancelled
ci / build_manifests (push) Has been cancelled
This commit is contained in:
parent
62c2bf86aa
commit
eb6d251a73
44 changed files with 778 additions and 886 deletions
|
@ -2,7 +2,8 @@ import { useFormikContext } from 'formik';
|
|||
|
||||
import { SwitchField } from '@@/form-components/SwitchField';
|
||||
|
||||
import { FormValues } from './types';
|
||||
import { FormValues } from '../../CreateView/types';
|
||||
|
||||
import { RecurringFieldset, defaultCronExpression } from './RecurringFieldset';
|
||||
import { ScheduledDateFieldset } from './ScheduledDateFieldset';
|
||||
|
||||
|
|
|
@ -1,14 +1,33 @@
|
|||
import { useFormikContext } from 'formik';
|
||||
import { Calendar, Edit } from 'lucide-react';
|
||||
|
||||
import { FormSection } from '@@/form-components/FormSection';
|
||||
import { BoxSelector } from '@@/BoxSelector';
|
||||
import { BoxSelector, BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
import { cronMethodOptions } from '../../CreateView/cron-method-options';
|
||||
import { FormValues } from '../../CreateView/types';
|
||||
|
||||
import { FormValues } from './types';
|
||||
import { AdvancedCronFieldset } from './AdvancedCronFieldset';
|
||||
import { BasicCronFieldset } from './BasicCronFieldset';
|
||||
|
||||
export const cronMethodOptions: ReadonlyArray<BoxSelectorOption<string>> = [
|
||||
{
|
||||
id: 'config_basic',
|
||||
value: 'basic',
|
||||
icon: Calendar,
|
||||
iconType: 'badge',
|
||||
label: 'Basic configuration',
|
||||
description: 'Select date from calendar',
|
||||
},
|
||||
{
|
||||
id: 'config_advanced',
|
||||
value: 'advanced',
|
||||
icon: Edit,
|
||||
iconType: 'badge',
|
||||
label: 'Advanced configuration',
|
||||
description: 'Write your own cron rule',
|
||||
},
|
||||
] as const;
|
||||
|
||||
export function JobConfigurationFieldset() {
|
||||
const { values, setFieldValue } = useFormikContext<FormValues>();
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import { addHours, getDate, getHours, getMinutes, getMonth } from 'date-fns';
|
||||
import moment from 'moment';
|
||||
|
||||
import { defaultCronExpression, timeOptions } from './RecurringFieldset';
|
||||
|
||||
interface RecurringViewModel {
|
||||
cronMethod: 'basic' | 'advanced';
|
||||
cronExpression: string;
|
||||
recurring: boolean;
|
||||
recurringOption: (typeof timeOptions)[number]['value'];
|
||||
dateTime: Date;
|
||||
}
|
||||
|
||||
interface RecurringRequestModel {
|
||||
recurring: boolean;
|
||||
cronExpression: string;
|
||||
}
|
||||
|
||||
export function toRecurringRequest(
|
||||
values: RecurringViewModel
|
||||
): RecurringRequestModel {
|
||||
if (values.cronMethod !== 'basic') {
|
||||
return {
|
||||
recurring: true,
|
||||
cronExpression: values.cronExpression,
|
||||
};
|
||||
}
|
||||
|
||||
if (values.recurring) {
|
||||
return {
|
||||
recurring: true,
|
||||
cronExpression: values.recurringOption,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
recurring: false,
|
||||
cronExpression: dateTimeToCron(values.dateTime),
|
||||
};
|
||||
|
||||
function dateTimeToCron(date: Date) {
|
||||
return [
|
||||
getMinutes(date),
|
||||
getHours(date),
|
||||
getDate(date),
|
||||
getMonth(date) + 1,
|
||||
'*',
|
||||
].join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
export function toRecurringViewModel(
|
||||
{ cronExpression, recurring }: RecurringRequestModel = {
|
||||
cronExpression: defaultCronExpression,
|
||||
recurring: true,
|
||||
}
|
||||
): RecurringViewModel {
|
||||
const defaultTime = addHours(new Date(), 1);
|
||||
const scheduled = timeOptions.find((v) => v.value === cronExpression);
|
||||
|
||||
return {
|
||||
recurring,
|
||||
cronExpression,
|
||||
recurringOption: scheduled?.value || defaultCronExpression,
|
||||
cronMethod: recurring && !scheduled ? 'advanced' : 'basic',
|
||||
dateTime: cronExpression
|
||||
? cronToDateTime(cronExpression, defaultTime)
|
||||
: defaultTime,
|
||||
};
|
||||
}
|
||||
|
||||
function cronToDateTime(cron: string, defaultTime: Date): Date {
|
||||
const strings = cron.split(' ');
|
||||
if (strings.length > 4) {
|
||||
return moment(cron, 'm H D M').toDate();
|
||||
}
|
||||
|
||||
return defaultTime;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
import { EdgeGroup } from '@/react/edge/edge-groups/types';
|
||||
import { EnvironmentId } from '@/react/portainer/environments/types';
|
||||
|
||||
import { timeOptions } from './RecurringFieldset';
|
||||
|
||||
export interface FormValues {
|
||||
name: string;
|
||||
recurring: boolean;
|
||||
edgeGroupIds: Array<EdgeGroup['Id']>;
|
||||
environmentIds: Array<EnvironmentId>;
|
||||
|
||||
method: 'editor' | 'upload';
|
||||
fileContent: string;
|
||||
file: File | undefined;
|
||||
|
||||
cronMethod: 'basic' | 'advanced';
|
||||
dateTime: Date; // basic !recurring
|
||||
recurringOption: (typeof timeOptions)[number]['value']; // basic recurring
|
||||
cronExpression: string; // advanced
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
import {
|
||||
SchemaOf,
|
||||
array,
|
||||
boolean,
|
||||
date,
|
||||
mixed,
|
||||
number,
|
||||
object,
|
||||
string,
|
||||
} from 'yup';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { file } from '@@/form-components/yup-file-validation';
|
||||
|
||||
import { EdgeJob } from '../../types';
|
||||
|
||||
import { FormValues } from './types';
|
||||
import { useNameValidation } from './NameField';
|
||||
import { cronValidation } from './AdvancedCronFieldset';
|
||||
import { timeOptions } from './RecurringFieldset';
|
||||
|
||||
export function useValidation({
|
||||
id,
|
||||
}: { id?: EdgeJob['Id'] } = {}): SchemaOf<FormValues> {
|
||||
const nameValidation = useNameValidation(id);
|
||||
return useMemo(
|
||||
() =>
|
||||
object({
|
||||
name: nameValidation,
|
||||
recurring: boolean().default(false),
|
||||
cronExpression: string().default('').when('cronMethod', {
|
||||
is: 'advanced',
|
||||
then: cronValidation().required(),
|
||||
}),
|
||||
edgeGroupIds: array(number().required()),
|
||||
environmentIds: array(number().required()),
|
||||
|
||||
method: mixed<'editor' | 'upload'>()
|
||||
.oneOf(['editor', 'upload'])
|
||||
.default('editor'),
|
||||
file: file().when('method', {
|
||||
is: 'upload',
|
||||
then: object().required('This field is required.'),
|
||||
}),
|
||||
fileContent: string()
|
||||
.default('')
|
||||
.when('method', {
|
||||
is: 'editor',
|
||||
then: (schema) => schema.required('This field is required.'),
|
||||
}),
|
||||
|
||||
cronMethod: mixed<'basic' | 'advanced'>()
|
||||
.oneOf(['basic', 'advanced'])
|
||||
.default('basic'),
|
||||
dateTime: date()
|
||||
.default(new Date())
|
||||
.when(['recurring', 'cronMethod'], {
|
||||
is: (recurring: boolean, cronMethod: 'basic' | 'advanced') =>
|
||||
!recurring && cronMethod === 'basic',
|
||||
then: (schema) => schema.required('This field is required.'),
|
||||
}),
|
||||
recurringOption: mixed()
|
||||
.oneOf(timeOptions.map((o) => o.value))
|
||||
.when(['recurring', 'cronMethod'], {
|
||||
is: (recurring: boolean, cronMethod: 'basic' | 'advanced') =>
|
||||
recurring && cronMethod === 'basic',
|
||||
then: (schema) => schema.required('This field is required.'),
|
||||
}),
|
||||
}),
|
||||
[nameValidation]
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue