Skip to content

Commit 6a67c4e

Browse files
added geo map chart for user engagment by region
1 parent 6c63789 commit 6a67c4e

File tree

6 files changed

+172
-3
lines changed

6 files changed

+172
-3
lines changed

client/packages/lowcoder/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"copy-to-clipboard": "^3.3.3",
4848
"core-js": "^3.25.2",
4949
"echarts": "^5.4.3",
50+
"echarts-extension-gmap": "^1.7.0",
5051
"echarts-for-react": "^3.0.2",
5152
"echarts-wordcloud": "^2.1.0",
5253
"eslint4b-prebuilt-2": "^7.32.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { useEffect, useMemo, useRef, useState } from "react";
2+
import ReactECharts from "echarts-for-react";
3+
import 'echarts-extension-gmap';
4+
import { findIndex } from "lodash";
5+
6+
const googleMapsApiUrl = "https://maps.googleapis.com/maps/api/js";
7+
8+
function loadGoogleMapsScript(apiKey: string) {
9+
const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
10+
const scripts = document.getElementsByTagName('script');
11+
// is script already loaded
12+
let scriptIndex = findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
13+
if(scriptIndex > -1) {
14+
return scripts[scriptIndex];
15+
}
16+
// is script loaded with diff api_key, remove the script and load again
17+
scriptIndex = findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
18+
if(scriptIndex > -1) {
19+
scripts[scriptIndex].remove();
20+
}
21+
22+
const script = document.createElement("script");
23+
script.type = "text/javascript";
24+
script.src = mapsUrl;
25+
script.async = true;
26+
script.defer = true;
27+
window.document.body.appendChild(script);
28+
29+
return script;
30+
}
31+
32+
interface Props {
33+
data: Array<any>;
34+
}
35+
36+
function getRandomLatLng(minLat: number, maxLat: number, minLng: number, maxLng: number) {
37+
const lat = Math.random() * (maxLat - minLat) + minLat
38+
const lng = Math.random() * (maxLng - minLng) + minLng
39+
return [lat, lng]
40+
}
41+
42+
const UserEngagementByRegionChart = ({ data }: Props) => {
43+
const chartRef = useRef<any>(null);
44+
const [mapScriptLoaded, setMapScriptLoaded] = useState(false);
45+
46+
const isMapScriptLoaded = useMemo(() => {
47+
return mapScriptLoaded || (window as any)?.google;
48+
}, [mapScriptLoaded])
49+
50+
const handleOnMapScriptLoad = () => {
51+
setMapScriptLoaded(true);
52+
}
53+
54+
useEffect(() => {
55+
const gMapScript = loadGoogleMapsScript('');
56+
if(isMapScriptLoaded) {
57+
handleOnMapScriptLoad();
58+
return;
59+
}
60+
gMapScript.addEventListener('load', handleOnMapScriptLoad);
61+
return () => {
62+
gMapScript.removeEventListener('load', handleOnMapScriptLoad);
63+
}
64+
}, [])
65+
66+
const series = useMemo(() => {
67+
return [
68+
{
69+
"name": "Company Size",
70+
"type": "scatter",
71+
"coordinateSystem": "gmap",
72+
"itemStyle": {
73+
"color": "#ff00ff"
74+
},
75+
"data": data
76+
// .filter(item => {
77+
// if (!item.geolocationDataJsonb) return false;
78+
// return item.geolocationDataJsonb.longitude !== null &&
79+
// item.geolocationDataJsonb.latitude !== null
80+
// })
81+
.map(item => ({
82+
name: item.details?.applicationName,
83+
value: [
84+
...getRandomLatLng(35, 72, 25, 65),
85+
1,
86+
]
87+
// value: [
88+
// geoLocation.location.longitude, // item.longitude,
89+
// geoLocation.location.latitude, // item.latitude,
90+
// 1
91+
// ]
92+
}))
93+
,
94+
"encode": {
95+
"value": 2,
96+
"lng": 0,
97+
"lat": 1
98+
}
99+
}
100+
]
101+
}, [data]);
102+
103+
return (
104+
<>
105+
{isMapScriptLoaded && (
106+
<ReactECharts
107+
ref={chartRef}
108+
option={{
109+
gmap: {
110+
center: [15, 55],
111+
zoom: 3,
112+
renderOnMoving: true,
113+
echartsLayerZIndex: 2019,
114+
roam: true
115+
},
116+
tooltip: {
117+
trigger: "item",
118+
formatter: "{b}"
119+
},
120+
animation: true,
121+
series: series,
122+
}}
123+
style={{ height: "400px" }}
124+
/>
125+
)}
126+
</>
127+
)
128+
}
129+
130+
export default UserEngagementByRegionChart;

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

+19
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import UserActivityByTimeChart from "./charts/userActivityByTime";
2222
import UserAuthStatusChart from "./charts/userAuthStatus";
2323
import DeviceOSBreakdownChart from "./charts/deviceOSBreakdown";
2424
import BrowserEngineBreakdownChart from "./charts/browserEngineBreakdown";
25+
import UserEngagementByRegionChart from "./charts/userEngagementByRegion";
26+
import { geoLocation } from "../audit/auditContants";
2527

2628
const { RangePicker } = DatePicker;
2729

@@ -55,6 +57,7 @@ export function AppUsageDashboard() {
5557
appId: string;
5658
isAnonymous: boolean;
5759
details: Record<string, any>;
60+
geolocationDataJsonb?: Record<string, any>,
5861
};
5962

6063
const currentUser = useSelector(getUser);
@@ -367,6 +370,22 @@ export function AppUsageDashboard() {
367370
</Form>
368371
</Card>
369372
</AppLogContent>
373+
<AppLogContent>
374+
<StyleThemeSettingsCover>
375+
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>{"User Engagement By Region"}</h2>
376+
</StyleThemeSettingsCover>
377+
<Card>
378+
{loading ? (
379+
<Skeleton active paragraph={{ rows: 5 }} />
380+
) : currentPageLogs.length > 0 ? (
381+
<>
382+
<UserEngagementByRegionChart data={allLogs}/>
383+
</>
384+
) : (
385+
<p>No logs found. Adjust the filters and try again.</p>
386+
)}
387+
</Card>
388+
</AppLogContent>
370389
<AppLogContent>
371390
<StyleThemeSettingsCover>
372391
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>{"App Usage Logs"}</h2>

client/packages/lowcoder/src/pages/setting/audit/auditContants.ts

+10
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,13 @@ export const eventTypes = [
9696
{ value: "LIBRARY_QUERY_PUBLISH", label: trans("enterprise.LIBRARY_QUERY_PUBLISH"), color: "#22075e" },
9797
{ value: "API_CALL_EVENT", label: trans("enterprise.API_CALL_EVENT"), color: "#8c8c8c" },
9898
];
99+
100+
// temporary geoLocation data
101+
export const geoLocation = {
102+
"location": {
103+
"accuracy_radius": 500,
104+
"latitude": 24.8591,
105+
"longitude": 66.9983,
106+
"time_zone": "Asia/Karachi"
107+
}
108+
}

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { getAuditLogs, getMeta } from "@lowcoder-ee/api/enterpriseApi";
1414
import { isEmpty } from "lodash";
1515
import { getEventColor, getEventLabel } from "./dashboard";
1616
import Tag from "antd/es/tag";
17+
import { geoLocation } from "./auditContants";
1718

1819
const StyleThemeSettingsCover = styled.div`
1920
display: flex;
@@ -232,8 +233,15 @@ export function AuditLogDetail() {
232233
<h2 style={{ color: "#ffffff", marginTop: "8px" }}>Geo Location</h2>
233234
</StyleThemeSettingsCover>
234235
<Card size="small" style={{ marginBottom: "20px", borderTopLeftRadius: 0, borderTopRightRadius: 0 }}>
235-
<Map height={300} defaultCenter={[50.879, 4.6997]} defaultZoom={11}>
236-
<Marker width={50} anchor={[50.879, 4.6997]} />
236+
<Map
237+
height={300}
238+
defaultZoom={11}
239+
defaultCenter={[geoLocation.location.latitude, geoLocation.location.longitude]}
240+
>
241+
<Marker
242+
width={50}
243+
anchor={[geoLocation.location.latitude, geoLocation.location.longitude]}
244+
/>
237245
</Map>
238246
</Card>
239247

client/yarn.lock

+2-1
Original file line numberDiff line numberDiff line change
@@ -9078,7 +9078,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
90789078
languageName: node
90799079
linkType: hard
90809080

9081-
"echarts-extension-gmap@npm:^1.6.0":
9081+
"echarts-extension-gmap@npm:^1.6.0, echarts-extension-gmap@npm:^1.7.0":
90829082
version: 1.7.0
90839083
resolution: "echarts-extension-gmap@npm:1.7.0"
90849084
checksum: b7a88dcaf83da44c482ace744761543abd8e796c680f211e03085f037b0c7231bb62cd333d25893bd450ac700cfb8c7b7a509a672cccf79f112f570c9991b348
@@ -14087,6 +14087,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
1408714087
core-js: ^3.25.2
1408814088
dotenv: ^16.0.3
1408914089
echarts: ^5.4.3
14090+
echarts-extension-gmap: ^1.7.0
1409014091
echarts-for-react: ^3.0.2
1409114092
echarts-wordcloud: ^2.1.0
1409214093
eslint: ^8.0.0

0 commit comments

Comments
 (0)