Skip to content

Commit f9a1d02

Browse files
authored
Add Material UI demo (#173)
Adds working example with Material UI
1 parent 7fd979a commit f9a1d02

File tree

11 files changed

+1032
-138
lines changed

11 files changed

+1032
-138
lines changed

package-lock.json

Lines changed: 793 additions & 138 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
"npm": ">=6.0.0"
3535
},
3636
"dependencies": {
37+
"@emotion/react": "^11.10.6",
38+
"@emotion/styled": "^11.10.6",
39+
"@mui/material": "^5.11.11",
3740
"prop-types": "^15.8.1",
3841
"react": "^18.2.0",
3942
"react-bootstrap": "^2.4.0",
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React, { useState, ChangeEvent, FormEvent } from 'react';
2+
import { Button, Grid, TextField, Typography } from '@mui/material';
3+
4+
interface FormInputProps {
5+
submitNewSheet: (sheetName: string) => {
6+
name: string;
7+
index: number;
8+
isActive: boolean;
9+
};
10+
}
11+
12+
const FormInput = ({ submitNewSheet }: FormInputProps) => {
13+
const [newSheetName, setNewSheetName] = useState('');
14+
15+
const handleChange = (event: ChangeEvent<HTMLInputElement>) =>
16+
setNewSheetName(event.target.value);
17+
18+
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
19+
event.preventDefault();
20+
if (newSheetName.length === 0) return;
21+
submitNewSheet(newSheetName);
22+
setNewSheetName('');
23+
};
24+
25+
return (
26+
<form
27+
onSubmit={handleSubmit}
28+
>
29+
<Grid container spacing={2}>
30+
<Grid item xs={10}>
31+
<TextField
32+
id="sheet-name"
33+
label="New Sheet Name"
34+
variant="outlined"
35+
value={newSheetName}
36+
onChange={handleChange}
37+
name="newSheetName"
38+
fullWidth
39+
size="small"
40+
/>
41+
</Grid>
42+
<Grid
43+
item
44+
xs={2}
45+
container
46+
direction="row"
47+
justifyContent="center"
48+
alignItems="center"
49+
>
50+
<Button variant="contained" type="submit">
51+
Submit
52+
</Button>
53+
</Grid>
54+
</Grid>
55+
<Typography variant="caption" gutterBottom>
56+
Enter the name for your new sheet.
57+
</Typography>
58+
<br />
59+
<Typography variant="caption" gutterBottom sx={{ fontStyle: 'italic' }}>
60+
This component is written in typescript!
61+
</Typography>
62+
</form>
63+
);
64+
};
65+
66+
export default FormInput;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Button, Typography } from '@mui/material';
3+
4+
import FormInput from './FormInput';
5+
import SheetTable from './SheetTable';
6+
7+
8+
// This is a wrapper for google.script.run that lets us use promises.
9+
import { serverFunctions } from '../../utils/serverFunctions';
10+
11+
const SheetEditor = () => {
12+
const [names, setNames] = useState([]);
13+
14+
useEffect(() => {
15+
serverFunctions.getSheetsData().then(setNames).catch(alert);
16+
}, []);
17+
18+
const deleteSheet = (sheetIndex) => {
19+
serverFunctions.deleteSheet(sheetIndex).then(setNames).catch(alert);
20+
};
21+
22+
const setActiveSheet = (sheetName) => {
23+
serverFunctions.setActiveSheet(sheetName).then(setNames).catch(alert);
24+
};
25+
26+
const submitNewSheet = async (newSheetName) => {
27+
try {
28+
const response = await serverFunctions.addSheet(newSheetName);
29+
setNames(response);
30+
} catch (error) {
31+
// eslint-disable-next-line no-alert
32+
alert(error);
33+
}
34+
};
35+
36+
return (
37+
<div style={{ padding: '3px', overflowX: 'hidden' }}>
38+
<Typography variant="h4" gutterBottom>
39+
☀️ MUI demo! ☀️
40+
</Typography>
41+
42+
<Typography variant="body1" gutterBottom sx={{ marginBottom: '30px' }}>
43+
This is a sample app that uses the <code>mui</code> library
44+
to help us build a simple React app. Enter a name for a new sheet, hit
45+
enter and the new sheet will be created. Click the red button next to the sheet name to
46+
delete it.
47+
</Typography>
48+
<FormInput submitNewSheet={submitNewSheet} />
49+
50+
{names.length > 0 &&
51+
<SheetTable rows={names.map((name) => {
52+
return {
53+
sheetName: name.name,
54+
goToButton: <Button
55+
variant="outlined"
56+
disabled={name?.isActive}
57+
onClick={() => setActiveSheet(name.name)}
58+
>Go To Sheet</Button>,
59+
deleteButton: <Button
60+
variant="contained"
61+
color="error"
62+
onClick={() => deleteSheet(name.index)}
63+
>Delete</Button>
64+
}
65+
})} />}
66+
</div>
67+
);
68+
};
69+
70+
export default SheetEditor;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as React from 'react';
2+
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
3+
4+
type sheetRow = {
5+
sheetName: string;
6+
goToButton: React.ReactNode;
7+
deleteButton: React.ReactNode;
8+
};
9+
10+
export default function SheetTable({ rows }: { rows: Array<sheetRow> }) {
11+
return (
12+
<TableContainer>
13+
<Table aria-label="simple table">
14+
<TableHead>
15+
<TableRow>
16+
<TableCell>Sheet Name</TableCell>
17+
<TableCell align="center">Go To</TableCell>
18+
<TableCell align="center">Delete</TableCell>
19+
</TableRow>
20+
</TableHead>
21+
<TableBody>
22+
{rows.map((row: sheetRow) => (
23+
<TableRow
24+
key={row.sheetName}
25+
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
26+
>
27+
<TableCell component="th" scope="row">
28+
{row.sheetName}
29+
</TableCell>
30+
<TableCell align="center">{row.goToButton}</TableCell>
31+
<TableCell align="center">{row.deleteButton}</TableCell>
32+
</TableRow>
33+
))}
34+
</TableBody>
35+
</Table>
36+
</TableContainer>
37+
);
38+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<base target="_top" />
5+
<!-- Add any external scripts and stylesheets here -->
6+
</head>
7+
<body>
8+
<section id="index">
9+
<!-- bundled js and css will get inlined here during build-->
10+
</section>
11+
</body>
12+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import SheetEditor from './components/SheetEditor';
4+
5+
import './styles.css';
6+
7+
ReactDOM.render(<SheetEditor />, document.getElementById('index'));
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/server/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
onOpen,
33
openDialog,
44
openDialogBootstrap,
5+
openDialogMUI,
56
openDialogTailwindCSS,
67
openAboutSidebar,
78
} from './ui';
@@ -13,6 +14,7 @@ export {
1314
onOpen,
1415
openDialog,
1516
openDialogBootstrap,
17+
openDialogMUI,
1618
openDialogTailwindCSS,
1719
openAboutSidebar,
1820
getSheetsData,

src/server/ui.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const onOpen = () => {
33
.createMenu('My Sample React Project') // edit me!
44
.addItem('Sheet Editor', 'openDialog')
55
.addItem('Sheet Editor (Bootstrap)', 'openDialogBootstrap')
6+
.addItem('Sheet Editor (MUI)', 'openDialogMUI')
67
.addItem('Sheet Editor (Tailwind CSS)', 'openDialogTailwindCSS')
78
.addItem('About me', 'openAboutSidebar');
89

@@ -23,6 +24,13 @@ export const openDialogBootstrap = () => {
2324
SpreadsheetApp.getUi().showModalDialog(html, 'Sheet Editor (Bootstrap)');
2425
};
2526

27+
export const openDialogMUI = () => {
28+
const html = HtmlService.createHtmlOutputFromFile('dialog-demo-mui')
29+
.setWidth(600)
30+
.setHeight(600);
31+
SpreadsheetApp.getUi().showModalDialog(html, 'Sheet Editor (MUI)');
32+
};
33+
2634
export const openDialogTailwindCSS = () => {
2735
const html = HtmlService.createHtmlOutputFromFile('dialog-demo-tailwindcss')
2836
.setWidth(600)

0 commit comments

Comments
 (0)