diff --git a/assets/arrow-right.svg b/assets/arrow-right.svg
index 6fc93909..efc5d74a 100644
--- a/assets/arrow-right.svg
+++ b/assets/arrow-right.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/arrow-up-right-from-square.svg b/assets/arrow-up-right-from-square.svg
index 90ad457f..8f6de672 100644
--- a/assets/arrow-up-right-from-square.svg
+++ b/assets/arrow-up-right-from-square.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/bars.svg b/assets/bars.svg
index fdb2d6e4..ba383fa4 100644
--- a/assets/bars.svg
+++ b/assets/bars.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/chart-bar.svg b/assets/chart-bar.svg
index d1d72fdc..36820b76 100644
--- a/assets/chart-bar.svg
+++ b/assets/chart-bar.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/check.svg b/assets/check.svg
index 1a7abdce..65810c19 100644
--- a/assets/check.svg
+++ b/assets/check.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/chevron-down.svg b/assets/chevron-down.svg
index cb9d8fe1..69add632 100644
--- a/assets/chevron-down.svg
+++ b/assets/chevron-down.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/code.svg b/assets/code.svg
index cd29765e..0f8e0814 100644
--- a/assets/code.svg
+++ b/assets/code.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/external-link.svg b/assets/external-link.svg
index ed09306f..e24896b0 100644
--- a/assets/external-link.svg
+++ b/assets/external-link.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/gear.svg b/assets/gear.svg
index ab97a693..47805d46 100644
--- a/assets/gear.svg
+++ b/assets/gear.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/logo.svg b/assets/logo.svg
index f0e52261..d2c71326 100644
--- a/assets/logo.svg
+++ b/assets/logo.svg
@@ -1,2 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/moon.svg b/assets/moon.svg
index 6c8955ae..638286fd 100644
--- a/assets/moon.svg
+++ b/assets/moon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/pen.svg b/assets/pen.svg
index 426c520c..b2979420 100644
--- a/assets/pen.svg
+++ b/assets/pen.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/sun.svg b/assets/sun.svg
index ebc20eb2..3e487291 100644
--- a/assets/sun.svg
+++ b/assets/sun.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/times.svg b/assets/times.svg
index c528bcdd..261bb277 100644
--- a/assets/times.svg
+++ b/assets/times.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/user.svg b/assets/user.svg
index c0094666..62df2c42 100644
--- a/assets/user.svg
+++ b/assets/user.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/xmark.svg b/assets/xmark.svg
index 340f479e..83bd5740 100644
--- a/assets/xmark.svg
+++ b/assets/xmark.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/components/common/Button.module.css b/components/common/Button.module.css
index b911095f..b6edc60e 100644
--- a/components/common/Button.module.css
+++ b/components/common/Button.module.css
@@ -2,9 +2,9 @@
display: flex;
justify-content: center;
align-items: center;
- font-size: var(--font-size-normal);
- color: var(--gray900);
- background: var(--gray100);
+ font-size: var(--font-size-md);
+ color: var(--base900);
+ background: var(--base100);
padding: 8px 16px;
border-radius: 4px;
border: 0;
@@ -14,11 +14,11 @@
}
.button:hover {
- background: var(--gray200);
+ background: var(--base200);
}
.button:active {
- color: var(--gray900);
+ color: var(--base900);
}
.label {
@@ -29,30 +29,30 @@
}
.large {
- font-size: var(--font-size-large);
+ font-size: var(--font-size-lg);
}
.small {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
}
.xsmall {
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
}
.action,
.action:active {
- color: var(--gray50);
- background: var(--gray900);
+ color: var(--base50);
+ background: var(--base900);
}
.action:hover {
- background: var(--gray800);
+ background: var(--base800);
}
.danger,
.danger:active {
- color: var(--gray50);
+ color: var(--base50);
background: var(--red500);
}
@@ -62,7 +62,7 @@
.light,
.light:active {
- color: var(--gray900);
+ color: var(--base900);
background: transparent;
}
@@ -85,18 +85,18 @@
.button:disabled {
cursor: default;
- color: var(--gray500);
- background: var(--gray75);
+ color: var(--base500);
+ background: var(--base75);
}
.button:disabled:active {
- color: var(--gray500);
+ color: var(--base500);
}
.button:disabled:hover {
- background: var(--gray75);
+ background: var(--base75);
}
.button.light:disabled {
- background: var(--gray50);
+ background: var(--base50);
}
diff --git a/components/common/ButtonGroup.module.css b/components/common/ButtonGroup.module.css
index bc60f8d3..04d33d22 100644
--- a/components/common/ButtonGroup.module.css
+++ b/components/common/ButtonGroup.module.css
@@ -2,14 +2,14 @@
display: inline-flex;
border-radius: 4px;
overflow: hidden;
- border: 1px solid var(--gray500);
+ border: 1px solid var(--base500);
}
.group .button {
border-radius: 0;
- color: var(--gray800);
- background: var(--gray50);
- border-left: 1px solid var(--gray500);
+ color: var(--base800);
+ background: var(--base50);
+ border-left: 1px solid var(--base500);
padding: 4px 8px;
}
@@ -18,7 +18,7 @@
}
.group .button:hover {
- background: var(--gray100);
+ background: var(--base100);
}
.group .button + .button {
@@ -26,6 +26,6 @@
}
.group .button.selected {
- color: var(--gray900);
+ color: var(--base900);
font-weight: 600;
}
diff --git a/components/common/Calendar.module.css b/components/common/Calendar.module.css
index 9751cf25..5e50e79a 100644
--- a/components/common/Calendar.module.css
+++ b/components/common/Calendar.module.css
@@ -1,7 +1,7 @@
.calendar {
display: flex;
flex-direction: column;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
flex: 1;
min-height: 306px;
}
@@ -12,7 +12,7 @@
}
.calendar td {
- color: var(--gray800);
+ color: var(--base800);
cursor: pointer;
text-align: center;
vertical-align: center;
@@ -23,17 +23,17 @@
}
.calendar td:hover {
- border: 1px solid var(--gray300);
- background: var(--gray75);
+ border: 1px solid var(--base300);
+ background: var(--base75);
}
.calendar td.faded {
- color: var(--gray500);
+ color: var(--base500);
}
.calendar td.selected {
font-weight: 600;
- border: 1px solid var(--gray600);
+ border: 1px solid var(--base600);
}
.calendar td.selected:hover {
@@ -41,18 +41,18 @@
}
.calendar td.disabled {
- color: var(--gray400);
- background: var(--gray75);
+ color: var(--base400);
+ background: var(--base75);
}
.calendar td.disabled:hover {
cursor: default;
- background: var(--gray75);
+ background: var(--base75);
border-color: transparent;
}
.calendar td.faded.disabled {
- background: var(--gray100);
+ background: var(--base100);
}
.header {
@@ -61,7 +61,7 @@
align-items: center;
font-weight: 700;
line-height: 40px;
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
}
.body {
diff --git a/components/common/Checkbox.module.css b/components/common/Checkbox.module.css
index c9a01eac..edd2b776 100644
--- a/components/common/Checkbox.module.css
+++ b/components/common/Checkbox.module.css
@@ -11,7 +11,7 @@
align-items: center;
width: 20px;
height: 20px;
- border: 1px solid var(--gray500);
+ border: 1px solid var(--base500);
border-radius: 4px;
}
diff --git a/components/common/Dot.module.css b/components/common/Dot.module.css
index 258d6e87..284aa66d 100644
--- a/components/common/Dot.module.css
+++ b/components/common/Dot.module.css
@@ -1,5 +1,5 @@
.wrapper {
- background: var(--gray50);
+ background: var(--base50);
margin-right: 10px;
border-radius: 100%;
}
diff --git a/components/common/Dropdown.module.css b/components/common/Dropdown.module.css
index 9738b007..a1877529 100644
--- a/components/common/Dropdown.module.css
+++ b/components/common/Dropdown.module.css
@@ -3,7 +3,7 @@
display: flex;
justify-content: space-between;
align-items: center;
- border: 1px solid var(--gray500);
+ border: 1px solid var(--base500);
border-radius: 4px;
cursor: pointer;
}
@@ -12,7 +12,7 @@
flex: 1;
display: flex;
justify-content: space-between;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
flex-wrap: nowrap;
white-space: nowrap;
padding: 4px 16px;
diff --git a/components/common/ErrorMessage.module.css b/components/common/ErrorMessage.module.css
index 88769cf5..dd9295d9 100644
--- a/components/common/ErrorMessage.module.css
+++ b/components/common/ErrorMessage.module.css
@@ -6,7 +6,7 @@
margin: auto;
display: flex;
z-index: 1;
- background-color: var(--gray50);
+ background-color: var(--base50);
padding: 10px;
}
diff --git a/components/common/FilterLink.module.css b/components/common/FilterLink.module.css
index 45b049da..ce3ffa5f 100644
--- a/components/common/FilterLink.module.css
+++ b/components/common/FilterLink.module.css
@@ -4,11 +4,11 @@
}
.row .inactive {
- color: var(--gray500);
+ color: var(--base500);
}
.row .active {
- color: var(--gray900);
+ color: var(--base900);
font-weight: 600;
}
diff --git a/components/common/Link.module.css b/components/common/Link.module.css
index dd2f92f9..0476bd92 100644
--- a/components/common/Link.module.css
+++ b/components/common/Link.module.css
@@ -2,7 +2,7 @@ a.link,
a.link:active,
a.link:visited {
position: relative;
- color: var(--gray900);
+ color: var(--base900);
text-decoration: none;
display: inline-flex;
align-items: center;
@@ -17,15 +17,15 @@ a.link:hover span {
}
a.link.large {
- font-size: var(--font-size-large);
+ font-size: var(--font-size-lg);
}
a.link.small {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
}
a.link.xsmall {
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
}
a.link .icon + * {
diff --git a/components/common/Loading.module.css b/components/common/Loading.module.css
index a69559e3..e2d53243 100644
--- a/components/common/Loading.module.css
+++ b/components/common/Loading.module.css
@@ -25,7 +25,7 @@
height: 100%;
width: 100%;
z-index: 10;
- background: var(--gray400);
+ background: var(--base400);
opacity: 0.4;
}
@@ -33,13 +33,13 @@
width: 10px;
height: 10px;
border-radius: 100%;
- background: var(--gray400);
+ background: var(--base400);
animation: blink 1.4s infinite;
animation-fill-mode: both;
}
.loading.overlay div {
- background: var(--gray900);
+ background: var(--base900);
}
.loading div + div {
diff --git a/components/common/Menu.module.css b/components/common/Menu.module.css
index d2ad2cc4..63491d40 100644
--- a/components/common/Menu.module.css
+++ b/components/common/Menu.module.css
@@ -1,22 +1,22 @@
.menu {
- background: var(--gray50);
- border: 1px solid var(--gray500);
+ background: var(--base50);
+ border: 1px solid var(--base500);
border-radius: 4px;
overflow: hidden;
z-index: 100;
}
.option {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
font-weight: normal;
- background: var(--gray50);
+ background: var(--base50);
padding: 4px 16px;
cursor: pointer;
white-space: nowrap;
}
.option:hover {
- background: var(--gray100);
+ background: var(--base100);
}
.float {
@@ -43,7 +43,7 @@
}
.divider {
- border-top: 1px solid var(--gray300);
+ border-top: 1px solid var(--base300);
}
.selected {
diff --git a/components/common/MenuButton.module.css b/components/common/MenuButton.module.css
index 7e9dd7e1..a59ae562 100644
--- a/components/common/MenuButton.module.css
+++ b/components/common/MenuButton.module.css
@@ -10,11 +10,11 @@
}
.text {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
}
.open,
.open:hover {
- background: var(--gray50);
- border: 1px solid var(--gray500);
+ background: var(--base50);
+ border: 1px solid var(--base500);
}
diff --git a/components/common/MobileMenu.module.css b/components/common/MobileMenu.module.css
index 78a440d9..d1a6f19b 100644
--- a/components/common/MobileMenu.module.css
+++ b/components/common/MobileMenu.module.css
@@ -8,7 +8,7 @@
z-index: 100;
display: flex;
flex-direction: column;
- background-color: var(--gray50);
+ background-color: var(--base50);
overflow: auto;
}
@@ -21,7 +21,7 @@
}
.item {
- font-size: var(--font-size-large);
+ font-size: var(--font-size-lg);
}
.item + .item {
diff --git a/components/common/Modal.module.css b/components/common/Modal.module.css
index bf2491c7..3bba9273 100644
--- a/components/common/Modal.module.css
+++ b/components/common/Modal.module.css
@@ -25,12 +25,12 @@
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
- background: var(--gray50);
+ background: var(--base50);
min-width: 400px;
min-height: 100px;
max-width: 100vw;
z-index: 1;
- border: 1px solid var(--gray300);
+ border: 1px solid var(--base300);
padding: 30px;
border-radius: 4px;
}
diff --git a/components/common/NavMenu.module.css b/components/common/NavMenu.module.css
index 7be73973..e0b01945 100644
--- a/components/common/NavMenu.module.css
+++ b/components/common/NavMenu.module.css
@@ -1,6 +1,6 @@
.menu {
- color: var(--gray800);
- border: 1px solid var(--gray500);
+ color: var(--base800);
+ border: 1px solid var(--base500);
border-radius: 4px;
overflow: hidden;
z-index: 2;
@@ -13,10 +13,10 @@
}
.option:hover {
- background: var(--gray75);
+ background: var(--base75);
}
.selected {
- color: var(--gray900);
+ color: var(--base900);
font-weight: 600;
}
diff --git a/components/common/NoData.module.css b/components/common/NoData.module.css
index 518fa488..29e9f8eb 100644
--- a/components/common/NoData.module.css
+++ b/components/common/NoData.module.css
@@ -1,6 +1,6 @@
.container {
- color: var(--gray500);
- font-size: var(--font-size-normal);
+ color: var(--base500);
+ font-size: var(--font-size-md);
position: relative;
display: flex;
align-items: center;
diff --git a/components/common/Table.module.css b/components/common/Table.module.css
index f92338f8..ba4facc5 100644
--- a/components/common/Table.module.css
+++ b/components/common/Table.module.css
@@ -5,16 +5,16 @@
.table label {
display: none;
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
font-weight: bold;
}
.header {
- border-bottom: 1px solid var(--gray300);
+ border-bottom: 1px solid var(--base300);
}
.head {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
font-weight: 600;
line-height: 40px;
}
@@ -26,7 +26,7 @@
}
.row {
- border-bottom: 1px solid var(--gray300);
+ border-bottom: 1px solid var(--base300);
padding: 10px 0;
}
diff --git a/components/common/Tag.module.css b/components/common/Tag.module.css
index 5e145ea1..95023bbf 100644
--- a/components/common/Tag.module.css
+++ b/components/common/Tag.module.css
@@ -1,6 +1,6 @@
.tag {
padding: 2px 4px;
- border: 1px solid var(--gray300);
+ border: 1px solid var(--base300);
border-radius: 4px;
margin-right: 10px;
}
diff --git a/components/common/Toast.module.css b/components/common/Toast.module.css
index 58677dcb..18b8b44d 100644
--- a/components/common/Toast.module.css
+++ b/components/common/Toast.module.css
@@ -17,7 +17,7 @@
}
.message {
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
}
.close {
diff --git a/components/common/UpdateNotice.module.css b/components/common/UpdateNotice.module.css
index 52bac611..5161ea71 100644
--- a/components/common/UpdateNotice.module.css
+++ b/components/common/UpdateNotice.module.css
@@ -6,7 +6,7 @@
}
.message {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
font-weight: 600;
flex: 1;
text-align: center;
diff --git a/components/declarations.d.ts b/components/declarations.d.ts
new file mode 100644
index 00000000..31e44ff3
--- /dev/null
+++ b/components/declarations.d.ts
@@ -0,0 +1,2 @@
+declare module '*.css';
+declare module '*.svg';
diff --git a/components/forms/DatePickerForm.module.css b/components/forms/DatePickerForm.module.css
index 96e2d2ec..92e59bb7 100644
--- a/components/forms/DatePickerForm.module.css
+++ b/components/forms/DatePickerForm.module.css
@@ -16,7 +16,7 @@
.calendars > div + div {
margin-left: 20px;
padding-left: 20px;
- border-left: 1px solid var(--gray300);
+ border-left: 1px solid var(--base300);
}
.filter {
diff --git a/components/forms/EventDataForm.module.css b/components/forms/EventDataForm.module.css
index 19d76f77..fd0ad290 100644
--- a/components/forms/EventDataForm.module.css
+++ b/components/forms/EventDataForm.module.css
@@ -3,7 +3,7 @@
}
.form {
- border-right: 1px solid var(--gray300);
+ border-right: 1px solid var(--base300);
width: 420px;
}
@@ -12,7 +12,7 @@
}
.filters + .filters {
- border-top: 1px solid var(--gray300);
+ border-top: 1px solid var(--base300);
min-height: 250px;
}
diff --git a/components/forms/Form.module.css b/components/forms/Form.module.css
new file mode 100644
index 00000000..9185da43
--- /dev/null
+++ b/components/forms/Form.module.css
@@ -0,0 +1,63 @@
+.form {
+ display: flex;
+ flex-direction: column;
+ gap: 30px;
+ width: 300px;
+ margin: 0 auto;
+}
+
+.header {
+ font-size: 24px;
+ font-weight: 700;
+ text-align: center;
+ margin: 30px auto;
+}
+
+.info {
+ text-align: center;
+ padding: 30px 0;
+}
+
+.footer {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ font-size: 14px;
+ text-align: center;
+ margin: 30px auto;
+}
+
+.footer a {
+ font-weight: 600;
+}
+
+.buttons {
+ justify-content: center;
+}
+
+.button {
+ flex: 1;
+ justify-content: center;
+}
+
+.error {
+ width: 600px;
+ margin: 0 auto 30px;
+ background: var(--base50);
+ padding: 16px;
+ color: var(--red400);
+ border: 1px solid var(--red400);
+ border-radius: 5px;
+ text-align: center;
+}
+
+.success {
+ width: 600px;
+ margin: 60px auto;
+ background: var(--base50);
+ padding: 16px;
+ color: var(--green400);
+ border: 1px solid var(--green400);
+ border-radius: 5px;
+ text-align: center;
+}
diff --git a/components/forms/LoginForm.js b/components/forms/LoginForm.js
index 6a6560f1..aad3f97d 100644
--- a/components/forms/LoginForm.js
+++ b/components/forms/LoginForm.js
@@ -1,113 +1,57 @@
-import React, { useState } from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Formik, Form, Field } from 'formik';
-import { setItem } from 'next-basics';
-import { useRouter } from 'next/router';
-import Button from 'components/common/Button';
-import FormLayout, {
+import { useMutation } from '@tanstack/react-query';
+import {
+ Form,
+ FormInput,
FormButtons,
- FormError,
- FormMessage,
- FormRow,
-} from 'components/layout/FormLayout';
-import Icon from 'components/common/Icon';
-import useApi from 'hooks/useApi';
-import { AUTH_TOKEN } from 'lib/constants';
+ TextField,
+ PasswordField,
+ SubmitButton,
+ Icon,
+} from 'react-basics';
+import { useRouter } from 'next/router';
+import { useApi } from 'next-basics';
import { setUser } from 'store/app';
+import { setAuthToken } from 'lib/client';
import Logo from 'assets/logo.svg';
-import styles from './LoginForm.module.css';
-
-const validate = ({ username, password }) => {
- const errors = {};
-
- if (!username) {
- errors.username = ;
- }
- if (!password) {
- errors.password = ;
- }
-
- return errors;
-};
+import styles from './Form.module.css';
export default function LoginForm() {
- const { post } = useApi();
const router = useRouter();
- const [message, setMessage] = useState();
+ const { post } = useApi();
+ const { mutate, error, isLoading } = useMutation(data => post('/auth/login', data));
- const handleSubmit = async ({ username, password }) => {
- const { ok, status, data } = await post('/auth/login', {
- username,
- password,
+ const handleSubmit = async data => {
+ mutate(data, {
+ onSuccess: async ({ token, user }) => {
+ setAuthToken(token);
+ setUser(user);
+
+ await router.push('/websites');
+ },
});
-
- if (ok) {
- const { user, token } = data;
-
- setItem(AUTH_TOKEN, token);
-
- setUser(user);
-
- await router.push('/');
-
- return null;
- } else {
- setMessage(
- status === 401 ? (
-
- ) : (
- data
- ),
- );
- }
};
return (
-
-
- {() => (
-
- )}
-
-
+ <>
+
+
+ >
);
}
diff --git a/components/layout/Footer.module.css b/components/layout/Footer.module.css
index c484d7f5..b86e9724 100644
--- a/components/layout/Footer.module.css
+++ b/components/layout/Footer.module.css
@@ -2,7 +2,7 @@
display: flex;
justify-content: space-between;
align-items: center;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
text-align: center;
margin: 30px 0;
}
diff --git a/components/layout/FormLayout.module.css b/components/layout/FormLayout.module.css
index 6d787136..48363f65 100644
--- a/components/layout/FormLayout.module.css
+++ b/components/layout/FormLayout.module.css
@@ -54,7 +54,7 @@
.msg {
color: var(--msgColor);
background: var(--red400);
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
padding: 4px 8px;
border-radius: 4px;
white-space: nowrap;
@@ -78,8 +78,8 @@
margin: 20px 0;
padding: 4px 8px;
border-radius: 4px;
- color: var(--gray50);
- background: var(--gray800);
+ color: var(--base50);
+ background: var(--base800);
}
@media only screen and (max-width: 576px) {
diff --git a/components/layout/GridLayout.module.css b/components/layout/GridLayout.module.css
index 675fce16..ee7947b6 100644
--- a/components/layout/GridLayout.module.css
+++ b/components/layout/GridLayout.module.css
@@ -9,12 +9,12 @@
}
.row {
- border-top: 1px solid var(--gray300);
+ border-top: 1px solid var(--base300);
min-height: 430px;
}
.row > .col {
- border-left: 1px solid var(--gray300);
+ border-left: 1px solid var(--base300);
padding: 20px;
}
@@ -33,7 +33,7 @@
}
.row > .col {
- border-top: 1px solid var(--gray300);
+ border-top: 1px solid var(--base300);
border-left: 0;
padding: 20px 0;
}
diff --git a/components/layout/GridRow.js b/components/layout/GridRow.js
new file mode 100644
index 00000000..8f840a84
--- /dev/null
+++ b/components/layout/GridRow.js
@@ -0,0 +1,18 @@
+import { Row, cloneChildren } from 'react-basics';
+import styles from './GridRow.module.css';
+import classNames from 'classnames';
+
+export default function GridRow(props) {
+ const { children, className, ...rowProps } = props;
+ return (
+
+ {breakpoint =>
+ cloneChildren(children, () => {
+ return {
+ className: classNames(styles.column, styles[breakpoint]),
+ };
+ })
+ }
+
+ );
+}
diff --git a/components/layout/GridRow.module.css b/components/layout/GridRow.module.css
new file mode 100644
index 00000000..dc1e31f8
--- /dev/null
+++ b/components/layout/GridRow.module.css
@@ -0,0 +1,21 @@
+.column {
+ padding: 20px;
+ border-top: 1px solid var(--base200);
+ border-left: 1px solid var(--base200);
+}
+
+.column:first-child {
+ padding-left: 0;
+ border-left: 0;
+}
+
+.column:last-child {
+ padding-right: 0;
+}
+
+.column.xs,
+.column.sm,
+.column.md {
+ border-left: 0;
+ border-right: 0;
+}
diff --git a/components/layout/Header.js b/components/layout/Header.js
index 13c3954e..a0063cfb 100644
--- a/components/layout/Header.js
+++ b/components/layout/Header.js
@@ -1,6 +1,6 @@
+import { Row, Column } from 'react-basics';
import { useRouter } from 'next/router';
import { FormattedMessage } from 'react-intl';
-import classNames from 'classnames';
import Link from 'components/common/Link';
import Icon from 'components/common/Icon';
import LanguageButton from 'components/settings/LanguageButton';
@@ -25,31 +25,33 @@ export default function Header() {
return (
<>
{allowUpdate && }
-
-
- } size="large" className={styles.logo} />
- umami
-
-
- {user && !adminDisabled && (
-
-
-
-
-
-
-
-
-
-
-
- )}
-
-
-
-
- {user && !adminDisabled && }
-
+
+
+
+ } size="large" className={styles.logo} />
+ umami
+
+
+ {user && !adminDisabled && (
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+ {user && !adminDisabled && }
+
+
>
);
diff --git a/components/layout/Header.module.css b/components/layout/Header.module.css
index 8882e9de..44bac0c5 100644
--- a/components/layout/Header.module.css
+++ b/components/layout/Header.module.css
@@ -7,10 +7,10 @@
.title {
flex: 1;
- font-size: var(--font-size-large);
+ font-size: var(--font-size-lg);
display: flex;
align-items: center;
- line-height: 1.4;
+ flex-direction: row;
}
.logo {
@@ -22,7 +22,7 @@
display: flex;
justify-content: center;
align-items: center;
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
font-weight: 600;
}
@@ -33,6 +33,7 @@
.buttons {
flex: 1;
display: flex;
+ flex-direction: row;
justify-content: flex-end;
align-items: center;
}
diff --git a/components/layout/Layout.js b/components/layout/Layout.js
index 2c097e41..1a8d4887 100644
--- a/components/layout/Layout.js
+++ b/components/layout/Layout.js
@@ -1,22 +1,32 @@
-import React from 'react';
+import { Container } from 'react-basics';
import Head from 'next/head';
import Header from 'components/layout/Header';
import Footer from 'components/layout/Footer';
import useLocale from 'hooks/useLocale';
+import { useRouter } from 'next/router';
export default function Layout({ title, children, header = true, footer = true }) {
const { dir } = useLocale();
+ const { basePath } = useRouter();
return (
- <>
+
- umami{title && ` - ${title}`}
+ {title ? `${title} | umami` : 'umami'}
+
+
+
+
+
+
+
+
+
+
-
{header && }
{children}
{footer && }
-
- >
+
);
}
diff --git a/components/layout/MenuLayout.module.css b/components/layout/MenuLayout.module.css
index 126d31a3..b5a812a4 100644
--- a/components/layout/MenuLayout.module.css
+++ b/components/layout/MenuLayout.module.css
@@ -12,7 +12,7 @@
.container .content {
flex: 1;
position: relative;
- border-left: 1px solid var(--gray300);
+ border-left: 1px solid var(--base300);
padding-left: 30px;
margin-left: 30px;
}
@@ -30,7 +30,7 @@
}
.container .content {
- border-top: 1px solid var(--gray300);
+ border-top: 1px solid var(--base300);
border-left: 0;
padding-left: 0;
margin-left: 0;
diff --git a/components/layout/Page.module.css b/components/layout/Page.module.css
index c80d0f1b..d3b03fff 100644
--- a/components/layout/Page.module.css
+++ b/components/layout/Page.module.css
@@ -3,5 +3,6 @@
display: flex;
flex-direction: column;
padding: 0 30px;
- background: var(--gray50);
+ background: var(--base50);
+ border-radius: 8px;
}
diff --git a/components/metrics/ActiveUsers.module.css b/components/metrics/ActiveUsers.module.css
index 31c6f346..e290e3de 100644
--- a/components/metrics/ActiveUsers.module.css
+++ b/components/metrics/ActiveUsers.module.css
@@ -5,7 +5,7 @@
.text {
display: flex;
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
}
.value {
diff --git a/components/metrics/ChartTooltip.module.css b/components/metrics/ChartTooltip.module.css
index cd26d3af..2d7ba958 100644
--- a/components/metrics/ChartTooltip.module.css
+++ b/components/metrics/ChartTooltip.module.css
@@ -17,7 +17,7 @@
}
.title {
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
font-weight: 600;
}
@@ -25,7 +25,7 @@
display: flex;
justify-content: center;
align-items: center;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
font-weight: 600;
}
@@ -34,7 +34,7 @@
overflow: hidden;
border-radius: 100%;
margin-right: 8px;
- background: var(--gray50);
+ background: var(--base50);
}
.color {
diff --git a/components/metrics/DataTable.module.css b/components/metrics/DataTable.module.css
index 5831d837..93c8f622 100644
--- a/components/metrics/DataTable.module.css
+++ b/components/metrics/DataTable.module.css
@@ -1,7 +1,7 @@
.table {
position: relative;
height: 100%;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
display: grid;
grid-template-rows: fit-content(100%) auto;
overflow: hidden;
@@ -23,11 +23,11 @@
.title {
display: flex;
font-weight: 600;
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
}
.metric {
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
font-weight: 600;
text-align: center;
width: 100px;
@@ -80,8 +80,8 @@
.percent {
position: relative;
width: 50px;
- color: var(--gray600);
- border-left: 1px solid var(--gray600);
+ color: var(--base600);
+ border-left: 1px solid var(--base600);
padding-left: 10px;
z-index: 1;
}
diff --git a/components/metrics/Legend.module.css b/components/metrics/Legend.module.css
index faa197e3..e78bf609 100644
--- a/components/metrics/Legend.module.css
+++ b/components/metrics/Legend.module.css
@@ -8,7 +8,7 @@
.label {
display: flex;
align-items: center;
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
cursor: pointer;
}
@@ -17,5 +17,5 @@
}
.hidden {
- color: var(--gray400);
+ color: var(--base400);
}
diff --git a/components/metrics/MetricCard.module.css b/components/metrics/MetricCard.module.css
index a79385aa..7de16157 100644
--- a/components/metrics/MetricCard.module.css
+++ b/components/metrics/MetricCard.module.css
@@ -6,7 +6,7 @@
}
.value {
- font-size: var(--font-size-xlarge);
+ font-size: var(--font-size-xl);
line-height: 40px;
min-height: 40px;
font-weight: 600;
@@ -14,7 +14,7 @@
}
.label {
- font-size: var(--font-size-normal);
+ font-size: var(--font-size-md);
white-space: nowrap;
display: flex;
align-items: center;
@@ -26,8 +26,8 @@
padding: 0 5px;
border-radius: 5px;
margin-left: 4px;
- border: 1px solid var(--gray200);
- color: var(--gray500);
+ border: 1px solid var(--base200);
+ color: var(--base500);
}
.change.positive {
diff --git a/components/metrics/MetricsTable.module.css b/components/metrics/MetricsTable.module.css
index d3a70866..7f3da961 100644
--- a/components/metrics/MetricsTable.module.css
+++ b/components/metrics/MetricsTable.module.css
@@ -2,7 +2,7 @@
position: relative;
min-height: 430px;
height: 100%;
- font-size: var(--font-size-small);
+ font-size: var(--font-size-sm);
display: flex;
flex-direction: column;
}
diff --git a/components/metrics/RealtimeLog.module.css b/components/metrics/RealtimeLog.module.css
index 7c07d017..292bbd8c 100644
--- a/components/metrics/RealtimeLog.module.css
+++ b/components/metrics/RealtimeLog.module.css
@@ -1,5 +1,5 @@
.table {
- font-size: var(--font-size-xsmall);
+ font-size: var(--font-size-xs);
overflow: hidden;
height: 100%;
display: grid;
@@ -19,7 +19,7 @@
display: flex;
align-items: center;
height: 40px;
- border-bottom: 1px solid var(--gray300);
+ border-bottom: 1px solid var(--base300);
}
.body {
@@ -50,7 +50,7 @@
}
.row .link {
- color: var(--gray900);
+ color: var(--base900);
text-decoration: none;
}
diff --git a/components/metrics/WebsiteChart.js b/components/metrics/WebsiteChart.js
index e4a7f527..a76e1f93 100644
--- a/components/metrics/WebsiteChart.js
+++ b/components/metrics/WebsiteChart.js
@@ -1,5 +1,5 @@
-import React, { useMemo } from 'react';
-import classNames from 'classnames';
+import { useMemo } from 'react';
+import { Row, Column } from 'react-basics';
import PageviewsChart from './PageviewsChart';
import MetricsBar from './MetricsBar';
import WebsiteHeader from './WebsiteHeader';
@@ -20,7 +20,6 @@ export default function WebsiteChart({
title,
domain,
stickyHeader = false,
- showLink = false,
showChart = true,
onDataLoad = () => {},
}) {
@@ -80,33 +79,34 @@ export default function WebsiteChart({
}
return (
-
-
-
-
-
-
+ <>
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
{error && }
{showChart && (
)}
-
-
-
+
+
+ >
);
}
diff --git a/components/metrics/WebsiteChart.module.css b/components/metrics/WebsiteChart.module.css
index d0a8ea68..d108366e 100644
--- a/components/metrics/WebsiteChart.module.css
+++ b/components/metrics/WebsiteChart.module.css
@@ -7,10 +7,11 @@
.chart {
position: relative;
+ padding-bottom: 20px;
}
.title {
- font-size: var(--font-size-large);
+ font-size: var(--font-size-lg);
line-height: 60px;
font-weight: 600;
}
@@ -31,19 +32,11 @@
position: fixed;
top: 0;
margin: auto;
- background: var(--gray50);
- border-bottom: 1px solid var(--gray300);
+ background: var(--base50);
+ border-bottom: 1px solid var(--base300);
z-index: 3;
}
.filter {
- display: flex;
- justify-content: flex-end;
- align-items: center;
-}
-
-@media only screen and (max-width: 992px) {
- .filter {
- display: block;
- }
+ align-self: center;
}
diff --git a/components/metrics/WebsiteHeader.js b/components/metrics/WebsiteHeader.js
index 517ef140..5d59b199 100644
--- a/components/metrics/WebsiteHeader.js
+++ b/components/metrics/WebsiteHeader.js
@@ -1,57 +1,22 @@
-import Arrow from 'assets/arrow-right.svg';
-import classNames from 'classnames';
+import { Row, Column } from 'react-basics';
import Favicon from 'components/common/Favicon';
-import Link from 'components/common/Link';
import OverflowText from 'components/common/OverflowText';
-import RefreshButton from 'components/common/RefreshButton';
-import ButtonLayout from 'components/layout/ButtonLayout';
import PageHeader from 'components/layout/PageHeader';
-import { FormattedMessage } from 'react-intl';
import ActiveUsers from './ActiveUsers';
import styles from './WebsiteHeader.module.css';
-export default function WebsiteHeader({ websiteId, title, domain, showLink = false }) {
- const header = showLink ? (
- <>
-
-
- {title}
-
- >
- ) : (
- <>
-
- {title}
- >
- );
-
+export default function WebsiteHeader({ websiteId, title, domain }) {
return (
-
- {header}
-
-
-
-
- {showLink && (
- }
- size="small"
- iconRight
- >
-
-
- )}
-
-
+
+
+
+
+ {title}
+
+
+
+
+
);
}
diff --git a/components/metrics/WebsiteHeader.module.css b/components/metrics/WebsiteHeader.module.css
index b888cadd..f7700fe8 100644
--- a/components/metrics/WebsiteHeader.module.css
+++ b/components/metrics/WebsiteHeader.module.css
@@ -1,32 +1,15 @@
.title {
- color: var(--gray900);
- font-size: var(--font-size-large);
- line-height: var(--font-size-xlarge);
- align-items: center;
display: flex;
- max-width: 100%;
+ flex-direction: row;
+ align-items: center;
+ gap: 10px;
+ font-size: var(--font-size-lg);
overflow: hidden;
}
-.titleLink {
- max-width: 100%;
-}
-
-.link {
- font-weight: 600;
-}
-
.active {
display: flex;
+ flex-direction: row;
+ align-items: center;
justify-content: center;
}
-
-@media only screen and (max-width: 992px) {
- .active {
- justify-content: flex-start;
- }
-
- a.link {
- display: none;
- }
-}
diff --git a/components/pages/DashboardEdit.module.css b/components/pages/DashboardEdit.module.css
index dcda714a..febc551d 100644
--- a/components/pages/DashboardEdit.module.css
+++ b/components/pages/DashboardEdit.module.css
@@ -16,19 +16,19 @@
.item h2 {
font-size: 14px;
- color: var(--gray700);
+ color: var(--base700);
}
.text {
padding: 20px;
border-radius: 5px;
- border: 1px solid var(--gray400);
- background: var(--gray50);
+ border: 1px solid var(--base400);
+ background: var(--base50);
}
.active .text {
- border-color: var(--gray600);
- box-shadow: 4px 4px 4px var(--gray100);
+ border-color: var(--base600);
+ box-shadow: 4px 4px 4px var(--base100);
}
.dragActive {
diff --git a/components/pages/TestConsole.js b/components/pages/TestConsole.js
index 4e80fcf8..c505030c 100644
--- a/components/pages/TestConsole.js
+++ b/components/pages/TestConsole.js
@@ -1,4 +1,4 @@
-import classNames from 'classnames';
+import { Row, Column } from 'react-basics';
import Head from 'next/head';
import Link from 'next/link';
import { useRouter } from 'next/router';
@@ -62,8 +62,8 @@ export default function TestConsole() {
{website && (
<>
-
-
+
+
Page links
@@ -87,22 +87,22 @@ export default function TestConsole() {
-
-
+
+
CSS events
-
-
+
+
Javascript events
-
-
-
+
+
>
)}
diff --git a/components/pages/TestConsole.module.css b/components/pages/TestConsole.module.css
index 690904b6..5ff8b96a 100644
--- a/components/pages/TestConsole.module.css
+++ b/components/pages/TestConsole.module.css
@@ -1,5 +1,5 @@
.test {
- border: 1px solid var(--gray200);
+ border: 1px solid var(--base200);
border-radius: 5px;
padding: 0 20px 20px 20px;
}
diff --git a/components/pages/WebsiteDetails.js b/components/pages/WebsiteDetails.js
index b40bc9ee..9f53c9b6 100644
--- a/components/pages/WebsiteDetails.js
+++ b/components/pages/WebsiteDetails.js
@@ -1,14 +1,14 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
+import { Column } from 'react-basics';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import classNames from 'classnames';
import WebsiteChart from 'components/metrics/WebsiteChart';
import WorldMap from 'components/common/WorldMap';
import Page from 'components/layout/Page';
-import GridLayout, { GridRow, GridColumn } from 'components/layout/GridLayout';
+import GridRow from 'components/layout/GridRow';
import MenuLayout from 'components/layout/MenuLayout';
import Link from 'components/common/Link';
import Loading from 'components/common/Loading';
-import Arrow from 'assets/arrow-right.svg';
import PagesTable from 'components/metrics/PagesTable';
import ReferrersTable from 'components/metrics/ReferrersTable';
import BrowsersTable from 'components/metrics/BrowsersTable';
@@ -16,15 +16,13 @@ import OSTable from 'components/metrics/OSTable';
import DevicesTable from 'components/metrics/DevicesTable';
import CountriesTable from 'components/metrics/CountriesTable';
import LanguagesTable from 'components/metrics/LanguagesTable';
-import EventsTable from 'components/metrics/EventsTable';
-import EventsChart from 'components/metrics/EventsChart';
import ScreenTable from 'components/metrics/ScreenTable';
import QueryParametersTable from 'components/metrics/QueryParametersTable';
import useFetch from 'hooks/useFetch';
import usePageQuery from 'hooks/usePageQuery';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
+import Arrow from 'assets/arrow-right.svg';
import styles from './WebsiteDetails.module.css';
-import EventDataButton from 'components/common/EventDataButton';
const messages = defineMessages({
pages: { id: 'metrics.pages', defaultMessage: 'Pages' },
@@ -35,7 +33,6 @@ const messages = defineMessages({
devices: { id: 'metrics.devices', defaultMessage: 'Devices' },
countries: { id: 'metrics.countries', defaultMessage: 'Countries' },
languages: { id: 'metrics.languages', defaultMessage: 'Languages' },
- events: { id: 'metrics.events', defaultMessage: 'Events' },
query: { id: 'metrics.query-parameters', defaultMessage: 'Query parameters' },
});
@@ -48,7 +45,6 @@ const views = {
screen: ScreenTable,
country: CountriesTable,
language: LanguagesTable,
- event: EventsTable,
query: QueryParametersTable,
};
@@ -56,7 +52,6 @@ export default function WebsiteDetails({ websiteId }) {
const { data } = useFetch(`/websites/${websiteId}`);
const [chartLoaded, setChartLoaded] = useState(false);
const [countryData, setCountryData] = useState();
- const [eventsData, setEventsData] = useState();
const {
resolve,
query: { view },
@@ -65,7 +60,7 @@ export default function WebsiteDetails({ websiteId }) {
const BackButton = () => (
- } size="small">
+ } sizes="small">
@@ -107,10 +102,6 @@ export default function WebsiteDetails({ websiteId }) {
label: formatMessage(messages.screens),
value: resolve({ view: 'screen' }),
},
- {
- label: formatMessage(messages.events),
- value: resolve({ view: 'event' }),
- },
{
label: formatMessage(messages.query),
value: resolve({ view: 'query' }),
@@ -137,58 +128,45 @@ export default function WebsiteDetails({ websiteId }) {
return (
-
-
-
- {!chartLoaded && }
-
-
+
+ {!chartLoaded && }
{chartLoaded && !view && (
-
+ <>
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
- 0 })}>
-
-
-
-
-
-
-
-
-
+ >
)}
{view && chartLoaded && (
extends NextApiRequest {
- auth: Auth;
- query: TQuery;
- body: TBody;
-}
-
-export interface NextApiRequestQuery extends NextApiRequest {
- auth: Auth;
- query: TQuery;
-}
-
-export interface NextApiRequestBody extends NextApiRequest {
- auth: Auth;
- body: TBody;
-}
-
-export interface ObjectAny {
- [key: string]: any;
-}
diff --git a/interface/index.d.ts b/interface/index.d.ts
deleted file mode 100644
index 5d498ebf..00000000
--- a/interface/index.d.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NextApiRequest } from 'next';
-import { Auth } from './auth';
-
-export interface NextApiRequestQueryBody extends NextApiRequest {
- auth: Auth;
- query: TQuery;
- body: TBody;
-}
-
-export interface NextApiRequestQuery extends NextApiRequest {
- auth: Auth;
- query: TQuery;
-}
-
-export interface NextApiRequestBody extends NextApiRequest {
- auth: Auth;
- body: TBody;
-}
-
-export interface ObjectAny {
- [key: string]: any;
-}
diff --git a/lib/auth.js b/lib/auth.js
deleted file mode 100644
index 09193e89..00000000
--- a/lib/auth.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { parseSecureToken, parseToken } from 'next-basics';
-import { getUser, getWebsite } from 'queries';
-import debug from 'debug';
-import { SHARE_TOKEN_HEADER, TYPE_USER, TYPE_WEBSITE } from 'lib/constants';
-import { secret } from 'lib/crypto';
-
-const log = debug('umami:auth');
-
-export function getAuthToken(req) {
- try {
- return req.headers.authorization.split(' ')[1];
- } catch {
- return null;
- }
-}
-
-export function parseAuthToken(req) {
- try {
- return parseSecureToken(getAuthToken(req), secret());
- } catch (e) {
- log(e);
- return null;
- }
-}
-
-export function parseShareToken(req) {
- try {
- return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
- } catch (e) {
- log(e);
- return null;
- }
-}
-
-export function isValidToken(token, validation) {
- try {
- if (typeof validation === 'object') {
- return !Object.keys(validation).find(key => token[key] !== validation[key]);
- } else if (typeof validation === 'function') {
- return validation(token);
- }
- } catch (e) {
- log(e);
- return false;
- }
-
- return false;
-}
-
-export async function allowQuery(req, type) {
- const { id } = req.query;
-
- const { user, shareToken } = req.auth;
-
- if (user?.isAdmin) {
- return true;
- }
-
- if (shareToken) {
- return isValidToken(shareToken, { id });
- }
-
- if (user?.id) {
- if (type === TYPE_WEBSITE) {
- const website = await getWebsite({ id });
-
- return website && website.userId === user.id;
- } else if (type === TYPE_USER) {
- const user = await getUser({ id });
-
- return user && user.id === id;
- }
- }
-
- return false;
-}
diff --git a/lib/auth.ts b/lib/auth.ts
new file mode 100644
index 00000000..7ba778c7
--- /dev/null
+++ b/lib/auth.ts
@@ -0,0 +1,129 @@
+import { parseSecureToken, parseToken, ensureArray } from 'next-basics';
+import debug from 'debug';
+import cache from 'lib/cache';
+import { SHARE_TOKEN_HEADER, PERMISSIONS, ROLE_PERMISSIONS } from 'lib/constants';
+import { secret } from 'lib/crypto';
+import { getTeamUser } from 'queries';
+
+const log = debug('umami:auth');
+
+export function getAuthToken(req) {
+ try {
+ return req.headers.authorization.split(' ')[1];
+ } catch {
+ return null;
+ }
+}
+
+export function parseAuthToken(req) {
+ try {
+ return parseSecureToken(getAuthToken(req), secret());
+ } catch (e) {
+ log(e);
+ return null;
+ }
+}
+
+export function parseShareToken(req) {
+ try {
+ return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
+ } catch (e) {
+ log(e);
+ return null;
+ }
+}
+
+export function isValidToken(token, validation) {
+ try {
+ if (typeof validation === 'object') {
+ return !Object.keys(validation).find(key => token[key] !== validation[key]);
+ } else if (typeof validation === 'function') {
+ return validation(token);
+ }
+ } catch (e) {
+ log(e);
+ return false;
+ }
+
+ return false;
+}
+
+export async function canViewWebsite(userId: string, websiteId: string) {
+ const website = await cache.fetchWebsite(websiteId);
+
+ if (website.userId) {
+ return userId === website.userId;
+ }
+
+ if (website.teamId) {
+ return getTeamUser(website.teamId, userId);
+ }
+
+ return false;
+}
+
+export async function canUpdateWebsite(userId: string, websiteId: string) {
+ const website = await cache.fetchWebsite(websiteId);
+
+ if (website.userId) {
+ return userId === website.userId;
+ }
+
+ if (website.teamId) {
+ const teamUser = await getTeamUser(website.teamId, userId);
+
+ return hasPermission(teamUser.role, PERMISSIONS.websiteUpdate);
+ }
+
+ return false;
+}
+
+export async function canDeleteWebsite(userId: string, websiteId: string) {
+ const website = await cache.fetchWebsite(websiteId);
+
+ if (website.userId) {
+ return userId === website.userId;
+ }
+
+ if (website.teamId) {
+ const teamUser = await getTeamUser(website.teamId, userId);
+
+ return hasPermission(teamUser.role, PERMISSIONS.websiteDelete);
+ }
+
+ return false;
+}
+
+// To-do: Implement when payments are setup.
+export async function canCreateTeam(userId: string) {
+ return !!userId;
+}
+
+// To-do: Implement when payments are setup.
+export async function canViewTeam(userId: string, teamId) {
+ return getTeamUser(teamId, userId);
+}
+
+export async function canUpdateTeam(userId: string, teamId: string) {
+ const teamUser = await getTeamUser(teamId, userId);
+
+ return hasPermission(teamUser.role, PERMISSIONS.teamUpdate);
+}
+
+export async function canDeleteTeam(userId: string, teamId: string) {
+ const teamUser = await getTeamUser(teamId, userId);
+
+ return hasPermission(teamUser.role, PERMISSIONS.teamDelete);
+}
+
+export async function canViewUser(userId: string, viewedUserId: string) {
+ return userId === viewedUserId;
+}
+
+export async function canUpdateUser(userId: string, viewedUserId: string) {
+ return userId === viewedUserId;
+}
+
+export async function hasPermission(role: string, permission: string | string[]) {
+ return ensureArray(permission).some(e => ROLE_PERMISSIONS[role]?.includes(e));
+}
diff --git a/lib/cache.js b/lib/cache.ts
similarity index 79%
rename from lib/cache.js
rename to lib/cache.ts
index bc065c14..5c79def0 100644
--- a/lib/cache.js
+++ b/lib/cache.ts
@@ -1,5 +1,6 @@
-import { getWebsite, getUser, getSession } from '../queries';
-import redis, { DELETED } from 'lib/redis';
+import { User, Website } from '@prisma/client';
+import redis from 'lib/redis';
+import { getSession, getUser, getWebsite } from '../queries';
async function fetchObject(key, query) {
const obj = await redis.get(key);
@@ -22,10 +23,10 @@ async function storeObject(key, data) {
}
async function deleteObject(key) {
- return redis.set(key, DELETED);
+ return redis.set(key, redis.DELETED);
}
-async function fetchWebsite(id) {
+async function fetchWebsite(id): Promise {
return fetchObject(`website:${id}`, () => getWebsite({ id }));
}
@@ -40,8 +41,8 @@ async function deleteWebsite(id) {
return deleteObject(`website:${id}`);
}
-async function fetchUser(id) {
- return fetchObject(`user:${id}`, () => getUser({ id }));
+async function fetchUser(id): Promise {
+ return fetchObject(`user:${id}`, () => getUser({ id }, true));
}
async function storeUser(data) {
diff --git a/lib/clickhouse.js b/lib/clickhouse.js
index 3d44daac..b28694b6 100644
--- a/lib/clickhouse.js
+++ b/lib/clickhouse.js
@@ -106,7 +106,7 @@ function getEventDataFilterQuery(column, filters) {
return query.join('\nand ');
}
-function getFilterQuery(column, filters = {}, params = []) {
+function getFilterQuery(filters = {}, params = []) {
const query = Object.keys(filters).reduce((arr, key) => {
const filter = filters[key];
@@ -146,7 +146,7 @@ function getFilterQuery(column, filters = {}, params = []) {
return query.join('\n');
}
-function parseFilters(column, filters = {}, params = []) {
+function parseFilters(filters = {}, params = []) {
const { domain, url, event_url, referrer, os, browser, device, country, event_name, query } =
filters;
@@ -159,9 +159,7 @@ function parseFilters(column, filters = {}, params = []) {
sessionFilters,
eventFilters,
event: { event_name },
- pageviewQuery: getFilterQuery(column, pageviewFilters, params),
- sessionQuery: getFilterQuery(column, sessionFilters, params),
- eventQuery: getFilterQuery(column, eventFilters, params),
+ filterQuery: getFilterQuery(filters, params),
};
}
diff --git a/lib/client.ts b/lib/client.ts
new file mode 100644
index 00000000..df68c6f8
--- /dev/null
+++ b/lib/client.ts
@@ -0,0 +1,14 @@
+import { getItem, setItem, removeItem } from 'next-basics';
+import { AUTH_TOKEN } from './constants';
+
+export function getAuthToken() {
+ return getItem(AUTH_TOKEN);
+}
+
+export function setAuthToken(token) {
+ setItem(AUTH_TOKEN, token);
+}
+
+export function removeAuthToken() {
+ removeItem(AUTH_TOKEN);
+}
diff --git a/lib/constants.js b/lib/constants.ts
similarity index 86%
rename from lib/constants.js
rename to lib/constants.ts
index 0e4eabec..54933d53 100644
--- a/lib/constants.js
+++ b/lib/constants.ts
@@ -1,3 +1,4 @@
+/* eslint-disable no-unused-vars */
export const CURRENT_VERSION = process.env.currentVersion;
export const AUTH_TOKEN = 'umami.auth';
export const LOCALE_CONFIG = 'umami.locale';
@@ -21,8 +22,51 @@ export const DEFAULT_WEBSITE_LIMIT = 10;
export const REALTIME_RANGE = 30;
export const REALTIME_INTERVAL = 3000;
-export const TYPE_WEBSITE = 'website';
-export const TYPE_USER = 'user';
+export const EVENT_TYPE = {
+ pageView: 1,
+ customEvent: 2,
+};
+
+export const ROLES = {
+ admin: 'admin',
+ user: 'user',
+ teamOwner: 'team-owner',
+ teamMember: 'team-member',
+ teamGuest: 'team-guest',
+};
+
+export const PERMISSIONS = {
+ all: 'all',
+ websiteCreate: 'website:create',
+ websiteUpdate: 'website:update',
+ websiteDelete: 'website:delete',
+ teamCreate: 'team:create',
+ teamUpdate: 'team:update',
+ teamDelete: 'team:delete',
+};
+
+export const ROLE_PERMISSIONS = {
+ [ROLES.admin]: [PERMISSIONS.all],
+ [ROLES.user]: [
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ PERMISSIONS.teamCreate,
+ ],
+ [ROLES.teamOwner]: [
+ PERMISSIONS.teamUpdate,
+ PERMISSIONS.teamDelete,
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ ],
+ [ROLES.teamMember]: [
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ ],
+ [ROLES.teamGuest]: [],
+};
export const THEME_COLORS = {
light: {
diff --git a/lib/middleware.js b/lib/middleware.js
index c60d2770..9d1498c7 100644
--- a/lib/middleware.js
+++ b/lib/middleware.js
@@ -3,9 +3,10 @@ import debug from 'debug';
import cors from 'cors';
import { validate } from 'uuid';
import { findSession } from 'lib/session';
-import { parseShareToken, getAuthToken } from 'lib/auth';
+import { getAuthToken, parseShareToken } from 'lib/auth';
import { secret } from 'lib/crypto';
import redis from 'lib/redis';
+import { ROLES } from 'lib/constants';
import { getUser } from '../queries';
const log = debug('umami:middleware');
@@ -45,6 +46,10 @@ export const useAuth = createMiddleware(async (req, res, next) => {
return unauthorized(res);
}
+ if (user) {
+ user.isAdmin = user.role === ROLES.admin;
+ }
+
req.auth = { user, token, shareToken, key };
next();
});
diff --git a/lib/prisma.js b/lib/prisma.ts
similarity index 70%
rename from lib/prisma.js
rename to lib/prisma.ts
index ab1e6ebf..08cfb0e0 100644
--- a/lib/prisma.js
+++ b/lib/prisma.ts
@@ -4,6 +4,7 @@ import moment from 'moment-timezone';
import debug from 'debug';
import { PRISMA, MYSQL, POSTGRESQL, getDatabaseType } from 'lib/db';
import { FILTER_IGNORED } from 'lib/constants';
+import { PrismaClientOptions } from '@prisma/client/runtime';
const MYSQL_DATE_FORMATS = {
minute: '%Y-%m-%d %H:%i:00',
@@ -37,7 +38,8 @@ function logQuery(e) {
}
function getClient(options) {
- const prisma = new PrismaClient(options);
+ const prisma: PrismaClient =
+ new PrismaClient(options);
if (process.env.LOG_QUERY) {
prisma.$on('query', logQuery);
@@ -52,7 +54,7 @@ function getClient(options) {
return prisma;
}
-function getDateQuery(field, unit, timezone) {
+function getDateQuery(field, unit, timezone?): string {
const db = getDatabaseType(process.env.DATABASE_URL);
if (db === POSTGRESQL) {
@@ -73,7 +75,7 @@ function getDateQuery(field, unit, timezone) {
}
}
-function getTimestampInterval(field) {
+function getTimestampInterval(field): string {
const db = getDatabaseType(process.env.DATABASE_URL);
if (db === POSTGRESQL) {
@@ -85,7 +87,7 @@ function getTimestampInterval(field) {
}
}
-function getJsonField(column, property, isNumber) {
+function getJsonField(column, property, isNumber): string {
const db = getDatabaseType(process.env.DATABASE_URL);
if (db === POSTGRESQL) {
@@ -103,7 +105,7 @@ function getJsonField(column, property, isNumber) {
}
}
-function getEventDataColumnsQuery(column, columns) {
+function getEventDataColumnsQuery(column, columns): string {
const query = Object.keys(columns).reduce((arr, key) => {
const filter = columns[key];
@@ -121,7 +123,7 @@ function getEventDataColumnsQuery(column, columns) {
return query.join(',\n');
}
-function getEventDataFilterQuery(column, filters) {
+function getEventDataFilterQuery(column, filters): string {
const query = Object.keys(filters).reduce((arr, key) => {
const filter = filters[key];
@@ -143,7 +145,7 @@ function getEventDataFilterQuery(column, filters) {
return query.join('\nand ');
}
-function getFilterQuery(table, column, filters = {}, params = []) {
+function getFilterQuery(filters = {}, params = []): string {
const query = Object.keys(filters).reduce((arr, key) => {
const filter = filters[key];
@@ -153,48 +155,25 @@ function getFilterQuery(table, column, filters = {}, params = []) {
switch (key) {
case 'url':
- if (table === 'pageview' || table === 'event') {
- arr.push(`and ${table}.${key}=$${params.length + 1}`);
- params.push(decodeURIComponent(filter));
- }
- break;
-
case 'os':
case 'browser':
case 'device':
case 'country':
- if (table === 'session') {
- arr.push(`and ${table}.${key}=$${params.length + 1}`);
- params.push(decodeURIComponent(filter));
- }
- break;
-
case 'event_name':
- if (table === 'event') {
- arr.push(`and ${table}.${key}=$${params.length + 1}`);
- params.push(decodeURIComponent(filter));
- }
+ arr.push(`and ${key}=$${params.length + 1}`);
+ params.push(decodeURIComponent(filter));
break;
-
case 'referrer':
- if (table === 'pageview' || table === 'event') {
- arr.push(`and ${table}.referrer like $${params.length + 1}`);
- params.push(`%${decodeURIComponent(filter)}%`);
- }
+ arr.push(`and referrer like $${params.length + 1}`);
+ params.push(`%${decodeURIComponent(filter)}%`);
break;
-
case 'domain':
- if (table === 'pageview') {
- arr.push(`and ${table}.referrer not like $${params.length + 1}`);
- arr.push(`and ${table}.referrer not like '/%'`);
- params.push(`%://${filter}/%`);
- }
+ arr.push(`and referrer not like $${params.length + 1}`);
+ arr.push(`and referrer not like '/%'`);
+ params.push(`%://${filter}/%`);
break;
-
case 'query':
- if (table === 'pageview') {
- arr.push(`and ${table}.url like '%?%'`);
- }
+ arr.push(`and url like '%?%'`);
}
return arr;
@@ -203,7 +182,11 @@ function getFilterQuery(table, column, filters = {}, params = []) {
return query.join('\n');
}
-function parseFilters(table, column, filters = {}, params = [], sessionKey = 'session_id') {
+function parseFilters(
+ filters: { [key: string]: any } = {},
+ params = [],
+ sessionKey = 'session_id',
+) {
const { domain, url, event_url, referrer, os, browser, device, country, event_name, query } =
filters;
@@ -218,15 +201,13 @@ function parseFilters(table, column, filters = {}, params = [], sessionKey = 'se
event: { event_name },
joinSession:
os || browser || device || country
- ? `inner join session on ${table}.${sessionKey} = session.${sessionKey}`
+ ? `inner join session on ${sessionKey} = session.${sessionKey}`
: '',
- pageviewQuery: getFilterQuery('pageview', column, pageviewFilters, params),
- sessionQuery: getFilterQuery('session', column, sessionFilters, params),
- eventQuery: getFilterQuery('event', column, eventFilters, params),
+ filterQuery: getFilterQuery(filters, params),
};
}
-async function rawQuery(query, params = []) {
+async function rawQuery(query, params = []): Promise {
const db = getDatabaseType(process.env.DATABASE_URL);
if (db !== POSTGRESQL && db !== MYSQL) {
@@ -238,12 +219,13 @@ async function rawQuery(query, params = []) {
return prisma.$queryRawUnsafe.apply(prisma, [sql, ...params]);
}
-async function transaction(queries) {
+async function transaction(queries): Promise {
return prisma.$transaction(queries);
}
// Initialization
-const prisma = global[PRISMA] || getClient(PRISMA_OPTIONS);
+const prisma: PrismaClient =
+ global[PRISMA] || getClient(PRISMA_OPTIONS);
export default {
client: prisma,
diff --git a/lib/redis.js b/lib/redis.js
index b2ea2279..02eb9424 100644
--- a/lib/redis.js
+++ b/lib/redis.js
@@ -1,39 +1,39 @@
+import { createClient } from 'redis';
import debug from 'debug';
-import Redis from 'ioredis';
-import { REDIS } from 'lib/db';
const log = debug('umami:redis');
-export const DELETED = 'deleted';
+const REDIS = Symbol();
+const DELETED = 'DELETED';
let redis;
-const enabled = Boolean(process.env.REDIS_URL);
+const url = process.env.REDIS_URL;
+const enabled = Boolean(url);
-function getClient() {
+async function getClient() {
if (!enabled) {
return null;
}
- const redis = new Redis(process.env.REDIS_URL, {
- retryStrategy(times) {
- log(`Redis reconnecting attempt: ${times}`);
- return 5000;
- },
- });
+ const client = createClient({ url });
+ client.on('error', err => log(err));
+ await client.connect();
if (process.env.NODE_ENV !== 'production') {
- global[REDIS] = redis;
+ global[REDIS] = client;
}
log('Redis initialized');
- return redis;
+ return client;
}
async function get(key) {
await connect();
+ const data = await redis.get(key);
+
try {
- return JSON.parse(await redis.get(key));
+ return JSON.parse(data);
} catch {
return null;
}
@@ -53,10 +53,10 @@ async function del(key) {
async function connect() {
if (!redis && enabled) {
- redis = global[REDIS] || getClient();
+ redis = global[REDIS] || (await getClient());
}
return redis;
}
-export default { enabled, client: redis, log, connect, get, set, del };
+export default { enabled, client: redis, log, connect, get, set, del, DELETED };
diff --git a/lib/session.js b/lib/session.js
index ad9f75b8..153b524c 100644
--- a/lib/session.js
+++ b/lib/session.js
@@ -40,7 +40,7 @@ export async function findSession(req) {
website = await getWebsite({ id: websiteId });
}
- if (!website || website.isDeleted) {
+ if (!website || website.deletedAt) {
throw new Error(`Website not found: ${websiteId}`);
}
diff --git a/lib/types.ts b/lib/types.ts
new file mode 100644
index 00000000..007d6fdb
--- /dev/null
+++ b/lib/types.ts
@@ -0,0 +1,90 @@
+import { NextApiRequest } from 'next';
+
+export interface Auth {
+ user?: {
+ id: string;
+ username: string;
+ role: string;
+ isAdmin: boolean;
+ };
+ shareToken?: string;
+}
+
+export interface NextApiRequestQueryBody extends NextApiRequest {
+ auth?: Auth;
+ query: TQuery & { [key: string]: string | string[] };
+ body: TBody;
+ headers: any;
+}
+
+export interface NextApiRequestAuth extends NextApiRequest {
+ auth?: Auth;
+ headers: any;
+}
+
+export interface Website {
+ id: string;
+ userId: string;
+ revId: number;
+ name: string;
+ domain: string;
+ shareId: string;
+ createdAt: Date;
+}
+
+export interface Share {
+ id: string;
+ token: string;
+}
+
+export interface Empty {}
+
+export interface WebsiteActive {
+ x: number;
+}
+
+export interface WebsiteEventDataMetric {
+ [key: string]: number;
+}
+
+export interface WebsiteMetric {
+ x: string;
+ y: number;
+}
+
+export interface WebsiteEventMetric {
+ x: string;
+ t: string;
+ y: number;
+}
+
+export interface WebsitePageviews {
+ pageviews: {
+ t: string;
+ y: number;
+ };
+ sessions: {
+ t: string;
+ y: number;
+ };
+}
+
+export interface WebsiteStats {
+ pageviews: { value: number; change: number };
+ uniques: { value: number; change: number };
+ bounces: { value: number; change: number };
+ totalTime: { value: number; change: number };
+}
+
+export interface RealtimeInit {
+ websites: Website[];
+ token: string;
+ data: RealtimeUpdate;
+}
+
+export interface RealtimeUpdate {
+ pageviews: any[];
+ sessions: any[];
+ events: any[];
+ timestamp: number;
+}
diff --git a/next-env.d.ts b/next-env.d.ts
index 62b8a52d..4f11a03d 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,5 +1,5 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/next.config.js b/next.config.js
index b95c39d4..eac47415 100644
--- a/next.config.js
+++ b/next.config.js
@@ -43,10 +43,13 @@ module.exports = {
eslint: {
ignoreDuringBuilds: true,
},
+ typescript: {
+ ignoreBuildErrors: true,
+ },
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
- issuer: /\.js$/,
+ issuer: /\.{js|jsx|ts|tsx}$/,
use: ['@svgr/webpack'],
});
diff --git a/package.json b/package.json
index f3b4304f..516c1783 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"postbuild": "node scripts/postbuild.js"
},
"lint-staged": {
- "**/*.js": [
+ "**/*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint"
],
@@ -57,6 +57,7 @@
"dependencies": {
"@fontsource/inter": "4.5.7",
"@prisma/client": "4.5.0",
+ "@tanstack/react-query": "^4.16.1",
"chalk": "^4.1.1",
"chart.js": "^2.9.4",
"classnames": "^2.3.1",
@@ -74,7 +75,6 @@
"formik": "^2.2.9",
"fs-extra": "^10.0.1",
"immer": "^9.0.12",
- "ioredis": "^5.2.3",
"ipaddr.js": "^2.0.1",
"is-ci": "^3.0.1",
"is-docker": "^3.0.0",
@@ -88,15 +88,17 @@
"node-fetch": "^3.2.8",
"npm-run-all": "^4.1.5",
"prop-types": "^15.7.2",
- "react": "^17.0.0",
+ "react": "^18.2.0",
+ "react-basics": "^0.37.0",
"react-beautiful-dnd": "^13.1.0",
- "react-dom": "^17.0.0",
+ "react-dom": "^18.2.0",
"react-intl": "^5.24.7",
"react-simple-maps": "^2.3.0",
"react-spring": "^9.4.4",
"react-tooltip": "^4.2.21",
"react-use-measure": "^2.0.4",
"react-window": "^1.8.6",
+ "redis": "^4.5.0",
"request-ip": "^3.3.0",
"semver": "^7.3.6",
"thenby": "^1.3.4",
diff --git a/pages/_app.js b/pages/_app.js
index c3617a08..10fa09ec 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -1,18 +1,17 @@
-import Head from 'next/head';
-import { useRouter } from 'next/router';
import { IntlProvider } from 'react-intl';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import useLocale from 'hooks/useLocale';
import useConfig from 'hooks/useConfig';
+import 'react-basics/dist/styles.css';
import 'styles/variables.css';
-import 'styles/bootstrap-grid.css';
import 'styles/index.css';
import '@fontsource/inter/400.css';
import '@fontsource/inter/600.css';
+const client = new QueryClient();
+
export default function App({ Component, pageProps }) {
const { locale, messages } = useLocale();
- const { basePath } = useRouter();
- const { dir } = useLocale();
useConfig();
const Wrapper = ({ children }) => {children};
@@ -22,22 +21,10 @@ export default function App({ Component, pageProps }) {
}
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
);
}
diff --git a/pages/api/auth/login.js b/pages/api/auth/login.ts
similarity index 59%
rename from pages/api/auth/login.js
rename to pages/api/auth/login.ts
index a54e8013..e5e0dab7 100644
--- a/pages/api/auth/login.js
+++ b/pages/api/auth/login.ts
@@ -7,11 +7,26 @@ import {
methodNotAllowed,
getRandomChars,
} from 'next-basics';
-import { getUser } from 'queries';
+import { getUser, User } from 'queries';
import { secret } from 'lib/crypto';
import redis from 'lib/redis';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { NextApiResponse } from 'next';
-export default async (req, res) => {
+export interface LoginRequestBody {
+ username: string;
+ password: string;
+}
+
+export interface LoginResponse {
+ token: string;
+ user: User;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
if (req.method === 'POST') {
const { username, password } = req.body;
@@ -19,7 +34,7 @@ export default async (req, res) => {
return badRequest(res);
}
- const user = await getUser({ username });
+ const user = await getUser({ username }, { includePassword: true });
if (user && checkPassword(password, user.password)) {
if (redis.enabled) {
@@ -27,7 +42,7 @@ export default async (req, res) => {
await redis.set(key, user);
- const token = createSecureToken(key, secret());
+ const token = createSecureToken({ key }, secret());
return ok(res, { token, user });
}
diff --git a/pages/api/auth/logout.js b/pages/api/auth/logout.ts
similarity index 74%
rename from pages/api/auth/logout.js
rename to pages/api/auth/logout.ts
index 37f117be..c05a05de 100644
--- a/pages/api/auth/logout.js
+++ b/pages/api/auth/logout.ts
@@ -2,8 +2,9 @@ import { methodNotAllowed, ok } from 'next-basics';
import { useAuth } from 'lib/middleware';
import redis from 'lib/redis';
import { getAuthToken } from 'lib/auth';
+import { NextApiRequest, NextApiResponse } from 'next';
-export default async (req, res) => {
+export default async (req: NextApiRequest, res: NextApiResponse) => {
await useAuth(req, res);
if (req.method === 'POST') {
diff --git a/pages/api/auth/verify.js b/pages/api/auth/verify.js
deleted file mode 100644
index 670480b1..00000000
--- a/pages/api/auth/verify.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { useAuth } from 'lib/middleware';
-import { ok } from 'next-basics';
-
-export default async (req, res) => {
- await useAuth(req, res);
-
- return ok(res, req.auth);
-};
diff --git a/pages/api/auth/verify.ts b/pages/api/auth/verify.ts
new file mode 100644
index 00000000..9eb9ea48
--- /dev/null
+++ b/pages/api/auth/verify.ts
@@ -0,0 +1,10 @@
+import { NextApiRequestAuth } from 'lib/types';
+import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { ok } from 'next-basics';
+
+export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
+ await useAuth(req, res);
+
+ return ok(res, req.auth);
+};
diff --git a/pages/api/collect.js b/pages/api/collect.ts
similarity index 73%
rename from pages/api/collect.js
rename to pages/api/collect.ts
index 87e516cc..254689fe 100644
--- a/pages/api/collect.js
+++ b/pages/api/collect.ts
@@ -6,14 +6,41 @@ import { savePageView, saveEvent } from 'queries';
import { useCors, useSession } from 'lib/middleware';
import { getJsonBody, getIpAddress } from 'lib/request';
import { secret } from 'lib/crypto';
+import { NextApiRequest, NextApiResponse } from 'next';
-export default async (req, res) => {
+export interface NextApiRequestCollect extends NextApiRequest {
+ session: {
+ id: string;
+ websiteId: string;
+ hostname: string;
+ browser: string;
+ os: string;
+ device: string;
+ screen: string;
+ language: string;
+ country: string;
+ };
+}
+
+export default async (req: NextApiRequestCollect, res: NextApiResponse) => {
await useCors(req, res);
if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) {
return unauthorized(res);
}
+ const { type, payload } = getJsonBody(req);
+
+ const { referrer, event_name: eventName, event_data: eventData } = payload;
+ let { url } = payload;
+
+ // Validate eventData is JSON
+ const valid = eventData && typeof eventData === 'object' && !Array.isArray(eventData);
+
+ if (!valid) {
+ return badRequest(res, 'Event Data must be in the form of a JSON Object.');
+ }
+
const ignoreIps = process.env.IGNORE_IP;
const ignoreHostnames = process.env.IGNORE_HOSTNAME;
@@ -60,10 +87,6 @@ export default async (req, res) => {
const session = req.session;
- const { type, payload } = getJsonBody(req);
-
- let { url, referrer, event_name: eventName, event_data: eventData } = payload;
-
if (process.env.REMOVE_TRAILING_SLASH) {
url = url.replace(/\/$/, '');
}
@@ -74,6 +97,7 @@ export default async (req, res) => {
await saveEvent({
...session,
url,
+ referrer,
eventName,
eventData,
});
diff --git a/pages/api/config.js b/pages/api/config.ts
similarity index 57%
rename from pages/api/config.js
rename to pages/api/config.ts
index faf94c0b..e5ae318a 100644
--- a/pages/api/config.js
+++ b/pages/api/config.ts
@@ -1,6 +1,15 @@
+import { NextApiRequest, NextApiResponse } from 'next';
import { ok, methodNotAllowed } from 'next-basics';
-export default async (req, res) => {
+export interface ConfigResponse {
+ basePath: string;
+ trackerScriptName: string;
+ updatesDisabled: boolean;
+ telemetryDisabled: boolean;
+ adminDisabled: boolean;
+}
+
+export default async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'GET') {
return ok(res, {
basePath: process.env.BASE_PATH || '',
diff --git a/pages/api/heartbeat.js b/pages/api/heartbeat.js
deleted file mode 100644
index a4ee5923..00000000
--- a/pages/api/heartbeat.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { ok } from 'next-basics';
-
-export default async (req, res) => {
- return ok(res);
-};
diff --git a/pages/api/heartbeat.ts b/pages/api/heartbeat.ts
new file mode 100644
index 00000000..1b515d39
--- /dev/null
+++ b/pages/api/heartbeat.ts
@@ -0,0 +1,6 @@
+import { NextApiRequest, NextApiResponse } from 'next';
+import { ok } from 'next-basics';
+
+export default async (req: NextApiRequest, res: NextApiResponse) => {
+ return ok(res);
+};
diff --git a/pages/api/realtime/init.js b/pages/api/realtime/init.ts
similarity index 62%
rename from pages/api/realtime/init.js
rename to pages/api/realtime/init.ts
index 16e7cad3..4e04c37b 100644
--- a/pages/api/realtime/init.js
+++ b/pages/api/realtime/init.ts
@@ -1,10 +1,13 @@
import { subMinutes } from 'date-fns';
-import { ok, methodNotAllowed, createToken } from 'next-basics';
-import { useAuth } from 'lib/middleware';
-import { getUserWebsites, getRealtimeData } from 'queries';
+import { RealtimeInit } from 'lib/types';
+import { NextApiRequestAuth } from 'lib/types';
import { secret } from 'lib/crypto';
+import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { createToken, methodNotAllowed, ok } from 'next-basics';
+import { getRealtimeData, getUserWebsites } from 'queries';
-export default async (req, res) => {
+export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
await useAuth(req, res);
if (req.method === 'GET') {
diff --git a/pages/api/realtime/update.js b/pages/api/realtime/update.ts
similarity index 66%
rename from pages/api/realtime/update.js
rename to pages/api/realtime/update.ts
index 9b91663d..9b99a282 100644
--- a/pages/api/realtime/update.js
+++ b/pages/api/realtime/update.ts
@@ -3,8 +3,18 @@ import { useAuth } from 'lib/middleware';
import { getRealtimeData } from 'queries';
import { SHARE_TOKEN_HEADER } from 'lib/constants';
import { secret } from 'lib/crypto';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { NextApiResponse } from 'next';
+import { RealtimeUpdate } from 'lib/types';
-export default async (req, res) => {
+export interface InitUpdateRequestQuery {
+ start_at: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useAuth(req, res);
if (req.method === 'GET') {
diff --git a/pages/api/share/[id].js b/pages/api/share/[id].ts
similarity index 52%
rename from pages/api/share/[id].js
rename to pages/api/share/[id].ts
index 6fb19739..b8a37e25 100644
--- a/pages/api/share/[id].js
+++ b/pages/api/share/[id].ts
@@ -1,8 +1,22 @@
-import { getWebsite } from 'queries';
-import { ok, notFound, methodNotAllowed, createToken } from 'next-basics';
+import { NextApiRequestQueryBody } from 'lib/types';
import { secret } from 'lib/crypto';
+import { NextApiResponse } from 'next';
+import { createToken, methodNotAllowed, notFound, ok } from 'next-basics';
+import { getWebsite } from 'queries';
-export default async (req, res) => {
+export interface ShareRequestQuery {
+ id: string;
+}
+
+export interface ShareResponse {
+ id: string;
+ token: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
const { id: shareId } = req.query;
if (req.method === 'GET') {
diff --git a/pages/api/teams/[id]/index.ts b/pages/api/teams/[id]/index.ts
new file mode 100644
index 00000000..a3ccd0b6
--- /dev/null
+++ b/pages/api/teams/[id]/index.ts
@@ -0,0 +1,61 @@
+import { Team } from '@prisma/client';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canDeleteTeam, canUpdateTeam, canViewTeam } from 'lib/auth';
+import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { deleteTeam, getTeam, updateTeam } from 'queries';
+
+export interface TeamRequestQuery {
+ id: string;
+}
+
+export interface TeamRequestBody {
+ name: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: teamId } = req.query;
+
+ if (req.method === 'GET') {
+ if (!(await canViewTeam(userId, teamId))) {
+ return unauthorized(res);
+ }
+
+ const user = await getTeam({ id: teamId });
+
+ return ok(res, user);
+ }
+
+ if (req.method === 'POST') {
+ const { name } = req.body;
+
+ if (!(await canUpdateTeam(userId, teamId))) {
+ return unauthorized(res, 'You must be the owner of this team.');
+ }
+
+ const updated = await updateTeam({ name }, { id: teamId });
+
+ return ok(res, updated);
+ }
+
+ if (req.method === 'DELETE') {
+ if (!(await canDeleteTeam(userId, teamId))) {
+ return unauthorized(res, 'You must be the owner of this team.');
+ }
+
+ await deleteTeam(teamId);
+
+ return ok(res);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/teams/[id]/users.ts b/pages/api/teams/[id]/users.ts
new file mode 100644
index 00000000..f0e34165
--- /dev/null
+++ b/pages/api/teams/[id]/users.ts
@@ -0,0 +1,70 @@
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canUpdateTeam, canViewTeam } from 'lib/auth';
+import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { createTeamUser, deleteTeamUser, getUser, getTeamUsers } from 'queries';
+
+export interface TeamUserRequestQuery {
+ id: string;
+}
+
+export interface TeamUserRequestBody {
+ email: string;
+ role_id: string;
+ team_user_id?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: teamId } = req.query;
+
+ if (req.method === 'GET') {
+ if (!(await canViewTeam(userId, teamId))) {
+ return unauthorized(res);
+ }
+
+ const users = await getTeamUsers(teamId);
+
+ return ok(res, users);
+ }
+
+ if (req.method === 'POST') {
+ if (!(await canUpdateTeam(userId, teamId))) {
+ return unauthorized(res, 'You must be the owner of this team.');
+ }
+
+ const { email, role_id: roleId } = req.body;
+
+ // Check for User
+ const user = await getUser({ username: email });
+
+ if (!user) {
+ return badRequest(res, 'The User does not exists.');
+ }
+
+ const updated = await createTeamUser(user.id, teamId, roleId);
+
+ return ok(res, updated);
+ }
+
+ if (req.method === 'DELETE') {
+ if (await canUpdateTeam(userId, teamId)) {
+ return unauthorized(res, 'You must be the owner of this team.');
+ }
+ const { team_user_id } = req.body;
+
+ await deleteTeamUser(team_user_id);
+
+ return ok(res);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/teams/[id]/websites.ts b/pages/api/teams/[id]/websites.ts
new file mode 100644
index 00000000..d1f22da8
--- /dev/null
+++ b/pages/api/teams/[id]/websites.ts
@@ -0,0 +1,39 @@
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canViewTeam } from 'lib/auth';
+import { useAuth } from 'lib/middleware';
+import { getTeamWebsites } from 'queries/admin/team';
+
+export interface TeamWebsiteRequestQuery {
+ id: string;
+}
+
+export interface TeamWebsiteRequestBody {
+ website_id: string;
+ team_website_id?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: teamId } = req.query;
+
+ if (req.method === 'GET') {
+ if (await canViewTeam(userId, teamId)) {
+ return unauthorized(res);
+ }
+
+ const websites = await getTeamWebsites(teamId);
+
+ return ok(res, websites);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/teams/index.ts b/pages/api/teams/index.ts
new file mode 100644
index 00000000..46cf65a9
--- /dev/null
+++ b/pages/api/teams/index.ts
@@ -0,0 +1,47 @@
+import { Team } from '@prisma/client';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canCreateTeam } from 'lib/auth';
+import { uuid } from 'lib/crypto';
+import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { createTeam, getUserTeams } from 'queries';
+
+export interface TeamsRequestBody {
+ name: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+
+ if (req.method === 'GET') {
+ const teams = await getUserTeams(userId);
+
+ return ok(res, teams);
+ }
+
+ if (req.method === 'POST') {
+ if (!(await canCreateTeam(userId))) {
+ return unauthorized(res);
+ }
+
+ const { name } = req.body;
+
+ const created = await createTeam({
+ id: uuid(),
+ name,
+ userId,
+ });
+
+ return ok(res, created);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/users/[id]/index.js b/pages/api/users/[id]/index.ts
similarity index 68%
rename from pages/api/users/[id]/index.js
rename to pages/api/users/[id]/index.ts
index a373bbd1..cd0332d5 100644
--- a/pages/api/users/[id]/index.js
+++ b/pages/api/users/[id]/index.ts
@@ -1,8 +1,23 @@
-import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { getUser, deleteUser, updateUser } from 'queries';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canUpdateUser, canViewUser } from 'lib/auth';
import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { deleteUser, getUser, updateUser, User } from 'queries';
-export default async (req, res) => {
+export interface UserRequestQuery {
+ id: string;
+}
+
+export interface UserRequestBody {
+ username: string;
+ password: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useAuth(req, res);
const {
@@ -11,7 +26,7 @@ export default async (req, res) => {
const { id } = req.query;
if (req.method === 'GET') {
- if (id !== userId && !isAdmin) {
+ if (await canViewUser(userId, id)) {
return unauthorized(res);
}
@@ -21,22 +36,22 @@ export default async (req, res) => {
}
if (req.method === 'POST') {
- const { username, password } = req.body;
-
- if (id !== userId && !isAdmin) {
+ if (await canUpdateUser(userId, id)) {
return unauthorized(res);
}
+ const { username, password } = req.body;
+
const user = await getUser({ id });
- const data = {};
+ const data: any = {};
if (password) {
data.password = hashPassword(password);
}
// Only admin can change these fields
- if (isAdmin) {
+ if (username && isAdmin) {
data.username = username;
}
@@ -55,12 +70,12 @@ export default async (req, res) => {
}
if (req.method === 'DELETE') {
- if (id === userId) {
- return badRequest(res, 'You cannot delete your own user.');
+ if (isAdmin) {
+ return unauthorized(res);
}
- if (!isAdmin) {
- return unauthorized(res);
+ if (id === userId) {
+ return badRequest(res, 'You cannot delete your own user.');
}
await deleteUser(id);
diff --git a/pages/api/users/[id]/password.js b/pages/api/users/[id]/password.ts
similarity index 51%
rename from pages/api/users/[id]/password.js
rename to pages/api/users/[id]/password.ts
index 6cad82ed..7a37d044 100644
--- a/pages/api/users/[id]/password.js
+++ b/pages/api/users/[id]/password.ts
@@ -1,27 +1,43 @@
-import { getUser, updateUser } from 'queries';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canUpdateUser } from 'lib/auth';
import { useAuth } from 'lib/middleware';
+import { NextApiResponse } from 'next';
import {
badRequest,
+ checkPassword,
+ hashPassword,
methodNotAllowed,
ok,
unauthorized,
- checkPassword,
- hashPassword,
} from 'next-basics';
-import { allowQuery } from 'lib/auth';
-import { TYPE_USER } from 'lib/constants';
+import { getUser, updateUser, User } from 'queries';
-export default async (req, res) => {
+export interface UserPasswordRequestQuery {
+ id: string;
+}
+
+export interface UserPasswordRequestBody {
+ current_password: string;
+ new_password: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useAuth(req, res);
const { current_password, new_password } = req.body;
const { id } = req.query;
-
- if (!(await allowQuery(req, TYPE_USER))) {
- return unauthorized(res);
- }
+ const {
+ user: { id: userId },
+ } = req.auth;
if (req.method === 'POST') {
+ if (canUpdateUser(userId, id)) {
+ return unauthorized(res);
+ }
+
const user = await getUser({ id });
if (!checkPassword(current_password, user.password)) {
diff --git a/pages/api/users/[id]/websites.ts b/pages/api/users/[id]/websites.ts
new file mode 100644
index 00000000..bc79f91a
--- /dev/null
+++ b/pages/api/users/[id]/websites.ts
@@ -0,0 +1,57 @@
+import { Prisma } from '@prisma/client';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { uuid } from 'lib/crypto';
+import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok } from 'next-basics';
+import { createWebsite, getUserWebsites } from 'queries';
+
+export interface WebsitesRequestQuery {}
+
+export interface WebsitesRequestBody {
+ name: string;
+ domain: string;
+ shareId: string;
+ teamId?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+
+ if (req.method === 'GET') {
+ const websites = await getUserWebsites(userId);
+
+ return ok(res, websites);
+ }
+
+ if (req.method === 'POST') {
+ const { name, domain, shareId, teamId } = req.body;
+
+ const data: Prisma.WebsiteUncheckedCreateInput = {
+ id: uuid(),
+ name,
+ domain,
+ shareId,
+ };
+
+ if (teamId) {
+ data.teamId = teamId;
+ } else {
+ data.userId = userId;
+ }
+
+ const website = await createWebsite(data);
+
+ return ok(res, website);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/users/index.js b/pages/api/users/index.js
deleted file mode 100644
index f4a5010a..00000000
--- a/pages/api/users/index.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { ok, unauthorized, methodNotAllowed, badRequest, hashPassword } from 'next-basics';
-import { useAuth } from 'lib/middleware';
-import { uuid } from 'lib/crypto';
-import { createUser, getUser, getUsers } from 'queries';
-
-export default async (req, res) => {
- await useAuth(req, res);
-
- const {
- user: { isAdmin },
- } = req.auth;
-
- if (!isAdmin) {
- return unauthorized(res);
- }
-
- if (req.method === 'GET') {
- const users = await getUsers();
-
- return ok(res, users);
- }
-
- if (req.method === 'POST') {
- const { username, password, id } = req.body;
-
- const user = await getUser({ username });
-
- if (user) {
- return badRequest(res, 'User already exists');
- }
-
- const created = await createUser({
- id: id || uuid(),
- username,
- password: hashPassword(password),
- });
-
- return ok(res, created);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/users/index.ts b/pages/api/users/index.ts
new file mode 100644
index 00000000..09f901c0
--- /dev/null
+++ b/pages/api/users/index.ts
@@ -0,0 +1,59 @@
+import { NextApiRequestQueryBody } from 'lib/types';
+import { uuid } from 'lib/crypto';
+import { useAuth } from 'lib/middleware';
+import { ROLES } from 'lib/constants';
+import { NextApiResponse } from 'next';
+import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { createUser, getUser, getUsers, User } from 'queries';
+
+export interface UsersRequestBody {
+ username: string;
+ password: string;
+ id: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useAuth(req, res);
+
+ const {
+ user: { isAdmin },
+ } = req.auth;
+
+ if (req.method === 'GET') {
+ if (isAdmin) {
+ return unauthorized(res);
+ }
+
+ const users = await getUsers();
+
+ return ok(res, users);
+ }
+
+ if (req.method === 'POST') {
+ if (isAdmin) {
+ return unauthorized(res);
+ }
+
+ const { username, password, id } = req.body;
+
+ const existingUser = await getUser({ username });
+
+ if (existingUser) {
+ return badRequest(res, 'User already exists');
+ }
+
+ const created = await createUser({
+ id: id || uuid(),
+ username,
+ password: hashPassword(password),
+ role: ROLES.user,
+ });
+
+ return ok(res, created);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/websites/[id]/active.js b/pages/api/websites/[id]/active.js
deleted file mode 100644
index 59af938e..00000000
--- a/pages/api/websites/[id]/active.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
-import { useAuth, useCors } from 'lib/middleware';
-import { getActiveVisitors } from 'queries';
-import { TYPE_WEBSITE } from 'lib/constants';
-
-export default async (req, res) => {
- await useCors(req, res);
- await useAuth(req, res);
-
- if (req.method === 'GET') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
- return unauthorized(res);
- }
-
- const { id: websiteId } = req.query;
-
- const result = await getActiveVisitors(websiteId);
-
- return ok(res, result);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/websites/[id]/active.ts b/pages/api/websites/[id]/active.ts
new file mode 100644
index 00000000..1d007f7f
--- /dev/null
+++ b/pages/api/websites/[id]/active.ts
@@ -0,0 +1,36 @@
+import { WebsiteActive } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
+import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { getActiveVisitors } from 'queries';
+
+export interface WebsiteActiveRequestQuery {
+ id: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: websiteId } = req.query;
+
+ if (req.method === 'GET') {
+ if (await canViewWebsite(userId, websiteId)) {
+ return unauthorized(res);
+ }
+
+ const result = await getActiveVisitors(websiteId);
+
+ return ok(res, result);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/websites/[id]/eventdata.js b/pages/api/websites/[id]/eventdata.js
deleted file mode 100644
index 0e6ad2e9..00000000
--- a/pages/api/websites/[id]/eventdata.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import moment from 'moment-timezone';
-import { getEventData } from 'queries';
-import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
-import { useAuth, useCors } from 'lib/middleware';
-import { TYPE_WEBSITE } from 'lib/constants';
-
-export default async (req, res) => {
- await useCors(req, res);
- await useAuth(req, res);
-
- if (req.method === 'POST') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
- return unauthorized(res);
- }
-
- const { id: websiteId } = req.query;
-
- const { start_at, end_at, timezone, event_name: eventName, columns, filters } = req.body;
-
- if (!moment.tz.zone(timezone)) {
- return badRequest(res);
- }
-
- const startDate = new Date(+start_at);
- const endDate = new Date(+end_at);
-
- const events = await getEventData(websiteId, {
- startDate,
- endDate,
- timezone,
- eventName,
- columns,
- filters,
- });
-
- return ok(res, events);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/websites/[id]/eventdata.ts b/pages/api/websites/[id]/eventdata.ts
new file mode 100644
index 00000000..9293cbad
--- /dev/null
+++ b/pages/api/websites/[id]/eventdata.ts
@@ -0,0 +1,54 @@
+import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
+import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { getEventData } from 'queries';
+
+export interface WebsiteEventDataRequestQuery {
+ id: string;
+}
+
+export interface WebsiteEventDataRequestBody {
+ start_at: string;
+ end_at: string;
+ event_name: string;
+ columns: { [key: string]: 'count' | 'max' | 'min' | 'avg' | 'sum' };
+ filters?: { [key: string]: any };
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: websiteId } = req.query;
+
+ if (req.method === 'POST') {
+ if (canViewWebsite(userId, websiteId)) {
+ return unauthorized(res);
+ }
+
+ const { start_at, end_at, event_name: eventName, columns, filters } = req.body;
+
+ const startDate = new Date(+start_at);
+ const endDate = new Date(+end_at);
+
+ const events = await getEventData(websiteId, {
+ startDate,
+ endDate,
+ eventName,
+ columns,
+ filters,
+ });
+
+ return ok(res, events);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/websites/[id]/events.js b/pages/api/websites/[id]/events.js
deleted file mode 100644
index da88794e..00000000
--- a/pages/api/websites/[id]/events.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import moment from 'moment-timezone';
-import { getEventMetrics } from 'queries';
-import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
-import { useAuth, useCors } from 'lib/middleware';
-import { TYPE_WEBSITE } from 'lib/constants';
-
-const unitTypes = ['year', 'month', 'hour', 'day'];
-
-export default async (req, res) => {
- await useCors(req, res);
- await useAuth(req, res);
-
- if (req.method === 'GET') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
- return unauthorized(res);
- }
-
- const { id: websiteId, start_at, end_at, unit, tz, url, event_name } = req.query;
-
- if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
- return badRequest(res);
- }
- const startDate = new Date(+start_at);
- const endDate = new Date(+end_at);
-
- const events = await getEventMetrics(websiteId, startDate, endDate, tz, unit, {
- url,
- eventName: event_name,
- });
-
- return ok(res, events);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/websites/[id]/events.ts b/pages/api/websites/[id]/events.ts
new file mode 100644
index 00000000..726669a3
--- /dev/null
+++ b/pages/api/websites/[id]/events.ts
@@ -0,0 +1,59 @@
+import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
+import { useAuth, useCors } from 'lib/middleware';
+import moment from 'moment-timezone';
+import { NextApiResponse } from 'next';
+import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { getEventMetrics } from 'queries';
+
+const unitTypes = ['year', 'month', 'hour', 'day'];
+
+export interface WebsiteEventsRequestQuery {
+ id: string;
+ start_at: string;
+ end_at: string;
+ unit: string;
+ tz: string;
+ url: string;
+ event_name: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const { id: websiteId, start_at, end_at, unit, tz, url, event_name } = req.query;
+
+ if (req.method === 'GET') {
+ if (canViewWebsite(userId, websiteId)) {
+ return unauthorized(res);
+ }
+
+ if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
+ return badRequest(res);
+ }
+ const startDate = new Date(+start_at);
+ const endDate = new Date(+end_at);
+
+ const events = await getEventMetrics(websiteId, {
+ startDate,
+ endDate,
+ timezone: tz,
+ unit,
+ filters: {
+ url,
+ eventName: event_name,
+ },
+ });
+
+ return ok(res, events);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/websites/[id]/index.js b/pages/api/websites/[id]/index.ts
similarity index 50%
rename from pages/api/websites/[id]/index.js
rename to pages/api/websites/[id]/index.ts
index 09056865..2f11ec70 100644
--- a/pages/api/websites/[id]/index.js
+++ b/pages/api/websites/[id]/index.ts
@@ -1,35 +1,52 @@
-import { allowQuery } from 'lib/auth';
+import { Website, NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite, canUpdateWebsite, canDeleteWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
import { methodNotAllowed, ok, serverError, unauthorized } from 'next-basics';
import { deleteWebsite, getWebsite, updateWebsite } from 'queries';
-import { TYPE_WEBSITE } from 'lib/constants';
-export default async (req, res) => {
+export interface WebsiteRequestQuery {
+ id: string;
+}
+
+export interface WebsiteRequestBody {
+ name: string;
+ domain: string;
+ shareId: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useCors(req, res);
await useAuth(req, res);
+ const {
+ user: { id: userId },
+ } = req.auth;
const { id: websiteId } = req.query;
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
- return unauthorized(res);
- }
-
if (req.method === 'GET') {
+ if (!(await canViewWebsite(userId, websiteId))) {
+ return unauthorized(res);
+ }
+
const website = await getWebsite({ id: websiteId });
return ok(res, website);
}
if (req.method === 'POST') {
+ if (!(await canUpdateWebsite(userId, websiteId))) {
+ return unauthorized(res);
+ }
+
const { name, domain, shareId } = req.body;
try {
- await updateWebsite(websiteId, {
- name,
- domain,
- shareId,
- });
- } catch (e) {
+ await updateWebsite(websiteId, { name, domain, shareId });
+ } catch (e: any) {
if (e.message.includes('Unique constraint') && e.message.includes('share_id')) {
return serverError(res, 'That share ID is already taken.');
}
@@ -39,7 +56,7 @@ export default async (req, res) => {
}
if (req.method === 'DELETE') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
+ if (!(await canDeleteWebsite(userId, websiteId))) {
return unauthorized(res);
}
diff --git a/pages/api/websites/[id]/metrics.js b/pages/api/websites/[id]/metrics.ts
similarity index 77%
rename from pages/api/websites/[id]/metrics.js
rename to pages/api/websites/[id]/metrics.ts
index 97216273..260814da 100644
--- a/pages/api/websites/[id]/metrics.js
+++ b/pages/api/websites/[id]/metrics.ts
@@ -1,6 +1,8 @@
-import { allowQuery } from 'lib/auth';
-import { FILTER_IGNORED, TYPE_WEBSITE } from 'lib/constants';
+import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
+import { FILTER_IGNORED } from 'lib/constants';
import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getPageviewMetrics, getSessionMetrics, getWebsite } from 'queries';
@@ -33,28 +35,47 @@ function getColumn(type) {
return type;
}
-export default async (req, res) => {
+export interface WebsiteMetricsRequestQuery {
+ id: string;
+ type: string;
+ start_at: number;
+ end_at: number;
+ url: string;
+ referrer: string;
+ os: string;
+ browser: string;
+ device: string;
+ country: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useCors(req, res);
await useAuth(req, res);
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const {
+ id: websiteId,
+ type,
+ start_at,
+ end_at,
+ url,
+ referrer,
+ os,
+ browser,
+ device,
+ country,
+ } = req.query;
+
if (req.method === 'GET') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
+ if (!(await canViewWebsite(userId, websiteId))) {
return unauthorized(res);
}
- const {
- id: websiteId,
- type,
- start_at,
- end_at,
- url,
- referrer,
- os,
- browser,
- device,
- country,
- } = req.query;
-
const startDate = new Date(+start_at);
const endDate = new Date(+end_at);
diff --git a/pages/api/websites/[id]/pageviews.js b/pages/api/websites/[id]/pageviews.ts
similarity index 54%
rename from pages/api/websites/[id]/pageviews.js
rename to pages/api/websites/[id]/pageviews.ts
index 5b628e3a..ea6c5df4 100644
--- a/pages/api/websites/[id]/pageviews.js
+++ b/pages/api/websites/[id]/pageviews.ts
@@ -1,35 +1,57 @@
-import moment from 'moment-timezone';
-import { getPageviewStats } from 'queries';
-import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
+import { NextApiRequestQueryBody, WebsitePageviews } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
-import { TYPE_WEBSITE } from 'lib/constants';
+import moment from 'moment-timezone';
+import { NextApiResponse } from 'next';
+import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { getPageviewStats } from 'queries';
const unitTypes = ['year', 'month', 'hour', 'day'];
-export default async (req, res) => {
+export interface WebsitePageviewRequestQuery {
+ id: string;
+ websiteId: string;
+ start_at: number;
+ end_at: number;
+ unit: string;
+ tz: string;
+ url?: string;
+ referrer?: string;
+ os?: string;
+ browser?: string;
+ device?: string;
+ country?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useCors(req, res);
await useAuth(req, res);
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const {
+ id: websiteId,
+ start_at,
+ end_at,
+ unit,
+ tz,
+ url,
+ referrer,
+ os,
+ browser,
+ device,
+ country,
+ } = req.query;
+
if (req.method === 'GET') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
+ if (!(await canViewWebsite(userId, websiteId))) {
return unauthorized(res);
}
- const {
- id: websiteId,
- start_at,
- end_at,
- unit,
- tz,
- url,
- referrer,
- os,
- browser,
- device,
- country,
- } = req.query;
-
const startDate = new Date(+start_at);
const endDate = new Date(+end_at);
@@ -39,8 +61,8 @@ export default async (req, res) => {
const [pageviews, sessions] = await Promise.all([
getPageviewStats(websiteId, {
- start_at: startDate,
- end_at: endDate,
+ startDate,
+ endDate,
timezone: tz,
unit,
count: '*',
@@ -54,8 +76,8 @@ export default async (req, res) => {
},
}),
getPageviewStats(websiteId, {
- start_at: startDate,
- end_at: endDate,
+ startDate,
+ endDate,
timezone: tz,
unit,
count: 'distinct pageview.',
diff --git a/pages/api/websites/[id]/reset.js b/pages/api/websites/[id]/reset.ts
similarity index 50%
rename from pages/api/websites/[id]/reset.js
rename to pages/api/websites/[id]/reset.ts
index 0dde02df..292672ae 100644
--- a/pages/api/websites/[id]/reset.js
+++ b/pages/api/websites/[id]/reset.ts
@@ -1,17 +1,28 @@
-import { resetWebsite } from 'queries';
-import { methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
-import { TYPE_WEBSITE } from 'lib/constants';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { resetWebsite } from 'queries';
-export default async (req, res) => {
+export interface WebsiteResetRequestQuery {
+ id: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useCors(req, res);
await useAuth(req, res);
+ const {
+ user: { id: userId },
+ } = req.auth;
const { id: websiteId } = req.query;
if (req.method === 'POST') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
+ if (!(await canViewWebsite(userId, websiteId))) {
return unauthorized(res);
}
diff --git a/pages/api/websites/[id]/stats.js b/pages/api/websites/[id]/stats.ts
similarity index 58%
rename from pages/api/websites/[id]/stats.js
rename to pages/api/websites/[id]/stats.ts
index 2c5b0156..85c4f254 100644
--- a/pages/api/websites/[id]/stats.js
+++ b/pages/api/websites/[id]/stats.ts
@@ -1,30 +1,51 @@
-import { getWebsiteStats } from 'queries';
-import { methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { allowQuery } from 'lib/auth';
+import { WebsiteStats } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
-import { TYPE_WEBSITE } from 'lib/constants';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { getWebsiteStats } from 'queries';
-export default async (req, res) => {
+export interface WebsiteStatsRequestQuery {
+ id: string;
+ type: string;
+ start_at: number;
+ end_at: number;
+ url: string;
+ referrer: string;
+ os: string;
+ browser: string;
+ device: string;
+ country: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
await useCors(req, res);
await useAuth(req, res);
+ const {
+ user: { id: userId },
+ } = req.auth;
+ const {
+ id: websiteId,
+ start_at,
+ end_at,
+ url,
+ referrer,
+ os,
+ browser,
+ device,
+ country,
+ } = req.query;
+
if (req.method === 'GET') {
- if (!(await allowQuery(req, TYPE_WEBSITE))) {
+ if (!(await canViewWebsite(userId, websiteId))) {
return unauthorized(res);
}
- const {
- id: websiteId,
- start_at,
- end_at,
- url,
- referrer,
- os,
- browser,
- device,
- country,
- } = req.query;
-
const startDate = new Date(+start_at);
const endDate = new Date(+end_at);
@@ -33,8 +54,8 @@ export default async (req, res) => {
const prevEndDate = new Date(+end_at - distance);
const metrics = await getWebsiteStats(websiteId, {
- start_at: startDate,
- end_at: endDate,
+ startDate,
+ endDate,
filters: {
url,
referrer,
@@ -45,8 +66,8 @@ export default async (req, res) => {
},
});
const prevPeriod = await getWebsiteStats(websiteId, {
- start_at: prevStartDate,
- end_at: prevEndDate,
+ startDate: prevStartDate,
+ endDate: prevEndDate,
filters: {
url,
referrer,
diff --git a/pages/api/websites/index.js b/pages/api/websites/index.js
deleted file mode 100644
index 3966ad70..00000000
--- a/pages/api/websites/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { createWebsite, getAllWebsites, getUserWebsites } from 'queries';
-import { ok, methodNotAllowed, getRandomChars } from 'next-basics';
-import { useAuth, useCors } from 'lib/middleware';
-import { uuid } from 'lib/crypto';
-
-export default async (req, res) => {
- await useCors(req, res);
- await useAuth(req, res);
-
- const {
- user: { id: userId, isAdmin },
- } = req.auth;
-
- if (req.method === 'GET') {
- const { include_all } = req.query;
-
- const websites =
- isAdmin && include_all ? await getAllWebsites() : await getUserWebsites(userId);
-
- return ok(res, websites);
- }
-
- if (req.method === 'POST') {
- const { name, domain, enableShareUrl } = req.body;
-
- const shareId = enableShareUrl ? getRandomChars(8) : null;
- const website = await createWebsite(userId, { id: uuid(), name, domain, shareId });
-
- return ok(res, website);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/websites/index.ts b/pages/api/websites/index.ts
new file mode 100644
index 00000000..bc79f91a
--- /dev/null
+++ b/pages/api/websites/index.ts
@@ -0,0 +1,57 @@
+import { Prisma } from '@prisma/client';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { uuid } from 'lib/crypto';
+import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok } from 'next-basics';
+import { createWebsite, getUserWebsites } from 'queries';
+
+export interface WebsitesRequestQuery {}
+
+export interface WebsitesRequestBody {
+ name: string;
+ domain: string;
+ shareId: string;
+ teamId?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+
+ if (req.method === 'GET') {
+ const websites = await getUserWebsites(userId);
+
+ return ok(res, websites);
+ }
+
+ if (req.method === 'POST') {
+ const { name, domain, shareId, teamId } = req.body;
+
+ const data: Prisma.WebsiteUncheckedCreateInput = {
+ id: uuid(),
+ name,
+ domain,
+ shareId,
+ };
+
+ if (teamId) {
+ data.teamId = teamId;
+ } else {
+ data.userId = userId;
+ }
+
+ const website = await createWebsite(data);
+
+ return ok(res, website);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/queries/admin/team.ts b/queries/admin/team.ts
new file mode 100644
index 00000000..1bebcadb
--- /dev/null
+++ b/queries/admin/team.ts
@@ -0,0 +1,72 @@
+import { Prisma, Team } from '@prisma/client';
+import prisma from 'lib/prisma';
+import { uuid } from 'lib/crypto';
+import { ROLES } from 'lib/constants';
+import { Website } from 'lib/types';
+
+export async function getTeam(where: Prisma.TeamWhereInput): Promise {
+ return prisma.client.team.findFirst({
+ where,
+ });
+}
+
+export async function getTeams(where: Prisma.TeamWhereInput): Promise {
+ return prisma.client.team.findMany({
+ where,
+ });
+}
+
+export async function getTeamWebsites(teamId: string): Promise {
+ return prisma.client.website.findMany({
+ where: {
+ teamId,
+ },
+ orderBy: [
+ {
+ name: 'asc',
+ },
+ ],
+ });
+}
+
+export async function createTeam(data: Prisma.TeamCreateInput): Promise {
+ const { id, userId } = data;
+
+ return prisma.transaction([
+ prisma.client.team.create({
+ data,
+ }),
+ prisma.client.teamUser.create({
+ data: {
+ id: uuid(),
+ teamId: id,
+ userId,
+ role: ROLES.teamOwner,
+ },
+ }),
+ ]);
+}
+
+export async function updateTeam(
+ data: Prisma.TeamUpdateInput,
+ where: Prisma.TeamWhereUniqueInput,
+): Promise {
+ return prisma.client.team.update({
+ data: {
+ ...data,
+ updatedAt: new Date(),
+ },
+ where,
+ });
+}
+
+export async function deleteTeam(teamId: string): Promise {
+ return prisma.client.team.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: {
+ id: teamId,
+ },
+ });
+}
diff --git a/queries/admin/teamUser.ts b/queries/admin/teamUser.ts
new file mode 100644
index 00000000..13090031
--- /dev/null
+++ b/queries/admin/teamUser.ts
@@ -0,0 +1,56 @@
+import { Prisma, TeamUser } from '@prisma/client';
+import { uuid } from 'lib/crypto';
+import prisma from 'lib/prisma';
+
+export async function getTeamUser(teamId: string, userId: string): Promise {
+ return prisma.client.teamUser.findFirst({
+ where: {
+ teamId,
+ userId,
+ },
+ });
+}
+
+export async function getTeamUsers(teamId: string): Promise {
+ return prisma.client.teamUser.findMany({
+ where: {
+ teamId,
+ },
+ });
+}
+
+export async function createTeamUser(
+ userId: string,
+ teamId: string,
+ role: string,
+): Promise {
+ return prisma.client.teamUser.create({
+ data: {
+ id: uuid(),
+ userId,
+ teamId,
+ role,
+ },
+ });
+}
+
+export async function updateTeamUser(
+ data: Prisma.TeamUserUpdateInput,
+ where: Prisma.TeamUserWhereUniqueInput,
+): Promise {
+ return prisma.client.teamUser.update({
+ data,
+ where,
+ });
+}
+
+export async function deleteTeamUser(teamUserId: string): Promise {
+ return prisma.client.teamUser.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: {
+ id: teamUserId,
+ },
+ });
+}
diff --git a/queries/admin/user.ts b/queries/admin/user.ts
new file mode 100644
index 00000000..a1cfd901
--- /dev/null
+++ b/queries/admin/user.ts
@@ -0,0 +1,159 @@
+import { Prisma, Team } from '@prisma/client';
+import cache from 'lib/cache';
+import prisma from 'lib/prisma';
+import { Website } from 'lib/types';
+
+export interface User {
+ id: string;
+ username: string;
+ password?: string;
+ createdAt?: Date;
+}
+
+export async function getUser(
+ where: Prisma.UserWhereUniqueInput,
+ options: { includePassword?: boolean } = {},
+): Promise {
+ const { includePassword = false } = options;
+
+ return prisma.client.user.findUnique({
+ where,
+ select: {
+ id: true,
+ username: true,
+ password: includePassword,
+ role: true,
+ },
+ });
+}
+
+export async function getUsers(): Promise {
+ return prisma.client.user.findMany({
+ orderBy: [
+ {
+ username: 'asc',
+ },
+ ],
+ select: {
+ id: true,
+ username: true,
+ role: true,
+ createdAt: true,
+ },
+ });
+}
+
+export async function getUserTeams(userId: string): Promise {
+ return prisma.client.teamUser
+ .findMany({
+ where: {
+ userId,
+ },
+ include: {
+ team: true,
+ },
+ })
+ .then(data => {
+ return data.map(a => a.team);
+ });
+}
+
+export async function getUserWebsites(userId: string): Promise {
+ return prisma.client.website.findMany({
+ where: {
+ userId,
+ },
+ orderBy: [
+ {
+ name: 'asc',
+ },
+ ],
+ });
+}
+
+export async function createUser(data: {
+ id: string;
+ username: string;
+ password: string;
+ role: string;
+}): Promise<{
+ id: string;
+ username: string;
+ role: string;
+}> {
+ return prisma.client.user.create({
+ data,
+ select: {
+ id: true,
+ username: true,
+ role: true,
+ },
+ });
+}
+
+export async function updateUser(
+ data: Prisma.UserUpdateInput,
+ where: Prisma.UserWhereUniqueInput,
+): Promise {
+ return prisma.client.user.update({
+ where,
+ data,
+ select: {
+ id: true,
+ username: true,
+ role: true,
+ createdAt: true,
+ },
+ });
+}
+
+export async function deleteUser(
+ userId: string,
+): Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Prisma.BatchPayload, User]> {
+ const { client } = prisma;
+
+ const websites = await client.website.findMany({
+ where: { userId },
+ });
+
+ let websiteIds = [];
+
+ if (websites.length > 0) {
+ websiteIds = websites.map(a => a.id);
+ }
+
+ return prisma
+ .transaction([
+ client.websiteEvent.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.session.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.website.updateMany({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: { id: { in: websiteIds } },
+ }),
+ client.user.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: {
+ id: userId,
+ },
+ }),
+ ])
+ .then(async data => {
+ if (cache.enabled) {
+ const ids = websites.map(a => a.id);
+
+ for (let i = 0; i < ids.length; i++) {
+ await cache.deleteWebsite(`website:${ids[i]}`);
+ }
+ }
+
+ return data;
+ });
+}
diff --git a/queries/admin/user/createUser.js b/queries/admin/user/createUser.js
deleted file mode 100644
index 54e008fe..00000000
--- a/queries/admin/user/createUser.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function createUser(data) {
- return prisma.client.user.create({
- data,
- });
-}
diff --git a/queries/admin/user/deleteUser.js b/queries/admin/user/deleteUser.js
deleted file mode 100644
index 5970d2a5..00000000
--- a/queries/admin/user/deleteUser.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import prisma from 'lib/prisma';
-import cache from 'lib/cache';
-
-export async function deleteUser(userId) {
- const { client } = prisma;
-
- const websites = await client.website.findMany({
- where: { userId },
- });
-
- let websiteIds = [];
-
- if (websites.length > 0) {
- websiteIds = websites.map(a => a.id);
- }
-
- return client
- .$transaction([
- client.websiteEvent.deleteMany({
- where: { websiteId: { in: websiteIds } },
- }),
- client.session.deleteMany({
- where: { websiteId: { in: websiteIds } },
- }),
- client.website.deleteMany({
- where: { userId },
- }),
- client.user.delete({
- where: {
- id: userId,
- },
- }),
- ])
- .then(async data => {
- if (cache.enabled) {
- const ids = websites.map(a => a.id);
-
- for (let i = 0; i < ids.length; i++) {
- await cache.deleteWebsite(`website:${ids[i]}`);
- }
- }
-
- return data;
- });
-}
diff --git a/queries/admin/user/getUser.js b/queries/admin/user/getUser.js
deleted file mode 100644
index 6c9ebd88..00000000
--- a/queries/admin/user/getUser.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function getUser(where) {
- return prisma.client.user.findUnique({
- where,
- });
-}
diff --git a/queries/admin/user/getUsers.js b/queries/admin/user/getUsers.js
deleted file mode 100644
index 2fc473cb..00000000
--- a/queries/admin/user/getUsers.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function getUsers() {
- return prisma.client.user.findMany({
- orderBy: [
- { isAdmin: 'desc' },
- {
- username: 'asc',
- },
- ],
- select: {
- id: true,
- username: true,
- isAdmin: true,
- createdAt: true,
- },
- });
-}
diff --git a/queries/admin/user/updateUser.js b/queries/admin/user/updateUser.js
deleted file mode 100644
index ea80cf43..00000000
--- a/queries/admin/user/updateUser.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function updateUser(data, where) {
- return prisma.client.user.update({
- where,
- data,
- });
-}
diff --git a/queries/admin/website.ts b/queries/admin/website.ts
new file mode 100644
index 00000000..cf2425a3
--- /dev/null
+++ b/queries/admin/website.ts
@@ -0,0 +1,110 @@
+import { Prisma, Website } from '@prisma/client';
+import cache from 'lib/cache';
+import prisma from 'lib/prisma';
+import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
+
+export async function getWebsite(where: Prisma.WebsiteWhereUniqueInput): Promise {
+ return prisma.client.website.findUnique({
+ where,
+ });
+}
+
+export async function getWebsites(): Promise {
+ return prisma.client.website.findMany({
+ orderBy: {
+ name: 'asc',
+ },
+ });
+}
+
+export async function createWebsite(
+ data: Prisma.WebsiteCreateInput | Prisma.WebsiteUncheckedCreateInput,
+): Promise {
+ return prisma.client.website
+ .create({
+ data,
+ })
+ .then(async data => {
+ if (cache.enabled) {
+ await cache.storeWebsite(data);
+ }
+
+ return data;
+ });
+}
+
+export async function updateWebsite(
+ websiteId,
+ data: Prisma.WebsiteUpdateInput | Prisma.WebsiteUncheckedUpdateInput,
+): Promise {
+ return prisma.client.website.update({
+ where: {
+ id: websiteId,
+ },
+ data,
+ });
+}
+
+export async function resetWebsite(
+ websiteId,
+): Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Website]> {
+ const { client, transaction } = prisma;
+
+ const { revId } = await getWebsite({ id: websiteId });
+
+ return transaction([
+ client.websiteEvent.deleteMany({
+ where: { websiteId },
+ }),
+ client.session.deleteMany({
+ where: { websiteId },
+ }),
+ client.website.update({ where: { id: websiteId }, data: { revId: revId + 1 } }),
+ ]).then(async data => {
+ if (cache.enabled) {
+ await cache.storeWebsite(data[2]);
+ }
+
+ return data;
+ });
+}
+
+export async function deleteWebsite(websiteId: string) {
+ return runQuery({
+ [PRISMA]: () => deleteWebsiteRelationalQuery(websiteId),
+ [CLICKHOUSE]: () => deleteWebsiteClickhouseQuery(websiteId),
+ });
+}
+
+async function deleteWebsiteRelationalQuery(
+ websiteId,
+): Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Website]> {
+ const { client, transaction } = prisma;
+
+ return transaction([
+ client.websiteEvent.deleteMany({
+ where: { websiteId },
+ }),
+ client.session.deleteMany({
+ where: { websiteId },
+ }),
+ client.website.delete({
+ where: { id: websiteId },
+ }),
+ ]).then(async data => {
+ if (cache.enabled) {
+ await cache.deleteWebsite(websiteId);
+ }
+
+ return data;
+ });
+}
+
+async function deleteWebsiteClickhouseQuery(websiteId): Promise {
+ return prisma.client.website.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: { id: websiteId },
+ });
+}
diff --git a/queries/admin/website/createWebsite.js b/queries/admin/website/createWebsite.js
deleted file mode 100644
index 0afe0bea..00000000
--- a/queries/admin/website/createWebsite.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import prisma from 'lib/prisma';
-import cache from 'lib/cache';
-
-export async function createWebsite(userId, data) {
- return prisma.client.website
- .create({
- data: {
- user: {
- connect: {
- id: userId,
- },
- },
- ...data,
- },
- })
- .then(async data => {
- if (cache.enabled) {
- await cache.storeWebsite(data);
- }
-
- return data;
- });
-}
diff --git a/queries/admin/website/deleteWebsite.js b/queries/admin/website/deleteWebsite.js
deleted file mode 100644
index 685cee8a..00000000
--- a/queries/admin/website/deleteWebsite.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import prisma from 'lib/prisma';
-import cache from 'lib/cache';
-
-export async function deleteWebsite(id) {
- const { client, transaction } = prisma;
-
- return transaction([
- client.websiteEvent.deleteMany({
- where: { websiteId: id },
- }),
- client.session.deleteMany({
- where: { websiteId: id },
- }),
- client.website.delete({
- where: { id },
- }),
- ]).then(async data => {
- if (cache.enabled) {
- await cache.deleteWebsite(id);
- }
-
- return data;
- });
-}
diff --git a/queries/admin/website/getAllWebsites.js b/queries/admin/website/getAllWebsites.js
deleted file mode 100644
index f9ad262c..00000000
--- a/queries/admin/website/getAllWebsites.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function getAllWebsites() {
- let data = await prisma.client.website.findMany({
- orderBy: [
- {
- userId: 'asc',
- },
- {
- name: 'asc',
- },
- ],
- include: {
- user: {
- select: {
- username: true,
- },
- },
- },
- });
-
- return data.map(i => ({ ...i, user: i.user.username }));
-}
diff --git a/queries/admin/website/getUserWebsites.js b/queries/admin/website/getUserWebsites.js
deleted file mode 100644
index c1a9d559..00000000
--- a/queries/admin/website/getUserWebsites.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function getUserWebsites(userId) {
- return prisma.client.website.findMany({
- where: {
- userId,
- },
- orderBy: {
- name: 'asc',
- },
- });
-}
diff --git a/queries/admin/website/getWebsite.js b/queries/admin/website/getWebsite.js
deleted file mode 100644
index 83c3e83a..00000000
--- a/queries/admin/website/getWebsite.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function getWebsite(where) {
- return prisma.client.website.findUnique({
- where,
- });
-}
diff --git a/queries/admin/website/resetWebsite.js b/queries/admin/website/resetWebsite.js
deleted file mode 100644
index f4d685cb..00000000
--- a/queries/admin/website/resetWebsite.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import prisma from 'lib/prisma';
-import { getWebsite } from 'queries';
-import cache from 'lib/cache';
-
-export async function resetWebsite(id) {
- const { client, transaction } = prisma;
-
- const { revId } = await getWebsite({ id });
-
- return transaction([
- client.websiteEvent.deleteMany({
- where: { websiteId: id },
- }),
- client.session.deleteMany({
- where: { websiteId: id },
- }),
- client.website.update({ where: { id }, data: { revId: revId + 1 } }),
- ]).then(async data => {
- if (cache.enabled) {
- await cache.storeWebsite(data[2]);
- }
-
- return data;
- });
-}
diff --git a/queries/admin/website/updateWebsite.js b/queries/admin/website/updateWebsite.js
deleted file mode 100644
index 5ac70a61..00000000
--- a/queries/admin/website/updateWebsite.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import prisma from 'lib/prisma';
-
-export async function updateWebsite(id, data) {
- return prisma.client.website.update({
- where: {
- id,
- },
- data,
- });
-}
diff --git a/queries/analytics/event/getEventData.js b/queries/analytics/event/getEventData.ts
similarity index 50%
rename from queries/analytics/event/getEventData.js
rename to queries/analytics/event/getEventData.ts
index f7d725c1..ae8b8503 100644
--- a/queries/analytics/event/getEventData.js
+++ b/queries/analytics/event/getEventData.ts
@@ -2,8 +2,21 @@ import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import cache from 'lib/cache';
+import { WebsiteMetric } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
-export async function getEventData(...args) {
+export async function getEventData(
+ ...args: [
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ eventName: string;
+ columns: any;
+ filters: object;
+ },
+ ]
+): Promise {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
@@ -14,31 +27,48 @@ export async function getEventData(...args) {
});
}
-async function relationalQuery(websiteId, { startDate, endDate, event_name, columns, filters }) {
+async function relationalQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ eventName: string;
+ columns: any;
+ filters: object;
+ },
+) {
+ const { startDate, endDate, eventName, columns, filters } = data;
const { rawQuery, getEventDataColumnsQuery, getEventDataFilterQuery } = prisma;
const params = [startDate, endDate];
return rawQuery(
`select
- ${getEventDataColumnsQuery('event_data.event_data', columns)}
- from event
- join website
- on event.website_id = website.website_id
- join event_data
- on event.event_id = event_data.event_id
- where website.website_id ='${websiteId}'
- and event.created_at between $1 and $2
- ${event_name ? `and event_name = ${event_name}` : ''}
+ ${getEventDataColumnsQuery('event_data', columns)}
+ from website_event
+ where website_id ='${websiteId}'
+ and created_at between $1 and $2
+ and event_type = ${EVENT_TYPE.customEvent}
+ ${eventName ? `and eventName = ${eventName}` : ''}
${
Object.keys(filters).length > 0
- ? `and ${getEventDataFilterQuery('event_data.event_data', filters)}`
+ ? `and ${getEventDataFilterQuery('event_data', filters)}`
: ''
}`,
params,
);
}
-async function clickhouseQuery(websiteId, { startDate, endDate, event_name, columns, filters }) {
+async function clickhouseQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ eventName: string;
+ columns: any;
+ filters: object;
+ },
+) {
+ const { startDate, endDate, eventName, columns, filters } = data;
const { rawQuery, getBetweenDates, getEventDataColumnsQuery, getEventDataFilterQuery } =
clickhouse;
const website = await cache.fetchWebsite(websiteId);
@@ -50,7 +80,8 @@ async function clickhouseQuery(websiteId, { startDate, endDate, event_name, colu
from event
where website_id = $1
and rev_id = $2
- ${event_name ? `and event_name = ${event_name}` : ''}
+ and event_type = ${EVENT_TYPE.customEvent}
+ ${eventName ? `and eventName = ${eventName}` : ''}
and ${getBetweenDates('created_at', startDate, endDate)}
${
Object.keys(filters).length > 0
diff --git a/queries/analytics/event/getEventMetrics.js b/queries/analytics/event/getEventMetrics.js
deleted file mode 100644
index 27ee6d04..00000000
--- a/queries/analytics/event/getEventMetrics.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import prisma from 'lib/prisma';
-import clickhouse from 'lib/clickhouse';
-import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
-import cache from 'lib/cache';
-
-export async function getEventMetrics(...args) {
- return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
- });
-}
-
-async function relationalQuery(
- websiteId,
- start_at,
- end_at,
- timezone = 'utc',
- unit = 'day',
- filters = {},
-) {
- const { rawQuery, getDateQuery, getFilterQuery } = prisma;
- const params = [start_at, end_at];
-
- return rawQuery(
- `select
- event_name x,
- ${getDateQuery('event.created_at', unit, timezone)} t,
- count(*) y
- from event
- join website
- on event.website_id = website.website_id
- where website.website_id='${websiteId}'
- and event.created_at between $1 and $2
- ${getFilterQuery('event', filters, params)}
- group by 1, 2
- order by 2`,
- params,
- );
-}
-
-async function clickhouseQuery(
- websiteId,
- start_at,
- end_at,
- timezone = 'UTC',
- unit = 'day',
- filters = {},
-) {
- const { rawQuery, getDateQuery, getBetweenDates, getFilterQuery } = clickhouse;
- const website = await cache.fetchWebsite(websiteId);
- const params = [websiteId, website?.revId || 0];
-
- return rawQuery(
- `select
- event_name x,
- ${getDateQuery('created_at', unit, timezone)} t,
- count(*) y
- from event
- where event_name != ''
- and website_id = $1
- and rev_id = $2
- and ${getBetweenDates('created_at', start_at, end_at)}
- ${getFilterQuery('event', filters, params)}
- group by x, t
- order by t`,
- params,
- );
-}
diff --git a/queries/analytics/event/getEventMetrics.ts b/queries/analytics/event/getEventMetrics.ts
new file mode 100644
index 00000000..0440cb3f
--- /dev/null
+++ b/queries/analytics/event/getEventMetrics.ts
@@ -0,0 +1,105 @@
+import prisma from 'lib/prisma';
+import clickhouse from 'lib/clickhouse';
+import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
+import cache from 'lib/cache';
+import { WebsiteEventMetric } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
+
+export async function getEventMetrics(
+ ...args: [
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ timezone: string;
+ unit: string;
+ filters: {
+ url: string;
+ eventName: string;
+ };
+ },
+ ]
+): Promise {
+ return runQuery({
+ [PRISMA]: () => relationalQuery(...args),
+ [CLICKHOUSE]: () => clickhouseQuery(...args),
+ });
+}
+
+async function relationalQuery(
+ websiteId: string,
+ {
+ startDate,
+ endDate,
+ timezone = 'utc',
+ unit = 'day',
+ filters,
+ }: {
+ startDate: Date;
+ endDate: Date;
+ timezone: string;
+ unit: string;
+ filters: {
+ url: string;
+ eventName: string;
+ };
+ },
+) {
+ const { rawQuery, getDateQuery, getFilterQuery } = prisma;
+ const params = [startDate, endDate];
+
+ return rawQuery(
+ `select
+ event_name x,
+ ${getDateQuery('created_at', unit, timezone)} t,
+ count(*) y
+ from website_event
+ where website_id='${websiteId}'
+ and created_at between $1 and $2
+ and event_type = ${EVENT_TYPE.customEvent}
+ ${getFilterQuery(filters, params)}
+ group by 1, 2
+ order by 2`,
+ params,
+ );
+}
+
+async function clickhouseQuery(
+ websiteId: string,
+ {
+ startDate,
+ endDate,
+ timezone = 'utc',
+ unit = 'day',
+ filters,
+ }: {
+ startDate: Date;
+ endDate: Date;
+ timezone: string;
+ unit: string;
+ filters: {
+ url: string;
+ eventName: string;
+ };
+ },
+) {
+ const { rawQuery, getDateQuery, getBetweenDates, getFilterQuery } = clickhouse;
+ const website = await cache.fetchWebsite(websiteId);
+ const params = [websiteId, website?.revId || 0];
+
+ return rawQuery(
+ `select
+ event_name x,
+ ${getDateQuery('created_at', unit, timezone)} t,
+ count(*) y
+ from event
+ where website_id = $1
+ and rev_id = $2
+ and event_type = ${EVENT_TYPE.customEvent}
+ and ${getBetweenDates('created_at', startDate, endDate)}
+ ${getFilterQuery(filters, params)}
+ group by x, t
+ order by t`,
+ params,
+ );
+}
diff --git a/queries/analytics/event/saveEvent.js b/queries/analytics/event/saveEvent.js
deleted file mode 100644
index 3bb3b0bf..00000000
--- a/queries/analytics/event/saveEvent.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import { EVENT_NAME_LENGTH, URL_LENGTH } from 'lib/constants';
-import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
-import kafka from 'lib/kafka';
-import prisma from 'lib/prisma';
-import { uuid } from 'lib/crypto';
-import cache from 'lib/cache';
-
-export async function saveEvent(...args) {
- return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
- });
-}
-
-async function relationalQuery(data) {
- const { websiteId, sessionId, url, eventName, eventData } = data;
- const eventId = uuid();
-
- const params = {
- id: eventId,
- websiteId,
- sessionId,
- url: url?.substring(0, URL_LENGTH),
- eventName: eventName?.substring(0, EVENT_NAME_LENGTH),
- };
-
- if (eventData) {
- params.eventData = {
- create: {
- id: eventId,
- eventData: eventData,
- },
- };
- }
-
- return prisma.client.event.create({
- data: params,
- });
-}
-
-async function clickhouseQuery(data) {
- const { websiteId, id: sessionId, url, eventName, eventData, country, ...args } = data;
- const { getDateFormat, sendMessage } = kafka;
- const website = await cache.fetchWebsite(websiteId);
-
- const params = {
- website_id: websiteId,
- session_id: sessionId,
- event_id: uuid(),
- url: url?.substring(0, URL_LENGTH),
- event_name: eventName?.substring(0, EVENT_NAME_LENGTH),
- event_data: eventData ? JSON.stringify(eventData) : null,
- rev_id: website?.revId || 0,
- created_at: getDateFormat(new Date()),
- country: country ? country : null,
- ...args,
- };
-
- await sendMessage(params, 'event');
-
- return data;
-}
diff --git a/queries/analytics/event/saveEvent.ts b/queries/analytics/event/saveEvent.ts
new file mode 100644
index 00000000..430ffd63
--- /dev/null
+++ b/queries/analytics/event/saveEvent.ts
@@ -0,0 +1,91 @@
+import { EVENT_NAME_LENGTH, URL_LENGTH, EVENT_TYPE } from 'lib/constants';
+import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
+import kafka from 'lib/kafka';
+import prisma from 'lib/prisma';
+import { uuid } from 'lib/crypto';
+import cache from 'lib/cache';
+
+export async function saveEvent(args: {
+ id: string;
+ websiteId: string;
+ url: string;
+ referrer?: string;
+ eventName?: string;
+ eventData?: any;
+ hostname?: string;
+ browser?: string;
+ os?: string;
+ device?: string;
+ screen?: string;
+ language?: string;
+ country?: string;
+}) {
+ return runQuery({
+ [PRISMA]: () => relationalQuery(args),
+ [CLICKHOUSE]: () => clickhouseQuery(args),
+ });
+}
+
+async function relationalQuery(data: {
+ id: string;
+ websiteId: string;
+ url: string;
+ referrer?: string;
+ eventName?: string;
+ eventData?: any;
+}) {
+ const { websiteId, id: sessionId, url, eventName, eventData, referrer } = data;
+
+ const params = {
+ id: uuid(),
+ websiteId,
+ sessionId,
+ url: url?.substring(0, URL_LENGTH),
+ referrer: referrer?.substring(0, URL_LENGTH),
+ eventType: EVENT_TYPE.customEvent,
+ eventName: eventName?.substring(0, EVENT_NAME_LENGTH),
+ eventData,
+ };
+
+ return prisma.client.websiteEvent.create({
+ data: params,
+ });
+}
+
+async function clickhouseQuery(data: {
+ id: string;
+ websiteId: string;
+ url: string;
+ referrer?: string;
+ eventName?: string;
+ eventData?: any;
+ hostname?: string;
+ browser?: string;
+ os?: string;
+ device?: string;
+ screen?: string;
+ language?: string;
+ country?: string;
+}) {
+ const { websiteId, id: sessionId, url, eventName, eventData, country, ...args } = data;
+ const { getDateFormat, sendMessage } = kafka;
+ const website = await cache.fetchWebsite(websiteId);
+
+ const message = {
+ website_id: websiteId,
+ session_id: sessionId,
+ event_id: uuid(),
+ url: url?.substring(0, URL_LENGTH),
+ event_type: EVENT_TYPE.customEvent,
+ event_name: eventName?.substring(0, EVENT_NAME_LENGTH),
+ event_data: eventData ? JSON.stringify(eventData) : null,
+ rev_id: website?.revId || 0,
+ created_at: getDateFormat(new Date()),
+ country: country ? country : null,
+ ...args,
+ };
+
+ await sendMessage(message, 'event');
+
+ return data;
+}
diff --git a/queries/analytics/pageview/getPageviewMetrics.js b/queries/analytics/pageview/getPageviewMetrics.js
deleted file mode 100644
index 8dfd6595..00000000
--- a/queries/analytics/pageview/getPageviewMetrics.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import prisma from 'lib/prisma';
-import clickhouse from 'lib/clickhouse';
-import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
-import cache from 'lib/cache';
-
-export async function getPageviewMetrics(...args) {
- return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
- });
-}
-
-async function relationalQuery(websiteId, { startDate, endDate, column, table, filters = {} }) {
- const { rawQuery, parseFilters } = prisma;
- const params = [startDate, endDate];
- const { pageviewQuery, sessionQuery, eventQuery, joinSession } = parseFilters(
- table,
- column,
- filters,
- params,
- );
-
- return rawQuery(
- `select ${column} x, count(*) y
- from ${table}
- ${` join website on ${table}.website_id = website.website_id`}
- ${joinSession}
- where website.website_id='${websiteId}'
- and ${table}.created_at between $1 and $2
- ${pageviewQuery}
- ${joinSession && sessionQuery}
- ${eventQuery}
- group by 1
- order by 2 desc`,
- params,
- );
-}
-
-async function clickhouseQuery(websiteId, { startDate, endDate, column, filters = {} }) {
- const { rawQuery, parseFilters, getBetweenDates } = clickhouse;
- const website = await cache.fetchWebsite(websiteId);
- const params = [websiteId, website?.revId || 0];
- const { pageviewQuery, sessionQuery, eventQuery } = parseFilters(column, filters, params);
-
- return rawQuery(
- `select ${column} x, count(*) y
- from event
- where website_id = $1
- and rev_id = $2
- ${column !== 'event_name' ? `and event_name = ''` : `and event_name != ''`}
- and ${getBetweenDates('created_at', startDate, endDate)}
- ${pageviewQuery}
- ${sessionQuery}
- ${eventQuery}
- group by x
- order by y desc`,
- params,
- );
-}
diff --git a/queries/analytics/pageview/getPageviewMetrics.ts b/queries/analytics/pageview/getPageviewMetrics.ts
new file mode 100644
index 00000000..1e619fb8
--- /dev/null
+++ b/queries/analytics/pageview/getPageviewMetrics.ts
@@ -0,0 +1,81 @@
+import prisma from 'lib/prisma';
+import clickhouse from 'lib/clickhouse';
+import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
+import cache from 'lib/cache';
+import { Prisma } from '@prisma/client';
+import { EVENT_TYPE } from 'lib/constants';
+
+export async function getPageviewMetrics(
+ ...args: [
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ column: Prisma.WebsiteEventScalarFieldEnum | Prisma.SessionScalarFieldEnum;
+ table: string;
+ filters: object;
+ },
+ ]
+) {
+ return runQuery({
+ [PRISMA]: () => relationalQuery(...args),
+ [CLICKHOUSE]: () => clickhouseQuery(...args),
+ });
+}
+
+async function relationalQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ column: Prisma.WebsiteEventScalarFieldEnum | Prisma.SessionScalarFieldEnum;
+ filters: object;
+ },
+) {
+ const { startDate, endDate, column, filters = {} } = data;
+ const { rawQuery, parseFilters } = prisma;
+ const params = [startDate, endDate];
+ const { filterQuery, joinSession } = parseFilters(filters, params);
+
+ return rawQuery(
+ `select ${column} x, count(*) y
+ from website_event
+ ${joinSession}
+ where website_id='${websiteId}'
+ and website_event.created_at between $1 and $2
+ and event_type = ${EVENT_TYPE.pageView}
+ ${filterQuery}
+ group by 1
+ order by 2 desc`,
+ params,
+ );
+}
+
+async function clickhouseQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ column: Prisma.WebsiteEventScalarFieldEnum | Prisma.SessionScalarFieldEnum;
+ filters: object;
+ },
+) {
+ const { startDate, endDate, column, filters = {} } = data;
+ const { rawQuery, parseFilters, getBetweenDates } = clickhouse;
+ const website = await cache.fetchWebsite(websiteId);
+ const params = [websiteId, website?.revId || 0, EVENT_TYPE.pageView];
+ const { filterQuery } = parseFilters(filters, params);
+
+ return rawQuery(
+ `select ${column} x, count(*) y
+ from event
+ where website_id = $1
+ and rev_id = $2
+ and event_type = $3
+ and ${getBetweenDates('created_at', startDate, endDate)}
+ ${filterQuery}
+ group by x
+ order by y desc`,
+ params,
+ );
+}
diff --git a/queries/analytics/pageview/getPageviewParams.js b/queries/analytics/pageview/getPageviewParams.js
deleted file mode 100644
index ce96c25b..00000000
--- a/queries/analytics/pageview/getPageviewParams.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import prisma from 'lib/prisma';
-import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
-
-export async function getPageviewParams(...args) {
- return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
- });
-}
-
-async function relationalQuery(websiteId, start_at, end_at, column, table, filters = {}) {
- const { parseFilters, rawQuery } = prisma;
- const params = [start_at, end_at];
- const { pageviewQuery, sessionQuery, eventQuery, joinSession } = parseFilters(
- table,
- column,
- filters,
- params,
- );
-
- return rawQuery(
- `select url x,
- count(*) y
- from ${table}
- ${` join website on ${table}.website_id = website.website_id`}
- ${joinSession}
- where website.website_id='${websiteId}'
- and ${table}.created_at between $1 and $2
- and ${table}.url like '%?%'
- ${pageviewQuery}
- ${joinSession && sessionQuery}
- ${eventQuery}
- group by 1
- order by 2 desc`,
- params,
- );
-}
-
-function clickhouseQuery() {
- return Promise.reject(new Error('Not implemented.'));
-}
diff --git a/queries/analytics/pageview/getPageviewStats.js b/queries/analytics/pageview/getPageviewStats.js
deleted file mode 100644
index c711d448..00000000
--- a/queries/analytics/pageview/getPageviewStats.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import prisma from 'lib/prisma';
-import clickhouse from 'lib/clickhouse';
-import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
-import cache from 'lib/cache';
-
-export async function getPageviewStats(...args) {
- return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
- });
-}
-
-async function relationalQuery(
- websiteId,
- {
- start_at,
- end_at,
- timezone = 'utc',
- unit = 'day',
- count = '*',
- filters = {},
- sessionKey = 'session_id',
- },
-) {
- const { getDateQuery, parseFilters, rawQuery } = prisma;
- const params = [start_at, end_at];
- const { pageviewQuery, sessionQuery, joinSession } = parseFilters(
- 'pageview',
- null,
- filters,
- params,
- );
-
- return rawQuery(
- `select ${getDateQuery('pageview.created_at', unit, timezone)} t,
- count(${count !== '*' ? `${count}${sessionKey}` : count}) y
- from pageview
- join website
- on pageview.website_id = website.website_id
- ${joinSession}
- where website.website_id='${websiteId}'
- and pageview.created_at between $1 and $2
- ${pageviewQuery}
- ${sessionQuery}
- group by 1`,
- params,
- );
-}
-
-async function clickhouseQuery(
- websiteId,
- { start_at, end_at, timezone = 'UTC', unit = 'day', count = '*', filters = {} },
-) {
- const { parseFilters, rawQuery, getDateStringQuery, getDateQuery, getBetweenDates } = clickhouse;
- const website = await cache.fetchWebsite(websiteId);
- const params = [websiteId, website?.revId || 0];
- const { pageviewQuery, sessionQuery } = parseFilters(null, filters, params);
-
- return rawQuery(
- `select
- ${getDateStringQuery('g.t', unit)} as t,
- g.y as y
- from
- (select
- ${getDateQuery('created_at', unit, timezone)} t,
- count(${count !== '*' ? 'distinct session_id' : count}) y
- from event
- where event_name = ''
- and website_id = $1
- and rev_id = $2
- and ${getBetweenDates('created_at', start_at, end_at)}
- ${pageviewQuery}
- ${sessionQuery}
- group by t) g
- order by t`,
- params,
- );
-}
diff --git a/queries/analytics/pageview/getPageviewStats.ts b/queries/analytics/pageview/getPageviewStats.ts
new file mode 100644
index 00000000..b23f782b
--- /dev/null
+++ b/queries/analytics/pageview/getPageviewStats.ts
@@ -0,0 +1,102 @@
+import cache from 'lib/cache';
+import clickhouse from 'lib/clickhouse';
+import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
+import prisma from 'lib/prisma';
+import { EVENT_TYPE } from 'lib/constants';
+
+export async function getPageviewStats(
+ ...args: [
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ timezone?: string;
+ unit?: string;
+ count?: string;
+ filters: object;
+ sessionKey?: string;
+ },
+ ]
+) {
+ return runQuery({
+ [PRISMA]: () => relationalQuery(...args),
+ [CLICKHOUSE]: () => clickhouseQuery(...args),
+ });
+}
+
+async function relationalQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ timezone?: string;
+ unit?: string;
+ count?: string;
+ filters: object;
+ sessionKey?: string;
+ },
+) {
+ const {
+ startDate,
+ endDate,
+ timezone = 'utc',
+ unit = 'day',
+ count = '*',
+ filters = {},
+ sessionKey = 'session_id',
+ } = data;
+ const { getDateQuery, parseFilters, rawQuery } = prisma;
+ const params = [startDate, endDate];
+ const { filterQuery, joinSession } = parseFilters(filters, params);
+
+ return rawQuery(
+ `select ${getDateQuery('website_event.created_at', unit, timezone)} t,
+ count(${count !== '*' ? `${count}${sessionKey}` : count}) y
+ from website_event
+ ${joinSession}
+ where website.website_id='${websiteId}'
+ and pageview.created_at between $1 and $2
+ and event_type = ${EVENT_TYPE.pageView}
+ ${filterQuery}
+ group by 1`,
+ params,
+ );
+}
+
+async function clickhouseQuery(
+ websiteId: string,
+ data: {
+ startDate: Date;
+ endDate: Date;
+ timezone?: string;
+ unit?: string;
+ count?: string;
+ filters: object;
+ sessionKey?: string;
+ },
+) {
+ const { startDate, endDate, timezone = 'UTC', unit = 'day', count = '*', filters = {} } = data;
+ const { parseFilters, rawQuery, getDateStringQuery, getDateQuery, getBetweenDates } = clickhouse;
+ const website = await cache.fetchWebsite(websiteId);
+ const params = [websiteId, website?.revId || 0];
+ const { filterQuery } = parseFilters(filters, params);
+
+ return rawQuery(
+ `select
+ ${getDateStringQuery('g.t', unit)} as t,
+ g.y as y
+ from
+ (select
+ ${getDateQuery('created_at', unit, timezone)} t,
+ count(${count !== '*' ? 'distinct session_id' : count}) y
+ from event
+ where website_id = $1
+ and rev_id = $2
+ and event_type = ${EVENT_TYPE.pageView}
+ and ${getBetweenDates('created_at', startDate, endDate)}
+ ${filterQuery}
+ group by t) g
+ order by t`,
+ params,
+ );
+}
diff --git a/queries/analytics/pageview/savePageView.js b/queries/analytics/pageview/savePageView.ts
similarity index 54%
rename from queries/analytics/pageview/savePageView.js
rename to queries/analytics/pageview/savePageView.ts
index adcb4b3f..ae702211 100644
--- a/queries/analytics/pageview/savePageView.js
+++ b/queries/analytics/pageview/savePageView.ts
@@ -1,26 +1,45 @@
-import { URL_LENGTH } from 'lib/constants';
+import { URL_LENGTH, EVENT_TYPE } from 'lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
import cache from 'lib/cache';
import { uuid } from 'lib/crypto';
-export async function savePageView(...args) {
+export async function savePageView(args: {
+ id: string;
+ websiteId: string;
+ url: string;
+ referrer?: string;
+ hostname?: string;
+ browser?: string;
+ os?: string;
+ device?: string;
+ screen?: string;
+ language?: string;
+ country?: string;
+}) {
return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
+ [PRISMA]: () => relationalQuery(args),
+ [CLICKHOUSE]: () => clickhouseQuery(args),
});
}
-async function relationalQuery(data) {
- const { websiteId, sessionId, url, referrer } = data;
- return prisma.client.pageview.create({
+async function relationalQuery(data: {
+ id: string;
+ websiteId: string;
+ url: string;
+ referrer?: string;
+}) {
+ const { websiteId, id: sessionId, url, referrer } = data;
+
+ return prisma.client.websiteEvent.create({
data: {
id: uuid(),
websiteId,
sessionId,
url: url?.substring(0, URL_LENGTH),
referrer: referrer?.substring(0, URL_LENGTH),
+ eventType: EVENT_TYPE.pageView,
},
});
}
@@ -30,7 +49,7 @@ async function clickhouseQuery(data) {
const website = await cache.fetchWebsite(websiteId);
const { getDateFormat, sendMessage } = kafka;
- const msg = {
+ const message = {
session_id: sessionId,
website_id: websiteId,
url: url?.substring(0, URL_LENGTH),
@@ -38,10 +57,11 @@ async function clickhouseQuery(data) {
rev_id: website?.revId || 0,
created_at: getDateFormat(new Date()),
country: country ? country : null,
+ event_type: EVENT_TYPE.pageView,
...args,
};
- await sendMessage(msg, 'event');
+ await sendMessage(message, 'event');
return data;
}
diff --git a/queries/analytics/session/createSession.js b/queries/analytics/session/createSession.ts
similarity index 63%
rename from queries/analytics/session/createSession.js
rename to queries/analytics/session/createSession.ts
index f401a20f..fe15f11c 100644
--- a/queries/analytics/session/createSession.js
+++ b/queries/analytics/session/createSession.ts
@@ -2,11 +2,12 @@ import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
import cache from 'lib/cache';
+import { Prisma } from '@prisma/client';
-export async function createSession(...args) {
+export async function createSession(args: Prisma.SessionCreateInput) {
return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
+ [PRISMA]: () => relationalQuery(args),
+ [CLICKHOUSE]: () => clickhouseQuery(args),
}).then(async data => {
if (cache.enabled) {
await cache.storeSession(data);
@@ -16,11 +17,21 @@ export async function createSession(...args) {
});
}
-async function relationalQuery(data) {
+async function relationalQuery(data: Prisma.SessionCreateInput) {
return prisma.client.session.create({ data });
}
-async function clickhouseQuery(data) {
+async function clickhouseQuery(data: {
+ id: string;
+ websiteId: string;
+ hostname?: string;
+ browser?: string;
+ os?: string;
+ device?: string;
+ screen?: string;
+ language?: string;
+ country?: string;
+}) {
const { id, websiteId, hostname, browser, os, device, screen, language, country } = data;
const { getDateFormat, sendMessage } = kafka;
const website = await cache.fetchWebsite(websiteId);
diff --git a/queries/analytics/session/getSession.js b/queries/analytics/session/getSession.ts
similarity index 64%
rename from queries/analytics/session/getSession.js
rename to queries/analytics/session/getSession.ts
index adc9acd8..19875117 100644
--- a/queries/analytics/session/getSession.js
+++ b/queries/analytics/session/getSession.ts
@@ -1,21 +1,22 @@
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
+import { Prisma } from '@prisma/client';
-export async function getSession(...args) {
+export async function getSession(args: { id: string }) {
return runQuery({
- [PRISMA]: () => relationalQuery(...args),
- [CLICKHOUSE]: () => clickhouseQuery(...args),
+ [PRISMA]: () => relationalQuery(args),
+ [CLICKHOUSE]: () => clickhouseQuery(args),
});
}
-async function relationalQuery(where) {
+async function relationalQuery(where: Prisma.SessionWhereUniqueInput) {
return prisma.client.session.findUnique({
where,
});
}
-async function clickhouseQuery({ id: sessionId }) {
+async function clickhouseQuery({ id: sessionId }: { id: string }) {
const { rawQuery, findFirst } = clickhouse;
const params = [sessionId];
diff --git a/queries/analytics/session/getSessionMetrics.js b/queries/analytics/session/getSessionMetrics.ts
similarity index 60%
rename from queries/analytics/session/getSessionMetrics.js
rename to queries/analytics/session/getSessionMetrics.ts
index 6e74e9b6..04e1801a 100644
--- a/queries/analytics/session/getSessionMetrics.js
+++ b/queries/analytics/session/getSessionMetrics.ts
@@ -3,17 +3,26 @@ import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import cache from 'lib/cache';
-export async function getSessionMetrics(...args) {
+export async function getSessionMetrics(
+ ...args: [
+ websiteId: string,
+ data: { startDate: Date; endDate: Date; field: string; filters: object },
+ ]
+) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
-async function relationalQuery(websiteId, { startDate, endDate, field, filters = {} }) {
+async function relationalQuery(
+ websiteId: string,
+ data: { startDate: Date; endDate: Date; field: string; filters: object },
+) {
+ const { startDate, endDate, field, filters = {} } = data;
const { parseFilters, rawQuery } = prisma;
const params = [startDate, endDate];
- const { pageviewQuery, sessionQuery, joinSession } = parseFilters(null, filters, params);
+ const { filterQuery, joinSession } = parseFilters(filters, params);
return rawQuery(
`select ${field} x, count(*) y
@@ -26,8 +35,7 @@ async function relationalQuery(websiteId, { startDate, endDate, field, filters =
${joinSession}
where website.website_id='${websiteId}'
and pageview.created_at between $1 and $2
- ${pageviewQuery}
- ${sessionQuery}
+ ${filterQuery}
)
group by 1
order by 2 desc`,
@@ -35,21 +43,24 @@ async function relationalQuery(websiteId, { startDate, endDate, field, filters =
);
}
-async function clickhouseQuery(websiteId, { startDate, endDate, field, filters = {} }) {
+async function clickhouseQuery(
+ websiteId: string,
+ data: { startDate: Date; endDate: Date; field: string; filters: object },
+) {
+ const { startDate, endDate, field, filters = {} } = data;
const { parseFilters, getBetweenDates, rawQuery } = clickhouse;
const website = await cache.fetchWebsite(websiteId);
const params = [websiteId, website?.revId || 0];
- const { pageviewQuery, sessionQuery } = parseFilters(null, filters, params);
+ const { filterQuery } = parseFilters(filters, params);
return rawQuery(
- `select ${field} x, count(*) y
+ `select ${field} x, count(distinct session_id) y
from event as x
where website_id = $1
and rev_id = $2
and event_name = ''
and ${getBetweenDates('created_at', startDate, endDate)}
- ${pageviewQuery}
- ${sessionQuery}
+ ${filterQuery}
group by x
order by y desc`,
params,
diff --git a/queries/analytics/stats/getActiveVisitors.js b/queries/analytics/stats/getActiveVisitors.ts
similarity index 83%
rename from queries/analytics/stats/getActiveVisitors.js
rename to queries/analytics/stats/getActiveVisitors.ts
index c7592e5b..0b07574d 100644
--- a/queries/analytics/stats/getActiveVisitors.js
+++ b/queries/analytics/stats/getActiveVisitors.ts
@@ -3,14 +3,14 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
-export async function getActiveVisitors(...args) {
+export async function getActiveVisitors(...args: [websiteId: string]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
-async function relationalQuery(websiteId) {
+async function relationalQuery(websiteId: string) {
const date = subMinutes(new Date(), 5);
const params = [date];
@@ -25,7 +25,7 @@ async function relationalQuery(websiteId) {
);
}
-async function clickhouseQuery(websiteId) {
+async function clickhouseQuery(websiteId: string) {
const { rawQuery, getDateFormat } = clickhouse;
const params = [websiteId];
diff --git a/queries/analytics/stats/getRealtimeData.js b/queries/analytics/stats/getRealtimeData.ts
similarity index 100%
rename from queries/analytics/stats/getRealtimeData.js
rename to queries/analytics/stats/getRealtimeData.ts
diff --git a/queries/analytics/stats/getWebsiteStats.js b/queries/analytics/stats/getWebsiteStats.ts
similarity index 70%
rename from queries/analytics/stats/getWebsiteStats.js
rename to queries/analytics/stats/getWebsiteStats.ts
index 002d8a9c..bf5cdd96 100644
--- a/queries/analytics/stats/getWebsiteStats.js
+++ b/queries/analytics/stats/getWebsiteStats.ts
@@ -3,22 +3,23 @@ import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import cache from 'lib/cache';
-export async function getWebsiteStats(...args) {
+export async function getWebsiteStats(
+ ...args: [websiteId: string, data: { startDate: Date; endDate: Date; filters: object }]
+) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
-async function relationalQuery(websiteId, { start_at, end_at, filters = {} }) {
+async function relationalQuery(
+ websiteId: string,
+ data: { startDate: Date; endDate: Date; filters: object },
+) {
+ const { startDate, endDate, filters = {} } = data;
const { getDateQuery, getTimestampInterval, parseFilters, rawQuery } = prisma;
- const params = [start_at, end_at];
- const { pageviewQuery, sessionQuery, joinSession } = parseFilters(
- 'pageview',
- null,
- filters,
- params,
- );
+ const params = [startDate, endDate];
+ const { filterQuery, joinSession } = parseFilters(filters, params);
return rawQuery(
`select sum(t.c) as "pageviews",
@@ -36,19 +37,22 @@ async function relationalQuery(websiteId, { start_at, end_at, filters = {} }) {
${joinSession}
where website.website_id='${websiteId}'
and pageview.created_at between $1 and $2
- ${pageviewQuery}
- ${sessionQuery}
+ ${filterQuery}
group by 1, 2
) t`,
params,
);
}
-async function clickhouseQuery(websiteId, { start_at, end_at, filters = {} }) {
+async function clickhouseQuery(
+ websiteId: string,
+ data: { startDate: Date; endDate: Date; filters: object },
+) {
+ const { startDate, endDate, filters = {} } = data;
const { rawQuery, getDateQuery, getBetweenDates, parseFilters } = clickhouse;
const website = await cache.fetchWebsite(websiteId);
const params = [websiteId, website?.revId || 0];
- const { pageviewQuery, sessionQuery } = parseFilters(null, filters, params);
+ const { filterQuery } = parseFilters(filters, params);
return rawQuery(
`select
@@ -66,9 +70,8 @@ async function clickhouseQuery(websiteId, { start_at, end_at, filters = {} }) {
where event_name = ''
and website_id = $1
and rev_id = $2
- and ${getBetweenDates('created_at', start_at, end_at)}
- ${pageviewQuery}
- ${sessionQuery}
+ and ${getBetweenDates('created_at', startDate, endDate)}
+ ${filterQuery}
group by session_id, time_series
) t;`,
params,
diff --git a/queries/index.js b/queries/index.js
index 4cdcedd9..2d1931ee 100644
--- a/queries/index.js
+++ b/queries/index.js
@@ -1,21 +1,12 @@
-export * from './admin/user/createUser';
-export * from './admin/user/deleteUser';
-export * from './admin/user/getUser';
-export * from './admin/user/getUsers';
-export * from './admin/user/updateUser';
-export * from './admin/website/createWebsite';
-export * from './admin/website/deleteWebsite';
-export * from './admin/website/getAllWebsites';
-export * from './admin/website/getUserWebsites';
-export * from './admin/website/getWebsite';
-export * from './admin/website/resetWebsite';
-export * from './admin/website/updateWebsite';
+export * from './admin/team';
+export * from './admin/teamUser';
+export * from './admin/user';
+export * from './admin/website';
export * from './analytics/event/getEventMetrics';
export * from './analytics/event/getEvents';
export * from './analytics/event/getEventData';
export * from './analytics/event/saveEvent';
export * from './analytics/pageview/getPageviewMetrics';
-export * from './analytics/pageview/getPageviewParams';
export * from './analytics/pageview/getPageviews';
export * from './analytics/pageview/getPageviewStats';
export * from './analytics/pageview/savePageView';
diff --git a/styles/bootstrap-grid.css b/styles/bootstrap-grid.css
deleted file mode 100644
index 8358a0fd..00000000
--- a/styles/bootstrap-grid.css
+++ /dev/null
@@ -1,3981 +0,0 @@
-/*!
- * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)
- * Copyright 2011-2020 The Bootstrap Authors
- * Copyright 2011-2020 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-html {
- box-sizing: border-box;
- -ms-overflow-style: scrollbar;
-}
-
-*,
-*::before,
-*::after {
- box-sizing: inherit;
-}
-
-.container {
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
- margin-right: auto;
- margin-left: auto;
-}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
-
-.container-fluid,
-.container-sm,
-.container-md,
-.container-lg,
-.container-xl {
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
- margin-right: auto;
- margin-left: auto;
-}
-
-@media (min-width: 576px) {
- .container,
- .container-sm {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container,
- .container-sm,
- .container-md {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container,
- .container-sm,
- .container-md,
- .container-lg {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container,
- .container-sm,
- .container-md,
- .container-lg,
- .container-xl {
- max-width: 1140px;
- }
-}
-
-.row {
- display: -ms-flexbox;
- display: flex;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap;
- margin-right: -15px;
- margin-left: -15px;
-}
-
-.no-gutters {
- margin-right: 0;
- margin-left: 0;
-}
-
-.no-gutters > .col,
-.no-gutters > [class*='col-'] {
- padding-right: 0;
- padding-left: 0;
-}
-
-.col-1,
-.col-2,
-.col-3,
-.col-4,
-.col-5,
-.col-6,
-.col-7,
-.col-8,
-.col-9,
-.col-10,
-.col-11,
-.col-12,
-.col,
-.col-auto,
-.col-sm-1,
-.col-sm-2,
-.col-sm-3,
-.col-sm-4,
-.col-sm-5,
-.col-sm-6,
-.col-sm-7,
-.col-sm-8,
-.col-sm-9,
-.col-sm-10,
-.col-sm-11,
-.col-sm-12,
-.col-sm,
-.col-sm-auto,
-.col-md-1,
-.col-md-2,
-.col-md-3,
-.col-md-4,
-.col-md-5,
-.col-md-6,
-.col-md-7,
-.col-md-8,
-.col-md-9,
-.col-md-10,
-.col-md-11,
-.col-md-12,
-.col-md,
-.col-md-auto,
-.col-lg-1,
-.col-lg-2,
-.col-lg-3,
-.col-lg-4,
-.col-lg-5,
-.col-lg-6,
-.col-lg-7,
-.col-lg-8,
-.col-lg-9,
-.col-lg-10,
-.col-lg-11,
-.col-lg-12,
-.col-lg,
-.col-lg-auto,
-.col-xl-1,
-.col-xl-2,
-.col-xl-3,
-.col-xl-4,
-.col-xl-5,
-.col-xl-6,
-.col-xl-7,
-.col-xl-8,
-.col-xl-9,
-.col-xl-10,
-.col-xl-11,
-.col-xl-12,
-.col-xl,
-.col-xl-auto {
- position: relative;
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
-}
-
-.col {
- -ms-flex-preferred-size: 0;
- flex-basis: 0;
- -ms-flex-positive: 1;
- flex-grow: 1;
- min-width: 0;
- max-width: 100%;
-}
-
-.row-cols-1 > * {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
-}
-
-.row-cols-2 > * {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
-}
-
-.row-cols-3 > * {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
-}
-
-.row-cols-4 > * {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
-}
-
-.row-cols-5 > * {
- -ms-flex: 0 0 20%;
- flex: 0 0 20%;
- max-width: 20%;
-}
-
-.row-cols-6 > * {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
-}
-
-.col-auto {
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- width: auto;
- max-width: 100%;
-}
-
-.col-1 {
- -ms-flex: 0 0 8.333333%;
- flex: 0 0 8.333333%;
- max-width: 8.333333%;
-}
-
-.col-2 {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
-}
-
-.col-3 {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
-}
-
-.col-4 {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
-}
-
-.col-5 {
- -ms-flex: 0 0 41.666667%;
- flex: 0 0 41.666667%;
- max-width: 41.666667%;
-}
-
-.col-6 {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
-}
-
-.col-7 {
- -ms-flex: 0 0 58.333333%;
- flex: 0 0 58.333333%;
- max-width: 58.333333%;
-}
-
-.col-8 {
- -ms-flex: 0 0 66.666667%;
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
-}
-
-.col-9 {
- -ms-flex: 0 0 75%;
- flex: 0 0 75%;
- max-width: 75%;
-}
-
-.col-10 {
- -ms-flex: 0 0 83.333333%;
- flex: 0 0 83.333333%;
- max-width: 83.333333%;
-}
-
-.col-11 {
- -ms-flex: 0 0 91.666667%;
- flex: 0 0 91.666667%;
- max-width: 91.666667%;
-}
-
-.col-12 {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
-}
-
-.order-first {
- -ms-flex-order: -1;
- order: -1;
-}
-
-.order-last {
- -ms-flex-order: 13;
- order: 13;
-}
-
-.order-0 {
- -ms-flex-order: 0;
- order: 0;
-}
-
-.order-1 {
- -ms-flex-order: 1;
- order: 1;
-}
-
-.order-2 {
- -ms-flex-order: 2;
- order: 2;
-}
-
-.order-3 {
- -ms-flex-order: 3;
- order: 3;
-}
-
-.order-4 {
- -ms-flex-order: 4;
- order: 4;
-}
-
-.order-5 {
- -ms-flex-order: 5;
- order: 5;
-}
-
-.order-6 {
- -ms-flex-order: 6;
- order: 6;
-}
-
-.order-7 {
- -ms-flex-order: 7;
- order: 7;
-}
-
-.order-8 {
- -ms-flex-order: 8;
- order: 8;
-}
-
-.order-9 {
- -ms-flex-order: 9;
- order: 9;
-}
-
-.order-10 {
- -ms-flex-order: 10;
- order: 10;
-}
-
-.order-11 {
- -ms-flex-order: 11;
- order: 11;
-}
-
-.order-12 {
- -ms-flex-order: 12;
- order: 12;
-}
-
-.offset-1 {
- margin-left: 8.333333%;
-}
-
-.offset-2 {
- margin-left: 16.666667%;
-}
-
-.offset-3 {
- margin-left: 25%;
-}
-
-.offset-4 {
- margin-left: 33.333333%;
-}
-
-.offset-5 {
- margin-left: 41.666667%;
-}
-
-.offset-6 {
- margin-left: 50%;
-}
-
-.offset-7 {
- margin-left: 58.333333%;
-}
-
-.offset-8 {
- margin-left: 66.666667%;
-}
-
-.offset-9 {
- margin-left: 75%;
-}
-
-.offset-10 {
- margin-left: 83.333333%;
-}
-
-.offset-11 {
- margin-left: 91.666667%;
-}
-
-@media (min-width: 576px) {
- .col-sm {
- -ms-flex-preferred-size: 0;
- flex-basis: 0;
- -ms-flex-positive: 1;
- flex-grow: 1;
- min-width: 0;
- max-width: 100%;
- }
- .row-cols-sm-1 > * {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .row-cols-sm-2 > * {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .row-cols-sm-3 > * {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .row-cols-sm-4 > * {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .row-cols-sm-5 > * {
- -ms-flex: 0 0 20%;
- flex: 0 0 20%;
- max-width: 20%;
- }
- .row-cols-sm-6 > * {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-sm-auto {
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- width: auto;
- max-width: 100%;
- }
- .col-sm-1 {
- -ms-flex: 0 0 8.333333%;
- flex: 0 0 8.333333%;
- max-width: 8.333333%;
- }
- .col-sm-2 {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-sm-3 {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .col-sm-4 {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .col-sm-5 {
- -ms-flex: 0 0 41.666667%;
- flex: 0 0 41.666667%;
- max-width: 41.666667%;
- }
- .col-sm-6 {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .col-sm-7 {
- -ms-flex: 0 0 58.333333%;
- flex: 0 0 58.333333%;
- max-width: 58.333333%;
- }
- .col-sm-8 {
- -ms-flex: 0 0 66.666667%;
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
- }
- .col-sm-9 {
- -ms-flex: 0 0 75%;
- flex: 0 0 75%;
- max-width: 75%;
- }
- .col-sm-10 {
- -ms-flex: 0 0 83.333333%;
- flex: 0 0 83.333333%;
- max-width: 83.333333%;
- }
- .col-sm-11 {
- -ms-flex: 0 0 91.666667%;
- flex: 0 0 91.666667%;
- max-width: 91.666667%;
- }
- .col-sm-12 {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .order-sm-first {
- -ms-flex-order: -1;
- order: -1;
- }
- .order-sm-last {
- -ms-flex-order: 13;
- order: 13;
- }
- .order-sm-0 {
- -ms-flex-order: 0;
- order: 0;
- }
- .order-sm-1 {
- -ms-flex-order: 1;
- order: 1;
- }
- .order-sm-2 {
- -ms-flex-order: 2;
- order: 2;
- }
- .order-sm-3 {
- -ms-flex-order: 3;
- order: 3;
- }
- .order-sm-4 {
- -ms-flex-order: 4;
- order: 4;
- }
- .order-sm-5 {
- -ms-flex-order: 5;
- order: 5;
- }
- .order-sm-6 {
- -ms-flex-order: 6;
- order: 6;
- }
- .order-sm-7 {
- -ms-flex-order: 7;
- order: 7;
- }
- .order-sm-8 {
- -ms-flex-order: 8;
- order: 8;
- }
- .order-sm-9 {
- -ms-flex-order: 9;
- order: 9;
- }
- .order-sm-10 {
- -ms-flex-order: 10;
- order: 10;
- }
- .order-sm-11 {
- -ms-flex-order: 11;
- order: 11;
- }
- .order-sm-12 {
- -ms-flex-order: 12;
- order: 12;
- }
- .offset-sm-0 {
- margin-left: 0;
- }
- .offset-sm-1 {
- margin-left: 8.333333%;
- }
- .offset-sm-2 {
- margin-left: 16.666667%;
- }
- .offset-sm-3 {
- margin-left: 25%;
- }
- .offset-sm-4 {
- margin-left: 33.333333%;
- }
- .offset-sm-5 {
- margin-left: 41.666667%;
- }
- .offset-sm-6 {
- margin-left: 50%;
- }
- .offset-sm-7 {
- margin-left: 58.333333%;
- }
- .offset-sm-8 {
- margin-left: 66.666667%;
- }
- .offset-sm-9 {
- margin-left: 75%;
- }
- .offset-sm-10 {
- margin-left: 83.333333%;
- }
- .offset-sm-11 {
- margin-left: 91.666667%;
- }
-}
-
-@media (min-width: 768px) {
- .col-md {
- -ms-flex-preferred-size: 0;
- flex-basis: 0;
- -ms-flex-positive: 1;
- flex-grow: 1;
- min-width: 0;
- max-width: 100%;
- }
- .row-cols-md-1 > * {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .row-cols-md-2 > * {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .row-cols-md-3 > * {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .row-cols-md-4 > * {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .row-cols-md-5 > * {
- -ms-flex: 0 0 20%;
- flex: 0 0 20%;
- max-width: 20%;
- }
- .row-cols-md-6 > * {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-md-auto {
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- width: auto;
- max-width: 100%;
- }
- .col-md-1 {
- -ms-flex: 0 0 8.333333%;
- flex: 0 0 8.333333%;
- max-width: 8.333333%;
- }
- .col-md-2 {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-md-3 {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .col-md-4 {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .col-md-5 {
- -ms-flex: 0 0 41.666667%;
- flex: 0 0 41.666667%;
- max-width: 41.666667%;
- }
- .col-md-6 {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .col-md-7 {
- -ms-flex: 0 0 58.333333%;
- flex: 0 0 58.333333%;
- max-width: 58.333333%;
- }
- .col-md-8 {
- -ms-flex: 0 0 66.666667%;
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
- }
- .col-md-9 {
- -ms-flex: 0 0 75%;
- flex: 0 0 75%;
- max-width: 75%;
- }
- .col-md-10 {
- -ms-flex: 0 0 83.333333%;
- flex: 0 0 83.333333%;
- max-width: 83.333333%;
- }
- .col-md-11 {
- -ms-flex: 0 0 91.666667%;
- flex: 0 0 91.666667%;
- max-width: 91.666667%;
- }
- .col-md-12 {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .order-md-first {
- -ms-flex-order: -1;
- order: -1;
- }
- .order-md-last {
- -ms-flex-order: 13;
- order: 13;
- }
- .order-md-0 {
- -ms-flex-order: 0;
- order: 0;
- }
- .order-md-1 {
- -ms-flex-order: 1;
- order: 1;
- }
- .order-md-2 {
- -ms-flex-order: 2;
- order: 2;
- }
- .order-md-3 {
- -ms-flex-order: 3;
- order: 3;
- }
- .order-md-4 {
- -ms-flex-order: 4;
- order: 4;
- }
- .order-md-5 {
- -ms-flex-order: 5;
- order: 5;
- }
- .order-md-6 {
- -ms-flex-order: 6;
- order: 6;
- }
- .order-md-7 {
- -ms-flex-order: 7;
- order: 7;
- }
- .order-md-8 {
- -ms-flex-order: 8;
- order: 8;
- }
- .order-md-9 {
- -ms-flex-order: 9;
- order: 9;
- }
- .order-md-10 {
- -ms-flex-order: 10;
- order: 10;
- }
- .order-md-11 {
- -ms-flex-order: 11;
- order: 11;
- }
- .order-md-12 {
- -ms-flex-order: 12;
- order: 12;
- }
- .offset-md-0 {
- margin-left: 0;
- }
- .offset-md-1 {
- margin-left: 8.333333%;
- }
- .offset-md-2 {
- margin-left: 16.666667%;
- }
- .offset-md-3 {
- margin-left: 25%;
- }
- .offset-md-4 {
- margin-left: 33.333333%;
- }
- .offset-md-5 {
- margin-left: 41.666667%;
- }
- .offset-md-6 {
- margin-left: 50%;
- }
- .offset-md-7 {
- margin-left: 58.333333%;
- }
- .offset-md-8 {
- margin-left: 66.666667%;
- }
- .offset-md-9 {
- margin-left: 75%;
- }
- .offset-md-10 {
- margin-left: 83.333333%;
- }
- .offset-md-11 {
- margin-left: 91.666667%;
- }
-}
-
-@media (min-width: 992px) {
- .col-lg {
- -ms-flex-preferred-size: 0;
- flex-basis: 0;
- -ms-flex-positive: 1;
- flex-grow: 1;
- min-width: 0;
- max-width: 100%;
- }
- .row-cols-lg-1 > * {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .row-cols-lg-2 > * {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .row-cols-lg-3 > * {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .row-cols-lg-4 > * {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .row-cols-lg-5 > * {
- -ms-flex: 0 0 20%;
- flex: 0 0 20%;
- max-width: 20%;
- }
- .row-cols-lg-6 > * {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-lg-auto {
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- width: auto;
- max-width: 100%;
- }
- .col-lg-1 {
- -ms-flex: 0 0 8.333333%;
- flex: 0 0 8.333333%;
- max-width: 8.333333%;
- }
- .col-lg-2 {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-lg-3 {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .col-lg-4 {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .col-lg-5 {
- -ms-flex: 0 0 41.666667%;
- flex: 0 0 41.666667%;
- max-width: 41.666667%;
- }
- .col-lg-6 {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .col-lg-7 {
- -ms-flex: 0 0 58.333333%;
- flex: 0 0 58.333333%;
- max-width: 58.333333%;
- }
- .col-lg-8 {
- -ms-flex: 0 0 66.666667%;
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
- }
- .col-lg-9 {
- -ms-flex: 0 0 75%;
- flex: 0 0 75%;
- max-width: 75%;
- }
- .col-lg-10 {
- -ms-flex: 0 0 83.333333%;
- flex: 0 0 83.333333%;
- max-width: 83.333333%;
- }
- .col-lg-11 {
- -ms-flex: 0 0 91.666667%;
- flex: 0 0 91.666667%;
- max-width: 91.666667%;
- }
- .col-lg-12 {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .order-lg-first {
- -ms-flex-order: -1;
- order: -1;
- }
- .order-lg-last {
- -ms-flex-order: 13;
- order: 13;
- }
- .order-lg-0 {
- -ms-flex-order: 0;
- order: 0;
- }
- .order-lg-1 {
- -ms-flex-order: 1;
- order: 1;
- }
- .order-lg-2 {
- -ms-flex-order: 2;
- order: 2;
- }
- .order-lg-3 {
- -ms-flex-order: 3;
- order: 3;
- }
- .order-lg-4 {
- -ms-flex-order: 4;
- order: 4;
- }
- .order-lg-5 {
- -ms-flex-order: 5;
- order: 5;
- }
- .order-lg-6 {
- -ms-flex-order: 6;
- order: 6;
- }
- .order-lg-7 {
- -ms-flex-order: 7;
- order: 7;
- }
- .order-lg-8 {
- -ms-flex-order: 8;
- order: 8;
- }
- .order-lg-9 {
- -ms-flex-order: 9;
- order: 9;
- }
- .order-lg-10 {
- -ms-flex-order: 10;
- order: 10;
- }
- .order-lg-11 {
- -ms-flex-order: 11;
- order: 11;
- }
- .order-lg-12 {
- -ms-flex-order: 12;
- order: 12;
- }
- .offset-lg-0 {
- margin-left: 0;
- }
- .offset-lg-1 {
- margin-left: 8.333333%;
- }
- .offset-lg-2 {
- margin-left: 16.666667%;
- }
- .offset-lg-3 {
- margin-left: 25%;
- }
- .offset-lg-4 {
- margin-left: 33.333333%;
- }
- .offset-lg-5 {
- margin-left: 41.666667%;
- }
- .offset-lg-6 {
- margin-left: 50%;
- }
- .offset-lg-7 {
- margin-left: 58.333333%;
- }
- .offset-lg-8 {
- margin-left: 66.666667%;
- }
- .offset-lg-9 {
- margin-left: 75%;
- }
- .offset-lg-10 {
- margin-left: 83.333333%;
- }
- .offset-lg-11 {
- margin-left: 91.666667%;
- }
-}
-
-@media (min-width: 1200px) {
- .col-xl {
- -ms-flex-preferred-size: 0;
- flex-basis: 0;
- -ms-flex-positive: 1;
- flex-grow: 1;
- min-width: 0;
- max-width: 100%;
- }
- .row-cols-xl-1 > * {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .row-cols-xl-2 > * {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .row-cols-xl-3 > * {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .row-cols-xl-4 > * {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .row-cols-xl-5 > * {
- -ms-flex: 0 0 20%;
- flex: 0 0 20%;
- max-width: 20%;
- }
- .row-cols-xl-6 > * {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-xl-auto {
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- width: auto;
- max-width: 100%;
- }
- .col-xl-1 {
- -ms-flex: 0 0 8.333333%;
- flex: 0 0 8.333333%;
- max-width: 8.333333%;
- }
- .col-xl-2 {
- -ms-flex: 0 0 16.666667%;
- flex: 0 0 16.666667%;
- max-width: 16.666667%;
- }
- .col-xl-3 {
- -ms-flex: 0 0 25%;
- flex: 0 0 25%;
- max-width: 25%;
- }
- .col-xl-4 {
- -ms-flex: 0 0 33.333333%;
- flex: 0 0 33.333333%;
- max-width: 33.333333%;
- }
- .col-xl-5 {
- -ms-flex: 0 0 41.666667%;
- flex: 0 0 41.666667%;
- max-width: 41.666667%;
- }
- .col-xl-6 {
- -ms-flex: 0 0 50%;
- flex: 0 0 50%;
- max-width: 50%;
- }
- .col-xl-7 {
- -ms-flex: 0 0 58.333333%;
- flex: 0 0 58.333333%;
- max-width: 58.333333%;
- }
- .col-xl-8 {
- -ms-flex: 0 0 66.666667%;
- flex: 0 0 66.666667%;
- max-width: 66.666667%;
- }
- .col-xl-9 {
- -ms-flex: 0 0 75%;
- flex: 0 0 75%;
- max-width: 75%;
- }
- .col-xl-10 {
- -ms-flex: 0 0 83.333333%;
- flex: 0 0 83.333333%;
- max-width: 83.333333%;
- }
- .col-xl-11 {
- -ms-flex: 0 0 91.666667%;
- flex: 0 0 91.666667%;
- max-width: 91.666667%;
- }
- .col-xl-12 {
- -ms-flex: 0 0 100%;
- flex: 0 0 100%;
- max-width: 100%;
- }
- .order-xl-first {
- -ms-flex-order: -1;
- order: -1;
- }
- .order-xl-last {
- -ms-flex-order: 13;
- order: 13;
- }
- .order-xl-0 {
- -ms-flex-order: 0;
- order: 0;
- }
- .order-xl-1 {
- -ms-flex-order: 1;
- order: 1;
- }
- .order-xl-2 {
- -ms-flex-order: 2;
- order: 2;
- }
- .order-xl-3 {
- -ms-flex-order: 3;
- order: 3;
- }
- .order-xl-4 {
- -ms-flex-order: 4;
- order: 4;
- }
- .order-xl-5 {
- -ms-flex-order: 5;
- order: 5;
- }
- .order-xl-6 {
- -ms-flex-order: 6;
- order: 6;
- }
- .order-xl-7 {
- -ms-flex-order: 7;
- order: 7;
- }
- .order-xl-8 {
- -ms-flex-order: 8;
- order: 8;
- }
- .order-xl-9 {
- -ms-flex-order: 9;
- order: 9;
- }
- .order-xl-10 {
- -ms-flex-order: 10;
- order: 10;
- }
- .order-xl-11 {
- -ms-flex-order: 11;
- order: 11;
- }
- .order-xl-12 {
- -ms-flex-order: 12;
- order: 12;
- }
- .offset-xl-0 {
- margin-left: 0;
- }
- .offset-xl-1 {
- margin-left: 8.333333%;
- }
- .offset-xl-2 {
- margin-left: 16.666667%;
- }
- .offset-xl-3 {
- margin-left: 25%;
- }
- .offset-xl-4 {
- margin-left: 33.333333%;
- }
- .offset-xl-5 {
- margin-left: 41.666667%;
- }
- .offset-xl-6 {
- margin-left: 50%;
- }
- .offset-xl-7 {
- margin-left: 58.333333%;
- }
- .offset-xl-8 {
- margin-left: 66.666667%;
- }
- .offset-xl-9 {
- margin-left: 75%;
- }
- .offset-xl-10 {
- margin-left: 83.333333%;
- }
- .offset-xl-11 {
- margin-left: 91.666667%;
- }
-}
-
-.d-none {
- display: none !important;
-}
-
-.d-inline {
- display: inline !important;
-}
-
-.d-inline-block {
- display: inline-block !important;
-}
-
-.d-block {
- display: block !important;
-}
-
-.d-table {
- display: table !important;
-}
-
-.d-table-row {
- display: table-row !important;
-}
-
-.d-table-cell {
- display: table-cell !important;
-}
-
-.d-flex {
- display: -ms-flexbox !important;
- display: flex !important;
-}
-
-.d-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
-}
-
-@media (min-width: 576px) {
- .d-sm-none {
- display: none !important;
- }
- .d-sm-inline {
- display: inline !important;
- }
- .d-sm-inline-block {
- display: inline-block !important;
- }
- .d-sm-block {
- display: block !important;
- }
- .d-sm-table {
- display: table !important;
- }
- .d-sm-table-row {
- display: table-row !important;
- }
- .d-sm-table-cell {
- display: table-cell !important;
- }
- .d-sm-flex {
- display: -ms-flexbox !important;
- display: flex !important;
- }
- .d-sm-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
- }
-}
-
-@media (min-width: 768px) {
- .d-md-none {
- display: none !important;
- }
- .d-md-inline {
- display: inline !important;
- }
- .d-md-inline-block {
- display: inline-block !important;
- }
- .d-md-block {
- display: block !important;
- }
- .d-md-table {
- display: table !important;
- }
- .d-md-table-row {
- display: table-row !important;
- }
- .d-md-table-cell {
- display: table-cell !important;
- }
- .d-md-flex {
- display: -ms-flexbox !important;
- display: flex !important;
- }
- .d-md-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
- }
-}
-
-@media (min-width: 992px) {
- .d-lg-none {
- display: none !important;
- }
- .d-lg-inline {
- display: inline !important;
- }
- .d-lg-inline-block {
- display: inline-block !important;
- }
- .d-lg-block {
- display: block !important;
- }
- .d-lg-table {
- display: table !important;
- }
- .d-lg-table-row {
- display: table-row !important;
- }
- .d-lg-table-cell {
- display: table-cell !important;
- }
- .d-lg-flex {
- display: -ms-flexbox !important;
- display: flex !important;
- }
- .d-lg-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
- }
-}
-
-@media (min-width: 1200px) {
- .d-xl-none {
- display: none !important;
- }
- .d-xl-inline {
- display: inline !important;
- }
- .d-xl-inline-block {
- display: inline-block !important;
- }
- .d-xl-block {
- display: block !important;
- }
- .d-xl-table {
- display: table !important;
- }
- .d-xl-table-row {
- display: table-row !important;
- }
- .d-xl-table-cell {
- display: table-cell !important;
- }
- .d-xl-flex {
- display: -ms-flexbox !important;
- display: flex !important;
- }
- .d-xl-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
- }
-}
-
-@media print {
- .d-print-none {
- display: none !important;
- }
- .d-print-inline {
- display: inline !important;
- }
- .d-print-inline-block {
- display: inline-block !important;
- }
- .d-print-block {
- display: block !important;
- }
- .d-print-table {
- display: table !important;
- }
- .d-print-table-row {
- display: table-row !important;
- }
- .d-print-table-cell {
- display: table-cell !important;
- }
- .d-print-flex {
- display: -ms-flexbox !important;
- display: flex !important;
- }
- .d-print-inline-flex {
- display: -ms-inline-flexbox !important;
- display: inline-flex !important;
- }
-}
-
-.flex-row {
- -ms-flex-direction: row !important;
- flex-direction: row !important;
-}
-
-.flex-column {
- -ms-flex-direction: column !important;
- flex-direction: column !important;
-}
-
-.flex-row-reverse {
- -ms-flex-direction: row-reverse !important;
- flex-direction: row-reverse !important;
-}
-
-.flex-column-reverse {
- -ms-flex-direction: column-reverse !important;
- flex-direction: column-reverse !important;
-}
-
-.flex-wrap {
- -ms-flex-wrap: wrap !important;
- flex-wrap: wrap !important;
-}
-
-.flex-nowrap {
- -ms-flex-wrap: nowrap !important;
- flex-wrap: nowrap !important;
-}
-
-.flex-wrap-reverse {
- -ms-flex-wrap: wrap-reverse !important;
- flex-wrap: wrap-reverse !important;
-}
-
-.flex-fill {
- -ms-flex: 1 1 auto !important;
- flex: 1 1 auto !important;
-}
-
-.flex-grow-0 {
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
-}
-
-.flex-grow-1 {
- -ms-flex-positive: 1 !important;
- flex-grow: 1 !important;
-}
-
-.flex-shrink-0 {
- -ms-flex-negative: 0 !important;
- flex-shrink: 0 !important;
-}
-
-.flex-shrink-1 {
- -ms-flex-negative: 1 !important;
- flex-shrink: 1 !important;
-}
-
-.justify-content-start {
- -ms-flex-pack: start !important;
- justify-content: flex-start !important;
-}
-
-.justify-content-end {
- -ms-flex-pack: end !important;
- justify-content: flex-end !important;
-}
-
-.justify-content-center {
- -ms-flex-pack: center !important;
- justify-content: center !important;
-}
-
-.justify-content-between {
- -ms-flex-pack: justify !important;
- justify-content: space-between !important;
-}
-
-.justify-content-around {
- -ms-flex-pack: distribute !important;
- justify-content: space-around !important;
-}
-
-.align-items-start {
- -ms-flex-align: start !important;
- align-items: flex-start !important;
-}
-
-.align-items-end {
- -ms-flex-align: end !important;
- align-items: flex-end !important;
-}
-
-.align-items-center {
- -ms-flex-align: center !important;
- align-items: center !important;
-}
-
-.align-items-baseline {
- -ms-flex-align: baseline !important;
- align-items: baseline !important;
-}
-
-.align-items-stretch {
- -ms-flex-align: stretch !important;
- align-items: stretch !important;
-}
-
-.align-content-start {
- -ms-flex-line-pack: start !important;
- align-content: flex-start !important;
-}
-
-.align-content-end {
- -ms-flex-line-pack: end !important;
- align-content: flex-end !important;
-}
-
-.align-content-center {
- -ms-flex-line-pack: center !important;
- align-content: center !important;
-}
-
-.align-content-between {
- -ms-flex-line-pack: justify !important;
- align-content: space-between !important;
-}
-
-.align-content-around {
- -ms-flex-line-pack: distribute !important;
- align-content: space-around !important;
-}
-
-.align-content-stretch {
- -ms-flex-line-pack: stretch !important;
- align-content: stretch !important;
-}
-
-.align-self-auto {
- -ms-flex-item-align: auto !important;
- align-self: auto !important;
-}
-
-.align-self-start {
- -ms-flex-item-align: start !important;
- align-self: flex-start !important;
-}
-
-.align-self-end {
- -ms-flex-item-align: end !important;
- align-self: flex-end !important;
-}
-
-.align-self-center {
- -ms-flex-item-align: center !important;
- align-self: center !important;
-}
-
-.align-self-baseline {
- -ms-flex-item-align: baseline !important;
- align-self: baseline !important;
-}
-
-.align-self-stretch {
- -ms-flex-item-align: stretch !important;
- align-self: stretch !important;
-}
-
-@media (min-width: 576px) {
- .flex-sm-row {
- -ms-flex-direction: row !important;
- flex-direction: row !important;
- }
- .flex-sm-column {
- -ms-flex-direction: column !important;
- flex-direction: column !important;
- }
- .flex-sm-row-reverse {
- -ms-flex-direction: row-reverse !important;
- flex-direction: row-reverse !important;
- }
- .flex-sm-column-reverse {
- -ms-flex-direction: column-reverse !important;
- flex-direction: column-reverse !important;
- }
- .flex-sm-wrap {
- -ms-flex-wrap: wrap !important;
- flex-wrap: wrap !important;
- }
- .flex-sm-nowrap {
- -ms-flex-wrap: nowrap !important;
- flex-wrap: nowrap !important;
- }
- .flex-sm-wrap-reverse {
- -ms-flex-wrap: wrap-reverse !important;
- flex-wrap: wrap-reverse !important;
- }
- .flex-sm-fill {
- -ms-flex: 1 1 auto !important;
- flex: 1 1 auto !important;
- }
- .flex-sm-grow-0 {
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- }
- .flex-sm-grow-1 {
- -ms-flex-positive: 1 !important;
- flex-grow: 1 !important;
- }
- .flex-sm-shrink-0 {
- -ms-flex-negative: 0 !important;
- flex-shrink: 0 !important;
- }
- .flex-sm-shrink-1 {
- -ms-flex-negative: 1 !important;
- flex-shrink: 1 !important;
- }
- .justify-content-sm-start {
- -ms-flex-pack: start !important;
- justify-content: flex-start !important;
- }
- .justify-content-sm-end {
- -ms-flex-pack: end !important;
- justify-content: flex-end !important;
- }
- .justify-content-sm-center {
- -ms-flex-pack: center !important;
- justify-content: center !important;
- }
- .justify-content-sm-between {
- -ms-flex-pack: justify !important;
- justify-content: space-between !important;
- }
- .justify-content-sm-around {
- -ms-flex-pack: distribute !important;
- justify-content: space-around !important;
- }
- .align-items-sm-start {
- -ms-flex-align: start !important;
- align-items: flex-start !important;
- }
- .align-items-sm-end {
- -ms-flex-align: end !important;
- align-items: flex-end !important;
- }
- .align-items-sm-center {
- -ms-flex-align: center !important;
- align-items: center !important;
- }
- .align-items-sm-baseline {
- -ms-flex-align: baseline !important;
- align-items: baseline !important;
- }
- .align-items-sm-stretch {
- -ms-flex-align: stretch !important;
- align-items: stretch !important;
- }
- .align-content-sm-start {
- -ms-flex-line-pack: start !important;
- align-content: flex-start !important;
- }
- .align-content-sm-end {
- -ms-flex-line-pack: end !important;
- align-content: flex-end !important;
- }
- .align-content-sm-center {
- -ms-flex-line-pack: center !important;
- align-content: center !important;
- }
- .align-content-sm-between {
- -ms-flex-line-pack: justify !important;
- align-content: space-between !important;
- }
- .align-content-sm-around {
- -ms-flex-line-pack: distribute !important;
- align-content: space-around !important;
- }
- .align-content-sm-stretch {
- -ms-flex-line-pack: stretch !important;
- align-content: stretch !important;
- }
- .align-self-sm-auto {
- -ms-flex-item-align: auto !important;
- align-self: auto !important;
- }
- .align-self-sm-start {
- -ms-flex-item-align: start !important;
- align-self: flex-start !important;
- }
- .align-self-sm-end {
- -ms-flex-item-align: end !important;
- align-self: flex-end !important;
- }
- .align-self-sm-center {
- -ms-flex-item-align: center !important;
- align-self: center !important;
- }
- .align-self-sm-baseline {
- -ms-flex-item-align: baseline !important;
- align-self: baseline !important;
- }
- .align-self-sm-stretch {
- -ms-flex-item-align: stretch !important;
- align-self: stretch !important;
- }
-}
-
-@media (min-width: 768px) {
- .flex-md-row {
- -ms-flex-direction: row !important;
- flex-direction: row !important;
- }
- .flex-md-column {
- -ms-flex-direction: column !important;
- flex-direction: column !important;
- }
- .flex-md-row-reverse {
- -ms-flex-direction: row-reverse !important;
- flex-direction: row-reverse !important;
- }
- .flex-md-column-reverse {
- -ms-flex-direction: column-reverse !important;
- flex-direction: column-reverse !important;
- }
- .flex-md-wrap {
- -ms-flex-wrap: wrap !important;
- flex-wrap: wrap !important;
- }
- .flex-md-nowrap {
- -ms-flex-wrap: nowrap !important;
- flex-wrap: nowrap !important;
- }
- .flex-md-wrap-reverse {
- -ms-flex-wrap: wrap-reverse !important;
- flex-wrap: wrap-reverse !important;
- }
- .flex-md-fill {
- -ms-flex: 1 1 auto !important;
- flex: 1 1 auto !important;
- }
- .flex-md-grow-0 {
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- }
- .flex-md-grow-1 {
- -ms-flex-positive: 1 !important;
- flex-grow: 1 !important;
- }
- .flex-md-shrink-0 {
- -ms-flex-negative: 0 !important;
- flex-shrink: 0 !important;
- }
- .flex-md-shrink-1 {
- -ms-flex-negative: 1 !important;
- flex-shrink: 1 !important;
- }
- .justify-content-md-start {
- -ms-flex-pack: start !important;
- justify-content: flex-start !important;
- }
- .justify-content-md-end {
- -ms-flex-pack: end !important;
- justify-content: flex-end !important;
- }
- .justify-content-md-center {
- -ms-flex-pack: center !important;
- justify-content: center !important;
- }
- .justify-content-md-between {
- -ms-flex-pack: justify !important;
- justify-content: space-between !important;
- }
- .justify-content-md-around {
- -ms-flex-pack: distribute !important;
- justify-content: space-around !important;
- }
- .align-items-md-start {
- -ms-flex-align: start !important;
- align-items: flex-start !important;
- }
- .align-items-md-end {
- -ms-flex-align: end !important;
- align-items: flex-end !important;
- }
- .align-items-md-center {
- -ms-flex-align: center !important;
- align-items: center !important;
- }
- .align-items-md-baseline {
- -ms-flex-align: baseline !important;
- align-items: baseline !important;
- }
- .align-items-md-stretch {
- -ms-flex-align: stretch !important;
- align-items: stretch !important;
- }
- .align-content-md-start {
- -ms-flex-line-pack: start !important;
- align-content: flex-start !important;
- }
- .align-content-md-end {
- -ms-flex-line-pack: end !important;
- align-content: flex-end !important;
- }
- .align-content-md-center {
- -ms-flex-line-pack: center !important;
- align-content: center !important;
- }
- .align-content-md-between {
- -ms-flex-line-pack: justify !important;
- align-content: space-between !important;
- }
- .align-content-md-around {
- -ms-flex-line-pack: distribute !important;
- align-content: space-around !important;
- }
- .align-content-md-stretch {
- -ms-flex-line-pack: stretch !important;
- align-content: stretch !important;
- }
- .align-self-md-auto {
- -ms-flex-item-align: auto !important;
- align-self: auto !important;
- }
- .align-self-md-start {
- -ms-flex-item-align: start !important;
- align-self: flex-start !important;
- }
- .align-self-md-end {
- -ms-flex-item-align: end !important;
- align-self: flex-end !important;
- }
- .align-self-md-center {
- -ms-flex-item-align: center !important;
- align-self: center !important;
- }
- .align-self-md-baseline {
- -ms-flex-item-align: baseline !important;
- align-self: baseline !important;
- }
- .align-self-md-stretch {
- -ms-flex-item-align: stretch !important;
- align-self: stretch !important;
- }
-}
-
-@media (min-width: 992px) {
- .flex-lg-row {
- -ms-flex-direction: row !important;
- flex-direction: row !important;
- }
- .flex-lg-column {
- -ms-flex-direction: column !important;
- flex-direction: column !important;
- }
- .flex-lg-row-reverse {
- -ms-flex-direction: row-reverse !important;
- flex-direction: row-reverse !important;
- }
- .flex-lg-column-reverse {
- -ms-flex-direction: column-reverse !important;
- flex-direction: column-reverse !important;
- }
- .flex-lg-wrap {
- -ms-flex-wrap: wrap !important;
- flex-wrap: wrap !important;
- }
- .flex-lg-nowrap {
- -ms-flex-wrap: nowrap !important;
- flex-wrap: nowrap !important;
- }
- .flex-lg-wrap-reverse {
- -ms-flex-wrap: wrap-reverse !important;
- flex-wrap: wrap-reverse !important;
- }
- .flex-lg-fill {
- -ms-flex: 1 1 auto !important;
- flex: 1 1 auto !important;
- }
- .flex-lg-grow-0 {
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- }
- .flex-lg-grow-1 {
- -ms-flex-positive: 1 !important;
- flex-grow: 1 !important;
- }
- .flex-lg-shrink-0 {
- -ms-flex-negative: 0 !important;
- flex-shrink: 0 !important;
- }
- .flex-lg-shrink-1 {
- -ms-flex-negative: 1 !important;
- flex-shrink: 1 !important;
- }
- .justify-content-lg-start {
- -ms-flex-pack: start !important;
- justify-content: flex-start !important;
- }
- .justify-content-lg-end {
- -ms-flex-pack: end !important;
- justify-content: flex-end !important;
- }
- .justify-content-lg-center {
- -ms-flex-pack: center !important;
- justify-content: center !important;
- }
- .justify-content-lg-between {
- -ms-flex-pack: justify !important;
- justify-content: space-between !important;
- }
- .justify-content-lg-around {
- -ms-flex-pack: distribute !important;
- justify-content: space-around !important;
- }
- .align-items-lg-start {
- -ms-flex-align: start !important;
- align-items: flex-start !important;
- }
- .align-items-lg-end {
- -ms-flex-align: end !important;
- align-items: flex-end !important;
- }
- .align-items-lg-center {
- -ms-flex-align: center !important;
- align-items: center !important;
- }
- .align-items-lg-baseline {
- -ms-flex-align: baseline !important;
- align-items: baseline !important;
- }
- .align-items-lg-stretch {
- -ms-flex-align: stretch !important;
- align-items: stretch !important;
- }
- .align-content-lg-start {
- -ms-flex-line-pack: start !important;
- align-content: flex-start !important;
- }
- .align-content-lg-end {
- -ms-flex-line-pack: end !important;
- align-content: flex-end !important;
- }
- .align-content-lg-center {
- -ms-flex-line-pack: center !important;
- align-content: center !important;
- }
- .align-content-lg-between {
- -ms-flex-line-pack: justify !important;
- align-content: space-between !important;
- }
- .align-content-lg-around {
- -ms-flex-line-pack: distribute !important;
- align-content: space-around !important;
- }
- .align-content-lg-stretch {
- -ms-flex-line-pack: stretch !important;
- align-content: stretch !important;
- }
- .align-self-lg-auto {
- -ms-flex-item-align: auto !important;
- align-self: auto !important;
- }
- .align-self-lg-start {
- -ms-flex-item-align: start !important;
- align-self: flex-start !important;
- }
- .align-self-lg-end {
- -ms-flex-item-align: end !important;
- align-self: flex-end !important;
- }
- .align-self-lg-center {
- -ms-flex-item-align: center !important;
- align-self: center !important;
- }
- .align-self-lg-baseline {
- -ms-flex-item-align: baseline !important;
- align-self: baseline !important;
- }
- .align-self-lg-stretch {
- -ms-flex-item-align: stretch !important;
- align-self: stretch !important;
- }
-}
-
-@media (min-width: 1200px) {
- .flex-xl-row {
- -ms-flex-direction: row !important;
- flex-direction: row !important;
- }
- .flex-xl-column {
- -ms-flex-direction: column !important;
- flex-direction: column !important;
- }
- .flex-xl-row-reverse {
- -ms-flex-direction: row-reverse !important;
- flex-direction: row-reverse !important;
- }
- .flex-xl-column-reverse {
- -ms-flex-direction: column-reverse !important;
- flex-direction: column-reverse !important;
- }
- .flex-xl-wrap {
- -ms-flex-wrap: wrap !important;
- flex-wrap: wrap !important;
- }
- .flex-xl-nowrap {
- -ms-flex-wrap: nowrap !important;
- flex-wrap: nowrap !important;
- }
- .flex-xl-wrap-reverse {
- -ms-flex-wrap: wrap-reverse !important;
- flex-wrap: wrap-reverse !important;
- }
- .flex-xl-fill {
- -ms-flex: 1 1 auto !important;
- flex: 1 1 auto !important;
- }
- .flex-xl-grow-0 {
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- }
- .flex-xl-grow-1 {
- -ms-flex-positive: 1 !important;
- flex-grow: 1 !important;
- }
- .flex-xl-shrink-0 {
- -ms-flex-negative: 0 !important;
- flex-shrink: 0 !important;
- }
- .flex-xl-shrink-1 {
- -ms-flex-negative: 1 !important;
- flex-shrink: 1 !important;
- }
- .justify-content-xl-start {
- -ms-flex-pack: start !important;
- justify-content: flex-start !important;
- }
- .justify-content-xl-end {
- -ms-flex-pack: end !important;
- justify-content: flex-end !important;
- }
- .justify-content-xl-center {
- -ms-flex-pack: center !important;
- justify-content: center !important;
- }
- .justify-content-xl-between {
- -ms-flex-pack: justify !important;
- justify-content: space-between !important;
- }
- .justify-content-xl-around {
- -ms-flex-pack: distribute !important;
- justify-content: space-around !important;
- }
- .align-items-xl-start {
- -ms-flex-align: start !important;
- align-items: flex-start !important;
- }
- .align-items-xl-end {
- -ms-flex-align: end !important;
- align-items: flex-end !important;
- }
- .align-items-xl-center {
- -ms-flex-align: center !important;
- align-items: center !important;
- }
- .align-items-xl-baseline {
- -ms-flex-align: baseline !important;
- align-items: baseline !important;
- }
- .align-items-xl-stretch {
- -ms-flex-align: stretch !important;
- align-items: stretch !important;
- }
- .align-content-xl-start {
- -ms-flex-line-pack: start !important;
- align-content: flex-start !important;
- }
- .align-content-xl-end {
- -ms-flex-line-pack: end !important;
- align-content: flex-end !important;
- }
- .align-content-xl-center {
- -ms-flex-line-pack: center !important;
- align-content: center !important;
- }
- .align-content-xl-between {
- -ms-flex-line-pack: justify !important;
- align-content: space-between !important;
- }
- .align-content-xl-around {
- -ms-flex-line-pack: distribute !important;
- align-content: space-around !important;
- }
- .align-content-xl-stretch {
- -ms-flex-line-pack: stretch !important;
- align-content: stretch !important;
- }
- .align-self-xl-auto {
- -ms-flex-item-align: auto !important;
- align-self: auto !important;
- }
- .align-self-xl-start {
- -ms-flex-item-align: start !important;
- align-self: flex-start !important;
- }
- .align-self-xl-end {
- -ms-flex-item-align: end !important;
- align-self: flex-end !important;
- }
- .align-self-xl-center {
- -ms-flex-item-align: center !important;
- align-self: center !important;
- }
- .align-self-xl-baseline {
- -ms-flex-item-align: baseline !important;
- align-self: baseline !important;
- }
- .align-self-xl-stretch {
- -ms-flex-item-align: stretch !important;
- align-self: stretch !important;
- }
-}
-
-.m-0 {
- margin: 0 !important;
-}
-
-.mt-0,
-.my-0 {
- margin-top: 0 !important;
-}
-
-.mr-0,
-.mx-0 {
- margin-right: 0 !important;
-}
-
-.mb-0,
-.my-0 {
- margin-bottom: 0 !important;
-}
-
-.ml-0,
-.mx-0 {
- margin-left: 0 !important;
-}
-
-.m-1 {
- margin: 0.25rem !important;
-}
-
-.mt-1,
-.my-1 {
- margin-top: 0.25rem !important;
-}
-
-.mr-1,
-.mx-1 {
- margin-right: 0.25rem !important;
-}
-
-.mb-1,
-.my-1 {
- margin-bottom: 0.25rem !important;
-}
-
-.ml-1,
-.mx-1 {
- margin-left: 0.25rem !important;
-}
-
-.m-2 {
- margin: 0.5rem !important;
-}
-
-.mt-2,
-.my-2 {
- margin-top: 0.5rem !important;
-}
-
-.mr-2,
-.mx-2 {
- margin-right: 0.5rem !important;
-}
-
-.mb-2,
-.my-2 {
- margin-bottom: 0.5rem !important;
-}
-
-.ml-2,
-.mx-2 {
- margin-left: 0.5rem !important;
-}
-
-.m-3 {
- margin: 1rem !important;
-}
-
-.mt-3,
-.my-3 {
- margin-top: 1rem !important;
-}
-
-.mr-3,
-.mx-3 {
- margin-right: 1rem !important;
-}
-
-.mb-3,
-.my-3 {
- margin-bottom: 1rem !important;
-}
-
-.ml-3,
-.mx-3 {
- margin-left: 1rem !important;
-}
-
-.m-4 {
- margin: 1.5rem !important;
-}
-
-.mt-4,
-.my-4 {
- margin-top: 1.5rem !important;
-}
-
-.mr-4,
-.mx-4 {
- margin-right: 1.5rem !important;
-}
-
-.mb-4,
-.my-4 {
- margin-bottom: 1.5rem !important;
-}
-
-.ml-4,
-.mx-4 {
- margin-left: 1.5rem !important;
-}
-
-.m-5 {
- margin: 3rem !important;
-}
-
-.mt-5,
-.my-5 {
- margin-top: 3rem !important;
-}
-
-.mr-5,
-.mx-5 {
- margin-right: 3rem !important;
-}
-
-.mb-5,
-.my-5 {
- margin-bottom: 3rem !important;
-}
-
-.ml-5,
-.mx-5 {
- margin-left: 3rem !important;
-}
-
-.p-0 {
- padding: 0 !important;
-}
-
-.pt-0,
-.py-0 {
- padding-top: 0 !important;
-}
-
-.pr-0,
-.px-0 {
- padding-right: 0 !important;
-}
-
-.pb-0,
-.py-0 {
- padding-bottom: 0 !important;
-}
-
-.pl-0,
-.px-0 {
- padding-left: 0 !important;
-}
-
-.p-1 {
- padding: 0.25rem !important;
-}
-
-.pt-1,
-.py-1 {
- padding-top: 0.25rem !important;
-}
-
-.pr-1,
-.px-1 {
- padding-right: 0.25rem !important;
-}
-
-.pb-1,
-.py-1 {
- padding-bottom: 0.25rem !important;
-}
-
-.pl-1,
-.px-1 {
- padding-left: 0.25rem !important;
-}
-
-.p-2 {
- padding: 0.5rem !important;
-}
-
-.pt-2,
-.py-2 {
- padding-top: 0.5rem !important;
-}
-
-.pr-2,
-.px-2 {
- padding-right: 0.5rem !important;
-}
-
-.pb-2,
-.py-2 {
- padding-bottom: 0.5rem !important;
-}
-
-.pl-2,
-.px-2 {
- padding-left: 0.5rem !important;
-}
-
-.p-3 {
- padding: 1rem !important;
-}
-
-.pt-3,
-.py-3 {
- padding-top: 1rem !important;
-}
-
-.pr-3,
-.px-3 {
- padding-right: 1rem !important;
-}
-
-.pb-3,
-.py-3 {
- padding-bottom: 1rem !important;
-}
-
-.pl-3,
-.px-3 {
- padding-left: 1rem !important;
-}
-
-.p-4 {
- padding: 1.5rem !important;
-}
-
-.pt-4,
-.py-4 {
- padding-top: 1.5rem !important;
-}
-
-.pr-4,
-.px-4 {
- padding-right: 1.5rem !important;
-}
-
-.pb-4,
-.py-4 {
- padding-bottom: 1.5rem !important;
-}
-
-.pl-4,
-.px-4 {
- padding-left: 1.5rem !important;
-}
-
-.p-5 {
- padding: 3rem !important;
-}
-
-.pt-5,
-.py-5 {
- padding-top: 3rem !important;
-}
-
-.pr-5,
-.px-5 {
- padding-right: 3rem !important;
-}
-
-.pb-5,
-.py-5 {
- padding-bottom: 3rem !important;
-}
-
-.pl-5,
-.px-5 {
- padding-left: 3rem !important;
-}
-
-.m-n1 {
- margin: -0.25rem !important;
-}
-
-.mt-n1,
-.my-n1 {
- margin-top: -0.25rem !important;
-}
-
-.mr-n1,
-.mx-n1 {
- margin-right: -0.25rem !important;
-}
-
-.mb-n1,
-.my-n1 {
- margin-bottom: -0.25rem !important;
-}
-
-.ml-n1,
-.mx-n1 {
- margin-left: -0.25rem !important;
-}
-
-.m-n2 {
- margin: -0.5rem !important;
-}
-
-.mt-n2,
-.my-n2 {
- margin-top: -0.5rem !important;
-}
-
-.mr-n2,
-.mx-n2 {
- margin-right: -0.5rem !important;
-}
-
-.mb-n2,
-.my-n2 {
- margin-bottom: -0.5rem !important;
-}
-
-.ml-n2,
-.mx-n2 {
- margin-left: -0.5rem !important;
-}
-
-.m-n3 {
- margin: -1rem !important;
-}
-
-.mt-n3,
-.my-n3 {
- margin-top: -1rem !important;
-}
-
-.mr-n3,
-.mx-n3 {
- margin-right: -1rem !important;
-}
-
-.mb-n3,
-.my-n3 {
- margin-bottom: -1rem !important;
-}
-
-.ml-n3,
-.mx-n3 {
- margin-left: -1rem !important;
-}
-
-.m-n4 {
- margin: -1.5rem !important;
-}
-
-.mt-n4,
-.my-n4 {
- margin-top: -1.5rem !important;
-}
-
-.mr-n4,
-.mx-n4 {
- margin-right: -1.5rem !important;
-}
-
-.mb-n4,
-.my-n4 {
- margin-bottom: -1.5rem !important;
-}
-
-.ml-n4,
-.mx-n4 {
- margin-left: -1.5rem !important;
-}
-
-.m-n5 {
- margin: -3rem !important;
-}
-
-.mt-n5,
-.my-n5 {
- margin-top: -3rem !important;
-}
-
-.mr-n5,
-.mx-n5 {
- margin-right: -3rem !important;
-}
-
-.mb-n5,
-.my-n5 {
- margin-bottom: -3rem !important;
-}
-
-.ml-n5,
-.mx-n5 {
- margin-left: -3rem !important;
-}
-
-.m-auto {
- margin: auto !important;
-}
-
-.mt-auto,
-.my-auto {
- margin-top: auto !important;
-}
-
-.mr-auto,
-.mx-auto {
- margin-right: auto !important;
-}
-
-.mb-auto,
-.my-auto {
- margin-bottom: auto !important;
-}
-
-.ml-auto,
-.mx-auto {
- margin-left: auto !important;
-}
-
-@media (min-width: 576px) {
- .m-sm-0 {
- margin: 0 !important;
- }
- .mt-sm-0,
- .my-sm-0 {
- margin-top: 0 !important;
- }
- .mr-sm-0,
- .mx-sm-0 {
- margin-right: 0 !important;
- }
- .mb-sm-0,
- .my-sm-0 {
- margin-bottom: 0 !important;
- }
- .ml-sm-0,
- .mx-sm-0 {
- margin-left: 0 !important;
- }
- .m-sm-1 {
- margin: 0.25rem !important;
- }
- .mt-sm-1,
- .my-sm-1 {
- margin-top: 0.25rem !important;
- }
- .mr-sm-1,
- .mx-sm-1 {
- margin-right: 0.25rem !important;
- }
- .mb-sm-1,
- .my-sm-1 {
- margin-bottom: 0.25rem !important;
- }
- .ml-sm-1,
- .mx-sm-1 {
- margin-left: 0.25rem !important;
- }
- .m-sm-2 {
- margin: 0.5rem !important;
- }
- .mt-sm-2,
- .my-sm-2 {
- margin-top: 0.5rem !important;
- }
- .mr-sm-2,
- .mx-sm-2 {
- margin-right: 0.5rem !important;
- }
- .mb-sm-2,
- .my-sm-2 {
- margin-bottom: 0.5rem !important;
- }
- .ml-sm-2,
- .mx-sm-2 {
- margin-left: 0.5rem !important;
- }
- .m-sm-3 {
- margin: 1rem !important;
- }
- .mt-sm-3,
- .my-sm-3 {
- margin-top: 1rem !important;
- }
- .mr-sm-3,
- .mx-sm-3 {
- margin-right: 1rem !important;
- }
- .mb-sm-3,
- .my-sm-3 {
- margin-bottom: 1rem !important;
- }
- .ml-sm-3,
- .mx-sm-3 {
- margin-left: 1rem !important;
- }
- .m-sm-4 {
- margin: 1.5rem !important;
- }
- .mt-sm-4,
- .my-sm-4 {
- margin-top: 1.5rem !important;
- }
- .mr-sm-4,
- .mx-sm-4 {
- margin-right: 1.5rem !important;
- }
- .mb-sm-4,
- .my-sm-4 {
- margin-bottom: 1.5rem !important;
- }
- .ml-sm-4,
- .mx-sm-4 {
- margin-left: 1.5rem !important;
- }
- .m-sm-5 {
- margin: 3rem !important;
- }
- .mt-sm-5,
- .my-sm-5 {
- margin-top: 3rem !important;
- }
- .mr-sm-5,
- .mx-sm-5 {
- margin-right: 3rem !important;
- }
- .mb-sm-5,
- .my-sm-5 {
- margin-bottom: 3rem !important;
- }
- .ml-sm-5,
- .mx-sm-5 {
- margin-left: 3rem !important;
- }
- .p-sm-0 {
- padding: 0 !important;
- }
- .pt-sm-0,
- .py-sm-0 {
- padding-top: 0 !important;
- }
- .pr-sm-0,
- .px-sm-0 {
- padding-right: 0 !important;
- }
- .pb-sm-0,
- .py-sm-0 {
- padding-bottom: 0 !important;
- }
- .pl-sm-0,
- .px-sm-0 {
- padding-left: 0 !important;
- }
- .p-sm-1 {
- padding: 0.25rem !important;
- }
- .pt-sm-1,
- .py-sm-1 {
- padding-top: 0.25rem !important;
- }
- .pr-sm-1,
- .px-sm-1 {
- padding-right: 0.25rem !important;
- }
- .pb-sm-1,
- .py-sm-1 {
- padding-bottom: 0.25rem !important;
- }
- .pl-sm-1,
- .px-sm-1 {
- padding-left: 0.25rem !important;
- }
- .p-sm-2 {
- padding: 0.5rem !important;
- }
- .pt-sm-2,
- .py-sm-2 {
- padding-top: 0.5rem !important;
- }
- .pr-sm-2,
- .px-sm-2 {
- padding-right: 0.5rem !important;
- }
- .pb-sm-2,
- .py-sm-2 {
- padding-bottom: 0.5rem !important;
- }
- .pl-sm-2,
- .px-sm-2 {
- padding-left: 0.5rem !important;
- }
- .p-sm-3 {
- padding: 1rem !important;
- }
- .pt-sm-3,
- .py-sm-3 {
- padding-top: 1rem !important;
- }
- .pr-sm-3,
- .px-sm-3 {
- padding-right: 1rem !important;
- }
- .pb-sm-3,
- .py-sm-3 {
- padding-bottom: 1rem !important;
- }
- .pl-sm-3,
- .px-sm-3 {
- padding-left: 1rem !important;
- }
- .p-sm-4 {
- padding: 1.5rem !important;
- }
- .pt-sm-4,
- .py-sm-4 {
- padding-top: 1.5rem !important;
- }
- .pr-sm-4,
- .px-sm-4 {
- padding-right: 1.5rem !important;
- }
- .pb-sm-4,
- .py-sm-4 {
- padding-bottom: 1.5rem !important;
- }
- .pl-sm-4,
- .px-sm-4 {
- padding-left: 1.5rem !important;
- }
- .p-sm-5 {
- padding: 3rem !important;
- }
- .pt-sm-5,
- .py-sm-5 {
- padding-top: 3rem !important;
- }
- .pr-sm-5,
- .px-sm-5 {
- padding-right: 3rem !important;
- }
- .pb-sm-5,
- .py-sm-5 {
- padding-bottom: 3rem !important;
- }
- .pl-sm-5,
- .px-sm-5 {
- padding-left: 3rem !important;
- }
- .m-sm-n1 {
- margin: -0.25rem !important;
- }
- .mt-sm-n1,
- .my-sm-n1 {
- margin-top: -0.25rem !important;
- }
- .mr-sm-n1,
- .mx-sm-n1 {
- margin-right: -0.25rem !important;
- }
- .mb-sm-n1,
- .my-sm-n1 {
- margin-bottom: -0.25rem !important;
- }
- .ml-sm-n1,
- .mx-sm-n1 {
- margin-left: -0.25rem !important;
- }
- .m-sm-n2 {
- margin: -0.5rem !important;
- }
- .mt-sm-n2,
- .my-sm-n2 {
- margin-top: -0.5rem !important;
- }
- .mr-sm-n2,
- .mx-sm-n2 {
- margin-right: -0.5rem !important;
- }
- .mb-sm-n2,
- .my-sm-n2 {
- margin-bottom: -0.5rem !important;
- }
- .ml-sm-n2,
- .mx-sm-n2 {
- margin-left: -0.5rem !important;
- }
- .m-sm-n3 {
- margin: -1rem !important;
- }
- .mt-sm-n3,
- .my-sm-n3 {
- margin-top: -1rem !important;
- }
- .mr-sm-n3,
- .mx-sm-n3 {
- margin-right: -1rem !important;
- }
- .mb-sm-n3,
- .my-sm-n3 {
- margin-bottom: -1rem !important;
- }
- .ml-sm-n3,
- .mx-sm-n3 {
- margin-left: -1rem !important;
- }
- .m-sm-n4 {
- margin: -1.5rem !important;
- }
- .mt-sm-n4,
- .my-sm-n4 {
- margin-top: -1.5rem !important;
- }
- .mr-sm-n4,
- .mx-sm-n4 {
- margin-right: -1.5rem !important;
- }
- .mb-sm-n4,
- .my-sm-n4 {
- margin-bottom: -1.5rem !important;
- }
- .ml-sm-n4,
- .mx-sm-n4 {
- margin-left: -1.5rem !important;
- }
- .m-sm-n5 {
- margin: -3rem !important;
- }
- .mt-sm-n5,
- .my-sm-n5 {
- margin-top: -3rem !important;
- }
- .mr-sm-n5,
- .mx-sm-n5 {
- margin-right: -3rem !important;
- }
- .mb-sm-n5,
- .my-sm-n5 {
- margin-bottom: -3rem !important;
- }
- .ml-sm-n5,
- .mx-sm-n5 {
- margin-left: -3rem !important;
- }
- .m-sm-auto {
- margin: auto !important;
- }
- .mt-sm-auto,
- .my-sm-auto {
- margin-top: auto !important;
- }
- .mr-sm-auto,
- .mx-sm-auto {
- margin-right: auto !important;
- }
- .mb-sm-auto,
- .my-sm-auto {
- margin-bottom: auto !important;
- }
- .ml-sm-auto,
- .mx-sm-auto {
- margin-left: auto !important;
- }
-}
-
-@media (min-width: 768px) {
- .m-md-0 {
- margin: 0 !important;
- }
- .mt-md-0,
- .my-md-0 {
- margin-top: 0 !important;
- }
- .mr-md-0,
- .mx-md-0 {
- margin-right: 0 !important;
- }
- .mb-md-0,
- .my-md-0 {
- margin-bottom: 0 !important;
- }
- .ml-md-0,
- .mx-md-0 {
- margin-left: 0 !important;
- }
- .m-md-1 {
- margin: 0.25rem !important;
- }
- .mt-md-1,
- .my-md-1 {
- margin-top: 0.25rem !important;
- }
- .mr-md-1,
- .mx-md-1 {
- margin-right: 0.25rem !important;
- }
- .mb-md-1,
- .my-md-1 {
- margin-bottom: 0.25rem !important;
- }
- .ml-md-1,
- .mx-md-1 {
- margin-left: 0.25rem !important;
- }
- .m-md-2 {
- margin: 0.5rem !important;
- }
- .mt-md-2,
- .my-md-2 {
- margin-top: 0.5rem !important;
- }
- .mr-md-2,
- .mx-md-2 {
- margin-right: 0.5rem !important;
- }
- .mb-md-2,
- .my-md-2 {
- margin-bottom: 0.5rem !important;
- }
- .ml-md-2,
- .mx-md-2 {
- margin-left: 0.5rem !important;
- }
- .m-md-3 {
- margin: 1rem !important;
- }
- .mt-md-3,
- .my-md-3 {
- margin-top: 1rem !important;
- }
- .mr-md-3,
- .mx-md-3 {
- margin-right: 1rem !important;
- }
- .mb-md-3,
- .my-md-3 {
- margin-bottom: 1rem !important;
- }
- .ml-md-3,
- .mx-md-3 {
- margin-left: 1rem !important;
- }
- .m-md-4 {
- margin: 1.5rem !important;
- }
- .mt-md-4,
- .my-md-4 {
- margin-top: 1.5rem !important;
- }
- .mr-md-4,
- .mx-md-4 {
- margin-right: 1.5rem !important;
- }
- .mb-md-4,
- .my-md-4 {
- margin-bottom: 1.5rem !important;
- }
- .ml-md-4,
- .mx-md-4 {
- margin-left: 1.5rem !important;
- }
- .m-md-5 {
- margin: 3rem !important;
- }
- .mt-md-5,
- .my-md-5 {
- margin-top: 3rem !important;
- }
- .mr-md-5,
- .mx-md-5 {
- margin-right: 3rem !important;
- }
- .mb-md-5,
- .my-md-5 {
- margin-bottom: 3rem !important;
- }
- .ml-md-5,
- .mx-md-5 {
- margin-left: 3rem !important;
- }
- .p-md-0 {
- padding: 0 !important;
- }
- .pt-md-0,
- .py-md-0 {
- padding-top: 0 !important;
- }
- .pr-md-0,
- .px-md-0 {
- padding-right: 0 !important;
- }
- .pb-md-0,
- .py-md-0 {
- padding-bottom: 0 !important;
- }
- .pl-md-0,
- .px-md-0 {
- padding-left: 0 !important;
- }
- .p-md-1 {
- padding: 0.25rem !important;
- }
- .pt-md-1,
- .py-md-1 {
- padding-top: 0.25rem !important;
- }
- .pr-md-1,
- .px-md-1 {
- padding-right: 0.25rem !important;
- }
- .pb-md-1,
- .py-md-1 {
- padding-bottom: 0.25rem !important;
- }
- .pl-md-1,
- .px-md-1 {
- padding-left: 0.25rem !important;
- }
- .p-md-2 {
- padding: 0.5rem !important;
- }
- .pt-md-2,
- .py-md-2 {
- padding-top: 0.5rem !important;
- }
- .pr-md-2,
- .px-md-2 {
- padding-right: 0.5rem !important;
- }
- .pb-md-2,
- .py-md-2 {
- padding-bottom: 0.5rem !important;
- }
- .pl-md-2,
- .px-md-2 {
- padding-left: 0.5rem !important;
- }
- .p-md-3 {
- padding: 1rem !important;
- }
- .pt-md-3,
- .py-md-3 {
- padding-top: 1rem !important;
- }
- .pr-md-3,
- .px-md-3 {
- padding-right: 1rem !important;
- }
- .pb-md-3,
- .py-md-3 {
- padding-bottom: 1rem !important;
- }
- .pl-md-3,
- .px-md-3 {
- padding-left: 1rem !important;
- }
- .p-md-4 {
- padding: 1.5rem !important;
- }
- .pt-md-4,
- .py-md-4 {
- padding-top: 1.5rem !important;
- }
- .pr-md-4,
- .px-md-4 {
- padding-right: 1.5rem !important;
- }
- .pb-md-4,
- .py-md-4 {
- padding-bottom: 1.5rem !important;
- }
- .pl-md-4,
- .px-md-4 {
- padding-left: 1.5rem !important;
- }
- .p-md-5 {
- padding: 3rem !important;
- }
- .pt-md-5,
- .py-md-5 {
- padding-top: 3rem !important;
- }
- .pr-md-5,
- .px-md-5 {
- padding-right: 3rem !important;
- }
- .pb-md-5,
- .py-md-5 {
- padding-bottom: 3rem !important;
- }
- .pl-md-5,
- .px-md-5 {
- padding-left: 3rem !important;
- }
- .m-md-n1 {
- margin: -0.25rem !important;
- }
- .mt-md-n1,
- .my-md-n1 {
- margin-top: -0.25rem !important;
- }
- .mr-md-n1,
- .mx-md-n1 {
- margin-right: -0.25rem !important;
- }
- .mb-md-n1,
- .my-md-n1 {
- margin-bottom: -0.25rem !important;
- }
- .ml-md-n1,
- .mx-md-n1 {
- margin-left: -0.25rem !important;
- }
- .m-md-n2 {
- margin: -0.5rem !important;
- }
- .mt-md-n2,
- .my-md-n2 {
- margin-top: -0.5rem !important;
- }
- .mr-md-n2,
- .mx-md-n2 {
- margin-right: -0.5rem !important;
- }
- .mb-md-n2,
- .my-md-n2 {
- margin-bottom: -0.5rem !important;
- }
- .ml-md-n2,
- .mx-md-n2 {
- margin-left: -0.5rem !important;
- }
- .m-md-n3 {
- margin: -1rem !important;
- }
- .mt-md-n3,
- .my-md-n3 {
- margin-top: -1rem !important;
- }
- .mr-md-n3,
- .mx-md-n3 {
- margin-right: -1rem !important;
- }
- .mb-md-n3,
- .my-md-n3 {
- margin-bottom: -1rem !important;
- }
- .ml-md-n3,
- .mx-md-n3 {
- margin-left: -1rem !important;
- }
- .m-md-n4 {
- margin: -1.5rem !important;
- }
- .mt-md-n4,
- .my-md-n4 {
- margin-top: -1.5rem !important;
- }
- .mr-md-n4,
- .mx-md-n4 {
- margin-right: -1.5rem !important;
- }
- .mb-md-n4,
- .my-md-n4 {
- margin-bottom: -1.5rem !important;
- }
- .ml-md-n4,
- .mx-md-n4 {
- margin-left: -1.5rem !important;
- }
- .m-md-n5 {
- margin: -3rem !important;
- }
- .mt-md-n5,
- .my-md-n5 {
- margin-top: -3rem !important;
- }
- .mr-md-n5,
- .mx-md-n5 {
- margin-right: -3rem !important;
- }
- .mb-md-n5,
- .my-md-n5 {
- margin-bottom: -3rem !important;
- }
- .ml-md-n5,
- .mx-md-n5 {
- margin-left: -3rem !important;
- }
- .m-md-auto {
- margin: auto !important;
- }
- .mt-md-auto,
- .my-md-auto {
- margin-top: auto !important;
- }
- .mr-md-auto,
- .mx-md-auto {
- margin-right: auto !important;
- }
- .mb-md-auto,
- .my-md-auto {
- margin-bottom: auto !important;
- }
- .ml-md-auto,
- .mx-md-auto {
- margin-left: auto !important;
- }
-}
-
-@media (min-width: 992px) {
- .m-lg-0 {
- margin: 0 !important;
- }
- .mt-lg-0,
- .my-lg-0 {
- margin-top: 0 !important;
- }
- .mr-lg-0,
- .mx-lg-0 {
- margin-right: 0 !important;
- }
- .mb-lg-0,
- .my-lg-0 {
- margin-bottom: 0 !important;
- }
- .ml-lg-0,
- .mx-lg-0 {
- margin-left: 0 !important;
- }
- .m-lg-1 {
- margin: 0.25rem !important;
- }
- .mt-lg-1,
- .my-lg-1 {
- margin-top: 0.25rem !important;
- }
- .mr-lg-1,
- .mx-lg-1 {
- margin-right: 0.25rem !important;
- }
- .mb-lg-1,
- .my-lg-1 {
- margin-bottom: 0.25rem !important;
- }
- .ml-lg-1,
- .mx-lg-1 {
- margin-left: 0.25rem !important;
- }
- .m-lg-2 {
- margin: 0.5rem !important;
- }
- .mt-lg-2,
- .my-lg-2 {
- margin-top: 0.5rem !important;
- }
- .mr-lg-2,
- .mx-lg-2 {
- margin-right: 0.5rem !important;
- }
- .mb-lg-2,
- .my-lg-2 {
- margin-bottom: 0.5rem !important;
- }
- .ml-lg-2,
- .mx-lg-2 {
- margin-left: 0.5rem !important;
- }
- .m-lg-3 {
- margin: 1rem !important;
- }
- .mt-lg-3,
- .my-lg-3 {
- margin-top: 1rem !important;
- }
- .mr-lg-3,
- .mx-lg-3 {
- margin-right: 1rem !important;
- }
- .mb-lg-3,
- .my-lg-3 {
- margin-bottom: 1rem !important;
- }
- .ml-lg-3,
- .mx-lg-3 {
- margin-left: 1rem !important;
- }
- .m-lg-4 {
- margin: 1.5rem !important;
- }
- .mt-lg-4,
- .my-lg-4 {
- margin-top: 1.5rem !important;
- }
- .mr-lg-4,
- .mx-lg-4 {
- margin-right: 1.5rem !important;
- }
- .mb-lg-4,
- .my-lg-4 {
- margin-bottom: 1.5rem !important;
- }
- .ml-lg-4,
- .mx-lg-4 {
- margin-left: 1.5rem !important;
- }
- .m-lg-5 {
- margin: 3rem !important;
- }
- .mt-lg-5,
- .my-lg-5 {
- margin-top: 3rem !important;
- }
- .mr-lg-5,
- .mx-lg-5 {
- margin-right: 3rem !important;
- }
- .mb-lg-5,
- .my-lg-5 {
- margin-bottom: 3rem !important;
- }
- .ml-lg-5,
- .mx-lg-5 {
- margin-left: 3rem !important;
- }
- .p-lg-0 {
- padding: 0 !important;
- }
- .pt-lg-0,
- .py-lg-0 {
- padding-top: 0 !important;
- }
- .pr-lg-0,
- .px-lg-0 {
- padding-right: 0 !important;
- }
- .pb-lg-0,
- .py-lg-0 {
- padding-bottom: 0 !important;
- }
- .pl-lg-0,
- .px-lg-0 {
- padding-left: 0 !important;
- }
- .p-lg-1 {
- padding: 0.25rem !important;
- }
- .pt-lg-1,
- .py-lg-1 {
- padding-top: 0.25rem !important;
- }
- .pr-lg-1,
- .px-lg-1 {
- padding-right: 0.25rem !important;
- }
- .pb-lg-1,
- .py-lg-1 {
- padding-bottom: 0.25rem !important;
- }
- .pl-lg-1,
- .px-lg-1 {
- padding-left: 0.25rem !important;
- }
- .p-lg-2 {
- padding: 0.5rem !important;
- }
- .pt-lg-2,
- .py-lg-2 {
- padding-top: 0.5rem !important;
- }
- .pr-lg-2,
- .px-lg-2 {
- padding-right: 0.5rem !important;
- }
- .pb-lg-2,
- .py-lg-2 {
- padding-bottom: 0.5rem !important;
- }
- .pl-lg-2,
- .px-lg-2 {
- padding-left: 0.5rem !important;
- }
- .p-lg-3 {
- padding: 1rem !important;
- }
- .pt-lg-3,
- .py-lg-3 {
- padding-top: 1rem !important;
- }
- .pr-lg-3,
- .px-lg-3 {
- padding-right: 1rem !important;
- }
- .pb-lg-3,
- .py-lg-3 {
- padding-bottom: 1rem !important;
- }
- .pl-lg-3,
- .px-lg-3 {
- padding-left: 1rem !important;
- }
- .p-lg-4 {
- padding: 1.5rem !important;
- }
- .pt-lg-4,
- .py-lg-4 {
- padding-top: 1.5rem !important;
- }
- .pr-lg-4,
- .px-lg-4 {
- padding-right: 1.5rem !important;
- }
- .pb-lg-4,
- .py-lg-4 {
- padding-bottom: 1.5rem !important;
- }
- .pl-lg-4,
- .px-lg-4 {
- padding-left: 1.5rem !important;
- }
- .p-lg-5 {
- padding: 3rem !important;
- }
- .pt-lg-5,
- .py-lg-5 {
- padding-top: 3rem !important;
- }
- .pr-lg-5,
- .px-lg-5 {
- padding-right: 3rem !important;
- }
- .pb-lg-5,
- .py-lg-5 {
- padding-bottom: 3rem !important;
- }
- .pl-lg-5,
- .px-lg-5 {
- padding-left: 3rem !important;
- }
- .m-lg-n1 {
- margin: -0.25rem !important;
- }
- .mt-lg-n1,
- .my-lg-n1 {
- margin-top: -0.25rem !important;
- }
- .mr-lg-n1,
- .mx-lg-n1 {
- margin-right: -0.25rem !important;
- }
- .mb-lg-n1,
- .my-lg-n1 {
- margin-bottom: -0.25rem !important;
- }
- .ml-lg-n1,
- .mx-lg-n1 {
- margin-left: -0.25rem !important;
- }
- .m-lg-n2 {
- margin: -0.5rem !important;
- }
- .mt-lg-n2,
- .my-lg-n2 {
- margin-top: -0.5rem !important;
- }
- .mr-lg-n2,
- .mx-lg-n2 {
- margin-right: -0.5rem !important;
- }
- .mb-lg-n2,
- .my-lg-n2 {
- margin-bottom: -0.5rem !important;
- }
- .ml-lg-n2,
- .mx-lg-n2 {
- margin-left: -0.5rem !important;
- }
- .m-lg-n3 {
- margin: -1rem !important;
- }
- .mt-lg-n3,
- .my-lg-n3 {
- margin-top: -1rem !important;
- }
- .mr-lg-n3,
- .mx-lg-n3 {
- margin-right: -1rem !important;
- }
- .mb-lg-n3,
- .my-lg-n3 {
- margin-bottom: -1rem !important;
- }
- .ml-lg-n3,
- .mx-lg-n3 {
- margin-left: -1rem !important;
- }
- .m-lg-n4 {
- margin: -1.5rem !important;
- }
- .mt-lg-n4,
- .my-lg-n4 {
- margin-top: -1.5rem !important;
- }
- .mr-lg-n4,
- .mx-lg-n4 {
- margin-right: -1.5rem !important;
- }
- .mb-lg-n4,
- .my-lg-n4 {
- margin-bottom: -1.5rem !important;
- }
- .ml-lg-n4,
- .mx-lg-n4 {
- margin-left: -1.5rem !important;
- }
- .m-lg-n5 {
- margin: -3rem !important;
- }
- .mt-lg-n5,
- .my-lg-n5 {
- margin-top: -3rem !important;
- }
- .mr-lg-n5,
- .mx-lg-n5 {
- margin-right: -3rem !important;
- }
- .mb-lg-n5,
- .my-lg-n5 {
- margin-bottom: -3rem !important;
- }
- .ml-lg-n5,
- .mx-lg-n5 {
- margin-left: -3rem !important;
- }
- .m-lg-auto {
- margin: auto !important;
- }
- .mt-lg-auto,
- .my-lg-auto {
- margin-top: auto !important;
- }
- .mr-lg-auto,
- .mx-lg-auto {
- margin-right: auto !important;
- }
- .mb-lg-auto,
- .my-lg-auto {
- margin-bottom: auto !important;
- }
- .ml-lg-auto,
- .mx-lg-auto {
- margin-left: auto !important;
- }
-}
-
-@media (min-width: 1200px) {
- .m-xl-0 {
- margin: 0 !important;
- }
- .mt-xl-0,
- .my-xl-0 {
- margin-top: 0 !important;
- }
- .mr-xl-0,
- .mx-xl-0 {
- margin-right: 0 !important;
- }
- .mb-xl-0,
- .my-xl-0 {
- margin-bottom: 0 !important;
- }
- .ml-xl-0,
- .mx-xl-0 {
- margin-left: 0 !important;
- }
- .m-xl-1 {
- margin: 0.25rem !important;
- }
- .mt-xl-1,
- .my-xl-1 {
- margin-top: 0.25rem !important;
- }
- .mr-xl-1,
- .mx-xl-1 {
- margin-right: 0.25rem !important;
- }
- .mb-xl-1,
- .my-xl-1 {
- margin-bottom: 0.25rem !important;
- }
- .ml-xl-1,
- .mx-xl-1 {
- margin-left: 0.25rem !important;
- }
- .m-xl-2 {
- margin: 0.5rem !important;
- }
- .mt-xl-2,
- .my-xl-2 {
- margin-top: 0.5rem !important;
- }
- .mr-xl-2,
- .mx-xl-2 {
- margin-right: 0.5rem !important;
- }
- .mb-xl-2,
- .my-xl-2 {
- margin-bottom: 0.5rem !important;
- }
- .ml-xl-2,
- .mx-xl-2 {
- margin-left: 0.5rem !important;
- }
- .m-xl-3 {
- margin: 1rem !important;
- }
- .mt-xl-3,
- .my-xl-3 {
- margin-top: 1rem !important;
- }
- .mr-xl-3,
- .mx-xl-3 {
- margin-right: 1rem !important;
- }
- .mb-xl-3,
- .my-xl-3 {
- margin-bottom: 1rem !important;
- }
- .ml-xl-3,
- .mx-xl-3 {
- margin-left: 1rem !important;
- }
- .m-xl-4 {
- margin: 1.5rem !important;
- }
- .mt-xl-4,
- .my-xl-4 {
- margin-top: 1.5rem !important;
- }
- .mr-xl-4,
- .mx-xl-4 {
- margin-right: 1.5rem !important;
- }
- .mb-xl-4,
- .my-xl-4 {
- margin-bottom: 1.5rem !important;
- }
- .ml-xl-4,
- .mx-xl-4 {
- margin-left: 1.5rem !important;
- }
- .m-xl-5 {
- margin: 3rem !important;
- }
- .mt-xl-5,
- .my-xl-5 {
- margin-top: 3rem !important;
- }
- .mr-xl-5,
- .mx-xl-5 {
- margin-right: 3rem !important;
- }
- .mb-xl-5,
- .my-xl-5 {
- margin-bottom: 3rem !important;
- }
- .ml-xl-5,
- .mx-xl-5 {
- margin-left: 3rem !important;
- }
- .p-xl-0 {
- padding: 0 !important;
- }
- .pt-xl-0,
- .py-xl-0 {
- padding-top: 0 !important;
- }
- .pr-xl-0,
- .px-xl-0 {
- padding-right: 0 !important;
- }
- .pb-xl-0,
- .py-xl-0 {
- padding-bottom: 0 !important;
- }
- .pl-xl-0,
- .px-xl-0 {
- padding-left: 0 !important;
- }
- .p-xl-1 {
- padding: 0.25rem !important;
- }
- .pt-xl-1,
- .py-xl-1 {
- padding-top: 0.25rem !important;
- }
- .pr-xl-1,
- .px-xl-1 {
- padding-right: 0.25rem !important;
- }
- .pb-xl-1,
- .py-xl-1 {
- padding-bottom: 0.25rem !important;
- }
- .pl-xl-1,
- .px-xl-1 {
- padding-left: 0.25rem !important;
- }
- .p-xl-2 {
- padding: 0.5rem !important;
- }
- .pt-xl-2,
- .py-xl-2 {
- padding-top: 0.5rem !important;
- }
- .pr-xl-2,
- .px-xl-2 {
- padding-right: 0.5rem !important;
- }
- .pb-xl-2,
- .py-xl-2 {
- padding-bottom: 0.5rem !important;
- }
- .pl-xl-2,
- .px-xl-2 {
- padding-left: 0.5rem !important;
- }
- .p-xl-3 {
- padding: 1rem !important;
- }
- .pt-xl-3,
- .py-xl-3 {
- padding-top: 1rem !important;
- }
- .pr-xl-3,
- .px-xl-3 {
- padding-right: 1rem !important;
- }
- .pb-xl-3,
- .py-xl-3 {
- padding-bottom: 1rem !important;
- }
- .pl-xl-3,
- .px-xl-3 {
- padding-left: 1rem !important;
- }
- .p-xl-4 {
- padding: 1.5rem !important;
- }
- .pt-xl-4,
- .py-xl-4 {
- padding-top: 1.5rem !important;
- }
- .pr-xl-4,
- .px-xl-4 {
- padding-right: 1.5rem !important;
- }
- .pb-xl-4,
- .py-xl-4 {
- padding-bottom: 1.5rem !important;
- }
- .pl-xl-4,
- .px-xl-4 {
- padding-left: 1.5rem !important;
- }
- .p-xl-5 {
- padding: 3rem !important;
- }
- .pt-xl-5,
- .py-xl-5 {
- padding-top: 3rem !important;
- }
- .pr-xl-5,
- .px-xl-5 {
- padding-right: 3rem !important;
- }
- .pb-xl-5,
- .py-xl-5 {
- padding-bottom: 3rem !important;
- }
- .pl-xl-5,
- .px-xl-5 {
- padding-left: 3rem !important;
- }
- .m-xl-n1 {
- margin: -0.25rem !important;
- }
- .mt-xl-n1,
- .my-xl-n1 {
- margin-top: -0.25rem !important;
- }
- .mr-xl-n1,
- .mx-xl-n1 {
- margin-right: -0.25rem !important;
- }
- .mb-xl-n1,
- .my-xl-n1 {
- margin-bottom: -0.25rem !important;
- }
- .ml-xl-n1,
- .mx-xl-n1 {
- margin-left: -0.25rem !important;
- }
- .m-xl-n2 {
- margin: -0.5rem !important;
- }
- .mt-xl-n2,
- .my-xl-n2 {
- margin-top: -0.5rem !important;
- }
- .mr-xl-n2,
- .mx-xl-n2 {
- margin-right: -0.5rem !important;
- }
- .mb-xl-n2,
- .my-xl-n2 {
- margin-bottom: -0.5rem !important;
- }
- .ml-xl-n2,
- .mx-xl-n2 {
- margin-left: -0.5rem !important;
- }
- .m-xl-n3 {
- margin: -1rem !important;
- }
- .mt-xl-n3,
- .my-xl-n3 {
- margin-top: -1rem !important;
- }
- .mr-xl-n3,
- .mx-xl-n3 {
- margin-right: -1rem !important;
- }
- .mb-xl-n3,
- .my-xl-n3 {
- margin-bottom: -1rem !important;
- }
- .ml-xl-n3,
- .mx-xl-n3 {
- margin-left: -1rem !important;
- }
- .m-xl-n4 {
- margin: -1.5rem !important;
- }
- .mt-xl-n4,
- .my-xl-n4 {
- margin-top: -1.5rem !important;
- }
- .mr-xl-n4,
- .mx-xl-n4 {
- margin-right: -1.5rem !important;
- }
- .mb-xl-n4,
- .my-xl-n4 {
- margin-bottom: -1.5rem !important;
- }
- .ml-xl-n4,
- .mx-xl-n4 {
- margin-left: -1.5rem !important;
- }
- .m-xl-n5 {
- margin: -3rem !important;
- }
- .mt-xl-n5,
- .my-xl-n5 {
- margin-top: -3rem !important;
- }
- .mr-xl-n5,
- .mx-xl-n5 {
- margin-right: -3rem !important;
- }
- .mb-xl-n5,
- .my-xl-n5 {
- margin-bottom: -3rem !important;
- }
- .ml-xl-n5,
- .mx-xl-n5 {
- margin-left: -3rem !important;
- }
- .m-xl-auto {
- margin: auto !important;
- }
- .mt-xl-auto,
- .my-xl-auto {
- margin-top: auto !important;
- }
- .mr-xl-auto,
- .mx-xl-auto {
- margin-right: auto !important;
- }
- .mb-xl-auto,
- .my-xl-auto {
- margin-bottom: auto !important;
- }
- .ml-xl-auto,
- .mx-xl-auto {
- margin-left: auto !important;
- }
-}
diff --git a/styles/index.css b/styles/index.css
index b6006b43..bc863869 100644
--- a/styles/index.css
+++ b/styles/index.css
@@ -3,6 +3,7 @@ body {
font-family: Inter, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans,
Ubuntu, Cantrell, 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol';
+ font-size: 16px;
font-weight: 400;
line-height: 1.8;
padding: 0;
@@ -12,14 +13,8 @@ body {
display: flex;
flex-direction: column;
flex: 1;
-
- font-size: var(--font-size-normal);
- overflow-y: overlay;
-}
-
-body {
- color: var(--gray900);
- background: var(--gray75);
+ color: var(--base800);
+ background: var(--base100);
}
.zh-CN {
@@ -70,56 +65,12 @@ h6 {
margin: 0;
}
-button,
-input,
-select {
- font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
-}
-
a,
a:active,
a:visited {
color: var(--primary400);
}
-input[type='text'],
-input[type='password'],
-select,
-textarea {
- color: var(--gray900);
- background: var(--gray50);
- padding: 4px 8px;
- font-size: var(--font-size-normal);
- line-height: 1.8;
- border: 1px solid var(--gray500);
- border-radius: 4px;
- outline: none;
- resize: none;
- flex: 1;
-}
-
-input[type='checkbox'] + label {
- margin-left: 10px;
-}
-
-label {
- flex: 1;
- margin-right: 20px;
-}
-
-label:empty {
- flex: 0;
-}
-
-dt {
- font-weight: 600;
- margin: 0 0 5px 0;
-}
-
-dd {
- margin: 0 0 30px 0;
-}
-
main {
flex: 1;
display: flex;
@@ -137,28 +88,3 @@ svg {
height: 100%;
flex: 1;
}
-
-#__modals {
- z-index: 10;
-}
-
-.container {
- padding: 0;
- display: flex;
- flex-direction: column;
- flex: 1;
-}
-
-.row {
- margin-right: 0;
- margin-left: 0;
-}
-.row > .col,
-.row > [class*='col-'] {
- padding-right: 0;
- padding-left: 0;
-}
-
-.center {
- text-align: center;
-}
diff --git a/styles/variables.css b/styles/variables.css
index 4c9d7dbf..726195d2 100644
--- a/styles/variables.css
+++ b/styles/variables.css
@@ -1,55 +1,6 @@
:root {
- --gray50: #ffffff;
- --gray75: #fafafa;
- --gray100: #f5f5f5;
- --gray200: #eaeaea;
- --gray300: #e1e1e1;
- --gray400: #cacaca;
- --gray500: #b3b3b3;
- --gray600: #8e8e8e;
- --gray700: #6e6e6e;
- --gray800: #4b4b4b;
- --gray900: #2c2c2c;
-
- --primary400: #2680eb;
- --primary500: #1473e6;
- --primary600: #0d66d0;
- --primary700: #095aba;
-
- --font-size-xlarge: 36px;
- --font-size-large: 24px;
- --font-size-normal: 16px;
- --font-size-small: 14px;
- --font-size-xsmall: 12px;
-
- --grid-size-small: 576px;
- --grid-size-medium: 768px;
- --grid-size-large: 992px;
- --grid-size-xlarge: 1140px;
-
- --red400: #e34850;
- --red500: #d7373f;
- --red600: #c9252d;
- --red700: #bb121a;
-
- --green400: #2d9d78;
- --green500: #268e6c;
- --green600: #12805c;
- --green700: #107154;
-
- --msgColor: #ffffff;
-}
-
-[data-theme='dark'] {
- --gray50: #252525;
- --gray75: #2f2f2f;
- --gray100: #323232;
- --gray200: #3e3e3e;
- --gray300: #4a4a4a;
- --gray400: #5a5a5a;
- --gray500: #6e6e6e;
- --gray600: #909090;
- --gray700: #b9b9b9;
- --gray800: #e3e3e3;
- --gray900: #ffffff;
+ --primary400: var(--blue800);
+ --primary500: var(--blue900);
+ --primary600: var(--blue1000);
+ --primary700: var(--blue1100);
}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..b022d603
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "outDir": "./build",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "incremental": true,
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "noImplicitAny": false,
+ "preserveConstEnums": true,
+ "removeComments": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowJs": true,
+ "strict": true,
+ "baseUrl": ".",
+ "strictNullChecks": false,
+ "noEmit": true,
+ "jsx": "preserve"
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"]
+}
diff --git a/yarn.lock b/yarn.lock
index f0229aa3..5daa7d28 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1050,21 +1050,28 @@
"@babel/plugin-transform-typescript" "^7.18.6"
"@babel/runtime-corejs3@^7.10.2":
- version "7.20.0"
- resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.0.tgz#56ef7af3cd23d1570969809a5a8782e774e0141a"
- integrity sha512-v1JH7PeAAGBEyTQM9TqojVl+b20zXtesFKCJHu50xMxZKD1fX0TKaKHPsZfFkXfs7D1M9M6Eeqg1FkJ3a0x2dA==
+ version "7.20.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.6.tgz#63dae945963539ab0ad578efbf3eff271e7067ae"
+ integrity sha512-tqeujPiuEfcH067mx+7otTQWROVMKHXEaOQcAeNV5dDdbPWvPcFA8/W9LXw2NfjNmOetqLl03dfnG2WALPlsRQ==
dependencies:
core-js-pure "^3.25.1"
- regenerator-runtime "^0.13.10"
+ regenerator-runtime "^0.13.11"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.9.2":
- version "7.18.9"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz"
- integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
+ version "7.20.1"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
+ integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==
dependencies:
- regenerator-runtime "^0.13.4"
+ regenerator-runtime "^0.13.10"
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9", "@babel/runtime@^7.8.4":
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
+ version "7.20.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3"
+ integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==
+ dependencies:
+ regenerator-runtime "^0.13.11"
+
+"@babel/runtime@^7.8.4":
version "7.20.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.0.tgz#824a9ef325ffde6f78056059db3168c08785e24a"
integrity sha512-NDYdls71fTXoU8TZHfbBWg7DiZfNzClcKui/+kyi6ppD2L1qnWW3VV6CjtaBXSUGGhiTWJ6ereOIkUvenif66Q==
@@ -1579,9 +1586,9 @@
unstorage "^0.6.0"
"@netlify/plugin-nextjs@^4.27.3":
- version "4.28.3"
- resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-4.28.3.tgz#e1d3d413a75605efcedc2f3fc27501f9bc8a49e6"
- integrity sha512-fA+gOkIowfQVaL1YDF3t+3uCsZ7OEkandLpFIv0D1faA/6Fy7VxCWhAxowRQ6oV3SjYxsV259aRMT0LaRejLMw==
+ version "4.29.2"
+ resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-4.29.2.tgz#b59e484d12ccc50c54282dd49fcfe27cc692e7d0"
+ integrity sha512-Sxaf+eITuDEMUOQ5ySMMDibwi3KmLgbQ5gLVDFuOnm/YDe9l3cHTwJf0Sn4BkvDPTaz6p0kkxAHo2ANt91qwuA==
dependencies:
"@netlify/esbuild" "0.14.39"
"@netlify/functions" "^1.3.0"
@@ -1606,82 +1613,82 @@
slash "^3.0.0"
tiny-glob "^0.2.9"
-"@next/env@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.2.tgz#fb819366771f5721e9438ca3a42ad18684f0949b"
- integrity sha512-upwtMaHxlv/udAWGq0kE+rg8huwmcxQPsKZFhS1R5iVO323mvxEBe1YrSXe1awLbg9sTIuEHbgxjLLt7JbeuAQ==
+"@next/env@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.4.tgz#c787837d36fcad75d72ff8df6b57482027d64a47"
+ integrity sha512-H/69Lc5Q02dq3o+dxxy5O/oNxFsZpdL6WREtOOtOM1B/weonIwDXkekr1KV5DPVPr12IHFPrMrcJQ6bgPMfn7A==
-"@next/eslint-plugin-next@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.2.tgz#c965bb41fd5c36b6fc5fe066aeebf9385b69a62d"
- integrity sha512-Jx0BIS9STamGSbA+vgTxPAi1mRcq4DoH/5kPMs0PFLFi542mmIKUUtYWB61bI+G6KPMTqejYmO3zi+SF6tzGYg==
+"@next/eslint-plugin-next@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.4.tgz#e7dc00e2e89ed361f111d687b8534483ec15518b"
+ integrity sha512-BFwj8ykJY+zc1/jWANsDprDIu2MgwPOIKxNVnrKvPs+f5TPegrVnem8uScND+1veT4B7F6VeqgaNLFW1Hzl9Og==
dependencies:
glob "7.1.7"
-"@next/swc-android-arm-eabi@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.2.tgz#806e3be9741bc14aafdfad0f0c4c6a8de5b77ee1"
- integrity sha512-r2rrz+DZ8YYGqzVrbRrpP6GKzwozpOrnFbErc4k36vUTSFMag9yQahZfaBe06JYdqu/e5yhm/saIDEaSVPRP4g==
+"@next/swc-android-arm-eabi@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.4.tgz#fd1c2dafe92066c6120761c6a39d19e666dc5dd0"
+ integrity sha512-cM42Cw6V4Bz/2+j/xIzO8nK/Q3Ly+VSlZJTa1vHzsocJRYz8KT6MrreXaci2++SIZCF1rVRCDgAg5PpqRibdIA==
-"@next/swc-android-arm64@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.2.tgz#f9ec6b7fc746832a217ad6bb5478624d1a9a9822"
- integrity sha512-B+TINJhCf+CrY1+b3/JWQlkecv53rAGa/gA7gi5B1cnBa/2Uvoe+Ue0JeCefTjfiyl1ScsyNx+NcESY8Ye2Ngg==
+"@next/swc-android-arm64@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.4.tgz#11a146dae7b8bca007239b21c616e83f77b19ed4"
+ integrity sha512-5jf0dTBjL+rabWjGj3eghpLUxCukRhBcEJgwLedewEA/LJk2HyqCvGIwj5rH+iwmq1llCWbOky2dO3pVljrapg==
-"@next/swc-darwin-arm64@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.2.tgz#97c532d35c66ce6b6941ae24b5b8b267b9b0d0d8"
- integrity sha512-PTUfe1ZrwjsiuTmr3bOM9lsoy5DCmfYsLOUF9ZVhtbi5MNJVmUTy4VZ06GfrvnCO5hGCr48z3vpFE9QZ0qLcPw==
+"@next/swc-darwin-arm64@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.4.tgz#14ac8357010c95e67327f47082af9c9d75d5be79"
+ integrity sha512-DqsSTd3FRjQUR6ao0E1e2OlOcrF5br+uegcEGPVonKYJpcr0MJrtYmPxd4v5T6UCJZ+XzydF7eQo5wdGvSZAyA==
-"@next/swc-darwin-x64@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.2.tgz#e0cb4ff4b11faaff3a891bd1d18ed72f71e30ebe"
- integrity sha512-1HkjmS9awwlaeEY8Y01nRSNkSv3y+qnC/mjMPe/W66hEh3QKa/LQHqHeS7NOdEs19B2mhZ7w+EgMRXdLQ0Su8w==
+"@next/swc-darwin-x64@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.4.tgz#e7dc63cd2ac26d15fb84d4d2997207fb9ba7da0f"
+ integrity sha512-PPF7tbWD4k0dJ2EcUSnOsaOJ5rhT3rlEt/3LhZUGiYNL8KvoqczFrETlUx0cUYaXe11dRA3F80Hpt727QIwByQ==
-"@next/swc-freebsd-x64@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.2.tgz#d7b93dd344cb67d1969565d0796c7b7d0217fccf"
- integrity sha512-h5Mx0BKDCJ5Vu/U8e07esF6PjPv1EJgmRbYWTUZMAflu13MQpCJkKEJir7+BeRfTXRfgFf+llc7uocrpd7mcrg==
+"@next/swc-freebsd-x64@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.4.tgz#fe7ceec58746fdf03f1fcb37ec1331c28e76af93"
+ integrity sha512-KM9JXRXi/U2PUM928z7l4tnfQ9u8bTco/jb939pdFUHqc28V43Ohd31MmZD1QzEK4aFlMRaIBQOWQZh4D/E5lQ==
-"@next/swc-linux-arm-gnueabihf@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.2.tgz#c2170a89effe00fdd65798c99684fd93a02b197c"
- integrity sha512-EuRZAamoxfe/WoWRaC0zsCAoE4gs/mEhilcloNM4J5Mnb3PLY8PZV394W7t5tjBjItMCF7l2Ebwjwtm46tq2RA==
+"@next/swc-linux-arm-gnueabihf@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.4.tgz#d7016934d02bfc8bd69818ffb0ae364b77b17af7"
+ integrity sha512-3zqD3pO+z5CZyxtKDTnOJ2XgFFRUBciOox6EWkoZvJfc9zcidNAQxuwonUeNts6Xbm8Wtm5YGIRC0x+12YH7kw==
-"@next/swc-linux-arm64-gnu@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.2.tgz#26df7d7cdc18cf413f12a408179ee4ac315f383a"
- integrity sha512-T9GCFyOIb4S3acA9LqflUYD+QZ94iZketHCqKdoO0Nx0OCHIgGJV5rotDe8TDXwh/goYpIfyHU4j1qqw4w4VnA==
+"@next/swc-linux-arm64-gnu@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.4.tgz#43a7bc409b03487bff5beb99479cacdc7bd29af5"
+ integrity sha512-kiX0vgJGMZVv+oo1QuObaYulXNvdH/IINmvdZnVzMO/jic/B8EEIGlZ8Bgvw8LCjH3zNVPO3mGrdMvnEEPEhKA==
-"@next/swc-linux-arm64-musl@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.2.tgz#fd42232a6b10d9f9a4f71433d59c280a4532d06f"
- integrity sha512-hxNVZS6L3c2z3l9EH2GP0MGQ9exu6O8cohYNZyqC9WUl6C03sEn8xzDH1y+NgD3fVurvYkGU5F0PDddJJLfDIw==
+"@next/swc-linux-arm64-musl@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.4.tgz#4d1db6de6dc982b974cd1c52937111e3e4a34bd3"
+ integrity sha512-EETZPa1juczrKLWk5okoW2hv7D7WvonU+Cf2CgsSoxgsYbUCZ1voOpL4JZTOb6IbKMDo6ja+SbY0vzXZBUMvkQ==
-"@next/swc-linux-x64-gnu@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.2.tgz#5307579e3d8fbdb03adbe6cfc915b51548e0a103"
- integrity sha512-fCPkLuwDwY8/QeXxciJJjDHG09liZym/Bhb4A+RLFQ877wUkwFsNWDUTSdUx0YXlYK/1gf67BKauqKkOKp6CYw==
+"@next/swc-linux-x64-gnu@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.4.tgz#c3b414d77bab08b35f7dd8943d5586f0adb15e38"
+ integrity sha512-4csPbRbfZbuWOk3ATyWcvVFdD9/Rsdq5YHKvRuEni68OCLkfy4f+4I9OBpyK1SKJ00Cih16NJbHE+k+ljPPpag==
-"@next/swc-linux-x64-musl@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.2.tgz#d5cb920a825a8dc80ffba8a6b797fb845af0b84c"
- integrity sha512-o+GifBIQ2K+/MEFxHsxUZoU3bsuVFLXZYWd3idimFHiVdDCVYiKsY6mYMmKDlucX+9xRyOCkKL9Tjf+3tuXJpw==
+"@next/swc-linux-x64-musl@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.4.tgz#187a883ec09eb2442a5ebf126826e19037313c61"
+ integrity sha512-YeBmI+63Ro75SUiL/QXEVXQ19T++58aI/IINOyhpsRL1LKdyfK/35iilraZEFz9bLQrwy1LYAR5lK200A9Gjbg==
-"@next/swc-win32-arm64-msvc@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.2.tgz#2a0d619e5bc0cec17ed093afd1ca6b1c37c2690c"
- integrity sha512-crii66irzGGMSUR0L8r9+A06eTv7FTXqw4rgzJ33M79EwQJOdpY7RVKXLQMurUhniEeQEEOfamiEdPIi/qxisw==
+"@next/swc-win32-arm64-msvc@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.4.tgz#89befa84e453ed2ef9a888f375eba565a0fde80b"
+ integrity sha512-Sd0qFUJv8Tj0PukAYbCCDbmXcMkbIuhnTeHm9m4ZGjCf6kt7E/RMs55Pd3R5ePjOkN7dJEuxYBehawTR/aPDSQ==
-"@next/swc-win32-ia32-msvc@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.2.tgz#769bef60d0d678c3d7606a4dc7fee018d6199227"
- integrity sha512-5hRUSvn3MdQ4nVRu1rmKxq5YJzpTtZfaC/NyGw6wa4NSF1noUn/pdQGUr+I5Qz3CZkd1gZzzC0eaXQHlrk0E2g==
+"@next/swc-win32-ia32-msvc@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.4.tgz#cb50c08f0e40ead63642a7f269f0c8254261f17c"
+ integrity sha512-rt/vv/vg/ZGGkrkKcuJ0LyliRdbskQU+91bje+PgoYmxTZf/tYs6IfbmgudBJk6gH3QnjHWbkphDdRQrseRefQ==
-"@next/swc-win32-x64-msvc@12.3.2":
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.2.tgz#45beb4b9d28e6dd6abf63cab1c5b92dc84323a6b"
- integrity sha512-tpQJYUH+TzPMIsdVl9fH8uDg47iwiNjKY+8e9da3dXqlkztKzjSw0OwSADoqh3KrifplXeKSta+BBGLdBqg3sg==
+"@next/swc-win32-x64-msvc@12.3.4":
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.4.tgz#d28ea15a72cdcf96201c60a43e9630cd7fda168f"
+ integrity sha512-DQ20JEfTBZAgF8QCjYfJhv2/279M6onxFjdG/+5B0Cyj00/EdBxiWb2eGGFgQhrBbNv/lsvzFbbi0Ptf8Vw/bg==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -1721,91 +1728,125 @@
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.5.0.tgz#82df347a893a5ae2a67707d44772ba181f4b9328"
integrity sha512-4t9ir2SbQQr/wMCNU4YpHWp5hU14J2m3wHUZnGJPpmBF8YtkisxyVyQsKd1e6FyLTaGq8LOLhm6VLYHKqKNm+g==
-"@react-spring/animated@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/animated/-/animated-9.5.2.tgz"
- integrity sha512-oRlX+MmYLbK8IuUZR7SQUnRjXxJ4PMIZeBkBd1SUWVgVJAHMTfJzPltzm+I6p59qX+qLlklYHfnWaonQKDqLuQ==
+"@react-spring/animated@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.5.5.tgz#d3bfd0f62ed13a337463a55d2c93bb23c15bbf3e"
+ integrity sha512-glzViz7syQ3CE6BQOwAyr75cgh0qsihm5lkaf24I0DfU63cMm/3+br299UEYkuaHNmfDfM414uktiPlZCNJbQA==
dependencies:
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/core@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/core/-/core-9.5.2.tgz"
- integrity sha512-UMRtFH6EfebMp/NMDGCUY5+hZFXsg9iT9hzt/iPzJSz2WMXKBjLoFZHJXcmiVOrIhzHmg1O0pFECn1Wp6pZ5Gw==
+"@react-spring/core@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.5.5.tgz#1d8a4c64630ee26b2295361e1eedfd716a85b4ae"
+ integrity sha512-shaJYb3iX18Au6gkk8ahaF0qx0LpS0Yd+ajb4asBaAQf6WPGuEdJsbsNSgei1/O13JyEATsJl20lkjeslJPMYA==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/rafz" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/rafz" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/konva@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/konva/-/konva-9.5.2.tgz"
- integrity sha512-FN8LpbGQtm2pllU9mOyYjYwvLtA9EiIPWk2NVuhhX+5lJZrdCWuEY7EyFpK8PtgZXBdVj8bj7eIu1LlTnARW/A==
+"@react-spring/konva@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.5.5.tgz#ddbb30cfa268219d69552aa71188832ca8ab4905"
+ integrity sha512-0CNh+1vCIjNUklTFwMvxg+H83Jo2OWykBrdEA28ccmnpZgkQ8Kq5xyvaPFLzcDKV67OXHnaWiCYKpRbhLy2wng==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/core" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/native@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/native/-/native-9.5.2.tgz"
- integrity sha512-G9BCAKVADLweLR43uyMnTrOnYDb4BboYvqKY+0X1fLs45PNrfbBXnSLot4g+5x3HjblypJgNq7CjHlqZKI980g==
+"@react-spring/native@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.5.5.tgz#4ecc420c7b4c3fefeebd55d852640d36c29ec9c8"
+ integrity sha512-kauqmyJ8u7aVy2bBs22vl1SdB2i5uYIL4rP53k1KDWrFSqJh4j3efWkbTt9uzR5cMXuNVbkNo9OYVFUcQBz50A==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/core" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/rafz@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.5.2.tgz"
- integrity sha512-xHSRXKKBI/wDUkZGrspkOm4VlgN6lZi8Tw9Jzibp9QKf3neoof+U2mDNgklvnLaasymtUwAq9o4ZfFvQIVNgPQ==
+"@react-spring/rafz@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.5.5.tgz#62a49c5e294104b79db2a8afdf4f3a274c7f44ca"
+ integrity sha512-F/CLwB0d10jL6My5vgzRQxCNY2RNyDJZedRBK7FsngdCmzoq3V4OqqNc/9voJb9qRC2wd55oGXUeXv2eIaFmsw==
-"@react-spring/shared@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/shared/-/shared-9.5.2.tgz"
- integrity sha512-/OSf2sjwY4BUnjZL6xMC+H3WxOOhMUCk+yZwgdj40XuyUpk6E6tYyiPeD9Yq5GLsZHodkvE1syVMRVReL4ndAg==
+"@react-spring/shared@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.5.5.tgz#9be0b391d546e3e184a24ecbaf40acbaeab7fc73"
+ integrity sha512-YwW70Pa/YXPOwTutExHZmMQSHcNC90kJOnNR4G4mCDNV99hE98jWkIPDOsgqbYx3amIglcFPiYKMaQuGdr8dyQ==
dependencies:
- "@react-spring/rafz" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/rafz" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/three@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/three/-/three-9.5.2.tgz"
- integrity sha512-3H7Lv8BJZ3dajh0yJA3m9rEbqz5ZNrTCAkhVOeLqgvBlcWU5qVs4luYA1Z7H4vZnLqVtzv+kHAyg3XIpuTOXhQ==
+"@react-spring/three@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.5.5.tgz#c6fbee977007d1980406db20a28ac3f5dc2ce153"
+ integrity sha512-9kTIaSceqFIl5EIrdwM7Z53o5I+9BGNVzbp4oZZYMao+GMAWOosnlQdDG5GeqNsIqfW9fZCEquGqagfKAxftcA==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/core" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/types@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/types/-/types-9.5.2.tgz"
- integrity sha512-n/wBRSHPqTmEd4BFWY6TeR1o/UY+3ujoqMxLjqy90CcY/ozJzDRuREL3c+pxMeTF2+B7dX33dTPCtFMX51nbxg==
+"@react-spring/types@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.5.5.tgz#c8e94f1b9232ca7cb9d860ea67762ec401b1de14"
+ integrity sha512-7I/qY8H7Enwasxr4jU6WmtNK+RZ4Z/XvSlDvjXFVe7ii1x0MoSlkw6pD7xuac8qrHQRm9BTcbZNyeeKApYsvCg==
-"@react-spring/web@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/web/-/web-9.5.2.tgz"
- integrity sha512-cusTjbOGTgtbsnpBDjb6Ia+B0lQLE0Fk5rGDog6Sww7hWnLIQ521PMiOBnAWtkntB9eXDUfj7L91nwJviEC0lw==
+"@react-spring/web@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.5.5.tgz#d416abc591aaed930401f0c98a991a8c5b90c382"
+ integrity sha512-+moT8aDX/ho/XAhU+HRY9m0LVV9y9CK6NjSRaI+30Re150pB3iEip6QfnF4qnhSCQ5drpMF0XRXHgOTY/xbtFw==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/core" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
-"@react-spring/zdog@~9.5.2":
- version "9.5.2"
- resolved "https://registry.npmjs.org/@react-spring/zdog/-/zdog-9.5.2.tgz"
- integrity sha512-zUX8RzX8gM51g8NJ5Qaf15KNKQgN3qN/8m5FvqmiqZ5ZGqjoHkbCoMD3o2MICTUN1l+d4eUu9TYrmiO2bgJo/g==
+"@react-spring/zdog@~9.5.5":
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.5.5.tgz#916dba337637d1151c3c2bc829b5105d15adacb5"
+ integrity sha512-LZgjo2kLlGmUqfE2fdVnvLXz+4eYyQARRvB9KQ4PTEynaETTG89Xgn9YxLrh1p57DzH7gEmTGDZ5hEw3pWqu8g==
dependencies:
- "@react-spring/animated" "~9.5.2"
- "@react-spring/core" "~9.5.2"
- "@react-spring/shared" "~9.5.2"
- "@react-spring/types" "~9.5.2"
+ "@react-spring/animated" "~9.5.5"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/shared" "~9.5.5"
+ "@react-spring/types" "~9.5.5"
+
+"@redis/bloom@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.1.0.tgz#64e310ddee72010676e14296076329e594a1f6c7"
+ integrity sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==
+
+"@redis/client@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.4.2.tgz#2a3f5e98bc33b7b979390442e6e08f96e57fabdd"
+ integrity sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==
+ dependencies:
+ cluster-key-slot "1.1.1"
+ generic-pool "3.9.0"
+ yallist "4.0.0"
+
+"@redis/graph@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.1.0.tgz#cc2b82e5141a29ada2cce7d267a6b74baa6dd519"
+ integrity sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==
+
+"@redis/json@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.4.tgz#f372b5f93324e6ffb7f16aadcbcb4e5c3d39bda1"
+ integrity sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==
+
+"@redis/search@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.0.tgz#7abb18d431f27ceafe6bcb4dd83a3fa67e9ab4df"
+ integrity sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==
+
+"@redis/time-series@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717"
+ integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==
"@rollup/plugin-buble@^0.21.3":
version "0.21.3"
@@ -1951,6 +1992,19 @@
dependencies:
tslib "^2.4.0"
+"@tanstack/query-core@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.19.0.tgz#be1ad7bfbc4edb68e21ab2a86dd4c52233a40c87"
+ integrity sha512-q+4GvS05nG2UXDE4ng0NU5SQNhT+VqhRTLNVtgVw1tIKJfG3CyYQpP/JwAdzMB7NEqC8L5oo9NAaORxEQN53dg==
+
+"@tanstack/react-query@^4.16.1":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.19.0.tgz#353169522ff2e6dcfcc36c95ba4c151974a7ec92"
+ integrity sha512-gP4kmfQ3BvCYxTxA/3Xf0P24iNgW539Thk89KzP7X+i+EvFiWhEUMl1NtuI87bFrVEBHs+1ColFNimDidBh/Ww==
+ dependencies:
+ "@tanstack/query-core" "4.19.0"
+ use-sync-external-store "^1.2.0"
+
"@trysound/sax@0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
@@ -2015,7 +2069,7 @@
"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
- resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
@@ -2063,12 +2117,12 @@
"@types/prop-types@*":
version "15.7.5"
- resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
"@types/react-redux@^7.1.20":
version "7.1.24"
- resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0"
integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
@@ -2076,7 +2130,16 @@
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
-"@types/react@*", "@types/react@16 || 17 || 18":
+"@types/react@*":
+ version "18.0.25"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44"
+ integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/react@16 || 17 || 18":
version "18.0.10"
resolved "https://registry.npmjs.org/@types/react/-/react-18.0.10.tgz"
integrity sha512-dIugadZuIPrRzvIEevIu7A1smqOAjkSMv8qOfwPt9Ve6i6JT/FQcCHyk2qIAxwsQNKZt5/oGR0T4z9h2dXRAkg==
@@ -2087,7 +2150,7 @@
"@types/scheduler@*":
version "0.16.2"
- resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/schema-utils@^2.4.0":
@@ -2098,47 +2161,47 @@
schema-utils "*"
"@typescript-eslint/parser@^5.21.0":
- version "5.42.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.42.0.tgz#be0ffbe279e1320e3d15e2ef0ad19262f59e9240"
- integrity sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==
+ version "5.45.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.45.0.tgz#b18a5f6b3cf1c2b3e399e9d2df4be40d6b0ddd0e"
+ integrity sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==
dependencies:
- "@typescript-eslint/scope-manager" "5.42.0"
- "@typescript-eslint/types" "5.42.0"
- "@typescript-eslint/typescript-estree" "5.42.0"
+ "@typescript-eslint/scope-manager" "5.45.0"
+ "@typescript-eslint/types" "5.45.0"
+ "@typescript-eslint/typescript-estree" "5.45.0"
debug "^4.3.4"
-"@typescript-eslint/scope-manager@5.42.0":
- version "5.42.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz#e1f2bb26d3b2a508421ee2e3ceea5396b192f5ef"
- integrity sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==
+"@typescript-eslint/scope-manager@5.45.0":
+ version "5.45.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz#7a4ac1bfa9544bff3f620ab85947945938319a96"
+ integrity sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==
dependencies:
- "@typescript-eslint/types" "5.42.0"
- "@typescript-eslint/visitor-keys" "5.42.0"
+ "@typescript-eslint/types" "5.45.0"
+ "@typescript-eslint/visitor-keys" "5.45.0"
-"@typescript-eslint/types@5.42.0":
- version "5.42.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.42.0.tgz#5aeff9b5eced48f27d5b8139339bf1ef805bad7a"
- integrity sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==
+"@typescript-eslint/types@5.45.0":
+ version "5.45.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.45.0.tgz#794760b9037ee4154c09549ef5a96599621109c5"
+ integrity sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==
-"@typescript-eslint/typescript-estree@5.42.0":
- version "5.42.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz#2592d24bb5f89bf54a63384ff3494870f95b3fd8"
- integrity sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==
+"@typescript-eslint/typescript-estree@5.45.0":
+ version "5.45.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz#f70a0d646d7f38c0dfd6936a5e171a77f1e5291d"
+ integrity sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==
dependencies:
- "@typescript-eslint/types" "5.42.0"
- "@typescript-eslint/visitor-keys" "5.42.0"
+ "@typescript-eslint/types" "5.45.0"
+ "@typescript-eslint/visitor-keys" "5.45.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
-"@typescript-eslint/visitor-keys@5.42.0":
- version "5.42.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz#ee8d62d486f41cfe646632fab790fbf0c1db5bb0"
- integrity sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==
+"@typescript-eslint/visitor-keys@5.45.0":
+ version "5.45.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz#e0d160e9e7fdb7f8da697a5b78e7a14a22a70528"
+ integrity sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==
dependencies:
- "@typescript-eslint/types" "5.42.0"
+ "@typescript-eslint/types" "5.45.0"
eslint-visitor-keys "^3.3.0"
"@vercel/node-bridge@^2.1.0":
@@ -2317,9 +2380,9 @@ ajv@^8.0.0, ajv@^8.8.0:
uri-js "^4.2.2"
ajv@^8.0.1:
- version "8.11.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
- integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
+ version "8.11.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78"
+ integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
@@ -2358,9 +2421,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
color-convert "^2.0.1"
anymatch@^3.1.2, anymatch@~3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
- integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
@@ -2390,7 +2453,7 @@ array-find-index@^1.0.1:
resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz"
integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==
-array-includes@^3.1.4, array-includes@^3.1.5:
+array-includes@^3.1.4:
version "3.1.5"
resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz"
integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==
@@ -2401,6 +2464,17 @@ array-includes@^3.1.4, array-includes@^3.1.5:
get-intrinsic "^1.1.1"
is-string "^1.0.7"
+array-includes@^3.1.5, array-includes@^3.1.6:
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f"
+ integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ get-intrinsic "^1.1.3"
+ is-string "^1.0.7"
+
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@@ -2416,16 +2490,27 @@ array.prototype.flat@^1.2.5:
es-abstract "^1.19.2"
es-shim-unscopables "^1.0.0"
-array.prototype.flatmap@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f"
- integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==
+array.prototype.flatmap@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
+ integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
es-shim-unscopables "^1.0.0"
+array.prototype.tosorted@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532"
+ integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+ get-intrinsic "^1.1.3"
+
arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -2486,9 +2571,9 @@ aws4@^1.8.0:
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axe-core@^4.4.3:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.5.0.tgz#6efe2ecdba205fcc9d7ddb3d48c2cf630f70eb5e"
- integrity sha512-4+rr8eQ7+XXS5nZrKcMO/AikHL0hVqy+lHWAnE3xdHl+aguag8SOQ6eEqLexwLNWgXIMfunGuD3ON1/6Kyet0A==
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.5.2.tgz#823fdf491ff717ac3c58a52631d4206930c1d9f7"
+ integrity sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA==
axobject-query@^2.2.0:
version "2.2.0"
@@ -2686,11 +2771,16 @@ caniuse-lite@^1.0.30001335:
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz"
integrity sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==
-caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001406:
+caniuse-lite@^1.0.30001400:
version "1.0.30001427"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001427.tgz#d3a749f74be7ae0671fbec3a4eea18576e8ad646"
integrity sha512-lfXQ73oB9c8DP5Suxaszm+Ta2sr/4tf8+381GkIm1MLj/YdLf+rEDyDSRCzeltuyTVGm+/s18gdZ0q+Wmp8VsQ==
+caniuse-lite@^1.0.30001406:
+ version "1.0.30001435"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001435.tgz#502c93dbd2f493bee73a408fe98e98fb1dad10b2"
+ integrity sha512-kdCkUTjR+v4YAJelyiDTqiu82BDr4W4CP5sgTA0ZBmqn30XfS2ZghPLMowik9TPhS+psWJiUNxsqLyurDbmutA==
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz"
@@ -2758,7 +2848,7 @@ chownr@^1.1.1:
chownr@^2.0.0:
version "2.0.0"
- resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
ci-info@^3.2.0:
@@ -2814,6 +2904,11 @@ clipboardy@^3.0.0:
execa "^5.1.1"
is-wsl "^2.2.0"
+cluster-key-slot@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz#10ccb9ded0729464b6d2e7d714b100a2d1259d43"
+ integrity sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==
+
cluster-key-slot@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz"
@@ -2934,9 +3029,9 @@ core-js-compat@^3.25.1:
browserslist "^4.21.4"
core-js-pure@^3.25.1:
- version "3.26.0"
- resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.0.tgz#7ad8a5dd7d910756f3124374b50026e23265ca9a"
- integrity sha512-LiN6fylpVBVwT8twhhluD9TzXmZQQsr2I2eIKtWNbZI1XMfBT7CV18itaN6RA7EtQd/SDdRx/wzvAShX2HvhQA==
+ version "3.26.1"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33"
+ integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ==
core-util-is@1.0.2:
version "1.0.2"
@@ -2951,10 +3046,10 @@ cors@^2.8.5:
object-assign "^4"
vary "^1"
-cosmiconfig@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
- integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
+cosmiconfig@^7.0.1, cosmiconfig@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
+ integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
dependencies:
"@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
@@ -2998,7 +3093,7 @@ css-blank-pseudo@^3.0.3:
css-box-model@^1.2.0:
version "1.2.1"
- resolved "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz"
+ resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==
dependencies:
tiny-invariant "^1.0.6"
@@ -3072,9 +3167,9 @@ csstype@^2.6.8:
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
csstype@^3.0.2:
- version "3.1.0"
- resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz"
- integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
currently-unhandled@^0.4.1:
version "0.4.1"
@@ -3173,18 +3268,18 @@ dashdash@^1.12.0:
data-uri-to-buffer@^4.0.0:
version "4.0.0"
- resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz"
+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==
date-fns-tz@^1.1.4:
- version "1.3.6"
- resolved "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.3.6.tgz"
- integrity sha512-C8q7mErvG4INw1ZwAFmPlGjEo5Sv4udjKVbTc03zpP9cu6cp5AemFzKhz0V68LGcWEtX5mJudzzg3G04emIxLA==
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/date-fns-tz/-/date-fns-tz-1.3.7.tgz#e8e9d2aaceba5f1cc0e677631563081fdcb0e69a"
+ integrity sha512-1t1b8zyJo+UI8aR+g3iqr5fkUHWpd58VBx8J/ZSQ+w7YrGlw80Ag4sA86qkfCXRBLmMc4I2US+aPMd4uKvwj5g==
date-fns@^2.23.0:
- version "2.29.2"
- resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz"
- integrity sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==
+ version "2.29.3"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
+ integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
dateformat@^5.0.3:
version "5.0.3"
@@ -3273,9 +3368,9 @@ define-properties@^1.1.3, define-properties@^1.1.4:
object-keys "^1.1.1"
defu@^6.0.0, defu@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.0.tgz#7a5411655da73335c7d933256911f17c74443e2d"
- integrity sha512-pOFYRTIhoKujrmbTRhcW5lYQLBXw/dlTwfI8IguF1QCDJOcJzNH1w+YFjxqy6BAuJrClTy6MUE8q+oKJ2FLsIw==
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.1.tgz#a12c712349197c545dc61d3cd3b607b4cc7ef0c1"
+ integrity sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA==
del@^6.0.0:
version "6.1.1"
@@ -3302,9 +3397,9 @@ denque@^2.0.1:
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
destr@^1.1.1, destr@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/destr/-/destr-1.2.0.tgz#8adb17fa3861b8032ea1bba92f60ba989a9ff119"
- integrity sha512-JG+cG4ZPB1L27sl2C2URg8MIOmIUtTbE5wEx02BpmrTCqg/hXxFKXsYsnODl5PdpqNRaS1KQGUQ56V8jk8XpYQ==
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/destr/-/destr-1.2.1.tgz#03f2e7cbcd01f9190938d05718948de9d7dfb71a"
+ integrity sha512-ud8w0qMLlci6iFG7CNgeRr8OcbUWMsbfjtWft1eJ5Luqrz/M8Ebqk/KCzne8rKUlIQWWfLv0wD6QHrqOf4GshA==
detect-browser@^5.2.0:
version "5.3.0"
@@ -3438,7 +3533,7 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5:
+es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.4:
version "1.20.4"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861"
integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==
@@ -3500,11 +3595,11 @@ escape-string-regexp@^4.0.0:
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@^12.2.4:
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.2.tgz#3dd50a9ae5acf77f0ca5c94d77b604e40c67bf5c"
- integrity sha512-ir8t3wRNexUMSKsMNh7J1EWwiBAr2dd015UAiCFvQ/01MRBPmFof1C6PFh/RqlupwamSZlv6j8gfaV1RxHuRoQ==
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.4.tgz#3d4d9e74b919b879c4cc79c61bdc388fb2b964ee"
+ integrity sha512-WuT3gvgi7Bwz00AOmKGhOeqnyA5P29Cdyr0iVjLyfDbk+FANQKcOjFUTZIdyYfe5Tq1x4TGcmoe4CwctGvFjHQ==
dependencies:
- "@next/eslint-plugin-next" "12.3.2"
+ "@next/eslint-plugin-next" "12.3.4"
"@rushstack/eslint-patch" "^1.1.3"
"@typescript-eslint/parser" "^5.21.0"
eslint-import-resolver-node "^0.3.6"
@@ -3601,24 +3696,25 @@ eslint-plugin-react-hooks@^4.5.0:
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
eslint-plugin-react@^7.31.7:
- version "7.31.10"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz#6782c2c7fe91c09e715d536067644bbb9491419a"
- integrity sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==
+ version "7.31.11"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz#011521d2b16dcf95795df688a4770b4eaab364c8"
+ integrity sha512-TTvq5JsT5v56wPa9OYHzsrOlHzKZKjV+aLgS+55NJP/cuzdiQPC7PfYoUjMoxlffKtvijpk7vA/jmuqRb9nohw==
dependencies:
- array-includes "^3.1.5"
- array.prototype.flatmap "^1.3.0"
+ array-includes "^3.1.6"
+ array.prototype.flatmap "^1.3.1"
+ array.prototype.tosorted "^1.1.1"
doctrine "^2.1.0"
estraverse "^5.3.0"
jsx-ast-utils "^2.4.1 || ^3.0.0"
minimatch "^3.1.2"
- object.entries "^1.1.5"
- object.fromentries "^2.0.5"
- object.hasown "^1.1.1"
- object.values "^1.1.5"
+ object.entries "^1.1.6"
+ object.fromentries "^2.0.6"
+ object.hasown "^1.1.2"
+ object.values "^1.1.6"
prop-types "^15.8.1"
resolve "^2.0.0-next.3"
semver "^6.3.0"
- string.prototype.matchall "^4.0.7"
+ string.prototype.matchall "^4.0.8"
eslint-scope@^5.1.1:
version "5.1.1"
@@ -3871,7 +3967,7 @@ fastq@^1.6.0:
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
version "3.2.0"
- resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz"
+ resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
dependencies:
node-domexception "^1.0.0"
@@ -3946,7 +4042,7 @@ form-data@~2.3.2:
formdata-polyfill@^4.0.10:
version "4.0.10"
- resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz"
+ resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
dependencies:
fetch-blob "^3.1.2"
@@ -4000,7 +4096,7 @@ fs-memo@^1.2.0:
fs-minipass@^2.0.0:
version "2.1.0"
- resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
dependencies:
minipass "^3.0.0"
@@ -4040,6 +4136,11 @@ functions-have-names@^1.2.2:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+generic-pool@3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
+ integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==
+
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@@ -4258,7 +4359,7 @@ has@^1.0.3:
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
- resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
@@ -4315,9 +4416,9 @@ ignore@^4.0.6:
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
ignore@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
- integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c"
+ integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==
image-meta@^0.1.1:
version "0.1.1"
@@ -4331,7 +4432,7 @@ immer@^9.0.12:
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.3.0"
- resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
dependencies:
parent-module "^1.0.0"
@@ -4659,9 +4760,9 @@ is-wsl@^2.2.0:
is-docker "^2.0.0"
isbot@^3.4.5:
- version "3.6.2"
- resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.6.2.tgz#aad0b8b44cd1bbb82822aac9498b2c6f3eafbce8"
- integrity sha512-jk8IRbrvyTJC2f4VpxXQ4ff+xVJgsXHygtpc5Sl6m9PWuF8oXVcpEmcZKR88j5WOoqpHTxrOKccCpxdAgW7Afw==
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.6.5.tgz#a749980d9dfba9ebcc03ee7b548d1f24dd8c9f1e"
+ integrity sha512-BchONELXt6yMad++BwGpa0oQxo/uD0keL7N15cYVf0A1oMIoNQ79OqeYdPMFWDrNhCqCbRuw9Y9F3QBjvAxZ5g==
isexe@^2.0.0:
version "2.0.0"
@@ -4835,9 +4936,9 @@ jws@^3.2.2:
safe-buffer "^5.0.1"
kafkajs@^2.1.0:
- version "2.2.0"
- resolved "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.0.tgz"
- integrity sha512-+sdgyLuC0Idw1g9LSBXjtoCr4K+vVaHP+tulzAK+V+HHvO3uW5woNkzLnbBx0MN4WRuEl/5g84M3FSkH0ZDzrA==
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/kafkajs/-/kafkajs-2.2.3.tgz#a1ab1b7c4a27699871a89b3978b5cfe5b05c6f3e"
+ integrity sha512-JmzIiLHE/TdQ7b4I2B/DNMtfhTh66fmEaEg7gGkyQXBC6f1A7I2jSjeUsVIJfC8d9YcEIURyBjtOEKBO5OHVhg==
kind-of@^6.0.2, kind-of@^6.0.3:
version "6.0.3"
@@ -4849,22 +4950,22 @@ kleur@^3.0.3:
resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-known-css-properties@^0.25.0:
- version "0.25.0"
- resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
- integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==
+known-css-properties@^0.26.0:
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.26.0.tgz#008295115abddc045a9f4ed7e2a84dc8b3a77649"
+ integrity sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==
-language-subtag-registry@~0.3.2:
+language-subtag-registry@^0.3.20:
version "0.3.22"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
language-tags@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a"
- integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.6.tgz#c087cc42cd92eb71f0925e9e271d4f8be5a93430"
+ integrity sha512-HNkaCgM8wZgE/BZACeotAAgpL9FUjEnhgF0FVQMIgH//zqTPreLYMb3rWYkYAqPoF75Jwuycp1da7uz66cfFQg==
dependencies:
- language-subtag-registry "~0.3.2"
+ language-subtag-registry "^0.3.20"
levn@^0.4.1:
version "0.4.1"
@@ -4913,9 +5014,9 @@ listhen@^0.2.15:
ufo "^0.8.5"
listhen@^0.3.4:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/listhen/-/listhen-0.3.4.tgz#5bb0db65dae5f2204ffa7ee46b40f2330854cf7f"
- integrity sha512-cuzWWoIWF8JvsPLmIurTkUXi27owH4RRKnBsbPswRJvB82uTv15W01yOOLaPvjxY5mMlftmW2p1XnxB835AdRA==
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/listhen/-/listhen-0.3.5.tgz#04a0f6dbdab5bbac711992004a37c8306fad3e4e"
+ integrity sha512-suyt79hNmCFeBIyftcLqLPfYiXeB795gSUWOJT7nspl2IvREY0Q9xvchLhekxvQ0KiOPvWoyALnc9Mxoelm0Pw==
dependencies:
clipboardy "^3.0.0"
colorette "^2.0.19"
@@ -4924,7 +5025,7 @@ listhen@^0.3.4:
http-shutdown "^1.2.2"
ip-regex "^5.0.0"
node-forge "^1.3.1"
- ufo "^0.8.5"
+ ufo "^0.8.6"
listr2@^3.12.2:
version "3.14.0"
@@ -5116,12 +5217,12 @@ mathml-tag-names@^2.1.3:
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
maxmind@^4.3.6:
- version "4.3.6"
- resolved "https://registry.npmjs.org/maxmind/-/maxmind-4.3.6.tgz"
- integrity sha512-CwnEZqJX0T6b2rWrc0/V3n9hL/hWAMEn7fY09077YJUHiHx7cn/esA2ZIz8BpYLSJUf7cGVel0oUJa9jMwyQpg==
+ version "4.3.8"
+ resolved "https://registry.yarnpkg.com/maxmind/-/maxmind-4.3.8.tgz#e284edd3619987211ee45909076c6d4fcd2dc4df"
+ integrity sha512-HrfxEu5yPBPtTy/OT+W5bPQwEfLUX0EHqe2EbJiB47xQMumHqXvSP7PAwzV8Z++NRCmQwy4moQrTSt0+dH+Jmg==
dependencies:
mmdb-lib "2.0.2"
- tiny-lru "8.0.2"
+ tiny-lru "9.0.3"
mdn-data@2.0.14:
version "2.0.14"
@@ -5130,7 +5231,7 @@ mdn-data@2.0.14:
"memoize-one@>=3.1.1 <6", memoize-one@^5.1.1:
version "5.2.1"
- resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
memorystream@^0.3.1:
@@ -5250,15 +5351,15 @@ minimist@^1.2.5:
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
minipass@^3.0.0:
- version "3.1.6"
- resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz"
- integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae"
+ integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==
dependencies:
yallist "^4.0.0"
minizlib@^2.1.1:
version "2.1.2"
- resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
dependencies:
minipass "^3.0.0"
@@ -5276,12 +5377,12 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
mkdirp@^1.0.3, mkdirp@^1.0.4:
version "1.0.4"
- resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mmdb-lib@2.0.2:
version "2.0.2"
- resolved "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz"
+ resolved "https://registry.yarnpkg.com/mmdb-lib/-/mmdb-lib-2.0.2.tgz#fe60404142c0456c19607c72caa15821731ae957"
integrity sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==
moize@^6.1.0:
@@ -5293,9 +5394,9 @@ moize@^6.1.0:
micro-memoize "^4.0.11"
moment-timezone@^0.5.35:
- version "0.5.38"
- resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.38.tgz#9674a5397b8be7c13de820fd387d8afa0f725aad"
- integrity sha512-nMIrzGah4+oYZPflDvLZUgoVUO4fvAqHstvG3xAUnMolWncuAiLDWNnJZj6EwJGMGfb1ZcuTFE6GI3hNOVWI/Q==
+ version "0.5.39"
+ resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.39.tgz#342625a3b98810f04c8f4ea917e448d3525e600b"
+ integrity sha512-hoB6suq4ISDj7BDgctiOy6zljBsdYT0++0ZzZm9rtxIvJhIbQ3nmbgSWe7dNFGurl6/7b1OUkHlmN9JWgXVz7w==
dependencies:
moment ">= 2.9.0"
@@ -5354,30 +5455,30 @@ next-basics@^0.23.0:
jsonwebtoken "^8.5.1"
next@^12.3.1:
- version "12.3.2"
- resolved "https://registry.yarnpkg.com/next/-/next-12.3.2.tgz#3a3356a8d752726128825a8bdf17f2a3b3f861cf"
- integrity sha512-orzvvebCwOqaz1eA5ZA0R5dbKxqtJyw7yeig7kDspu6p8OrplfyelzpvMHcDTKscv/l0nn/0l0v3mSsE8w4k7A==
+ version "12.3.4"
+ resolved "https://registry.yarnpkg.com/next/-/next-12.3.4.tgz#f2780a6ebbf367e071ce67e24bd8a6e05de2fcb1"
+ integrity sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ==
dependencies:
- "@next/env" "12.3.2"
+ "@next/env" "12.3.4"
"@swc/helpers" "0.4.11"
caniuse-lite "^1.0.30001406"
postcss "8.4.14"
styled-jsx "5.0.7"
use-sync-external-store "1.2.0"
optionalDependencies:
- "@next/swc-android-arm-eabi" "12.3.2"
- "@next/swc-android-arm64" "12.3.2"
- "@next/swc-darwin-arm64" "12.3.2"
- "@next/swc-darwin-x64" "12.3.2"
- "@next/swc-freebsd-x64" "12.3.2"
- "@next/swc-linux-arm-gnueabihf" "12.3.2"
- "@next/swc-linux-arm64-gnu" "12.3.2"
- "@next/swc-linux-arm64-musl" "12.3.2"
- "@next/swc-linux-x64-gnu" "12.3.2"
- "@next/swc-linux-x64-musl" "12.3.2"
- "@next/swc-win32-arm64-msvc" "12.3.2"
- "@next/swc-win32-ia32-msvc" "12.3.2"
- "@next/swc-win32-x64-msvc" "12.3.2"
+ "@next/swc-android-arm-eabi" "12.3.4"
+ "@next/swc-android-arm64" "12.3.4"
+ "@next/swc-darwin-arm64" "12.3.4"
+ "@next/swc-darwin-x64" "12.3.4"
+ "@next/swc-freebsd-x64" "12.3.4"
+ "@next/swc-linux-arm-gnueabihf" "12.3.4"
+ "@next/swc-linux-arm64-gnu" "12.3.4"
+ "@next/swc-linux-arm64-musl" "12.3.4"
+ "@next/swc-linux-x64-gnu" "12.3.4"
+ "@next/swc-linux-x64-musl" "12.3.4"
+ "@next/swc-win32-arm64-msvc" "12.3.4"
+ "@next/swc-win32-ia32-msvc" "12.3.4"
+ "@next/swc-win32-x64-msvc" "12.3.4"
nice-try@^1.0.4:
version "1.0.5"
@@ -5398,7 +5499,7 @@ node-addon-api@^5.0.0:
node-domexception@^1.0.0:
version "1.0.0"
- resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz"
+ resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
node-fetch-native@^0.1.8:
@@ -5414,9 +5515,9 @@ node-fetch@^2.0.0, node-fetch@^2.6.6:
whatwg-url "^5.0.0"
node-fetch@^3.2.8:
- version "3.2.10"
- resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz"
- integrity sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.0.tgz#37e71db4ecc257057af828d523a7243d651d91e4"
+ integrity sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
@@ -5526,50 +5627,50 @@ object.assign@^4.1.3, object.assign@^4.1.4:
has-symbols "^1.0.3"
object-keys "^1.1.1"
-object.entries@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861"
- integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==
+object.entries@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23"
+ integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.1"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
-object.fromentries@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251"
- integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==
+object.fromentries@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73"
+ integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.1"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
-object.hasown@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3"
- integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==
+object.hasown@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92"
+ integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==
dependencies:
define-properties "^1.1.4"
- es-abstract "^1.19.5"
+ es-abstract "^1.20.4"
-object.values@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac"
- integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==
+object.values@^1.1.5, object.values@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
+ integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.1"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
ohmyfetch@^0.4.18, ohmyfetch@^0.4.19:
- version "0.4.20"
- resolved "https://registry.yarnpkg.com/ohmyfetch/-/ohmyfetch-0.4.20.tgz#735895d396c6d2fbf5705625db1196bd3f29be16"
- integrity sha512-+c3/l+X91owrT1reTos1R13rb2j8NGZpKi0bRWwrnxIHlr1FZ8NzghIsNBKpUvk9nsnFoNK4phw+nTnXrcALzA==
+ version "0.4.21"
+ resolved "https://registry.yarnpkg.com/ohmyfetch/-/ohmyfetch-0.4.21.tgz#6850db751fc7bbf08153aa8b11ff1ef45fcfd963"
+ integrity sha512-VG7f/JRvqvBOYvL0tHyEIEG7XHWm7OqIfAs6/HqwWwDfjiJ1g0huIpe5sFEmyb+7hpFa1EGNH2aERWR72tlClw==
dependencies:
- destr "^1.1.1"
+ destr "^1.2.0"
node-fetch-native "^0.1.8"
ufo "^0.8.6"
- undici "^5.11.0"
+ undici "^5.12.0"
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
@@ -6020,7 +6121,15 @@ postcss-selector-not@^5.0.0:
dependencies:
balanced-match "^1.0.0"
-postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
+postcss-selector-parser@^6.0.10:
+ version "6.0.11"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc"
+ integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
version "6.0.10"
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz"
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
@@ -6051,10 +6160,10 @@ postcss@^8.3.11:
picocolors "^1.0.0"
source-map-js "^1.0.2"
-postcss@^8.4.12, postcss@^8.4.17:
- version "8.4.18"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
- integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
+postcss@^8.4.12, postcss@^8.4.19:
+ version "8.4.19"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc"
+ integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
@@ -6091,9 +6200,9 @@ prettier-linter-helpers@^1.0.0:
fast-diff "^1.1.2"
prettier@^2.6.2:
- version "2.7.1"
- resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz"
- integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.0.tgz#c7df58393c9ba77d6fba3921ae01faf994fb9dc9"
+ integrity sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==
pretty-bytes@^5.6.0:
version "5.6.0"
@@ -6179,7 +6288,7 @@ radix3@^0.2.1:
raf-schd@^4.0.2:
version "4.0.3"
- resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz"
+ resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
randombytes@^2.1.0:
@@ -6199,10 +6308,22 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-basics@^0.37.0:
+ version "0.37.0"
+ resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.37.0.tgz#87ce9de15372bcb79b70779e54ec2dfaebd97473"
+ integrity sha512-0f7plY1A2BvJVRxudyUlNjqCFMLub/XwuepAl1knblwOUOApQ3nUpIFoVI+OU4ThmA6EDlsEdoaXkfAomM1UXg==
+ dependencies:
+ classnames "^2.3.1"
+ react "^18.2.0"
+ react-dom "^18.2.0"
+ react-hook-form "^7.34.2"
+ react-spring "^9.5.5"
+ react-window "^1.8.6"
+
react-beautiful-dnd@^13.1.0:
- version "13.1.0"
- resolved "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz"
- integrity sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==
+ version "13.1.1"
+ resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2"
+ integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==
dependencies:
"@babel/runtime" "^7.9.2"
css-box-model "^1.2.0"
@@ -6212,20 +6333,24 @@ react-beautiful-dnd@^13.1.0:
redux "^4.0.4"
use-memo-one "^1.1.1"
-react-dom@^17.0.0:
- version "17.0.2"
- resolved "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz"
- integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+react-dom@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
- scheduler "^0.20.2"
+ scheduler "^0.23.0"
react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+react-hook-form@^7.34.2:
+ version "7.39.5"
+ resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.39.5.tgz#a4272b60288ef5e1bb42bbb6ba3b36d243ab2879"
+ integrity sha512-OE0HKyz5IPc6svN2wd+e+evidZrw4O4WZWAWYzQVZuHi+hYnHFSLnxOq0ddjbdmaLIsLHut/ab7j72y2QT3+KA==
+
react-intl@^5.24.7:
version "5.25.1"
resolved "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz"
@@ -6244,18 +6369,18 @@ react-intl@^5.24.7:
react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
- resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.2:
version "17.0.2"
- resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-redux@^7.2.0:
- version "7.2.8"
- resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz"
- integrity sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==
+ version "7.2.9"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d"
+ integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/react-redux" "^7.1.20"
@@ -6274,24 +6399,24 @@ react-simple-maps@^2.3.0:
d3-zoom "^2.0.0"
topojson-client "^3.1.0"
-react-spring@^9.4.4:
- version "9.5.2"
- resolved "https://registry.npmjs.org/react-spring/-/react-spring-9.5.2.tgz"
- integrity sha512-OGWNgKi2TSjpqsK67NCUspaCgEvWcG7HcpO9KAaDLFzFGNxWdGdN3YTXhhWUqCsLAx9I6LxPzmRuUPsMNqTgrw==
+react-spring@^9.4.4, react-spring@^9.5.5:
+ version "9.5.5"
+ resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.5.5.tgz#314009a65efc04d0ef157d3d60590dbb9de65f3c"
+ integrity sha512-vMGVd2yjgxWcRCzoLn9AD1d24+WpunHBRg5DoehcRdiBocaOH6qgle0xN9C5LPplXfv4yIpS5QWGN5MKrWxSZg==
dependencies:
- "@react-spring/core" "~9.5.2"
- "@react-spring/konva" "~9.5.2"
- "@react-spring/native" "~9.5.2"
- "@react-spring/three" "~9.5.2"
- "@react-spring/web" "~9.5.2"
- "@react-spring/zdog" "~9.5.2"
+ "@react-spring/core" "~9.5.5"
+ "@react-spring/konva" "~9.5.5"
+ "@react-spring/native" "~9.5.5"
+ "@react-spring/three" "~9.5.5"
+ "@react-spring/web" "~9.5.5"
+ "@react-spring/zdog" "~9.5.5"
react-tooltip@^4.2.21:
- version "4.2.21"
- resolved "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz"
- integrity sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.5.1.tgz#77eccccdf16adec804132e558ec20ca5783b866a"
+ integrity sha512-Zo+CSFUGXar1uV+bgXFFDe7VeS2iByeIp5rTgTcc2HqtuOS5D76QapejNNfx320MCY91TlhTQat36KGFTqgcvw==
dependencies:
- prop-types "^15.7.2"
+ prop-types "^15.8.1"
uuid "^7.0.3"
react-use-measure@^2.0.4:
@@ -6302,20 +6427,19 @@ react-use-measure@^2.0.4:
debounce "^1.2.1"
react-window@^1.8.6:
- version "1.8.7"
- resolved "https://registry.npmjs.org/react-window/-/react-window-1.8.7.tgz"
- integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==
+ version "1.8.8"
+ resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.8.tgz#1b52919f009ddf91970cbdb2050a6c7be44df243"
+ integrity sha512-D4IiBeRtGXziZ1n0XklnFGu7h9gU684zepqyKzgPNzrsrk7xOCxni+TCckjg2Nr/DiaEEGVVmnhYSlT2rB47dQ==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"
-react@^17.0.0:
- version "17.0.2"
- resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
- integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+react@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
read-babelrc-up@^1.1.0:
version "1.1.0"
@@ -6396,9 +6520,21 @@ redis-parser@^3.0.0:
dependencies:
redis-errors "^1.0.0"
+redis@^4.5.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/redis/-/redis-4.5.1.tgz#f5a818970bb2dc5d60540bab41308640604c7d33"
+ integrity sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==
+ dependencies:
+ "@redis/bloom" "1.1.0"
+ "@redis/client" "1.4.2"
+ "@redis/graph" "1.1.0"
+ "@redis/json" "1.0.4"
+ "@redis/search" "1.1.0"
+ "@redis/time-series" "1.0.4"
+
redux@^4.0.0, redux@^4.0.4:
version "4.2.0"
- resolved "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
dependencies:
"@babel/runtime" "^7.9.2"
@@ -6422,10 +6558,10 @@ regenerate@^1.4.0, regenerate@^1.4.2:
resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
-regenerator-runtime@^0.13.10, regenerator-runtime@^0.13.4:
- version "0.13.10"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee"
- integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==
+regenerator-runtime@^0.13.10, regenerator-runtime@^0.13.11:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
regenerator-transform@^0.15.0:
version "0.15.0"
@@ -6439,7 +6575,7 @@ regexp-tree@^0.1.24:
resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.24.tgz#3d6fa238450a4d66e5bc9c4c14bb720e2196829d"
integrity sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==
-regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3:
+regexp.prototype.flags@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
@@ -6659,13 +6795,12 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-scheduler@^0.20.2:
- version "0.20.2"
- resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz"
- integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+scheduler@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
+ integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
schema-utils@*:
version "4.0.0"
@@ -6715,20 +6850,13 @@ semver@^7.2.1:
dependencies:
lru-cache "^6.0.0"
-semver@^7.3.4, semver@^7.3.5, semver@^7.3.7:
+semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"
-semver@^7.3.6:
- version "7.3.7"
- resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz"
- integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
- dependencies:
- lru-cache "^6.0.0"
-
serialize-javascript@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz"
@@ -6952,18 +7080,18 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
-string.prototype.matchall@^4.0.7:
- version "4.0.7"
- resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d"
- integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==
+string.prototype.matchall@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3"
+ integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.1"
- get-intrinsic "^1.1.1"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ get-intrinsic "^1.1.3"
has-symbols "^1.0.3"
internal-slot "^1.0.3"
- regexp.prototype.flags "^1.4.1"
+ regexp.prototype.flags "^1.4.3"
side-channel "^1.0.4"
string.prototype.padend@^3.0.0:
@@ -6976,22 +7104,22 @@ string.prototype.padend@^3.0.0:
es-abstract "^1.19.1"
string.prototype.trimend@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
- integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
+ integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
- es-abstract "^1.19.5"
+ es-abstract "^1.20.4"
string.prototype.trimstart@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
- integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
+ integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
- es-abstract "^1.19.5"
+ es-abstract "^1.20.4"
string_decoder@^1.1.1:
version "1.3.0"
@@ -7066,9 +7194,9 @@ stylelint-config-css-modules@^4.1.0:
stylelint-scss "^4.2.0"
stylelint-config-prettier@^9.0.3:
- version "9.0.3"
- resolved "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz"
- integrity sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-9.0.4.tgz#1b1dda614d5b3ef6c1f583fa6fa55f88245eb00b"
+ integrity sha512-38nIGTGpFOiK5LjJ8Ma1yUgpKENxoKSOhbDNSemY7Ep0VsJoXIW9Iq/2hSt699oB9tReynfWicTAoIHiq8Rvbg==
stylelint-config-recommended@^7.0.0:
version "7.0.0"
@@ -7087,14 +7215,14 @@ stylelint-scss@^4.2.0:
postcss-value-parser "^4.1.0"
stylelint@^14.5.3:
- version "14.14.0"
- resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.14.0.tgz#1acb52497c9a921f23f9c4014d4e0ee6eba768d0"
- integrity sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==
+ version "14.15.0"
+ resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.15.0.tgz#4df55078e734869f81f6b85bbec2d56a4b478ece"
+ integrity sha512-JOgDAo5QRsqiOZPZO+B9rKJvBm64S0xasbuRPAbPs6/vQDgDCnZLIiw6XcAS6GQKk9k1sBWR6rmH3Mfj8OknKg==
dependencies:
"@csstools/selector-specificity" "^2.0.2"
balanced-match "^2.0.0"
colord "^2.9.3"
- cosmiconfig "^7.0.1"
+ cosmiconfig "^7.1.0"
css-functions-list "^3.1.0"
debug "^4.3.4"
fast-glob "^3.2.12"
@@ -7108,13 +7236,13 @@ stylelint@^14.5.3:
import-lazy "^4.0.0"
imurmurhash "^0.1.4"
is-plain-object "^5.0.0"
- known-css-properties "^0.25.0"
+ known-css-properties "^0.26.0"
mathml-tag-names "^2.1.3"
meow "^9.0.0"
micromatch "^4.0.5"
normalize-path "^3.0.0"
picocolors "^1.0.0"
- postcss "^8.4.17"
+ postcss "^8.4.19"
postcss-media-query-parser "^0.2.3"
postcss-resolve-nested-selector "^0.1.1"
postcss-safe-parser "^6.0.0"
@@ -7126,7 +7254,7 @@ stylelint@^14.5.3:
style-search "^0.1.0"
supports-hyperlinks "^2.3.0"
svg-tags "^1.0.0"
- table "^6.8.0"
+ table "^6.8.1"
v8-compile-cache "^2.3.0"
write-file-atomic "^4.0.2"
@@ -7187,7 +7315,7 @@ svgo@^2.8.0:
picocolors "^1.0.0"
stable "^0.1.8"
-table@^6.0.9, table@^6.8.0:
+table@^6.0.9:
version "6.8.0"
resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz"
integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==
@@ -7198,6 +7326,17 @@ table@^6.0.9, table@^6.8.0:
string-width "^4.2.3"
strip-ansi "^6.0.1"
+table@^6.8.1:
+ version "6.8.1"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
+ integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==
+ dependencies:
+ ajv "^8.0.1"
+ lodash.truncate "^4.4.2"
+ slice-ansi "^4.0.0"
+ string-width "^4.2.3"
+ strip-ansi "^6.0.1"
+
tar-fs@^2.0.0, tar-fs@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
@@ -7220,9 +7359,9 @@ tar-stream@^2.1.4:
readable-stream "^3.1.1"
tar@^6.1.2:
- version "6.1.11"
- resolved "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz"
- integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
+ version "6.1.12"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.12.tgz#3b742fb05669b55671fb769ab67a7791ea1a62e6"
+ integrity sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
@@ -7272,14 +7411,14 @@ tiny-glob@^0.2.9:
globrex "^0.1.2"
tiny-invariant@^1.0.6:
- version "1.2.0"
- resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz"
- integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
+ integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
-tiny-lru@8.0.2:
- version "8.0.2"
- resolved "https://registry.npmjs.org/tiny-lru/-/tiny-lru-8.0.2.tgz"
- integrity sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==
+tiny-lru@9.0.3:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-9.0.3.tgz#f6a2121f433607a7f338881a23090829c1ea8cae"
+ integrity sha512-/i9GruRjXsnDgehxvy6iZ4AFNVxngEFbwzirhdulomMNPGPVV3ECMZOWSw0w4sRMZ9Al9m4jy08GPvRxRUGYlw==
tiny-warning@^1.0.2:
version "1.0.3"
@@ -7441,7 +7580,7 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"
-undici@^5.11.0:
+undici@^5.12.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.12.0.tgz#c758ffa704fbcd40d506e4948860ccaf4099f531"
integrity sha512-zMLamCG62PGjd9HHMpo05bSLvvwWOZgGeiWlN/vlqu3+lRo3elxktVGEyLMX+IO7c2eflLjcW74AlkhEZm15mg==
@@ -7532,11 +7671,11 @@ uri-js@^4.2.2:
punycode "^2.1.0"
use-memo-one@^1.1.1:
- version "1.1.2"
- resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz"
- integrity sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
+ integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==
-use-sync-external-store@1.2.0:
+use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
@@ -7553,7 +7692,7 @@ uuid@3.4.0, uuid@^3.3.2:
uuid@^7.0.3:
version "7.0.3"
- resolved "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
uuid@^8.3.2:
@@ -7601,7 +7740,7 @@ vue@^3.2.23:
web-streams-polyfill@^3.0.3:
version "3.2.1"
- resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz"
+ resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
webidl-conversions@^3.0.0:
@@ -7701,9 +7840,9 @@ write-json-file@^4.3.0:
write-file-atomic "^3.0.0"
ws@^8.9.0:
- version "8.10.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-8.10.0.tgz#00a28c09dfb76eae4eb45c3b565f771d6951aa51"
- integrity sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==
+ version "8.11.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
+ integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
xss@^1.0.14:
version "1.0.14"
@@ -7713,7 +7852,7 @@ xss@^1.0.14:
commander "^2.20.3"
cssfilter "0.0.10"
-yallist@^4.0.0:
+yallist@4.0.0, yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==