mirror of
https://github.com/umami-software/umami.git
synced 2026-02-25 06:55:35 +01:00
implement OR logic to filters, segments, cohorts
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 commit is contained in:
parent
79c06787cd
commit
cc1e4438d0
64 changed files with 343 additions and 54 deletions
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "مدير",
|
"manager": "مدير",
|
||||||
"max": "الحد الأقصى",
|
"max": "الحد الأقصى",
|
||||||
"maximize": "توسيع",
|
"maximize": "توسيع",
|
||||||
|
"match": "تطابق",
|
||||||
|
"match-all": "الكل (AND)",
|
||||||
|
"match-any": "أي (OR)",
|
||||||
"medium": "وسيط",
|
"medium": "وسيط",
|
||||||
"member": "عضو",
|
"member": "عضو",
|
||||||
"members": "الأعضاء",
|
"members": "الأعضاء",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Кіраўнік",
|
"manager": "Кіраўнік",
|
||||||
"max": "Максімум",
|
"max": "Максімум",
|
||||||
"maximize": "Разгарнуць",
|
"maximize": "Разгарнуць",
|
||||||
|
"match": "Адпаведнасць",
|
||||||
|
"match-all": "Усе (AND)",
|
||||||
|
"match-any": "Любы (OR)",
|
||||||
"medium": "Сярэдні",
|
"medium": "Сярэдні",
|
||||||
"member": "Удзельнік",
|
"member": "Удзельнік",
|
||||||
"members": "Удзельнікі",
|
"members": "Удзельнікі",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Мениджър",
|
"manager": "Мениджър",
|
||||||
"max": "Максимум",
|
"max": "Максимум",
|
||||||
"maximize": "Разшири",
|
"maximize": "Разшири",
|
||||||
|
"match": "Съвпадение",
|
||||||
|
"match-all": "Всички (AND)",
|
||||||
|
"match-any": "Някои (OR)",
|
||||||
"medium": "Среден",
|
"medium": "Среден",
|
||||||
"member": "Член",
|
"member": "Член",
|
||||||
"members": "Членове",
|
"members": "Членове",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "পরিচালক",
|
"manager": "পরিচালক",
|
||||||
"max": "সর্বাধিক",
|
"max": "সর্বাধিক",
|
||||||
"maximize": "বিস্তৃত করুন",
|
"maximize": "বিস্তৃত করুন",
|
||||||
|
"match": "মিলান",
|
||||||
|
"match-all": "সব (AND)",
|
||||||
|
"match-any": "যেকোনো (OR)",
|
||||||
"medium": "মাঝারি",
|
"medium": "মাঝারি",
|
||||||
"member": "সদস্য",
|
"member": "সদস্য",
|
||||||
"members": "সদস্যগণ",
|
"members": "সদস্যগণ",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Menadžer",
|
"manager": "Menadžer",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Proširi",
|
"maximize": "Proširi",
|
||||||
|
"match": "Podudaranje",
|
||||||
|
"match-all": "Sve (AND)",
|
||||||
|
"match-any": "Bilo koje (OR)",
|
||||||
"medium": "Srednje",
|
"medium": "Srednje",
|
||||||
"member": "Član",
|
"member": "Član",
|
||||||
"members": "Članovi",
|
"members": "Članovi",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Responsable",
|
"manager": "Responsable",
|
||||||
"max": "Màx",
|
"max": "Màx",
|
||||||
"maximize": "Expandeix",
|
"maximize": "Expandeix",
|
||||||
|
"match": "Coincidència",
|
||||||
|
"match-all": "Tots (AND)",
|
||||||
|
"match-any": "Qualsevol (OR)",
|
||||||
"medium": "Mitjà",
|
"medium": "Mitjà",
|
||||||
"member": "Membre",
|
"member": "Membre",
|
||||||
"members": "Membres",
|
"members": "Membres",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Správce",
|
"manager": "Správce",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Rozbalit",
|
"maximize": "Rozbalit",
|
||||||
|
"match": "Shoda",
|
||||||
|
"match-all": "Vše (AND)",
|
||||||
|
"match-any": "Jakýkoli (OR)",
|
||||||
"medium": "Střední",
|
"medium": "Střední",
|
||||||
"member": "Člen",
|
"member": "Člen",
|
||||||
"members": "Členové",
|
"members": "Členové",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Leder",
|
"manager": "Leder",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Udvid",
|
"maximize": "Udvid",
|
||||||
|
"match": "Match",
|
||||||
|
"match-all": "Alle (AND)",
|
||||||
|
"match-any": "Enhver (OR)",
|
||||||
"medium": "Medie",
|
"medium": "Medie",
|
||||||
"member": "Medlem",
|
"member": "Medlem",
|
||||||
"members": "Medlemmer",
|
"members": "Medlemmer",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Verwalter",
|
"manager": "Verwalter",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Uusklappe",
|
"maximize": "Uusklappe",
|
||||||
|
"match": "Übereinstimmung",
|
||||||
|
"match-all": "Alle (AND)",
|
||||||
|
"match-any": "Beliebige (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Mitglied",
|
"member": "Mitglied",
|
||||||
"members": "Mitglieder",
|
"members": "Mitglieder",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Verwaltung",
|
"manager": "Verwaltung",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Erweitern",
|
"maximize": "Erweitern",
|
||||||
|
"match": "Übereinstimmung",
|
||||||
|
"match-all": "Alle (AND)",
|
||||||
|
"match-any": "Beliebige (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Mitglied",
|
"member": "Mitglied",
|
||||||
"members": "Mitglieder",
|
"members": "Mitglieder",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Διαχειριστής",
|
"manager": "Διαχειριστής",
|
||||||
"max": "Μέγ",
|
"max": "Μέγ",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "Αντιστοίχιση",
|
||||||
|
"match-all": "Όλα (AND)",
|
||||||
|
"match-any": "Οποιοδήποτε (OR)",
|
||||||
"medium": "Μέσο",
|
"medium": "Μέσο",
|
||||||
"member": "Μέλος",
|
"member": "Μέλος",
|
||||||
"members": "Μέλη",
|
"members": "Μέλη",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Manager",
|
"manager": "Manager",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "Match",
|
||||||
|
"match-all": "All (AND)",
|
||||||
|
"match-any": "Any (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Member",
|
"member": "Member",
|
||||||
"members": "Members",
|
"members": "Members",
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,9 @@
|
||||||
"manage": "Manage",
|
"manage": "Manage",
|
||||||
"manager": "Manager",
|
"manager": "Manager",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
|
"match": "Match",
|
||||||
|
"match-all": "All (AND)",
|
||||||
|
"match-any": "Any (OR)",
|
||||||
"maximize": "Maximize",
|
"maximize": "Maximize",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Member",
|
"member": "Member",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Gerente",
|
"manager": "Gerente",
|
||||||
"max": "Máximo",
|
"max": "Máximo",
|
||||||
"maximize": "Expandir",
|
"maximize": "Expandir",
|
||||||
|
"match": "Coincidencia",
|
||||||
|
"match-all": "Todo (AND)",
|
||||||
|
"match-any": "Cualquiera (OR)",
|
||||||
"medium": "Medio",
|
"medium": "Medio",
|
||||||
"member": "Miembro",
|
"member": "Miembro",
|
||||||
"members": "Miembros",
|
"members": "Miembros",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "مدیر",
|
"manager": "مدیر",
|
||||||
"max": "حداکثر",
|
"max": "حداکثر",
|
||||||
"maximize": "گسترش",
|
"maximize": "گسترش",
|
||||||
|
"match": "تطابق",
|
||||||
|
"match-all": "همه (AND)",
|
||||||
|
"match-any": "هر (OR)",
|
||||||
"medium": "متوسط",
|
"medium": "متوسط",
|
||||||
"member": "عضو",
|
"member": "عضو",
|
||||||
"members": "اعضا",
|
"members": "اعضا",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Päällikkö",
|
"manager": "Päällikkö",
|
||||||
"max": "Maksimi",
|
"max": "Maksimi",
|
||||||
"maximize": "Laajenna",
|
"maximize": "Laajenna",
|
||||||
|
"match": "Vastaavuus",
|
||||||
|
"match-all": "Kaikki (AND)",
|
||||||
|
"match-any": "Mikä tahansa (OR)",
|
||||||
"medium": "Keskitaso",
|
"medium": "Keskitaso",
|
||||||
"member": "Jäsen",
|
"member": "Jäsen",
|
||||||
"members": "Jäsenet",
|
"members": "Jäsenet",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Stjóri",
|
"manager": "Stjóri",
|
||||||
"max": "Mest",
|
"max": "Mest",
|
||||||
"maximize": "Víðka",
|
"maximize": "Víðka",
|
||||||
|
"match": "Samsvørun",
|
||||||
|
"match-all": "Allt (AND)",
|
||||||
|
"match-any": "Nakað (OR)",
|
||||||
"medium": "Miðal",
|
"medium": "Miðal",
|
||||||
"member": "Limur",
|
"member": "Limur",
|
||||||
"members": "Limir",
|
"members": "Limir",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Gestionnaire",
|
"manager": "Gestionnaire",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Développer",
|
"maximize": "Développer",
|
||||||
|
"match": "Correspondance",
|
||||||
|
"match-all": "Tous (AND)",
|
||||||
|
"match-any": "N'importe lequel (OR)",
|
||||||
"medium": "Moyen",
|
"medium": "Moyen",
|
||||||
"member": "Membre",
|
"member": "Membre",
|
||||||
"members": "Membres",
|
"members": "Membres",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Xestor",
|
"manager": "Xestor",
|
||||||
"max": "Máx",
|
"max": "Máx",
|
||||||
"maximize": "Expandir",
|
"maximize": "Expandir",
|
||||||
|
"match": "Coincidencia",
|
||||||
|
"match-all": "Todo (AND)",
|
||||||
|
"match-any": "Calquera (OR)",
|
||||||
"medium": "Medio",
|
"medium": "Medio",
|
||||||
"member": "Membro",
|
"member": "Membro",
|
||||||
"members": "Membros",
|
"members": "Membros",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "מנהל",
|
"manager": "מנהל",
|
||||||
"max": "מקסימום",
|
"max": "מקסימום",
|
||||||
"maximize": "הרחב",
|
"maximize": "הרחב",
|
||||||
|
"match": "התאמה",
|
||||||
|
"match-all": "הכל (AND)",
|
||||||
|
"match-any": "כלשהו (OR)",
|
||||||
"medium": "בינוני",
|
"medium": "בינוני",
|
||||||
"member": "חבר",
|
"member": "חבר",
|
||||||
"members": "חברים",
|
"members": "חברים",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "प्रबंधक",
|
"manager": "प्रबंधक",
|
||||||
"max": "अधिकतम",
|
"max": "अधिकतम",
|
||||||
"maximize": "विस्तार करें",
|
"maximize": "विस्तार करें",
|
||||||
|
"match": "मेल",
|
||||||
|
"match-all": "सभी (AND)",
|
||||||
|
"match-any": "कोई भी (OR)",
|
||||||
"medium": "मध्यम",
|
"medium": "मध्यम",
|
||||||
"member": "सदस्य",
|
"member": "सदस्य",
|
||||||
"members": "सदस्यगण",
|
"members": "सदस्यगण",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Upravitelj",
|
"manager": "Upravitelj",
|
||||||
"max": "Maksimum",
|
"max": "Maksimum",
|
||||||
"maximize": "Proširi",
|
"maximize": "Proširi",
|
||||||
|
"match": "Podudaranje",
|
||||||
|
"match-all": "Sve (AND)",
|
||||||
|
"match-any": "Bilo koje (OR)",
|
||||||
"medium": "Srednje",
|
"medium": "Srednje",
|
||||||
"member": "Član",
|
"member": "Član",
|
||||||
"members": "Članovi",
|
"members": "Članovi",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Menedzser",
|
"manager": "Menedzser",
|
||||||
"max": "Maximum",
|
"max": "Maximum",
|
||||||
"maximize": "Kibontás",
|
"maximize": "Kibontás",
|
||||||
|
"match": "Egyezés",
|
||||||
|
"match-all": "Összes (AND)",
|
||||||
|
"match-any": "Bármelyik (OR)",
|
||||||
"medium": "Közepes",
|
"medium": "Közepes",
|
||||||
"member": "Tag",
|
"member": "Tag",
|
||||||
"members": "Tagok",
|
"members": "Tagok",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Manajer",
|
"manager": "Manajer",
|
||||||
"max": "Maksimum",
|
"max": "Maksimum",
|
||||||
"maximize": "Perluas",
|
"maximize": "Perluas",
|
||||||
|
"match": "Cocok",
|
||||||
|
"match-all": "Semua (AND)",
|
||||||
|
"match-any": "Salah satu (OR)",
|
||||||
"medium": "Sedang",
|
"medium": "Sedang",
|
||||||
"member": "Anggota",
|
"member": "Anggota",
|
||||||
"members": "Anggota",
|
"members": "Anggota",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Gestore",
|
"manager": "Gestore",
|
||||||
"max": "Massimo",
|
"max": "Massimo",
|
||||||
"maximize": "Espandi",
|
"maximize": "Espandi",
|
||||||
|
"match": "Corrispondenza",
|
||||||
|
"match-all": "Tutti (AND)",
|
||||||
|
"match-any": "Qualsiasi (OR)",
|
||||||
"medium": "Medio",
|
"medium": "Medio",
|
||||||
"member": "Membro",
|
"member": "Membro",
|
||||||
"members": "Membri",
|
"members": "Membri",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "管理者",
|
"manager": "管理者",
|
||||||
"max": "最大",
|
"max": "最大",
|
||||||
"maximize": "展開",
|
"maximize": "展開",
|
||||||
|
"match": "一致",
|
||||||
|
"match-all": "すべて (AND)",
|
||||||
|
"match-any": "いずれか (OR)",
|
||||||
"medium": "メディア",
|
"medium": "メディア",
|
||||||
"member": "メンバー",
|
"member": "メンバー",
|
||||||
"members": "メンバー",
|
"members": "メンバー",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "អ្នកគ្រប់គ្រង",
|
"manager": "អ្នកគ្រប់គ្រង",
|
||||||
"max": "អតិបរមា",
|
"max": "អតិបរមា",
|
||||||
"maximize": "ពង្រីក",
|
"maximize": "ពង្រីក",
|
||||||
|
"match": "ត្រូវគ្នា",
|
||||||
|
"match-all": "ទាំងអស់ (AND)",
|
||||||
|
"match-any": "ណាមួយ (OR)",
|
||||||
"medium": "មធ្យម",
|
"medium": "មធ្យម",
|
||||||
"member": "សមាជិក",
|
"member": "សមាជិក",
|
||||||
"members": "សមាជិក",
|
"members": "សមាជិក",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "관리자",
|
"manager": "관리자",
|
||||||
"max": "최대",
|
"max": "최대",
|
||||||
"maximize": "확장",
|
"maximize": "확장",
|
||||||
|
"match": "일치",
|
||||||
|
"match-all": "전체 (AND)",
|
||||||
|
"match-any": "일부 (OR)",
|
||||||
"medium": "미디엄",
|
"medium": "미디엄",
|
||||||
"member": "멤버",
|
"member": "멤버",
|
||||||
"members": "멤버",
|
"members": "멤버",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Vadovas",
|
"manager": "Vadovas",
|
||||||
"max": "Maksimumas",
|
"max": "Maksimumas",
|
||||||
"maximize": "Išplėsti",
|
"maximize": "Išplėsti",
|
||||||
|
"match": "Atitikimas",
|
||||||
|
"match-all": "Visi (AND)",
|
||||||
|
"match-any": "Bet kuris (OR)",
|
||||||
"medium": "Vidutinis",
|
"medium": "Vidutinis",
|
||||||
"member": "Narys",
|
"member": "Narys",
|
||||||
"members": "Nariai",
|
"members": "Nariai",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Удирдагч",
|
"manager": "Удирдагч",
|
||||||
"max": "Дээд",
|
"max": "Дээд",
|
||||||
"maximize": "Өргөтгөх",
|
"maximize": "Өргөтгөх",
|
||||||
|
"match": "Тохирох",
|
||||||
|
"match-all": "Бүгд (AND)",
|
||||||
|
"match-any": "Ямар ч (OR)",
|
||||||
"medium": "Дунд",
|
"medium": "Дунд",
|
||||||
"member": "Гишүүн",
|
"member": "Гишүүн",
|
||||||
"members": "Гишүүд",
|
"members": "Гишүүд",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Pengurus",
|
"manager": "Pengurus",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "Padanan",
|
||||||
|
"match-all": "Semua (AND)",
|
||||||
|
"match-any": "Mana-mana (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Ahli",
|
"member": "Ahli",
|
||||||
"members": "Ahli",
|
"members": "Ahli",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "မန်နေဂျာ",
|
"manager": "မန်နေဂျာ",
|
||||||
"max": "အများဆုံး",
|
"max": "အများဆုံး",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "ကိုက်ညီ",
|
||||||
|
"match-all": "အားလုံး (AND)",
|
||||||
|
"match-any": "တစ်ခုခု (OR)",
|
||||||
"medium": "မီဒီယမ်",
|
"medium": "မီဒီယမ်",
|
||||||
"member": "အဖွဲ့ဝင်",
|
"member": "အဖွဲ့ဝင်",
|
||||||
"members": "အဖွဲ့ဝင်များ",
|
"members": "အဖွဲ့ဝင်များ",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Administrator",
|
"manager": "Administrator",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Utvid",
|
"maximize": "Utvid",
|
||||||
|
"match": "Samsvar",
|
||||||
|
"match-all": "Alle (AND)",
|
||||||
|
"match-any": "Enhver (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Bruker",
|
"member": "Bruker",
|
||||||
"members": "Brukere",
|
"members": "Brukere",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Beheerder",
|
"manager": "Beheerder",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Uitvouwen",
|
"maximize": "Uitvouwen",
|
||||||
|
"match": "Overeenkomst",
|
||||||
|
"match-all": "Alle (AND)",
|
||||||
|
"match-any": "Elk (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Gebruiker",
|
"member": "Gebruiker",
|
||||||
"members": "Gebruikers",
|
"members": "Gebruikers",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Menedżer",
|
"manager": "Menedżer",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Rozwiń",
|
"maximize": "Rozwiń",
|
||||||
|
"match": "Dopasowanie",
|
||||||
|
"match-all": "Wszystkie (AND)",
|
||||||
|
"match-any": "Dowolny (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Członek",
|
"member": "Członek",
|
||||||
"members": "Członkowie",
|
"members": "Członkowie",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Gerente",
|
"manager": "Gerente",
|
||||||
"max": "Máximo",
|
"max": "Máximo",
|
||||||
"maximize": "Expandir",
|
"maximize": "Expandir",
|
||||||
|
"match": "Correspondência",
|
||||||
|
"match-all": "Todos (AND)",
|
||||||
|
"match-any": "Qualquer (OR)",
|
||||||
"medium": "Médio",
|
"medium": "Médio",
|
||||||
"member": "Membro",
|
"member": "Membro",
|
||||||
"members": "Membros",
|
"members": "Membros",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Gestor",
|
"manager": "Gestor",
|
||||||
"max": "Máximo",
|
"max": "Máximo",
|
||||||
"maximize": "Expandir",
|
"maximize": "Expandir",
|
||||||
|
"match": "Correspondência",
|
||||||
|
"match-all": "Todos (AND)",
|
||||||
|
"match-any": "Qualquer (OR)",
|
||||||
"medium": "Médio",
|
"medium": "Médio",
|
||||||
"member": "Membro",
|
"member": "Membro",
|
||||||
"members": "Membros",
|
"members": "Membros",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Manager",
|
"manager": "Manager",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Extinde",
|
"maximize": "Extinde",
|
||||||
|
"match": "Potrivire",
|
||||||
|
"match-all": "Toate (AND)",
|
||||||
|
"match-any": "Oricare (OR)",
|
||||||
"medium": "Mediu",
|
"medium": "Mediu",
|
||||||
"member": "Membru",
|
"member": "Membru",
|
||||||
"members": "Membri",
|
"members": "Membri",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Менеджер",
|
"manager": "Менеджер",
|
||||||
"max": "Максимум",
|
"max": "Максимум",
|
||||||
"maximize": "Развернуть",
|
"maximize": "Развернуть",
|
||||||
|
"match": "Соответствие",
|
||||||
|
"match-all": "Все (AND)",
|
||||||
|
"match-any": "Любой (OR)",
|
||||||
"medium": "Средний",
|
"medium": "Средний",
|
||||||
"member": "Участник",
|
"member": "Участник",
|
||||||
"members": "Участники",
|
"members": "Участники",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "කළමනාකරු",
|
"manager": "කළමනාකරු",
|
||||||
"max": "උපරිම",
|
"max": "උපරිම",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "ගැළපීම",
|
||||||
|
"match-all": "සියල්ල (AND)",
|
||||||
|
"match-any": "ඕනෑම (OR)",
|
||||||
"medium": "මාධ්යය",
|
"medium": "මාධ්යය",
|
||||||
"member": "සාමාජිකයා",
|
"member": "සාමාජිකයා",
|
||||||
"members": "සාමාජිකයින්",
|
"members": "සාමාජිකයින්",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Manažér",
|
"manager": "Manažér",
|
||||||
"max": "Maximum",
|
"max": "Maximum",
|
||||||
"maximize": "Rozbaliť",
|
"maximize": "Rozbaliť",
|
||||||
|
"match": "Zhoda",
|
||||||
|
"match-all": "Všetky (AND)",
|
||||||
|
"match-any": "Akýkoľvek (OR)",
|
||||||
"medium": "Stredný",
|
"medium": "Stredný",
|
||||||
"member": "Člen",
|
"member": "Člen",
|
||||||
"members": "Členovia",
|
"members": "Členovia",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Upravitelj",
|
"manager": "Upravitelj",
|
||||||
"max": "Največ",
|
"max": "Največ",
|
||||||
"maximize": "Povečaj",
|
"maximize": "Povečaj",
|
||||||
|
"match": "Ujemanje",
|
||||||
|
"match-all": "Vse (AND)",
|
||||||
|
"match-any": "Katero koli (OR)",
|
||||||
"medium": "Medij",
|
"medium": "Medij",
|
||||||
"member": "Član",
|
"member": "Član",
|
||||||
"members": "Člani",
|
"members": "Člani",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Ansvarig",
|
"manager": "Ansvarig",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"maximize": "Expandera",
|
"maximize": "Expandera",
|
||||||
|
"match": "Matchning",
|
||||||
|
"match-all": "Alla (AND)",
|
||||||
|
"match-any": "Vilken som helst (OR)",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"member": "Medlem",
|
"member": "Medlem",
|
||||||
"members": "Medlemmar",
|
"members": "Medlemmar",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "மேலாளர்",
|
"manager": "மேலாளர்",
|
||||||
"max": "அதிகபட்சம்",
|
"max": "அதிகபட்சம்",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "பொருத்தம்",
|
||||||
|
"match-all": "அனைத்தும் (AND)",
|
||||||
|
"match-any": "எதுவும் (OR)",
|
||||||
"medium": "ஊடகம்",
|
"medium": "ஊடகம்",
|
||||||
"member": "உறுப்பினர்",
|
"member": "உறுப்பினர்",
|
||||||
"members": "உறுப்பினர்கள்",
|
"members": "உறுப்பினர்கள்",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "ผู้จัดการ",
|
"manager": "ผู้จัดการ",
|
||||||
"max": "สูงสุด",
|
"max": "สูงสุด",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "จับคู่",
|
||||||
|
"match-all": "ทั้งหมด (AND)",
|
||||||
|
"match-any": "ใดๆ (OR)",
|
||||||
"medium": "สื่อ",
|
"medium": "สื่อ",
|
||||||
"member": "สมาชิก",
|
"member": "สมาชิก",
|
||||||
"members": "สมาชิก",
|
"members": "สมาชิก",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Yönetici",
|
"manager": "Yönetici",
|
||||||
"max": "Maks",
|
"max": "Maks",
|
||||||
"maximize": "Genişlet",
|
"maximize": "Genişlet",
|
||||||
|
"match": "Eşleşme",
|
||||||
|
"match-all": "Tümü (AND)",
|
||||||
|
"match-any": "Herhangi (OR)",
|
||||||
"medium": "Orta",
|
"medium": "Orta",
|
||||||
"member": "Üye",
|
"member": "Üye",
|
||||||
"members": "Üyeler",
|
"members": "Üyeler",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Менеджер",
|
"manager": "Менеджер",
|
||||||
"max": "Макс.",
|
"max": "Макс.",
|
||||||
"maximize": "Розгорнути",
|
"maximize": "Розгорнути",
|
||||||
|
"match": "Відповідність",
|
||||||
|
"match-all": "Усі (AND)",
|
||||||
|
"match-any": "Будь-який (OR)",
|
||||||
"medium": "Середній",
|
"medium": "Середній",
|
||||||
"member": "Учасник",
|
"member": "Учасник",
|
||||||
"members": "Учасники",
|
"members": "Учасники",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "منتظم",
|
"manager": "منتظم",
|
||||||
"max": "زیادہ سے زیادہ",
|
"max": "زیادہ سے زیادہ",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "مطابقت",
|
||||||
|
"match-all": "سب (AND)",
|
||||||
|
"match-any": "کوئی بھی (OR)",
|
||||||
"medium": "میڈیم",
|
"medium": "میڈیم",
|
||||||
"member": "رکن",
|
"member": "رکن",
|
||||||
"members": "اراکین",
|
"members": "اراکین",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Menejer",
|
"manager": "Menejer",
|
||||||
"max": "Maksimal",
|
"max": "Maksimal",
|
||||||
"maximize": "Kattalashtirish",
|
"maximize": "Kattalashtirish",
|
||||||
|
"match": "Moslik",
|
||||||
|
"match-all": "Barchasi (AND)",
|
||||||
|
"match-any": "Istalgan (OR)",
|
||||||
"medium": "Vosita",
|
"medium": "Vosita",
|
||||||
"member": "A'zo",
|
"member": "A'zo",
|
||||||
"members": "A'zolar",
|
"members": "A'zolar",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "Quản lý",
|
"manager": "Quản lý",
|
||||||
"max": "Tối đa",
|
"max": "Tối đa",
|
||||||
"maximize": "Phóng to",
|
"maximize": "Phóng to",
|
||||||
|
"match": "Khớp",
|
||||||
|
"match-all": "Tất cả (AND)",
|
||||||
|
"match-any": "Bất kỳ (OR)",
|
||||||
"medium": "Phương tiện",
|
"medium": "Phương tiện",
|
||||||
"member": "Thành viên",
|
"member": "Thành viên",
|
||||||
"members": "Các thành viên",
|
"members": "Các thành viên",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "管理者",
|
"manager": "管理者",
|
||||||
"max": "最大",
|
"max": "最大",
|
||||||
"maximize": "展开",
|
"maximize": "展开",
|
||||||
|
"match": "匹配",
|
||||||
|
"match-all": "全部 (AND)",
|
||||||
|
"match-any": "任意 (OR)",
|
||||||
"medium": "中等",
|
"medium": "中等",
|
||||||
"member": "成员",
|
"member": "成员",
|
||||||
"members": "成员",
|
"members": "成员",
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@
|
||||||
"manager": "管理者",
|
"manager": "管理者",
|
||||||
"max": "最大值",
|
"max": "最大值",
|
||||||
"maximize": "Expand",
|
"maximize": "Expand",
|
||||||
|
"match": "符合",
|
||||||
|
"match-all": "全部 (AND)",
|
||||||
|
"match-any": "任意 (OR)",
|
||||||
"medium": "媒介",
|
"medium": "媒介",
|
||||||
"member": "成員",
|
"member": "成員",
|
||||||
"members": "成員",
|
"members": "成員",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
Loading,
|
Loading,
|
||||||
TextField,
|
TextField,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useMessages, useUpdateQuery, useWebsiteCohortQuery } from '@/components/hooks';
|
import { useMessages, useUpdateQuery, useWebsiteCohortQuery } from '@/components/hooks';
|
||||||
import { ActionSelect } from '@/components/input/ActionSelect';
|
import { ActionSelect } from '@/components/input/ActionSelect';
|
||||||
import { DateFilter } from '@/components/input/DateFilter';
|
import { DateFilter } from '@/components/input/DateFilter';
|
||||||
|
|
@ -32,6 +33,11 @@ export function CohortEditForm({
|
||||||
}) {
|
}) {
|
||||||
const { data } = useWebsiteCohortQuery(websiteId, cohortId);
|
const { data } = useWebsiteCohortQuery(websiteId, cohortId);
|
||||||
const { t, labels, messages, getErrorMessage } = useMessages();
|
const { t, labels, messages, getErrorMessage } = useMessages();
|
||||||
|
const [currentMatch, setCurrentMatch] = useState<string>('all');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentMatch((data?.parameters as any)?.match || 'all');
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery(
|
const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery(
|
||||||
`/websites/${websiteId}/segments${cohortId ? `/${cohortId}` : ''}`,
|
`/websites/${websiteId}/segments${cohortId ? `/${cohortId}` : ''}`,
|
||||||
|
|
@ -41,14 +47,23 @@ export function CohortEditForm({
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = async (formData: any) => {
|
const handleSubmit = async (formData: any) => {
|
||||||
await mutateAsync(formData, {
|
await mutateAsync(
|
||||||
onSuccess: async () => {
|
{
|
||||||
toast(t(messages.saved));
|
...formData,
|
||||||
touch('cohorts');
|
parameters: {
|
||||||
onSave?.();
|
...formData.parameters,
|
||||||
onClose?.();
|
match: currentMatch !== 'all' ? currentMatch : undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: async () => {
|
||||||
|
toast(t(messages.saved));
|
||||||
|
touch('cohorts');
|
||||||
|
onSave?.();
|
||||||
|
onClose?.();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cohortId && !data) {
|
if (cohortId && !data) {
|
||||||
|
|
@ -105,7 +120,12 @@ export function CohortEditForm({
|
||||||
<Column>
|
<Column>
|
||||||
<Label>{t(labels.filters)}</Label>
|
<Label>{t(labels.filters)}</Label>
|
||||||
<FormField name="parameters.filters">
|
<FormField name="parameters.filters">
|
||||||
<FieldFilters websiteId={websiteId} exclude={['path', 'event']} />
|
<FieldFilters
|
||||||
|
websiteId={websiteId}
|
||||||
|
exclude={['path', 'event']}
|
||||||
|
match={currentMatch}
|
||||||
|
onMatchChange={setCurrentMatch}
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</Column>
|
</Column>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Loading,
|
Loading,
|
||||||
TextField,
|
TextField,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useMessages, useUpdateQuery, useWebsiteSegmentQuery } from '@/components/hooks';
|
import { useMessages, useUpdateQuery, useWebsiteSegmentQuery } from '@/components/hooks';
|
||||||
import { FieldFilters } from '@/components/input/FieldFilters';
|
import { FieldFilters } from '@/components/input/FieldFilters';
|
||||||
|
|
||||||
|
|
@ -28,6 +29,11 @@ export function SegmentEditForm({
|
||||||
}) {
|
}) {
|
||||||
const { data } = useWebsiteSegmentQuery(websiteId, segmentId);
|
const { data } = useWebsiteSegmentQuery(websiteId, segmentId);
|
||||||
const { t, labels, messages, getErrorMessage } = useMessages();
|
const { t, labels, messages, getErrorMessage } = useMessages();
|
||||||
|
const [currentMatch, setCurrentMatch] = useState<string>('all');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentMatch((data?.parameters as any)?.match || 'all');
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery(
|
const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery(
|
||||||
`/websites/${websiteId}/segments${segmentId ? `/${segmentId}` : ''}`,
|
`/websites/${websiteId}/segments${segmentId ? `/${segmentId}` : ''}`,
|
||||||
|
|
@ -37,14 +43,23 @@ export function SegmentEditForm({
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = async (formData: any) => {
|
const handleSubmit = async (formData: any) => {
|
||||||
await mutateAsync(formData, {
|
await mutateAsync(
|
||||||
onSuccess: async () => {
|
{
|
||||||
toast(t(messages.saved));
|
...formData,
|
||||||
touch('segments');
|
parameters: {
|
||||||
onSave?.();
|
...formData.parameters,
|
||||||
onClose?.();
|
match: currentMatch !== 'all' ? currentMatch : undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onSuccess: async () => {
|
||||||
|
toast(t(messages.saved));
|
||||||
|
touch('segments');
|
||||||
|
onSave?.();
|
||||||
|
onClose?.();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (segmentId && !data) {
|
if (segmentId && !data) {
|
||||||
|
|
@ -64,7 +79,11 @@ export function SegmentEditForm({
|
||||||
<>
|
<>
|
||||||
<Label>{t(labels.filters)}</Label>
|
<Label>{t(labels.filters)}</Label>
|
||||||
<FormField name="parameters.filters" rules={{ required: t(labels.required) }}>
|
<FormField name="parameters.filters" rules={{ required: t(labels.required) }}>
|
||||||
<FieldFilters websiteId={websiteId} />
|
<FieldFilters
|
||||||
|
websiteId={websiteId}
|
||||||
|
match={currentMatch}
|
||||||
|
onMatchChange={setCurrentMatch}
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export function useFilterParameters() {
|
||||||
segment: query.segment,
|
segment: query.segment,
|
||||||
cohort: query.cohort,
|
cohort: query.cohort,
|
||||||
excludeBounce: query.excludeBounce,
|
excludeBounce: query.excludeBounce,
|
||||||
|
match: query.match,
|
||||||
page: query.page,
|
page: query.page,
|
||||||
pageSize: query.pageSize,
|
pageSize: query.pageSize,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import {
|
||||||
Column,
|
Column,
|
||||||
Grid,
|
Grid,
|
||||||
Icon,
|
Icon,
|
||||||
|
Label,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListSection,
|
ListSection,
|
||||||
|
|
@ -12,6 +13,7 @@ import {
|
||||||
MenuTrigger,
|
MenuTrigger,
|
||||||
Popover,
|
Popover,
|
||||||
Row,
|
Row,
|
||||||
|
Select,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { endOfDay, subMonths } from 'date-fns';
|
import { endOfDay, subMonths } from 'date-fns';
|
||||||
import type { Key } from 'react';
|
import type { Key } from 'react';
|
||||||
|
|
@ -24,11 +26,20 @@ export interface FieldFiltersProps {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
value?: { name: string; operator: string; value: string }[];
|
value?: { name: string; operator: string; value: string }[];
|
||||||
exclude?: string[];
|
exclude?: string[];
|
||||||
|
match?: string;
|
||||||
onChange?: (data: any) => void;
|
onChange?: (data: any) => void;
|
||||||
|
onMatchChange?: (match: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FieldFilters({ websiteId, value, exclude = [], onChange }: FieldFiltersProps) {
|
export function FieldFilters({
|
||||||
const { t, messages } = useMessages();
|
websiteId,
|
||||||
|
value,
|
||||||
|
exclude = [],
|
||||||
|
match = 'all',
|
||||||
|
onChange,
|
||||||
|
onMatchChange,
|
||||||
|
}: FieldFiltersProps) {
|
||||||
|
const { t, labels, messages } = useMessages();
|
||||||
const { fields, groupLabels } = useFields();
|
const { fields, groupLabels } = useFields();
|
||||||
const startDate = subMonths(endOfDay(new Date()), 6);
|
const startDate = subMonths(endOfDay(new Date()), 6);
|
||||||
const endDate = endOfDay(new Date());
|
const endDate = endOfDay(new Date());
|
||||||
|
|
@ -126,6 +137,17 @@ export function FieldFilters({ websiteId, value, exclude = [], onChange }: Field
|
||||||
</List>
|
</List>
|
||||||
</Column>
|
</Column>
|
||||||
<Column overflow="auto" gapY="4" style={{ contain: 'layout' }}>
|
<Column overflow="auto" gapY="4" style={{ contain: 'layout' }}>
|
||||||
|
{onMatchChange && (
|
||||||
|
<Row alignItems="center" gap>
|
||||||
|
<Column gap="1">
|
||||||
|
<Label>{t(labels.match)}</Label>
|
||||||
|
<Select value={match} onChange={onMatchChange} style={{ width: 150 }}>
|
||||||
|
<ListItem id="all">{t(labels.matchAll)}</ListItem>
|
||||||
|
<ListItem id="any">{t(labels.matchAny)}</ListItem>
|
||||||
|
</Select>
|
||||||
|
</Column>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
{value.map((filter, index) => {
|
{value.map((filter, index) => {
|
||||||
return (
|
return (
|
||||||
<FilterRecord
|
<FilterRecord
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,18 @@ import { SegmentFilters } from '@/components/input/SegmentFilters';
|
||||||
|
|
||||||
export interface FilterEditFormProps {
|
export interface FilterEditFormProps {
|
||||||
websiteId?: string;
|
websiteId?: string;
|
||||||
onChange?: (params: { filters: any[]; segment?: string; cohort?: string }) => void;
|
onChange?: (params: {
|
||||||
|
filters: any[];
|
||||||
|
segment?: string;
|
||||||
|
cohort?: string;
|
||||||
|
match?: string;
|
||||||
|
}) => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormProps) {
|
export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormProps) {
|
||||||
const {
|
const {
|
||||||
query: { segment, cohort },
|
query: { segment, cohort, match },
|
||||||
pathname,
|
pathname,
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
const { filters } = useFilters();
|
const { filters } = useFilters();
|
||||||
|
|
@ -20,6 +25,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
|
||||||
const [currentFilters, setCurrentFilters] = useState(filters);
|
const [currentFilters, setCurrentFilters] = useState(filters);
|
||||||
const [currentSegment, setCurrentSegment] = useState(segment);
|
const [currentSegment, setCurrentSegment] = useState(segment);
|
||||||
const [currentCohort, setCurrentCohort] = useState(cohort);
|
const [currentCohort, setCurrentCohort] = useState(cohort);
|
||||||
|
const [currentMatch, setCurrentMatch] = useState<string>(match || 'all');
|
||||||
const { isMobile } = useMobile();
|
const { isMobile } = useMobile();
|
||||||
const excludeFilters = pathname.includes('/pixels') || pathname.includes('/links');
|
const excludeFilters = pathname.includes('/pixels') || pathname.includes('/links');
|
||||||
const excludeEvent = !pathname.endsWith('/events');
|
const excludeEvent = !pathname.endsWith('/events');
|
||||||
|
|
@ -28,6 +34,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
|
||||||
setCurrentFilters([]);
|
setCurrentFilters([]);
|
||||||
setCurrentSegment(undefined);
|
setCurrentSegment(undefined);
|
||||||
setCurrentCohort(undefined);
|
setCurrentCohort(undefined);
|
||||||
|
setCurrentMatch('all');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
|
|
@ -35,6 +42,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
|
||||||
filters: currentFilters.filter(f => f.value),
|
filters: currentFilters.filter(f => f.value),
|
||||||
segment: currentSegment,
|
segment: currentSegment,
|
||||||
cohort: currentCohort,
|
cohort: currentCohort,
|
||||||
|
match: currentMatch !== 'all' ? currentMatch : undefined,
|
||||||
});
|
});
|
||||||
onClose?.();
|
onClose?.();
|
||||||
};
|
};
|
||||||
|
|
@ -61,7 +69,9 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
|
||||||
<FieldFilters
|
<FieldFilters
|
||||||
websiteId={websiteId}
|
websiteId={websiteId}
|
||||||
value={currentFilters}
|
value={currentFilters}
|
||||||
|
match={currentMatch}
|
||||||
onChange={setCurrentFilters}
|
onChange={setCurrentFilters}
|
||||||
|
onMatchChange={setCurrentMatch}
|
||||||
exclude={
|
exclude={
|
||||||
excludeFilters
|
excludeFilters
|
||||||
? ['path', 'title', 'hostname', 'distinctId', 'tag', 'event']
|
? ['path', 'title', 'hostname', 'distinctId', 'tag', 'event']
|
||||||
|
|
@ -92,7 +102,13 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
|
||||||
<Button onPress={handleReset}>{t(labels.reset)}</Button>
|
<Button onPress={handleReset}>{t(labels.reset)}</Button>
|
||||||
<Row alignItems="center" justifyContent="flex-end" gridColumn="span 2" gap>
|
<Row alignItems="center" justifyContent="flex-end" gridColumn="span 2" gap>
|
||||||
<Button onPress={onClose}>{t(labels.cancel)}</Button>
|
<Button onPress={onClose}>{t(labels.cancel)}</Button>
|
||||||
<Button variant="primary" onPress={handleSave}>
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
onPress={handleSave}
|
||||||
|
isDisabled={
|
||||||
|
currentFilters.filter(f => f.value).length === 0 && !currentSegment && !currentCohort
|
||||||
|
}
|
||||||
|
>
|
||||||
{t(labels.apply)}
|
{t(labels.apply)}
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,14 @@ export function WebsiteFilterButton({
|
||||||
const isOverview =
|
const isOverview =
|
||||||
/^\/teams\/[^/]+\/websites\/[^/]+$/.test(pathname) || /^\/share\/[^/]+$/.test(pathname);
|
/^\/teams\/[^/]+\/websites\/[^/]+$/.test(pathname) || /^\/share\/[^/]+$/.test(pathname);
|
||||||
|
|
||||||
const handleChange = ({ filters, segment, cohort }: any) => {
|
const handleChange = ({ filters, segment, cohort, match }: any) => {
|
||||||
const params = filtersArrayToObject(filters);
|
const params = filtersArrayToObject(filters);
|
||||||
|
|
||||||
const url = updateParams({
|
const url = updateParams({
|
||||||
...params,
|
...params,
|
||||||
segment,
|
segment,
|
||||||
cohort,
|
cohort,
|
||||||
|
match,
|
||||||
excludeBounce: excludeBounce ? 'true' : undefined,
|
excludeBounce: excludeBounce ? 'true' : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,9 @@ export const labels: Record<string, string> = {
|
||||||
other: 'label.other',
|
other: 'label.other',
|
||||||
boards: 'label.boards',
|
boards: 'label.boards',
|
||||||
apply: 'label.apply',
|
apply: 'label.apply',
|
||||||
|
match: 'label.match',
|
||||||
|
matchAll: 'label.match-all',
|
||||||
|
matchAny: 'label.match-any',
|
||||||
link: 'label.link',
|
link: 'label.link',
|
||||||
links: 'label.links',
|
links: 'label.links',
|
||||||
pixel: 'label.pixel',
|
pixel: 'label.pixel',
|
||||||
|
|
|
||||||
|
|
@ -99,32 +99,44 @@ function mapFilter(
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilterQuery(filters: Record<string, any>, options: QueryOptions = {}) {
|
function getFilterQuery(filters: Record<string, any>, options: QueryOptions = {}) {
|
||||||
const query = filtersObjectToArray(filters, options).reduce(
|
const { isCohort, cohortMatch, cohortActionName } = options;
|
||||||
(arr, { name, column, operator, paramName }) => {
|
const isOr = isCohort ? cohortMatch === 'any' : filters.match === 'any';
|
||||||
const isCohort = options?.isCohort;
|
const orClauses: string[] = [];
|
||||||
|
const andClauses: string[] = [];
|
||||||
|
|
||||||
if (isCohort) {
|
filtersObjectToArray(filters, options).forEach(({ name, column, operator, paramName }) => {
|
||||||
column = FILTER_COLUMNS[name.slice('cohort_'.length)];
|
if (isCohort) {
|
||||||
|
column = FILTER_COLUMNS[name.slice('cohort_'.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column) {
|
||||||
|
const isAlwaysAnd = name === 'eventType' || (isCohort && name === cohortActionName);
|
||||||
|
|
||||||
|
if (isAlwaysAnd) {
|
||||||
|
andClauses.push(
|
||||||
|
`and ${mapFilter(column, operator, name, name === 'eventType' ? 'UInt32' : 'String', paramName)}`,
|
||||||
|
);
|
||||||
|
} else if (isOr) {
|
||||||
|
orClauses.push(mapFilter(column, operator, name, 'String', paramName));
|
||||||
|
} else {
|
||||||
|
andClauses.push(`and ${mapFilter(column, operator, name, 'String', paramName)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column) {
|
if (name === 'referrer') {
|
||||||
if (name === 'eventType') {
|
andClauses.push(`and referrer_domain != hostname`);
|
||||||
arr.push(`and ${mapFilter(column, operator, name, 'UInt32', paramName)}`);
|
|
||||||
} else {
|
|
||||||
arr.push(`and ${mapFilter(column, operator, name, 'String', paramName)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name === 'referrer') {
|
|
||||||
arr.push(`and referrer_domain != hostname`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return arr;
|
const parts: string[] = [];
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return query.join('\n');
|
if (orClauses.length > 0) {
|
||||||
|
parts.push(`and (\n ${orClauses.join('\n or ')}\n)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(...andClauses);
|
||||||
|
|
||||||
|
return parts.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCohortQuery(filters: Record<string, any>) {
|
function getCohortQuery(filters: Record<string, any>) {
|
||||||
|
|
@ -132,7 +144,10 @@ function getCohortQuery(filters: Record<string, any>) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterQuery = getFilterQuery(filters, { isCohort: true });
|
const cohortMatch = filters.cohort_match;
|
||||||
|
const cohortActionName = filters.cohort_actionName;
|
||||||
|
|
||||||
|
const filterQuery = getFilterQuery(filters, { isCohort: true, cohortMatch, cohortActionName });
|
||||||
|
|
||||||
return `join (
|
return `join (
|
||||||
select distinct session_id
|
select distinct session_id
|
||||||
|
|
@ -267,7 +282,7 @@ async function rawQuery<T = unknown>(
|
||||||
output_format_json_quote_64bit_integers: 0,
|
output_format_json_quote_64bit_integers: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
console.log(query, params);
|
||||||
return (await resultSet.json()) as T;
|
return (await resultSet.json()) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,30 +106,47 @@ function mapFilter(
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilterQuery(filters: Record<string, any>, options: QueryOptions = {}): string {
|
function getFilterQuery(filters: Record<string, any>, options: QueryOptions = {}): string {
|
||||||
const query = filtersObjectToArray(filters, options).reduce(
|
const { isCohort, cohortMatch, cohortActionName } = options;
|
||||||
(arr, { name, column, operator, prefix = '', paramName }) => {
|
const isOr = isCohort ? cohortMatch === 'any' : filters.match === 'any';
|
||||||
const isCohort = options?.isCohort;
|
const orClauses: string[] = [];
|
||||||
|
const andClauses: string[] = [];
|
||||||
|
|
||||||
|
filtersObjectToArray(filters, options).forEach(
|
||||||
|
({ name, column, operator, prefix = '', paramName }) => {
|
||||||
if (isCohort) {
|
if (isCohort) {
|
||||||
column = FILTER_COLUMNS[name.slice('cohort_'.length)];
|
column = FILTER_COLUMNS[name.slice('cohort_'.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column) {
|
if (column) {
|
||||||
arr.push(`and ${mapFilter(`${prefix}${column}`, operator, name, '', paramName)}`);
|
const clause = mapFilter(`${prefix}${column}`, operator, name, '', paramName);
|
||||||
|
const isAlwaysAnd = name === 'eventType' || (isCohort && name === cohortActionName);
|
||||||
|
|
||||||
|
if (isAlwaysAnd) {
|
||||||
|
andClauses.push(`and ${clause}`);
|
||||||
|
} else if (isOr) {
|
||||||
|
orClauses.push(clause);
|
||||||
|
} else {
|
||||||
|
andClauses.push(`and ${clause}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'referrer') {
|
if (name === 'referrer') {
|
||||||
arr.push(
|
andClauses.push(
|
||||||
`and (website_event.referrer_domain != regexp_replace(website_event.hostname, '^www.', '') or website_event.referrer_domain is null)`,
|
`and (website_event.referrer_domain != regexp_replace(website_event.hostname, '^www.', '') or website_event.referrer_domain is null)`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
|
||||||
},
|
},
|
||||||
[],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return query.join('\n');
|
const parts: string[] = [];
|
||||||
|
|
||||||
|
if (orClauses.length > 0) {
|
||||||
|
parts.push(`and (\n ${orClauses.join('\n or ')}\n)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(...andClauses);
|
||||||
|
|
||||||
|
return parts.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCohortQuery(filters: QueryFilters = {}) {
|
function getCohortQuery(filters: QueryFilters = {}) {
|
||||||
|
|
@ -137,7 +154,10 @@ function getCohortQuery(filters: QueryFilters = {}) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterQuery = getFilterQuery(filters, { isCohort: true });
|
const cohortMatch = (filters as any).cohort_match;
|
||||||
|
const cohortActionName = (filters as any).cohort_actionName;
|
||||||
|
|
||||||
|
const filterQuery = getFilterQuery(filters, { isCohort: true, cohortMatch, cohortActionName });
|
||||||
|
|
||||||
return `join
|
return `join
|
||||||
(select distinct website_event.session_id
|
(select distinct website_event.session_id
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,8 @@ export async function getQueryFilters(
|
||||||
const dateRange = getRequestDateRange(params);
|
const dateRange = getRequestDateRange(params);
|
||||||
const filters = getRequestFilters(params);
|
const filters = getRequestFilters(params);
|
||||||
|
|
||||||
|
let match = params?.match;
|
||||||
|
|
||||||
if (websiteId) {
|
if (websiteId) {
|
||||||
await setWebsiteDate(websiteId, dateRange);
|
await setWebsiteDate(websiteId, dateRange);
|
||||||
|
|
||||||
|
|
@ -123,6 +125,10 @@ export async function getQueryFilters(
|
||||||
?.parameters as Record<string, any>;
|
?.parameters as Record<string, any>;
|
||||||
|
|
||||||
Object.assign(filters, filtersArrayToObject(segmentParams.filters));
|
Object.assign(filters, filtersArrayToObject(segmentParams.filters));
|
||||||
|
|
||||||
|
if (segmentParams.match) {
|
||||||
|
match = segmentParams.match;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.cohort) {
|
if (params.cohort) {
|
||||||
|
|
@ -146,6 +152,10 @@ export async function getQueryFilters(
|
||||||
...filtersArrayToObject(cohortFilters),
|
...filtersArrayToObject(cohortFilters),
|
||||||
cohort_startDate: startDate,
|
cohort_startDate: startDate,
|
||||||
cohort_endDate: endDate,
|
cohort_endDate: endDate,
|
||||||
|
...(cohortParams.match && {
|
||||||
|
cohort_match: cohortParams.match,
|
||||||
|
cohort_actionName: `cohort_${cohortParams.action.type}`,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,6 +167,7 @@ export async function getQueryFilters(
|
||||||
return {
|
return {
|
||||||
...dateRange,
|
...dateRange,
|
||||||
...filters,
|
...filters,
|
||||||
|
match,
|
||||||
page: params?.page,
|
page: params?.page,
|
||||||
pageSize: params?.pageSize ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined,
|
pageSize: params?.pageSize ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined,
|
||||||
orderBy: params?.orderBy,
|
orderBy: params?.orderBy,
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ export const filterParams = {
|
||||||
cohort: z.uuid().optional(),
|
cohort: z.uuid().optional(),
|
||||||
eventType: z.coerce.number().int().positive().optional(),
|
eventType: z.coerce.number().int().positive().optional(),
|
||||||
excludeBounce: z.string().optional(),
|
excludeBounce: z.string().optional(),
|
||||||
|
match: z.enum(['all', 'any']).optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const searchParams = {
|
export const searchParams = {
|
||||||
|
|
@ -295,6 +296,7 @@ export const segmentParamSchema = z.object({
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
|
match: z.enum(['all', 'any']).optional(),
|
||||||
dateRange: z.string().optional(),
|
dateRange: z.string().optional(),
|
||||||
action: z
|
action: z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ export interface QueryOptions {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
isCohort?: boolean;
|
isCohort?: boolean;
|
||||||
|
cohortMatch?: string;
|
||||||
|
cohortActionName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryFilters
|
export interface QueryFilters
|
||||||
|
|
@ -93,6 +95,7 @@ export interface FilterParams {
|
||||||
cohort?: string;
|
cohort?: string;
|
||||||
compare?: string;
|
compare?: string;
|
||||||
excludeBounce?: boolean;
|
excludeBounce?: boolean;
|
||||||
|
match?: 'all' | 'any';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SortParams {
|
export interface SortParams {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue