feat: scope workspace routes by organization slug
This commit is contained in:
5
app/(app)/app/[organizationSlug]/alerts/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/alerts/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import AlertsPage from "../../alerts/page";
|
||||
|
||||
export default function ScopedAlertsPage(): React.ReactElement {
|
||||
return AlertsPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/beds/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/beds/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import BedsPage from "../../beds/page";
|
||||
|
||||
export default async function ScopedBedsPage(): Promise<React.ReactElement> {
|
||||
return BedsPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/care/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/care/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import CarePage from "../../care/page";
|
||||
|
||||
export default function ScopedCarePage(): React.ReactElement {
|
||||
return CarePage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/dashboard/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/dashboard/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DashboardPage from "../../dashboard/page";
|
||||
|
||||
export default async function ScopedDashboardPage(): Promise<React.ReactElement> {
|
||||
return DashboardPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/devices/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/devices/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DevicesPage from "../../devices/page";
|
||||
|
||||
export default function ScopedDevicesPage(): React.ReactElement {
|
||||
return DevicesPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/elders/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/elders/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import EldersPage from "../../elders/page";
|
||||
|
||||
export default async function ScopedEldersPage(): Promise<React.ReactElement> {
|
||||
return EldersPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/emergency/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/emergency/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import EmergencyPage from "../../emergency/page";
|
||||
|
||||
export default function ScopedEmergencyPage(): React.ReactElement {
|
||||
return EmergencyPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/family/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/family/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import FamilyPage from "../../family/page";
|
||||
|
||||
export default function ScopedFamilyPage(): React.ReactElement {
|
||||
return FamilyPage();
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/health/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/health/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import HealthPage from "../../health/page";
|
||||
|
||||
export default function ScopedHealthPage(): React.ReactElement {
|
||||
return HealthPage();
|
||||
}
|
||||
28
app/(app)/app/[organizationSlug]/layout.tsx
Normal file
28
app/(app)/app/[organizationSlug]/layout.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type OrganizationWorkspaceLayoutProps = {
|
||||
children: React.ReactNode;
|
||||
params: Promise<{
|
||||
organizationSlug: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
export default async function OrganizationWorkspaceLayout({
|
||||
children,
|
||||
params,
|
||||
}: OrganizationWorkspaceLayoutProps): Promise<React.ReactElement> {
|
||||
const [{ organizationSlug }, context] = await Promise.all([params, getCurrentAuthContext()]);
|
||||
if (!context) {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const activeSlug = context.organization?.slug;
|
||||
if (activeSlug && activeSlug !== organizationSlug) {
|
||||
redirect(getWorkspaceHref(activeSlug, "/dashboard"));
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/notices/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/notices/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import NoticesPage from "../../notices/page";
|
||||
|
||||
export default function ScopedNoticesPage(): React.ReactElement {
|
||||
return NoticesPage();
|
||||
}
|
||||
14
app/(app)/app/[organizationSlug]/page.tsx
Normal file
14
app/(app)/app/[organizationSlug]/page.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type ScopedAppIndexPageProps = {
|
||||
params: Promise<{
|
||||
organizationSlug: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
export default async function ScopedAppIndexPage({ params }: ScopedAppIndexPageProps): Promise<never> {
|
||||
const { organizationSlug } = await params;
|
||||
redirect(getWorkspaceHref(organizationSlug, "/dashboard"));
|
||||
}
|
||||
10
app/(app)/app/[organizationSlug]/settings/audit/page.tsx
Normal file
10
app/(app)/app/[organizationSlug]/settings/audit/page.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import AuditPage from "../../../settings/audit/page";
|
||||
import type { SearchParams } from "@/modules/settings/lib/pagination";
|
||||
|
||||
type ScopedAuditPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function ScopedAuditPage({ searchParams }: ScopedAuditPageProps): Promise<React.ReactElement> {
|
||||
return AuditPage({ searchParams });
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import GlobalSettingsPage from "../../../settings/global/page";
|
||||
|
||||
export default async function ScopedGlobalSettingsPage(): Promise<React.ReactElement> {
|
||||
return GlobalSettingsPage();
|
||||
}
|
||||
9
app/(app)/app/[organizationSlug]/settings/layout.tsx
Normal file
9
app/(app)/app/[organizationSlug]/settings/layout.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import SettingsLayout from "../../settings/layout";
|
||||
|
||||
type ScopedSettingsLayoutProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function ScopedSettingsLayout({ children }: ScopedSettingsLayoutProps): React.ReactElement {
|
||||
return <SettingsLayout>{children}</SettingsLayout>;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import OrganizationDetailPage from "../../../../settings/organizations/[id]/page";
|
||||
|
||||
type ScopedOrganizationDetailPageProps = {
|
||||
params: Promise<{
|
||||
organizationSlug: string;
|
||||
id: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
export default async function ScopedOrganizationDetailPage({
|
||||
params,
|
||||
}: ScopedOrganizationDetailPageProps): Promise<React.ReactElement> {
|
||||
const { id } = await params;
|
||||
return OrganizationDetailPage({ params: Promise.resolve({ id }) });
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import OrganizationsPage from "../../../settings/organizations/page";
|
||||
import type { SearchParams } from "@/modules/settings/lib/pagination";
|
||||
|
||||
type ScopedOrganizationsPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function ScopedOrganizationsPage({
|
||||
searchParams,
|
||||
}: ScopedOrganizationsPageProps): Promise<React.ReactElement> {
|
||||
return OrganizationsPage({ searchParams });
|
||||
}
|
||||
5
app/(app)/app/[organizationSlug]/settings/page.tsx
Normal file
5
app/(app)/app/[organizationSlug]/settings/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import SettingsPage from "../../settings/page";
|
||||
|
||||
export default async function ScopedSettingsPage(): Promise<React.ReactElement> {
|
||||
return SettingsPage();
|
||||
}
|
||||
10
app/(app)/app/[organizationSlug]/settings/roles/page.tsx
Normal file
10
app/(app)/app/[organizationSlug]/settings/roles/page.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import RolesPage from "../../../settings/roles/page";
|
||||
import type { SearchParams } from "@/modules/settings/lib/pagination";
|
||||
|
||||
type ScopedRolesPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function ScopedRolesPage({ searchParams }: ScopedRolesPageProps): Promise<React.ReactElement> {
|
||||
return RolesPage({ searchParams });
|
||||
}
|
||||
10
app/(app)/app/[organizationSlug]/settings/status/page.tsx
Normal file
10
app/(app)/app/[organizationSlug]/settings/status/page.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import StatusPage from "../../../settings/status/page";
|
||||
import type { SearchParams } from "@/modules/settings/lib/pagination";
|
||||
|
||||
type ScopedStatusPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function ScopedStatusPage({ searchParams }: ScopedStatusPageProps): Promise<React.ReactElement> {
|
||||
return StatusPage({ searchParams });
|
||||
}
|
||||
10
app/(app)/app/[organizationSlug]/settings/users/page.tsx
Normal file
10
app/(app)/app/[organizationSlug]/settings/users/page.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import UsersPage from "../../../settings/users/page";
|
||||
import type { SearchParams } from "@/modules/settings/lib/pagination";
|
||||
|
||||
type ScopedUsersPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function ScopedUsersPage({ searchParams }: ScopedUsersPageProps): Promise<React.ReactElement> {
|
||||
return UsersPage({ searchParams });
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "@/modules/core/server/operations";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import { BedsWorkspace } from "@/modules/facilities/components/BedsWorkspace";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
export default async function BedsPage(): Promise<React.ReactElement> {
|
||||
const context = await getCurrentAuthContext();
|
||||
@@ -17,7 +18,7 @@ export default async function BedsPage(): Promise<React.ReactElement> {
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "facility:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const organizationId = context.organization?.id;
|
||||
|
||||
@@ -7,10 +7,13 @@ import {
|
||||
listOperationalElders,
|
||||
listOperationalIncidents,
|
||||
} from "@/modules/core/server/operations";
|
||||
import type { BedStatus } from "@/modules/core/types";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import type { BedStatus, Permission } from "@/modules/core/types";
|
||||
import { DashboardHome, type DashboardMetric } from "@/modules/dashboard/components/DashboardHome";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
const BED_STATUSES: BedStatus[] = ["available", "occupied", "maintenance", "disabled"];
|
||||
const DASHBOARD_PERMISSIONS: Permission[] = ["elder:read", "facility:read", "admission:read", "incident:read"];
|
||||
|
||||
export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
const context = await getCurrentAuthContext();
|
||||
@@ -19,6 +22,11 @@ export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
}
|
||||
|
||||
const organizationId = context.organization?.id;
|
||||
const canViewDashboard = DASHBOARD_PERMISSIONS.some((permission) => hasPermission(context.permissions, permission));
|
||||
if (!canViewDashboard) {
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/family"));
|
||||
}
|
||||
|
||||
const [elders, beds, admissions, incidents] = await Promise.all([
|
||||
listOperationalElders(organizationId),
|
||||
listOperationalBeds(organizationId),
|
||||
|
||||
@@ -2,7 +2,9 @@ import { redirect } from "next/navigation";
|
||||
|
||||
import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { listOperationalElders } from "@/modules/core/server/operations";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import { EldersClient } from "@/modules/elders/components/EldersClient";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
export default async function EldersPage(): Promise<React.ReactElement> {
|
||||
const context = await getCurrentAuthContext();
|
||||
@@ -10,6 +12,10 @@ export default async function EldersPage(): Promise<React.ReactElement> {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "elder:read")) {
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const elders = await listOperationalElders(context.organization?.id);
|
||||
|
||||
return <EldersClient initialElders={elders} permissions={context.permissions} />;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function AppIndexPage(): never {
|
||||
redirect("/app/dashboard");
|
||||
import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
export default async function AppIndexPage(): Promise<never> {
|
||||
const context = await getCurrentAuthContext();
|
||||
redirect(getWorkspaceHref(context?.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import { TablePagination, TableToolbar } from "@/modules/settings/components/TableToolbar";
|
||||
import { getPage, getPageCount, getSearchParam, paginate, type SearchParams } from "@/modules/settings/lib/pagination";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type AuditPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
@@ -19,9 +20,10 @@ export default async function AuditPage({ searchParams }: AuditPageProps): Promi
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "audit:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const pagePath = getWorkspaceHref(context.organization?.slug, "/settings/audit");
|
||||
const params = (await searchParams) ?? {};
|
||||
const query = getSearchParam(params, "q");
|
||||
const page = getPage(params);
|
||||
@@ -47,7 +49,7 @@ export default async function AuditPage({ searchParams }: AuditPageProps): Promi
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<TableToolbar
|
||||
pathname="/app/settings/audit"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
searchPlaceholder="搜索操作者、动作、对象、结果"
|
||||
total={filteredLogs.length}
|
||||
@@ -91,7 +93,7 @@ export default async function AuditPage({ searchParams }: AuditPageProps): Promi
|
||||
<TablePagination
|
||||
page={Math.min(page, pageCount)}
|
||||
pageCount={pageCount}
|
||||
pathname="/app/settings/audit"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
total={filteredLogs.length}
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import { getSystemSettings } from "@/modules/core/server/system-settings";
|
||||
import { GlobalSettingsClient } from "@/modules/settings/components/GlobalSettingsClient";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
export default async function GlobalSettingsPage(): Promise<React.ReactElement> {
|
||||
const context = await getCurrentAuthContext();
|
||||
@@ -12,7 +13,7 @@ export default async function GlobalSettingsPage(): Promise<React.ReactElement>
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "platform:manage")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const settings = await getSystemSettings();
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
listSettingsOrganizations,
|
||||
} from "@/modules/core/server/settings";
|
||||
import { OrganizationDetailClient } from "@/modules/settings/components/OrganizationDetailClient";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type OrganizationDetailPageProps = {
|
||||
params: Promise<{
|
||||
@@ -31,7 +32,7 @@ export default async function OrganizationDetailPage({
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "organization:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
@@ -42,7 +43,7 @@ export default async function OrganizationDetailPage({
|
||||
}
|
||||
|
||||
if (!context.account.platformRoleId && context.organization?.id && context.organization.id !== organization.id) {
|
||||
redirect("/app/settings/organizations");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/settings/organizations"));
|
||||
}
|
||||
|
||||
const [roles, organizationMemberships, organizationAccounts, invitations, joinRequests] = await Promise.all([
|
||||
@@ -72,7 +73,7 @@ export default async function OrganizationDetailPage({
|
||||
<div className="flex flex-col gap-5">
|
||||
<section className="flex flex-col gap-4 border-b pb-5 lg:flex-row lg:items-end lg:justify-between">
|
||||
<div>
|
||||
<LinkButton href="/app/settings/organizations" size="sm" variant="outline">
|
||||
<LinkButton href={getWorkspaceHref(context.organization?.slug, "/settings/organizations")} size="sm" variant="outline">
|
||||
<ArrowLeft className="size-4" aria-hidden="true" />
|
||||
返回机构列表
|
||||
</LinkButton>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/modules/settings/components/OrganizationManagementClient";
|
||||
import { TablePagination, TableToolbar } from "@/modules/settings/components/TableToolbar";
|
||||
import { getPage, getPageCount, getSearchParam, paginate, type SearchParams } from "@/modules/settings/lib/pagination";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type OrganizationsPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
@@ -24,9 +25,10 @@ export default async function OrganizationsPage({ searchParams }: OrganizationsP
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "organization:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const pagePath = getWorkspaceHref(context.organization?.slug, "/settings/organizations");
|
||||
const params = (await searchParams) ?? {};
|
||||
const query = getSearchParam(params, "q");
|
||||
const page = getPage(params);
|
||||
@@ -64,7 +66,7 @@ export default async function OrganizationsPage({ searchParams }: OrganizationsP
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<TableToolbar
|
||||
pathname="/app/settings/organizations"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
searchPlaceholder="搜索机构名称、标识、状态"
|
||||
total={filteredOrganizations.length}
|
||||
@@ -86,7 +88,7 @@ export default async function OrganizationsPage({ searchParams }: OrganizationsP
|
||||
<Table.Cell className="px-4 py-3">
|
||||
<Link
|
||||
className="font-medium text-primary underline-offset-4 hover:underline"
|
||||
href={`/app/settings/organizations/${organization.id}`}
|
||||
href={getWorkspaceHref(context.organization?.slug, `/settings/organizations/${organization.id}`)}
|
||||
>
|
||||
{organization.name}
|
||||
</Link>
|
||||
@@ -118,7 +120,7 @@ export default async function OrganizationsPage({ searchParams }: OrganizationsP
|
||||
<TablePagination
|
||||
page={Math.min(page, pageCount)}
|
||||
pageCount={pageCount}
|
||||
pathname="/app/settings/organizations"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
total={filteredOrganizations.length}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { getCurrentAuthContext } from "@/modules/core/server/auth";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
export default async function SettingsPage(): Promise<React.ReactElement> {
|
||||
redirect("/app/settings/users");
|
||||
const context = await getCurrentAuthContext();
|
||||
redirect(getWorkspaceHref(context?.organization?.slug, "/settings/users"));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getRoleDefinitions, hasPermission, PERMISSION_DEFINITIONS } from "@/mod
|
||||
import { RoleManagementClient, RoleRowActions } from "@/modules/settings/components/RoleManagementClient";
|
||||
import { TablePagination, TableToolbar } from "@/modules/settings/components/TableToolbar";
|
||||
import { getPage, getPageCount, getSearchParam, paginate, type SearchParams } from "@/modules/settings/lib/pagination";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type RolesPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
@@ -19,9 +20,10 @@ export default async function RolesPage({ searchParams }: RolesPageProps): Promi
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "role:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const pagePath = getWorkspaceHref(context.organization?.slug, "/settings/roles");
|
||||
const params = (await searchParams) ?? {};
|
||||
const query = getSearchParam(params, "q");
|
||||
const page = getPage(params);
|
||||
@@ -48,7 +50,7 @@ export default async function RolesPage({ searchParams }: RolesPageProps): Promi
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<TableToolbar
|
||||
pathname="/app/settings/roles"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
searchPlaceholder="搜索角色、权限、说明"
|
||||
total={filteredRoles.length}
|
||||
@@ -94,7 +96,7 @@ export default async function RolesPage({ searchParams }: RolesPageProps): Promi
|
||||
<TablePagination
|
||||
page={Math.min(page, pageCount)}
|
||||
pageCount={pageCount}
|
||||
pathname="/app/settings/roles"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
total={filteredRoles.length}
|
||||
/>
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
import { IncidentStatusActions } from "@/modules/settings/components/IncidentStatusActions";
|
||||
import { TablePagination, TableToolbar } from "@/modules/settings/components/TableToolbar";
|
||||
import { getPage, getPageCount, getSearchParam, paginate, type SearchParams } from "@/modules/settings/lib/pagination";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type StatusPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
@@ -27,9 +28,10 @@ export default async function StatusPage({ searchParams }: StatusPageProps): Pro
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "incident:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const pagePath = getWorkspaceHref(context.organization?.slug, "/settings/status");
|
||||
const params = (await searchParams) ?? {};
|
||||
const query = getSearchParam(params, "q");
|
||||
const page = getPage(params);
|
||||
@@ -93,7 +95,7 @@ export default async function StatusPage({ searchParams }: StatusPageProps): Pro
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<TableToolbar
|
||||
pathname="/app/settings/status"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
searchPlaceholder="搜索故障标题、来源、状态"
|
||||
total={filteredIncidents.length}
|
||||
@@ -145,7 +147,7 @@ export default async function StatusPage({ searchParams }: StatusPageProps): Pro
|
||||
<TablePagination
|
||||
page={Math.min(page, pageCount)}
|
||||
pageCount={pageCount}
|
||||
pathname="/app/settings/status"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
total={filteredIncidents.length}
|
||||
/>
|
||||
|
||||
@@ -17,6 +17,7 @@ import { TablePagination, TableToolbar } from "@/modules/settings/components/Tab
|
||||
import { UserAccountActions, UserManagementClient } from "@/modules/settings/components/UserManagementClient";
|
||||
import { getPage, getPageCount, getSearchParam, paginate, type SearchParams } from "@/modules/settings/lib/pagination";
|
||||
import { UserAvatar } from "@/modules/shared/components/UserAvatar";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
type UsersPageProps = {
|
||||
searchParams?: Promise<SearchParams>;
|
||||
@@ -37,9 +38,10 @@ export default async function UsersPage({ searchParams }: UsersPageProps): Promi
|
||||
}
|
||||
|
||||
if (!hasPermission(context.permissions, "account:read")) {
|
||||
redirect("/app/dashboard");
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/dashboard"));
|
||||
}
|
||||
|
||||
const pagePath = getWorkspaceHref(context.organization?.slug, "/settings/users");
|
||||
const params = (await searchParams) ?? {};
|
||||
const query = getSearchParam(params, "q");
|
||||
const page = getPage(params);
|
||||
@@ -90,7 +92,7 @@ export default async function UsersPage({ searchParams }: UsersPageProps): Promi
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<TableToolbar
|
||||
pathname="/app/settings/users"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
searchPlaceholder="搜索姓名、邮箱、角色、状态"
|
||||
total={filteredAccounts.length}
|
||||
@@ -152,7 +154,7 @@ export default async function UsersPage({ searchParams }: UsersPageProps): Promi
|
||||
<TablePagination
|
||||
page={Math.min(page, pageCount)}
|
||||
pageCount={pageCount}
|
||||
pathname="/app/settings/users"
|
||||
pathname={pagePath}
|
||||
query={query}
|
||||
total={filteredAccounts.length}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user