248a90023c
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
89 lines
3.0 KiB
HTML
89 lines
3.0 KiB
HTML
<!--
|
|
This is a development server page that serves as a wrapper for Google Apps Script (GAS) client-side development.
|
|
|
|
It is meant to be run inside a Google Sheets/Docs/Forms dialog window during local development.
|
|
|
|
It loads the gas-client library (as an external), sets up an iframe that points to a local development
|
|
server (such as running with vite), and establishes a communication bridge between the GAS server functions and the local development server.
|
|
|
|
This allows for local development and testing of client-side code while still being able to interact with
|
|
the GAS server-side functions.
|
|
|
|
Two placeholders are used in this file that will need to be replaced in a build step:
|
|
- _ _PORT_ _: The port number of the local development server. (e.g. 3000)
|
|
- _ _FILE_NAME_ _: The name of the file being loaded. (e.g. dialog-demo-bootstrap/index.html)
|
|
|
|
-->
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<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.2.0/dist/index.js"></script>
|
|
<style>
|
|
body,
|
|
html {
|
|
margin: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// These values need to be replaced during the build process
|
|
const PORT = '__PORT__';
|
|
const FILE_NAME = '__FILE_NAME__';
|
|
|
|
const iframe = document.getElementById('iframe');
|
|
iframe.src = 'https://localhost:' + PORT + '/' + FILE_NAME;
|
|
|
|
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)
|
|
.then((response) => {
|
|
iframe.contentWindow.postMessage(
|
|
{ type: 'RESPONSE', id, status: 'SUCCESS', response },
|
|
'https://localhost:' + PORT
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
iframe.contentWindow.postMessage(
|
|
{
|
|
type: 'RESPONSE',
|
|
id,
|
|
status: 'ERROR',
|
|
response: err,
|
|
},
|
|
'https://localhost:' + PORT
|
|
);
|
|
});
|
|
};
|
|
window.addEventListener('message', handleRequest, false);
|
|
});
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div style="width: 100%; height: 100%">
|
|
<iframe
|
|
id="iframe"
|
|
style="width: 100%; height: 100%; border: 0; position: absolute"
|
|
></iframe>
|
|
</div>
|
|
</body>
|
|
</html>
|