Add Material UI demo (#173)

Adds working example with Material UI
This commit is contained in:
h-contributeur
2023-03-10 21:01:46 +01:00
committed by GitHub
parent 7fd979aed8
commit f9a1d02588
11 changed files with 1032 additions and 138 deletions
+793 -138
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -34,6 +34,9 @@
"npm": ">=6.0.0"
},
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@mui/material": "^5.11.11",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
@@ -0,0 +1,66 @@
import React, { useState, ChangeEvent, FormEvent } from 'react';
import { Button, Grid, TextField, Typography } from '@mui/material';
interface FormInputProps {
submitNewSheet: (sheetName: string) => {
name: string;
index: number;
isActive: boolean;
};
}
const FormInput = ({ submitNewSheet }: FormInputProps) => {
const [newSheetName, setNewSheetName] = useState('');
const handleChange = (event: ChangeEvent<HTMLInputElement>) =>
setNewSheetName(event.target.value);
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (newSheetName.length === 0) return;
submitNewSheet(newSheetName);
setNewSheetName('');
};
return (
<form
onSubmit={handleSubmit}
>
<Grid container spacing={2}>
<Grid item xs={10}>
<TextField
id="sheet-name"
label="New Sheet Name"
variant="outlined"
value={newSheetName}
onChange={handleChange}
name="newSheetName"
fullWidth
size="small"
/>
</Grid>
<Grid
item
xs={2}
container
direction="row"
justifyContent="center"
alignItems="center"
>
<Button variant="contained" type="submit">
Submit
</Button>
</Grid>
</Grid>
<Typography variant="caption" gutterBottom>
Enter the name for your new sheet.
</Typography>
<br />
<Typography variant="caption" gutterBottom sx={{ fontStyle: 'italic' }}>
This component is written in typescript!
</Typography>
</form>
);
};
export default FormInput;
@@ -0,0 +1,70 @@
import React, { useState, useEffect } from 'react';
import { Button, Typography } from '@mui/material';
import FormInput from './FormInput';
import SheetTable from './SheetTable';
// This is a wrapper for google.script.run that lets us use promises.
import { serverFunctions } from '../../utils/serverFunctions';
const SheetEditor = () => {
const [names, setNames] = useState([]);
useEffect(() => {
serverFunctions.getSheetsData().then(setNames).catch(alert);
}, []);
const deleteSheet = (sheetIndex) => {
serverFunctions.deleteSheet(sheetIndex).then(setNames).catch(alert);
};
const setActiveSheet = (sheetName) => {
serverFunctions.setActiveSheet(sheetName).then(setNames).catch(alert);
};
const submitNewSheet = async (newSheetName) => {
try {
const response = await serverFunctions.addSheet(newSheetName);
setNames(response);
} catch (error) {
// eslint-disable-next-line no-alert
alert(error);
}
};
return (
<div style={{ padding: '3px', overflowX: 'hidden' }}>
<Typography variant="h4" gutterBottom>
☀️ MUI demo! ☀️
</Typography>
<Typography variant="body1" gutterBottom sx={{ marginBottom: '30px' }}>
This is a sample app that uses the <code>mui</code> library
to help us build a simple React app. Enter a name for a new sheet, hit
enter and the new sheet will be created. Click the red button next to the sheet name to
delete it.
</Typography>
<FormInput submitNewSheet={submitNewSheet} />
{names.length > 0 &&
<SheetTable rows={names.map((name) => {
return {
sheetName: name.name,
goToButton: <Button
variant="outlined"
disabled={name?.isActive}
onClick={() => setActiveSheet(name.name)}
>Go To Sheet</Button>,
deleteButton: <Button
variant="contained"
color="error"
onClick={() => deleteSheet(name.index)}
>Delete</Button>
}
})} />}
</div>
);
};
export default SheetEditor;
@@ -0,0 +1,38 @@
import * as React from 'react';
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
type sheetRow = {
sheetName: string;
goToButton: React.ReactNode;
deleteButton: React.ReactNode;
};
export default function SheetTable({ rows }: { rows: Array<sheetRow> }) {
return (
<TableContainer>
<Table aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Sheet Name</TableCell>
<TableCell align="center">Go To</TableCell>
<TableCell align="center">Delete</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row: sheetRow) => (
<TableRow
key={row.sheetName}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.sheetName}
</TableCell>
<TableCell align="center">{row.goToButton}</TableCell>
<TableCell align="center">{row.deleteButton}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<base target="_top" />
<!-- Add any external scripts and stylesheets here -->
</head>
<body>
<section id="index">
<!-- bundled js and css will get inlined here during build-->
</section>
</body>
</html>
+7
View File
@@ -0,0 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import SheetEditor from './components/SheetEditor';
import './styles.css';
ReactDOM.render(<SheetEditor />, document.getElementById('index'));
+4
View File
@@ -0,0 +1,4 @@
/* needed to make consistent test snapshots across OSs */
body {
font-family: Arial !important;
}
+2
View File
@@ -2,6 +2,7 @@ import {
onOpen,
openDialog,
openDialogBootstrap,
openDialogMUI,
openDialogTailwindCSS,
openAboutSidebar,
} from './ui';
@@ -13,6 +14,7 @@ export {
onOpen,
openDialog,
openDialogBootstrap,
openDialogMUI,
openDialogTailwindCSS,
openAboutSidebar,
getSheetsData,
+8
View File
@@ -3,6 +3,7 @@ export const onOpen = () => {
.createMenu('My Sample React Project') // edit me!
.addItem('Sheet Editor', 'openDialog')
.addItem('Sheet Editor (Bootstrap)', 'openDialogBootstrap')
.addItem('Sheet Editor (MUI)', 'openDialogMUI')
.addItem('Sheet Editor (Tailwind CSS)', 'openDialogTailwindCSS')
.addItem('About me', 'openAboutSidebar');
@@ -23,6 +24,13 @@ export const openDialogBootstrap = () => {
SpreadsheetApp.getUi().showModalDialog(html, 'Sheet Editor (Bootstrap)');
};
export const openDialogMUI = () => {
const html = HtmlService.createHtmlOutputFromFile('dialog-demo-mui')
.setWidth(600)
.setHeight(600);
SpreadsheetApp.getUi().showModalDialog(html, 'Sheet Editor (MUI)');
};
export const openDialogTailwindCSS = () => {
const html = HtmlService.createHtmlOutputFromFile('dialog-demo-tailwindcss')
.setWidth(600)
+29
View File
@@ -58,6 +58,12 @@ const clientEntrypoints = [
filename: 'dialog-demo-bootstrap',
template: './src/client/dialog-demo-bootstrap/index.html',
},
{
name: 'CLIENT - Dialog Demo MUI',
entry: './src/client/dialog-demo-mui/index.js',
filename: 'dialog-demo-mui',
template: './src/client/dialog-demo-mui/index.html',
},
{
name: 'CLIENT - Dialog Demo Tailwind CSS',
entry: './src/client/dialog-demo-tailwindcss/index.js',
@@ -209,6 +215,29 @@ const DynamicCdnWebpackPluginConfig = {
version: packageVersion,
url: `https://unpkg.com/react-bootstrap@${packageVersion}/dist/react-bootstrap${packageSuffix}`,
};
case '@mui/material':
return {
name: packageName,
var: 'MaterialUI',
version: packageVersion,
url: `https://unpkg.com/@mui/material@${packageVersion}/umd/material-ui.${
isProd ? 'production.min.js' : 'development.js'
}`,
};
case '@emotion/react':
return {
name: packageName,
var: 'emotionReact',
version: packageVersion,
url: `https://unpkg.com/@emotion/react@${packageVersion}/dist/emotion-react.umd.min.js`,
};
case '@emotion/styled':
return {
name: packageName,
var: 'emotionStyled',
version: packageVersion,
url: `https://unpkg.com/@emotion/styled@${packageVersion}/dist/emotion-styled.umd.min.js`,
};
// externalize gas-client to keep bundle size even smaller
case 'gas-client':
return {