From e3d530cb907221ad279d758447d95a4176168858 Mon Sep 17 00:00:00 2001
From: Enzo Salson <drawkend@gmail.com>
Date: Mon, 22 May 2023 22:56:00 +0000
Subject: [PATCH 01/11] Translated using Weblate (French)

Currently translated at 97.3% (371 of 381 strings)

Translation: ntfy/Web app
Translate-URL: https://hosted.weblate.org/projects/ntfy/web/fr/
---
 web/public/static/langs/fr.json | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/web/public/static/langs/fr.json b/web/public/static/langs/fr.json
index ba71eb4a..cf4bb721 100644
--- a/web/public/static/langs/fr.json
+++ b/web/public/static/langs/fr.json
@@ -352,5 +352,24 @@
     "account_upgrade_dialog_interval_yearly_discount_save_up_to": "économisez jusqu'à {{discount}}%",
     "account_upgrade_dialog_tier_price_per_month": "mois",
     "account_upgrade_dialog_tier_price_billed_yearly": "{{price}} prélevé annuellement. Économisez {{save}}.",
-    "account_upgrade_dialog_billing_contact_email": "Pour des questions concernant la facturation, merci de nous <Link>contacter</Link> directement."
+    "account_upgrade_dialog_billing_contact_email": "Pour des questions concernant la facturation, merci de nous <Link>contacter</Link> directement.",
+    "publish_dialog_call_label": "Appel téléphonique",
+    "account_basics_phone_numbers_title": "Numéros de téléphone",
+    "account_basics_phone_numbers_dialog_description": "Pour utiliser la fonctionnalité de notification par appels, vous devez ajouter et vérifier au moins un numéro de téléphone. La vérification peut se faire par SMS ou appel téléphonique.",
+    "account_basics_phone_numbers_description": "Pour des notifications par appel téléphoniques",
+    "account_basics_phone_numbers_no_phone_numbers_yet": "Pas encore de numéros de téléphone",
+    "account_basics_phone_numbers_copied_to_clipboard": "Numéro de téléphone copié dans le presse-papier",
+    "account_basics_phone_numbers_dialog_title": "Ajouter un numéro de téléphone",
+    "account_basics_phone_numbers_dialog_number_label": "Numéro de téléphone",
+    "account_basics_phone_numbers_dialog_number_placeholder": "Ex : +33701020304",
+    "account_basics_phone_numbers_dialog_verify_button_sms": "Envoyer un SMS",
+    "account_basics_phone_numbers_dialog_verify_button_call": "Appelez moi",
+    "account_basics_phone_numbers_dialog_code_label": "Code de vérification",
+    "account_basics_phone_numbers_dialog_code_placeholder": "Ex : 123456",
+    "account_basics_phone_numbers_dialog_check_verification_button": "Code de confirmarion",
+    "account_basics_phone_numbers_dialog_channel_sms": "SMS",
+    "account_basics_phone_numbers_dialog_channel_call": "Appel",
+    "account_usage_calls_none": "Aucun appels téléphoniques ne peut être fait avec ce compte",
+    "publish_dialog_call_reset": "Supprimer les appels téléphoniques",
+    "publish_dialog_chip_call_label": "Appel téléphonique"
 }

From d3be1fa3594ef9d0a15eae1d38ddef839634336d Mon Sep 17 00:00:00 2001
From: Andrew <stanol777@gmail.com>
Date: Tue, 23 May 2023 14:16:18 +0000
Subject: [PATCH 02/11] Translated using Weblate (Ukrainian)

Currently translated at 92.9% (354 of 381 strings)

Translation: ntfy/Web app
Translate-URL: https://hosted.weblate.org/projects/ntfy/web/uk/
---
 web/public/static/langs/uk.json | 59 ++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/web/public/static/langs/uk.json b/web/public/static/langs/uk.json
index 111292f4..7d995dd2 100644
--- a/web/public/static/langs/uk.json
+++ b/web/public/static/langs/uk.json
@@ -295,5 +295,62 @@
     "account_usage_messages_title": "Опубліковані повідомлення",
     "account_usage_emails_title": "Надіслані електронні листи",
     "account_usage_reservations_title": "Зарезервовані теми",
-    "account_usage_reservations_none": "Для цього облікового запису немає зарезервованих тем"
+    "account_usage_reservations_none": "Для цього облікового запису немає зарезервованих тем",
+    "account_upgrade_dialog_tier_features_attachment_file_size": "{{filesize}} на файл",
+    "account_upgrade_dialog_tier_features_attachment_total_size": "{{totalsize}} загальне сховище",
+    "account_upgrade_dialog_tier_current_label": "Поточний",
+    "account_upgrade_dialog_tier_selected_label": "Вибране",
+    "account_upgrade_dialog_cancel_warning": "Це <strong> скасує вашу підписку</strong> і знизить версію вашого облікового запису {{date}}. У цю дату резервування тем, а також повідомлення, кешовані на сервері <strong>, буде видалено</strong>.",
+    "account_upgrade_dialog_tier_features_reservations_other": "{{reservations}} зарезервовані теми",
+    "account_upgrade_dialog_tier_features_no_reservations": "Немає зарезервованих тем",
+    "account_upgrade_dialog_tier_features_messages_other": "{{messages}} повідомлень в день",
+    "account_upgrade_dialog_tier_features_emails_one": "{{emails}} електронний лист в день",
+    "account_upgrade_dialog_tier_features_emails_other": "{{emails}} електронних листів в день",
+    "account_upgrade_dialog_tier_features_calls_one": "{{calls}} телефонний дзвінок в день",
+    "account_upgrade_dialog_tier_features_calls_other": "{{дзвінки}} телефонних дзвінків в день",
+    "account_upgrade_dialog_tier_features_no_calls": "Без телефонних дзвінків",
+    "account_upgrade_dialog_tier_price_per_month": "місяць",
+    "account_upgrade_dialog_tier_price_billed_monthly": "{{price}} на рік. Рахунок виставляється щомісяця.",
+    "account_upgrade_dialog_tier_price_billed_yearly": "{{price}} виставляється щорічно. Збережіть {{save}}.",
+    "account_upgrade_dialog_billing_contact_email": "Якщо у вас виникли запитання щодо оплати, <Link>зв’яжіться з нами</Link> безпосередньо.",
+    "account_upgrade_dialog_billing_contact_website": "Якщо у вас виникли запитання щодо оплати, відвідайте наш <Link>веб-сайт</Link>.",
+    "account_upgrade_dialog_button_cancel_subscription": "Скасувати підписку",
+    "account_upgrade_dialog_button_update_subscription": "Оновити підписку",
+    "account_tokens_title": "Токени доступу",
+    "account_tokens_table_expires_header": "Термін дії закінчується",
+    "account_tokens_description": "Використовуйте токени доступу при публікації та підписці через ntfy API, щоб не надсилати свої облікові дані. Ознайомтеся з <Link>документацією</Link>, щоб дізнатися більше.",
+    "account_tokens_table_token_header": "Токен",
+    "account_tokens_table_never_expires": "Ніколи не закінчується",
+    "account_tokens_table_label_header": "Мітка",
+    "account_tokens_table_current_session": "Поточний сеанс браузера",
+    "account_tokens_table_last_access_header": "Останній доступ",
+    "account_tokens_table_copied_to_clipboard": "Токен доступу скопійовано",
+    "account_tokens_table_cannot_delete_or_edit": "Неможливо редагувати або видалити токен поточного сеансу",
+    "account_tokens_table_create_token_button": "Створити токен доступу",
+    "account_tokens_table_last_origin_tooltip": "З IP-адреси {{ip}} натисніть для пошуку",
+    "account_tokens_dialog_title_create": "Створити токен доступу",
+    "account_tokens_dialog_button_cancel": "Скасувати",
+    "account_tokens_dialog_title_edit": "Редагувати токен доступу",
+    "account_tokens_dialog_title_delete": "Видалити токен доступу",
+    "account_tokens_dialog_label": "Мітка, наприклад, сповіщення Radarr",
+    "account_tokens_dialog_button_create": "Створити токен",
+    "account_tokens_dialog_button_update": "Оновити токен",
+    "account_tokens_dialog_expires_label": "Термін дії токену доступу закінчується через",
+    "account_tokens_dialog_expires_x_hours": "Термін дії токена закінчується через {{hours}} годин",
+    "account_tokens_dialog_expires_x_days": "Термін дії токена закінчується через {{days}} днів",
+    "account_tokens_delete_dialog_description": "Перш ніж видалити токен доступу, переконайтеся, що жодна програма або скрипт не використовує його. <strong>Ця дія не може бути скасована</strong>.",
+    "prefs_users_description_no_sync": "Користувачі та паролі не синхронізуються з вашим акаунтом.",
+    "prefs_users_table_cannot_delete_or_edit": "Неможливо видалити або відредагувати користувача, який увійшов у систему",
+    "account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} зарезервована тема",
+    "account_upgrade_dialog_tier_features_messages_one": "{{messages}} повідомлення в день",
+    "account_tokens_dialog_expires_unchanged": "Залишити термін придатності без змін",
+    "account_tokens_dialog_expires_never": "Термін дії токена ніколи не закінчується",
+    "account_tokens_delete_dialog_title": "Видалити токен доступу",
+    "account_tokens_delete_dialog_submit_button": "Видалити токен назавжди",
+    "account_upgrade_dialog_proration_info": "<strong>Пропорція</strong>: При переході з одного тарифного плану на інший різниця в ціні буде <strong>списана негайно</strong>. При переході на нижчий рівень залишок коштів буде використано для оплати майбутніх розрахункових періодів.",
+    "account_upgrade_dialog_reservations_warning_one": "Обраний рівень дозволяє менше зарезервованих тем, ніж ваш поточний рівень. Перш ніж змінити свій рівень, <strong>будь ласка, видаліть принаймні одне резервування</strong>. Ви можете видалити резервування в <Link>Налаштуваннях</Link>.",
+    "account_upgrade_dialog_reservations_warning_other": "Обраний рівень дозволяє менше зарезервованих тем, ніж ваш поточний рівень. Перш ніж змінити свій рівень, <strong>будь ласка, видаліть принаймні {{count}} резервувань</strong>. Ви можете видалити резервування в <Link>Налаштуваннях</Link>.",
+    "account_upgrade_dialog_button_cancel": "Скасувати",
+    "account_upgrade_dialog_button_redirect_signup": "Зареєструватися зараз",
+    "account_upgrade_dialog_button_pay_now": "Оплатити зараз і підписатися"
 }

