Expand Up @@ -10,6 +10,10 @@ import { Button, Tag, Result, Row, Col, Statistic, Progress, } from "antd"; import { LinkOutlined, Expand All @@ -21,6 +25,11 @@ import { CloseCircleOutlined, ExclamationCircleOutlined, SyncOutlined, CloudServerOutlined, UserOutlined, SafetyOutlined, CrownOutlined, ApiOutlined, } from "@ant-design/icons"; import { useSingleEnvironmentContext } from "./context/SingleEnvironmentContext"; Expand All @@ -31,10 +40,12 @@ import history from "@lowcoder-ee/util/history"; import WorkspacesTab from "./components/WorkspacesTab"; import UserGroupsTab from "./components/UserGroupsTab"; import EnvironmentHeader from "./components/EnvironmentHeader"; import StatsCard from "./components/StatsCard"; import ModernBreadcrumbs from "./components/ModernBreadcrumbs"; import { getEnvironmentTagColor } from "./utils/environmentUtils"; import { formatAPICalls, getAPICallsStatusColor } from "./services/license.service"; import ErrorComponent from './components/ErrorComponent'; const {TabPane }= Tabs ;import {Level1SettingPageContent }from "../styled" ;/** * Environment Detail Page Component Expand Down Expand Up @@ -124,33 +135,80 @@ const EnvironmentDetail: React.FC = () => { ); } const breadcrumbItems = [ // Stats data for the cards const statsData = [ { key: 'environments', title: ( title: "Type", value: environment.environmentType || "Unknown", icon: <CloudServerOutlined />, color: getEnvironmentTagColor(environment.environmentType) }, { title: "Status", value: environment.isLicensed ? "Licensed" : "Unlicensed", icon: environment.isLicensed ? <CheckCircleOutlined /> : <CloseCircleOutlined />, color: environment.isLicensed ? "#52c41a" : "#ff4d4f" }, { title: "API Key", value: environment.environmentApikey ? "Configured" : "Not Set", icon: <SafetyOutlined />, color: environment.environmentApikey ? "#1890ff" : "#faad14" }, { title: "Master Env", value: environment.isMaster ? "Yes" : "No", icon: <UserOutlined />, color: environment.isMaster ? "#722ed1" : "#8c8c8c" } ]; const tabItems = [ { key: 'workspaces', label: ( <span> <HomeOutlined />Environments <AppstoreOutlined />Workspaces </span> ), onClick: () => history.push("/setting/environments") children: <WorkspacesTab environment={environment} /> }, { key: 'currentEnvironment', title: environment.environmentName key: 'userGroups', label: ( <span> <UsergroupAddOutlined /> User Groups </span> ), children: <UserGroupsTab environment={environment} /> } ]; return ( <div className="environment-detail-container" style={{ padding: "24px", flex: 1, minWidth: "1000px" }} > <Level1SettingPageContent style={{ minWidth: "1000px" }}> {/* Breadcrumbs */} {/* Environment Header Component */} <EnvironmentHeader environment={environment} onEditClick={handleEditClick} /> {/* Stats Cards Row */} <Row gutter={[16, 16]} style={{ marginBottom: "24px" }}> {statsData.map((stat, index) => ( <Col xs={24} sm={12} lg={6} key={index}> <StatsCard title={stat.title} value={stat.value} icon={stat.icon} color={stat.color} /> </Col> ))} </Row> {/* Basic Environment Information Card */} <Card title="Environment Overview" Expand Down Expand Up @@ -180,13 +238,10 @@ const EnvironmentDetail: React.FC = () => { "No domain set" )} </Descriptions.Item> <Descriptions.Item label="Environment Type"> <Tag color={getEnvironmentTagColor(environment.environmentType)} style={{ borderRadius: '4px' }} > {environment.environmentType} </Tag> <Descriptions.Item label="Environment ID"> <code style={{ padding: '2px 6px', background: '#f5f5f5', borderRadius: '3px' }}> {environment.environmentId} </code> </Descriptions.Item> <Descriptions.Item label="License Status"> {(() => { Expand All @@ -196,29 +251,178 @@ const EnvironmentDetail: React.FC = () => { case 'licensed': return <Tag icon={<CheckCircleOutlined />} color="green" style={{ borderRadius: '4px' }}>Licensed</Tag>; case 'unlicensed': return <Tag icon={<CloseCircleOutlined />} color="red " style={{ borderRadius: '4px' }}>Not Licensed </Tag>; return <Tag icon={<CloseCircleOutlined />} color="orange " style={{ borderRadius: '4px' }}>License Needed </Tag>; case 'error': return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '4px' }}>License Error </Tag>; return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '4px' }}>Setup Required </Tag>; default: return <Tag color="default" style={{ borderRadius: '4px' }}>Unknown</Tag>; } })()} </Descriptions.Item> <Descriptions.Item label="API Key Status"> {environment.environmentApikey ? ( <Tag color="green" style={{ borderRadius: '4px' }}>Configured</Tag> ) : ( <Tag color="red" style={{ borderRadius: '4px' }}>Not Configured</Tag> )} </Descriptions.Item> <Descriptions.Item label="Master Environment"> {environment.isMaster ? "Yes" : "No"} <Descriptions.Item label="Created"> {environment.createdAt ? new Date(environment.createdAt).toLocaleDateString() : "Unknown"} </Descriptions.Item> </Descriptions> </Card> {/* Modern Breadcrumbs navigation */} <ModernBreadcrumbs items={breadcrumbItems} /> <ModernBreadcrumbs items={[ { key: 'environments', title: 'Environments', onClick: () => history.push('/setting/environments') }, { key: 'current', title: environment.environmentName || "Environment Detail" } ]} /> {/* Detailed License Information Card - only show for licensed environments with details */} {environment.isLicensed && environment.licenseDetails && ( <Card title={ <span> <CrownOutlined style={{ color: '#52c41a', marginRight: '8px' }} /> License Details </span> } style={{ marginBottom: "24px", borderRadius: '4px', border: '1px solid #f0f0f0' }} className="license-details-card" > <Row gutter={[24, 16]}> {/* API Calls Status */} <Col xs={24} sm={12} md={8}> <Card size="small" style={{ height: '100%', textAlign: 'center' }} styles={{ body: { padding: '16px' } }} > <Statistic title="API Calls Remaining" value={environment.licenseDetails.remainingAPICalls} formatter={(value) => ( <span style={{ color: getAPICallsStatusColor( environment.licenseDetails?.remainingAPICalls || 0, environment.licenseDetails?.totalAPICallsLimit || 0 ) }}> {value?.toLocaleString()} </span> )} prefix={<ApiOutlined />} /> <div style={{ marginTop: '12px' }}> <Progress percent={environment.licenseDetails.apiCallsUsage || 0} strokeColor={getAPICallsStatusColor( environment.licenseDetails.remainingAPICalls, environment.licenseDetails.totalAPICallsLimit || 0 )} size="small" showInfo={false} /> <div style={{ fontSize: '12px', color: '#8c8c8c', marginTop: '4px' }}> {environment.licenseDetails.apiCallsUsage || 0}% used </div> </div> </Card> </Col> {/* Total License Limit */} <Col xs={24} sm={12} md={8}> <Card size="small" style={{ height: '100%', textAlign: 'center' }} styles={{ body: { padding: '16px' } }} > <Statistic title="Total API Calls Limit" value={environment.licenseDetails.totalAPICallsLimit} formatter={(value) => value?.toLocaleString()} prefix={<ApiOutlined />} /> <Tag color="blue" style={{ marginTop: '12px' }} > {environment.licenseDetails.eeLicenses.length} License{environment.licenseDetails.eeLicenses.length !== 1 ? 's' : ''} </Tag> </Card> </Col> {/* Enterprise Edition Status */} <Col xs={24} sm={12} md={8}> <Card size="small" style={{ height: '100%', textAlign: 'center' }} styles={{ body: { padding: '16px' } }} > <Statistic title="Enterprise Edition" value={environment.licenseDetails.eeActive ? "Active" : "Inactive"} formatter={(value) => ( <Tag color={environment.licenseDetails?.eeActive ? "green" : "red"} icon={environment.licenseDetails?.eeActive ? <CheckCircleOutlined /> : <CloseCircleOutlined />} > {value} </Tag> )} /> </Card> </Col> </Row> {/* License Details */} <div style={{ marginTop: '24px' }}> <Typography.Title level={5} style={{ marginBottom: '16px' }}> <UserOutlined style={{ marginRight: '8px' }} /> License Information </Typography.Title> <Row gutter={[16, 16]}> {environment.licenseDetails.eeLicenses.map((license, index) => ( <Col xs={24} sm={12} md={8} key={license.uuid}> <Card size="small" style={{ border: '1px solid #f0f0f0', borderRadius: '6px' }} styles={{ body: { padding: '12px' } }} > <div style={{ marginBottom: '8px' }}> <strong style={{ color: '#262626' }}> {license.customerName} </strong> </div> <div style={{ fontSize: '12px', color: '#8c8c8c', marginBottom: '8px' }}> ID: {license.customerId} </div> <div style={{ fontSize: '12px', color: '#8c8c8c', marginBottom: '8px' }}> UUID: <span style={{ fontFamily: 'monospace' }}>{license.uuid.substring(0, 8)}...</span> </div> <Tag color="blue"> {license.apiCallsLimit.toLocaleString()} calls </Tag> </Card> </Col> ))} </Row> </div> </Card> )} {/* Tabs for Workspaces and User Groups */} <Tabs Expand All @@ -227,29 +431,8 @@ const EnvironmentDetail: React.FC = () => { onChange={setActiveTab} className="modern-tabs" type="line" > <TabPane tab={ <span> <AppstoreOutlined /> Workspaces </span> } key="workspaces" > <WorkspacesTab environment={environment} /> </TabPane> <TabPane tab={ <span> <UsergroupAddOutlined /> User Groups </span> } key="userGroups" > <UserGroupsTab environment={environment} /> </TabPane> </Tabs> items={tabItems} /> {/* Edit Environment Modal */} {environment && ( Expand All @@ -261,7 +444,7 @@ const EnvironmentDetail: React.FC = () => { loading={isUpdating} /> )} </div > </Level1SettingPageContent > ); }; Expand Down