7b86fd1f09
- Added aiAgentWorkflowBindingRepository for managing workflow bindings associated with AI agents. - Enhanced agentRevisionService to include workflow bindings in agent revisions. - Updated aIAgentService to handle workflow bindings during agent creation and updates. - Introduced ai_agent_workflow_binding_service for managing workflow binding logic. - Created new API endpoints for fetching, creating, updating, and deleting AI workflows. - Developed a new dashboard page for managing AI workflows. - Updated frontend components to support workflow binding management in agent configuration. - Added necessary tests for workflow binding functionality and updated existing tests for compatibility. - Translated relevant UI texts and messages for workflow management.
314 lines
8.0 KiB
TypeScript
314 lines
8.0 KiB
TypeScript
import {
|
|
BotMessageSquareIcon,
|
|
BrainCircuitIcon,
|
|
Building2Icon,
|
|
CalendarClockIcon,
|
|
FileTextIcon,
|
|
GlobeIcon,
|
|
KeyRoundIcon,
|
|
LayoutDashboardIcon,
|
|
MessageSquareCodeIcon,
|
|
MessageSquareMoreIcon,
|
|
ShieldCheckIcon,
|
|
TagsIcon,
|
|
UserCogIcon,
|
|
UsersIcon,
|
|
WorkflowIcon,
|
|
} from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
|
|
/** Keep in sync with backend internal/pkg/constants/auth.go RoleCodeSuperAdmin. */
|
|
export const DASHBOARD_ROLE_SUPER_ADMIN = "super_admin";
|
|
|
|
export type DashboardNavMenuItem = {
|
|
title: string;
|
|
titleKey: string;
|
|
url: string;
|
|
icon: ReactNode;
|
|
};
|
|
|
|
export type DashboardNavItemConfig = Omit<DashboardNavMenuItem, "title"> & {
|
|
/**
|
|
* Keep in sync with backend Permission.Code. Missing value means any signed-in
|
|
* admin can see the module.
|
|
*/
|
|
requiredPermission?: string;
|
|
};
|
|
|
|
export type DashboardNavSectionConfig = {
|
|
titleKey: string;
|
|
icon: ReactNode;
|
|
items: DashboardNavItemConfig[];
|
|
};
|
|
|
|
function navItemVisible(
|
|
item: DashboardNavItemConfig,
|
|
superAdmin: boolean,
|
|
permissionSet: Set<string>,
|
|
): boolean {
|
|
if (superAdmin) {
|
|
return true;
|
|
}
|
|
if (!item.requiredPermission) {
|
|
return true;
|
|
}
|
|
return permissionSet.has(item.requiredPermission);
|
|
}
|
|
|
|
export function filterDashboardNavForSession(
|
|
permissions: readonly string[] | undefined,
|
|
roles: readonly string[] | undefined,
|
|
): { titleKey: string; icon: ReactNode; items: DashboardNavMenuItem[] }[] {
|
|
const superAdmin = roles?.includes(DASHBOARD_ROLE_SUPER_ADMIN) ?? false;
|
|
const permissionSet = new Set(permissions ?? []);
|
|
return dashboardNavSections
|
|
.map((section) => ({
|
|
titleKey: section.titleKey,
|
|
icon: section.icon,
|
|
items: section.items
|
|
.filter((item) => navItemVisible(item, superAdmin, permissionSet))
|
|
.map(({ titleKey, url, icon }) => ({ title: titleKey, titleKey, url, icon })),
|
|
}))
|
|
.filter((section) => section.items.length > 0);
|
|
}
|
|
|
|
export function filterDashboardSecondaryNavForSession(
|
|
permissions: readonly string[] | undefined,
|
|
roles: readonly string[] | undefined,
|
|
): DashboardNavMenuItem[] {
|
|
const superAdmin = roles?.includes(DASHBOARD_ROLE_SUPER_ADMIN) ?? false;
|
|
const permissionSet = new Set(permissions ?? []);
|
|
return dashboardSecondaryNav
|
|
.filter((item) => navItemVisible(item, superAdmin, permissionSet))
|
|
.map(({ titleKey, url, icon }) => ({ title: titleKey, titleKey, url, icon }));
|
|
}
|
|
|
|
export const dashboardNavSections: DashboardNavSectionConfig[] = [
|
|
// {
|
|
// title: "Overview",
|
|
// items: [
|
|
// {
|
|
// title: "Overview",
|
|
// url: "/",
|
|
// icon: <LayoutDashboardIcon />,
|
|
// },
|
|
// ],
|
|
// },
|
|
{
|
|
titleKey: "nav.receptionCenter",
|
|
icon: <BotMessageSquareIcon />,
|
|
items: [
|
|
{
|
|
titleKey: "nav.overview",
|
|
url: "/dashboard",
|
|
icon: <LayoutDashboardIcon />,
|
|
},
|
|
{
|
|
titleKey: "nav.conversations",
|
|
url: "/dashboard/conversations",
|
|
icon: <BotMessageSquareIcon />,
|
|
requiredPermission: "conversation.view",
|
|
},
|
|
{
|
|
titleKey: "nav.tickets",
|
|
url: "/dashboard/tickets",
|
|
icon: <FileTextIcon />,
|
|
requiredPermission: "ticket.view",
|
|
},
|
|
{
|
|
titleKey: "nav.conversationMonitor",
|
|
url: "/dashboard/conversation-monitor",
|
|
icon: <BotMessageSquareIcon />,
|
|
requiredPermission: "conversation.view",
|
|
},
|
|
{
|
|
titleKey: "nav.customers",
|
|
url: "/dashboard/customers",
|
|
icon: <UsersIcon />,
|
|
requiredPermission: "customer.view",
|
|
},
|
|
{
|
|
titleKey: "nav.companies",
|
|
url: "/dashboard/companies",
|
|
icon: <Building2Icon />,
|
|
requiredPermission: "company.view",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
titleKey: "nav.agentConfig",
|
|
icon: <UserCogIcon />,
|
|
items: [
|
|
{
|
|
titleKey: "nav.tags",
|
|
url: "/dashboard/tags",
|
|
icon: <TagsIcon />,
|
|
requiredPermission: "tag.view",
|
|
},
|
|
{
|
|
titleKey: "nav.quickReplies",
|
|
url: "/dashboard/quick-replies",
|
|
icon: <MessageSquareMoreIcon />,
|
|
requiredPermission: "quickReply.view",
|
|
},
|
|
{
|
|
titleKey: "nav.agents",
|
|
url: "/dashboard/agents",
|
|
icon: <UserCogIcon />,
|
|
requiredPermission: "agent.view",
|
|
},
|
|
{
|
|
titleKey: "nav.agentTeamSchedules",
|
|
url: "/dashboard/agent-team-schedules",
|
|
icon: <CalendarClockIcon />,
|
|
requiredPermission: "agentTeamSchedule.view",
|
|
},
|
|
{
|
|
titleKey: "nav.channels",
|
|
url: "/dashboard/channels",
|
|
icon: <GlobeIcon />,
|
|
requiredPermission: "channel.view",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
titleKey: "nav.aiCapabilities",
|
|
icon: <BrainCircuitIcon />,
|
|
items: [
|
|
{
|
|
titleKey: "nav.knowledge",
|
|
url: "/dashboard/knowledge",
|
|
icon: <FileTextIcon />,
|
|
requiredPermission: "knowledgeBase.view",
|
|
},
|
|
{
|
|
titleKey: "nav.aiConfigs",
|
|
url: "/dashboard/ai-configs",
|
|
icon: <BrainCircuitIcon />,
|
|
requiredPermission: "aiConfig.view",
|
|
},
|
|
{
|
|
titleKey: "nav.aiAgents",
|
|
url: "/dashboard/ai-agents",
|
|
icon: <MessageSquareMoreIcon />,
|
|
requiredPermission: "aiAgent.view",
|
|
},
|
|
{
|
|
titleKey: "nav.workflows",
|
|
url: "/dashboard/ai-workflows",
|
|
icon: <WorkflowIcon />,
|
|
requiredPermission: "aiAgent.view",
|
|
},
|
|
{
|
|
titleKey: "nav.skillDefinition",
|
|
url: "/dashboard/skill-definition",
|
|
icon: <MessageSquareCodeIcon />,
|
|
requiredPermission: "skillDefinition.view",
|
|
},
|
|
{
|
|
titleKey: "nav.mcp",
|
|
url: "/dashboard/mcp",
|
|
icon: <MessageSquareCodeIcon />,
|
|
requiredPermission: "mcp.view",
|
|
},
|
|
{
|
|
titleKey: "nav.workflowRuns",
|
|
url: "/dashboard/ai-workflow-runs",
|
|
icon: <WorkflowIcon />,
|
|
requiredPermission: "aiAgent.view",
|
|
},
|
|
{
|
|
titleKey: "nav.agentRuns",
|
|
url: "/dashboard/agent-runs",
|
|
icon: <BotMessageSquareIcon />,
|
|
requiredPermission: "aiAgent.view",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
titleKey: "nav.system",
|
|
icon: <ShieldCheckIcon />,
|
|
items: [
|
|
{
|
|
titleKey: "nav.users",
|
|
url: "/dashboard/users",
|
|
icon: <UsersIcon />,
|
|
requiredPermission: "user.view",
|
|
},
|
|
{
|
|
titleKey: "nav.roles",
|
|
url: "/dashboard/roles",
|
|
icon: <ShieldCheckIcon />,
|
|
requiredPermission: "role.view",
|
|
},
|
|
{
|
|
titleKey: "nav.permissions",
|
|
url: "/dashboard/permissions",
|
|
icon: <KeyRoundIcon />,
|
|
requiredPermission: "permission.view",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
export const dashboardSecondaryNav: DashboardNavItemConfig[] = [
|
|
// {
|
|
// title: "System Settings",
|
|
// url: "/settings",
|
|
// icon: <Settings2Icon />,
|
|
// },
|
|
// {
|
|
// title: "Help Center",
|
|
// url: "/help",
|
|
// icon: <LifeBuoyIcon />,
|
|
// },
|
|
];
|
|
|
|
export const dashboardQuickActions = [
|
|
{
|
|
title: "View Conversations",
|
|
icon: <BotMessageSquareIcon />,
|
|
},
|
|
{
|
|
title: "Invite Members",
|
|
icon: <UserCogIcon />,
|
|
},
|
|
{
|
|
title: "Connect Bot",
|
|
icon: <MessageSquareCodeIcon />,
|
|
},
|
|
] as const;
|
|
|
|
export function getPageTitle(pathname: string): string {
|
|
return getPageTitleKey(pathname);
|
|
}
|
|
|
|
export function getPageTitleKey(pathname: string): string {
|
|
let matchedTitle = "nav.dashboardHome";
|
|
let longestMatch = 0;
|
|
|
|
for (const section of dashboardNavSections) {
|
|
for (const item of section.items) {
|
|
if (pathname === item.url || pathname.startsWith(item.url + "/")) {
|
|
const matchLength = item.url.length;
|
|
if (matchLength > longestMatch) {
|
|
longestMatch = matchLength;
|
|
matchedTitle = item.titleKey;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const item of dashboardSecondaryNav) {
|
|
if (pathname === item.url || pathname.startsWith(item.url + "/")) {
|
|
const matchLength = item.url.length;
|
|
if (matchLength > longestMatch) {
|
|
longestMatch = matchLength;
|
|
matchedTitle = item.titleKey;
|
|
}
|
|
}
|
|
}
|
|
|
|
return matchedTitle;
|
|
}
|