2024-07-29 18:54:28 +02:00
|
|
|
import {Button, Form, FormInstance, Input, Select, Space} from "antd";
|
|
|
|
|
import {t} from "ttag";
|
2024-07-30 22:03:04 +02:00
|
|
|
import {ApiOutlined, MinusCircleOutlined, PlusOutlined, ThunderboltFilled} from "@ant-design/icons";
|
|
|
|
|
import React from "react";
|
2024-07-29 18:54:28 +02:00
|
|
|
import {EventAction} from "../../utils/api";
|
2024-07-30 00:55:36 +02:00
|
|
|
import {Connector} from "../../utils/api/connectors";
|
2024-07-29 18:54:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
const formItemLayout = {
|
|
|
|
|
labelCol: {
|
|
|
|
|
xs: {span: 24},
|
|
|
|
|
sm: {span: 4},
|
|
|
|
|
},
|
|
|
|
|
wrapperCol: {
|
|
|
|
|
xs: {span: 24},
|
|
|
|
|
sm: {span: 20},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formItemLayoutWithOutLabel = {
|
|
|
|
|
wrapperCol: {
|
|
|
|
|
xs: {span: 24, offset: 0},
|
|
|
|
|
sm: {span: 20, offset: 4},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-30 00:55:36 +02:00
|
|
|
export function WatchlistForm({form, connectors, onCreateWatchlist}: {
|
2024-07-29 18:54:28 +02:00
|
|
|
form: FormInstance,
|
2024-07-30 00:55:36 +02:00
|
|
|
connectors: (Connector & { id: string })[]
|
2024-07-29 18:54:28 +02:00
|
|
|
onCreateWatchlist: (values: { domains: string[], triggers: { event: string, action: string }[] }) => void
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
|
|
const triggerEventItems: { label: string, value: EventAction }[] = [
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is expired`,
|
|
|
|
|
value: 'expiration'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is deleted`,
|
|
|
|
|
value: 'deletion'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is updated`,
|
|
|
|
|
value: 'last changed'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is transferred`,
|
|
|
|
|
value: 'transfer'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is locked`,
|
|
|
|
|
value: 'locked'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is unlocked`,
|
|
|
|
|
value: 'unlocked'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is reregistered`,
|
|
|
|
|
value: 'reregistration'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is reinstantiated`,
|
|
|
|
|
value: 'reinstantiation'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t`When a domain is registered`,
|
|
|
|
|
value: 'registration'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
2024-07-30 00:55:36 +02:00
|
|
|
const triggerActionItems = [
|
2024-07-29 18:54:28 +02:00
|
|
|
{
|
|
|
|
|
label: t`Send me an email`,
|
|
|
|
|
value: 'email'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
return <Form
|
|
|
|
|
{...formItemLayoutWithOutLabel}
|
|
|
|
|
form={form}
|
|
|
|
|
onFinish={onCreateWatchlist}
|
|
|
|
|
>
|
|
|
|
|
<Form.List
|
|
|
|
|
name="domains"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
validator: async (_, domains) => {
|
|
|
|
|
if (!domains || domains.length < 1) {
|
|
|
|
|
return Promise.reject(new Error(t`At least one domain name`));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
{(fields, {add, remove}, {errors}) => (
|
|
|
|
|
<>
|
|
|
|
|
{fields.map((field, index) => (
|
|
|
|
|
<Form.Item
|
|
|
|
|
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
|
|
|
|
label={index === 0 ? t`Domain names` : ''}
|
|
|
|
|
required={true}
|
|
|
|
|
key={field.key}
|
|
|
|
|
>
|
|
|
|
|
<Form.Item
|
|
|
|
|
{...field}
|
|
|
|
|
validateTrigger={['onChange', 'onBlur']}
|
|
|
|
|
rules={[{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t`Required`
|
|
|
|
|
}, {
|
|
|
|
|
pattern: /^(?=.*\.)\S*[^.\s]$/,
|
|
|
|
|
message: t`This domain name does not appear to be valid`,
|
|
|
|
|
max: 63,
|
|
|
|
|
min: 2
|
|
|
|
|
}]}
|
|
|
|
|
noStyle
|
|
|
|
|
>
|
|
|
|
|
<Input placeholder={t`Domain name`} style={{width: '60%'}} autoComplete='off'/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
{fields.length > 1 ? (
|
|
|
|
|
<MinusCircleOutlined
|
|
|
|
|
className="dynamic-delete-button"
|
|
|
|
|
onClick={() => remove(field.name)}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
))}
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<Button
|
|
|
|
|
type="dashed"
|
|
|
|
|
onClick={() => add()}
|
|
|
|
|
style={{width: '60%'}}
|
|
|
|
|
icon={<PlusOutlined/>}
|
|
|
|
|
>
|
|
|
|
|
{t`Add a Domain name`}
|
|
|
|
|
</Button>
|
|
|
|
|
<Form.ErrorList errors={errors}/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</Form.List>
|
|
|
|
|
<Form.List
|
|
|
|
|
name="triggers"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
validator: async (_, domains) => {
|
|
|
|
|
if (!domains || domains.length < 1) {
|
|
|
|
|
return Promise.reject(new Error(t`At least one domain trigger`));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
{(fields, {add, remove}, {errors}) => (
|
|
|
|
|
<>
|
|
|
|
|
{fields.map((field, index) => (
|
|
|
|
|
<Form.Item
|
|
|
|
|
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
|
|
|
|
label={index === 0 ? t`Domain trigger` : ''}
|
|
|
|
|
required={true}
|
|
|
|
|
key={field.key}
|
|
|
|
|
>
|
|
|
|
|
<Space wrap>
|
|
|
|
|
<Form.Item {...field}
|
|
|
|
|
validateTrigger={['onChange', 'onBlur']}
|
|
|
|
|
rules={[{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t`Required`
|
|
|
|
|
}]}
|
|
|
|
|
noStyle name={[field.name, 'event']}>
|
|
|
|
|
<Select style={{minWidth: 300}} options={triggerEventItems} showSearch
|
|
|
|
|
placeholder={t`If this happens`} optionFilterProp="label"/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item {...field}
|
|
|
|
|
validateTrigger={['onChange', 'onBlur']}
|
|
|
|
|
rules={[{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t`Required`
|
|
|
|
|
}]}
|
|
|
|
|
noStyle name={[field.name, 'action']}>
|
2024-07-30 00:55:36 +02:00
|
|
|
<Select style={{minWidth: 300}} options={triggerActionItems} showSearch
|
2024-07-29 18:54:28 +02:00
|
|
|
placeholder={t`Then do that`}
|
2024-07-30 22:03:04 +02:00
|
|
|
optionFilterProp="label"/>
|
2024-07-30 00:55:36 +02:00
|
|
|
</Form.Item>
|
2024-07-29 18:54:28 +02:00
|
|
|
</Space>
|
|
|
|
|
|
|
|
|
|
{fields.length > 1 ? (
|
|
|
|
|
<MinusCircleOutlined
|
|
|
|
|
className="dynamic-delete-button"
|
|
|
|
|
onClick={() => remove(field.name)}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
))}
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<Button
|
|
|
|
|
type="dashed"
|
|
|
|
|
onClick={() => add()}
|
|
|
|
|
style={{width: '60%'}}
|
|
|
|
|
icon={<ThunderboltFilled/>}
|
|
|
|
|
>
|
|
|
|
|
{t`Add a Trigger`}
|
|
|
|
|
</Button>
|
|
|
|
|
<Form.ErrorList errors={errors}/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</Form.List>
|
2024-07-30 22:03:04 +02:00
|
|
|
<Form.Item label={t`Connector`}
|
|
|
|
|
name='connector'
|
2024-07-31 02:22:36 +02:00
|
|
|
labelCol={{
|
|
|
|
|
xs: {span: 24},
|
|
|
|
|
sm: {span: 4},
|
|
|
|
|
}}
|
|
|
|
|
wrapperCol={{
|
|
|
|
|
md: {span: 12},
|
|
|
|
|
sm: {span: 20},
|
|
|
|
|
}}
|
2024-07-30 22:03:04 +02:00
|
|
|
>
|
|
|
|
|
<Select showSearch
|
|
|
|
|
allowClear
|
|
|
|
|
placeholder={t`Connector`}
|
|
|
|
|
suffixIcon={<ApiOutlined/>}
|
|
|
|
|
optionFilterProp="label"
|
|
|
|
|
options={connectors.map(c => ({
|
|
|
|
|
label: `${c.provider} (${c.id})`,
|
|
|
|
|
value: c.id
|
|
|
|
|
}))}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
2024-07-29 18:54:28 +02:00
|
|
|
<Form.Item>
|
|
|
|
|
<Space>
|
|
|
|
|
<Button type="primary" htmlType="submit">
|
|
|
|
|
{t`Create`}
|
|
|
|
|
</Button>
|
|
|
|
|
<Button type="default" htmlType="reset">
|
|
|
|
|
{t`Reset`}
|
|
|
|
|
</Button>
|
|
|
|
|
</Space>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
}
|