增加代码编辑器表单组件
This commit is contained in:
parent
a8a9e2625e
commit
edd34ae5db
@ -0,0 +1,159 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import {
|
||||||
|
Settings,
|
||||||
|
Bell,
|
||||||
|
Package,
|
||||||
|
MoreHorizontal,
|
||||||
|
Edit,
|
||||||
|
Trash2
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
interface ActionButtonsCellProps {
|
||||||
|
environmentId: number;
|
||||||
|
environmentName?: string;
|
||||||
|
onConfig: (environmentId: number) => void;
|
||||||
|
onNotification: (config: any) => void;
|
||||||
|
onAppManage: (environmentId: number) => void;
|
||||||
|
onDelete: (config: any) => void;
|
||||||
|
config: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ActionButtonsCell: React.FC<ActionButtonsCellProps> = ({
|
||||||
|
environmentId,
|
||||||
|
environmentName,
|
||||||
|
onConfig,
|
||||||
|
onNotification,
|
||||||
|
onAppManage,
|
||||||
|
onDelete,
|
||||||
|
config
|
||||||
|
}) => {
|
||||||
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleConfig = () => {
|
||||||
|
onConfig(environmentId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNotification = () => {
|
||||||
|
onNotification(config);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAppManage = () => {
|
||||||
|
onAppManage(environmentId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
onDelete(config);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-end gap-1">
|
||||||
|
{/* 主要操作按钮 */}
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={handleConfig}
|
||||||
|
className="h-8 px-2"
|
||||||
|
>
|
||||||
|
<Settings className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-xs">环境配置</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={handleNotification}
|
||||||
|
className="h-8 px-2"
|
||||||
|
>
|
||||||
|
<Bell className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-xs">通知设置</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={handleAppManage}
|
||||||
|
className="h-8 px-2"
|
||||||
|
>
|
||||||
|
<Package className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-xs">应用管理</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
{/* 更多操作下拉菜单 */}
|
||||||
|
<DropdownMenu open={isDropdownOpen} onOpenChange={setIsDropdownOpen}>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-8 px-2"
|
||||||
|
>
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-xs">更多操作</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
<DropdownMenuContent align="end" className="w-48">
|
||||||
|
<DropdownMenuItem onClick={handleConfig} className="cursor-pointer">
|
||||||
|
<Edit className="h-4 w-4 mr-2" />
|
||||||
|
编辑配置
|
||||||
|
</DropdownMenuItem>
|
||||||
|
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={handleDelete}
|
||||||
|
className="cursor-pointer text-destructive focus:text-destructive"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4 mr-2" />
|
||||||
|
删除配置
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import { Package, PackageOpen } from 'lucide-react';
|
||||||
|
|
||||||
|
interface ApplicationCountCellProps {
|
||||||
|
applicationCount?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ApplicationCountCell: React.FC<ApplicationCountCellProps> = ({
|
||||||
|
applicationCount = 0
|
||||||
|
}) => {
|
||||||
|
const count = applicationCount || 0;
|
||||||
|
|
||||||
|
const config = count === 0
|
||||||
|
? {
|
||||||
|
icon: <Package className="h-3 w-3" />,
|
||||||
|
label: '0个应用',
|
||||||
|
variant: 'secondary' as const,
|
||||||
|
description: '该环境尚未配置任何应用',
|
||||||
|
color: 'text-muted-foreground'
|
||||||
|
}
|
||||||
|
: count <= 5
|
||||||
|
? {
|
||||||
|
icon: <PackageOpen className="h-3 w-3 text-green-500" />,
|
||||||
|
label: `${count}个应用`,
|
||||||
|
variant: 'success' as const,
|
||||||
|
description: `已配置${count}个应用`,
|
||||||
|
color: 'text-green-600'
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
icon: <PackageOpen className="h-3 w-3 text-blue-500" />,
|
||||||
|
label: `${count}个应用`,
|
||||||
|
variant: 'default' as const,
|
||||||
|
description: `已配置${count}个应用,应用较多`,
|
||||||
|
color: 'text-blue-600'
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
{config.icon}
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{config.label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="max-w-xs bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-white text-xs">
|
||||||
|
{config.description}
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
101
frontend/src/pages/Deploy/Team/List/components/ApproversCell.tsx
Normal file
101
frontend/src/pages/Deploy/Team/List/components/ApproversCell.tsx
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import { Users, CheckCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
id: number;
|
||||||
|
realName?: string;
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ApproversCellProps {
|
||||||
|
approvalRequired?: boolean;
|
||||||
|
approverUserIds?: number[];
|
||||||
|
users?: User[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ApproversCell: React.FC<ApproversCellProps> = ({
|
||||||
|
approvalRequired,
|
||||||
|
approverUserIds,
|
||||||
|
users = []
|
||||||
|
}) => {
|
||||||
|
// 不需要审批
|
||||||
|
if (!approvalRequired) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1.5 text-muted-foreground text-sm">
|
||||||
|
<CheckCircle className="h-3 w-3 text-green-500" />
|
||||||
|
<span>无需审批</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要审批但没有设置审批人
|
||||||
|
if (!approverUserIds || approverUserIds.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1.5 text-orange-600 text-sm">
|
||||||
|
<Users className="h-3 w-3" />
|
||||||
|
<span>未设置审批人</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取有效的审批人
|
||||||
|
const validApprovers = approverUserIds
|
||||||
|
.map(id => users.find(u => u.id === id))
|
||||||
|
.filter(Boolean) as User[];
|
||||||
|
|
||||||
|
if (validApprovers.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1.5 text-orange-600 text-sm">
|
||||||
|
<Users className="h-3 w-3" />
|
||||||
|
<span>审批人无效</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayApprovers = validApprovers.slice(0, 2);
|
||||||
|
const remainingCount = validApprovers.length - 2;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center gap-1 min-w-0">
|
||||||
|
<div className="flex gap-1 flex-wrap">
|
||||||
|
{displayApprovers.map((user) => (
|
||||||
|
<Badge key={user.id} variant="secondary" className="text-xs">
|
||||||
|
{user.realName || user.username}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
{remainingCount > 0 && (
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
+{remainingCount}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{remainingCount > 0 && (
|
||||||
|
<TooltipContent className="max-w-xs bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="space-y-1 text-white">
|
||||||
|
<div className="text-xs font-medium">全部审批人:</div>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{validApprovers.map((user) => (
|
||||||
|
<Badge key={user.id} variant="outline" className="text-xs border-gray-600 text-gray-200">
|
||||||
|
{user.realName || user.username}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import { GitBranch, GitPullRequest, ShieldCheck } from 'lucide-react';
|
||||||
|
|
||||||
|
interface CodeReviewCellProps {
|
||||||
|
requireCodeReview?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CodeReviewCell: React.FC<CodeReviewCellProps> = ({
|
||||||
|
requireCodeReview
|
||||||
|
}) => {
|
||||||
|
const config = requireCodeReview
|
||||||
|
? {
|
||||||
|
icon: <ShieldCheck className="h-3 w-3 text-blue-500" />,
|
||||||
|
label: '需要',
|
||||||
|
variant: 'default' as const,
|
||||||
|
description: '部署前需要进行代码审查',
|
||||||
|
color: 'text-blue-600'
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
icon: <GitPullRequest className="h-3 w-3 text-gray-500" />,
|
||||||
|
label: '不需要',
|
||||||
|
variant: 'secondary' as const,
|
||||||
|
description: '部署时不需要代码审查',
|
||||||
|
color: 'text-gray-500'
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<Badge variant={config.variant} className="text-xs px-2 py-0.5">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
{config.icon}
|
||||||
|
<span>{config.label}</span>
|
||||||
|
</div>
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent className="max-w-xs bg-gray-900 border-gray-700 text-white">
|
||||||
|
<div className="text-white text-xs">
|
||||||
|
{config.description}
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,151 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import {
|
||||||
|
Bell,
|
||||||
|
MessageSquare,
|
||||||
|
Mail,
|
||||||
|
AlertTriangle,
|
||||||
|
CheckCircle,
|
||||||
|
XCircle
|
||||||
|
} from 'lucide-react';
|
||||||
|
import type { NotificationConfig } from '../types';
|
||||||
|
|
||||||
|
interface NotificationChannelCellProps {
|
||||||
|
notificationConfig?: NotificationConfig | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知渠道类型映射
|
||||||
|
const getChannelIcon = (channelType?: string) => {
|
||||||
|
switch (channelType) {
|
||||||
|
case 'WEWORK':
|
||||||
|
return <MessageSquare className="h-3 w-3" />;
|
||||||
|
case 'EMAIL':
|
||||||
|
return <Mail className="h-3 w-3" />;
|
||||||
|
case 'DINGTALK':
|
||||||
|
return <Bell className="h-3 w-3" />;
|
||||||
|
default:
|
||||||
|
return <Bell className="h-3 w-3" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 通知类型配置
|
||||||
|
const notificationTypes = [
|
||||||
|
{
|
||||||
|
key: 'deployNotificationEnabled',
|
||||||
|
label: '部署',
|
||||||
|
variant: 'success' as const,
|
||||||
|
description: '部署状态变更时发送通知'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'buildNotificationEnabled',
|
||||||
|
label: '构建',
|
||||||
|
variant: 'default' as const,
|
||||||
|
description: '构建状态变更时发送通知'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'buildFailureFileEnabled',
|
||||||
|
label: '失败文件',
|
||||||
|
variant: 'destructive' as const,
|
||||||
|
description: '构建失败文件时发送通知'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const NotificationChannelCell: React.FC<NotificationChannelCellProps> = ({
|
||||||
|
notificationConfig
|
||||||
|
}) => {
|
||||||
|
// 未配置状态
|
||||||
|
if (!notificationConfig) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2 text-muted-foreground text-sm">
|
||||||
|
<Bell className="h-3 w-3 opacity-50" />
|
||||||
|
<span>未配置</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
notificationChannelName,
|
||||||
|
deployNotificationEnabled,
|
||||||
|
buildNotificationEnabled,
|
||||||
|
buildFailureFileEnabled,
|
||||||
|
updateTime,
|
||||||
|
updateBy
|
||||||
|
} = notificationConfig;
|
||||||
|
|
||||||
|
// 计算启用的通知类型
|
||||||
|
const enabledNotifications = notificationTypes.filter(type =>
|
||||||
|
notificationConfig[type.key as keyof NotificationConfig]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 渠道名称显示
|
||||||
|
const channelName = notificationChannelName || '未知渠道';
|
||||||
|
|
||||||
|
// 状态判断
|
||||||
|
const hasEnabledNotifications = enabledNotifications.length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip delayDuration={300}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="flex items-center gap-1.5 min-w-0 max-w-48">
|
||||||
|
{getChannelIcon(notificationConfig.channelType)}
|
||||||
|
<span className="text-sm font-medium truncate">
|
||||||
|
{channelName}
|
||||||
|
</span>
|
||||||
|
{hasEnabledNotifications ? (
|
||||||
|
<div className="flex gap-0.5 ml-auto">
|
||||||
|
{enabledNotifications.map((notification) => (
|
||||||
|
<div
|
||||||
|
key={notification.key}
|
||||||
|
className={`w-1.5 h-1.5 rounded-full ${
|
||||||
|
notification.variant === 'success' ? 'bg-green-500' :
|
||||||
|
notification.variant === 'destructive' ? 'bg-red-500' :
|
||||||
|
'bg-blue-500'
|
||||||
|
}`}
|
||||||
|
title={notification.label}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span className="text-xs text-muted-foreground ml-auto">未启用</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
|
||||||
|
<TooltipContent
|
||||||
|
side="top"
|
||||||
|
align="start"
|
||||||
|
className="max-w-xs bg-gray-900 border-gray-700 text-white"
|
||||||
|
>
|
||||||
|
<div className="text-white">
|
||||||
|
{/* 启用的通知类型 */}
|
||||||
|
{hasEnabledNotifications ? (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="text-xs font-medium text-gray-300 mb-1">启用的通知类型:</div>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{enabledNotifications.map((notification) => (
|
||||||
|
<Badge
|
||||||
|
key={notification.key}
|
||||||
|
variant="outline"
|
||||||
|
className="text-xs border-gray-600 text-gray-200"
|
||||||
|
>
|
||||||
|
{notification.label}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-xs text-gray-300">未启用任何通知</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -27,6 +27,11 @@ import { getTeamEnvironmentConfigs, deleteTeamEnvironmentConfig } from '../servi
|
|||||||
import { TeamEnvironmentConfigDialog } from './TeamEnvironmentConfigDialog';
|
import { TeamEnvironmentConfigDialog } from './TeamEnvironmentConfigDialog';
|
||||||
import { TeamApplicationManageDialog } from './TeamApplicationManageDialog';
|
import { TeamApplicationManageDialog } from './TeamApplicationManageDialog';
|
||||||
import { NotificationConfigDialog } from './NotificationConfigDialog';
|
import { NotificationConfigDialog } from './NotificationConfigDialog';
|
||||||
|
import { NotificationChannelCell } from './NotificationChannelCell';
|
||||||
|
import { ApproversCell } from './ApproversCell';
|
||||||
|
import { CodeReviewCell } from './CodeReviewCell';
|
||||||
|
import { ApplicationCountCell } from './ApplicationCountCell';
|
||||||
|
import { ActionButtonsCell } from './ActionButtonsCell';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: number;
|
id: number;
|
||||||
@ -196,112 +201,42 @@ export const TeamEnvironmentManageDialog: React.FC<
|
|||||||
{config.environmentName}
|
{config.environmentName}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{config.approvalRequired && config.approverUserIds && config.approverUserIds.length > 0 ? (
|
<ApproversCell
|
||||||
<div className="flex gap-1 flex-wrap">
|
approvalRequired={config.approvalRequired}
|
||||||
{config.approverUserIds.map((userId) => {
|
approverUserIds={config.approverUserIds}
|
||||||
const user = users.find(u => u.id === userId);
|
users={users}
|
||||||
return user ? (
|
/>
|
||||||
<Badge key={userId} variant="secondary" className="text-xs">
|
|
||||||
{user.realName || user.username}
|
|
||||||
</Badge>
|
|
||||||
) : null;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<span className="text-muted-foreground text-sm">
|
|
||||||
无需审批
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{config.notificationConfig ? (
|
<NotificationChannelCell
|
||||||
<div className="flex flex-col gap-1">
|
notificationConfig={config.notificationConfig}
|
||||||
{config.notificationConfig.deployNotificationEnabled && (
|
/>
|
||||||
<Badge variant="outline" className="text-xs">
|
|
||||||
部署通知
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
{config.notificationConfig.buildNotificationEnabled && (
|
|
||||||
<Badge variant="outline" className="text-xs">
|
|
||||||
构建通知
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
{!config.notificationConfig.deployNotificationEnabled &&
|
|
||||||
!config.notificationConfig.buildNotificationEnabled && (
|
|
||||||
<span className="text-muted-foreground text-sm">
|
|
||||||
未启用
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<span className="text-muted-foreground text-sm">
|
|
||||||
未配置
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<span className="text-sm">
|
<ApplicationCountCell
|
||||||
{config.applicationCount || 0} 个应用
|
applicationCount={config.applicationCount}
|
||||||
</span>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Badge
|
<CodeReviewCell
|
||||||
variant={
|
requireCodeReview={config.requireCodeReview}
|
||||||
config.requireCodeReview
|
/>
|
||||||
? 'default'
|
|
||||||
: 'secondary'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{config.requireCodeReview ? '需要' : '不需要'}
|
|
||||||
</Badge>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
{config.remark || '-'}
|
{config.remark || '-'}
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell>
|
||||||
<div className="flex items-center justify-end gap-2">
|
<ActionButtonsCell
|
||||||
<Button
|
environmentId={config.environmentId}
|
||||||
variant="ghost"
|
environmentName={config.environmentName}
|
||||||
size="sm"
|
onConfig={handleOpenConfigDialog}
|
||||||
onClick={() =>
|
onNotification={handleOpenNotificationDialog}
|
||||||
handleOpenConfigDialog(
|
onAppManage={handleOpenAppManageDialog}
|
||||||
config.environmentId
|
onDelete={handleOpenDeleteDialog}
|
||||||
)
|
config={config}
|
||||||
}
|
/>
|
||||||
>
|
|
||||||
<Settings className="h-4 w-4 mr-1" />
|
|
||||||
配置
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleOpenNotificationDialog(config)}
|
|
||||||
>
|
|
||||||
<Bell className="h-4 w-4 mr-1" />
|
|
||||||
通知
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() =>
|
|
||||||
handleOpenAppManageDialog(
|
|
||||||
config.environmentId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<AppWindow className="h-4 w-4 mr-1" />
|
|
||||||
应用
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleOpenDeleteDialog(config)}
|
|
||||||
>
|
|
||||||
<Trash2 className="h-4 w-4 text-destructive" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -55,7 +55,11 @@ export interface NotificationConfig {
|
|||||||
notificationChannelId?: number;
|
notificationChannelId?: number;
|
||||||
deployNotificationEnabled?: boolean;
|
deployNotificationEnabled?: boolean;
|
||||||
buildNotificationEnabled?: boolean;
|
buildNotificationEnabled?: boolean;
|
||||||
|
buildFailureFileEnabled?: boolean;
|
||||||
notificationChannelName?: string; // 关联数据
|
notificationChannelName?: string; // 关联数据
|
||||||
|
channelType?: string; // 渠道类型:WEWORK, EMAIL, DINGTALK等
|
||||||
|
updateTime?: string; // 更新时间
|
||||||
|
updateBy?: string; // 更新人
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user