import intl from 'react-intl-universal'; import React, { useCallback, useEffect, useState } from 'react'; import { Modal, message, InputNumber, Form, Radio, Select, Input, Switch, } from 'antd'; import { request } from '@/utils/http'; import config from '@/utils/config'; import CronExpressionParser from 'cron-parser'; import isNil from 'lodash/isNil'; const { Option } = Select; const repoUrlRegx = /([^\/\:]+\/[^\/]+)(?=\.git)/; const fileUrlRegx = /([^\/\:]+\/[^\/\.]+)\.[a-z]+$/; const SubscriptionModal = ({ subscription, handleCancel, }: { subscription?: any; handleCancel: (needUpdate?: boolean) => void; }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [type, setType] = useState(subscription?.type || 'public-repo'); const [scheduleType, setScheduleType] = useState( subscription?.schedule_type || 'crontab', ); const [pullType, setPullType] = useState<'ssh-key' | 'user-pwd'>( subscription?.pull_type || 'ssh-key', ); const handleOk = async (values: any) => { setLoading(true); const method = subscription ? 'put' : 'post'; const payload = { ...values, autoAddCron: Boolean(values.autoAddCron), autoDelCron: Boolean(values.autoDelCron), }; if (subscription) { payload.id = subscription.id; } try { const { code, data } = await request[method]( `${config.apiPrefix}subscriptions`, payload, ); if (code === 200) { message.success( subscription ? intl.get('更新订阅成功') : intl.get('创建订阅成功'), ); handleCancel(data); } setLoading(false); } catch (error: any) { setLoading(false); } }; const typeChange = (e) => { setType(e.target.value); const _url = form.getFieldValue('url'); const _branch = form.getFieldValue('branch'); form.setFieldsValue({ alias: formatAlias(_url, _branch, e.target.value), }); if (_url) { form.validateFields(['url']); } }; const scheduleTypeChange = (e) => { setScheduleType(e.target.value); form.setFieldsValue({ schedule: '' }); }; const pullTypeChange = (e) => { setPullType(e.target.value); }; const onUrlChange = (e) => { const _branch = form.getFieldValue('branch'); form.setFieldsValue({ alias: formatAlias(e.target.value, _branch), }); }; const onBranchChange = (e) => { const _url = form.getFieldValue('url'); form.setFieldsValue({ alias: formatAlias(_url, e.target.value), }); }; const formatAlias = (_url: string, _branch: string, _type = type) => { let _alias = ''; const _regx = _type === 'file' ? fileUrlRegx : repoUrlRegx; if (_regx.test(_url)) { _alias = _url.match(_regx)![1].replaceAll('/', '_').replaceAll('.', '_'); } if (_branch) { _alias = _alias + '_' + _branch; } return _alias; }; const IntervalSelect = ({ value, onChange, }: { value?: any; onChange?: (param: any) => void; }) => { const [intervalType, setIntervalType] = useState('days'); const [intervalNumber, setIntervalNumber] = useState(); const intervalTypeChange = (type: string) => { setIntervalType(type); if (intervalNumber && intervalNumber > 0) { onChange?.({ type, value: intervalNumber }); } }; const numberChange = (value: number | null) => { setIntervalNumber(value || 1); if (!value) { onChange?.(null); } else { onChange?.({ type: intervalType, value }); } }; useEffect(() => { if (value) { setIntervalType(value.type); setIntervalNumber(value.value); } }, [value]); return ( ); }; const PullOptions = ({ value, onChange, type, }: { value?: any; type: 'ssh-key' | 'user-pwd'; onChange?: (param: any) => void; }) => { return type === 'ssh-key' ? ( ) : ( <> ); }; const onPaste = useCallback((e: any) => { const text = e.clipboardData.getData('text') as string; if (text.startsWith('ql ')) { const [ , type, url, whitelist, blacklist, dependences, branch, extensions, ] = text .split(' ') .map((x) => x.trim().replace(/\"/g, '').replace(/\'/, '')); const _type = type === 'raw' ? 'file' : url.startsWith('http') ? 'public-repo' : 'private-repo'; form.setFieldsValue({ type: _type, url, whitelist, blacklist, dependences, branch, extensions, alias: formatAlias(url, branch, _type), }); setType(_type); } }, []); const onNamePaste = useCallback((e) => { const text = e.clipboardData.getData('text') as string; if (text.includes('ql repo') || text.includes('ql raw')) { e.preventDefault(); } }, []); const formatParams = (sub) => { return { ...sub, autoAddCron: isNil(sub?.autoAddCron) ? true : Boolean(sub?.autoAddCron), autoDelCron: isNil(sub?.autoDelCron) ? true : Boolean(sub?.autoDelCron), }; }; useEffect(() => { window.addEventListener('paste', onPaste); return () => { window.removeEventListener('paste', onPaste); }; }, []); return ( { form .validateFields() .then((values) => { handleOk(values); }) .catch((info) => { console.log('Validate Failed:', info); }); }} onCancel={() => handleCancel()} confirmLoading={loading} >
{intl.get('公开仓库')} {intl.get('私有仓库')} {intl.get('单文件')} {type !== 'file' && ( )} {type === 'private-repo' && ( <> {intl.get('私钥')} {intl.get('用户名密码/Token')} )} crontab interval { try { if ( scheduleType === 'interval' || !value || CronExpressionParser.parse(value).hasNext() ) { return Promise.resolve(); } else { return Promise.reject(intl.get('Subscription表达式格式有误')); } } catch (e) { return Promise.reject(intl.get('Subscription表达式格式有误')); } }, }, ]} > {scheduleType === 'interval' ? ( ) : ( )} {type !== 'file' && ( <> )}
); }; export default SubscriptionModal;