From 9ebeb7f12fb7bcf37d2241c28c71d21300631db8 Mon Sep 17 00:00:00 2001
From: nimbleghost <132819643+nimbleghost@users.noreply.github.com>
Date: Wed, 24 May 2023 21:08:33 +0200
Subject: [PATCH 03/11] Fix mui inputProps

---
 web/src/components/EmojiPicker.jsx   | 8 +++++---
 web/src/components/PublishDialog.jsx | 7 +++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/web/src/components/EmojiPicker.jsx b/web/src/components/EmojiPicker.jsx
index da8d4369..e582a9bd 100644
--- a/web/src/components/EmojiPicker.jsx
+++ b/web/src/components/EmojiPicker.jsx
@@ -76,9 +76,11 @@ const EmojiPicker = (props) => {
                 variant="standard"
                 fullWidth
                 sx={{ marginTop: 0, marginBottom: "12px", paddingRight: 2 }}
-                inputProps={{
-                  role: "searchbox",
-                  "aria-label": t("emoji_picker_search_placeholder"),
+                InputProps={{
+                  inputProps: {
+                    role: "searchbox",
+                    "aria-label": t("emoji_picker_search_placeholder"),
+                  },
                   endAdornment: (
                     <InputAdornment position="end" sx={{ display: search ? "" : "none" }}>
                       <IconButton size="small" onClick={handleSearchClear} edge="end" aria-label={t("emoji_picker_search_clear")}>
diff --git a/web/src/components/PublishDialog.jsx b/web/src/components/PublishDialog.jsx
index 6a89aef0..553f9af9 100644
--- a/web/src/components/PublishDialog.jsx
+++ b/web/src/components/PublishDialog.jsx
@@ -824,8 +824,11 @@ const ExpandingTextField = (props) => {
         variant="standard"
         sx={{ width: `${textWidth}px`, borderBottom: "none" }}
         InputProps={{
-          style: { fontSize: theme.typography[props.variant].fontSize, paddingBottom: 0, paddingTop: 0 },
-          "aria-label": props.placeholder,
+          style: { fontSize: theme.typography[props.variant].fontSize },
+          inputProps: {
+            style: { paddingBottom: 0, paddingTop: 0 },
+            "aria-label": props.placeholder,
+          },
         }}
         disabled={props.disabled}
       />

From 7ccc5be9b42f41a6e9877d44d988d7256d45548d Mon Sep 17 00:00:00 2001
From: nimbleghost <132819643+nimbleghost@users.noreply.github.com>
Date: Wed, 24 May 2023 21:10:09 +0200
Subject: [PATCH 04/11] Fix jsx key issue

---
 web/src/components/PublishDialog.jsx | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/web/src/components/PublishDialog.jsx b/web/src/components/PublishDialog.jsx
index 553f9af9..4413aef1 100644
--- a/web/src/components/PublishDialog.jsx
+++ b/web/src/components/PublishDialog.jsx
@@ -467,10 +467,8 @@ const PublishDialog = (props) => {
                     "aria-label": t("publish_dialog_call_label"),
                   }}
                 >
-                  {account?.phone_numbers?.map((phoneNumber, i) => (
-                    // TODO(eslint): Possibly just use the phone number as a key?
-                    // eslint-disable-next-line react/no-array-index-key
-                    <MenuItem key={`phoneNumberMenuItem${i}`} value={phoneNumber} aria-label={phoneNumber}>
+                  {account?.phone_numbers?.map((phoneNumber) => (
+                    <MenuItem key={phoneNumber} value={phoneNumber} aria-label={phoneNumber}>
                       {t("publish_dialog_call_item", { number: phoneNumber })}
                     </MenuItem>
                   ))}

From b7c121e78ec13ca58de3bc4f511438541613f67f Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 21:32:15 -0400
Subject: [PATCH 05/11] Revert inputProps things

---
 web/.eslintrc                            |  6 ++++++
 web/src/components/Account.jsx           |  5 ++++-
 web/src/components/App.jsx               |  5 ++---
 web/src/components/EmojiPicker.jsx       |  8 ++++----
 web/src/components/ErrorBoundary.jsx     |  7 ++++---
 web/src/components/PublishDialog.jsx     | 22 +++++++++++-----------
 web/src/components/SubscriptionPopup.jsx |  2 ++
 7 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/web/.eslintrc b/web/.eslintrc
index 52e2c6b0..adf66130 100644
--- a/web/.eslintrc
+++ b/web/.eslintrc
@@ -20,6 +20,12 @@
     "react/destructuring-assignment": "off",
     "react/jsx-no-useless-fragment": "off",
     "react/jsx-props-no-spreading": "off",
+    "react/jsx-no-duplicate-props": [
+      "error",
+      {
+        "ignoreCase": false // For <TextField>'s [iI]nputProps
+      }
+    ],
     "react/function-component-definition": [
       "error",
       {
diff --git a/web/src/components/Account.jsx b/web/src/components/Account.jsx
index 535ccbc7..82956e52 100644
--- a/web/src/components/Account.jsx
+++ b/web/src/components/Account.jsx
@@ -994,6 +994,7 @@ const TokenDialog = (props) => {
 
 const TokenDeleteDialog = (props) => {
   const { t } = useTranslation();
+  const [error, setError] = useState("");
 
   const handleSubmit = async () => {
     try {
@@ -1003,6 +1004,8 @@ const TokenDeleteDialog = (props) => {
       console.log(`[Account] Error deleting token`, e);
       if (e instanceof UnauthorizedError) {
         session.resetAndRedirect(routes.login);
+      } else {
+        setError(e.message);
       }
     }
   };
@@ -1015,7 +1018,7 @@ const TokenDeleteDialog = (props) => {
           <Trans i18nKey="account_tokens_delete_dialog_description" />
         </DialogContentText>
       </DialogContent>
-      <DialogFooter status>
+      <DialogFooter status={error}>
         <Button onClick={props.onClose}>{t("common_cancel")}</Button>
         <Button onClick={handleSubmit} color="error">
           {t("account_tokens_delete_dialog_submit_button")}
diff --git a/web/src/components/App.jsx b/web/src/components/App.jsx
index 607d125b..07fd9554 100644
--- a/web/src/components/App.jsx
+++ b/web/src/components/App.jsx
@@ -30,14 +30,13 @@ export const AccountContext = createContext(null);
 
 const App = () => {
   const [account, setAccount] = useState(null);
-
-  const contextValue = useMemo(() => ({ account, setAccount }), [account, setAccount]);
+  const accountMemo = useMemo(() => ({ account, setAccount }), [account, setAccount]);
 
   return (
     <Suspense fallback={<Loader />}>
       <BrowserRouter>
         <ThemeProvider theme={theme}>
-          <AccountContext.Provider value={contextValue}>
+          <AccountContext.Provider value={accountMemo}>
             <CssBaseline />
             <ErrorBoundary>
               <Routes>
diff --git a/web/src/components/EmojiPicker.jsx b/web/src/components/EmojiPicker.jsx
index e582a9bd..6cbebf55 100644
--- a/web/src/components/EmojiPicker.jsx
+++ b/web/src/components/EmojiPicker.jsx
@@ -76,11 +76,11 @@ const EmojiPicker = (props) => {
                 variant="standard"
                 fullWidth
                 sx={{ marginTop: 0, marginBottom: "12px", paddingRight: 2 }}
+                inputProps={{
+                  role: "searchbox",
+                  "aria-label": t("emoji_picker_search_placeholder"),
+                }}
                 InputProps={{
-                  inputProps: {
-                    role: "searchbox",
-                    "aria-label": t("emoji_picker_search_placeholder"),
-                  },
                   endAdornment: (
                     <InputAdornment position="end" sx={{ display: search ? "" : "none" }}>
                       <IconButton size="small" onClick={handleSearchClear} edge="end" aria-label={t("emoji_picker_search_clear")}>
diff --git a/web/src/components/ErrorBoundary.jsx b/web/src/components/ErrorBoundary.jsx
index ef5d9184..9c4bd204 100644
--- a/web/src/components/ErrorBoundary.jsx
+++ b/web/src/components/ErrorBoundary.jsx
@@ -46,9 +46,10 @@ class ErrorBoundaryImpl extends React.Component {
     // Fetch additional info and a better stack trace
     StackTrace.fromError(error).then((stack) => {
       console.error("[ErrorBoundary] Stacktrace fetched", stack);
-      const niceStack = `${error.toString()}\n${stack
-        .map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`)
-        .join("\n")}`;
+      const stackString = stack
+          .map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`)
+          .join("\n");
+      const niceStack = `${error.toString()}\n${stackString}`;
       this.setState({ niceStack });
     });
   }
diff --git a/web/src/components/PublishDialog.jsx b/web/src/components/PublishDialog.jsx
index 4413aef1..51b95612 100644
--- a/web/src/components/PublishDialog.jsx
+++ b/web/src/components/PublishDialog.jsx
@@ -373,23 +373,23 @@ const PublishDialog = (props) => {
                   "aria-label": t("publish_dialog_priority_label"),
                 }}
               >
-                {[5, 4, 3, 2, 1].map((priorityMenuItem) => (
+                {[5, 4, 3, 2, 1].map((p) => (
                   <MenuItem
-                    key={`priorityMenuItem${priorityMenuItem}`}
-                    value={priorityMenuItem}
+                    key={`priorityMenuItem${p}`}
+                    value={p}
                     aria-label={t("notifications_priority_x", {
-                      priority: priorityMenuItem,
+                      priority: p,
                     })}
                   >
                     <div style={{ display: "flex", alignItems: "center" }}>
                       <img
-                        src={priorities[priorityMenuItem].file}
+                        src={priorities[p].file}
                         style={{ marginRight: "8px" }}
                         alt={t("notifications_priority_x", {
-                          priority: priorityMenuItem,
+                          priority: p,
                         })}
                       />
-                      <div>{priorities[priorityMenuItem].label}</div>
+                      <div>{priorities[p].label}</div>
                     </div>
                   </MenuItem>
                 ))}
@@ -823,10 +823,10 @@ const ExpandingTextField = (props) => {
         sx={{ width: `${textWidth}px`, borderBottom: "none" }}
         InputProps={{
           style: { fontSize: theme.typography[props.variant].fontSize },
-          inputProps: {
-            style: { paddingBottom: 0, paddingTop: 0 },
-            "aria-label": props.placeholder,
-          },
+        }}
+        inputProps={{
+          style: { paddingBottom: 0, paddingTop: 0 },
+          "aria-label": props.placeholder,
         }}
         disabled={props.disabled}
       />
diff --git a/web/src/components/SubscriptionPopup.jsx b/web/src/components/SubscriptionPopup.jsx
index 7e747e41..196df01a 100644
--- a/web/src/components/SubscriptionPopup.jsx
+++ b/web/src/components/SubscriptionPopup.jsx
@@ -241,6 +241,8 @@ const DisplayNameDialog = (props) => {
           inputProps={{
             maxLength: 64,
             "aria-label": t("display_name_dialog_placeholder"),
+          }}
+          InputProps={{
             endAdornment: (
               <InputAdornment position="end">
                 <IconButton onClick={() => setDisplayName("")} edge="end">

From 6bb5274d831c3c03d52117148071275570167516 Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 21:34:25 -0400
Subject: [PATCH 06/11] Release notes

---
 docs/releases.md | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/docs/releases.md b/docs/releases.md
index 523f46f6..52fba345 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -1222,8 +1222,12 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
 
 ### ntfy server v2.6.0 (UNRELEASED)
 
-**Bug fixes + maintenance:**
+**Bug fixes:**
 
 * Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting)
+
+**Maintenance:**
+
 * Improved GitHub Actions flow ([#745](https://github.com/binwiederhier/ntfy/pull/745), thanks to [@nimbleghost](https://github.com/nimbleghost))
 * Web: Add JS formatter "prettier" ([#746](https://github.com/binwiederhier/ntfy/pull/746), thanks to [@nimbleghost](https://github.com/nimbleghost))
+* Web: Add eslint with eslint-config-airbnb ([#748](https://github.com/binwiederhier/ntfy/pull/748), thanks to [@nimbleghost](https://github.com/nimbleghost))

From a90bd4cd0674ac37297cdac07b9c73e02b9f3a79 Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 21:44:12 -0400
Subject: [PATCH 07/11] Formatting, npm update

---
 web/package-lock.json                | 745 ++++++---------------------
 web/src/components/ErrorBoundary.jsx |   4 +-
 web/vite.config.js                   |   2 +-
 3 files changed, 172 insertions(+), 579 deletions(-)

diff --git a/web/package-lock.json b/web/package-lock.json
index c02c249f..d74be988 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -55,7 +55,7 @@
       "version": "7.21.4",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
       "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "@babel/highlight": "^7.18.6"
       },
@@ -64,9 +64,9 @@
       }
     },
     "node_modules/@babel/compat-data": {
-      "version": "7.21.7",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.7.tgz",
-      "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==",
+      "version": "7.21.9",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.9.tgz",
+      "integrity": "sha512-FUGed8kfhyWvbYug/Un/VPJD41rDIgoVVcR+FuzhzOYyRz5uED+Gd3SLZml0Uw2l2aHFb7ZgdW5mGA3G2cCCnQ==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -102,19 +102,10 @@
         "url": "https://opencollective.com/babel"
       }
     },
-    "node_modules/@babel/core/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/@babel/generator": {
-      "version": "7.21.5",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz",
-      "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==",
+      "version": "7.21.9",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.9.tgz",
+      "integrity": "sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==",
       "dev": true,
       "dependencies": {
         "@babel/types": "^7.21.5",
@@ -145,15 +136,6 @@
         "@babel/core": "^7.0.0"
       }
     },
-    "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/@babel/helper-environment-visitor": {
       "version": "7.21.5",
       "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz",
@@ -192,7 +174,7 @@
       "version": "7.21.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz",
       "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "@babel/types": "^7.21.4"
       },
@@ -256,7 +238,7 @@
       "version": "7.21.5",
       "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz",
       "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
@@ -265,7 +247,7 @@
       "version": "7.19.1",
       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
       "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
@@ -297,7 +279,7 @@
       "version": "7.18.6",
       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
       "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "@babel/helper-validator-identifier": "^7.18.6",
         "chalk": "^2.0.0",
@@ -308,9 +290,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.21.8",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz",
-      "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==",
+      "version": "7.21.9",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.9.tgz",
+      "integrity": "sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -361,14 +343,14 @@
       }
     },
     "node_modules/@babel/template": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
-      "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
+      "version": "7.21.9",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz",
+      "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.18.6",
-        "@babel/parser": "^7.20.7",
-        "@babel/types": "^7.20.7"
+        "@babel/code-frame": "^7.21.4",
+        "@babel/parser": "^7.21.9",
+        "@babel/types": "^7.21.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -399,7 +381,7 @@
       "version": "7.21.5",
       "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz",
       "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "@babel/helper-string-parser": "^7.21.5",
         "@babel/helper-validator-identifier": "^7.19.1",
@@ -409,26 +391,6 @@
         "node": ">=6.9.0"
       }
     },
-    "node_modules/@emotion/babel-plugin": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
-      "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.16.7",
-        "@babel/runtime": "^7.18.3",
-        "@emotion/hash": "^0.9.1",
-        "@emotion/memoize": "^0.8.1",
-        "@emotion/serialize": "^1.1.2",
-        "babel-plugin-macros": "^3.1.0",
-        "convert-source-map": "^1.5.0",
-        "escape-string-regexp": "^4.0.0",
-        "find-root": "^1.1.0",
-        "source-map": "^0.5.7",
-        "stylis": "4.2.0"
-      }
-    },
     "node_modules/@emotion/cache": {
       "version": "11.11.0",
       "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
@@ -441,13 +403,6 @@
         "stylis": "4.2.0"
       }
     },
-    "node_modules/@emotion/hash": {
-      "version": "0.9.1",
-      "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
-      "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/@emotion/is-prop-valid": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
@@ -461,91 +416,11 @@
       "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
       "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
     },
-    "node_modules/@emotion/react": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.0.tgz",
-      "integrity": "sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@babel/runtime": "^7.18.3",
-        "@emotion/babel-plugin": "^11.11.0",
-        "@emotion/cache": "^11.11.0",
-        "@emotion/serialize": "^1.1.2",
-        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
-        "@emotion/utils": "^1.2.1",
-        "@emotion/weak-memoize": "^0.3.1",
-        "hoist-non-react-statics": "^3.3.1"
-      },
-      "peerDependencies": {
-        "react": ">=16.8.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@emotion/serialize": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
-      "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@emotion/hash": "^0.9.1",
-        "@emotion/memoize": "^0.8.1",
-        "@emotion/unitless": "^0.8.1",
-        "@emotion/utils": "^1.2.1",
-        "csstype": "^3.0.2"
-      }
-    },
     "node_modules/@emotion/sheet": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
       "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
     },
-    "node_modules/@emotion/styled": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
-      "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@babel/runtime": "^7.18.3",
-        "@emotion/babel-plugin": "^11.11.0",
-        "@emotion/is-prop-valid": "^1.2.1",
-        "@emotion/serialize": "^1.1.2",
-        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
-        "@emotion/utils": "^1.2.1"
-      },
-      "peerDependencies": {
-        "@emotion/react": "^11.0.0-rc.0",
-        "react": ">=16.8.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@emotion/unitless": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
-      "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
-      "optional": true,
-      "peer": true
-    },
-    "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
-      "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
-      "optional": true,
-      "peer": true,
-      "peerDependencies": {
-        "react": ">=16.8.0"
-      }
-    },
     "node_modules/@emotion/utils": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
@@ -955,12 +830,6 @@
         "url": "https://opencollective.com/eslint"
       }
     },
-    "node_modules/@eslint/eslintrc/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
     "node_modules/@eslint/eslintrc/node_modules/globals": {
       "version": "13.20.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
@@ -976,30 +845,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/@eslint/eslintrc/node_modules/type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/@eslint/js": {
       "version": "8.41.0",
       "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz",
@@ -1074,18 +919,6 @@
         "node": ">=6.0.0"
       }
     },
-    "node_modules/@jridgewell/source-map": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz",
-      "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.0",
-        "@jridgewell/trace-mapping": "^0.3.9"
-      }
-    },
     "node_modules/@jridgewell/sourcemap-codec": {
       "version": "1.4.15",
       "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -1109,12 +942,12 @@
       "dev": true
     },
     "node_modules/@mui/base": {
-      "version": "5.0.0-beta.1",
-      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.1.tgz",
-      "integrity": "sha512-xrkDCeu3JQE+JjJUnJnOrdQJMXwKhbV4AW+FRjMIj5i9cHK3BAuatG/iqbf1M+jklVWLk0KdbgioKwK+03aYbA==",
+      "version": "5.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.2.tgz",
+      "integrity": "sha512-R9R+aqrl1QhZJaO05rhvooqxOaf7SKpQ+EjW80sbP3ticTVmLmrn4YBLQS7/ML+WXdrkrPtqSmKFdSE5Ik3gBQ==",
       "dependencies": {
         "@babel/runtime": "^7.21.0",
-        "@emotion/is-prop-valid": "^1.2.0",
+        "@emotion/is-prop-valid": "^1.2.1",
         "@mui/types": "^7.2.4",
         "@mui/utils": "^5.13.1",
         "@popperjs/core": "^2.11.7",
@@ -1141,9 +974,9 @@
       }
     },
     "node_modules/@mui/core-downloads-tracker": {
-      "version": "5.13.1",
-      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.1.tgz",
-      "integrity": "sha512-qDHtNDO72NcBQMhaWBt9EZMvNiO+OXjPg5Sdk/6LgRDw6Zr3HdEZ5n2FJ/qtYsaT/okGyCuQavQkcZCOCEVf/g==",
+      "version": "5.13.2",
+      "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.2.tgz",
+      "integrity": "sha512-aOLCXMCySMFL2WmUhnz+DjF84AoFVu8rn35OsL759HXOZMz8zhEwVf5w/xxkWx7DycM2KXDTgAvYW48nTfqTLA==",
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/mui"
@@ -1175,14 +1008,14 @@
       }
     },
     "node_modules/@mui/material": {
-      "version": "5.13.1",
-      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.1.tgz",
-      "integrity": "sha512-qSnbJZer8lIuDYFDv19/t3s0AXYY9SxcOdhCnGvetRSfOG4gy3TkiFXNCdW5OLNveTieiMpOuv46eXUmE3ZA6A==",
+      "version": "5.13.2",
+      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.2.tgz",
+      "integrity": "sha512-Pfke1l0GG2OJb/Nr10aVr8huoBFcBTdWKV5iFSTEHqf9c2C1ZlyYMISn7ui6X3Gix8vr+hP5kVqH1LAWwQSb6w==",
       "dependencies": {
         "@babel/runtime": "^7.21.0",
-        "@mui/base": "5.0.0-beta.1",
-        "@mui/core-downloads-tracker": "^5.13.1",
-        "@mui/system": "^5.13.1",
+        "@mui/base": "5.0.0-beta.2",
+        "@mui/core-downloads-tracker": "^5.13.2",
+        "@mui/system": "^5.13.2",
         "@mui/types": "^7.2.4",
         "@mui/utils": "^5.13.1",
         "@types/react-transition-group": "^4.4.6",
@@ -1245,12 +1078,12 @@
       }
     },
     "node_modules/@mui/styled-engine": {
-      "version": "5.12.3",
-      "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.12.3.tgz",
-      "integrity": "sha512-AhZtiRyT8Bjr7fufxE/mLS+QJ3LxwX1kghIcM2B2dvJzSSg9rnIuXDXM959QfUVIM3C8U4x3mgVoPFMQJvc4/g==",
+      "version": "5.13.2",
+      "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.13.2.tgz",
+      "integrity": "sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==",
       "dependencies": {
         "@babel/runtime": "^7.21.0",
-        "@emotion/cache": "^11.10.8",
+        "@emotion/cache": "^11.11.0",
         "csstype": "^3.1.2",
         "prop-types": "^15.8.1"
       },
@@ -1276,13 +1109,13 @@
       }
     },
     "node_modules/@mui/system": {
-      "version": "5.13.1",
-      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.1.tgz",
-      "integrity": "sha512-BsDUjhiO6ZVAvzKhnWBHLZ5AtPJcdT+62VjnRLyA4isboqDKLg4fmYIZXq51yndg/soDK9RkY5lYZwEDku13Ow==",
+      "version": "5.13.2",
+      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.2.tgz",
+      "integrity": "sha512-TPyWmRJPt0JPVxacZISI4o070xEJ7ftxpVtu6LWuYVOUOINlhoGOclam4iV8PDT3EMQEHuUrwU49po34UdWLlw==",
       "dependencies": {
         "@babel/runtime": "^7.21.0",
         "@mui/private-theming": "^5.13.1",
-        "@mui/styled-engine": "^5.12.3",
+        "@mui/styled-engine": "^5.13.2",
         "@mui/types": "^7.2.4",
         "@mui/utils": "^5.13.1",
         "clsx": "^1.2.1",
@@ -1407,30 +1240,15 @@
       "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
       "dev": true
     },
-    "node_modules/@types/node": {
-      "version": "20.2.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.1.tgz",
-      "integrity": "sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg==",
-      "dev": true,
-      "optional": true,
-      "peer": true
-    },
-    "node_modules/@types/parse-json": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
-      "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/@types/prop-types": {
       "version": "15.7.5",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
       "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
     },
     "node_modules/@types/react": {
-      "version": "18.2.6",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz",
-      "integrity": "sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==",
+      "version": "18.2.7",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.7.tgz",
+      "integrity": "sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==",
       "dependencies": {
         "@types/prop-types": "*",
         "@types/scheduler": "*",
@@ -1476,15 +1294,6 @@
         "vite": "^4.2.0"
       }
     },
-    "node_modules/@vitejs/plugin-react/node_modules/react-refresh": {
-      "version": "0.14.0",
-      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
-      "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/acorn": {
       "version": "8.8.2",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
@@ -1535,7 +1344,7 @@
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "color-convert": "^1.9.0"
       },
@@ -1543,6 +1352,12 @@
         "node": ">=4"
       }
     },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
     "node_modules/aria-query": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
@@ -1669,22 +1484,6 @@
         "deep-equal": "^2.0.5"
       }
     },
-    "node_modules/babel-plugin-macros": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
-      "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@babel/runtime": "^7.12.5",
-        "cosmiconfig": "^7.0.0",
-        "resolve": "^1.19.0"
-      },
-      "engines": {
-        "node": ">=10",
-        "npm": ">=6"
-      }
-    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -1729,14 +1528,6 @@
         "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
       }
     },
-    "node_modules/buffer-from": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
-      "dev": true,
-      "optional": true,
-      "peer": true
-    },
     "node_modules/call-bind": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
@@ -1754,15 +1545,15 @@
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
       "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001488",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001488.tgz",
-      "integrity": "sha512-NORIQuuL4xGpIy6iCCQGN4iFjlBXtfKWIenlUuyZJumLRIindLb7wXM+GO8erEhb7vXfcnf4BAg2PrSDN5TNLQ==",
+      "version": "1.0.30001489",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz",
+      "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==",
       "dev": true,
       "funding": [
         {
@@ -1783,7 +1574,7 @@
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
@@ -1793,15 +1584,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/chalk/node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "devOptional": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
     "node_modules/clsx": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -1814,7 +1596,7 @@
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "color-name": "1.1.3"
       }
@@ -1823,7 +1605,7 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "devOptional": true
+      "dev": true
     },
     "node_modules/concat-map": {
       "version": "0.0.1",
@@ -1841,24 +1623,7 @@
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
       "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
-      "devOptional": true
-    },
-    "node_modules/cosmiconfig": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
-      "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@types/parse-json": "^4.0.0",
-        "import-fresh": "^3.2.1",
-        "parse-json": "^5.0.0",
-        "path-type": "^4.0.0",
-        "yaml": "^1.10.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
+      "dev": true
     },
     "node_modules/cross-fetch": {
       "version": "3.1.5",
@@ -2001,9 +1766,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.399",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.399.tgz",
-      "integrity": "sha512-+V1aNvVgoWNWYIbMOiQ1n5fRIaY4SlQ/uRlrsCjLrUwr/3OvQgiX2f5vdav4oArVT9TnttJKcPCqjwPNyZqw/A==",
+      "version": "1.4.406",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.406.tgz",
+      "integrity": "sha512-NXlDDH8Z4tK5ZX7w9dW/lRUsZ0TwL1rg3Sw1e5HKbk3+LCAh3SyUjYyGoxOf9xNxyg+DtaofkFpHS4T5Z2Q26w==",
       "dev": true
     },
     "node_modules/emoji-regex": {
@@ -2012,16 +1777,6 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
-    "node_modules/error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "is-arrayish": "^0.2.1"
-      }
-    },
     "node_modules/error-stack-parser": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
