Reorganize admin into tabbed hubs with a condensed sidebar.
Local Build and Deploy / deploy (push) Successful in 57s
Local Build and Deploy / deploy (push) Successful in 57s
Replace the long flat nav with hub entries, shared AdminHubChrome tabs, and AdminPageShell. Existing URLs stay stable; Settings/Radio and other sections now share one chrome. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
367f69a439
commit
363c9b3d56
30 files changed
+854
-432
No files matched your search
+36
-367
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,3 @@
|
|||||||
import { Cog, ExternalLink } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
@@ -10,13 +8,6 @@ import { CmsSettingsForm } from "./cms-settings-form";
|
|||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
export const metadata = { title: "CMS Settings" };
|
export const metadata = { title: "CMS Settings" };
|
||||||
|
|
||||||
const RELATED = [
|
|
||||||
{ href: "/admin/theme", label: "Theme & colors" },
|
|
||||||
{ href: "/admin/maintenance", label: "Maintenance" },
|
|
||||||
{ href: "/admin/vpn", label: "VPN / proxy block" },
|
|
||||||
{ href: "/admin/emulator", label: "Emulator config" },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export default async function AdminSettings() {
|
export default async function AdminSettings() {
|
||||||
const { session, permissions } = await getAdminContext();
|
const { session, permissions } = await getAdminContext();
|
||||||
if (!canAccess(permissions, PERMS.SETTINGS_VIEW, session.user.rank)) {
|
if (!canAccess(permissions, PERMS.SETTINGS_VIEW, session.user.rank)) {
|
||||||
@@ -49,34 +40,6 @@ export default async function AdminSettings() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="flex flex-wrap items-start justify-between gap-4">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-[var(--admin-accent)]/20 to-[var(--admin-accent)]/5 grid place-items-center">
|
|
||||||
<Cog size={20} className="text-[var(--admin-accent)]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 className="m-0 text-2xl font-extrabold tracking-tight text-[var(--admin-text)]">
|
|
||||||
CMS Settings
|
|
||||||
</h1>
|
|
||||||
<p className="m-0 mt-0.5 text-sm text-[var(--admin-text-muted)]">
|
|
||||||
Configure hotel identity, imaging, client, radio and security.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{RELATED.map((item) => (
|
|
||||||
<Link
|
|
||||||
key={item.href}
|
|
||||||
href={item.href}
|
|
||||||
className="inline-flex items-center gap-1.5 rounded-full border border-[var(--admin-border)] bg-[var(--admin-surface)] px-3 py-1.5 text-xs font-semibold text-[var(--admin-text)] no-underline hover:border-[var(--admin-accent)] transition-colors"
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
<ExternalLink size={12} className="opacity-60" />
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="admin-stat-row">
|
<div className="admin-stat-row">
|
||||||
<span className="admin-stat-chip">
|
<span className="admin-stat-chip">
|
||||||
{settings.length} keys in database
|
{settings.length} keys in database
|
||||||
|
|||||||
@@ -505,6 +505,12 @@ tbody tr:hover {
|
|||||||
scroll-margin-top: 1rem;
|
scroll-margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hub chrome already shows the section title — soften page-level heroes. */
|
||||||
|
.admin-hub-panel > .space-y-6 > div:first-child > h1.text-3xl {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
/* Page heading */
|
/* Page heading */
|
||||||
.admin-page main > h1:first-child,
|
.admin-page main > h1:first-child,
|
||||||
.admin-page > h1:first-child {
|
.admin-page > h1:first-child {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import { AdminPageShell } from "@/components/admin/admin-page-shell";
|
||||||
|
import { AdminSectionTabs } from "@/components/admin/admin-section-tabs";
|
||||||
|
import { findAdminHub } from "@/lib/admin-nav";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the current path belongs to a hub, wraps children with a shared
|
||||||
|
* title + tab strip. Dashboard and unknown routes render children as-is.
|
||||||
|
*/
|
||||||
|
export function AdminHubChrome({ children }: { children: ReactNode }) {
|
||||||
|
const pathname = usePathname() ?? "";
|
||||||
|
const hub = findAdminHub(pathname);
|
||||||
|
|
||||||
|
if (!hub) return <>{children}</>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AdminPageShell
|
||||||
|
icon={hub.icon}
|
||||||
|
title={hub.title}
|
||||||
|
subtitle={hub.subtitle}
|
||||||
|
tabs={<AdminSectionTabs tabs={hub.tabs} />}
|
||||||
|
className="admin-hub-panel"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AdminPageShell>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,25 +6,33 @@ import type { ReactNode } from "react";
|
|||||||
import { useAdminMobile } from "@/components/admin/admin-mobile-wrapper";
|
import { useAdminMobile } from "@/components/admin/admin-mobile-wrapper";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sidebar link that highlights when its route is active. "/admin" matches
|
* Sidebar link that highlights when its route is active.
|
||||||
* exactly; every other entry also matches its sub-routes (e.g. /admin/radio is
|
* Optional matchPrefixes cover multi-page hubs (e.g. Settings → theme/vpn).
|
||||||
* active on /admin/radio/history) so the current section stays lit.
|
|
||||||
*/
|
*/
|
||||||
export function AdminNavLink({
|
export function AdminNavLink({
|
||||||
href,
|
href,
|
||||||
icon,
|
icon,
|
||||||
|
matchPrefixes,
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
href: string;
|
href: string;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
|
matchPrefixes?: string[];
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const pathname = usePathname() ?? "";
|
const pathname = usePathname() ?? "";
|
||||||
const { close } = useAdminMobile();
|
const { close } = useAdminMobile();
|
||||||
const active =
|
|
||||||
href === "/admin"
|
let active: boolean;
|
||||||
? pathname === "/admin"
|
if (href === "/admin") {
|
||||||
: pathname === href || pathname.startsWith(`${href}/`);
|
active = pathname === "/admin";
|
||||||
|
} else if (matchPrefixes?.length) {
|
||||||
|
active = matchPrefixes.some(
|
||||||
|
(p) => pathname === p || pathname.startsWith(`${p}/`),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
active = pathname === href || pathname.startsWith(`${href}/`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import type { LucideIcon } from "lucide-react";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface AdminPageShellProps {
|
||||||
|
icon?: LucideIcon;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
actions?: ReactNode;
|
||||||
|
tabs?: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Shared admin page chrome: icon title, optional actions/tabs, then body. */
|
||||||
|
export function AdminPageShell({
|
||||||
|
icon: Icon,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
actions,
|
||||||
|
tabs,
|
||||||
|
children,
|
||||||
|
className = "",
|
||||||
|
}: AdminPageShellProps) {
|
||||||
|
return (
|
||||||
|
<div className={`space-y-5 ${className}`.trim()}>
|
||||||
|
<div className="flex flex-wrap items-start justify-between gap-4">
|
||||||
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
|
{Icon ? (
|
||||||
|
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-[var(--admin-accent)]/20 to-[var(--admin-accent)]/5 grid place-items-center shrink-0">
|
||||||
|
<Icon size={20} className="text-[var(--admin-accent)]" />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div className="min-w-0">
|
||||||
|
<h1 className="m-0 text-2xl font-extrabold tracking-tight text-[var(--admin-text)]">
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
{subtitle ? (
|
||||||
|
<p className="m-0 mt-0.5 text-sm text-[var(--admin-text-muted)]">
|
||||||
|
{subtitle}
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{actions ? (
|
||||||
|
<div className="flex flex-wrap items-center gap-2">{actions}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
{tabs}
|
||||||
|
<div className="min-w-0">{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export interface AdminTab {
|
||||||
|
href: string;
|
||||||
|
label: string;
|
||||||
|
/** Extra prefixes that count as active for this tab (detail routes). */
|
||||||
|
match?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchLength(pathname: string, prefix: string): number {
|
||||||
|
if (pathname === prefix) return prefix.length + 1; // prefer exact
|
||||||
|
if (pathname.startsWith(`${prefix}/`)) return prefix.length;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AdminSectionTabs({ tabs }: { tabs: AdminTab[] }) {
|
||||||
|
const pathname = usePathname() ?? "";
|
||||||
|
|
||||||
|
let bestIndex = -1;
|
||||||
|
let bestScore = -1;
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
const prefixes = tab.match ?? [tab.href];
|
||||||
|
for (const prefix of prefixes) {
|
||||||
|
const score = matchLength(pathname, prefix);
|
||||||
|
if (score > bestScore) {
|
||||||
|
bestScore = score;
|
||||||
|
bestIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav
|
||||||
|
className="flex gap-1 overflow-x-auto border-b border-[var(--admin-border)] -mx-1 px-1"
|
||||||
|
aria-label="Section"
|
||||||
|
>
|
||||||
|
{tabs.map((tab, index) => {
|
||||||
|
const active = index === bestIndex;
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={tab.href}
|
||||||
|
href={tab.href}
|
||||||
|
aria-current={active ? "page" : undefined}
|
||||||
|
className={cn(
|
||||||
|
"-mb-px shrink-0 rounded-t-lg border-b-2 px-3.5 py-2.5 text-sm font-semibold no-underline transition-colors",
|
||||||
|
active
|
||||||
|
? "border-[var(--admin-accent)] text-[var(--admin-text)] bg-[var(--admin-accent)]/8"
|
||||||
|
: "border-transparent text-[var(--admin-text-muted)] hover:text-[var(--admin-text)] hover:bg-[var(--admin-accent)]/5",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Обратно към сайта",
|
"backToSite": "Обратно към сайта",
|
||||||
"housekeeping": "Домакинство",
|
"housekeeping": "Домакинство",
|
||||||
"hotelManagementPanel": "Панел за управление на хотел",
|
"hotelManagementPanel": "Панел за управление на хотел",
|
||||||
"rankLabel": "Ранг {rank}"
|
"rankLabel": "Ранг {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Табло за управление",
|
"title": "Табло за управление",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Zpět na stránku",
|
"backToSite": "Zpět na stránku",
|
||||||
"housekeeping": "Úklid",
|
"housekeeping": "Úklid",
|
||||||
"hotelManagementPanel": "Panel správy hotelu",
|
"hotelManagementPanel": "Panel správy hotelu",
|
||||||
"rankLabel": "Hodnost {rank}"
|
"rankLabel": "Hodnost {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Tilbage til webstedet",
|
"backToSite": "Tilbage til webstedet",
|
||||||
"housekeeping": "Husholdning",
|
"housekeeping": "Husholdning",
|
||||||
"hotelManagementPanel": "Hotel management panel",
|
"hotelManagementPanel": "Hotel management panel",
|
||||||
"rankLabel": "Rangering {rank}"
|
"rankLabel": "Rangering {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -719,7 +719,16 @@
|
|||||||
"backToSite": "Zurück zur Website",
|
"backToSite": "Zurück zur Website",
|
||||||
"housekeeping": "Hausverwaltung",
|
"housekeeping": "Hausverwaltung",
|
||||||
"hotelManagementPanel": "Hotel-Verwaltungsbereich",
|
"hotelManagementPanel": "Hotel-Verwaltungsbereich",
|
||||||
"rankLabel": "Rang {rank}"
|
"rankLabel": "Rang {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Επιστροφή στον ιστότοπο",
|
"backToSite": "Επιστροφή στον ιστότοπο",
|
||||||
"housekeeping": "Οικονομία",
|
"housekeeping": "Οικονομία",
|
||||||
"hotelManagementPanel": "Πάνελ διαχείρισης ξενοδοχείου",
|
"hotelManagementPanel": "Πάνελ διαχείρισης ξενοδοχείου",
|
||||||
"rankLabel": "Κατάταξη {rank}"
|
"rankLabel": "Κατάταξη {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Ταμπλό",
|
"title": "Ταμπλό",
|
||||||
|
|||||||
@@ -690,6 +690,9 @@
|
|||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Dashboard",
|
||||||
"content": "Content",
|
"content": "Content",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
"articles": "Articles",
|
"articles": "Articles",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"navigator": "Navigator",
|
"navigator": "Navigator",
|
||||||
@@ -703,6 +706,8 @@
|
|||||||
"banners": "Banners",
|
"banners": "Banners",
|
||||||
"prefixes": "Prefixes",
|
"prefixes": "Prefixes",
|
||||||
"usersAndAccess": "Users & access",
|
"usersAndAccess": "Users & access",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
"bans": "Bans",
|
"bans": "Bans",
|
||||||
"ipManagement": "IP management",
|
"ipManagement": "IP management",
|
||||||
@@ -713,6 +718,8 @@
|
|||||||
"onlineUsers": "Online users",
|
"onlineUsers": "Online users",
|
||||||
"moderation": "Moderation",
|
"moderation": "Moderation",
|
||||||
"economy": "Economy",
|
"economy": "Economy",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
"catalog": "Catalog",
|
"catalog": "Catalog",
|
||||||
"shop": "Shop",
|
"shop": "Shop",
|
||||||
"transactions": "Transactions",
|
"transactions": "Transactions",
|
||||||
@@ -734,6 +741,8 @@
|
|||||||
"radioRanks": "Ranks",
|
"radioRanks": "Ranks",
|
||||||
"radioAutodj": "Auto DJ",
|
"radioAutodj": "Auto DJ",
|
||||||
"system": "System",
|
"system": "System",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability",
|
||||||
"commandocentrum": "Commandocentrum",
|
"commandocentrum": "Commandocentrum",
|
||||||
"emulator": "Emulator",
|
"emulator": "Emulator",
|
||||||
"alerts": "Alerts",
|
"alerts": "Alerts",
|
||||||
|
|||||||
+10
-1
@@ -719,7 +719,16 @@
|
|||||||
"backToSite": "Volver al sitio",
|
"backToSite": "Volver al sitio",
|
||||||
"housekeeping": "Housekeeping",
|
"housekeeping": "Housekeeping",
|
||||||
"hotelManagementPanel": "Panel de gestión del hotel",
|
"hotelManagementPanel": "Panel de gestión del hotel",
|
||||||
"rankLabel": "Rango {rank}"
|
"rankLabel": "Rango {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Panel",
|
"title": "Panel",
|
||||||
|
|||||||
+10
-1
@@ -719,7 +719,16 @@
|
|||||||
"backToSite": "Retour au site",
|
"backToSite": "Retour au site",
|
||||||
"housekeeping": "Gouvernance",
|
"housekeeping": "Gouvernance",
|
||||||
"hotelManagementPanel": "Panneau de gestion de l'hôtel",
|
"hotelManagementPanel": "Panneau de gestion de l'hôtel",
|
||||||
"rankLabel": "Rang {rank}"
|
"rankLabel": "Rang {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Tableau de bord",
|
"title": "Tableau de bord",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Povratak na stranicu",
|
"backToSite": "Povratak na stranicu",
|
||||||
"housekeeping": "Domaćinstvo",
|
"housekeeping": "Domaćinstvo",
|
||||||
"hotelManagementPanel": "Upravljačka ploča hotela",
|
"hotelManagementPanel": "Upravljačka ploča hotela",
|
||||||
"rankLabel": "Rang {rank}"
|
"rankLabel": "Rang {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Nadzorna ploča",
|
"title": "Nadzorna ploča",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Vissza a webhelyre",
|
"backToSite": "Vissza a webhelyre",
|
||||||
"housekeeping": "Takarítás",
|
"housekeeping": "Takarítás",
|
||||||
"hotelManagementPanel": "Hotel menedzsment panel",
|
"hotelManagementPanel": "Hotel menedzsment panel",
|
||||||
"rankLabel": "rang {rank}"
|
"rankLabel": "rang {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Irányítópult",
|
"title": "Irányítópult",
|
||||||
|
|||||||
+10
-1
@@ -719,7 +719,16 @@
|
|||||||
"settings": "Impostazioni",
|
"settings": "Impostazioni",
|
||||||
"backToSite": "Torna al sito",
|
"backToSite": "Torna al sito",
|
||||||
"hotelManagementPanel": "Pannello di gestione hotel",
|
"hotelManagementPanel": "Pannello di gestione hotel",
|
||||||
"rankLabel": "Grado {rank}"
|
"rankLabel": "Grado {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Terug naar site",
|
"backToSite": "Terug naar site",
|
||||||
"housekeeping": "Housekeeping",
|
"housekeeping": "Housekeeping",
|
||||||
"hotelManagementPanel": "Hotelbeheerpaneel",
|
"hotelManagementPanel": "Hotelbeheerpaneel",
|
||||||
"rankLabel": "Rang {rank}"
|
"rankLabel": "Rang {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Tilbake til nettstedet",
|
"backToSite": "Tilbake til nettstedet",
|
||||||
"housekeeping": "Rengjøring",
|
"housekeeping": "Rengjøring",
|
||||||
"hotelManagementPanel": "Hotellstyringspanel",
|
"hotelManagementPanel": "Hotellstyringspanel",
|
||||||
"rankLabel": "Rangering {rank}"
|
"rankLabel": "Rangering {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashbord",
|
"title": "Dashbord",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Powrót do serwisu",
|
"backToSite": "Powrót do serwisu",
|
||||||
"housekeeping": "Sprzątanie",
|
"housekeeping": "Sprzątanie",
|
||||||
"hotelManagementPanel": "Panel zarządzania hotelem",
|
"hotelManagementPanel": "Panel zarządzania hotelem",
|
||||||
"rankLabel": "Ranga {rank}"
|
"rankLabel": "Ranga {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Pulpit nawigacyjny",
|
"title": "Pulpit nawigacyjny",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Voltar ao site",
|
"backToSite": "Voltar ao site",
|
||||||
"housekeeping": "Limpeza",
|
"housekeeping": "Limpeza",
|
||||||
"hotelManagementPanel": "Painel de gestão hoteleira",
|
"hotelManagementPanel": "Painel de gestão hoteleira",
|
||||||
"rankLabel": "Classificação {rank}"
|
"rankLabel": "Classificação {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Painel",
|
"title": "Painel",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Înapoi la site",
|
"backToSite": "Înapoi la site",
|
||||||
"housekeeping": "Menaj",
|
"housekeeping": "Menaj",
|
||||||
"hotelManagementPanel": "Panoul de management al hotelului",
|
"hotelManagementPanel": "Panoul de management al hotelului",
|
||||||
"rankLabel": "Clasament {rank}"
|
"rankLabel": "Clasament {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Tabloul de bord",
|
"title": "Tabloul de bord",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Вернуться на сайт",
|
"backToSite": "Вернуться на сайт",
|
||||||
"housekeeping": "Ведение домашнего хозяйства",
|
"housekeeping": "Ведение домашнего хозяйства",
|
||||||
"hotelManagementPanel": "Панель управления отелем",
|
"hotelManagementPanel": "Панель управления отелем",
|
||||||
"rankLabel": "Ранг {rank}"
|
"rankLabel": "Ранг {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Панель управления",
|
"title": "Панель управления",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Späť na stránku",
|
"backToSite": "Späť na stránku",
|
||||||
"housekeeping": "Upratovanie",
|
"housekeeping": "Upratovanie",
|
||||||
"hotelManagementPanel": "Panel riadenia hotela",
|
"hotelManagementPanel": "Panel riadenia hotela",
|
||||||
"rankLabel": "Hodnotenie {rank}"
|
"rankLabel": "Hodnotenie {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Назад на сајт",
|
"backToSite": "Назад на сајт",
|
||||||
"housekeeping": "Домаћинство",
|
"housekeeping": "Домаћинство",
|
||||||
"hotelManagementPanel": "Панел за управљање хотелом",
|
"hotelManagementPanel": "Панел за управљање хотелом",
|
||||||
"rankLabel": "Ранг {rank}"
|
"rankLabel": "Ранг {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Дасхбоард",
|
"title": "Дасхбоард",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Tillbaka till webbplatsen",
|
"backToSite": "Tillbaka till webbplatsen",
|
||||||
"housekeeping": "Städning",
|
"housekeeping": "Städning",
|
||||||
"hotelManagementPanel": "Hotellledningspanel",
|
"hotelManagementPanel": "Hotellledningspanel",
|
||||||
"rankLabel": "Rank {rank}"
|
"rankLabel": "Rank {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Instrumentbräda",
|
"title": "Instrumentbräda",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Siteye geri dön",
|
"backToSite": "Siteye geri dön",
|
||||||
"housekeeping": "Temizlik",
|
"housekeeping": "Temizlik",
|
||||||
"hotelManagementPanel": "Otel yönetim paneli",
|
"hotelManagementPanel": "Otel yönetim paneli",
|
||||||
"rankLabel": "Sıra {rank}"
|
"rankLabel": "Sıra {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Kontrol Paneli",
|
"title": "Kontrol Paneli",
|
||||||
|
|||||||
+10
-1
@@ -755,7 +755,16 @@
|
|||||||
"backToSite": "Повернутися на сайт",
|
"backToSite": "Повернутися на сайт",
|
||||||
"housekeeping": "Прибирання",
|
"housekeeping": "Прибирання",
|
||||||
"hotelManagementPanel": "Панель управління готелем",
|
"hotelManagementPanel": "Панель управління готелем",
|
||||||
"rankLabel": "Рейтинг {rank}"
|
"rankLabel": "Рейтинг {rank}",
|
||||||
|
"hubNewsMedia": "News & media",
|
||||||
|
"hubSiteContent": "Site content",
|
||||||
|
"hubEngagement": "Engagement",
|
||||||
|
"hubUsers": "Users",
|
||||||
|
"hubAccess": "Access & security",
|
||||||
|
"hubCatalog": "Catalog & rares",
|
||||||
|
"hubShop": "Shop & payments",
|
||||||
|
"hubTools": "Tools",
|
||||||
|
"hubObservability": "Observability"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Приладова панель",
|
"title": "Приладова панель",
|
||||||
|
|||||||
Reference in new issue
Block a user