mirror of
https://github.com/Ravinou/borgwarehouse
synced 2024-06-08 00:42:11 +02:00
feat: add checkbox to generate LAN commands
This commit is contained in:
parent
fca4560e18
commit
bbe1de8b8a
|
@ -10,438 +10,456 @@ import { SpinnerDotted } from 'spinners-react';
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
|
|
||||||
export default function RepoManage(props) {
|
export default function RepoManage(props) {
|
||||||
////Var
|
////Var
|
||||||
let targetRepo;
|
let targetRepo;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
formState: { errors, isSubmitting, isValid },
|
formState: { errors, isSubmitting, isValid },
|
||||||
} = useForm({ mode: 'onChange' });
|
} = useForm({ mode: 'onChange' });
|
||||||
//List of possible times for alerts
|
//List of possible times for alerts
|
||||||
const alertOptions = [
|
const alertOptions = [
|
||||||
{ value: 3600, label: '1 hour' },
|
{ value: 3600, label: '1 hour' },
|
||||||
{ value: 21600, label: '6 hours' },
|
{ value: 21600, label: '6 hours' },
|
||||||
{ value: 43200, label: '12 hours' },
|
{ value: 43200, label: '12 hours' },
|
||||||
{ value: 90000, label: '1 day' },
|
{ value: 90000, label: '1 day' },
|
||||||
{ value: 172800, label: '2 days' },
|
{ value: 172800, label: '2 days' },
|
||||||
{ value: 259200, label: '3 days' },
|
{ value: 259200, label: '3 days' },
|
||||||
{ value: 345600, label: '4 days' },
|
{ value: 345600, label: '4 days' },
|
||||||
{ value: 432000, label: '5 days' },
|
{ value: 432000, label: '5 days' },
|
||||||
{ value: 518400, label: '6 days' },
|
{ value: 518400, label: '6 days' },
|
||||||
{ value: 604800, label: '7 days' },
|
{ value: 604800, label: '7 days' },
|
||||||
{ value: 864000, label: '10 days' },
|
{ value: 864000, label: '10 days' },
|
||||||
{ value: 1209600, label: '14 days' },
|
{ value: 1209600, label: '14 days' },
|
||||||
{ value: 2592000, label: '30 days' },
|
{ value: 2592000, label: '30 days' },
|
||||||
];
|
];
|
||||||
const toastOptions = {
|
const toastOptions = {
|
||||||
position: 'top-right',
|
position: 'top-right',
|
||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
hideProgressBar: false,
|
hideProgressBar: false,
|
||||||
closeOnClick: true,
|
closeOnClick: true,
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
progress: undefined,
|
progress: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
////State
|
////State
|
||||||
const [deleteDialog, setDeleteDialog] = useState(false);
|
const [deleteDialog, setDeleteDialog] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
////Functions
|
////Functions
|
||||||
//router.query.slug is undefined for few milliseconds on first render for a direct URL access (https://github.com/vercel/next.js/discussions/11484).
|
//router.query.slug is undefined for few milliseconds on first render for a direct URL access (https://github.com/vercel/next.js/discussions/11484).
|
||||||
//If I call repoManage with edit mode (props), i'm firstly waiting that router.query.slug being available before rendering.
|
//If I call repoManage with edit mode (props), i'm firstly waiting that router.query.slug being available before rendering.
|
||||||
if (!router.query.slug && props.mode == 'edit') {
|
if (!router.query.slug && props.mode == 'edit') {
|
||||||
return (
|
return (
|
||||||
<SpinnerDotted
|
<SpinnerDotted
|
||||||
size={30}
|
size={30}
|
||||||
thickness={100}
|
thickness={100}
|
||||||
speed={180}
|
speed={180}
|
||||||
color='rgba(109, 74, 255, 1)'
|
color='rgba(109, 74, 255, 1)'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (props.mode == 'edit') {
|
} else if (props.mode == 'edit') {
|
||||||
for (let element in props.repoList) {
|
for (let element in props.repoList) {
|
||||||
if (props.repoList[element].id == router.query.slug) {
|
if (props.repoList[element].id == router.query.slug) {
|
||||||
targetRepo = props.repoList[element];
|
targetRepo = props.repoList[element];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//If the ID does not exist > 404
|
//If the ID does not exist > 404
|
||||||
if (!targetRepo) {
|
if (!targetRepo) {
|
||||||
router.push('/404');
|
router.push('/404');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete a repo
|
//Delete a repo
|
||||||
const deleteHandler = async () => {
|
const deleteHandler = async () => {
|
||||||
//API Call for delete
|
//API Call for delete
|
||||||
fetch('/api/repo/id/' + router.query.slug + '/delete', {
|
fetch('/api/repo/id/' + router.query.slug + '/delete', {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json',
|
'Content-type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ toDelete: true }),
|
body: JSON.stringify({ toDelete: true }),
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
toast.success(
|
toast.success(
|
||||||
'🗑 The repository #' +
|
'🗑 The repository #' +
|
||||||
router.query.slug +
|
router.query.slug +
|
||||||
' has been successfully deleted',
|
' has been successfully deleted',
|
||||||
toastOptions
|
toastOptions
|
||||||
);
|
);
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
} else {
|
} else {
|
||||||
toast.error('An error has occurred', toastOptions);
|
toast.error('An error has occurred', toastOptions);
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
console.log('Fail to delete');
|
console.log('Fail to delete');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
toast.error('An error has occurred', toastOptions);
|
toast.error('An error has occurred', toastOptions);
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
//Form submit Handler for ADD or EDIT a repo
|
//Form submit Handler for ADD or EDIT a repo
|
||||||
const formSubmitHandler = async (dataForm) => {
|
const formSubmitHandler = async (dataForm) => {
|
||||||
//Loading button on submit to avoid multiple send.
|
//Loading button on submit to avoid multiple send.
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
//ADD a repo
|
//ADD a repo
|
||||||
if (props.mode == 'add') {
|
if (props.mode == 'add') {
|
||||||
const newRepo = {
|
const newRepo = {
|
||||||
alias: dataForm.alias,
|
alias: dataForm.alias,
|
||||||
size: dataForm.size,
|
size: dataForm.size,
|
||||||
sshPublicKey: dataForm.sshkey,
|
sshPublicKey: dataForm.sshkey,
|
||||||
comment: dataForm.comment,
|
comment: dataForm.comment,
|
||||||
alert: dataForm.alert.value,
|
alert: dataForm.alert.value,
|
||||||
};
|
lanCommand: dataForm.lanCommand,
|
||||||
//POST API to send new repo
|
};
|
||||||
await fetch('/api/repo/add', {
|
//POST API to send new repo
|
||||||
method: 'POST',
|
await fetch('/api/repo/add', {
|
||||||
headers: {
|
method: 'POST',
|
||||||
'Content-type': 'application/json',
|
headers: {
|
||||||
},
|
'Content-type': 'application/json',
|
||||||
body: JSON.stringify(newRepo),
|
},
|
||||||
})
|
body: JSON.stringify(newRepo),
|
||||||
.then((response) => {
|
})
|
||||||
if (response.ok) {
|
.then((response) => {
|
||||||
toast.success(
|
if (response.ok) {
|
||||||
'New repository added ! 🥳',
|
toast.success(
|
||||||
toastOptions
|
'New repository added ! 🥳',
|
||||||
);
|
toastOptions
|
||||||
router.replace('/');
|
);
|
||||||
} else {
|
router.replace('/');
|
||||||
toast.error('An error has occurred', toastOptions);
|
} else {
|
||||||
router.replace('/');
|
toast.error('An error has occurred', toastOptions);
|
||||||
console.log('Fail to post');
|
router.replace('/');
|
||||||
}
|
console.log('Fail to post');
|
||||||
})
|
}
|
||||||
.catch((error) => {
|
})
|
||||||
toast.error('An error has occurred', toastOptions);
|
.catch((error) => {
|
||||||
router.replace('/');
|
toast.error('An error has occurred', toastOptions);
|
||||||
console.log(error);
|
router.replace('/');
|
||||||
});
|
console.log(error);
|
||||||
//EDIT a repo
|
});
|
||||||
} else if (props.mode == 'edit') {
|
//EDIT a repo
|
||||||
const dataEdited = {
|
} else if (props.mode == 'edit') {
|
||||||
alias: dataForm.alias,
|
const dataEdited = {
|
||||||
size: dataForm.size,
|
alias: dataForm.alias,
|
||||||
sshPublicKey: dataForm.sshkey,
|
size: dataForm.size,
|
||||||
comment: dataForm.comment,
|
sshPublicKey: dataForm.sshkey,
|
||||||
alert: dataForm.alert.value,
|
comment: dataForm.comment,
|
||||||
};
|
alert: dataForm.alert.value,
|
||||||
await fetch('/api/repo/id/' + router.query.slug + '/edit', {
|
lanCommand: dataForm.lanCommand,
|
||||||
method: 'PUT',
|
};
|
||||||
headers: {
|
await fetch('/api/repo/id/' + router.query.slug + '/edit', {
|
||||||
'Content-type': 'application/json',
|
method: 'PUT',
|
||||||
},
|
headers: {
|
||||||
body: JSON.stringify(dataEdited),
|
'Content-type': 'application/json',
|
||||||
})
|
},
|
||||||
.then((response) => {
|
body: JSON.stringify(dataEdited),
|
||||||
if (response.ok) {
|
})
|
||||||
toast.success(
|
.then((response) => {
|
||||||
'The repository #' +
|
if (response.ok) {
|
||||||
targetRepo.id +
|
toast.success(
|
||||||
' has been successfully edited !',
|
'The repository #' +
|
||||||
toastOptions
|
targetRepo.id +
|
||||||
);
|
' has been successfully edited !',
|
||||||
router.replace('/');
|
toastOptions
|
||||||
} else {
|
);
|
||||||
toast.error('An error has occurred', toastOptions);
|
router.replace('/');
|
||||||
router.replace('/');
|
} else {
|
||||||
console.log('Fail to PUT');
|
toast.error('An error has occurred', toastOptions);
|
||||||
}
|
router.replace('/');
|
||||||
})
|
console.log('Fail to PUT');
|
||||||
.catch((error) => {
|
}
|
||||||
toast.error('An error has occurred', toastOptions);
|
})
|
||||||
router.replace('/');
|
.catch((error) => {
|
||||||
console.log(error);
|
toast.error('An error has occurred', toastOptions);
|
||||||
});
|
router.replace('/');
|
||||||
}
|
console.log(error);
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classes.modaleWrapper} />
|
<div className={classes.modaleWrapper} />
|
||||||
<div className={classes.modale}>
|
<div className={classes.modale}>
|
||||||
<div onClick={props.closeHandler} className={classes.close}>
|
<div onClick={props.closeHandler} className={classes.close}>
|
||||||
<IconX size={36} />
|
<IconX size={36} />
|
||||||
</div>
|
</div>
|
||||||
{deleteDialog ? (
|
{deleteDialog ? (
|
||||||
<div className={classes.deleteDialogWrapper}>
|
<div className={classes.deleteDialogWrapper}>
|
||||||
<div>
|
<div>
|
||||||
<IconAlertCircle
|
<IconAlertCircle
|
||||||
size={80}
|
size={80}
|
||||||
color='red'
|
color='red'
|
||||||
style={{ margin: 'auto' }}
|
style={{ margin: 'auto' }}
|
||||||
/>
|
/>
|
||||||
<h1 style={{ textAlign: 'center' }}>
|
<h1 style={{ textAlign: 'center' }}>
|
||||||
Delete the repository{' '}
|
Delete the repository{' '}
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
color: 'rgba(99, 115, 129, 0.38)',
|
color: 'rgba(99, 115, 129, 0.38)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
#{targetRepo.id}
|
#{targetRepo.id}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
?
|
?
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.deleteDialogMessage}>
|
<div className={classes.deleteDialogMessage}>
|
||||||
<div style={{ marginBottom: '5px' }}>
|
<div style={{ marginBottom: '5px' }}>
|
||||||
You are about to permanently delete the
|
You are about to permanently delete the
|
||||||
repository <b>#{targetRepo.id}</b> and all the
|
repository <b>#{targetRepo.id}</b> and all the
|
||||||
backups it contains.
|
backups it contains.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
The data will not be recoverable and it will not
|
The data will not be recoverable and it will not
|
||||||
be possible to go back.
|
be possible to go back.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.deleteDialogButtonWrapper}>
|
<div className={classes.deleteDialogButtonWrapper}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<SpinnerDotted
|
<SpinnerDotted
|
||||||
size={30}
|
size={30}
|
||||||
thickness={150}
|
thickness={150}
|
||||||
speed={100}
|
speed={100}
|
||||||
color='#6d4aff'
|
color='#6d4aff'
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={props.closeHandler}
|
onClick={props.closeHandler}
|
||||||
className={classes.cancelButton}
|
className={classes.cancelButton}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
}}
|
}}
|
||||||
className={classes.deleteButton}
|
className={classes.deleteButton}
|
||||||
>
|
>
|
||||||
Yes, delete it !
|
Yes, delete it !
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.formWrapper}>
|
<div className={classes.formWrapper}>
|
||||||
{props.mode == 'edit' && (
|
{props.mode == 'edit' && (
|
||||||
<h1>
|
<h1>
|
||||||
Edit the repository{' '}
|
Edit the repository{' '}
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
color: 'rgba(99, 115, 129, 0.38)',
|
color: 'rgba(99, 115, 129, 0.38)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
#{targetRepo.id}
|
#{targetRepo.id}
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
)}
|
||||||
{props.mode == 'add' && <h1>Add a repository</h1>}
|
{props.mode == 'add' && <h1>Add a repository</h1>}
|
||||||
<form
|
<form
|
||||||
className={classes.repoManageForm}
|
className={classes.repoManageForm}
|
||||||
onSubmit={handleSubmit(formSubmitHandler)}
|
onSubmit={handleSubmit(formSubmitHandler)}
|
||||||
>
|
>
|
||||||
{/* ALIAS */}
|
{/* ALIAS */}
|
||||||
<label htmlFor='alias'>Alias</label>
|
<label htmlFor='alias'>Alias</label>
|
||||||
<input
|
<input
|
||||||
className='form-control is-invalid'
|
className='form-control is-invalid'
|
||||||
placeholder='Alias for the repository, e.g."Server 1"'
|
placeholder='Alias for the repository, e.g."Server 1"'
|
||||||
type='text'
|
type='text'
|
||||||
defaultValue={
|
defaultValue={
|
||||||
props.mode == 'edit'
|
props.mode == 'edit'
|
||||||
? targetRepo.alias
|
? targetRepo.alias
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{...register('alias', {
|
{...register('alias', {
|
||||||
required: 'An alias is required.',
|
required: 'An alias is required.',
|
||||||
minLength: {
|
minLength: {
|
||||||
value: 2,
|
value: 2,
|
||||||
message: '2 characters min',
|
message: '2 characters min',
|
||||||
},
|
},
|
||||||
maxLength: {
|
maxLength: {
|
||||||
value: 40,
|
value: 40,
|
||||||
message: '40 characters max',
|
message: '40 characters max',
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{errors.alias && (
|
{errors.alias && (
|
||||||
<span className={classes.errorMessage}>
|
<span className={classes.errorMessage}>
|
||||||
{errors.alias.message}
|
{errors.alias.message}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* SSH KEY */}
|
{/* SSH KEY */}
|
||||||
<label htmlFor='sshkey'>SSH public key</label>
|
<label htmlFor='sshkey'>SSH public key</label>
|
||||||
<textarea
|
<textarea
|
||||||
placeholder='Public key in OpenSSH format (rsa, ed25519, ed25519-sk)'
|
placeholder='Public key in OpenSSH format (rsa, ed25519, ed25519-sk)'
|
||||||
type='text'
|
type='text'
|
||||||
defaultValue={
|
defaultValue={
|
||||||
props.mode == 'edit'
|
props.mode == 'edit'
|
||||||
? targetRepo.sshPublicKey
|
? targetRepo.sshPublicKey
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{...register('sshkey', {
|
{...register('sshkey', {
|
||||||
required: 'SSH public key is required.',
|
required: 'SSH public key is required.',
|
||||||
pattern: {
|
pattern: {
|
||||||
value: /^(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$/,
|
value: /^(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$/,
|
||||||
message:
|
message:
|
||||||
'Invalid public key. The SSH key needs to be in OpenSSH format (rsa, ed25519, ed25519-sk)',
|
'Invalid public key. The SSH key needs to be in OpenSSH format (rsa, ed25519, ed25519-sk)',
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{errors.sshkey && (
|
{errors.sshkey && (
|
||||||
<span className={classes.errorMessage}>
|
<span className={classes.errorMessage}>
|
||||||
{errors.sshkey.message}
|
{errors.sshkey.message}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* SIZE */}
|
{/* SIZE */}
|
||||||
<label htmlFor='size'>Storage Size (Go)</label>
|
<label htmlFor='size'>Storage Size (Go)</label>
|
||||||
<input
|
<input
|
||||||
type='number'
|
type='number'
|
||||||
defaultValue={
|
defaultValue={
|
||||||
props.mode == 'edit'
|
props.mode == 'edit'
|
||||||
? targetRepo.storageSize
|
? targetRepo.storageSize
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{...register('size', {
|
{...register('size', {
|
||||||
required: 'A size is required.',
|
required: 'A size is required.',
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{errors.size && (
|
{errors.size && (
|
||||||
<span className={classes.errorMessage}>
|
<span className={classes.errorMessage}>
|
||||||
{errors.size.message}
|
{errors.size.message}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* COMMENT */}
|
{/* COMMENT */}
|
||||||
<label htmlFor='comment'>Comment</label>
|
<label htmlFor='comment'>Comment</label>
|
||||||
<textarea
|
<textarea
|
||||||
type='text'
|
type='text'
|
||||||
placeholder='Little comment for your repository...'
|
placeholder='Little comment for your repository...'
|
||||||
defaultValue={
|
defaultValue={
|
||||||
props.mode == 'edit'
|
props.mode == 'edit'
|
||||||
? targetRepo.comment
|
? targetRepo.comment
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{...register('comment', {
|
{...register('comment', {
|
||||||
required: false,
|
required: false,
|
||||||
maxLength: {
|
maxLength: {
|
||||||
value: 200,
|
value: 200,
|
||||||
message: '200 characters maximum.',
|
message: '200 characters maximum.',
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{errors.comment && (
|
{errors.comment && (
|
||||||
<span className={classes.errorMessage}>
|
<span className={classes.errorMessage}>
|
||||||
{errors.comment.message}
|
{errors.comment.message}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* ALERT */}
|
{/* LAN COMMAND GENERATION */}
|
||||||
<label
|
<div className={classes.lanCommandWrapper}>
|
||||||
style={{ margin: '25px auto 10px auto' }}
|
<input
|
||||||
htmlFor='alert'
|
type='checkbox'
|
||||||
>
|
name='lanCommand'
|
||||||
Alert if there is no backup since :
|
defaultChecked={
|
||||||
</label>
|
props.mode == 'edit'
|
||||||
<div className={classes.selectAlert}>
|
? targetRepo.lanCommand
|
||||||
<Controller
|
: false
|
||||||
name='alert'
|
}
|
||||||
defaultValue={
|
{...register('lanCommand')}
|
||||||
props.mode == 'edit'
|
/>
|
||||||
? alertOptions.find(
|
<label htmlFor='lanCommand'>
|
||||||
(x) =>
|
Generates commands for use over LAN.
|
||||||
x.value ===
|
</label>
|
||||||
targetRepo.alert
|
</div>
|
||||||
)
|
{/* ALERT */}
|
||||||
: alertOptions[3]
|
<label
|
||||||
}
|
style={{ margin: '25px auto 10px auto' }}
|
||||||
control={control}
|
htmlFor='alert'
|
||||||
render={({
|
>
|
||||||
field: { onChange, value },
|
Alert if there is no backup since :
|
||||||
}) => (
|
</label>
|
||||||
<Select
|
<div className={classes.selectAlert}>
|
||||||
onChange={onChange}
|
<Controller
|
||||||
value={value}
|
name='alert'
|
||||||
options={alertOptions}
|
defaultValue={
|
||||||
isSearchable={false}
|
props.mode == 'edit'
|
||||||
maxMenuHeight={150}
|
? alertOptions.find(
|
||||||
menuPlacement='top'
|
(x) =>
|
||||||
theme={(theme) => ({
|
x.value ===
|
||||||
...theme,
|
targetRepo.alert
|
||||||
borderRadius: '5px',
|
)
|
||||||
colors: {
|
: alertOptions[3]
|
||||||
...theme.colors,
|
}
|
||||||
primary25: '#c3b6fa',
|
control={control}
|
||||||
primary: '#6d4aff',
|
render={({
|
||||||
},
|
field: { onChange, value },
|
||||||
})}
|
}) => (
|
||||||
/>
|
<Select
|
||||||
)}
|
onChange={onChange}
|
||||||
/>
|
value={value}
|
||||||
</div>
|
options={alertOptions}
|
||||||
{isLoading ? (
|
isSearchable={false}
|
||||||
<div
|
maxMenuHeight={150}
|
||||||
style={{
|
menuPlacement='top'
|
||||||
textAlign: 'center',
|
theme={(theme) => ({
|
||||||
marginTop: '8px',
|
...theme,
|
||||||
}}
|
borderRadius: '5px',
|
||||||
>
|
colors: {
|
||||||
<SpinnerDotted
|
...theme.colors,
|
||||||
size={30}
|
primary25: '#c3b6fa',
|
||||||
thickness={150}
|
primary: '#6d4aff',
|
||||||
speed={100}
|
},
|
||||||
color='#6d4aff'
|
})}
|
||||||
/>
|
/>
|
||||||
</div>
|
)}
|
||||||
) : (
|
/>
|
||||||
<button
|
</div>
|
||||||
type='submit'
|
{isLoading ? (
|
||||||
className='defaultButton'
|
<div
|
||||||
disabled={!isValid || isSubmitting}
|
style={{
|
||||||
>
|
textAlign: 'center',
|
||||||
{props.mode == 'edit' && 'Edit'}
|
marginTop: '8px',
|
||||||
{props.mode == 'add' && 'Add'}
|
}}
|
||||||
</button>
|
>
|
||||||
)}
|
<SpinnerDotted
|
||||||
</form>
|
size={30}
|
||||||
{props.mode == 'edit' ? (
|
thickness={150}
|
||||||
<button
|
speed={100}
|
||||||
className={classes.littleDeleteButton}
|
color='#6d4aff'
|
||||||
onClick={() => setDeleteDialog(true)}
|
/>
|
||||||
>
|
</div>
|
||||||
Delete this repository
|
) : (
|
||||||
</button>
|
<button
|
||||||
) : null}
|
type='submit'
|
||||||
</div>
|
className='defaultButton'
|
||||||
)}
|
disabled={!isValid || isSubmitting}
|
||||||
</div>
|
>
|
||||||
</>
|
{props.mode == 'edit' && 'Edit'}
|
||||||
);
|
{props.mode == 'add' && 'Add'}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
{props.mode == 'edit' ? (
|
||||||
|
<button
|
||||||
|
className={classes.littleDeleteButton}
|
||||||
|
onClick={() => setDeleteDialog(true)}
|
||||||
|
>
|
||||||
|
Delete this repository
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue