mirror of
https://github.com/umami-software/umami.git
synced 2026-02-14 17:45:38 +01:00
Add personal dashboard flow and per-component website selection
Some checks are pending
Node.js CI / build (push) Waiting to run
Some checks are pending
Node.js CI / build (push) Waiting to run
This introduces a user-scoped dashboard with board-style view/edit pages while keeping it unavailable in team context, and moves website targeting to component config so dashboard components can each select their own website.
This commit is contained in:
parent
2633697585
commit
631cc46f7f
73 changed files with 418 additions and 88 deletions
|
|
@ -116,6 +116,16 @@ if (collectApiEndpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirects = [
|
const redirects = [
|
||||||
|
{
|
||||||
|
source: '/teams/:id/dashboard/edit',
|
||||||
|
destination: '/dashboard/edit',
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/teams/:id/dashboard',
|
||||||
|
destination: '/dashboard',
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
source: '/settings',
|
source: '/settings',
|
||||||
destination: '/settings/preferences',
|
destination: '/settings/preferences',
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "تحميل",
|
"download": "تحميل",
|
||||||
"dropoff": "إنزال",
|
"dropoff": "إنزال",
|
||||||
"edit": "تعديل",
|
"edit": "تعديل",
|
||||||
"edit-dashboard": "عدّل لوحة التحكم",
|
|
||||||
"edit-member": "عدّل العضو",
|
"edit-member": "عدّل العضو",
|
||||||
"email": "بريد إلكتروني",
|
"email": "بريد إلكتروني",
|
||||||
"enable-share-url": "فعّل مشاركة الرابط",
|
"enable-share-url": "فعّل مشاركة الرابط",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Спампаваць",
|
"download": "Спампаваць",
|
||||||
"dropoff": "Адмовы",
|
"dropoff": "Адмовы",
|
||||||
"edit": "Змяніць",
|
"edit": "Змяніць",
|
||||||
"edit-dashboard": "Змяніць інфармацыйную панэль",
|
|
||||||
"edit-member": "Рэдагаваць удзельніка",
|
"edit-member": "Рэдагаваць удзельніка",
|
||||||
"email": "Электронная пошта",
|
"email": "Электронная пошта",
|
||||||
"enable-share-url": "Дазволіць дзяліцца спасылкай",
|
"enable-share-url": "Дазволіць дзяліцца спасылкай",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Изтегляне",
|
"download": "Изтегляне",
|
||||||
"dropoff": "Отпадане",
|
"dropoff": "Отпадане",
|
||||||
"edit": "Редактирай",
|
"edit": "Редактирай",
|
||||||
"edit-dashboard": "Редактирай табло",
|
|
||||||
"edit-member": "Редактирай член",
|
"edit-member": "Редактирай член",
|
||||||
"email": "Имейл",
|
"email": "Имейл",
|
||||||
"enable-share-url": "Активирай Линк за споделяне",
|
"enable-share-url": "Активирай Линк за споделяне",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ডাউনলোড",
|
"download": "ডাউনলোড",
|
||||||
"dropoff": "ছেড়ে যাওয়া",
|
"dropoff": "ছেড়ে যাওয়া",
|
||||||
"edit": "সম্পাদনা করুন",
|
"edit": "সম্পাদনা করুন",
|
||||||
"edit-dashboard": "ড্যাশবোর্ড সম্পাদনা করুন",
|
|
||||||
"edit-member": "সদস্য সম্পাদনা করুন",
|
"edit-member": "সদস্য সম্পাদনা করুন",
|
||||||
"email": "ইমেইল",
|
"email": "ইমেইল",
|
||||||
"enable-share-url": "শেয়ার ইউআরএল শেয়ার করুন",
|
"enable-share-url": "শেয়ার ইউআরএল শেয়ার করুন",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Preuzmi",
|
"download": "Preuzmi",
|
||||||
"dropoff": "Odlazak",
|
"dropoff": "Odlazak",
|
||||||
"edit": "Uredi",
|
"edit": "Uredi",
|
||||||
"edit-dashboard": "Uredi dashboard",
|
|
||||||
"edit-member": "Uredi člana",
|
"edit-member": "Uredi člana",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Omogući URL za dijeljenje",
|
"enable-share-url": "Omogući URL za dijeljenje",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Descarregar",
|
"download": "Descarregar",
|
||||||
"dropoff": "Abandonament",
|
"dropoff": "Abandonament",
|
||||||
"edit": "Edita",
|
"edit": "Edita",
|
||||||
"edit-dashboard": "Edita panell",
|
|
||||||
"edit-member": "Edita membre",
|
"edit-member": "Edita membre",
|
||||||
"email": "Correu electrònic",
|
"email": "Correu electrònic",
|
||||||
"enable-share-url": "Activa l'enllaç per compartir",
|
"enable-share-url": "Activa l'enllaç per compartir",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Stáhnout",
|
"download": "Stáhnout",
|
||||||
"dropoff": "Opuštění",
|
"dropoff": "Opuštění",
|
||||||
"edit": "Upravit",
|
"edit": "Upravit",
|
||||||
"edit-dashboard": "Upravit dashboard",
|
|
||||||
"edit-member": "Upravit člena",
|
"edit-member": "Upravit člena",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Povolit sdílení URL",
|
"enable-share-url": "Povolit sdílení URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"dropoff": "Frafald",
|
"dropoff": "Frafald",
|
||||||
"edit": "Rediger",
|
"edit": "Rediger",
|
||||||
"edit-dashboard": "Rediger betjeningspanel",
|
|
||||||
"edit-member": "Rediger medlem",
|
"edit-member": "Rediger medlem",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Aktivér delings-URL",
|
"enable-share-url": "Aktivér delings-URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Herunterladen",
|
"download": "Herunterladen",
|
||||||
"dropoff": "Absprung",
|
"dropoff": "Absprung",
|
||||||
"edit": "Bearbeite",
|
"edit": "Bearbeite",
|
||||||
"edit-dashboard": "Dashboard bearbeite",
|
|
||||||
"edit-member": "Mitglied bearbeite",
|
"edit-member": "Mitglied bearbeite",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"enable-share-url": "Freigab-URL aktiviere",
|
"enable-share-url": "Freigab-URL aktiviere",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Herunterladen",
|
"download": "Herunterladen",
|
||||||
"dropoff": "Absprung",
|
"dropoff": "Absprung",
|
||||||
"edit": "Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
"edit-dashboard": "Dashboard bearbeiten",
|
|
||||||
"edit-member": "Mitglied bearbeiten",
|
"edit-member": "Mitglied bearbeiten",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"enable-share-url": "Freigabe-URL aktivieren",
|
"enable-share-url": "Freigabe-URL aktivieren",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Λήψη",
|
"download": "Λήψη",
|
||||||
"dropoff": "Εγκατάλειψη",
|
"dropoff": "Εγκατάλειψη",
|
||||||
"edit": "Επεξεργασία",
|
"edit": "Επεξεργασία",
|
||||||
"edit-dashboard": "Επεξεργασία πίνακα ελέγχου",
|
|
||||||
"edit-member": "Επεξεργασία μέλους",
|
"edit-member": "Επεξεργασία μέλους",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Ενεργοποίηση κοινής χρήσης URL",
|
"enable-share-url": "Ενεργοποίηση κοινής χρήσης URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"dropoff": "Dropoff",
|
"dropoff": "Dropoff",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"edit-dashboard": "Edit dashboard",
|
|
||||||
"edit-member": "Edit member",
|
"edit-member": "Edit member",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Enable share URL",
|
"enable-share-url": "Enable share URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"dropoff": "Dropoff",
|
"dropoff": "Dropoff",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"edit-dashboard": "Edit dashboard",
|
|
||||||
"edit-member": "Edit member",
|
"edit-member": "Edit member",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Enable share URL",
|
"enable-share-url": "Enable share URL",
|
||||||
|
|
@ -351,6 +350,7 @@
|
||||||
"delete-team-warning": "Deleting a team will also delete all team websites.",
|
"delete-team-warning": "Deleting a team will also delete all team websites.",
|
||||||
"delete-website-warning": "All website data will be deleted.",
|
"delete-website-warning": "All website data will be deleted.",
|
||||||
"error": "Something went wrong.",
|
"error": "Something went wrong.",
|
||||||
|
"empty-dashboard": "Your dashboard is empty. Click Edit to add your first component.",
|
||||||
"event-log": "<b>{event}</b> on <a>{url}</a>",
|
"event-log": "<b>{event}</b> on <a>{url}</a>",
|
||||||
"forbidden": "Forbidden",
|
"forbidden": "Forbidden",
|
||||||
"go-to-settings": "Go to settings",
|
"go-to-settings": "Go to settings",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Descargar",
|
"download": "Descargar",
|
||||||
"dropoff": "Abandono",
|
"dropoff": "Abandono",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit-dashboard": "Editar panel",
|
|
||||||
"edit-member": "Editar miembro",
|
"edit-member": "Editar miembro",
|
||||||
"email": "Correo electrónico",
|
"email": "Correo electrónico",
|
||||||
"enable-share-url": "Habilitar compartir URL",
|
"enable-share-url": "Habilitar compartir URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "دانلود",
|
"download": "دانلود",
|
||||||
"dropoff": "رها کردن",
|
"dropoff": "رها کردن",
|
||||||
"edit": "ویرایش",
|
"edit": "ویرایش",
|
||||||
"edit-dashboard": "ویرایش داشبورد",
|
|
||||||
"edit-member": "ویرایش عضو",
|
"edit-member": "ویرایش عضو",
|
||||||
"email": "ایمیل",
|
"email": "ایمیل",
|
||||||
"enable-share-url": "فعال کردن اشتراک گذاری آدرس اینترنتی",
|
"enable-share-url": "فعال کردن اشتراک گذاری آدرس اینترنتی",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Lataa",
|
"download": "Lataa",
|
||||||
"dropoff": "Poistuminen",
|
"dropoff": "Poistuminen",
|
||||||
"edit": "Muokkaa",
|
"edit": "Muokkaa",
|
||||||
"edit-dashboard": "Muokkaa ohjauspaneelia",
|
|
||||||
"edit-member": "Muokkaa jäsentä",
|
"edit-member": "Muokkaa jäsentä",
|
||||||
"email": "Sähköposti",
|
"email": "Sähköposti",
|
||||||
"enable-share-url": "Ota jakamisen URL-osoite käyttöön",
|
"enable-share-url": "Ota jakamisen URL-osoite käyttöön",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Tak niður",
|
"download": "Tak niður",
|
||||||
"dropoff": "Fráfall",
|
"dropoff": "Fráfall",
|
||||||
"edit": "Ger broyting",
|
"edit": "Ger broyting",
|
||||||
"edit-dashboard": "Ritstjórna yvirlitsskíggja",
|
|
||||||
"edit-member": "Ritstjórna lim",
|
"edit-member": "Ritstjórna lim",
|
||||||
"email": "Teldupostur",
|
"email": "Teldupostur",
|
||||||
"enable-share-url": "Virkja deili leinki",
|
"enable-share-url": "Virkja deili leinki",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Télécharger",
|
"download": "Télécharger",
|
||||||
"dropoff": "Abandons",
|
"dropoff": "Abandons",
|
||||||
"edit": "Modifier",
|
"edit": "Modifier",
|
||||||
"edit-dashboard": "Modifier le tableau de bord",
|
|
||||||
"edit-member": "Modifier le membre",
|
"edit-member": "Modifier le membre",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Activer l'URL de partage",
|
"enable-share-url": "Activer l'URL de partage",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Descargar",
|
"download": "Descargar",
|
||||||
"dropoff": "Disminución",
|
"dropoff": "Disminución",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit-dashboard": "Editar taboleiro",
|
|
||||||
"edit-member": "Editar membro",
|
"edit-member": "Editar membro",
|
||||||
"email": "Correo electrónico",
|
"email": "Correo electrónico",
|
||||||
"enable-share-url": "Activar URL de compartición",
|
"enable-share-url": "Activar URL de compartición",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "הורדה",
|
"download": "הורדה",
|
||||||
"dropoff": "עזיבה",
|
"dropoff": "עזיבה",
|
||||||
"edit": "עריכה",
|
"edit": "עריכה",
|
||||||
"edit-dashboard": "ערוך לוח מחוונים",
|
|
||||||
"edit-member": "ערוך חבר",
|
"edit-member": "ערוך חבר",
|
||||||
"email": "אימייל",
|
"email": "אימייל",
|
||||||
"enable-share-url": "הפעלת URL שיתוף",
|
"enable-share-url": "הפעלת URL שיתוף",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "डाउनलोड",
|
"download": "डाउनलोड",
|
||||||
"dropoff": "ड्रॉपऑफ",
|
"dropoff": "ड्रॉपऑफ",
|
||||||
"edit": "संपादित करें",
|
"edit": "संपादित करें",
|
||||||
"edit-dashboard": "डैशबोर्ड संपादित करें",
|
|
||||||
"edit-member": "सदस्य संपादित करें",
|
"edit-member": "सदस्य संपादित करें",
|
||||||
"email": "ईमेल",
|
"email": "ईमेल",
|
||||||
"enable-share-url": "शेयर URL सक्षम करें",
|
"enable-share-url": "शेयर URL सक्षम करें",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Preuzmi",
|
"download": "Preuzmi",
|
||||||
"dropoff": "Odlazak",
|
"dropoff": "Odlazak",
|
||||||
"edit": "Uredi",
|
"edit": "Uredi",
|
||||||
"edit-dashboard": "Uredi nadzornu ploču",
|
|
||||||
"edit-member": "Uredi člana",
|
"edit-member": "Uredi člana",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Omogući dijeljenje poveznice",
|
"enable-share-url": "Omogući dijeljenje poveznice",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Letöltés",
|
"download": "Letöltés",
|
||||||
"dropoff": "Lemorzsolódás",
|
"dropoff": "Lemorzsolódás",
|
||||||
"edit": "Módosítás",
|
"edit": "Módosítás",
|
||||||
"edit-dashboard": "Irányítópult szerkesztése",
|
|
||||||
"edit-member": "Tag szerkesztése",
|
"edit-member": "Tag szerkesztése",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "URL-megosztás engedélyezése",
|
"enable-share-url": "URL-megosztás engedélyezése",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Unduh",
|
"download": "Unduh",
|
||||||
"dropoff": "Penurunan",
|
"dropoff": "Penurunan",
|
||||||
"edit": "Sunting",
|
"edit": "Sunting",
|
||||||
"edit-dashboard": "Sunting dasbor",
|
|
||||||
"edit-member": "Sunting anggota",
|
"edit-member": "Sunting anggota",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Aktifkan URL berbagi",
|
"enable-share-url": "Aktifkan URL berbagi",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Scarica",
|
"download": "Scarica",
|
||||||
"dropoff": "Abbandono",
|
"dropoff": "Abbandono",
|
||||||
"edit": "Modifica",
|
"edit": "Modifica",
|
||||||
"edit-dashboard": "Modifica pannello di controllo",
|
|
||||||
"edit-member": "Modifica membro",
|
"edit-member": "Modifica membro",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Abilita URL di condivisione",
|
"enable-share-url": "Abilita URL di condivisione",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ダウンロード",
|
"download": "ダウンロード",
|
||||||
"dropoff": "切り捨て",
|
"dropoff": "切り捨て",
|
||||||
"edit": "編集",
|
"edit": "編集",
|
||||||
"edit-dashboard": "ダッシュボードの編集",
|
|
||||||
"edit-member": "メンバーの編集",
|
"edit-member": "メンバーの編集",
|
||||||
"email": "メール",
|
"email": "メール",
|
||||||
"enable-share-url": "共有URLを有効にする",
|
"enable-share-url": "共有URLを有効にする",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ទាញយក",
|
"download": "ទាញយក",
|
||||||
"dropoff": "ការចាកចេញ",
|
"dropoff": "ការចាកចេញ",
|
||||||
"edit": "កែប្រែ",
|
"edit": "កែប្រែ",
|
||||||
"edit-dashboard": "កែផ្ទាំងគ្រប់គ្រង",
|
|
||||||
"edit-member": "កែព័ត៌មានសមាជិក",
|
"edit-member": "កែព័ត៌មានសមាជិក",
|
||||||
"email": "អ៊ីមែល",
|
"email": "អ៊ីមែល",
|
||||||
"enable-share-url": "បើកការចែករំលែក URL",
|
"enable-share-url": "បើកការចែករំលែក URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "다운로드",
|
"download": "다운로드",
|
||||||
"dropoff": "이탈",
|
"dropoff": "이탈",
|
||||||
"edit": "편집",
|
"edit": "편집",
|
||||||
"edit-dashboard": "대시보드 편집",
|
|
||||||
"edit-member": "멤버 편집",
|
"edit-member": "멤버 편집",
|
||||||
"email": "이메일",
|
"email": "이메일",
|
||||||
"enable-share-url": "URL 공유 활성화",
|
"enable-share-url": "URL 공유 활성화",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Atsisiųsti",
|
"download": "Atsisiųsti",
|
||||||
"dropoff": "Atsitraukimas",
|
"dropoff": "Atsitraukimas",
|
||||||
"edit": "Redaguoti",
|
"edit": "Redaguoti",
|
||||||
"edit-dashboard": "Redaguoti švieslentę",
|
|
||||||
"edit-member": "Redaguoti narį",
|
"edit-member": "Redaguoti narį",
|
||||||
"email": "El. paštas",
|
"email": "El. paštas",
|
||||||
"enable-share-url": "Įjungti bendrinimą su nuoroda",
|
"enable-share-url": "Įjungti bendrinimą su nuoroda",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Татах",
|
"download": "Татах",
|
||||||
"dropoff": "Уналт",
|
"dropoff": "Уналт",
|
||||||
"edit": "Засах",
|
"edit": "Засах",
|
||||||
"edit-dashboard": "Хянах самбар засах",
|
|
||||||
"edit-member": "Гишүүн засах",
|
"edit-member": "Гишүүн засах",
|
||||||
"email": "Имэйл",
|
"email": "Имэйл",
|
||||||
"enable-share-url": "Хуваалцах холбоос идэвхжүүлэх",
|
"enable-share-url": "Хуваалцах холбоос идэвхжүүлэх",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Muat turun",
|
"download": "Muat turun",
|
||||||
"dropoff": "Tercicir",
|
"dropoff": "Tercicir",
|
||||||
"edit": "Sunting",
|
"edit": "Sunting",
|
||||||
"edit-dashboard": "Sunting papan pemuka",
|
|
||||||
"edit-member": "Sunting ahli",
|
"edit-member": "Sunting ahli",
|
||||||
"email": "E-mel",
|
"email": "E-mel",
|
||||||
"enable-share-url": "Aktifkan url berkongsi",
|
"enable-share-url": "Aktifkan url berkongsi",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ဒေါင်းလုဒ်လုပ်မည်",
|
"download": "ဒေါင်းလုဒ်လုပ်မည်",
|
||||||
"dropoff": "ထွက်ခွာမှု",
|
"dropoff": "ထွက်ခွာမှု",
|
||||||
"edit": "ပြုပြင်မည်",
|
"edit": "ပြုပြင်မည်",
|
||||||
"edit-dashboard": "ဒက်ရှ်ဘုတ်ကို ပြုပြင်မည်",
|
|
||||||
"edit-member": "အဖွဲ့ဝင် ပြင်ဆင်မည်",
|
"edit-member": "အဖွဲ့ဝင် ပြင်ဆင်မည်",
|
||||||
"email": "အီးမေးလ်",
|
"email": "အီးမေးလ်",
|
||||||
"enable-share-url": "ဝေငှခြင်းကိုလင့်ကို ဖွင့်မည်",
|
"enable-share-url": "ဝေငှခြင်းကိုလင့်ကို ဖွင့်မည်",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Last ned",
|
"download": "Last ned",
|
||||||
"dropoff": "Frafall",
|
"dropoff": "Frafall",
|
||||||
"edit": "Rediger",
|
"edit": "Rediger",
|
||||||
"edit-dashboard": "Rediger dashboard",
|
|
||||||
"edit-member": "Rediger bruker",
|
"edit-member": "Rediger bruker",
|
||||||
"email": "E-post",
|
"email": "E-post",
|
||||||
"enable-share-url": "Aktiver delings-URL",
|
"enable-share-url": "Aktiver delings-URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Downloaden",
|
"download": "Downloaden",
|
||||||
"dropoff": "Uitval",
|
"dropoff": "Uitval",
|
||||||
"edit": "Bewerken",
|
"edit": "Bewerken",
|
||||||
"edit-dashboard": "Dashboard aanpassen",
|
|
||||||
"edit-member": "Gebruiker aanpassen",
|
"edit-member": "Gebruiker aanpassen",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Sta delen via openbare URL toe",
|
"enable-share-url": "Sta delen via openbare URL toe",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Pobierz",
|
"download": "Pobierz",
|
||||||
"dropoff": "Odpływ",
|
"dropoff": "Odpływ",
|
||||||
"edit": "Edytuj",
|
"edit": "Edytuj",
|
||||||
"edit-dashboard": "Edytuj panel",
|
|
||||||
"edit-member": "Edytuj członka",
|
"edit-member": "Edytuj członka",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Włącz udostępnianie adresu URL",
|
"enable-share-url": "Włącz udostępnianie adresu URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"dropoff": "Abandono",
|
"dropoff": "Abandono",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit-dashboard": "Editar painel",
|
|
||||||
"edit-member": "Editar membro",
|
"edit-member": "Editar membro",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Ativar link para compartilhar",
|
"enable-share-url": "Ativar link para compartilhar",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Transferir",
|
"download": "Transferir",
|
||||||
"dropoff": "Abandono",
|
"dropoff": "Abandono",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit-dashboard": "Editar painel",
|
|
||||||
"edit-member": "Editar membro",
|
"edit-member": "Editar membro",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Ativar link de partilha",
|
"enable-share-url": "Ativar link de partilha",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Descarcă",
|
"download": "Descarcă",
|
||||||
"dropoff": "Rată de abandon",
|
"dropoff": "Rată de abandon",
|
||||||
"edit": "Editare",
|
"edit": "Editare",
|
||||||
"edit-dashboard": "Editare tablou de bord",
|
|
||||||
"edit-member": "Editare membru",
|
"edit-member": "Editare membru",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Activare adresă URL de distribuire",
|
"enable-share-url": "Activare adresă URL de distribuire",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Скачать",
|
"download": "Скачать",
|
||||||
"dropoff": "Высадка",
|
"dropoff": "Высадка",
|
||||||
"edit": "Изменить",
|
"edit": "Изменить",
|
||||||
"edit-dashboard": "Редактировать дашборд",
|
|
||||||
"edit-member": "Редактировать участника",
|
"edit-member": "Редактировать участника",
|
||||||
"email": "Электронная почта",
|
"email": "Электронная почта",
|
||||||
"enable-share-url": "Разрешить делиться ссылкой",
|
"enable-share-url": "Разрешить делиться ссылкой",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "බාගන්න",
|
"download": "බාගන්න",
|
||||||
"dropoff": "අතහැර යෑම",
|
"dropoff": "අතහැර යෑම",
|
||||||
"edit": "සංස්කරණය කරන්න",
|
"edit": "සංස්කරණය කරන්න",
|
||||||
"edit-dashboard": "උපකරණ පුවරුව සංස්කරණය",
|
|
||||||
"edit-member": "සාමාජිකයා සංස්කරණය",
|
"edit-member": "සාමාජිකයා සංස්කරණය",
|
||||||
"email": "විද්යුත් තැපෑල",
|
"email": "විද්යුත් තැපෑල",
|
||||||
"enable-share-url": "බෙදාගැනීමේ URL සබල කරන්න",
|
"enable-share-url": "බෙදාගැනීමේ URL සබල කරන්න",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Stiahnuť",
|
"download": "Stiahnuť",
|
||||||
"dropoff": "Odchod",
|
"dropoff": "Odchod",
|
||||||
"edit": "Upraviť",
|
"edit": "Upraviť",
|
||||||
"edit-dashboard": "Upraviť prehľad",
|
|
||||||
"edit-member": "Upraviť člena",
|
"edit-member": "Upraviť člena",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"enable-share-url": "Povoliť zdielanie URL",
|
"enable-share-url": "Povoliť zdielanie URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Prenesi",
|
"download": "Prenesi",
|
||||||
"dropoff": "Zapustitev",
|
"dropoff": "Zapustitev",
|
||||||
"edit": "Uredi",
|
"edit": "Uredi",
|
||||||
"edit-dashboard": "Uredi nadzorno ploščo",
|
|
||||||
"edit-member": "Uredi člana",
|
"edit-member": "Uredi člana",
|
||||||
"email": "E-pošta",
|
"email": "E-pošta",
|
||||||
"enable-share-url": "Omogoči povezavo za deljenje",
|
"enable-share-url": "Omogoči povezavo za deljenje",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Ladda ner",
|
"download": "Ladda ner",
|
||||||
"dropoff": "Bortfall",
|
"dropoff": "Bortfall",
|
||||||
"edit": "Redigera",
|
"edit": "Redigera",
|
||||||
"edit-dashboard": "Redigera översikt",
|
|
||||||
"edit-member": "Redigera medlem",
|
"edit-member": "Redigera medlem",
|
||||||
"email": "E-post",
|
"email": "E-post",
|
||||||
"enable-share-url": "Aktivera delningslänk",
|
"enable-share-url": "Aktivera delningslänk",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "பதிவிறக்கு",
|
"download": "பதிவிறக்கு",
|
||||||
"dropoff": "விலகல்",
|
"dropoff": "விலகல்",
|
||||||
"edit": "திருத்துதல்",
|
"edit": "திருத்துதல்",
|
||||||
"edit-dashboard": "முகப்பைத் திருத்து",
|
|
||||||
"edit-member": "உறுப்பினரைத் திருத்து",
|
"edit-member": "உறுப்பினரைத் திருத்து",
|
||||||
"email": "மின்னஞ்சல்",
|
"email": "மின்னஞ்சல்",
|
||||||
"enable-share-url": "கள முகவரியை பகிரலாம்",
|
"enable-share-url": "கள முகவரியை பகிரலாம்",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ดาวน์โหลด",
|
"download": "ดาวน์โหลด",
|
||||||
"dropoff": "การออกจากระบบ",
|
"dropoff": "การออกจากระบบ",
|
||||||
"edit": "แก้ไข",
|
"edit": "แก้ไข",
|
||||||
"edit-dashboard": "แก้ไขแดชบอร์ด",
|
|
||||||
"edit-member": "แก้ไขสมาชิก",
|
"edit-member": "แก้ไขสมาชิก",
|
||||||
"email": "อีเมล",
|
"email": "อีเมล",
|
||||||
"enable-share-url": "เปิดใช้งานการแชร์ลิงก์",
|
"enable-share-url": "เปิดใช้งานการแชร์ลิงก์",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "İndir",
|
"download": "İndir",
|
||||||
"dropoff": "Bırakma",
|
"dropoff": "Bırakma",
|
||||||
"edit": "Düzenle",
|
"edit": "Düzenle",
|
||||||
"edit-dashboard": "Kontrol panelini düzenle",
|
|
||||||
"edit-member": "Üyeyi düzenle",
|
"edit-member": "Üyeyi düzenle",
|
||||||
"email": "E-posta",
|
"email": "E-posta",
|
||||||
"enable-share-url": "Anonim paylaşım URL'i aktif",
|
"enable-share-url": "Anonim paylaşım URL'i aktif",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Завантажити",
|
"download": "Завантажити",
|
||||||
"dropoff": "Відсів",
|
"dropoff": "Відсів",
|
||||||
"edit": "Редагувати",
|
"edit": "Редагувати",
|
||||||
"edit-dashboard": "Редагувати панель",
|
|
||||||
"edit-member": "Редагувати учасника",
|
"edit-member": "Редагувати учасника",
|
||||||
"email": "Електронна пошта",
|
"email": "Електронна пошта",
|
||||||
"enable-share-url": "Увімкнути спільне посилання",
|
"enable-share-url": "Увімкнути спільне посилання",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "ڈاؤن لوڈ",
|
"download": "ڈاؤن لوڈ",
|
||||||
"dropoff": "ڈراپ آف",
|
"dropoff": "ڈراپ آف",
|
||||||
"edit": "ترمیم",
|
"edit": "ترمیم",
|
||||||
"edit-dashboard": "ڈیش بورڈ میں ترمیم",
|
|
||||||
"edit-member": "رکن میں ترمیم",
|
"edit-member": "رکن میں ترمیم",
|
||||||
"email": "ای میل",
|
"email": "ای میل",
|
||||||
"enable-share-url": "شیئر یو آر ایل کو فعال کریں",
|
"enable-share-url": "شیئر یو آر ایل کو فعال کریں",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Yuklab olish",
|
"download": "Yuklab olish",
|
||||||
"dropoff": "Tashlab ketish",
|
"dropoff": "Tashlab ketish",
|
||||||
"edit": "Tahrirlash",
|
"edit": "Tahrirlash",
|
||||||
"edit-dashboard": "Boshqaruv panelini tahrirlash",
|
|
||||||
"edit-member": "A'zoni tahrirlash",
|
"edit-member": "A'zoni tahrirlash",
|
||||||
"email": "Elektron pochta",
|
"email": "Elektron pochta",
|
||||||
"enable-share-url": "Ulashish URL'ini yoqish",
|
"enable-share-url": "Ulashish URL'ini yoqish",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "Tải xuống",
|
"download": "Tải xuống",
|
||||||
"dropoff": "Tỷ lệ bỏ qua",
|
"dropoff": "Tỷ lệ bỏ qua",
|
||||||
"edit": "Chỉnh sửa",
|
"edit": "Chỉnh sửa",
|
||||||
"edit-dashboard": "Chỉnh sửa bảng điều khiển",
|
|
||||||
"edit-member": "Chỉnh sửa thành viên",
|
"edit-member": "Chỉnh sửa thành viên",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"enable-share-url": "Bật chia sẻ URL",
|
"enable-share-url": "Bật chia sẻ URL",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "下载",
|
"download": "下载",
|
||||||
"dropoff": "丢弃",
|
"dropoff": "丢弃",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
"edit-dashboard": "编辑仪表盘",
|
|
||||||
"edit-member": "编辑成员",
|
"edit-member": "编辑成员",
|
||||||
"email": "邮箱",
|
"email": "邮箱",
|
||||||
"enable-share-url": "启用共享链接",
|
"enable-share-url": "启用共享链接",
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@
|
||||||
"download": "下載",
|
"download": "下載",
|
||||||
"dropoff": "離開",
|
"dropoff": "離開",
|
||||||
"edit": "編輯",
|
"edit": "編輯",
|
||||||
"edit-dashboard": "編輯儀表板",
|
|
||||||
"edit-member": "編輯成員",
|
"edit-member": "編輯成員",
|
||||||
"email": "電子郵件",
|
"email": "電子郵件",
|
||||||
"enable-share-url": "啟用分享連結",
|
"enable-share-url": "啟用分享連結",
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,33 @@ import { SettingsNav } from '@/app/(main)/settings/SettingsNav';
|
||||||
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
|
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
|
||||||
import { IconLabel } from '@/components/common/IconLabel';
|
import { IconLabel } from '@/components/common/IconLabel';
|
||||||
import { useGlobalState, useMessages, useNavigation } from '@/components/hooks';
|
import { useGlobalState, useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { Globe, Grid2x2, LayoutDashboard, LinkIcon, PanelLeft } from '@/components/icons';
|
import {
|
||||||
|
Globe,
|
||||||
|
Grid2x2,
|
||||||
|
LayoutDashboard,
|
||||||
|
LayoutGrid,
|
||||||
|
LinkIcon,
|
||||||
|
PanelLeft,
|
||||||
|
} from '@/components/icons';
|
||||||
import { UserButton } from '@/components/input/UserButton';
|
import { UserButton } from '@/components/input/UserButton';
|
||||||
import { Logo } from '@/components/svg';
|
import { Logo } from '@/components/svg';
|
||||||
|
|
||||||
export function SideNav(props: any) {
|
export function SideNav(props: any) {
|
||||||
const { t, labels } = useMessages();
|
const { t, labels } = useMessages();
|
||||||
const { pathname, renderUrl, websiteId } = useNavigation();
|
const { pathname, renderUrl, websiteId, teamId } = useNavigation();
|
||||||
const [isCollapsed] = useGlobalState('sidenav-collapsed', false);
|
const [isCollapsed] = useGlobalState('sidenav-collapsed', false);
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
|
...(!teamId
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
id: 'dashboard',
|
||||||
|
label: t(labels.dashboard),
|
||||||
|
path: '/dashboard',
|
||||||
|
icon: <LayoutGrid />,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
id: 'boards',
|
id: 'boards',
|
||||||
label: t(labels.boards),
|
label: t(labels.boards),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ function BoardComponentRendererComponent({
|
||||||
websiteId,
|
websiteId,
|
||||||
}: {
|
}: {
|
||||||
config: BoardComponentConfig;
|
config: BoardComponentConfig;
|
||||||
websiteId: string;
|
websiteId?: string;
|
||||||
}) {
|
}) {
|
||||||
const definition = getComponentDefinition(config.type);
|
const definition = getComponentDefinition(config.type);
|
||||||
|
|
||||||
|
|
@ -22,6 +22,14 @@ function BoardComponentRendererComponent({
|
||||||
|
|
||||||
const Component = definition.component;
|
const Component = definition.component;
|
||||||
|
|
||||||
|
if (!websiteId) {
|
||||||
|
return (
|
||||||
|
<Column alignItems="center" justifyContent="center" width="100%" height="100%">
|
||||||
|
<Text color="muted">Select a website</Text>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return <Component websiteId={websiteId} {...config.props} />;
|
return <Component websiteId={websiteId} {...config.props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
|
||||||
import type { BoardComponentConfig } from '@/lib/types';
|
import type { BoardComponentConfig } from '@/lib/types';
|
||||||
import {
|
import {
|
||||||
CATEGORIES,
|
CATEGORIES,
|
||||||
|
|
@ -21,12 +22,16 @@ import {
|
||||||
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
||||||
|
|
||||||
export function BoardComponentSelect({
|
export function BoardComponentSelect({
|
||||||
|
teamId,
|
||||||
websiteId,
|
websiteId,
|
||||||
|
defaultWebsiteId,
|
||||||
initialConfig,
|
initialConfig,
|
||||||
onSelect,
|
onSelect,
|
||||||
onClose,
|
onClose,
|
||||||
}: {
|
}: {
|
||||||
websiteId: string;
|
teamId?: string;
|
||||||
|
websiteId?: string;
|
||||||
|
defaultWebsiteId?: string;
|
||||||
initialConfig?: BoardComponentConfig;
|
initialConfig?: BoardComponentConfig;
|
||||||
onSelect: (config: BoardComponentConfig) => void;
|
onSelect: (config: BoardComponentConfig) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
@ -34,6 +39,9 @@ export function BoardComponentSelect({
|
||||||
const { t, labels, messages } = useMessages();
|
const { t, labels, messages } = useMessages();
|
||||||
const [selectedDef, setSelectedDef] = useState<ComponentDefinition | null>(null);
|
const [selectedDef, setSelectedDef] = useState<ComponentDefinition | null>(null);
|
||||||
const [configValues, setConfigValues] = useState<Record<string, any>>({});
|
const [configValues, setConfigValues] = useState<Record<string, any>>({});
|
||||||
|
const [selectedWebsiteId, setSelectedWebsiteId] = useState(
|
||||||
|
initialConfig?.websiteId || websiteId || defaultWebsiteId,
|
||||||
|
);
|
||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
const [description, setDescription] = useState('');
|
const [description, setDescription] = useState('');
|
||||||
|
|
||||||
|
|
@ -73,9 +81,10 @@ export function BoardComponentSelect({
|
||||||
|
|
||||||
setSelectedDef(definition);
|
setSelectedDef(definition);
|
||||||
setConfigValues(getDefaultConfigValues(definition, initialConfig));
|
setConfigValues(getDefaultConfigValues(definition, initialConfig));
|
||||||
|
setSelectedWebsiteId(initialConfig.websiteId || websiteId || defaultWebsiteId);
|
||||||
setTitle(initialConfig.title ?? '');
|
setTitle(initialConfig.title ?? '');
|
||||||
setDescription(initialConfig.description || '');
|
setDescription(initialConfig.description || '');
|
||||||
}, [initialConfig, allDefinitions]);
|
}, [initialConfig, allDefinitions, websiteId, defaultWebsiteId]);
|
||||||
|
|
||||||
const handleSelectComponent = (def: ComponentDefinition) => {
|
const handleSelectComponent = (def: ComponentDefinition) => {
|
||||||
setSelectedDef(def);
|
setSelectedDef(def);
|
||||||
|
|
@ -107,6 +116,7 @@ export function BoardComponentSelect({
|
||||||
|
|
||||||
const config: BoardComponentConfig = {
|
const config: BoardComponentConfig = {
|
||||||
type: selectedDef.type,
|
type: selectedDef.type,
|
||||||
|
websiteId: selectedWebsiteId,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
};
|
};
|
||||||
|
|
@ -172,12 +182,14 @@ export function BoardComponentSelect({
|
||||||
|
|
||||||
<Column gap="3" flexGrow={1} style={{ minWidth: 0 }}>
|
<Column gap="3" flexGrow={1} style={{ minWidth: 0 }}>
|
||||||
<Panel maxHeight="100%">
|
<Panel maxHeight="100%">
|
||||||
{previewConfig && websiteId ? (
|
{previewConfig && selectedWebsiteId ? (
|
||||||
<BoardComponentRenderer config={previewConfig} websiteId={websiteId} />
|
<BoardComponentRenderer config={previewConfig} websiteId={selectedWebsiteId} />
|
||||||
) : (
|
) : (
|
||||||
<Column alignItems="center" justifyContent="center" height="100%">
|
<Column alignItems="center" justifyContent="center" height="100%">
|
||||||
<Text color="muted">
|
<Text color="muted">
|
||||||
{websiteId ? t(messages.selectComponentPreview) : t(messages.selectWebsiteFirst)}
|
{selectedWebsiteId
|
||||||
|
? t(messages.selectComponentPreview)
|
||||||
|
: t(messages.selectWebsiteFirst)}
|
||||||
</Text>
|
</Text>
|
||||||
</Column>
|
</Column>
|
||||||
)}
|
)}
|
||||||
|
|
@ -187,6 +199,18 @@ export function BoardComponentSelect({
|
||||||
<Column gap="3" style={{ width: 320, flexShrink: 0, overflowY: 'auto' }}>
|
<Column gap="3" style={{ width: 320, flexShrink: 0, overflowY: 'auto' }}>
|
||||||
<Text weight="bold">{t(labels.properties)}</Text>
|
<Text weight="bold">{t(labels.properties)}</Text>
|
||||||
|
|
||||||
|
<Column gap="2">
|
||||||
|
<Text size="sm" color="muted">
|
||||||
|
{t(labels.website)}
|
||||||
|
</Text>
|
||||||
|
<WebsiteSelect
|
||||||
|
websiteId={selectedWebsiteId}
|
||||||
|
teamId={teamId}
|
||||||
|
placeholder={t(labels.selectWebsite)}
|
||||||
|
onChange={setSelectedWebsiteId}
|
||||||
|
/>
|
||||||
|
</Column>
|
||||||
|
|
||||||
<Column gap="2">
|
<Column gap="2">
|
||||||
<Text size="sm" color="muted">
|
<Text size="sm" color="muted">
|
||||||
{t(labels.title)}
|
{t(labels.title)}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { GripHorizontal, Plus } from '@/components/icons';
|
||||||
import { BoardEditRow } from './BoardEditRow';
|
import { BoardEditRow } from './BoardEditRow';
|
||||||
import { BUTTON_ROW_HEIGHT, MAX_ROW_HEIGHT, MIN_ROW_HEIGHT } from './boardConstants';
|
import { BUTTON_ROW_HEIGHT, MAX_ROW_HEIGHT, MIN_ROW_HEIGHT } from './boardConstants';
|
||||||
|
|
||||||
export function BoardEditBody() {
|
export function BoardEditBody({ requiresBoardWebsite = true }: { requiresBoardWebsite?: boolean }) {
|
||||||
const { board, updateBoard, registerLayoutGetter } = useBoard();
|
const { board, updateBoard, registerLayoutGetter } = useBoard();
|
||||||
const rowGroupRef = useRef<GroupImperativeHandle>(null);
|
const rowGroupRef = useRef<GroupImperativeHandle>(null);
|
||||||
const columnGroupRefs = useRef<Map<string, GroupImperativeHandle>>(new Map());
|
const columnGroupRefs = useRef<Map<string, GroupImperativeHandle>>(new Map());
|
||||||
|
|
@ -103,6 +103,7 @@ export function BoardEditBody() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const websiteId = board?.parameters?.websiteId;
|
const websiteId = board?.parameters?.websiteId;
|
||||||
|
const canEdit = requiresBoardWebsite ? !!websiteId : true;
|
||||||
const rows = board?.parameters?.rows ?? [];
|
const rows = board?.parameters?.rows ?? [];
|
||||||
const minHeight = (rows.length || 1) * MAX_ROW_HEIGHT + BUTTON_ROW_HEIGHT;
|
const minHeight = (rows.length || 1) * MAX_ROW_HEIGHT + BUTTON_ROW_HEIGHT;
|
||||||
|
|
||||||
|
|
@ -122,7 +123,7 @@ export function BoardEditBody() {
|
||||||
rowId={row.id}
|
rowId={row.id}
|
||||||
rowIndex={index}
|
rowIndex={index}
|
||||||
rowCount={rows.length}
|
rowCount={rows.length}
|
||||||
canEdit={!!websiteId}
|
canEdit={canEdit}
|
||||||
onRemove={handleRemoveRow}
|
onRemove={handleRemoveRow}
|
||||||
onMoveUp={handleMoveRowUp}
|
onMoveUp={handleMoveRowUp}
|
||||||
onMoveDown={handleMoveRowDown}
|
onMoveDown={handleMoveRowDown}
|
||||||
|
|
@ -157,7 +158,7 @@ export function BoardEditBody() {
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
{!!websiteId && (
|
{canEdit && (
|
||||||
<Panel minSize={BUTTON_ROW_HEIGHT}>
|
<Panel minSize={BUTTON_ROW_HEIGHT}>
|
||||||
<Row padding="3">
|
<Row padding="3">
|
||||||
<TooltipTrigger delay={0}>
|
<TooltipTrigger delay={0}>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
import { useBoard, useMessages } from '@/components/hooks';
|
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { Pencil, Plus, X } from '@/components/icons';
|
import { Pencil, Plus, X } from '@/components/icons';
|
||||||
import type { BoardComponentConfig } from '@/lib/types';
|
import type { BoardComponentConfig } from '@/lib/types';
|
||||||
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
||||||
|
|
@ -36,7 +36,9 @@ export function BoardEditColumn({
|
||||||
const [showActions, setShowActions] = useState(false);
|
const [showActions, setShowActions] = useState(false);
|
||||||
const { board } = useBoard();
|
const { board } = useBoard();
|
||||||
const { t, labels } = useMessages();
|
const { t, labels } = useMessages();
|
||||||
const websiteId = board?.parameters?.websiteId;
|
const { teamId } = useNavigation();
|
||||||
|
const boardWebsiteId = board?.parameters?.websiteId;
|
||||||
|
const websiteId = component?.websiteId || boardWebsiteId;
|
||||||
const renderedComponent = useMemo(() => {
|
const renderedComponent = useMemo(() => {
|
||||||
if (!component || !websiteId) {
|
if (!component || !websiteId) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -126,7 +128,9 @@ export function BoardEditColumn({
|
||||||
>
|
>
|
||||||
{() => (
|
{() => (
|
||||||
<BoardComponentSelect
|
<BoardComponentSelect
|
||||||
|
teamId={teamId}
|
||||||
websiteId={websiteId}
|
websiteId={websiteId}
|
||||||
|
defaultWebsiteId={boardWebsiteId}
|
||||||
initialConfig={component}
|
initialConfig={component}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
onClose={() => setShowSelect(false)}
|
onClose={() => setShowSelect(false)}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { BoardComponentRenderer } from './BoardComponentRenderer';
|
||||||
|
|
||||||
export function BoardViewColumn({ component }: { component?: BoardComponentConfig }) {
|
export function BoardViewColumn({ component }: { component?: BoardComponentConfig }) {
|
||||||
const { board } = useBoard();
|
const { board } = useBoard();
|
||||||
const websiteId = board?.parameters?.websiteId;
|
const websiteId = component?.websiteId || board?.parameters?.websiteId;
|
||||||
|
|
||||||
if (!component || !websiteId) {
|
if (!component || !websiteId) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
27
src/app/(main)/dashboard/DashboardEditHeader.tsx
Normal file
27
src/app/(main)/dashboard/DashboardEditHeader.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Button, LoadingButton, Row } from '@umami/react-zen';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
|
||||||
|
export function DashboardEditHeader() {
|
||||||
|
const { saveBoard, isPending } = useBoard();
|
||||||
|
const { t, labels } = useMessages();
|
||||||
|
const { router, renderUrl } = useNavigation();
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
await saveBoard();
|
||||||
|
router.push(renderUrl('/dashboard', false));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageHeader title={t(labels.dashboard)}>
|
||||||
|
<Row gap="3">
|
||||||
|
<Button variant="quiet" onPress={() => router.push(renderUrl('/dashboard', false))}>
|
||||||
|
{t(labels.cancel)}
|
||||||
|
</Button>
|
||||||
|
<LoadingButton variant="primary" onPress={handleSave} isLoading={isPending}>
|
||||||
|
{t(labels.save)}
|
||||||
|
</LoadingButton>
|
||||||
|
</Row>
|
||||||
|
</PageHeader>
|
||||||
|
);
|
||||||
|
}
|
||||||
33
src/app/(main)/dashboard/DashboardEditPage.tsx
Normal file
33
src/app/(main)/dashboard/DashboardEditPage.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
'use client';
|
||||||
|
import { Column } from '@umami/react-zen';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { BoardEditBody } from '@/app/(main)/boards/[boardId]/BoardEditBody';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { useNavigation } from '@/components/hooks';
|
||||||
|
import { DashboardEditHeader } from './DashboardEditHeader';
|
||||||
|
import { DashboardProvider } from './DashboardProvider';
|
||||||
|
|
||||||
|
export function DashboardEditPage() {
|
||||||
|
const { teamId, router } = useNavigation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (teamId) {
|
||||||
|
router.replace('/dashboard/edit');
|
||||||
|
}
|
||||||
|
}, [teamId, router]);
|
||||||
|
|
||||||
|
if (teamId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DashboardProvider editing>
|
||||||
|
<PageBody>
|
||||||
|
<Column>
|
||||||
|
<DashboardEditHeader />
|
||||||
|
<BoardEditBody requiresBoardWebsite={false} />
|
||||||
|
</Column>
|
||||||
|
</PageBody>
|
||||||
|
</DashboardProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
'use client';
|
|
||||||
import { Column } from '@umami/react-zen';
|
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
|
|
||||||
export function DashboardPage() {
|
|
||||||
const { t, labels } = useMessages();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageBody>
|
|
||||||
<Column margin="2">
|
|
||||||
<PageHeader title={t(labels.dashboard)}></PageHeader>
|
|
||||||
</Column>
|
|
||||||
</PageBody>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
111
src/app/(main)/dashboard/DashboardProvider.tsx
Normal file
111
src/app/(main)/dashboard/DashboardProvider.tsx
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
'use client';
|
||||||
|
import { Loading, useToast } from '@umami/react-zen';
|
||||||
|
import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import { BoardContext, type LayoutGetter } from '@/app/(main)/boards/BoardProvider';
|
||||||
|
import { getComponentDefinition } from '@/app/(main)/boards/boardComponentRegistry';
|
||||||
|
import { useApi, useDashboardQuery, useMessages, useModified } from '@/components/hooks';
|
||||||
|
import type { Board, BoardParameters } from '@/lib/types';
|
||||||
|
|
||||||
|
const createDefaultBoard = (): Partial<Board> => ({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
rows: [{ id: uuid(), columns: [{ id: uuid(), component: null }] }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function sanitizeBoardParameters(parameters?: BoardParameters): BoardParameters | undefined {
|
||||||
|
if (!parameters?.rows) {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...parameters,
|
||||||
|
rows: parameters.rows.map(row => ({
|
||||||
|
...row,
|
||||||
|
columns: row.columns.map(column => {
|
||||||
|
if (column.component && !getComponentDefinition(column.component.type)) {
|
||||||
|
return {
|
||||||
|
...column,
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return column;
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DashboardProvider({
|
||||||
|
editing = false,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
editing?: boolean;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
const { data, isFetching, isLoading } = useDashboardQuery();
|
||||||
|
const { post, useMutation } = useApi();
|
||||||
|
const { touch } = useModified();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const { t, labels, messages } = useMessages();
|
||||||
|
const [board, setBoard] = useState<Partial<Board>>(data ?? createDefaultBoard());
|
||||||
|
const layoutGetterRef = useRef<LayoutGetter | null>(null);
|
||||||
|
|
||||||
|
const registerLayoutGetter = useCallback((getter: LayoutGetter) => {
|
||||||
|
layoutGetterRef.current = getter;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
setBoard({
|
||||||
|
...data,
|
||||||
|
parameters: sanitizeBoardParameters(data.parameters),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const { mutateAsync, isPending } = useMutation({
|
||||||
|
mutationFn: (boardData: Partial<Board>) => {
|
||||||
|
return post('/dashboard', boardData);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateBoard = useCallback((data: Partial<Board>) => {
|
||||||
|
setBoard(current => ({ ...current, ...data }));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const saveBoard = useCallback(async () => {
|
||||||
|
const dashboardName = t(labels.dashboard);
|
||||||
|
const layoutData = layoutGetterRef.current?.();
|
||||||
|
const parameters = sanitizeBoardParameters(
|
||||||
|
layoutData ? { ...board.parameters, ...layoutData } : board.parameters,
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await mutateAsync({
|
||||||
|
...board,
|
||||||
|
name: dashboardName,
|
||||||
|
description: '',
|
||||||
|
parameters,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast(t(messages.saved));
|
||||||
|
touch('dashboard');
|
||||||
|
touch('boards');
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [board, labels.dashboard, messages.saved, mutateAsync, t, toast, touch]);
|
||||||
|
|
||||||
|
if (isFetching && isLoading) {
|
||||||
|
return <Loading placement="absolute" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BoardContext.Provider
|
||||||
|
value={{ board, editing, updateBoard, saveBoard, isPending, registerLayoutGetter }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</BoardContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(main)/dashboard/DashboardViewHeader.tsx
Normal file
18
src/app/(main)/dashboard/DashboardViewHeader.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { IconLabel } from '@/components/common/IconLabel';
|
||||||
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { Edit } from '@/components/icons';
|
||||||
|
|
||||||
|
export function DashboardViewHeader() {
|
||||||
|
const { t, labels } = useMessages();
|
||||||
|
const { renderUrl } = useNavigation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageHeader title={t(labels.dashboard)}>
|
||||||
|
<LinkButton href={renderUrl('/dashboard/edit', false)}>
|
||||||
|
<IconLabel icon={<Edit />}>{t(labels.edit)}</IconLabel>
|
||||||
|
</LinkButton>
|
||||||
|
</PageHeader>
|
||||||
|
);
|
||||||
|
}
|
||||||
49
src/app/(main)/dashboard/DashboardViewPage.tsx
Normal file
49
src/app/(main)/dashboard/DashboardViewPage.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
'use client';
|
||||||
|
import { Column } from '@umami/react-zen';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { BoardViewBody } from '@/app/(main)/boards/[boardId]/BoardViewBody';
|
||||||
|
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { DashboardProvider } from './DashboardProvider';
|
||||||
|
import { DashboardViewHeader } from './DashboardViewHeader';
|
||||||
|
|
||||||
|
function DashboardContent() {
|
||||||
|
const { board } = useBoard();
|
||||||
|
const { t, labels, messages } = useMessages();
|
||||||
|
const rows = board?.parameters?.rows ?? [];
|
||||||
|
const hasComponents = rows.some(row => row.columns?.some(column => !!column.component));
|
||||||
|
|
||||||
|
if (!hasComponents) {
|
||||||
|
return (
|
||||||
|
<EmptyPlaceholder title={t(labels.dashboard)} description={t(messages.emptyDashboard)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <BoardViewBody />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DashboardViewPage() {
|
||||||
|
const { teamId, router } = useNavigation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (teamId) {
|
||||||
|
router.replace('/dashboard');
|
||||||
|
}
|
||||||
|
}, [teamId, router]);
|
||||||
|
|
||||||
|
if (teamId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DashboardProvider>
|
||||||
|
<PageBody>
|
||||||
|
<Column>
|
||||||
|
<DashboardViewHeader />
|
||||||
|
<DashboardContent />
|
||||||
|
</Column>
|
||||||
|
</PageBody>
|
||||||
|
</DashboardProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
src/app/(main)/dashboard/edit/page.tsx
Normal file
10
src/app/(main)/dashboard/edit/page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { DashboardEditPage } from '../DashboardEditPage';
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return <DashboardEditPage />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Edit Dashboard',
|
||||||
|
};
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { DashboardPage } from './DashboardPage';
|
import { DashboardViewPage } from './DashboardViewPage';
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
return <DashboardPage />;
|
return <DashboardViewPage />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
|
|
||||||
64
src/app/api/dashboard/route.ts
Normal file
64
src/app/api/dashboard/route.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { uuid } from '@/lib/crypto';
|
||||||
|
import { parseRequest } from '@/lib/request';
|
||||||
|
import { json, unauthorized } from '@/lib/response';
|
||||||
|
import { createBoard, getBoard, updateBoard } from '@/queries/prisma';
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
const { auth, error } = await parseRequest(request);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const board = await getBoard(auth.user.id);
|
||||||
|
|
||||||
|
if (board && board.userId !== auth.user.id) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
const schema = z.object({
|
||||||
|
name: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
parameters: z.object({}).passthrough().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = auth.user.id;
|
||||||
|
const existing = await getBoard(userId);
|
||||||
|
|
||||||
|
if (existing && existing.userId !== userId) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
name: body.name,
|
||||||
|
description: body.description,
|
||||||
|
parameters: body.parameters ?? {},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
const result = await updateBoard(userId, data);
|
||||||
|
|
||||||
|
return json(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await createBoard({
|
||||||
|
id: userId,
|
||||||
|
type: 'dashboard',
|
||||||
|
slug: uuid(),
|
||||||
|
userId,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
|
||||||
|
return json(result);
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ export * from './context/useWebsite';
|
||||||
export * from './queries/useActiveUsersQuery';
|
export * from './queries/useActiveUsersQuery';
|
||||||
export * from './queries/useBoardQuery';
|
export * from './queries/useBoardQuery';
|
||||||
export * from './queries/useBoardsQuery';
|
export * from './queries/useBoardsQuery';
|
||||||
|
export * from './queries/useDashboardQuery';
|
||||||
export * from './queries/useDateRangeQuery';
|
export * from './queries/useDateRangeQuery';
|
||||||
export * from './queries/useDeleteQuery';
|
export * from './queries/useDeleteQuery';
|
||||||
export * from './queries/useEventDataEventsQuery';
|
export * from './queries/useEventDataEventsQuery';
|
||||||
|
|
|
||||||
16
src/components/hooks/queries/useDashboardQuery.ts
Normal file
16
src/components/hooks/queries/useDashboardQuery.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { keepPreviousData } from '@tanstack/react-query';
|
||||||
|
import type { ReactQueryOptions } from '@/lib/types';
|
||||||
|
import { useApi } from '../useApi';
|
||||||
|
import { useModified } from '../useModified';
|
||||||
|
|
||||||
|
export function useDashboardQuery(options?: ReactQueryOptions) {
|
||||||
|
const { get, useQuery } = useApi();
|
||||||
|
const { modified } = useModified('dashboard');
|
||||||
|
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['dashboard', { modified }],
|
||||||
|
queryFn: () => get('/dashboard'),
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ export function WebsiteSelect({
|
||||||
includeTeams?: boolean;
|
includeTeams?: boolean;
|
||||||
isCollapsed?: boolean;
|
isCollapsed?: boolean;
|
||||||
} & SelectProps) {
|
} & SelectProps) {
|
||||||
const { t, messages } = useMessages();
|
const { t, labels, messages } = useMessages();
|
||||||
const { data: website } = useWebsiteQuery(websiteId);
|
const { data: website } = useWebsiteQuery(websiteId);
|
||||||
const [name, setName] = useState<string>(website?.name);
|
const [name, setName] = useState<string>(website?.name);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
|
|
@ -57,12 +57,16 @@ export function WebsiteSelect({
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = name || props.placeholder || t(labels.selectWebsite);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row alignItems="center" gap>
|
<Row alignItems="center" gap>
|
||||||
<Icon>
|
<Icon>
|
||||||
<Globe />
|
<Globe />
|
||||||
</Icon>
|
</Icon>
|
||||||
<Text truncate>{name}</Text>
|
<Text truncate color={name ? undefined : 'muted'}>
|
||||||
|
{value}
|
||||||
|
</Text>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,6 @@ export const labels: Record<string, string> = {
|
||||||
tablet: 'label.tablet',
|
tablet: 'label.tablet',
|
||||||
mobile: 'label.mobile',
|
mobile: 'label.mobile',
|
||||||
toggleCharts: 'label.toggle-charts',
|
toggleCharts: 'label.toggle-charts',
|
||||||
editDashboard: 'label.edit-dashboard',
|
|
||||||
title: 'label.title',
|
title: 'label.title',
|
||||||
view: 'label.view',
|
view: 'label.view',
|
||||||
cities: 'label.cities',
|
cities: 'label.cities',
|
||||||
|
|
@ -368,6 +367,7 @@ export const messages: Record<string, string> = {
|
||||||
noResultsFound: 'message.no-results-found',
|
noResultsFound: 'message.no-results-found',
|
||||||
noWebsitesConfigured: 'message.no-websites-configured',
|
noWebsitesConfigured: 'message.no-websites-configured',
|
||||||
noTeamWebsites: 'message.no-team-websites',
|
noTeamWebsites: 'message.no-team-websites',
|
||||||
|
emptyDashboard: 'message.empty-dashboard',
|
||||||
selectComponentPreview: 'message.select-component-preview',
|
selectComponentPreview: 'message.select-component-preview',
|
||||||
selectWebsiteFirst: 'message.select-website-first',
|
selectWebsiteFirst: 'message.select-website-first',
|
||||||
teamWebsitesInfo: 'message.team-websites-info',
|
teamWebsitesInfo: 'message.team-websites-info',
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,7 @@ export interface ApiError extends Error {
|
||||||
|
|
||||||
export interface BoardComponentConfig {
|
export interface BoardComponentConfig {
|
||||||
type: string;
|
type: string;
|
||||||
|
websiteId?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
props?: Record<string, any>;
|
props?: Record<string, any>;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue