keycloak-scim/src/clients/authorization/policy/Time.tsx

218 lines
5.4 KiB
TypeScript
Raw Normal View History

import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import moment from "moment";
import { Controller, useFormContext } from "react-hook-form";
import {
DatePicker,
Flex,
FlexItem,
FormGroup,
NumberInput,
Radio,
Split,
SplitItem,
TimePicker,
} from "@patternfly/react-core";
import { HelpItem } from "../../../components/help-enabler/HelpItem";
const DATE_TIME_FORMAT = /(\d\d\d\d-\d\d-\d\d)? (\d\d?):(\d\d?)/;
const DateTime = ({ name }: { name: string }) => {
const { control } = useFormContext();
const parseDate = (value: string, date?: Date): string => {
const parts = value.match(DATE_TIME_FORMAT);
if (date) {
const parsedDate = moment(date).format("yyyy-MM-DD");
return `${parsedDate} ${parts ? parts[2] : "00"}:${
parts ? parts[3] : "00"
}:00`;
}
return value;
};
const parseTime = (
value: string,
hour?: number | null,
minute?: number | null
): string => {
const parts = value.match(DATE_TIME_FORMAT);
if (minute !== undefined && minute !== null) {
return `${parts ? parts[1] : ""} ${hour}:${
minute < 10 ? `0${minute}` : minute
}:00`;
}
return value;
};
return (
<Controller
name={name}
defaultValue=""
control={control}
render={({ onChange, value }) => {
const dateTime = value.match(DATE_TIME_FORMAT) || ["", "", "0", "00"];
return (
<Split hasGutter id={name}>
<SplitItem>
<DatePicker
value={dateTime[1]}
onChange={(_, date) => {
onChange(parseDate(value, date));
}}
/>
</SplitItem>
<SplitItem>
<TimePicker
time={`${dateTime[2]}:${dateTime[3]}`}
onChange={(_, hour, minute) =>
onChange(parseTime(value, hour, minute))
}
is24Hour
/>
</SplitItem>
</Split>
);
}}
/>
);
};
type NumberControlProps = {
name: string;
min: number;
max: number;
};
const NumberControl = ({ name, min, max }: NumberControlProps) => {
const { control } = useFormContext();
const setValue = (newValue: number) => Math.min(newValue, max);
return (
<Controller
name={name}
defaultValue=""
control={control}
render={({ onChange, value }) => (
<NumberInput
id={name}
value={value}
min={min}
max={max}
onPlus={() => onChange(Number(value) + 1)}
onMinus={() => onChange(Number(value) - 1)}
onChange={(event) => {
const newValue = Number(event.currentTarget.value);
onChange(setValue(!isNaN(newValue) ? newValue : 0));
}}
/>
)}
/>
);
};
const FromTo = ({ name, ...rest }: NumberControlProps) => {
const { t } = useTranslation("clients");
return (
<FormGroup
label={t(name)}
fieldId={name}
labelIcon={
<HelpItem
helpText={`clients-help:${name}`}
fieldLabelId={`clients:${name}`}
/>
}
>
<Split hasGutter>
<SplitItem>
<NumberControl name={name} {...rest} />
</SplitItem>
<SplitItem>{t("common:to")}</SplitItem>
<SplitItem>
<NumberControl name={`${name}End`} {...rest} />
</SplitItem>
</Split>
</FormGroup>
);
};
export const Time = () => {
const { t } = useTranslation("clients");
const { getValues } = useFormContext();
const [repeat, setRepeat] = useState(getValues("month"));
return (
<>
<FormGroup
label={t("repeat")}
fieldId="repeat"
labelIcon={
<HelpItem
helpText="clients-help:repeat"
fieldLabelId="clients:repeat"
/>
}
>
<Flex>
<FlexItem>
<Radio
id="notRepeat"
data-testid="notRepeat"
isChecked={!repeat}
name="repeat"
onChange={() => setRepeat(false)}
label={t("notRepeat")}
className="pf-u-mb-md"
/>
</FlexItem>
<FlexItem>
<Radio
id="repeat"
data-testid="repeat"
isChecked={repeat}
name="repeat"
onChange={() => setRepeat(true)}
label={t("repeat")}
className="pf-u-mb-md"
/>
</FlexItem>
</Flex>
</FormGroup>
{repeat && (
<>
<FromTo name="month" min={1} max={12} />
<FromTo name="dayMonth" min={1} max={31} />
<FromTo name="hour" min={0} max={23} />
<FromTo name="minute" min={0} max={59} />
</>
)}
<FormGroup
label={t("startTime")}
fieldId="notBefore"
labelIcon={
<HelpItem
helpText="clients-help:startTime"
fieldLabelId="clients:startTime"
/>
}
>
<DateTime name="notBefore" />
</FormGroup>
<FormGroup
label={t("expireTime")}
fieldId="notOnOrAfter"
labelIcon={
<HelpItem
helpText="clients-help:expireTime"
fieldLabelId="clients:expireTime"
/>
}
>
<DateTime name="notOnOrAfter" />
</FormGroup>
</>
);
};