@@ -2185,15 +1940,12 @@
       }
     },
     "node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "devOptional": true,
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
       "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
+        "node": ">=0.8.0"
       }
     },
     "node_modules/eslint": {
@@ -2292,15 +2044,6 @@
         "eslint-plugin-import": "^2.25.2"
       }
     },
-    "node_modules/eslint-config-airbnb-base/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/eslint-config-prettier": {
       "version": "8.8.0",
       "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
@@ -2409,15 +2152,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/eslint-plugin-import/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/eslint-plugin-jsx-a11y": {
       "version": "6.7.1",
       "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
@@ -2448,15 +2182,6 @@
         "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
       }
     },
-    "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/eslint-plugin-react": {
       "version": "7.32.2",
       "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz",
@@ -2527,15 +2252,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/eslint-plugin-react/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
     "node_modules/eslint-scope": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
@@ -2579,12 +2295,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/eslint/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
     "node_modules/eslint/node_modules/chalk": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -2619,6 +2329,18 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
+    "node_modules/eslint/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/eslint/node_modules/globals": {
       "version": "13.20.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
@@ -2643,18 +2365,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/eslint/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/eslint/node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -2667,18 +2377,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/eslint/node_modules/type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/espree": {
       "version": "9.5.2",
       "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
@@ -2777,13 +2475,6 @@
         "node": "^10.12.0 || >=12.0.0"
       }
     },
-    "node_modules/find-root": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
-      "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/find-up": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -2852,7 +2543,7 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "devOptional": true
+      "dev": true
     },
     "node_modules/function.prototype.name": {
       "version": "1.1.5",
@@ -2999,7 +2690,7 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "function-bind": "^1.1.1"
       },
@@ -3020,7 +2711,7 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
       "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -3076,23 +2767,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/hoist-non-react-statics": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
-      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "react-is": "^16.7.0"
-      }
-    },
-    "node_modules/hoist-non-react-statics/node_modules/react-is": {
-      "version": "16.13.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/html-parse-stringify": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
@@ -3157,7 +2831,7 @@
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
       "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "parent-module": "^1.0.0",
         "resolve-from": "^4.0.0"
@@ -3238,13 +2912,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/is-arrayish": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/is-bigint": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -3289,7 +2956,7 @@
       "version": "2.12.1",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
       "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "has": "^1.0.3"
       },
@@ -3520,6 +3187,18 @@
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
       "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
     },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/jsesc": {
       "version": "2.5.2",
       "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -3532,13 +3211,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/json-parse-even-better-errors": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -3604,13 +3276,6 @@
         "node": ">= 0.8.0"
       }
     },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "optional": true,
-      "peer": true
-    },
     "node_modules/locate-path": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -3723,9 +3388,9 @@
       }
     },
     "node_modules/node-releases": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz",
-      "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==",
+      "version": "2.0.12",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
+      "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
       "dev": true
     },
     "node_modules/object-assign": {
@@ -3909,7 +3574,7 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
       "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "callsites": "^3.0.0"
       },
@@ -3917,25 +3582,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/parse-json": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
-      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.0.0",
-        "error-ex": "^1.3.1",
-        "json-parse-even-better-errors": "^2.3.0",
-        "lines-and-columns": "^1.1.6"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/path-exists": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3967,17 +3613,7 @@
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
       "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "devOptional": true
-    },
-    "node_modules/path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "optional": true,
-      "peer": true,
-      "engines": {
-        "node": ">=8"
-      }
+      "dev": true
     },
     "node_modules/picocolors": {
       "version": "1.0.0",
@@ -4141,6 +3777,15 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
       "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
     },
+    "node_modules/react-refresh": {
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
+      "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/react-router": {
       "version": "6.11.2",
       "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.2.tgz",
@@ -4212,7 +3857,7 @@
       "version": "1.22.2",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
       "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "is-core-module": "^2.11.0",
         "path-parse": "^1.0.7",
@@ -4229,7 +3874,7 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -4259,6 +3904,22 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/rollup": {
+      "version": "3.23.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.23.0.tgz",
+      "integrity": "sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==",
+      "dev": true,
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=14.18.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
     "node_modules/run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4304,6 +3965,15 @@
         "loose-envify": "^1.1.0"
       }
     },
+    "node_modules/semver": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
     "node_modules/shebang-command": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4340,11 +4010,9 @@
       }
     },
     "node_modules/source-map": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
-      "optional": true,
-      "peer": true,
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+      "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -4358,29 +4026,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/source-map-support": {
-      "version": "0.5.21",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "buffer-from": "^1.0.0",
-        "source-map": "^0.6.0"
-      }
-    },
-    "node_modules/source-map-support/node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/stack-generator": {
       "version": "2.0.10",
       "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
@@ -4403,14 +4048,6 @@
         "stackframe": "^1.3.4"
       }
     },
-    "node_modules/stacktrace-gps/node_modules/source-map": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-      "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/stacktrace-js": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
@@ -4509,6 +4146,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/strip-json-comments": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -4530,7 +4176,7 @@
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "devOptional": true,
+      "dev": true,
       "dependencies": {
         "has-flag": "^3.0.0"
       },
@@ -4542,7 +4188,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
       "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">= 0.4"
       },
@@ -4550,34 +4196,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/terser": {
-      "version": "5.17.4",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.4.tgz",
-      "integrity": "sha512-jcEKZw6UPrgugz/0Tuk/PVyLAPfMBJf5clnGueo45wTweoV8yh7Q7PEkhkJ5uuUbC7zAxEcG3tqNr1bstkQ8nw==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@jridgewell/source-map": "^0.3.2",
-        "acorn": "^8.5.0",
-        "commander": "^2.20.0",
-        "source-map-support": "~0.5.20"
-      },
-      "bin": {
-        "terser": "bin/terser"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/terser/node_modules/commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-      "dev": true,
-      "optional": true,
-      "peer": true
-    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -4596,7 +4214,7 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
       "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
-      "devOptional": true,
+      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -4630,15 +4248,6 @@
         "json5": "lib/cli.js"
       }
     },
-    "node_modules/tsconfig-paths/node_modules/strip-bom": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4651,6 +4260,18 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/type-fest": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/typed-array-length": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
@@ -4767,22 +4388,6 @@
         }
       }
     },
-    "node_modules/vite/node_modules/rollup": {
-      "version": "3.23.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.23.0.tgz",
-      "integrity": "sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==",
-      "dev": true,
-      "bin": {
-        "rollup": "dist/bin/rollup"
-      },
-      "engines": {
-        "node": ">=14.18.0",
-        "npm": ">=8.0.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
     "node_modules/void-elements": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
@@ -4791,6 +4396,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+    },
     "node_modules/whatwg-url": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
@@ -4800,11 +4410,6 @@
         "webidl-conversions": "^3.0.0"
       }
     },
