From 0ee3f1f60ff80b14e3507b88e1f80e9da127a259 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 15:52:03 +0500 Subject: [PATCH 01/13] Add api calls count --- .../environments/EnvironmentDetail.tsx | 154 ++++++++++++++++++ .../components/EnvironmentsTable.tsx | 37 ++++- .../services/environments.service.ts | 2 + .../environments/services/license.service.ts | 86 +++++++++- .../environments/types/environment.types.ts | 26 +++ 5 files changed, 294 insertions(+), 11 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index 041997779..eb6e250f8 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -10,6 +10,11 @@ import { Button, Tag, Result, + Progress, + Statistic, + Row, + Col, + Tooltip, } from "antd"; import { LinkOutlined, @@ -21,6 +26,9 @@ import { CloseCircleOutlined, ExclamationCircleOutlined, SyncOutlined, + ApiOutlined, + UserOutlined, + CrownOutlined, } from "@ant-design/icons"; import { useSingleEnvironmentContext } from "./context/SingleEnvironmentContext"; @@ -33,6 +41,7 @@ import UserGroupsTab from "./components/UserGroupsTab"; import EnvironmentHeader from "./components/EnvironmentHeader"; 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; @@ -217,6 +226,151 @@ const EnvironmentDetail: React.FC = () => { + {/* Detailed License Information Card - only show for licensed environments with details */} + {environment.isLicensed && environment.licenseDetails && ( + + + License Details + + } + style={{ + marginBottom: "24px", + borderRadius: '4px', + border: '1px solid #f0f0f0' + }} + className="license-details-card" + > + + {/* API Calls Status */} + + + ( + + {value?.toLocaleString()} + + )} + prefix={} + /> +
+ +
+ {environment.licenseDetails.apiCallsUsage || 0}% used +
+
+
+ + + {/* Total License Limit */} + + + value?.toLocaleString()} + prefix={} + /> + + {environment.licenseDetails.eeLicenses.length} License{environment.licenseDetails.eeLicenses.length !== 1 ? 's' : ''} + + + + + {/* Enterprise Edition Status */} + + + ( + : } + > + {value} + + )} + /> + + +
+ + {/* License Details */} +
+ + + License Information + + + + {environment.licenseDetails.eeLicenses.map((license, index) => ( + + +
+ + {license.customerName} + +
+
+ ID: {license.customerId} +
+
+ UUID: {license.uuid.substring(0, 8)}... +
+ + {license.apiCallsLimit.toLocaleString()} calls + +
+ + ))} +
+
+
+ )} + {/* Modern Breadcrumbs navigation */} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx index 0a1e9d98e..aeebf4036 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import { Table, Tag, Button, Tooltip, Space, Card, Row, Col, Typography, Avatar, Spin, Alert } from 'antd'; -import { EditOutlined, AuditOutlined, LinkOutlined, EnvironmentOutlined, StarFilled, CloudServerOutlined, CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined, SyncOutlined } from '@ant-design/icons'; +import { Table, Tag, Button, Tooltip, Space, Card, Row, Col, Typography, Avatar, Spin, Alert, Progress } from 'antd'; +import { EditOutlined, AuditOutlined, LinkOutlined, EnvironmentOutlined, StarFilled, CloudServerOutlined, CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined, SyncOutlined, ApiOutlined } from '@ant-design/icons'; import { Environment } from '../types/environment.types'; import { getEnvironmentTagColor, formatEnvironmentType } from '../utils/environmentUtils'; +import { getAPICallsStatusColor } from '../services/license.service'; const { Text, Title } = Typography; @@ -267,6 +268,38 @@ const EnvironmentsTable: React.FC = ({ + + {/* API Calls Information - show if license details are available */} + {env.licenseDetails && ( +
+
+ + + API Calls + + +
+ +
+ {env.licenseDetails.apiCallsUsage || 0}% used +
+
+ )} diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts index eb11609f5..b3ccb5314 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts @@ -136,6 +136,7 @@ export async function getEnvironmentById(id: string): Promise { envWithLicense.isLicensed = licenseInfo.isValid; envWithLicense.licenseStatus = licenseInfo.isValid ? 'licensed' : 'unlicensed'; envWithLicense.licenseError = licenseInfo.error; + envWithLicense.licenseDetails = licenseInfo.details; } else { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; @@ -556,6 +557,7 @@ export async function getEnvironmentsWithLicenseStatus(): Promise envWithLicense.isLicensed = licenseInfo.isValid; envWithLicense.licenseStatus = licenseInfo.isValid ? 'licensed' : 'unlicensed'; envWithLicense.licenseError = licenseInfo.error; + envWithLicense.licenseDetails = licenseInfo.details; } else { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts index ff0be0ce6..1d80a2164 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts @@ -1,11 +1,11 @@ import axios from 'axios'; -import { EnvironmentLicense } from '../types/environment.types'; +import { EnvironmentLicense, DetailedLicenseInfo } from '../types/environment.types'; /** - * Check if license endpoint exists for an environment + * Check license and fetch detailed license information for an environment * @param apiServiceUrl - API service URL for the environment * @param apiKey - API key for the environment - * @returns Promise with license information + * @returns Promise with license information including detailed data */ export async function checkEnvironmentLicense( apiServiceUrl: string, @@ -25,8 +25,8 @@ export async function checkEnvironmentLicense( headers.Authorization = `Bearer ${apiKey}`; } - // Use GET request to check endpoint existence - await axios.get( + // Fetch detailed license information + const response = await axios.get( `${apiServiceUrl}/api/plugins/enterprise/license`, { headers, @@ -34,16 +34,84 @@ export async function checkEnvironmentLicense( } ); - // If we get a successful response, the endpoint exists + // Parse the license response + const licenseData = response.data; + + // Calculate total API calls limit and usage percentage + const totalAPICallsLimit = licenseData.eeLicenses?.reduce( + (sum: number, license: any) => sum + (license.apiCallsLimit || 0), + 0 + ) || 0; + + const apiCallsUsage = totalAPICallsLimit > 0 + ? Math.round(((totalAPICallsLimit - licenseData.remainingAPICalls) / totalAPICallsLimit) * 100) + : 0; + + const licenseDetails: DetailedLicenseInfo = { + eeActive: licenseData.eeActive || false, + remainingAPICalls: licenseData.remainingAPICalls || 0, + eeLicenses: licenseData.eeLicenses || [], + totalAPICallsLimit, + apiCallsUsage + }; + + // Determine if license is valid based on enterprise edition status and remaining calls + const isValid = licenseDetails.eeActive && licenseDetails.remainingAPICalls > 0; + return { - isValid: true + isValid, + details: licenseDetails }; } catch (error) { - // Any error means the endpoint doesn't exist or isn't accessible + // Determine the specific error type + let errorMessage = 'License not available'; + + if (axios.isAxiosError(error)) { + if (error.code === 'ECONNABORTED') { + errorMessage = 'License check timed out'; + } else if (error.response?.status === 404) { + errorMessage = 'License endpoint not found'; + } else if (error.response?.status === 401) { + errorMessage = 'Unauthorized - check API key'; + } else if (error.response && error.response.status >= 500) { + errorMessage = 'License server error'; + } + } + return { isValid: false, - error: 'License not available' + error: errorMessage }; } +} + +/** + * Format API calls for display + * @param remaining - Remaining API calls + * @param total - Total API calls limit + * @returns Formatted string + */ +export function formatAPICalls(remaining: number, total: number): string { + const used = total - remaining; + const percentage = total > 0 ? Math.round((used / total) * 100) : 0; + + return `${remaining.toLocaleString()} remaining (${used.toLocaleString()}/${total.toLocaleString()} used, ${percentage}%)`; +} + +/** + * Get API calls status color based on usage percentage + * @param remainingCalls - Remaining API calls + * @param totalCalls - Total API calls limit + * @returns Color string for UI components + */ +export function getAPICallsStatusColor(remainingCalls: number, totalCalls: number): string { + if (totalCalls === 0) return '#d9d9d9'; // Unknown + + const usagePercentage = ((totalCalls - remainingCalls) / totalCalls) * 100; + + if (usagePercentage >= 90) return '#ff4d4f'; // Red - Critical + if (usagePercentage >= 75) return '#faad14'; // Orange - Warning + if (usagePercentage >= 50) return '#1890ff'; // Blue - Moderate + return '#52c41a'; // Green - Good } \ No newline at end of file diff --git a/client/packages/lowcoder/src/pages/setting/environments/types/environment.types.ts b/client/packages/lowcoder/src/pages/setting/environments/types/environment.types.ts index 388fbab02..d62730c98 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/types/environment.types.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/types/environment.types.ts @@ -18,6 +18,8 @@ export interface Environment { isLicensed?: boolean; licenseStatus?: 'checking' | 'licensed' | 'unlicensed' | 'error'; licenseError?: string; + // Enhanced license details + licenseDetails?: DetailedLicenseInfo; } /** @@ -26,4 +28,28 @@ export interface Environment { export interface EnvironmentLicense { isValid: boolean; error?: string; + // Enhanced license details + details?: DetailedLicenseInfo; +} + +/** + * Interface representing detailed license information from the license endpoint + */ +export interface DetailedLicenseInfo { + eeActive: boolean; + remainingAPICalls: number; + eeLicenses: LicenseEntry[]; + // Calculated fields + totalAPICallsLimit?: number; + apiCallsUsage?: number; // percentage used +} + +/** + * Interface representing a single license entry + */ +export interface LicenseEntry { + uuid: string; + customerId: string; + customerName: string; + apiCallsLimit: number; } \ No newline at end of file From 49d8481b16f1576351fd86e22eb64a0c8f119507 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 16:59:49 +0500 Subject: [PATCH 02/13] update alert texts for environment modals --- .../environments/components/CreateEnvironmentModal.tsx | 6 +++--- .../environments/components/EditEnvironmentModal.tsx | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx index ace410bab..b9b5c7c2a 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx @@ -192,9 +192,9 @@ const CreateEnvironmentModal: React.FC = ({ diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx index 593e4be2e..3b90bc826 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Modal, Form, Input, Select, Switch, Button, Tooltip } from 'antd'; +import { Modal, Form, Input, Select, Switch, Button, Alert, Tooltip } from 'antd'; import { useSelector } from 'react-redux'; import { selectMasterEnvironment, selectHasMasterEnvironment } from 'redux/selectors/enterpriseSelectors'; import { Environment } from '../types/environment.types'; @@ -191,7 +191,13 @@ const EditEnvironmentModal: React.FC = ({ - + ); From 2252d2ce17d042a26d8b322d4b6743fbcbf3242f Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 17:41:38 +0500 Subject: [PATCH 03/13] add less aggressive license messages --- .../environments/EnvironmentDetail.tsx | 4 +-- .../components/EnvironmentsTable.tsx | 18 ++++++------ .../components/UnlicensedEnvironmentView.tsx | 28 +++++++------------ .../environments/services/license.service.ts | 20 ++++++------- 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index eb6e250f8..8672589ce 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -205,9 +205,9 @@ const EnvironmentDetail: React.FC = () => { case 'licensed': return } color="green" style={{ borderRadius: '4px' }}>Licensed; case 'unlicensed': - return } color="red" style={{ borderRadius: '4px' }}>Not Licensed; + return } color="orange" style={{ borderRadius: '4px' }}>License Needed; case 'error': - return } color="orange" style={{ borderRadius: '4px' }}>License Error; + return } color="orange" style={{ borderRadius: '4px' }}>Setup Required; default: return Unknown; } diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx index aeebf4036..10e077c2b 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx @@ -55,29 +55,29 @@ const EnvironmentsTable: React.FC = ({ case 'checking': return { icon: , - color: '#1890ff', + color: '#40a9ff', text: 'Checking...', status: 'processing' as const }; case 'licensed': return { icon: , - color: '#52c41a', + color: '#73d13d', text: 'Licensed', status: 'success' as const }; case 'unlicensed': return { icon: , - color: '#ff4d4f', - text: 'Not Licensed', - status: 'error' as const + color: '#ff7875', + text: 'License Required', + status: 'warning' as const }; case 'error': return { icon: , - color: '#faad14', - text: 'License Error', + color: '#ffc53d', + text: 'Setup Required', status: 'warning' as const }; default: @@ -180,8 +180,8 @@ const EnvironmentsTable: React.FC = ({ {licenseDisplay.text} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx index 6b61379dd..fbe2644b8 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx @@ -31,37 +31,29 @@ const UnlicensedEnvironmentView: React.FC = ({ const getLicenseIcon = () => { switch (environment.licenseStatus) { case 'unlicensed': - return ; + return ; case 'error': - return ; + return ; default: - return ; + return ; } }; const getLicenseTitle = () => { - switch (environment.licenseStatus) { - case 'unlicensed': - return 'Environment Not Licensed'; - case 'error': - return 'License Configuration Error'; - default: - return 'License Issue'; - } - }; + return environment.licenseError; + } + + const getLicenseDescription = () => { - if (environment.licenseError) { - return environment.licenseError; - } switch (environment.licenseStatus) { case 'unlicensed': - return 'This environment requires a valid license to access its features and functionality.'; + return 'This environment needs a valid license to unlock its full capabilities and features. Please make sure your API Service URL is correctly configured and Plugin is installed.'; case 'error': - return 'There was an error validating the license for this environment. Please check the configuration.'; + return 'We encountered an issue while checking the license. Please review the configuration settings.'; default: - return 'This environment has license-related issues that need to be resolved.'; + return 'This environment requires license configuration to proceed.'; } }; diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts index 1d80a2164..ebc0ae46a 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts @@ -65,17 +65,17 @@ export async function checkEnvironmentLicense( } catch (error) { // Determine the specific error type - let errorMessage = 'License not available'; + let errorMessage = 'License information unavailable'; if (axios.isAxiosError(error)) { if (error.code === 'ECONNABORTED') { - errorMessage = 'License check timed out'; + errorMessage = 'License check took too long'; } else if (error.response?.status === 404) { - errorMessage = 'License endpoint not found'; + errorMessage = 'License service not available'; } else if (error.response?.status === 401) { - errorMessage = 'Unauthorized - check API key'; + errorMessage = 'Authentication required - please check API key'; } else if (error.response && error.response.status >= 500) { - errorMessage = 'License server error'; + errorMessage = 'License service temporarily unavailable'; } } @@ -100,7 +100,7 @@ export function formatAPICalls(remaining: number, total: number): string { } /** - * Get API calls status color based on usage percentage + * Get API calls status color based on usage percentage - using softer, less aggressive colors * @param remainingCalls - Remaining API calls * @param totalCalls - Total API calls limit * @returns Color string for UI components @@ -110,8 +110,8 @@ export function getAPICallsStatusColor(remainingCalls: number, totalCalls: numbe const usagePercentage = ((totalCalls - remainingCalls) / totalCalls) * 100; - if (usagePercentage >= 90) return '#ff4d4f'; // Red - Critical - if (usagePercentage >= 75) return '#faad14'; // Orange - Warning - if (usagePercentage >= 50) return '#1890ff'; // Blue - Moderate - return '#52c41a'; // Green - Good + if (usagePercentage >= 90) return '#ff7875'; // Soft red - High usage + if (usagePercentage >= 75) return '#ffc53d'; // Soft orange - Moderate usage + if (usagePercentage >= 50) return '#40a9ff'; // Soft blue - Normal usage + return '#73d13d'; // Soft green - Low usage } \ No newline at end of file From b7109c5849ff0d824c827eab1a3c6182e87034e0 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 19:56:37 +0500 Subject: [PATCH 04/13] [Fix]: antd errors for environments --- .../environments/components/ContactLowcoderModal.tsx | 4 ++-- .../setting/environments/components/EnvironmentsTable.tsx | 2 +- .../environments/components/UnlicensedEnvironmentView.tsx | 2 +- .../setting/environments/components/WorkspaceHeader.tsx | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx index 145b08e98..34ab0526f 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx @@ -100,7 +100,7 @@ const ContactLowcoderModal: React.FC = ({ width={800} centered style={{ top: 20 }} - bodyStyle={{ padding: '24px' }} + styles={{ body: { padding: '24px' } }} > {/* Environment Context Section */} = ({ background: '#fafafa', border: '1px solid #f0f0f0' }} - bodyStyle={{ padding: '16px' }} + styles={{ body: { padding: '16px' } }} > diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx index 509cb509a..2c582561c 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx @@ -112,7 +112,7 @@ const EnvironmentsTable: React.FC = ({ border: '1px solid #f0f0f0', position: 'relative' }} - bodyStyle={{ padding: '16px' }} + styles={{ body: { padding: '16px' } }} onClick={() => handleRowClick(env)} > {/* Subtle overlay for unlicensed environments */} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx index 6b61379dd..c7a0ebb9e 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx @@ -92,7 +92,7 @@ const UnlicensedEnvironmentView: React.FC = ({ background: 'white', overflow: 'hidden' }} - bodyStyle={{ padding: '48px 32px' }} + styles={{ body: { padding: '48px 32px' } }} > {/* Status Icon */}
diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/WorkspaceHeader.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/WorkspaceHeader.tsx index f4c00c22e..69f390671 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/WorkspaceHeader.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/WorkspaceHeader.tsx @@ -43,8 +43,8 @@ const HeaderWrapper = styled.div` margin-bottom: 24px; `; -const GradientBanner = styled.div<{ avatarColor: string }>` - background: linear-gradient(135deg, ${props => props.avatarColor} 0%, rgba(24, 144, 255, 0.8) 100%); +const GradientBanner = styled.div<{ $avatarColor: string }>` + background: linear-gradient(135deg, ${props => props.$avatarColor} 0%, rgba(24, 144, 255, 0.8) 100%); height: 140px; position: relative; overflow: hidden; @@ -77,7 +77,7 @@ const GradientBanner = styled.div<{ avatarColor: string }>` } &:hover { - background: linear-gradient(135deg, rgba(24, 144, 255, 0.8) 0%, ${props => props.avatarColor} 100%); + background: linear-gradient(135deg, rgba(24, 144, 255, 0.8) 0%, ${props => props.$avatarColor} 100%); transition: background 1s ease-in-out; } `; @@ -187,7 +187,7 @@ const WorkspaceHeader: React.FC = ({ return ( - + {workspace.managed ? "Managed" : "Unmanaged"} From 55ff3e55af6643a044111e712adbc79facb85ad7 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 20:07:55 +0500 Subject: [PATCH 05/13] [Fix] tabs and breadcrumbs error --- .../environments/EnvironmentDetail.tsx | 47 +++++------ .../setting/environments/WorkspaceDetail.tsx | 84 +++++++++++++------ .../components/ModernBreadcrumbs.tsx | 42 +++++----- 3 files changed, 102 insertions(+), 71 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index 041997779..08d163d14 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -34,7 +34,6 @@ import EnvironmentHeader from "./components/EnvironmentHeader"; import ModernBreadcrumbs from "./components/ModernBreadcrumbs"; import { getEnvironmentTagColor } from "./utils/environmentUtils"; import ErrorComponent from './components/ErrorComponent'; -const { TabPane } = Tabs; /** * Environment Detail Page Component @@ -140,6 +139,27 @@ const EnvironmentDetail: React.FC = () => { } ]; + const tabItems = [ + { + key: 'workspaces', + label: ( + + Workspaces + + ), + children: + }, + { + key: 'userGroups', + label: ( + + User Groups + + ), + children: + } + ]; + return (
{ onChange={setActiveTab} className="modern-tabs" type="line" - > - - Workspaces - - } - key="workspaces" - > - - - - - User Groups - - } - key="userGroups" - > - - - + items={tabItems} + /> {/* Edit Environment Modal */} {environment && ( diff --git a/client/packages/lowcoder/src/pages/setting/environments/WorkspaceDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/WorkspaceDetail.tsx index 6ed3a1427..ecdd09d25 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/WorkspaceDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/WorkspaceDetail.tsx @@ -27,15 +27,12 @@ import ModernBreadcrumbs from "./components/ModernBreadcrumbs"; import WorkspaceHeader from "./components/WorkspaceHeader"; import ErrorComponent from "./components/ErrorComponent"; -const { TabPane } = Tabs; - const WorkspaceDetail: React.FC = () => { // Use the context hooks const { environment } = useSingleEnvironmentContext(); const { workspace, isLoading, error, toggleManagedStatus } = useWorkspaceContext(); const { openDeployModal } = useDeployModal(); - const [isToggling, setIsToggling] = useState(false); // Handle toggle managed status @@ -58,7 +55,17 @@ const WorkspaceDetail: React.FC = () => { if (isLoading) { return (
- + +
+ Loading workspace details... +
+
); } @@ -98,6 +105,51 @@ const WorkspaceDetail: React.FC = () => { } ]; + const tabItems = [ + { + key: 'apps', + label: ( + + Apps + + ), + children: ( + + ) + }, + { + key: 'dataSources', + label: ( + + Data Sources + + ), + children: ( + + ) + }, + { + key: 'queries', + label: ( + + Queries + + ), + children: ( + + ) + } + ]; + return (
{ defaultActiveKey="apps" className="modern-tabs" type="line" - > - Apps} key="apps"> - - - - Data Sources} key="dataSources"> - - - Queries} key="queries"> - - - - + items={tabItems} + />
); }; diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/ModernBreadcrumbs.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/ModernBreadcrumbs.tsx index 1a3d35524..509e3fd1a 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/ModernBreadcrumbs.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/ModernBreadcrumbs.tsx @@ -2,7 +2,7 @@ import React, { ReactNode } from 'react'; import { Breadcrumb } from 'antd'; import { BreadcrumbProps } from 'antd/lib/breadcrumb'; -interface ModernBreadcrumbsProps extends BreadcrumbProps { +interface ModernBreadcrumbsProps extends Omit { /** * Items to display in the breadcrumb */ @@ -17,6 +17,25 @@ interface ModernBreadcrumbsProps extends BreadcrumbProps { * Modern styled breadcrumb component with consistent styling */ const ModernBreadcrumbs: React.FC = ({ items = [], ...props }) => { + // Convert custom items format to Antd's expected format + const breadcrumbItems = items.map(item => ({ + key: item.key, + title: item.onClick ? ( + e.currentTarget.style.textDecoration = 'underline'} + onMouseLeave={(e) => e.currentTarget.style.textDecoration = 'none'} + > + {item.title} + + ) : ( + + {item.title} + + ) + })); + return (
= ({ items = [], ...pr display: 'flex', alignItems: 'center' }}> - - {items.map(item => ( - - {item.onClick ? ( - e.currentTarget.style.textDecoration = 'underline'} - onMouseLeave={(e) => e.currentTarget.style.textDecoration = 'none'} - > - {item.title} - - ) : ( - - {item.title} - - )} - - ))} - +
); }; From 880a4fbcc7945adb09d0382826a36677f65ef498 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 20:33:51 +0500 Subject: [PATCH 06/13] [FIx]: improve UI for environments --- .../environments/EnvironmentDetail.tsx | 100 ++++++++++----- .../setting/environments/EnvironmentsList.tsx | 114 ++++++------------ .../components/EnvironmentHeader.tsx | 47 +++++--- .../components/ModernBreadcrumbs.tsx | 34 ++++-- .../environments/components/StatsCard.tsx | 74 ++++++++++++ 5 files changed, 232 insertions(+), 137 deletions(-) create mode 100644 client/packages/lowcoder/src/pages/setting/environments/components/StatsCard.tsx diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index 08d163d14..945b86424 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -10,6 +10,8 @@ import { Button, Tag, Result, + Row, + Col, } from "antd"; import { LinkOutlined, @@ -21,6 +23,9 @@ import { CloseCircleOutlined, ExclamationCircleOutlined, SyncOutlined, + CloudServerOutlined, + UserOutlined, + SafetyOutlined, } from "@ant-design/icons"; import { useSingleEnvironmentContext } from "./context/SingleEnvironmentContext"; @@ -31,9 +36,11 @@ 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 ErrorComponent from './components/ErrorComponent'; +import { Level1SettingPageContent } from "../styled"; /** * Environment Detail Page Component @@ -123,19 +130,31 @@ const EnvironmentDetail: React.FC = () => { ); } - const breadcrumbItems = [ + // Stats data for the cards + const statsData = [ { - key: 'environments', - title: ( - - Environments - - ), - onClick: () => history.push("/setting/environments") + title: "Type", + value: environment.environmentType || "Unknown", + icon: , + color: getEnvironmentTagColor(environment.environmentType) + }, + { + title: "Status", + value: environment.isLicensed ? "Licensed" : "Unlicensed", + icon: environment.isLicensed ? : , + color: environment.isLicensed ? "#52c41a" : "#ff4d4f" + }, + { + title: "API Key", + value: environment.environmentApikey ? "Configured" : "Not Set", + icon: , + color: environment.environmentApikey ? "#1890ff" : "#faad14" }, { - key: 'currentEnvironment', - title: environment.environmentName + title: "Master Env", + value: environment.isMaster ? "Yes" : "No", + icon: , + color: environment.isMaster ? "#722ed1" : "#8c8c8c" } ]; @@ -161,16 +180,30 @@ const EnvironmentDetail: React.FC = () => { ]; return ( -
+ + {/* Breadcrumbs */} + + {/* Environment Header Component */} + {/* Stats Cards Row */} + + {statsData.map((stat, index) => ( + + + + ))} + + {/* Basic Environment Information Card */} { "No domain set" )} - - - {environment.environmentType} - + + + {environment.environmentId} + {(() => { @@ -224,21 +254,25 @@ const EnvironmentDetail: React.FC = () => { } })()} - - {environment.environmentApikey ? ( - Configured - ) : ( - Not Configured - )} - - - {environment.isMaster ? "Yes" : "No"} + + {environment.createdAt ? new Date(environment.createdAt).toLocaleDateString() : "Unknown"} - {/* Modern Breadcrumbs navigation */} - + history.push('/setting/environments') + }, + { + key: 'current', + title: environment.environmentName || "Environment Detail" + } + ]} + /> {/* Tabs for Workspaces and User Groups */} { loading={isUpdating} /> )} -
+ ); }; diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx index 7b041b81f..36be33166 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { Alert, Empty, Spin, Card } from "antd"; +import { Alert, Empty, Spin, Card, Row, Col } from "antd"; import { SyncOutlined, CloudServerOutlined } from "@ant-design/icons"; import { AddIcon, Search, TacoButton } from "lowcoder-design"; import { useHistory } from "react-router-dom"; @@ -9,6 +9,7 @@ import { fetchEnvironments } from "redux/reduxActions/enterpriseActions"; import { Environment } from "./types/environment.types"; import EnvironmentsTable from "./components/EnvironmentsTable"; import CreateEnvironmentModal from "./components/CreateEnvironmentModal"; +import StatsCard from "./components/StatsCard"; import { buildEnvironmentId } from "@lowcoder-ee/constants/routesURL"; import { createEnvironment } from "./services/environments.service"; import { getEnvironmentTagColor } from "./utils/environmentUtils"; @@ -107,37 +108,6 @@ const EnvironmentsList: React.FC = () => { return ; }; - // Stat card component - const StatCard = ({ title, value, color }: { title: string; value: number; color: string }) => ( - -
-
-
{title}
-
{value}
-
-
- {getEnvironmentIcon(title)} -
-
-
- ); - // Filter environments based on search text const filteredEnvironments = environments.filter((env) => { const searchLower = searchText.toLowerCase(); @@ -201,75 +171,65 @@ const EnvironmentsList: React.FC = () => { > Refresh - setIsCreateModalVisible(true)}> - New Environment + } + onClick={() => setIsCreateModalVisible(true)} + > + Add Environment - {/* Environment Type Statistics */} - {!isLoading && environments.length > 0 && ( - -
- {environmentStats.map(([type, count]) => ( -
- -
- ))} -
-
- )} + {/* Environment Statistics Cards */} + + + {environmentStats.map(([type, count]) => ( + + + + ))} + + - {/* Error handling */} {error && ( )} - {/* Loading, empty state or table */} - {isLoading ? ( -
- -
- ) : environments.length === 0 && !error ? ( - - ) : filteredEnvironments.length === 0 ? ( - - ) : ( - /* Table component */ + )} + + {(filteredEnvironments.length > 0 || isLoading) && ( )} - - {/* Results counter when searching */} - {searchText && filteredEnvironments.length !== environments.length && ( -
- Showing {filteredEnvironments.length} of {environments.length} environments -
- )}
- {/* Create Environment Modal */} setIsCreateModalVisible(false)} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx index 0a999129e..43ecb5fc0 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Button, Tag, Typography, Row, Col } from 'antd'; import { EditOutlined, CloudServerOutlined } from '@ant-design/icons'; import { Environment } from '../types/environment.types'; -import { getEnvironmentTagColor, getEnvironmentHeaderGradient } from '../utils/environmentUtils'; +import { getEnvironmentTagColor } from '../utils/environmentUtils'; const { Title, Text } = Typography; @@ -24,11 +24,11 @@ const EnvironmentHeader: React.FC = ({ className="environment-header" style={{ marginBottom: "24px", - background: getEnvironmentHeaderGradient(environment.environmentType), + background: '#fff', padding: '20px 24px', borderRadius: '8px', - color: 'white', - boxShadow: '0 2px 8px rgba(0,0,0,0.1)' + border: '1px solid #f0f0f0', + boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }} > @@ -36,35 +36,50 @@ const EnvironmentHeader: React.FC = ({
- + <Title level={3} style={{ margin: '0 0 8px 0', color: '#222222', fontWeight: '500' }}> {environment.environmentName || "Unnamed Environment"}
- + ID: {environment.environmentId} {environment.environmentType} {environment.isMaster && ( - + Master )} + {environment.isLicensed === false && ( + + Unlicensed + + )}
@@ -73,14 +88,10 @@ const EnvironmentHeader: React.FC = ({ + +
+ + +
); }; From 5b542764e2f676c28c21400f5b64ed3b8e5bb4a5 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 21:37:34 +0500 Subject: [PATCH 09/13] [Fix]: query deployment param --- .../setting/environments/config/query.config.tsx | 7 +++++++ .../setting/environments/config/workspace.config.tsx | 11 ++--------- .../setting/environments/services/query.service.ts | 4 +++- .../environments/services/workspace.service.ts | 3 --- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx index 35189c8c9..4d4d5e588 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx @@ -17,6 +17,12 @@ export const queryConfig: DeployableItemConfig = { label: 'Update Dependencies If Needed', type: 'checkbox', defaultValue: false + }, + { + name: 'deployCredential', + label: 'Overwrite Credentials', + type: 'checkbox', + defaultValue: false } ], prepareParams: (item: Query, values: any, sourceEnv: Environment, targetEnv: Environment) => { @@ -26,6 +32,7 @@ export const queryConfig: DeployableItemConfig = { queryId: item.id, updateDependenciesIfNeeded: values.updateDependenciesIfNeeded, queryGid: item.gid, + deployCredential: values.deployCredential ?? false }; }, execute: (params: any) => deployQuery(params) diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx index 6689931f9..b0549ba0d 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx @@ -5,20 +5,13 @@ import { Environment } from '../types/environment.types'; import { deployWorkspace } from '../services/workspace.service'; import { Workspace } from '../types/workspace.types'; - - export const workspaceConfig: DeployableItemConfig = { // Deploy configuration deploy: { singularLabel: 'Workspace', fields: [ - { - name: 'deployCredential', - label: 'Overwrite Credentials', - type: 'checkbox', - defaultValue: false - } + // Removed deployCredential field as workspaces don't need credential overwrite ], prepareParams: (item: Workspace, values: any, sourceEnv: Environment, targetEnv: Environment) => { if (!item.gid) { @@ -30,7 +23,7 @@ export const workspaceConfig: DeployableItemConfig = { envId: sourceEnv.environmentId, targetEnvId: targetEnv.environmentId, workspaceId: item.gid, - deployCredential: values.deployCredential ?? false + // Removed deployCredential parameter }; }, execute: (params: any) => deployWorkspace(params) diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts index 4cf7a29be..d22887931 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts @@ -16,6 +16,7 @@ export interface MergedQueriesResult { queryId: string; updateDependenciesIfNeeded?: boolean; queryGid: string; + deployCredential: boolean; } @@ -71,7 +72,8 @@ export interface MergedQueriesResult { envId: params.envId, targetEnvId: params.targetEnvId, queryId: params.queryId, - updateDependenciesIfNeeded: params.updateDependenciesIfNeeded ?? false + updateDependenciesIfNeeded: params.updateDependenciesIfNeeded ?? false, + deployCredential: params.deployCredential } }); if (response.status === 200) { diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts index dec7c7cf7..b7cf4a37c 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts @@ -84,7 +84,6 @@ export async function deployWorkspace(params: { envId: string; targetEnvId: string; workspaceId: string; - deployCredential: boolean; // Mandatory parameter }): Promise { try { // Use the new endpoint format with only essential parameters @@ -93,7 +92,6 @@ export async function deployWorkspace(params: { orgGid: params.workspaceId, // Using workspaceId as orgGid envId: params.envId, targetEnvId: params.targetEnvId, - deployCredential: params.deployCredential } }); @@ -107,7 +105,6 @@ export async function deployWorkspace(params: { ); } - return response.status === 200; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Failed to deploy workspace'; From e54c63fa377b8fcb9f0c332fa6f80b238b4612d3 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 21:49:48 +0500 Subject: [PATCH 10/13] [Fix] remove updated dependenceis need for DS and QL --- .../environments/config/data-sources.config.tsx | 9 --------- .../pages/setting/environments/config/query.config.tsx | 10 ---------- .../environments/services/datasources.service.ts | 2 -- .../setting/environments/services/query.service.ts | 2 -- 4 files changed, 23 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx index 591621862..ce802e8de 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx @@ -5,18 +5,10 @@ import { DataSource} from '../types/datasource.types'; import { Environment } from '../types/environment.types'; import { deployDataSource, DataSourceStats } from '../services/datasources.service'; - - export const dataSourcesConfig: DeployableItemConfig = { deploy: { singularLabel: 'Data Source', fields: [ - { - name: 'updateDependenciesIfNeeded', - label: 'Update Dependencies If Needed', - type: 'checkbox', - defaultValue: false - }, { name: 'deployCredential', label: 'Overwrite Credentials', @@ -29,7 +21,6 @@ export const dataSourcesConfig: DeployableItemConfig = { envId: sourceEnv.environmentId, targetEnvId: targetEnv.environmentId, datasourceId: item.id, - updateDependenciesIfNeeded: values.updateDependenciesIfNeeded, datasourceGid: item.gid, deployCredential: values.deployCredential ?? false }; diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx index 4d4d5e588..7495e5371 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx @@ -4,20 +4,11 @@ import { Query } from '../types/query.types'; import { deployQuery } from '../services/query.service'; import { Environment } from '../types/environment.types'; - - - export const queryConfig: DeployableItemConfig = { deploy: { singularLabel: 'Query', fields: [ - { - name: 'updateDependenciesIfNeeded', - label: 'Update Dependencies If Needed', - type: 'checkbox', - defaultValue: false - }, { name: 'deployCredential', label: 'Overwrite Credentials', @@ -30,7 +21,6 @@ export const queryConfig: DeployableItemConfig = { envId: sourceEnv.environmentId, targetEnvId: targetEnv.environmentId, queryId: item.id, - updateDependenciesIfNeeded: values.updateDependenciesIfNeeded, queryGid: item.gid, deployCredential: values.deployCredential ?? false }; diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts index e743179b0..2fc492028 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts @@ -21,7 +21,6 @@ export interface DeployDataSourceParams { targetEnvId: string; datasourceId: string; datasourceGid: string; - updateDependenciesIfNeeded?: boolean; deployCredential: boolean; } // Get data sources for a workspace - using your correct implementation @@ -158,7 +157,6 @@ export async function deployDataSource(params: DeployDataSourceParams): Promise< envId: params.envId, targetEnvId: params.targetEnvId, datasourceId: params.datasourceId, - updateDependenciesIfNeeded: params.updateDependenciesIfNeeded ?? false, deployCredential: params.deployCredential } }); diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts index d22887931..20b79f4ee 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts @@ -14,7 +14,6 @@ export interface MergedQueriesResult { envId: string; targetEnvId: string; queryId: string; - updateDependenciesIfNeeded?: boolean; queryGid: string; deployCredential: boolean; } @@ -72,7 +71,6 @@ export interface MergedQueriesResult { envId: params.envId, targetEnvId: params.targetEnvId, queryId: params.queryId, - updateDependenciesIfNeeded: params.updateDependenciesIfNeeded ?? false, deployCredential: params.deployCredential } }); From 2714ddefc67d752d27fbf9bc90cf1668b5d8a57a Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 21:58:17 +0500 Subject: [PATCH 11/13] [Fix] unlicensed environment page UI --- .../components/UnlicensedEnvironmentView.tsx | 235 ++++++++++-------- 1 file changed, 134 insertions(+), 101 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx index c7a0ebb9e..7967ce161 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/UnlicensedEnvironmentView.tsx @@ -6,10 +6,15 @@ import { ArrowLeftOutlined, CloseCircleOutlined, ExclamationCircleOutlined, - WarningOutlined + WarningOutlined, + CloudServerOutlined } from '@ant-design/icons'; import { Environment } from '../types/environment.types'; import ContactLowcoderModal from './ContactLowcoderModal'; +import ModernBreadcrumbs from './ModernBreadcrumbs'; +import EnvironmentHeader from './EnvironmentHeader'; +import StatsCard from './StatsCard'; +import { Level1SettingPageContent } from "../../styled"; import history from "@lowcoder-ee/util/history"; const { Title, Text } = Typography; @@ -20,7 +25,7 @@ interface UnlicensedEnvironmentViewProps { } /** - * Modern UI for unlicensed environments + * Consistent UI for unlicensed environments matching other environment pages */ const UnlicensedEnvironmentView: React.FC = ({ environment, @@ -65,84 +70,110 @@ const UnlicensedEnvironmentView: React.FC = ({ } }; + // Stats data consistent with other environment pages + const statsData = [ + { + title: "Type", + value: environment.environmentType || "Unknown", + icon: , + color: "#1890ff" + }, + { + title: "Status", + value: "Unlicensed", + icon: , + color: "#ff4d4f" + }, + { + title: "Master Env", + value: environment.isMaster ? "Yes" : "No", + icon: , + color: environment.isMaster ? "#722ed1" : "#8c8c8c" + }, + { + title: "License Issue", + value: environment.licenseStatus === 'error' ? "Error" : "Missing", + icon: environment.licenseStatus === 'error' ? : , + color: environment.licenseStatus === 'error' ? "#faad14" : "#ff4d4f" + } + ]; + return ( -
- - -
- {/* Main Status Card */} - + + {/* Environment Header Component */} + + + {/* Stats Cards Row */} + + {statsData.map((stat, index) => ( + + + + ))} + + + {/* Breadcrumbs */} + history.push('/setting/environments') + }, + { + key: 'current', + title: environment.environmentName || "Environment Detail" + } + ]} + /> + + {/* License Issue Card */} + + + +
{/* Status Icon */}
{getLicenseIcon()}
- {/* Environment Info */} -
- - {getLicenseTitle()} - - - {getLicenseDescription()} - - - {/* Environment Details */} -
- Environment: - - {environment.environmentName || 'Unnamed Environment'} - - - ID: {environment.environmentId} - -
-
+ {/* License Issue Information */} + + {getLicenseTitle()} + + + {getLicenseDescription()} + {/* Action Buttons */} - + - - - {/* Footer Help Text */} - - Need assistance? Contact our team for licensing support or edit the environment configuration to resolve this issue. - -
- -
+
+ +
+ + + {/* Help Text */} + + + Need assistance? Contact our team for licensing support or edit the environment configuration to resolve this issue. + + {/* Contact Lowcoder Modal */} = ({ onClose={() => setIsContactModalVisible(false)} environment={environment} /> -
+ ); }; From 540af6f23b6115fb6a53ed8724ff03057f9f8245 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Thu, 29 May 2025 23:12:47 +0500 Subject: [PATCH 12/13] change progressbar direction --- .../src/pages/setting/environments/EnvironmentDetail.tsx | 2 +- .../pages/setting/environments/components/EnvironmentsTable.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index 688544ca6..d8cc31eb1 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -319,7 +319,7 @@ const EnvironmentDetail: React.FC = () => { />
= ({
Date: Fri, 30 May 2025 00:05:58 +0500 Subject: [PATCH 13/13] [Fix] antD deprecated properties --- .../src/pages/setting/environments/EnvironmentDetail.tsx | 8 ++++---- .../setting/environments/components/EnvironmentsTable.tsx | 1 - .../setting/environments/config/workspace.config.tsx | 2 -- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index d8cc31eb1..245e12971 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -300,7 +300,7 @@ const EnvironmentDetail: React.FC = () => { { { { border: '1px solid #f0f0f0', borderRadius: '6px' }} - bodyStyle={{ padding: '12px' }} + styles={{ body: { padding: '12px' } }} >
diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx index a58a3434c..2336c8d5d 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx @@ -287,7 +287,6 @@ const EnvironmentsTable: React.FC = ({ )} size="small" showInfo={false} - strokeWidth={4} />
deployWorkspace(params)