mirror of
https://github.com/umami-software/umami.git
synced 2026-02-08 22:57:12 +01:00
Handle website delete. Added response helper functions.
This commit is contained in:
parent
0a411a9ad6
commit
c4b75e4aec
31 changed files with 314 additions and 96 deletions
|
|
@ -8,13 +8,15 @@ import Trash from 'assets/trash.svg';
|
|||
import Plus from 'assets/plus.svg';
|
||||
import { get } from 'lib/web';
|
||||
import Modal from './common/Modal';
|
||||
import WebsiteForm from './forms/WebsiteForm';
|
||||
import WebsiteEditForm from './forms/WebsiteEditForm';
|
||||
import styles from './Settings.module.css';
|
||||
import WebsiteDeleteForm from './forms/WebsiteDeleteForm';
|
||||
|
||||
export default function Settings() {
|
||||
const [data, setData] = useState();
|
||||
const [edit, setEdit] = useState();
|
||||
const [del, setDelete] = useState();
|
||||
const [add, setAdd] = useState();
|
||||
const [saved, setSaved] = useState(0);
|
||||
|
||||
const columns = [
|
||||
|
|
@ -44,6 +46,7 @@ export default function Settings() {
|
|||
}
|
||||
|
||||
function handleClose() {
|
||||
setAdd(null);
|
||||
setEdit(null);
|
||||
setDelete(null);
|
||||
}
|
||||
|
|
@ -64,14 +67,28 @@ export default function Settings() {
|
|||
<Page>
|
||||
<PageHeader>
|
||||
<div>Websites</div>
|
||||
<Button icon={<Plus />} size="S">
|
||||
<Button icon={<Plus />} size="S" onClick={() => setAdd(true)}>
|
||||
<div>Add website</div>
|
||||
</Button>
|
||||
</PageHeader>
|
||||
<Table columns={columns} rows={data} />
|
||||
{edit && (
|
||||
<Modal title="Edit website">
|
||||
<WebsiteForm initialValues={edit} onSave={handleSave} onClose={handleClose} />
|
||||
<WebsiteEditForm initialValues={edit} onSave={handleSave} onClose={handleClose} />
|
||||
</Modal>
|
||||
)}
|
||||
{add && (
|
||||
<Modal title="Add website">
|
||||
<WebsiteEditForm
|
||||
initialValues={{ name: '', domain: '' }}
|
||||
onSave={handleSave}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{del && (
|
||||
<Modal title="Delete website">
|
||||
<WebsiteDeleteForm initialValues={del} onSave={handleSave} onClose={handleClose} />
|
||||
</Modal>
|
||||
)}
|
||||
</Page>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default function DropDown({
|
|||
<div ref={ref} className={classNames(styles.dropdown, className)} onClick={handleShowMenu}>
|
||||
<div className={styles.value}>
|
||||
{options.find(e => e.value === value)?.label}
|
||||
<Icon icon={<Chevron />} size="S" className={styles.icon} />
|
||||
<Icon icon={<Chevron />} size="S" />
|
||||
</div>
|
||||
{showMenu && <Menu className={menuClassName} options={options} onSelect={handleSelect} />}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,18 +5,12 @@
|
|||
}
|
||||
|
||||
.value {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
padding: 4px 32px 4px 16px;
|
||||
padding: 4px 16px;
|
||||
border: 1px solid var(--gray500);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 12px;
|
||||
margin: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
border: 1px solid var(--gray300);
|
||||
padding: 30px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export default function LoginForm() {
|
|||
<FormError name="password" />
|
||||
</FormRow>
|
||||
<FormButtons>
|
||||
<Button className={styles.button} type="submit">
|
||||
<Button type="submit" variant="action">
|
||||
Login
|
||||
</Button>
|
||||
</FormButtons>
|
||||
|
|
|
|||
68
components/forms/WebsiteDeleteForm.js
Normal file
68
components/forms/WebsiteDeleteForm.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Formik, Form, Field } from 'formik';
|
||||
import { del } from 'lib/web';
|
||||
import Button from 'components/interface/Button';
|
||||
import FormLayout, {
|
||||
FormButtons,
|
||||
FormError,
|
||||
FormMessage,
|
||||
FormRow,
|
||||
} from 'components/layout/FormLayout';
|
||||
|
||||
const validate = ({ confirmation }) => {
|
||||
const errors = {};
|
||||
|
||||
if (confirmation !== 'DELETE') {
|
||||
errors.confirmation = !confirmation ? 'Required' : 'Invalid';
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export default function WebsiteDeleteForm({ initialValues, onSave, onClose }) {
|
||||
const [message, setMessage] = useState();
|
||||
|
||||
const handleSubmit = async ({ website_id }) => {
|
||||
const response = await del(`/api/website/${website_id}`);
|
||||
|
||||
if (response) {
|
||||
onSave();
|
||||
} else {
|
||||
setMessage('Something went wrong.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FormLayout>
|
||||
<Formik
|
||||
initialValues={{ confirmation: '', ...initialValues }}
|
||||
validate={validate}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<div>
|
||||
Are your sure you want to delete <b>{initialValues.name}</b>?
|
||||
</div>
|
||||
<div>All associated data will be deleted as well.</div>
|
||||
<p>
|
||||
Type <b>DELETE</b> in the box below to confirm.
|
||||
</p>
|
||||
<FormRow>
|
||||
<label htmlFor="confirmation">Confirm</label>
|
||||
<Field name="confirmation" />
|
||||
<FormError name="confirmation" />
|
||||
</FormRow>
|
||||
<FormButtons>
|
||||
<Button type="submit" variant="danger">
|
||||
Delete
|
||||
</Button>
|
||||
<Button onClick={onClose}>Cancel</Button>
|
||||
</FormButtons>
|
||||
<FormMessage>{message}</FormMessage>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</FormLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Formik, Form, Field } from 'formik';
|
||||
import Router from 'next/router';
|
||||
import { post } from 'lib/web';
|
||||
import Button from 'components/interface/Button';
|
||||
import FormLayout, {
|
||||
|
|
@ -23,7 +22,7 @@ const validate = ({ name, domain }) => {
|
|||
return errors;
|
||||
};
|
||||
|
||||
export default function WebsiteForm({ initialValues, onSave, onClose }) {
|
||||
export default function WebsiteEditForm({ initialValues, onSave, onClose }) {
|
||||
const [message, setMessage] = useState();
|
||||
|
||||
const handleSubmit = async values => {
|
||||
|
|
@ -52,7 +51,9 @@ export default function WebsiteForm({ initialValues, onSave, onClose }) {
|
|||
<FormError name="domain" />
|
||||
</FormRow>
|
||||
<FormButtons>
|
||||
<Button type="submit">Save</Button>
|
||||
<Button type="submit" variant="action">
|
||||
Save
|
||||
</Button>
|
||||
<Button onClick={onClose}>Cancel</Button>
|
||||
</FormButtons>
|
||||
<FormMessage>{message}</FormMessage>
|
||||
|
|
@ -7,6 +7,7 @@ export default function Button({
|
|||
type = 'button',
|
||||
icon,
|
||||
size,
|
||||
variant,
|
||||
children,
|
||||
className,
|
||||
onClick = () => {},
|
||||
|
|
@ -17,6 +18,8 @@ export default function Button({
|
|||
className={classNames(styles.button, className, {
|
||||
[styles.small]: size === 'S',
|
||||
[styles.large]: size === 'L',
|
||||
[styles.action]: variant === 'action',
|
||||
[styles.danger]: variant === 'danger',
|
||||
})}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -26,3 +26,21 @@
|
|||
.large {
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
|
||||
.action {
|
||||
color: var(--gray50) !important;
|
||||
background: var(--gray900) !important;
|
||||
}
|
||||
|
||||
.action:hover {
|
||||
background: var(--gray800) !important;
|
||||
}
|
||||
|
||||
.danger {
|
||||
color: var(--gray50) !important;
|
||||
background: var(--red500) !important;
|
||||
}
|
||||
|
||||
.danger:hover {
|
||||
background: var(--red400) !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { useSpring, animated } from 'react-spring';
|
||||
import classNames from 'classnames';
|
||||
import { ErrorMessage } from 'formik';
|
||||
import styles from './FormLayout.module.css';
|
||||
|
|
@ -11,9 +12,19 @@ export const FormButtons = ({ className, children }) => (
|
|||
<div className={classNames(styles.buttons, className)}>{children}</div>
|
||||
);
|
||||
|
||||
export const FormError = ({ name }) => (
|
||||
<ErrorMessage name={name}>{msg => <div className={styles.error}>{msg}</div>}</ErrorMessage>
|
||||
);
|
||||
export const FormError = ({ name }) => {
|
||||
return <ErrorMessage name={name}>{msg => <ErrorTag msg={msg} />}</ErrorMessage>;
|
||||
};
|
||||
|
||||
const ErrorTag = ({ msg }) => {
|
||||
const props = useSpring({ opacity: 1, from: { opacity: 0 } });
|
||||
|
||||
return (
|
||||
<animated.div className={styles.error} style={props}>
|
||||
{msg}
|
||||
</animated.div>
|
||||
);
|
||||
};
|
||||
|
||||
export const FormRow = ({ children }) => <div className={styles.row}>{children}</div>;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@
|
|||
.buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--gray50);
|
||||
background: var(--color-error);
|
||||
background: var(--red400);
|
||||
font-size: var(--font-size-small);
|
||||
position: absolute;
|
||||
display: flex;
|
||||
|
|
@ -47,7 +48,7 @@
|
|||
margin: auto;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--color-error);
|
||||
background: var(--red400);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue