Sunday, May 8, 2022

How to create React.js app for Google Apps Script WebApp Project in ChromeOS

(1) Goto https://script.google.com/home/usersettings and enable Google Apps Script API

(2) Install nodejs and required packages using Terminal Command
shell script    Select all
sudo apt install nodejs npm mkdir -p ~/webappreact cd ~/webappreact npm init -y #Change the following file in ~/webappreact/package.json as cat > ~/webappreact/package.json <<EOF { "name": "webappreact", "version": "1.0.0", "description": "", "scripts": { "glogin": "clasp login", "glogout": "clasp logout", "gcreate": "clasp create --title 'React Test Project' --rootDir ./apps-script", "gpush": "clasp push", "gpull": "clasp pull", "gstart": "clasp push --watch", "build": "parcel build src/index.html --dist-dir ./apps-script", "start": "parcel src/index.html --dist-dir ./apps-script" }, "keywords": [], "author": "", "license": "ISC" } EOF # install dependencies npm install -D @google/clasp npm install -D @types/google-apps-script # if you use VS Code Editor in ChromeOS npm install -D parcel npm install react react-dom mkdir -p ~/webappreact/apps-script # create ~/webappreact/apps-script/main.js as cat > ~/webappreact/apps-script/main.js <<EOF function doGet() { return HtmlService.createTemplateFromFile("index") .evaluate() .addMetaTag("viewport","width=device-width, initial-scale=1.0") } EOF mkdir -p ~/webappreact/src # create ~/webappreact/src/index.html as cat > ~/webappreact/src/index.html <<EOF <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"></div> <script type="module"> import "./index.js" </script> </body> </html> EOF # create ~/webappreact/src/index.js as cat > ~/webappreact/src/index.js <<EOF import React from "react" import App from "./App" import { createRoot } from 'react-dom/client'; const container = document.getElementById('app'); const root = createRoot(container); root.render(<App />, app) EOF # create ~/webappreact/src/App.js as cat > ~/webappreact/src/App.js <<EOF function App() { return <div> <h1>First React App</h1> <p>Hello World</p> </div> } export default App EOF



(3) Test building and push to Google Drive using Terminal Command
shell script    Select all
# Testing building cd ~/webappreact npm run build # Testing running in localhost:1234 # For Chrome Browser, please install React Developer Tools in chrome web store for testing at localhost npm run start # Login in to google apps script npm run glogin # Create Project in google apps script and choose spreadsheet npm run gcreate mv ~/webappreact/apps-script/.clasp.json ~/webappreact/ # Push to google apps script npm run gpush



(4) Browser Go to https://script.google.com/home and deploy the React Test Project as webapp and test



(5) Add CSS and react-router
shell script    Select all
mkdir -p ~/webappreact/src/styles/ #Add ~/webappreact/src/styles/main.scss as cat > ~/webappreact/src/styles/main.scss <<EOF h1 { color:green; font-size: 2rem; } p { color:purple; } .css-nav { padding-left: 15px; padding-right: 15px; } EOF # change ~/webappreact/src/index.html as cat > ~/webappreact/src/index.html <<EOF <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> @import "./styles/main.scss"; </style> </head> <body> <div id="app"></div> <script type="module"> import "./index.js" </script> </body> </html> EOF # install dependencies npm install react-router-dom@6 mkdir -p ~/webappreact/src/components # create ~/webappreact/src/components/Home.js as cat > ~/webappreact/src/components/Home.js <<EOF function Home() { return <> <h1>HomePage</h1> </> } export default Home EOF # create ~/webappreact/src/components/About.js as cat > ~/webappreact/src/components/About.js <<EOF function About() { return <> <h1>About</h1> </> } export default About EOF # create ~/webappreact/src/components/Nav.js as cat > ~/webappreact/src/components/Nav.js <<EOF import { Link } from "react-router-dom" function Nav() { return <> <span className="css-nav"><Link to="/">Home</Link></span> <span className="css-nav"><Link to="/about">About</Link></span> </> } export default Nav EOF # change ~/webappreact/src/index.js as cat > ~/webappreact/src/index.js <<EOF import React from "react" import { BrowserRouter } from "react-router-dom" import App from "./App" import { createRoot } from 'react-dom/client'; const container = document.getElementById('app'); const root = createRoot(container); root.render(<BrowserRouter><App /></BrowserRouter>) EOF # change ~/webappreact/src/App.js as cat > ~/webappreact/src/App.js <<EOF import { Routes, Route } from "react-router-dom" import Home from "./components/Home" import About from "./components/About" import Nav from "./components/Nav" function App() { return <> <Nav /> <Routes> <Route path="/" element={<Home />} /> <Route path="about" element={<About />} /> <Route path="*" element={<Home />} /> </Routes> </> } export default App EOF



(6) Test building and push to Google Drive using Terminal Command
shell script    Select all
# Testing building cd ~/webappreact npm run build # Testing running in localhost:1234 npm run start # Push to google apps script npm run gpush # test again in webapp of Google Apps Script



(7) Add google apps script getData() function as backend
shell script    Select all
# Change ~/webappreact/apps-script/main.js as cat > ~/webappreact/apps-script/main.js <<EOF function doGet() { return HtmlService.createTemplateFromFile("index") .evaluate() .addMetaTag("viewport","width=device-width, initial-scale=1.0") } function getData() { return ( [{ "key": "apple", "value": "green" }, { "key": "banana", "value": "yellow" }] ); } function getSpreadData() { return SpreadsheetApp .getActiveSpreadsheet() .getActiveSheet() .getDataRange() .getValues(); } EOF # Change ~/webappreact/src/components/About.js as cat > ~/webappreact/src/components/About.js <<EOF import React, {useState, useEffect} from "react" function About() { const [data,setData] = useState(null) const [loading, setLoading] = useState(false) if (typeof google === 'object') { useEffect(()=>{ setLoading(true) google.script.run.withSuccessHandler(response => { setData([...response]) setLoading(false) }).withFailureHandler(er => { alert(er) }).getData() },[]) } else { return <> <h1>About</h1> <table> <tbody> <tr> <td><span style={{paddingLeft:'30px',paddingRight:'30px'}}>key: row.key</span></td> <td><span style={{paddingRight:'30px'}}>value: row.value</span></td> </tr> </tbody> </table> </> } if (loading) return <h1>loading...</h1> if (!data) return null; return <> <h1>About Data</h1> <table> <tbody> { data.map((row) => ( <tr> <td><span style={{paddingLeft:'30px',paddingRight:'30px'}}>key: {row.key}</span></td> <td><span style={{paddingRight:'30px'}}>value: {row.value}</span></td> </tr> )) } </tbody> </table> </> } export default About EOF



(8) Push to Google Drive and test in Google Apps Script Web App
shell script    Select all
# Testing building and Push to google apps script cd ~/webappreact npm run build && npm run gpush # test again in webapp of Google Apps Script