Skip to content

Commit b8e1821

Browse files
committed
feat: add-ons menu added
1 parent abd78fb commit b8e1821

File tree

23 files changed

+822
-1239
lines changed

23 files changed

+822
-1239
lines changed

.eslintignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
/dist
2-
/node_modules
2+
/node_modules
3+
4+
tailwind.config.js
5+
vite.config.ts

.eslintrc.json

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"root": true,
33
"parser": "@typescript-eslint/parser",
44
"extends": [
5-
"airbnb-base",
65
"plugin:prettier/recommended",
76
"eslint:recommended",
87
"plugin:@typescript-eslint/recommended"
@@ -14,17 +13,7 @@
1413
"rules": {
1514
"prettier/prettier": "error",
1615
"camelcase": "warn",
17-
"import/prefer-default-export": "warn",
18-
"import/no-extraneous-dependencies": "warn",
19-
"prefer-object-spread": "warn",
20-
"import/extensions": [
21-
"error",
22-
"ignorePackages",
23-
{
24-
"js": "never",
25-
"ts": "never"
26-
}
27-
]
16+
"prefer-object-spread": "warn"
2817
},
2918
"ignorePatterns": ["dist", ".eslintrc.json"],
3019
"settings": {

appsscript.json

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
{
22
"timeZone": "America/New_York",
3-
"dependencies": {},
3+
"dependencies": {
4+
"libraries": [
5+
{
6+
"userSymbol": "OAuth2",
7+
"version": "43",
8+
"libraryId": "1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF"
9+
}
10+
]
11+
},
412
"exceptionLogging": "STACKDRIVER",
513
"oauthScopes": [
614
"https://www.googleapis.com/auth/script.container.ui",
7-
"https://www.googleapis.com/auth/spreadsheets"
15+
"https://www.googleapis.com/auth/script.external_request",
16+
"https://www.googleapis.com/auth/documents"
817
],
18+
"addOns": {
19+
"common": {
20+
"name": "Mermaid Chart",
21+
"logoUrl": "https://www.mermaidchart.com/img/mermaid-chart-48.png",
22+
"useLocaleFromApp": true,
23+
"universalActions": [
24+
{
25+
"label": "Learn more about Mermaid Chart",
26+
"openLink": "www.mermaidchart.com"
27+
}
28+
],
29+
"layoutProperties": {
30+
"primaryColor": "#424242",
31+
"secondaryColor": "#ff3670"
32+
}
33+
}
34+
},
935
"runtimeVersion": "V8"
1036
}

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@
5757
"cross-env": "^7.0.3",
5858
"dotenv": "^16.4.5",
5959
"eslint": "^8.57.0",
60-
"eslint-config-airbnb-base": "^15.0.0",
6160
"eslint-config-prettier": "^8.5.0",
6261
"eslint-plugin-googleappsscript": "^1.0.4",
63-
"eslint-plugin-import": "^2.29.1",
6462
"eslint-plugin-jest": "^26.5.3",
6563
"eslint-plugin-prettier": "^4.0.0",
6664
"eslint-plugin-react-hooks": "^4.6.0",

src/client/.eslintrc.json

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"root": true,
33
"extends": [
4-
"airbnb-base",
54
"plugin:prettier/recommended",
65
"eslint:recommended",
76
"plugin:@typescript-eslint/recommended",
@@ -11,24 +10,13 @@
1110
"rules": {
1211
"prettier/prettier": "error",
1312
"camelcase": "warn",
14-
"import/prefer-default-export": "warn",
15-
"import/no-extraneous-dependencies": "warn",
1613
"prefer-object-spread": "warn",
1714
"spaced-comment": "off",
1815
"react-refresh/only-export-components": [
1916
"warn",
2017
{ "allowConstantExport": true }
2118
],
22-
"import/extensions": [
23-
"error",
24-
"ignorePackages",
25-
{
26-
"js": "never",
27-
"jsx": "never",
28-
"ts": "never",
29-
"tsx": "never"
30-
}
31-
]
19+
"@typescript-eslint/no-explicit-any": "off"
3220
},
3321
"settings": {
3422
"react": {

src/client/dialog/components/Dialog.tsx

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,87 @@
1+
import { useEffect, useState } from 'react';
2+
import { buildUrl, handleDialogClose } from '../../utils/helpers';
3+
import { serverFunctions } from '../../utils/serverFunctions';
4+
5+
interface AuthState {
6+
authorized: boolean;
7+
token?: string;
8+
message?: string;
9+
}
10+
11+
type Status = 'idle' | 'loading' | 'success' | 'error';
12+
113
const Dialog = () => {
14+
const [diagramsUrl, setDiagramsUrl] = useState('');
15+
const [, setAuthState] = useState<null | AuthState>(null);
16+
const [authStatus, setAuthStatus] = useState<Status>('idle');
17+
18+
useEffect(() => {
19+
const getAuth = async () => {
20+
setAuthStatus('loading');
21+
try {
22+
const state = await serverFunctions.getAuthorizationState();
23+
setAuthState(state);
24+
setAuthStatus('success');
25+
26+
if (state.authorized) {
27+
const url = buildUrl('/app/plugins/confluence/select', state.token);
28+
setDiagramsUrl(url);
29+
}
30+
} catch (error) {
31+
console.log('Error getting auth data', error);
32+
setAuthStatus('error');
33+
}
34+
};
35+
36+
getAuth();
37+
}, []);
38+
39+
useEffect(() => {
40+
const handleMessage = async (e: MessageEvent) => {
41+
const action = e.data.action;
42+
console.log('action', action, e.data);
43+
if (action === 'save') {
44+
const data = e.data.data;
45+
console.log(data);
46+
const metadata = new URLSearchParams({
47+
projectID: data.projectID,
48+
documentID: data.documentID,
49+
major: data.major,
50+
minor: data.minor,
51+
});
52+
try {
53+
await serverFunctions.insertBase64ImageWithMetadata(
54+
data.diagramImage,
55+
metadata.toString()
56+
);
57+
handleDialogClose();
58+
} catch (error) {
59+
console.error('Error inserting image with metadata', error);
60+
}
61+
}
62+
};
63+
64+
window.addEventListener('message', handleMessage);
65+
66+
return () => {
67+
window.removeEventListener('message', handleMessage);
68+
};
69+
}, []);
70+
71+
if (authStatus !== 'success') {
72+
return null;
73+
}
74+
275
return (
3-
<div style={{ padding: '3px', overflowX: 'hidden' }}>
76+
<div style={{ padding: '3px', overflowX: 'hidden', height: '100%' }}>
477
<iframe
5-
src="https://mermaid-js.github.io/mermaid-live-editor/edit/"
6-
style={{ border: 'none', height: '742px', width: '100%' }}
78+
src={diagramsUrl}
79+
title="diagrams"
80+
style={{
81+
border: 'none',
82+
width: '100%',
83+
height: '96.5vh',
84+
}}
785
/>
886
</div>
987
);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { useEffect, useState } from 'react';
2+
import { serverFunctions } from '../../utils/serverFunctions';
3+
import { buildUrl, handleDialogClose } from '../../utils/helpers';
4+
import useAuth from '../../hooks/useAuth';
5+
6+
const EditDialog = () => {
7+
const { authState, authStatus } = useAuth();
8+
const [diagramsUrl, setDiagramsUrl] = useState('');
9+
10+
useEffect(() => {
11+
if (!authState) return;
12+
const getMetadata = async () => {
13+
try {
14+
const metadata = await serverFunctions.readSelectedImageMetadata();
15+
console.log(metadata, 'metadata');
16+
if (typeof metadata === 'string') {
17+
const params = new URLSearchParams(metadata);
18+
const projectID = params.get('projectID');
19+
const documentID = params.get('documentID');
20+
const major = params.get('major');
21+
const minor = params.get('minor');
22+
if (projectID && documentID && major && minor && authState?.token) {
23+
const iframeUrl = buildUrl(
24+
`/app/projects/${projectID}/diagrams/${documentID}/version/v.${major}.${minor}/edit`,
25+
authState.token
26+
);
27+
setDiagramsUrl(iframeUrl);
28+
}
29+
}
30+
} catch (error) {
31+
console.log(error);
32+
}
33+
};
34+
getMetadata();
35+
}, [authState]);
36+
37+
useEffect(() => {
38+
const handleMessage = async (e: MessageEvent) => {
39+
const action = e.data.action;
40+
console.log('action', action);
41+
if (action === 'save') {
42+
const data = e.data.data;
43+
const metadata = new URLSearchParams({
44+
projectID: data.projectID,
45+
documentID: data.documentID,
46+
major: data.major,
47+
minor: data.minor,
48+
});
49+
try {
50+
await serverFunctions.replaceSelectedImageWithBase64AndSize(
51+
data.diagramImage,
52+
metadata.toString()
53+
);
54+
handleDialogClose();
55+
} catch (error) {
56+
console.error('Error updating image with metadata', error);
57+
}
58+
}
59+
};
60+
61+
window.addEventListener('message', handleMessage);
62+
63+
return () => {
64+
window.removeEventListener('message', handleMessage);
65+
};
66+
}, []);
67+
68+
if (authStatus !== 'success' || !diagramsUrl) {
69+
return null;
70+
}
71+
72+
return (
73+
<div style={{ padding: '3px', overflowX: 'hidden', height: '100%' }}>
74+
<iframe
75+
src={diagramsUrl}
76+
title="diagrams"
77+
style={{
78+
border: 'none',
79+
width: '100%',
80+
height: '96.5vh',
81+
}}
82+
/>
83+
</div>
84+
);
85+
};
86+
87+
export default EditDialog;

src/client/edit-dialog/index.html

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<base target="_top" />
5+
<!-- Add any external scripts and stylesheets here -->
6+
<script
7+
crossorigin
8+
src="https://unpkg.com/react@18.2.0/umd/react.production.min.js"
9+
></script>
10+
<script
11+
crossorigin
12+
src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js"
13+
></script>
14+
<script
15+
crossorigin
16+
src="https://unpkg.com/@mui/material@5.11.11/umd/material-ui.production.min.js"
17+
></script>
18+
<script
19+
crossorigin
20+
src="https://unpkg.com/gas-client@1.1.1/dist/index.js"
21+
></script>
22+
<script
23+
crossorigin
24+
src="https://unpkg.com/@types/react@18.2.66/index.d.ts"
25+
></script>
26+
</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>
33+
</html>

src/client/edit-dialog/index.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import ReactDOM from 'react-dom';
2+
import EditDialog from './components/EditDialog';
3+
4+
import './styles.css';
5+
6+
ReactDOM.render(<EditDialog />, document.getElementById('index'));

src/client/edit-dialog/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* needed to make consistent test snapshots across OSs */
2+
body {
3+
font-family: Arial !important;
4+
}

src/client/hooks/useAuth.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useCallback, useEffect, useState } from 'react';
2+
import { serverFunctions } from '../utils/serverFunctions';
3+
4+
interface AuthState {
5+
authorized: boolean;
6+
token?: string;
7+
message?: string;
8+
}
9+
10+
type Status = 'idle' | 'loading' | 'success' | 'error';
11+
12+
const useAuth = () => {
13+
const [authState, setAuthState] = useState<null | AuthState>(null);
14+
const [authStatus, setAuthStatus] = useState<Status>('idle');
15+
16+
const getAuth = useCallback(async () => {
17+
setAuthStatus('loading');
18+
try {
19+
const state = await serverFunctions.getAuthorizationState();
20+
setAuthState(state);
21+
setAuthStatus('success');
22+
} catch (error) {
23+
console.log('Error getting auth data', error);
24+
setAuthStatus('error');
25+
}
26+
}, []);
27+
28+
useEffect(() => {
29+
getAuth();
30+
}, [getAuth]);
31+
32+
const signOut = async () => {
33+
serverFunctions.resetOAuth();
34+
setTimeout(getAuth, 2000);
35+
};
36+
37+
return { authState, authStatus, signOut };
38+
};
39+
40+
export default useAuth;

0 commit comments

Comments
 (0)