Skip to content

Commit 1e15901

Browse files
committed
Improved the Performance for inserting diagram and added proper Analytics
1 parent 582ab53 commit 1e15901

13 files changed

Lines changed: 491 additions & 84 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "google-plugin",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"type": "module",
55
"scripts": {
66
"dev": "vite",

src/analytics/analytics.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
import httpClient from './httpClient';
21
class Analytics {
32

3+
private async getServerFunctions() {
4+
try {
5+
// Dynamic import to avoid circular dependency issues
6+
const { serverFunctions } = await import('../client/utils/serverFunctions');
7+
return serverFunctions;
8+
} catch (error) {
9+
console.warn('Failed to import serverFunctions:', error);
10+
return null;
11+
}
12+
}
13+
414
public sendEvent(eventName: string, eventID:string, errorMessage?: string, diagramType?:string, userLoginState: boolean = true) {
515
const analyticsID = getAnalyticsID();
616
const pluginID= "google-docs-plugin";
@@ -16,10 +26,16 @@ class Analytics {
1626
diagramType
1727
};
1828

19-
httpClient.post('/rest-api/plugins/pulse', payload).catch(error => {
20-
if (error.code !== 'ERR_NETWORK') {
21-
console.error('Failed to send analytics event:', error);
29+
this.getServerFunctions().then(serverFunctions => {
30+
if (serverFunctions && serverFunctions.sendAnalyticsEvent) {
31+
serverFunctions.sendAnalyticsEvent(payload).catch(error => {
32+
console.error('Failed to send analytics event:', error);
33+
});
34+
} else {
35+
console.warn('Analytics service unavailable - serverFunctions not available');
2236
}
37+
}).catch(error => {
38+
console.error('Failed to send analytics event:', error);
2339
});
2440
}
2541

src/client/components/toast.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Snackbar, Alert, AlertColor } from '@mui/material';
2+
3+
interface ToastProps {
4+
open: boolean;
5+
message: string;
6+
severity: AlertColor;
7+
onClose: () => void;
8+
autoHideDuration?: number;
9+
}
10+
11+
const Toast = ({
12+
open,
13+
message,
14+
severity,
15+
onClose,
16+
autoHideDuration = 4000,
17+
}: ToastProps) => (
18+
<Snackbar
19+
open={open}
20+
autoHideDuration={autoHideDuration}
21+
onClose={onClose}
22+
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
23+
>
24+
<Alert onClose={onClose} severity={severity} sx={{ width: '100%' }}>
25+
{message}
26+
</Alert>
27+
</Snackbar>
28+
);
29+
30+
export default Toast;

src/client/create-diagram-dialog/components/create-diagram-dialog.tsx

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import {
44
handleDialogClose,
55
compressBase64Image,
66
} from '../../utils/helpers';
7-
import { serverFunctions } from '../../utils/serverFunctions';
7+
88
import useAuth from '../../hooks/useAuth';
99
import { CircularProgress, Container, Typography, Box } from '@mui/material';
1010
import { showAlertDialog } from '../../utils/alert';
11-
import LoadingOverlay from '../../components/loading-overlay';
1211

1312
const CreateDiagramDialog = () => {
1413
const { authState, authStatus } = useAuth();
1514
const [diagramsUrl, setDiagramsUrl] = useState('');
16-
const [isInserting, setIsInserting] = useState(false);
1715
const [iframeLoading, setIframeLoading] = useState(true);
1816

1917
useEffect(() => {
@@ -29,13 +27,6 @@ const CreateDiagramDialog = () => {
2927
const handleMessage = async (e: MessageEvent) => {
3028
const action = e.data.action;
3129
if (action === 'save') {
32-
if (isInserting) {
33-
console.log('Already inserting diagram, ignoring duplicate click');
34-
return;
35-
}
36-
37-
setIsInserting(true);
38-
3930
const data = e.data.data;
4031
const metadata = new URLSearchParams({
4132
projectID: data.projectID,
@@ -47,15 +38,21 @@ const CreateDiagramDialog = () => {
4738
try {
4839
const compressedImage = await compressBase64Image(data.diagramImage);
4940

50-
await serverFunctions.insertBase64ImageWithMetadata(
51-
compressedImage,
52-
metadata.toString()
53-
);
41+
// Pass data to sidebar via BroadcastChannel and close immediately
42+
const channel = new BroadcastChannel('diagram_channel');
43+
channel.postMessage({
44+
type: 'pendingInsertion',
45+
payload: {
46+
image: compressedImage,
47+
metadata: metadata.toString(),
48+
operation: 'insert',
49+
},
50+
});
51+
channel.close();
5452
handleDialogClose();
5553
} catch (error) {
56-
console.error('Error inserting image with metadata', error);
57-
showAlertDialog('Error inserting image, please try again');
58-
setIsInserting(false);
54+
console.error('Error preparing diagram insertion', error);
55+
showAlertDialog('Error preparing diagram, please try again');
5956
}
6057
}
6158
};
@@ -65,7 +62,7 @@ const CreateDiagramDialog = () => {
6562
return () => {
6663
window.removeEventListener('message', handleMessage);
6764
};
68-
}, [isInserting]);
65+
}, []);
6966

7067
const handleIframeLoad = () => {
7168
setIframeLoading(false);
@@ -124,7 +121,6 @@ const CreateDiagramDialog = () => {
124121

125122
return (
126123
<>
127-
{isInserting && <LoadingOverlay />}
128124
{iframeLoading && (
129125
<Box
130126
sx={{
@@ -151,8 +147,7 @@ const CreateDiagramDialog = () => {
151147
border: 'none',
152148
width: '100%',
153149
height: '96.5vh',
154-
opacity: isInserting ? 0.5 : 1,
155-
pointerEvents: isInserting ? 'none' : 'auto',
150+
opacity: 1,
156151
}}
157152
onLoad={handleIframeLoad}
158153
/>

src/client/create-diagram-dialog/index.html

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,39 @@
2626
</head>
2727
<body>
2828
<section id="index">
29+
<style>
30+
.loading-container {
31+
display: flex;
32+
justify-content: center;
33+
align-items: center;
34+
height: 100vh;
35+
flex-direction: column;
36+
font-family: sans-serif;
37+
position: fixed;
38+
top: 0;
39+
left: 0;
40+
width: 100%;
41+
background: white;
42+
z-index: 9999;
43+
}
44+
.spinner {
45+
border: 4px solid #f3f3f3;
46+
border-top: 4px solid #3498db;
47+
border-radius: 50%;
48+
width: 40px;
49+
height: 40px;
50+
animation: spin 1s linear infinite;
51+
margin-bottom: 16px;
52+
}
53+
@keyframes spin {
54+
0% { transform: rotate(0deg); }
55+
100% { transform: rotate(360deg); }
56+
}
57+
</style>
58+
<div class="loading-container">
59+
<div class="spinner"></div>
60+
<div>Loading...</div>
61+
</div>
2962
<script type="module" src="./index.jsx"></script>
3063
<!-- bundled js and css will get inlined here during build-->
3164
</section>

src/client/edit-diagram-dialog/components/edit-diagram-dialog.tsx

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import {
77
} from '../../utils/helpers';
88
import useAuth from '../../hooks/useAuth';
99
import { showAlertDialog } from '../../utils/alert';
10-
import LoadingOverlay from '../../components/loading-overlay';
1110
import { CircularProgress, Container, Typography, Box } from '@mui/material';
1211

1312
const EditDiagramDialog = () => {
1413
const { authState, authStatus } = useAuth();
1514
const [diagramsUrl, setDiagramsUrl] = useState('');
16-
const [isUpdating, setIsUpdating] = useState(false);
1715
const [iframeLoading, setIframeLoading] = useState(true);
1816

1917
useEffect(() => {
@@ -49,12 +47,6 @@ const EditDiagramDialog = () => {
4947
const action = e.data.action;
5048
console.log('action', action);
5149
if (action === 'save') {
52-
if (isUpdating) {
53-
return;
54-
}
55-
56-
setIsUpdating(true);
57-
5850
const data = e.data.data;
5951
const metadata = new URLSearchParams({
6052
projectID: data.projectID,
@@ -65,15 +57,21 @@ const EditDiagramDialog = () => {
6557
try {
6658
const compressedImage = await compressBase64Image(data.diagramImage);
6759

68-
await serverFunctions.replaceSelectedImageWithBase64AndSize(
69-
compressedImage,
70-
metadata.toString()
71-
);
60+
// Pass data to sidebar via BroadcastChannel and close immediately
61+
const channel = new BroadcastChannel('diagram_channel');
62+
channel.postMessage({
63+
type: 'pendingInsertion',
64+
payload: {
65+
image: compressedImage,
66+
metadata: metadata.toString(),
67+
operation: 'replace',
68+
},
69+
});
70+
channel.close();
7271
handleDialogClose();
7372
} catch (error) {
74-
console.error('Error updating image with metadata', error);
75-
showAlertDialog('Error updating image, please try again');
76-
setIsUpdating(false);
73+
console.error('Error preparing diagram update', error);
74+
showAlertDialog('Error preparing diagram update, please try again');
7775
}
7876
}
7977
};
@@ -83,7 +81,7 @@ const EditDiagramDialog = () => {
8381
return () => {
8482
window.removeEventListener('message', handleMessage);
8583
};
86-
}, [isUpdating]);
84+
}, []);
8785

8886
const handleIframeLoad = () => {
8987
setIframeLoading(false);
@@ -142,7 +140,6 @@ const EditDiagramDialog = () => {
142140

143141
return (
144142
<>
145-
{isUpdating && <LoadingOverlay />}
146143
{iframeLoading && (
147144
<Box
148145
sx={{
@@ -169,8 +166,7 @@ const EditDiagramDialog = () => {
169166
border: 'none',
170167
width: '100%',
171168
height: '96.5vh',
172-
opacity: isUpdating ? 0.5 : 1,
173-
pointerEvents: isUpdating ? 'none' : 'auto',
169+
opacity: 1,
174170
}}
175171
onLoad={handleIframeLoad}
176172
/>

src/client/edit-diagram-dialog/index.html

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,50 @@
2424
src="https://unpkg.com/@types/react@18.2.66/index.d.ts"
2525
></script>
2626
</head>
27-
<body>
28-
<section id="index">
29-
<script type="module" src="./index.jsx"></script>
30-
<!-- bundled js and css will get inlined here during build-->
31-
</section>
32-
</body>
27+
<body>
28+
<section id="index">
29+
<style>
30+
.loading-container {
31+
display: flex;
32+
justify-content: center;
33+
align-items: center;
34+
height: 100vh;
35+
flex-direction: column;
36+
font-family: sans-serif;
37+
position: fixed;
38+
top: 0;
39+
left: 0;
40+
width: 100%;
41+
background: white;
42+
z-index: 9999;
43+
}
44+
45+
.spinner {
46+
border: 4px solid #f3f3f3;
47+
border-top: 4px solid #3498db;
48+
border-radius: 50%;
49+
width: 40px;
50+
height: 40px;
51+
animation: spin 1s linear infinite;
52+
margin-bottom: 16px;
53+
}
54+
55+
@keyframes spin {
56+
0% {
57+
transform: rotate(0deg);
58+
}
59+
60+
100% {
61+
transform: rotate(360deg);
62+
}
63+
}
64+
</style>
65+
<div class="loading-container">
66+
<div class="spinner"></div>
67+
<div>Loading...</div>
68+
</div>
69+
<script type="module" src="./index.jsx"></script>
70+
<!-- bundled js and css will get inlined here during build-->
71+
</section>
72+
</body>
3373
</html>

0 commit comments

Comments
 (0)