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) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy