作者: javacomhk 時間: 2022-5-16 19:53 標題: 用 ChromeOS/Linux 開發 Google Apps Script WebApp 不用起 server 續篇
本帖最後由 javacomhk 於 2022-5-19 17:48 編輯
請首先參考這篇怎樣設定 React.js + Bootstrap 開發 Cloud 嘅 WebApp 教學,而現在呢一續篇是延續上一篇去講解 Google Apps Script WebApp 最精彩及重要的 backend 功能,就係可儲存及讀取在 Google Spreadsheet 嘅 data。與及在儲存 Spreadsheet data 後立即用 Gmail 服務去觸發 sendMail 功能。
(D) 第四部份,使用 React.js + Bootstrap 增加 Input Form 及 Validation Rules 另外修改網頁去顯示 Google Spreadsheet data。
(D1) 修改以下文件 ~/webappreact/src/App.js 內容為
- import { Routes, Route } from "react-router-dom"
- import Home from "./components/Home"
- import About from "./components/About"
- import Data from "./components/Data"
- import FormInput from "./components/FormInput"
- import Nav from "./components/Nav"
- function App() {
- return <>
- <Nav />
- <Routes>
- <Route path="/" element={<Home />} />
- <Route path="/about" element={<About />} />
- <Route path="/data" element={<Data />} />
- <Route path="/form" element={<FormInput />} />
- <Route path="*" element={<Home />} />
- </Routes>
- </>
- }
- export default App
- 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>
- <span className="css-nav"><Link to="data">Data</Link></span>
- <span className="css-nav"><Link to="form">Form</Link></span>
- </>
- }
- export default Nav
- import React, {useState, useEffect} from "react"
- import {Container, Table} from "react-bootstrap";
- function Data() {
- const [jsonResults,setJsonResults] = useState(null)
- const [data,setData] = useState(null)
- const [loading, setLoading] = useState(false)
- if (typeof google === 'object') {
- useEffect(()=>{
- setLoading(true)
- google.script.run.withSuccessHandler(response => {
- console.log(response)
- const [...values] = JSON.parse(response);
- const keys = ["firstname","lastname","country","email","date"];
- const objects = values.map(array => array.reduce((a, v, i) => ({...a, [keys[i]]: v}), {}));
- console.log(objects);
- setData([...objects])
- setLoading(false);
- }).withFailureHandler(er => {
- alert(er)
- }).getSpreadData();
- },[])
- }
- else {
- return <>
- <Container>
- <div style={{"height": "30px"}}/>
- <h1 className="h1">Test getData from localhost</h1>
- <Table striped bordered hover>
- <thead>
- <tr>
- <th>#</th>
- <th>First Name</th>
- <th>Last Name</th>
- <th>Creation Date</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>1</td>
- <td>FirstName 1</td>
- <td>LastName 1</td>
- <td>20220516</td>
- </tr>
- <tr>
- <td>2</td>
- <td>FirstName 2</td>
- <td>LastName 2</td>
- <td>20220517</td>
- </tr>
- </tbody>
- </Table>
- </Container>
- </>
- }
- if (loading) return <h1>loading...</h1>
- if (!data) return null;
- console.log(JSON.stringify(data))
- return <>
- <Container>
- <div style={{"height": "30px"}}/>
- <h1 className="h1">getData from Google SpreadSheet</h1>
- <Table striped bordered hover>
- <thead>
- <tr>
- <th>#</th>
- <th>First Name</th>
- <th>Last Name</th>
- <th>Creation Date</th>
- </tr>
- </thead>
- <tbody>
- { data.map((row, index) => (
- <tr key={index}>
- <td>{index}</td>
- <td>{row.firstname}</td>
- <td>{row.lastname}</td>
- <td>{row.date}</td>
- </tr>
- ))
- }
- </tbody>
- </Table>
- </Container>
- </>
- }
- export default Data
- function doGet() {
- return HtmlService.createTemplateFromFile("index")
- .evaluate()
- .addMetaTag("viewport","width=device-width, initial-scale=1.0")
- }
- function getData() {
- console.log("getData()")
- return (
- [{
- "key": "apple",
- "value": "green"
- },
- {
- "key": "banana",
- "value": "yellow"
- }]
- );
- }
- function getSpreadData() {
- const data = SpreadsheetApp
- .getActiveSpreadsheet()
- .getActiveSheet()
- .getDataRange()
- .getValues();
- console.log("getSpreadData() "+ JSON.stringify(data))
- return JSON.stringify(data)
- }
- function AddRecord(firstname, lastname, country, email) {
- console.log("AddRecord() "+ email)
- var webAppSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
- const datestr = (new Date().toLocaleString('sv',{timeZone: 'Asia/Hong_Kong'})).slice(0, 19).replace(/-/g, "").replace(/:/g, "").replace("T", " ");
- webAppSheet.appendRow([firstname, lastname, country, email, datestr]);
- // sendEmailfromdoc(firstname, lastname, email);
- }
- function sendEmailfromdoc(firstname, lastname, email){
- // fill in google doc ID here
- var id = 'FILL-IN-GOOGLE-DOC-ID-HERE' ;
- var forDriveScope = DriveApp.getStorageUsed(); //needed to get Drive Scope requested
- var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+id+"&exportFormat=html";
- var param = {
- method : "get",
- headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
- muteHttpExceptions:true,
- };
- var html = UrlFetchApp.fetch(url,param).getContentText();
- // email send out with replaced fields
- var htmlout1 = html.replace("{{title_1}}","Welcome to join our Newsletter subscription");
- htmlout1 = htmlout1.replace("{{heading_1}}","Dear "+ firstname +" "+lastname);
- htmlout1 = htmlout1.replace("{{heading_2}}","You have subscribed our Newsletter successfully.");
- // Logger.log(htmlout1);
- MailApp.sendEmail({
- to: email,
- subject: "Newsletter Registration",
- htmlBody: htmlout1
- });
- console.log('email sent to '+ email + ' !!')
- }
- 上傳在 … https://pastebin.com/nFWTgrdz
(D7) 新增及修改完 Code 後可根據上一篇的(B9) 的方法執行 npm run build 及 npm run gpush 後預備在 Google WebApp 測試,接著便可用 Browser 打入Test Development 的Web URL 去測試 Input Form,今次主要測試Form 內的 Registration Form Input,成功後如下截圖。
[attach]2320492[/attach][attach]2320493[/attach]
(E) 第五部份,製作 email template 及修改 Google Apps Script Code 去測試 Gmail 服務
(E1) 用 Chrome Browser在 drive.google.com 新增一個 Google doc 作為 email template ,內容如下圖,具備有 {{title_1}} {{heading_1}} {{heading_2}} 等字串及或附加任何圖片或文字格式。

