update webpack, update packages, dev experience

update webpack, clasp, client code, eslint, prettier, readme, packages to latest
This commit is contained in:
Elisha Nuchi
2020-05-03 05:12:50 -04:00
parent f898046c06
commit 0ea874e8b4
30 changed files with 1978 additions and 2851 deletions
+29 -7
View File
@@ -1,8 +1,12 @@
{
"root": true,
"parser": "babel-eslint",
"extends": ["airbnb-base", "plugin:react/recommended", "eslint:recommended"],
"plugins": ["babel", "react"],
"extends": [
"airbnb-base",
"plugin:prettier/recommended",
"plugin:react/recommended"
],
"plugins": ["babel", "react", "prettier"],
"env": {
"browser": true,
"es6": true
@@ -12,11 +16,29 @@
"alert": false,
"css": true
},
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"import/prefer-default-export": 0,
"no-console": 0,
"require-jsdoc": 0,
"no-invalid-this": 0,
"babel/no-invalid-this": 0
"prettier/prettier": "error",
"react/prop-types": "warn",
"camelcase": "warn",
"import/prefer-default-export": "warn",
"import/no-extraneous-dependencies": "warn",
"prefer-object-spread": "warn"
},
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"node": {
"extensions": [".js", ".jsx"]
}
}
}
}
+5
View File
@@ -0,0 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import About from './components/About';
ReactDOM.render(<About />, document.getElementById('index'));
+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'));
-8
View File
@@ -1,8 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {AboutPage} from './components/about-sidebar';
ReactDOM.render(
<AboutPage />,
document.getElementById('index')
);
@@ -1,6 +1,6 @@
import React from 'react';
export const AboutPage = () => (
const About = () => (
<div className="sheetNameText">
<div>Github repo:</div>
<a
@@ -13,3 +13,5 @@ export const AboutPage = () => (
<div>-Elisha Nuchi</div>
</div>
);
export default About;
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
export default function FormInput(props) {
const FormInput = ({ newSheetFormHandler }) => {
const [text, setText] = useState('');
const handleChange = event => setText(event.target.value);
@@ -10,7 +10,7 @@ export default function FormInput(props) {
event.preventDefault();
if (text.length === 0) return;
props.newSheetFormHandler(event, text);
newSheetFormHandler(event, text);
setText('');
};
@@ -22,7 +22,9 @@ export default function FormInput(props) {
</form>
</div>
);
}
};
export default FormInput;
FormInput.propTypes = {
newSheetFormHandler: PropTypes.func,
@@ -1,9 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
const SheetButton = props => {
const { name, deleteButtonHandler, clickSheetNameHandler } = props;
const SheetButton = ({ name, deleteButtonHandler, clickSheetNameHandler }) => {
const { sheetIndex, text, isActive } = name;
return (
@@ -11,7 +9,7 @@ const SheetButton = props => {
<button onClick={e => deleteButtonHandler(e, sheetIndex)}>X</button>
<span
onClick={e => clickSheetNameHandler(e, text)}
className={'sheetNameText ' + (isActive ? 'active-sheet' : '')}
className={`sheetNameText ${isActive ? 'active-sheet' : ''}`}
>
{text}
</span>
@@ -22,7 +20,11 @@ const SheetButton = props => {
export default SheetButton;
SheetButton.propTypes = {
name: PropTypes.object,
name: PropTypes.shape({
sheetIndex: PropTypes.number,
text: PropTypes.string,
isActive: PropTypes.bool,
}),
deleteButtonHandler: PropTypes.func,
clickSheetNameHandler: PropTypes.func,
};
+67
View File
@@ -0,0 +1,67 @@
/* eslint-disable no-alert */
import React, { useState, useEffect } from 'react';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import FormInput from './FormInput';
import SheetButton from './SheetButton';
import server from '../server';
const SheetEditor = () => {
const { getSheetsData, addSheet, deleteSheet, setActiveSheet } = server;
const [names, setNames] = useState([]);
useEffect(() => {
getSheetsData()
.then(setNames)
.catch(alert);
}, []);
const deleteButtonHandler = (e, sheetIndex) => {
deleteSheet(sheetIndex)
.then(setNames)
.catch(alert);
};
const clickSheetNameHandler = (e, sheetName) => {
setActiveSheet(sheetName)
.then(setNames)
.catch(alert);
};
// just for fun, let's use async/await for this one
const newSheetFormHandler = async (e, newSheetTitle) => {
try {
const response = await addSheet(newSheetTitle);
setNames(response);
} catch (error) {
alert(error);
}
};
return (
<div>
<FormInput newSheetFormHandler={newSheetFormHandler} />
<TransitionGroup className="todo-list">
{names.length &&
names.map(name => (
<CSSTransition
transitionName="sheetNames"
transitionAppear={true}
transitionEnterTimeout={300}
transitionLeaveTimeout={300}
key={name.sheetName}
>
<SheetButton
name={name}
deleteButtonHandler={deleteButtonHandler}
clickSheetNameHandler={clickSheetNameHandler}
/>
</CSSTransition>
))}
</TransitionGroup>
</div>
);
};
export default SheetEditor;
-61
View File
@@ -1,61 +0,0 @@
import React, { useState, useEffect } from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import FormInput from './form-input';
import SheetButton from './sheet-button';
import server from '../server';
export default function SheetEditor() {
const { getSheetsData, addSheet, deleteSheet, setActiveSheet } = server;
const [names, setNames] = useState([]);
useEffect(() => {
getSheetsData()
.then(setNames)
.catch(alert);
}, []);
const deleteButtonHandler = (e, sheetIndex) => {
deleteSheet(sheetIndex)
.then(setNames)
.catch(alert);
};
const clickSheetNameHandler = (e, sheetName) => {
setActiveSheet(sheetName)
.then(setNames)
.catch(alert);
};
const newSheetFormHandler = (e, newSheetTitle) => {
addSheet(newSheetTitle)
.then(setNames)
.catch(alert);
};
return (
<div>
<FormInput newSheetFormHandler={newSheetFormHandler} />
<ReactCSSTransitionGroup
transitionName="sheetNames"
transitionAppear={true}
transitionEnterTimeout={100}
transitionLeaveTimeout={100}
>
{names.length
? names.map(name => {
return (
<SheetButton
name={name}
deleteButtonHandler={deleteButtonHandler}
clickSheetNameHandler={clickSheetNameHandler}
key={name.sheetName}
/>
);
})
: null}
</ReactCSSTransitionGroup>
</div>
);
}
-10
View File
@@ -1,10 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import SheetEditor from './components/sheet-editor';
import './styles.css';
ReactDOM.render(
<SheetEditor />,
document.getElementById('index')
);
+23 -20
View File
@@ -1,29 +1,32 @@
/*
Convert google script server calls to more
familiar js/promise-based functions.
*/
// Convert google script server calls to more familiar promise-based functions
const serverMethods = {};
const myServerFunctions = {};
// skip the reserved methods
const ignoredMethods = [
// identify the reserved functions
const ignoredMethods = new Set([
'withFailureHandler',
'withLogger',
'withSuccessHandler',
'withUserObject',
];
]);
for (const method in google.script.run) {
if (!ignoredMethods.includes(method)) {
serverMethods[method] = (...args) => {
return new Promise((resolve, reject) => {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)[method](...args);
});
};
}
}
// get all the public/global function names from the server
const serverFunctionNames = Object.keys(google.script.run);
// filter out the reserved names
const myServerFunctionNames = serverFunctionNames.filter(
serverFunction => !ignoredMethods.has(serverFunction)
);
export default serverMethods;
// save each function to our new server object using promises
myServerFunctionNames.forEach(serverFunctionName => {
myServerFunctions[serverFunctionName] = (...args) =>
new Promise((resolve, reject) => {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
[serverFunctionName](...args);
});
});
export default myServerFunctions;