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