-    "node_modules/whatwg-url/node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
-    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4892,16 +4497,6 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
-    "node_modules/yaml": {
-      "version": "1.10.2",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
-      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-      "optional": true,
-      "peer": true,
-      "engines": {
-        "node": ">= 6"
-      }
-    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/web/src/components/ErrorBoundary.jsx b/web/src/components/ErrorBoundary.jsx
index f749eab9..9715c0cb 100644
--- a/web/src/components/ErrorBoundary.jsx
+++ b/web/src/components/ErrorBoundary.jsx
@@ -45,9 +45,7 @@ class ErrorBoundaryImpl extends React.Component {
     // Fetch additional info and a better stack trace
     StackTrace.fromError(error).then((stack) => {
       console.error("[ErrorBoundary] Stacktrace fetched", stack);
-      const stackString = stack
-          .map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`)
-          .join("\n");
+      const stackString = stack.map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`).join("\n");
       const niceStack = `${error.toString()}\n${stackString}`;
       this.setState({ niceStack });
     });
diff --git a/web/vite.config.js b/web/vite.config.js
index 56ae2e40..ffc80ab7 100644
--- a/web/vite.config.js
+++ b/web/vite.config.js
@@ -5,7 +5,7 @@ import react from "@vitejs/plugin-react";
 export default defineConfig(() => ({
   build: {
     outDir: "build",
-    assetsDir: "static/media"
+    assetsDir: "static/media",
   },
   server: {
     port: 3000,

From e7bf165934ab0013404fa2a1045dd581e583041a Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 21:59:04 -0400
Subject: [PATCH 08/11] Formatting

---
 web/src/components/ErrorBoundary.jsx | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/web/src/components/ErrorBoundary.jsx b/web/src/components/ErrorBoundary.jsx
index 9c4bd204..9ce98129 100644
--- a/web/src/components/ErrorBoundary.jsx
+++ b/web/src/components/ErrorBoundary.jsx
@@ -46,9 +46,7 @@ class ErrorBoundaryImpl extends React.Component {
     // Fetch additional info and a better stack trace
     StackTrace.fromError(error).then((stack) => {
       console.error("[ErrorBoundary] Stacktrace fetched", stack);
-      const stackString = stack
-          .map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`)
-          .join("\n");
+      const stackString = stack.map((el) => `  at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`).join("\n");
       const niceStack = `${error.toString()}\n${stackString}`;
       this.setState({ niceStack });
     });

From 517341b5d793b74465b14a643d4529ed3e5837e5 Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 22:15:46 -0400
Subject: [PATCH 09/11] Re-add @emotion due to build errors

---
 web/package-lock.json | 261 ++++++++++++++++++++++++++++++++++++------
 web/package.json      |   2 +
 2 files changed, 231 insertions(+), 32 deletions(-)

diff --git a/web/package-lock.json b/web/package-lock.json
index d74be988..37812787 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -8,6 +8,8 @@
       "name": "ntfy",
       "version": "1.0.0",
       "dependencies": {
+        "@emotion/react": "^11.11.0",
+        "@emotion/styled": "^11.11.0",
         "@mui/icons-material": "^5.4.2",
         "@mui/material": "latest",
         "dexie": "^3.2.1",
@@ -55,7 +57,6 @@
       "version": "7.21.4",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
       "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
-      "dev": true,
       "dependencies": {
         "@babel/highlight": "^7.18.6"
       },
@@ -174,7 +175,6 @@
       "version": "7.21.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz",
       "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==",
-      "dev": true,
       "dependencies": {
         "@babel/types": "^7.21.4"
       },
@@ -238,7 +238,6 @@
       "version": "7.21.5",
       "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz",
       "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==",
-      "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
@@ -247,7 +246,6 @@
       "version": "7.19.1",
       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
       "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
-      "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
@@ -279,7 +277,6 @@
       "version": "7.18.6",
       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
       "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
-      "dev": true,
       "dependencies": {
         "@babel/helper-validator-identifier": "^7.18.6",
         "chalk": "^2.0.0",
@@ -381,7 +378,6 @@
       "version": "7.21.5",
       "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz",
       "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==",
-      "dev": true,
       "dependencies": {
         "@babel/helper-string-parser": "^7.21.5",
         "@babel/helper-validator-identifier": "^7.19.1",
@@ -391,6 +387,43 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@emotion/babel-plugin": {
+      "version": "11.11.0",
+      "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
+      "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.16.7",
+        "@babel/runtime": "^7.18.3",
+        "@emotion/hash": "^0.9.1",
+        "@emotion/memoize": "^0.8.1",
+        "@emotion/serialize": "^1.1.2",
+        "babel-plugin-macros": "^3.1.0",
+        "convert-source-map": "^1.5.0",
+        "escape-string-regexp": "^4.0.0",
+        "find-root": "^1.1.0",
+        "source-map": "^0.5.7",
+        "stylis": "4.2.0"
+      }
+    },
+    "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@emotion/babel-plugin/node_modules/source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/@emotion/cache": {
       "version": "11.11.0",
       "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
@@ -403,6 +436,11 @@
         "stylis": "4.2.0"
       }
     },
+    "node_modules/@emotion/hash": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+      "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+    },
     "node_modules/@emotion/is-prop-valid": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
@@ -416,11 +454,81 @@
       "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
       "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
     },
+    "node_modules/@emotion/react": {
+      "version": "11.11.0",
+      "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.0.tgz",
+      "integrity": "sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "@emotion/babel-plugin": "^11.11.0",
+        "@emotion/cache": "^11.11.0",
+        "@emotion/serialize": "^1.1.2",
+        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+        "@emotion/utils": "^1.2.1",
+        "@emotion/weak-memoize": "^0.3.1",
+        "hoist-non-react-statics": "^3.3.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@emotion/serialize": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
+      "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
+      "dependencies": {
+        "@emotion/hash": "^0.9.1",
+        "@emotion/memoize": "^0.8.1",
+        "@emotion/unitless": "^0.8.1",
+        "@emotion/utils": "^1.2.1",
+        "csstype": "^3.0.2"
+      }
+    },
     "node_modules/@emotion/sheet": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
       "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
     },
+    "node_modules/@emotion/styled": {
+      "version": "11.11.0",
+      "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
+      "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "@emotion/babel-plugin": "^11.11.0",
+        "@emotion/is-prop-valid": "^1.2.1",
+        "@emotion/serialize": "^1.1.2",
+        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+        "@emotion/utils": "^1.2.1"
+      },
+      "peerDependencies": {
+        "@emotion/react": "^11.0.0-rc.0",
+        "react": ">=16.8.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@emotion/unitless": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+      "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+    },
+    "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
+      "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
     "node_modules/@emotion/utils": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
@@ -1240,6 +1348,11 @@
       "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
       "dev": true
     },
+    "node_modules/@types/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
+    },
     "node_modules/@types/prop-types": {
       "version": "15.7.5",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@@ -1344,7 +1457,6 @@
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
       "dependencies": {
         "color-convert": "^1.9.0"
       },
@@ -1484,6 +1596,20 @@
         "deep-equal": "^2.0.5"
       }
     },
+    "node_modules/babel-plugin-macros": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+      "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "cosmiconfig": "^7.0.0",
+        "resolve": "^1.19.0"
+      },
+      "engines": {
+        "node": ">=10",
+        "npm": ">=6"
+      }
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -1545,7 +1671,6 @@
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
       "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true,
       "engines": {
         "node": ">=6"
       }
@@ -1574,7 +1699,6 @@
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
       "dependencies": {
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
@@ -1596,7 +1720,6 @@
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
       "dependencies": {
         "color-name": "1.1.3"
       }
@@ -1604,8 +1727,7 @@
     "node_modules/color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
     },
     "node_modules/concat-map": {
       "version": "0.0.1",
@@ -1622,8 +1744,22 @@
     "node_modules/convert-source-map": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
-      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
-      "dev": true
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+    },
+    "node_modules/cosmiconfig": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+      "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+      "dependencies": {
+        "@types/parse-json": "^4.0.0",
+        "import-fresh": "^3.2.1",
+        "parse-json": "^5.0.0",
+        "path-type": "^4.0.0",
+        "yaml": "^1.10.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
     },
     "node_modules/cross-fetch": {
       "version": "3.1.5",
@@ -1766,9 +1902,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.406",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.406.tgz",
-      "integrity": "sha512-NXlDDH8Z4tK5ZX7w9dW/lRUsZ0TwL1rg3Sw1e5HKbk3+LCAh3SyUjYyGoxOf9xNxyg+DtaofkFpHS4T5Z2Q26w==",
+      "version": "1.4.407",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.407.tgz",
+      "integrity": "sha512-5smEvFSFYMv90tICOzRVP7Opp98DAC4KW7RRipg3BuNpGbbV3N+x24Zh3sbLb1T5haGtOSy/hrBfXsWnIM9aCg==",
       "dev": true
     },
     "node_modules/emoji-regex": {
@@ -1777,6 +1913,14 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
+    "node_modules/error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dependencies": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
     "node_modules/error-stack-parser": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
@@ -1943,7 +2087,6 @@
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
       "engines": {
         "node": ">=0.8.0"
       }
@@ -2475,6 +2618,11 @@
         "node": "^10.12.0 || >=12.0.0"
       }
     },
+    "node_modules/find-root": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+      "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+    },
     "node_modules/find-up": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -2542,8 +2690,7 @@
     "node_modules/function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "dev": true
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
     "node_modules/function.prototype.name": {
       "version": "1.1.5",
@@ -2690,7 +2837,6 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "dev": true,
       "dependencies": {
         "function-bind": "^1.1.1"
       },
@@ -2711,7 +2857,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
       "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -2767,6 +2912,19 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/hoist-non-react-statics": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+      "dependencies": {
+        "react-is": "^16.7.0"
+      }
+    },
+    "node_modules/hoist-non-react-statics/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
     "node_modules/html-parse-stringify": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
@@ -2831,7 +2989,6 @@
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
       "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
       "dependencies": {
         "parent-module": "^1.0.0",
         "resolve-from": "^4.0.0"
@@ -2912,6 +3069,11 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+    },
     "node_modules/is-bigint": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -2956,7 +3118,6 @@
       "version": "2.12.1",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
       "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
-      "dev": true,
       "dependencies": {
         "has": "^1.0.3"
       },
@@ -3211,6 +3372,11 @@
         "node": ">=4"
       }
     },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+    },
     "node_modules/json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -3276,6 +3442,11 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+    },
     "node_modules/locate-path": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -3574,7 +3745,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
       "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
       "dependencies": {
         "callsites": "^3.0.0"
       },
@@ -3582,6 +3752,23 @@
         "node": ">=6"
       }
     },
+    "node_modules/parse-json": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "dependencies": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/path-exists": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3612,8 +3799,15 @@
     "node_modules/path-parse": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "dev": true
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "engines": {
+        "node": ">=8"
+      }
     },
     "node_modules/picocolors": {
       "version": "1.0.0",
@@ -3857,7 +4051,6 @@
       "version": "1.22.2",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
       "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
-      "dev": true,
       "dependencies": {
         "is-core-module": "^2.11.0",
         "path-parse": "^1.0.7",
@@ -3874,7 +4067,6 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -4176,7 +4368,6 @@
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
       "dependencies": {
         "has-flag": "^3.0.0"
       },
@@ -4188,7 +4379,6 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
       "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "dev": true,
       "engines": {
         "node": ">= 0.4"
       },
@@ -4214,7 +4404,6 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
       "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
-      "dev": true,
       "engines": {
         "node": ">=4"
       }
@@ -4497,6 +4686,14 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
+    "node_modules/yaml": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/web/package.json b/web/package.json
index 40f9f4bd..c00e8c6a 100644
--- a/web/package.json
+++ b/web/package.json
@@ -11,6 +11,8 @@
     "lint": "eslint --report-unused-disable-directives --ext .js,.jsx ./src/"
   },
   "dependencies": {
+    "@emotion/react": "^11.11.0",
+    "@emotion/styled": "^11.11.0",
     "@mui/icons-material": "^5.4.2",
     "@mui/material": "latest",
     "dexie": "^3.2.1",

From c50633d9901b56d898b723ce8a1386c8f3ccf4e9 Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 22:18:10 -0400
Subject: [PATCH 10/11] Deps

---
 web/package-lock.json | 64 ++++++++++++++++++-------------------------
 1 file changed, 26 insertions(+), 38 deletions(-)

diff --git a/web/package-lock.json b/web/package-lock.json
index 37812787..b5754d90 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -405,25 +405,6 @@
         "stylis": "4.2.0"
       }
     },
-    "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@emotion/babel-plugin/node_modules/source-map": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/@emotion/cache": {
       "version": "11.11.0",
       "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
@@ -1708,6 +1689,14 @@
         "node": ">=4"
       }
     },
+    "node_modules/chalk/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
     "node_modules/clsx": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -2084,11 +2073,14 @@
       }
     },
     "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
       "engines": {
-        "node": ">=0.8.0"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/eslint": {
@@ -2472,18 +2464,6 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
       "dev": true
     },
-    "node_modules/eslint/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/eslint/node_modules/globals": {
       "version": "13.20.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
@@ -4202,9 +4182,9 @@
       }
     },
     "node_modules/source-map": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-      "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -4240,6 +4220,14 @@
         "stackframe": "^1.3.4"
       }
     },
+    "node_modules/stacktrace-gps/node_modules/source-map": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+      "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/stacktrace-js": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",

From c16da2678094cbba088fbb5b292d8d7f24beff90 Mon Sep 17 00:00:00 2001
From: binwiederhier <philipp.heckel@gmail.com>
Date: Wed, 24 May 2023 22:28:26 -0400
Subject: [PATCH 11/11] Release notes

---
 docs/releases.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/releases.md b/docs/releases.md
index 52fba345..71fceb1e 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -1231,3 +1231,4 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
 * Improved GitHub Actions flow ([#745](https://github.com/binwiederhier/ntfy/pull/745), thanks to [@nimbleghost](https://github.com/nimbleghost))
 * Web: Add JS formatter "prettier" ([#746](https://github.com/binwiederhier/ntfy/pull/746), thanks to [@nimbleghost](https://github.com/nimbleghost))
 * Web: Add eslint with eslint-config-airbnb ([#748](https://github.com/binwiederhier/ntfy/pull/748), thanks to [@nimbleghost](https://github.com/nimbleghost))
+* Web: Switch to Vite ([#749](https://github.com/binwiederhier/ntfy/pull/749), thanks to [@nimbleghost](https://github.com/nimbleghost))