(E2) 在 Browser 網址欄中取得當時這個 Google doc 的 ID 字串(如下圖)。
(E3) 將這個 ID 貼在 ~/webappreact/src/apps-script/main.js 檔的相應位置(如下圖)及同時 uncomment (即去除最開頭嘅 // 字符) 這句 sendEmailfromdoc 代碼讓 input form save data 後隨即執行 sendMail 功能。
[attach]2320497[/attach]
[attach]2320496[/attach]
(E4) 修改完 Code 後可根據上一篇的(B9) 方法執行 npm run build 及 npm run gpush 後預備在 Google WebApp 測試。
(E5) Browser 在 drive.google.com 打開 React Test Project ,進入 Apps Script Editor 透過執行任何 function 例如 getData() ,便會激發要求去授權取得 Authorisation token 讀取 Google doc 及可以去 send mail 。
(E6) 接著便可使用 Test Development 的 Web URL 去測試 Input Form 內輸入你自己的電郵地址去登記,看看是否可以收到郵件如下截圖。
[attach]2320491[/attach]
作者: javacomhk 時間: 2022-5-16 20:22
本帖最後由 javacomhk 於 2022-5-19 17:35 編輯
留位
作者: javacomhk 時間: 2022-5-17 03:07
本帖最後由 javacomhk 於 2022-5-19 17:36 編輯
留位
