Feature: Support closing dialog windows (#233)

Supports closing dialogs in development. Upgrades gas-client to 1.2.0 and uses new API here: Add scriptHostFunctions for google.script.host gas-client#36
Example button to close dialog in Bootstrap sample
Updates integration tests
This commit is contained in:
Elisha Nuchi
2025-03-16 12:13:30 -04:00
committed by GitHub
parent 85223ca42a
commit 248a90023c
17 changed files with 2494 additions and 2502 deletions
@@ -9,9 +9,9 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, macos-13, windows-2022]
os: [macos-13, windows-2022]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
node-version: [18, 20]
node-version: [20]
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
@@ -9,9 +9,9 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, macos-13, windows-2022]
os: [macos-13, windows-2022]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
node-version: [18, 20]
node-version: [20]
timeout-minutes: 11
steps:
- uses: actions/checkout@v4
+8 -2
View File
@@ -309,8 +309,8 @@ google.script.run
.addSheet(sheetTitle);
// Using gas-client we can use more familiar promises style like this:
import Server from 'gas-client';
const { serverFunctions } = new Server();
import { GASClient } from 'gas-client';
const { serverFunctions, scriptHostFunctions } = new GASClient({});
// We now have access to all our server functions, which return promises!
serverFunctions
@@ -327,6 +327,12 @@ async () => {
handleError(err);
}
};
// Use scriptHostFunctions to control dialogs
scriptHostFunctions.close(); // close a dialog or sidebar
scriptHostFunctions.setWidth(400); // set dialog width to 400px
scriptHostFunctions.setHeight(800); // set dialog height to 800px
```
In development, `gas-client` will allow you to call server-side functions from your local environment. In production, it will use Google's underlying `google.script.run` utility.
+11 -5
View File
@@ -20,7 +20,7 @@ Two placeholders are used in this file that will need to be replaced in a build
<base target="_top" />
<title>Dev Server</title>
<!-- Load gas-client as external. Exposed global variable is GASClient. -->
<script src="https://unpkg.com/gas-client@1.1.1/dist/index.js"></script>
<script src="https://unpkg.com/gas-client@1.2.0/dist/index.js"></script>
<style>
body,
html {
@@ -37,15 +37,21 @@ Two placeholders are used in this file that will need to be replaced in a build
const iframe = document.getElementById('iframe');
iframe.src = 'https://localhost:' + PORT + '/' + FILE_NAME;
const { serverFunctions } = new window.GASClient.GASClient({
allowedDevelopmentDomains: (origin) =>
/https:\/\/.*\.googleusercontent\.com$/.test(origin),
});
const { serverFunctions, scriptHostFunctions } =
new window.GASClient.GASClient({
allowedDevelopmentDomains: (origin) =>
/https:\/\/.*\.googleusercontent\.com$/.test(origin),
});
const handleRequest = (event) => {
const request = event.data;
const { type, functionName, id, args } = request;
if (type === 'SCRIPT_HOST_FUNCTION_REQUEST') {
scriptHostFunctions[functionName](...args);
}
if (type !== 'REQUEST') return;
serverFunctions[functionName](...args)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-google-apps-script",
"version": "3.0.0",
"version": "3.1.0",
"type": "module",
"description": "Starter project for using React with Google Apps Script",
"repository": {
@@ -41,7 +41,7 @@
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@mui/material": "^5.11.11",
"gas-client": "^1.1.1",
"gas-client": "^1.2.0",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
@@ -4,10 +4,14 @@ import { Button, ListGroup } from 'react-bootstrap';
import FormInput from './FormInput';
// This is a wrapper for google.script.run that lets us use promises.
import { serverFunctions } from '../../utils/serverFunctions';
import {
serverFunctions,
scriptHostFunctions,
} from '../../utils/serverFunctions';
const SheetEditor = () => {
const [names, setNames] = useState([]);
const [isExpanded, setIsExpanded] = useState(false);
useEffect(() => {
serverFunctions.getSheetsData().then(setNames).catch(alert);
@@ -77,6 +81,29 @@ const SheetEditor = () => {
))}
</TransitionGroup>
</ListGroup>
{names.length > 0 && (
<div className="d-flex justify-content-end py-3">
{!isExpanded ? (
<Button
variant="light"
className="mr-2"
onClick={() => {
scriptHostFunctions.setHeight(1000);
scriptHostFunctions.setWidth(1000);
setIsExpanded(true);
}}
>
Expand Dialog
</Button>
) : null}
<Button
variant="outline-dark"
onClick={() => scriptHostFunctions.close()}
>
Close Dialog Window
</Button>
</div>
)}
</div>
);
};
+1 -1
View File
@@ -21,7 +21,7 @@
></script>
<script
crossorigin
src="https://unpkg.com/gas-client@1.1.1/dist/index.js"
src="https://unpkg.com/gas-client@1.2.0/dist/index.js"
></script>
<script
crossorigin
+1 -1
View File
@@ -17,7 +17,7 @@
></script>
<script
crossorigin
src="https://unpkg.com/gas-client@1.1.1/dist/index.js"
src="https://unpkg.com/gas-client@1.2.0/dist/index.js"
></script>
<script
crossorigin
@@ -17,7 +17,7 @@
></script>
<script
crossorigin
src="https://unpkg.com/gas-client@1.1.1/dist/index.js"
src="https://unpkg.com/gas-client@1.2.0/dist/index.js"
></script>
<script
crossorigin
+1 -1
View File
@@ -17,7 +17,7 @@
></script>
<script
crossorigin
src="https://unpkg.com/gas-client@1.1.1/dist/index.js"
src="https://unpkg.com/gas-client@1.2.0/dist/index.js"
></script>
<script
crossorigin
+4 -2
View File
@@ -1,10 +1,12 @@
import { GASClient } from 'gas-client';
import * as publicServerFunctions from '../../server';
const { serverFunctions } = new GASClient<typeof publicServerFunctions>({
const { serverFunctions, scriptHostFunctions } = new GASClient<
typeof publicServerFunctions
>({
// this is necessary for local development but will be ignored in production
allowedDevelopmentDomains: (origin) =>
/https:\/\/.*\.googleusercontent\.com$/.test(origin),
});
export { serverFunctions };
export { serverFunctions, scriptHostFunctions };
Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 63 KiB

+3 -3
View File
@@ -26,7 +26,7 @@ const srcTestFile = path.join(
'../src/client/dialog-demo-bootstrap/components/SheetEditor.jsx'
);
const webpackDevServerReady = async (process) => {
const viteDevServerReady = async (process) => {
console.log('Waiting for vite to serve...');
return new Promise((resolve) => {
process.stdout.on('data', (data) => {
@@ -40,7 +40,7 @@ const webpackDevServerReady = async (process) => {
describe(`Local setup ${isExtended ? '*extended*' : ''}`, () => {
let page;
let process;
const containerSelector = isExtended ? '.script-app-dialog' : 'body';
const containerSelector = isExtended ? 'div[role="dialog"]' : 'body';
beforeAll(async () => {
process = exec('yarn dev');
@@ -52,7 +52,7 @@ describe(`Local setup ${isExtended ? '*extended*' : ''}`, () => {
deviceScaleFactor: 1,
});
await webpackDevServerReady(process);
await viteDevServerReady(process);
if (isExtended) {
await openAddon(page);
+3 -2
View File
@@ -1,6 +1,7 @@
export const openAddon = async (page) => {
await page.goto(process.env.SHEET_URL);
await page.waitForTimeout(5000); // pause for 3 seconds
await page.click('a:nth-child(2)'); // click on signin button
await page.waitForSelector('input[name="identifier"]', { visible: true });
@@ -97,10 +98,10 @@ export const openAddon = async (page) => {
new MouseEvent('mouseup', { bubbles: true })
);
});
await page.waitForSelector('.script-app-dialog', {
await page.waitForSelector('div[role="dialog"]', {
visible: true,
timeout: 10000,
});
await page.waitForTimeout(3000);
await page.waitForTimeout(15000);
};
+2427 -2477
View File
File diff suppressed because it is too large Load Diff