Standardize NodeDC UI components

This commit is contained in:
DCCONSTRUCTIONS
2026-05-02 10:56:43 +03:00
parent c99c91c826
commit 69eb5260b0
22 changed files with 1955 additions and 550 deletions
+58 -42
View File
@@ -1,5 +1,4 @@
import { useEffect, useMemo, useState } from "react";
import type { ServiceAccessException, ServiceGrant } from "../entities/access/types";
import type { Client } from "../entities/client/types";
import type { Invite } from "../entities/invite/types";
import type { LauncherServiceView, Service } from "../entities/service/types";
@@ -13,7 +12,7 @@ import {
type LauncherData,
} from "../shared/api/mockApi";
import { loadPersistedLauncherData, persistLauncherData } from "../shared/api/storageApi";
import { AdminOverlay } from "../widgets/admin-overlay/AdminOverlay";
import { AdminOverlay, type SetUserServiceAccessCommand } from "../widgets/admin-overlay/AdminOverlay";
import { ServiceRail } from "../widgets/service-rail/ServiceRail";
import { ServiceStage } from "../widgets/service-stage/ServiceStage";
import { TopBar } from "../widgets/top-bar/TopBar";
@@ -111,45 +110,64 @@ export function LauncherApp() {
});
}
function handleCreateGrant(grant: Omit<ServiceGrant, "id" | "status" | "createdAt" | "updatedAt">) {
setData((current) => ({
...current,
grants: [
...current.grants,
{
...grant,
id: `grant_mock_${Date.now()}`,
status: "active",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
],
}));
}
function handleSetUserServiceAccess({ userId, serviceId, value }: SetUserServiceAccessCommand) {
setData((current) => {
const now = new Date().toISOString();
const directGrant = current.grants.find(
(grant) => grant.serviceId === serviceId && grant.targetType === "user" && grant.targetId === userId
);
const grantsWithoutDirect = current.grants.filter(
(grant) => !(grant.serviceId === serviceId && grant.targetType === "user" && grant.targetId === userId)
);
const exceptionsWithoutDirect = current.exceptions.filter(
(exception) => !(exception.serviceId === serviceId && exception.userId === userId)
);
function handleCreateDenyException(exception: Omit<ServiceAccessException, "id" | "type" | "createdAt" | "updatedAt">) {
setData((current) => ({
...current,
exceptions: [
...current.exceptions.filter(
(item) => !(item.serviceId === exception.serviceId && item.userId === exception.userId && item.type === "deny")
),
{
...exception,
id: `exception_mock_${Date.now()}`,
type: "deny",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
],
}));
}
if (value === "unset") {
return {
...current,
grants: grantsWithoutDirect,
exceptions: exceptionsWithoutDirect,
};
}
function handleRemoveException(exceptionId: string) {
setData((current) => ({
...current,
exceptions: current.exceptions.filter((exception) => exception.id !== exceptionId),
}));
if (value === "deny") {
return {
...current,
grants: grantsWithoutDirect,
exceptions: [
...exceptionsWithoutDirect,
{
id: `exception_mock_${Date.now()}`,
serviceId,
userId,
type: "deny",
reason: "Создано из матрицы доступа.",
createdAt: now,
updatedAt: now,
},
],
};
}
return {
...current,
grants: [
...grantsWithoutDirect,
{
id: directGrant?.id ?? `grant_mock_${Date.now()}`,
serviceId,
targetType: "user",
targetId: userId,
appRole: value,
status: "active",
createdAt: directGrant?.createdAt ?? now,
updatedAt: now,
},
],
exceptions: exceptionsWithoutDirect,
};
});
}
function handleCreateInvite(invite: Pick<Invite, "clientId" | "email" | "role">) {
@@ -422,9 +440,7 @@ export function LauncherApp() {
me={me}
activeClientId={resolvedClientId}
onClose={() => setAdminOpen(false)}
onCreateGrant={handleCreateGrant}
onCreateDenyException={handleCreateDenyException}
onRemoveException={handleRemoveException}
onSetUserServiceAccess={handleSetUserServiceAccess}
onCreateInvite={handleCreateInvite}
onUpdateInvite={handleUpdateInvite}
onRetrySync={handleRetrySync}