Skip to content

Consistent UI for the Environments #1718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update Environments UI
  • Loading branch information
iamfaran committed May 28, 2025
commit d2d7ede5f9be4b1d59325f99cf656fae5dcecad1
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ const EnvironmentDetail: React.FC = () => {

if (isLoading) {
return (
<div style={{ display: 'flex', justifyContent: 'center', padding: '50px' }}>
<Spin size="large" tip="Loading environment..." style={{ display: 'block', textAlign: 'center' }} />
<div style={{ display: 'flex', justifyContent: 'center', padding: '60px 0' }}>
<Spin size="large" />
</div>
);
}
Expand Down Expand Up @@ -151,19 +151,21 @@ const EnvironmentDetail: React.FC = () => {
onEditClick={handleEditClick}
/>



{/* Basic Environment Information Card - improved responsiveness */}
{/* Basic Environment Information Card */}
<Card
title="Environment Overview"
style={{ marginBottom: "24px", borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,0.05)' }}
style={{
marginBottom: "24px",
borderRadius: '4px',
border: '1px solid #f0f0f0'
}}
className="environment-overview-card"
>
<Descriptions
bordered
layout="vertical" // Change to vertical layout on smaller screens
layout="vertical"
column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }}
size="small" // Use smaller size on mobile
size="small"
>
<Descriptions.Item label="Domain">
{environment.environmentFrontendUrl ? (
Expand All @@ -181,7 +183,7 @@ const EnvironmentDetail: React.FC = () => {
<Descriptions.Item label="Environment Type">
<Tag
color={getEnvironmentTagColor(environment.environmentType)}
style={{ borderRadius: '12px' }}
style={{ borderRadius: '4px' }}
>
{environment.environmentType}
</Tag>
Expand All @@ -190,23 +192,23 @@ const EnvironmentDetail: React.FC = () => {
{(() => {
switch (environment.licenseStatus) {
case 'checking':
return <Tag icon={<SyncOutlined spin />} color="blue" style={{ borderRadius: '12px' }}>Checking...</Tag>;
return <Tag icon={<SyncOutlined spin />} color="blue" style={{ borderRadius: '4px' }}>Checking...</Tag>;
case 'licensed':
return <Tag icon={<CheckCircleOutlined />} color="green" style={{ borderRadius: '12px' }}>Licensed</Tag>;
return <Tag icon={<CheckCircleOutlined />} color="green" style={{ borderRadius: '4px' }}>Licensed</Tag>;
case 'unlicensed':
return <Tag icon={<CloseCircleOutlined />} color="red" style={{ borderRadius: '12px' }}>Not Licensed</Tag>;
return <Tag icon={<CloseCircleOutlined />} color="red" style={{ borderRadius: '4px' }}>Not Licensed</Tag>;
case 'error':
return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '12px' }}>License Error</Tag>;
return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '4px' }}>License Error</Tag>;
default:
return <Tag color="default" style={{ borderRadius: '12px' }}>Unknown</Tag>;
return <Tag color="default" style={{ borderRadius: '4px' }}>Unknown</Tag>;
}
})()}
</Descriptions.Item>
<Descriptions.Item label="API Key Status">
{environment.environmentApikey ? (
<Tag color="green" style={{ borderRadius: '12px' }}>Configured</Tag>
<Tag color="green" style={{ borderRadius: '4px' }}>Configured</Tag>
) : (
<Tag color="red" style={{ borderRadius: '12px' }}>Not Configured</Tag>
<Tag color="red" style={{ borderRadius: '4px' }}>Not Configured</Tag>
)}
</Descriptions.Item>
<Descriptions.Item label="Master Environment">
Expand All @@ -217,13 +219,20 @@ const EnvironmentDetail: React.FC = () => {

{/* Modern Breadcrumbs navigation */}
<ModernBreadcrumbs items={breadcrumbItems} />

{/* Tabs for Workspaces and User Groups */}
<Tabs
defaultActiveKey="workspaces"
activeKey={activeTab}
onChange={setActiveTab}
className="modern-tabs"
type="card"
type="line"
style={{
background: '#fff',
borderRadius: '4px',
border: '1px solid #f0f0f0',
padding: '0'
}}
>
<TabPane
tab={
Expand All @@ -233,7 +242,6 @@ const EnvironmentDetail: React.FC = () => {
}
key="workspaces"
>
{/* Using our new standalone WorkspacesTab component */}
<WorkspacesTab environment={environment} />
</TabPane>

Expand All @@ -245,7 +253,6 @@ const EnvironmentDetail: React.FC = () => {
}
key="userGroups"
>
{/* Now using our standalone UserGroupsTab component */}
<UserGroupsTab environment={environment} />
</TabPane>
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { Alert, Empty, Spin } from "antd";
import { SyncOutlined } from "@ant-design/icons";
import { Alert, Empty, Spin, Row, Col, Card } from "antd";
import { SyncOutlined, CloudServerOutlined } from "@ant-design/icons";
import { AddIcon, Search, TacoButton } from "lowcoder-design";
import { useHistory } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
Expand All @@ -11,6 +11,7 @@ import EnvironmentsTable from "./components/EnvironmentsTable";
import CreateEnvironmentModal from "./components/CreateEnvironmentModal";
import { buildEnvironmentId } from "@lowcoder-ee/constants/routesURL";
import { createEnvironment } from "./services/environments.service";
import { getEnvironmentTagColor } from "./utils/environmentUtils";
import styled from "styled-components";

const EnvironmentsWrapper = styled.div`
Expand Down Expand Up @@ -54,6 +55,10 @@ const BodyWrapper = styled.div`
padding: 0 24px;
`;

const StatsWrapper = styled.div`
margin-bottom: 20px;
`;

/**
* Environment Listing Page Component
* Displays a table of environments
Expand All @@ -73,6 +78,65 @@ const EnvironmentsList: React.FC = () => {
// Hook for navigation
const history = useHistory();

// Calculate environment type statistics
const environmentStats = React.useMemo(() => {
const stats = environments.reduce((acc, env) => {
const type = env.environmentType.toUpperCase();
acc[type] = (acc[type] || 0) + 1;
return acc;
}, {} as Record<string, number>);

// Sort by common environment types first
const typeOrder = ['PROD', 'PREPROD', 'TEST', 'DEV'];
const sortedStats = Object.entries(stats).sort(([a], [b]) => {
const aIndex = typeOrder.indexOf(a);
const bIndex = typeOrder.indexOf(b);

if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
if (aIndex !== -1) return -1;
if (bIndex !== -1) return 1;
return a.localeCompare(b);
});

return sortedStats;
}, [environments]);

// Get icon for environment type
const getEnvironmentIcon = (type: string) => {
return <CloudServerOutlined />;
};

// Stat card component
const StatCard = ({ title, value, color }: { title: string; value: number; color: string }) => (
<Card
style={{
height: '100%',
borderRadius: '4px',
border: '1px solid #f0f0f0'
}}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div>
<div style={{ fontSize: '13px', color: '#8c8c8c', marginBottom: '8px' }}>{title}</div>
<div style={{ fontSize: '20px', fontWeight: 500 }}>{value}</div>
</div>
<div style={{
fontSize: '24px',
opacity: 0.8,
color: color,
padding: '8px',
backgroundColor: `${color}15`,
borderRadius: '4px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
{getEnvironmentIcon(title)}
</div>
</div>
</Card>
);

// Filter environments based on search text
const filteredEnvironments = environments.filter((env) => {
const searchLower = searchText.toLowerCase();
Expand Down Expand Up @@ -133,7 +197,6 @@ const EnvironmentsList: React.FC = () => {
buttonType="normal"
icon={<SyncOutlined spin={isLoading} />}
onClick={handleRefresh}
loading={isLoading}
>
Refresh
</RefreshBtn>
Expand All @@ -143,6 +206,23 @@ const EnvironmentsList: React.FC = () => {
</HeaderWrapper>

<BodyWrapper>
{/* Environment Type Statistics */}
{!isLoading && environments.length > 0 && (
<StatsWrapper>
<Row gutter={[16, 16]} style={{ marginBottom: '20px' }}>
{environmentStats.map(([type, count]) => (
<Col xs={24} sm={12} md={8} lg={6} key={type}>
<StatCard
title={type}
value={count}
color={getEnvironmentTagColor(type.toLowerCase())}
/>
</Col>
))}
</Row>
</StatsWrapper>
)}

{/* Error handling */}
{error && (
<Alert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,17 @@ const WorkspaceDetail: React.FC = () => {
<ModernBreadcrumbs items={breadcrumbItems} />

{/* Tabs for Apps, Data Sources, and Queries */}
<Tabs defaultActiveKey="apps" className="modern-tabs" type="card">
<Tabs
defaultActiveKey="apps"
className="modern-tabs"
type="line"
style={{
background: '#fff',
borderRadius: '4px',
border: '1px solid #f0f0f0',
padding: '0'
}}
>
<TabPane tab={<span><AppstoreOutlined /> Apps</span>} key="apps">
<AppsTab
environment={environment}
Expand Down
Loading