Skip to content

Commit bf0cfab

Browse files
authored
Merge branch 'dev' into environments-translations
2 parents bbc0828 + c8aff04 commit bf0cfab

File tree

12 files changed

+586
-99
lines changed

12 files changed

+586
-99
lines changed

client/packages/lowcoder/src/comps/comps/iconComp.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useRef, useState } from "react";
1+
import { useEffect, useMemo, useRef, useState } from "react";
22
import styled, { css } from "styled-components";
33
import { RecordConstructorToView } from "lowcoder-core";
44
import { styleControl } from "comps/controls/styleControl";
@@ -34,8 +34,10 @@ import { AssetType, IconscoutControl } from "@lowcoder-ee/comps/controls/iconsco
3434
import { dropdownControl } from "../controls/dropdownControl";
3535

3636
const Container = styled.div<{
37+
$sourceMode: string;
3738
$style: IconStyleType | undefined;
38-
$animationStyle:AnimationStyleType}>`
39+
$animationStyle:AnimationStyleType;
40+
}>`
3941
display: flex;
4042
align-items: center;
4143
justify-content: center;
@@ -59,6 +61,15 @@ const Container = styled.div<{
5961
pointer-events: auto;
6062
}
6163
`}
64+
${(props) => props.$sourceMode === 'asset-library' && `
65+
img {
66+
max-width: 100%;
67+
max-height: 100%;
68+
width: 100%;
69+
height: 100%;
70+
object-fit: contain;
71+
}
72+
`}
6273
`;
6374

6475
const EventOptions = [clickEvent] as const;
@@ -101,17 +112,28 @@ const IconView = (props: RecordConstructorToView<typeof childrenMap>) => {
101112
onResize,
102113
});
103114

115+
const style = useMemo(() => {
116+
if (props.sourceMode === 'standard') {
117+
return {
118+
fontSize: props.autoHeight
119+
? `${height < width ? height : width}px`
120+
: props.iconSize,
121+
background: props.style.background,
122+
}
123+
}
124+
return {
125+
width: props.autoHeight ? '' : props.iconSize,
126+
background: props.style.background,
127+
}
128+
}, [width, height, props.autoHeight, props.iconSize, props.sourceMode, props.style.background]);
129+
104130
return (
105131
<Container
106132
ref={conRef}
107133
$style={props.style}
134+
$sourceMode={props.sourceMode}
108135
$animationStyle={props.animationStyle}
109-
style={{
110-
fontSize: props.autoHeight
111-
? `${height < width ? height : width}px`
112-
: props.iconSize,
113-
background: props.style.background,
114-
}}
136+
style={style}
115137
onClick={() => props.onEvent("click")}
116138
>
117139
{ props.sourceMode === 'standard'

client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,7 +2484,7 @@ export const en = {
24842484
"GrantUpdateDeletePermission": "Grant or update permissions",
24852485
"LibraryQueryActions": "Create / Update / Delete library queries",
24862486
"PublishLibraryQuery": "Publish library query",
2487-
"AuditLogsPreviewTitle": "Preview the Audit Log in action",
2487+
"AuditLogsPreviewTitle": "Preview the Audit Log in action (click to zoom)",
24882488
"ScreenshotPlaceholder1": "[ Screenshot 1 Placeholder ]",
24892489
"ScreenshotPlaceholder2": "[ Screenshot 2 Placeholder ]",
24902490
"ScreenshotPlaceholder3": "[ Screenshot 3 Placeholder ]",
@@ -2514,7 +2514,7 @@ export const en = {
25142514
"MetricDevices": "Access by device (desktop, tablet, mobile)",
25152515
"MetricBrowsers": "Access by browser and OS",
25162516
"MetricCountries": "Geographic origin of users",
2517-
"AppUsageScreenshotsTitle": "App Usage Analytics in action",
2517+
"AppUsageScreenshotsTitle": "App Usage Analytics in action (click to zoom)",
25182518
"AppUsageScreenshot1": "[ App Usage Dashboard Screenshot ]",
25192519
"AppUsageScreenshot2": "[ Per-App Views Chart ]",
25202520
"AppUsageScreenshot3": "[ Geo Distribution Map ]",
@@ -2538,20 +2538,23 @@ export const en = {
25382538
"EnvironmentsIntro1": "Lowcoder Environments allow you to separate your Dev, Test, and Prod stages cleanly and safely.",
25392539
"EnvironmentsIntro2": "Enterprise teams benefit from structured release workflows, approval processes, and version stability across stages.",
25402540
"EnvironmentsIntro3": "With the Environments feature, admins can control what gets deployed, when, and where — all from a single interface.",
2541+
"EnvironmentsIntro4" : "Lowcoder includes multiple object types like Workspaces, Data Sources, Data Queries, and Apps. Since many of these objects are interconnected (e.g. a Data Source can be shared across multiple Apps), a pure Git-based export would not capture all dependencies consistently. Instead, Lowcoder offers a selective, integrated deployment mechanism directly within the UI. Apps, data sources, and queries can be selectively managed and deployed across environments. Managed objects ensure safe, controlled staging and production releases.",
25412542
"yourDeploymentID" : "Your Deployment ID",
2542-
"EnvironmentsFeaturePreviewTitle" : "Environments & Deployment in action",
2543+
"EnvironmentsFeaturePreviewTitle" : "Environments & Deployment in action (click to zoom)",
25432544

2544-
"EnvironmentsUseCasesTitle": "Why Use Environments?",
2545+
"EnvironmentsUseCasesTitle": "Why Use Environments? (Staging)",
25452546
"EnvironmentsUseCase1": "Prevent unintended changes in production by testing apps in dedicated Dev or QA environments.",
25462547
"EnvironmentsUseCase2": "Align with corporate IT governance by implementing staged deployments with audit-ready tracking.",
25472548
"EnvironmentsUseCase3": "Empower teams to build confidently with environment-specific configurations, data, and integrations.",
25482549

25492550
"EnvironmentsFeaturesTitle": "What You Get",
25502551
"EnvironmentsFeature1": "Centralized dashboard to view and manage all Lowcoder environments.",
2551-
"EnvironmentsFeature2": "Deployment of applications, data sources, and configurations between environments, directly from the UI.",
2552+
"EnvironmentsFeature2": "Deployment of applications, data sources, and configurations between environments, directly from the UI without the need for Additional CI/CD tools.",
25522553
"EnvironmentsFeature3": "Environment-specific access controls and visibility rules.",
25532554
"EnvironmentsFeature5": "Clear separation of concerns for staging, sandbox, and production operations.",
2554-
2555+
"apiUsage" : "API Calls.",
2556+
"loadingApiUsage" : "Loading API usage data..."
2557+
},
25552558
// Environments page translations
25562559
"environments": {
25572560
"title": "Environments",
@@ -3024,6 +3027,18 @@ export const en = {
30243027
"fetchInvoices": "Error fetching invoices."
30253028
},
30263029

3030+
"auditLog": {
3031+
"title": "Audit Log Detail",
3032+
"geoLocation": "Geo Location",
3033+
"browserData": "Browser / System Metadata",
3034+
"browser": "Browser",
3035+
"OS": "OS",
3036+
"device": "Device",
3037+
"deviceType": "Device Type",
3038+
"engine": "Engine",
3039+
"webview": "Webview",
3040+
"eventDetail": "Event Detail"
3041+
},
30273042

30283043
// thirteenth part
30293044

@@ -3535,7 +3550,8 @@ export const en = {
35353550
"whatsNewLinkHelp": "Provide a valid URL that users can visit for your news.",
35363551
"deleteBranding": "Delete Branding",
35373552
"deleteBrandingContent": "Are you sure you want to delete \"{orgName}\" branding?",
3538-
"fetchBrandingError": "Something went wrong while fetching branding details. Please try again."
3553+
"fetchBrandingError": "Something went wrong while fetching branding details. Please try again.",
3554+
"upload": "Upload"
35393555
},
35403556
"networkMessage": {
35413557
"200": "Success",

client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ export function AdvancedSetting() {
326326
<div className="section-title">{trans("advanced.APIConsumption")}</div>
327327
<HelpText style={{ marginBottom: 12 }}>{trans("advanced.APIConsumptionDescription")}</HelpText>
328328
<div className="section-content">
329-
{trans("advanced.overallAPIConsumption")} : {apiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(apiUsage) + " API Calls.": 'Loading API usage data...'}<br/>
330-
{trans("advanced.lastMonthAPIConsumption")} : {lastMonthApiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(lastMonthApiUsage) + " API Calls." : 'Loading API usage data...'}
329+
{trans("advanced.overallAPIConsumption")} : {apiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(apiUsage) + " " + trans("enterprise.apiUsage") : trans("enterprise.loadingApiUsage")}<br/>
330+
{trans("advanced.lastMonthAPIConsumption")} : {lastMonthApiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(lastMonthApiUsage) + " " + trans("enterprise.apiUsage") : trans("enterprise.loadingApiUsage")}
331331
</div>
332332
</AdvancedSettingContent>
333333
</Level1SettingPageContent>

client/packages/lowcoder/src/pages/setting/appUsage/dashboard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ export function AppUsageDashboard() {
363363
<DetailContainer>
364364
<Header>
365365
<Level1SettingPageTitle style={{marginBottom: 0}}>
366-
<span>{"App Usage Logs"}</span>
366+
<span>{trans("settings.appUsage")}</span>
367367
</Level1SettingPageTitle>
368368
</Header>
369369

@@ -470,6 +470,7 @@ export function AppUsageDashboard() {
470470
) : currentPageLogs.length > 0 ? (
471471
<div style={{ overflowX: "auto", width: "100%" }}>
472472
<Table
473+
rowKey={"id"}
473474
columns={columns}
474475
dataSource={topApps}
475476
size="small" // Compact Layout

client/packages/lowcoder/src/pages/setting/appUsage/index.tsx

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@ import { APP_USAGE_DASHBOARD, APP_USAGE_DETAIL } from "@lowcoder-ee/constants/ro
22
import { Route, Switch } from "react-router-dom";
33
import { AppUsageDashboard } from "./dashboard";
44
import { AppUsageDetail } from "./detail";
5-
import { useSelector } from "react-redux";
5+
import { useSelector, useDispatch } from "react-redux";
66
import { selectIsLicenseActive } from "redux/selectors/enterpriseSelectors";
77
import styled from "styled-components";
8-
import { Card, Row, Col, Typography } from "antd";
8+
import { Card, Row, Col, Typography, Divider } from "antd";
99
import { Level1SettingPageContent, Level1SettingPageTitle } from "../styled";
1010
import { trans } from "i18n";
1111

12+
import { Image } from 'antd';
13+
import { getUser } from "@lowcoder-ee/redux/selectors/usersSelectors";
14+
import { getDeploymentId } from "@lowcoder-ee/redux/selectors/configSelectors";
15+
import { getOrgApiUsage, getOrgLastMonthApiUsage } from "redux/selectors/orgSelectors";
16+
import { fetchAPIUsageAction, fetchLastMonthAPIUsageAction } from "redux/reduxActions/orgActions";
17+
import { HelpText } from "components/HelpText";
18+
import { useEffect } from "react";
19+
1220
const { Paragraph, Text } = Typography;
1321

1422
const StyledSection = styled.div`
@@ -43,6 +51,21 @@ const AppUsageRoutes = () => (
4351
);
4452

4553
const AppUsageDoc = () => {
54+
55+
const user = useSelector(getUser);
56+
const deploymentId = useSelector(getDeploymentId);
57+
const dispatch = useDispatch();
58+
59+
const apiUsage = useSelector(getOrgApiUsage);
60+
useEffect(() => {
61+
dispatch(fetchAPIUsageAction(user.currentOrgId));
62+
}, [user.currentOrgId])
63+
64+
const lastMonthApiUsage = useSelector(getOrgLastMonthApiUsage);
65+
useEffect(() => {
66+
dispatch(fetchLastMonthAPIUsageAction(user.currentOrgId));
67+
}, [user.currentOrgId])
68+
4669
return (
4770
<Level1SettingPageContent>
4871
<Level1SettingPageTitle>{trans("enterprise.AppUsageTitle")}</Level1SettingPageTitle>
@@ -72,23 +95,81 @@ const AppUsageDoc = () => {
7295
<Card title={trans("enterprise.AppUsageScreenshotsTitle")}>
7396
<Row gutter={[24, 24]}>
7497
<Col span={8}>
75-
<div className="image-placeholder">
76-
<Text type="secondary">{trans("enterprise.AppUsageScreenshot1")}</Text>
77-
</div>
98+
<Image
99+
width="100%"
100+
height={180}
101+
src="https://raw.githubusercontent.com/lowcoder-org/lowcoder-media-assets/refs/heads/main/images/Enterprise%20Edition%20%7C%20App%20Usage%20Metrics%20Geomap.png"
102+
alt="Enterprise Edition | App Usage Metrics Geomap"
103+
style={{ borderRadius: 8, objectFit: 'cover', border: "1px solid #d9d9d9" }}
104+
preview={{
105+
mask: <Text>Enterprise Edition | App Usage Metrics Geomap</Text>,
106+
}}
107+
/>
78108
</Col>
79109
<Col span={8}>
80-
<div className="image-placeholder">
81-
<Text type="secondary">{trans("enterprise.AppUsageScreenshot2")}</Text>
82-
</div>
83-
</Col>
84-
<Col span={8}>
85-
<div className="image-placeholder">
86-
<Text type="secondary">{trans("enterprise.AppUsageScreenshot3")}</Text>
87-
</div>
110+
<Image
111+
width="100%"
112+
height={180}
113+
src="https://raw.githubusercontent.com/lowcoder-org/lowcoder-media-assets/refs/heads/main/images/Enterprise%20Edition%20%7C%20App%20Usage%20Metrics%20Stats.png"
114+
alt="Enterprise Edition | App Usage Metrics and Statistics"
115+
style={{ borderRadius: 8, objectFit: 'cover', border: "1px solid #d9d9d9" }}
116+
preview={{
117+
mask: <Text>Enterprise Edition | App Usage Metrics and Statistics</Text>,
118+
}}
119+
/>
88120
</Col>
89121
</Row>
90122
</Card>
91123
</StyledSection>
124+
125+
<StyledSection>
126+
<Card title={trans("enterprise.yourDeploymentID")}>
127+
<Paragraph><h3>{deploymentId}</h3></Paragraph>
128+
</Card>
129+
</StyledSection>
130+
131+
<StyledSection>
132+
<Card title={trans("enterprise.PricingTitle")}>
133+
<Paragraph>{trans("enterprise.PricingIntro")}</Paragraph>
134+
135+
<Paragraph>
136+
<Text strong>{trans("enterprise.FlatRateTitle")}</Text>
137+
<br />
138+
{trans("enterprise.FlatRateDesc")}
139+
</Paragraph>
140+
<ul>
141+
<li>{trans("enterprise.FlatRatePoint1")}</li>
142+
<li>{trans("enterprise.FlatRatePoint2")}</li>
143+
</ul>
144+
145+
<Divider />
146+
147+
<Paragraph>
148+
<Text strong>{trans("enterprise.UsagePricingTitle")}</Text>
149+
<br />
150+
{trans("enterprise.UsagePricingDesc")}
151+
</Paragraph>
152+
<ul>
153+
<li>{trans("enterprise.API100k")}</li>
154+
<li>{trans("enterprise.API1M")}</li>
155+
<li>{trans("enterprise.API10M")}</li>
156+
</ul>
157+
158+
<Paragraph>{trans("enterprise.UsageOverrunDesc")}</Paragraph>
159+
<Paragraph>{trans("enterprise.UsageTopUpInfo")}</Paragraph>
160+
161+
<Divider/>
162+
163+
<Text strong className="section-title">{trans("advanced.APIConsumption")}</Text>
164+
<HelpText style={{ marginBottom: 12 }}>{trans("advanced.APIConsumptionDescription")}</HelpText>
165+
<div className="section-content">
166+
{trans("advanced.overallAPIConsumption")} : {apiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(apiUsage) + " " + trans("enterprise.apiUsage") : trans("enterprise.loadingApiUsage")}<br/>
167+
{trans("advanced.lastMonthAPIConsumption")} : {lastMonthApiUsage ? Intl.NumberFormat('en-GB', { maximumFractionDigits: 2 }).format(lastMonthApiUsage) + " " + trans("enterprise.apiUsage") : trans("enterprise.loadingApiUsage")}
168+
</div>
169+
170+
</Card>
171+
</StyledSection>
172+
92173
</Level1SettingPageContent>
93174
);
94175
};

client/packages/lowcoder/src/pages/setting/audit/detail.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,14 @@ export function AuditLogDetail() {
274274
{trans("enterprise.AuditLogTitle")}
275275
</span>
276276
<ArrowIcon />
277-
<span>{"Audit Log Detail"}</span>
277+
<span>{trans("auditLog.title")}</span>
278278
</HeaderBack>
279279
</Header>
280280

281281
<DetailContent>
282282
{/* Geolocation */}
283283
<StyleThemeSettingsCover>
284-
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>Geo Location</h2>
284+
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>{trans("auditLog.geoLocation")}</h2>
285285
</StyleThemeSettingsCover>
286286
<Card size="small" style={{ marginBottom: "20px", borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
287287
<Map
@@ -298,22 +298,22 @@ export function AuditLogDetail() {
298298

299299
{/* Browser/System Meta data */}
300300
<StyleThemeSettingsCover>
301-
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>Browser / System Metadata</h2>
301+
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>{trans("auditLog.browserData")}</h2>
302302
</StyleThemeSettingsCover>
303303
<Card size="small" style={{ marginBottom: "20px", borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
304304
<Descriptions bordered column={1} size="small">
305-
<Descriptions.Item label={<span><ChromeOutlined className="text-lg mr-2" /> Browser</span>}>{event?.agentName}</Descriptions.Item>
306-
<Descriptions.Item label={<span><AppleOutlined className="text-lg mr-2" /> OS</span>}>{event?.operatingSystemName} ({event?.operatingSystemVersion})</Descriptions.Item>
307-
<Descriptions.Item label={<span><DesktopOutlined className="text-lg mr-2" /> Device</span>}>{event?.deviceName}</Descriptions.Item>
308-
<Descriptions.Item label={<span><DesktopOutlined className="text-lg mr-2" /> Device Type</span>}>{event?.deviceClass}</Descriptions.Item>
309-
<Descriptions.Item label={<span><AppstoreOutlined className="text-lg mr-2" /> Engine</span>}>{event?.layoutEngineName} (Version: {event?.layoutEngineVersion})</Descriptions.Item>
310-
<Descriptions.Item label={<span><AppstoreOutlined className="text-lg mr-2" /> Webview</span>}>{event?.webviewAppName}</Descriptions.Item>
305+
<Descriptions.Item label={<span><ChromeOutlined className="text-lg mr-2" /> {trans("auditLog.browser")}</span>}>{event?.agentName}</Descriptions.Item>
306+
<Descriptions.Item label={<span><AppleOutlined className="text-lg mr-2" /> {trans("auditLog.OS")}</span>}>{event?.operatingSystemName} ({event?.operatingSystemVersion})</Descriptions.Item>
307+
<Descriptions.Item label={<span><DesktopOutlined className="text-lg mr-2" /> {trans("auditLog.device")}</span>}>{event?.deviceName}</Descriptions.Item>
308+
<Descriptions.Item label={<span><DesktopOutlined className="text-lg mr-2" /> {trans("auditLog.deviceType")}</span>}>{event?.deviceClass}</Descriptions.Item>
309+
<Descriptions.Item label={<span><AppstoreOutlined className="text-lg mr-2" /> {trans("auditLog.engine")}</span>}>{event?.layoutEngineName} (Version: {event?.layoutEngineVersion})</Descriptions.Item>
310+
<Descriptions.Item label={<span><AppstoreOutlined className="text-lg mr-2" /> {trans("auditLog.browserData")}</span>}>{event?.webviewAppName}</Descriptions.Item>
311311
</Descriptions>
312312
</Card>
313313

314314
{/* Event Detail */}
315315
<StyleThemeSettingsCover>
316-
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>Event Detail</h2>
316+
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>{trans("auditLog.eventDetail")}</h2>
317317
</StyleThemeSettingsCover>
318318
<Card size="small" style={{ marginBottom: "20px", borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
319319
{Boolean(eventHierarchy.length) && (

0 commit comments

Comments
 (0)