add Bootstrap working example
• re-organize file structure with one directory per dialog • add index.html file per dialog • add bootstrap styling and dynamic cdn loading • clean up react code and stylesheet npm setup script update adds force flag "setup": "rm -f .clasp.json ..." Update README.md Move clasp to devDependencies update dynamic cdn urls Add repository field
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
||||
import { Form, Button, ListGroup, Col, Row } from 'react-bootstrap';
|
||||
|
||||
// This is a wrapper for google.script.run that lets us use promises.
|
||||
import server from '../../utils/server';
|
||||
|
||||
const SheetEditor = () => {
|
||||
const [newSheetName, setNewSheetName] = useState('');
|
||||
const [names, setNames] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
server
|
||||
.getSheetsData()
|
||||
.then(setNames)
|
||||
.catch(alert);
|
||||
}, []);
|
||||
|
||||
const deleteSheet = sheetIndex => {
|
||||
server
|
||||
.deleteSheet(sheetIndex)
|
||||
.then(setNames)
|
||||
.catch(alert);
|
||||
};
|
||||
|
||||
const setActiveSheet = sheetName => {
|
||||
server
|
||||
.setActiveSheet(sheetName)
|
||||
.then(setNames)
|
||||
.catch(alert);
|
||||
};
|
||||
|
||||
const submitNewSheet = async () => {
|
||||
try {
|
||||
const response = await server.addSheet(newSheetName);
|
||||
setNames(response);
|
||||
} catch (error) {
|
||||
alert(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: '3px', overflowX: 'hidden' }}>
|
||||
<Form onSubmit={submitNewSheet}>
|
||||
<Form.Group controlId="formNewSheet">
|
||||
<Form.Label>Add a new sheet</Form.Label>
|
||||
<Row>
|
||||
<Col xs={10}>
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder="Sheet name"
|
||||
value={newSheetName}
|
||||
onChange={e => {
|
||||
setNewSheetName(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={2}>
|
||||
<Button variant="primary" type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Text className="text-muted">
|
||||
Enter the name for your new sheet.
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
<ListGroup>
|
||||
<TransitionGroup className="sheet-list">
|
||||
{names.length > 0 &&
|
||||
names.map(name => (
|
||||
<CSSTransition
|
||||
classNames="sheetNames"
|
||||
timeout={500}
|
||||
key={name.name}
|
||||
>
|
||||
<ListGroup.Item
|
||||
className="d-flex"
|
||||
key={`${name.index}-${name.name}`}
|
||||
>
|
||||
<Button
|
||||
className="border-0"
|
||||
variant="outline-danger"
|
||||
size="sm"
|
||||
onClick={() => deleteSheet(name.index)}
|
||||
>
|
||||
×
|
||||
</Button>
|
||||
<Button
|
||||
className="border-0 mx-2"
|
||||
variant={name.isActive ? 'success' : 'outline-success'}
|
||||
onClick={() => setActiveSheet(name.name)}
|
||||
>
|
||||
{name.name}
|
||||
</Button>
|
||||
</ListGroup.Item>
|
||||
</CSSTransition>
|
||||
))}
|
||||
</TransitionGroup>
|
||||
</ListGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SheetEditor;
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<base target="_top" />
|
||||
<!-- Add any external scripts and stylesheets here -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
|
||||
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<section id="index">
|
||||
<!-- bundled js and css will get inlined here during build-->
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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'));
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
CSSTransitionGroup styling
|
||||
*/
|
||||
.sheetNames-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.sheetNames-enter.sheetNames-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
|
||||
.sheetNames-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sheetNames-exit.sheetNames-exit-active {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
|
||||
.sheetNames-appear {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.sheetNames-appear.sheetNames-appear-active {
|
||||
opacity: 1;
|
||||
transition: opacity 0.5ms ease-in;
|
||||
}
|
||||
Reference in New Issue
Block a user