diff --git a/.github/scripts/biome-gs.ts b/.github/scripts/biome-gs.ts new file mode 100644 index 000000000..0a7703049 --- /dev/null +++ b/.github/scripts/biome-gs.ts @@ -0,0 +1,120 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { exec } from "node:child_process"; +import { readdirSync, renameSync, statSync } from "node:fs"; +import { join, resolve } from "node:path"; +import { promisify } from "node:util"; + +const execAsync = promisify(exec); + +async function findGsFiles( + dir: string, + fileList: string[] = [], +): Promise { + const files = readdirSync(dir); + for (const file of files) { + const filePath = join(dir, file); + if ( + file === "node_modules" || + file === ".git" || + file === "dist" || + file === "target" || + file === "pkg" + ) { + continue; + } + const stat = statSync(filePath); + if (stat.isDirectory()) { + await findGsFiles(filePath, fileList); + } else if (file.endsWith(".gs") && file !== "moment.gs") { + fileList.push(filePath); + } + } + return fileList; +} + +async function main() { + const command = process.argv[2]; // 'lint' or 'format' + if (command !== "lint" && command !== "format") { + console.error("Usage: tsx biome-gs.ts [lint|format]"); + process.exit(1); + } + + const rootDir = resolve("."); + const gsFiles = await findGsFiles(rootDir); + const renamedFiles: { oldPath: string; newPath: string }[] = []; + + const restoreFiles = () => { + for (const { oldPath, newPath } of renamedFiles) { + try { + renameSync(newPath, oldPath); + } catch (e) { + console.error(`Failed to restore ${newPath} to ${oldPath}:`, e); + } + } + renamedFiles.length = 0; + }; + + process.on("SIGINT", () => { + restoreFiles(); + process.exit(1); + }); + process.on("SIGTERM", () => { + restoreFiles(); + process.exit(1); + }); + process.on("exit", restoreFiles); + + try { + // 1. Rename .gs to .gs.js + for (const gsFile of gsFiles) { + const jsFile = `${gsFile}.js`; + renameSync(gsFile, jsFile); + renamedFiles.push({ oldPath: gsFile, newPath: jsFile }); + } + + // 2. Run Biome + const biomeArgs = command === "format" ? "check --write ." : "check ."; + console.log(`Running biome ${biomeArgs}...`); + try { + const { stdout, stderr } = await execAsync( + `pnpm exec biome ${biomeArgs}`, + { cwd: rootDir }, + ); + if (stdout) console.log(stdout.replace(/\.gs\.js/g, ".gs")); + if (stderr) console.error(stderr.replace(/\.gs\.js/g, ".gs")); + } catch (e: unknown) { + const err = e as { stdout?: string; stderr?: string }; + if (err.stdout) console.log(err.stdout.replace(/\.gs\.js/g, ".gs")); + if (err.stderr) console.error(err.stderr.replace(/\.gs\.js/g, ".gs")); + // Don't exit yet, we need to restore files + } + } catch (err) { + console.error("An error occurred:", err); + } finally { + restoreFiles(); + // Remove listeners to avoid double-running or issues on exit + process.removeAllListeners("exit"); + process.removeAllListeners("SIGINT"); + process.removeAllListeners("SIGTERM"); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/GEMINI.md b/GEMINI.md index 44d1d37c0..9cf2ac384 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -6,7 +6,8 @@ This guide outlines best practices for developing Google Apps Script projects, f * For new sample directories, ensure the top-level folder is included in the [`test.yaml`](.github/workflows/test.yaml) GitHub workflow's matrix configuration. * Do not move or delete snippet tags: `[END apps_script_... ]` or `[END apps_script_... ]`. - +* Keep code within snippet tags self-contained. Avoid depending on helper functions defined outside the snippet tags if the snippet is intended to be copied and pasted. +* Avoid function name collisions (e.g., multiple `onOpen` or `main` functions) by placing separate samples in their own directories or files. Do not append suffixes like `_2`, `_3` to function names. For variables, replace collisions with a more descriptive name. ## Tools diff --git a/adminSDK/directory/quickstart.gs b/adminSDK/directory/quickstart.gs index 78fe433c0..5ebad2ac5 100644 --- a/adminSDK/directory/quickstart.gs +++ b/adminSDK/directory/quickstart.gs @@ -20,27 +20,27 @@ */ function listUsers() { const optionalArgs = { - customer: 'my_customer', + customer: "my_customer", maxResults: 10, - orderBy: 'email' + orderBy: "email", }; if (!AdminDirectory || !AdminDirectory.Users) { - throw new Error('Enable the AdminDirectory Advanced Service.'); + throw new Error("Enable the AdminDirectory Advanced Service."); } const response = AdminDirectory.Users.list(optionalArgs); const users = response.users; if (!users || users.length === 0) { - console.log('No users found.'); + console.log("No users found."); return; } // Print the list of user's full name and email - console.log('Users:'); + console.log("Users:"); for (const user of users) { if (user.primaryEmail) { if (user.name?.fullName) { - console.log('%s (%s)', user.primaryEmail, user.name.fullName); + console.log("%s (%s)", user.primaryEmail, user.name.fullName); } else { - console.log('%s', user.primaryEmail); + console.log("%s", user.primaryEmail); } } } diff --git a/adminSDK/reports/quickstart.gs b/adminSDK/reports/quickstart.gs index 9612f39aa..38692b43c 100644 --- a/adminSDK/reports/quickstart.gs +++ b/adminSDK/reports/quickstart.gs @@ -19,27 +19,38 @@ * @see https://developers.google.com/admin-sdk/reports/reference/rest/v1/activities/list */ function listLogins() { - const userKey = 'all'; - const applicationName = 'login'; + const userKey = "all"; + const applicationName = "login"; const optionalArgs = { - maxResults: 10 + maxResults: 10, }; if (!AdminReports || !AdminReports.Activities) { - throw new Error('Enable the AdminReports Advanced Service.'); + throw new Error("Enable the AdminReports Advanced Service."); } const response = AdminReports.Activities.list( - userKey, applicationName, optionalArgs); + userKey, + applicationName, + optionalArgs, + ); const activities = response.items; if (!activities || activities.length === 0) { - console.log('No logins found.'); + console.log("No logins found."); return; } // Print login events - console.log('Logins:'); + console.log("Logins:"); for (const activity of activities) { - if (activity.id?.time && activity.actor?.email && activity.events?.[0]?.name) { - console.log('%s: %s (%s)', activity.id.time, activity.actor.email, - activity.events[0].name); + if ( + activity.id?.time && + activity.actor?.email && + activity.events?.[0]?.name + ) { + console.log( + "%s: %s (%s)", + activity.id.time, + activity.actor.email, + activity.events[0].name, + ); } } } diff --git a/adminSDK/reseller/quickstart.gs b/adminSDK/reseller/quickstart.gs index 95947e24c..4938da885 100644 --- a/adminSDK/reseller/quickstart.gs +++ b/adminSDK/reseller/quickstart.gs @@ -20,25 +20,29 @@ */ function listSubscriptions() { const optionalArgs = { - maxResults: 10 + maxResults: 10, }; if (!AdminReseller || !AdminReseller.Subscriptions) { - throw new Error('Enable the AdminReseller Advanced Service.'); + throw new Error("Enable the AdminReseller Advanced Service."); } const response = AdminReseller.Subscriptions.list(optionalArgs); const subscriptions = response.subscriptions; if (!subscriptions || subscriptions.length === 0) { - console.log('No subscriptions found.'); + console.log("No subscriptions found."); return; } - console.log('Subscriptions:'); + console.log("Subscriptions:"); for (const subscription of subscriptions) { if (subscription.customerId && subscription.skuId) { if (subscription.plan?.planName) { - console.log('%s (%s, %s)', subscription.customerId, subscription.skuId, - subscription.plan.planName); + console.log( + "%s (%s, %s)", + subscription.customerId, + subscription.skuId, + subscription.plan.planName, + ); } else { - console.log('%s (%s)', subscription.customerId, subscription.skuId); + console.log("%s (%s)", subscription.customerId, subscription.skuId); } } } diff --git a/advanced/adminSDK.gs b/advanced/adminSDK.gs index c0aed633d..27b5698db 100644 --- a/advanced/adminSDK.gs +++ b/advanced/adminSDK.gs @@ -23,19 +23,19 @@ function listAllUsers() { let page; do { page = AdminDirectory.Users.list({ - domain: 'example.com', - orderBy: 'givenName', + domain: "example.com", + orderBy: "givenName", maxResults: 100, - pageToken: pageToken + pageToken: pageToken, }); const users = page.users; if (!users) { - console.log('No users found.'); + console.log("No users found."); return; } // Print the user's full name and email. for (const user of users) { - console.log('%s (%s)', user.name.fullName, user.primaryEmail); + console.log("%s (%s)", user.name.fullName, user.primaryEmail); } pageToken = page.nextPageToken; } while (pageToken); @@ -49,13 +49,13 @@ function listAllUsers() { */ function getUser() { // TODO (developer) - Replace userEmail value with yours - const userEmail = 'liz@example.com'; + const userEmail = "liz@example.com"; try { const user = AdminDirectory.Users.get(userEmail); - console.log('User data:\n %s', JSON.stringify(user, null, 2)); + console.log("User data:\n %s", JSON.stringify(user, null, 2)); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_get_users] @@ -69,20 +69,20 @@ function getUser() { function addUser() { let user = { // TODO (developer) - Replace primaryEmail value with yours - primaryEmail: 'liz@example.com', + primaryEmail: "liz@example.com", name: { - givenName: 'Elizabeth', - familyName: 'Smith' + givenName: "Elizabeth", + familyName: "Smith", }, // Generate a random password string. - password: Math.random().toString(36) + password: Math.random().toString(36), }; try { user = AdminDirectory.Users.insert(user); - console.log('User %s created with ID %s.', user.primaryEmail, user.id); + console.log("User %s created with ID %s.", user.primaryEmail, user.id); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_add_user] @@ -94,16 +94,16 @@ function addUser() { */ function createAlias() { // TODO (developer) - Replace userEmail value with yours - const userEmail = 'liz@example.com'; + const userEmail = "liz@example.com"; let alias = { - alias: 'chica@example.com' + alias: "chica@example.com", }; try { alias = AdminDirectory.Users.Aliases.insert(alias, userEmail); - console.log('Created alias %s for user %s.', alias.alias, userEmail); + console.log("Created alias %s for user %s.", alias.alias, userEmail); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_create_alias] @@ -118,18 +118,18 @@ function listAllGroups() { let page; do { page = AdminDirectory.Groups.list({ - domain: 'example.com', + domain: "example.com", maxResults: 100, - pageToken: pageToken + pageToken: pageToken, }); const groups = page.groups; if (!groups) { - console.log('No groups found.'); + console.log("No groups found."); return; } // Print group name and email. for (const group of groups) { - console.log('%s (%s)', group.name, group.email); + console.log("%s (%s)", group.name, group.email); } pageToken = page.nextPageToken; } while (pageToken); @@ -143,19 +143,23 @@ function listAllGroups() { */ function addGroupMember() { // TODO (developer) - Replace userEmail value with yours - const userEmail = 'liz@example.com'; + const userEmail = "liz@example.com"; // TODO (developer) - Replace groupEmail value with yours - const groupEmail = 'bookclub@example.com'; + const groupEmail = "bookclub@example.com"; const member = { email: userEmail, - role: 'MEMBER' + role: "MEMBER", }; try { AdminDirectory.Members.insert(member, groupEmail); - console.log('User %s added as a member of group %s.', userEmail, groupEmail); + console.log( + "User %s added as a member of group %s.", + userEmail, + groupEmail, + ); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_add_group_member] @@ -168,10 +172,10 @@ function addGroupMember() { */ function migrateMessages() { // TODO (developer) - Replace groupId value with yours - const groupId = 'exampleGroup@example.com'; + const groupId = "exampleGroup@example.com"; const messagesToMigrate = getRecentMessagesContent(); for (const messageContent of messagesToMigrate) { - const contentBlob = Utilities.newBlob(messageContent, 'message/rfc822'); + const contentBlob = Utilities.newBlob(messageContent, "message/rfc822"); AdminGroupsMigration.Archive.insert(groupId, contentBlob); } } @@ -206,13 +210,13 @@ function getRecentMessagesContent() { */ function getGroupSettings() { // TODO (developer) - Replace groupId value with yours - const groupId = 'exampleGroup@example.com'; + const groupId = "exampleGroup@example.com"; try { const group = AdminGroupsSettings.Groups.get(groupId); console.log(JSON.stringify(group, null, 2)); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_get_group_setting] @@ -224,14 +228,14 @@ function getGroupSettings() { * @see https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups/patch */ function updateGroupSettings() { - const groupId = 'exampleGroup@example.com'; + const groupId = "exampleGroup@example.com"; try { const group = AdminGroupsSettings.newGroups(); - group.description = 'Newly changed group description'; + group.description = "Newly changed group description"; AdminGroupsSettings.Groups.patch(group, groupId); } catch (err) { // TODO (developer)- Handle exception from the API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_admin_sdk_update_group_setting] @@ -243,22 +247,30 @@ function updateGroupSettings() { * list of results. */ function getLicenseAssignments() { - const productId = 'Google-Apps'; - const customerId = 'example.com'; + const productId = "Google-Apps"; + const customerId = "example.com"; let assignments = []; let pageToken = null; do { - const response = AdminLicenseManager.LicenseAssignments.listForProduct(productId, customerId, { - maxResults: 500, - pageToken: pageToken - }); + const response = AdminLicenseManager.LicenseAssignments.listForProduct( + productId, + customerId, + { + maxResults: 500, + pageToken: pageToken, + }, + ); assignments = assignments.concat(response.items); pageToken = response.nextPageToken; } while (pageToken); // Print the productId and skuId for (const assignment of assignments) { - console.log('userId: %s, productId: %s, skuId: %s', - assignment.userId, assignment.productId, assignment.skuId); + console.log( + "userId: %s, productId: %s, skuId: %s", + assignment.userId, + assignment.productId, + assignment.skuId, + ); } } // [END apps_script_admin_sdk_get_license_assignments] @@ -271,16 +283,19 @@ function getLicenseAssignments() { * https://developers.google.com/admin-sdk/licensing/reference/rest/v1/licenseAssignments/insert */ function insertLicenseAssignment() { - const productId = 'Google-Apps'; - const skuId = 'Google-Vault'; - const userId = 'marty@hoverboard.net'; + const productId = "Google-Apps"; + const skuId = "Google-Vault"; + const userId = "marty@hoverboard.net"; try { - const results = AdminLicenseManager.LicenseAssignments - .insert({userId: userId}, productId, skuId); + const results = AdminLicenseManager.LicenseAssignments.insert( + { userId: userId }, + productId, + skuId, + ); console.log(results); } catch (e) { // TODO (developer) - Handle exception. - console.log('Failed with an error %s ', e.message); + console.log("Failed with an error %s ", e.message); } } // [END apps_script_admin_sdk_insert_license_assignment] @@ -301,11 +316,11 @@ function generateLoginActivityReport() { let pageToken; let page; do { - page = AdminReports.Activities.list('all', 'login', { + page = AdminReports.Activities.list("all", "login", { startTime: startTime, endTime: endTime, maxResults: 500, - pageToken: pageToken + pageToken: pageToken, }); const items = page.items; if (items) { @@ -313,7 +328,7 @@ function generateLoginActivityReport() { const row = [ new Date(item.id.time), item.actor.email, - item.events[0].name + item.events[0].name, ]; rows.push(row); } @@ -322,20 +337,20 @@ function generateLoginActivityReport() { } while (pageToken); if (rows.length === 0) { - console.log('No results returned.'); + console.log("No results returned."); return; } - const spreadsheet = SpreadsheetApp.create('Google Workspace Login Report'); + const spreadsheet = SpreadsheetApp.create("Google Workspace Login Report"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. - const headers = ['Time', 'User', 'Login Result']; + const headers = ["Time", "User", "Login Result"]; sheet.appendRow(headers); // Append the results. sheet.getRange(2, 1, rows.length, headers.length).setValues(rows); - console.log('Report spreadsheet created: %s', spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } // [END apps_script_admin_sdk_generate_login_activity_report] @@ -350,21 +365,21 @@ function generateUserUsageReport() { const today = new Date(); const oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); const timezone = Session.getScriptTimeZone(); - const date = Utilities.formatDate(oneWeekAgo, timezone, 'yyyy-MM-dd'); + const date = Utilities.formatDate(oneWeekAgo, timezone, "yyyy-MM-dd"); const parameters = [ - 'accounts:last_login_time', - 'gmail:num_emails_received', - 'drive:num_items_created' + "accounts:last_login_time", + "gmail:num_emails_received", + "drive:num_items_created", ]; const rows = []; let pageToken; let page; do { - page = AdminReports.UserUsageReport.get('all', date, { - parameters: parameters.join(','), + page = AdminReports.UserUsageReport.get("all", date, { + parameters: parameters.join(","), maxResults: 500, - pageToken: pageToken + pageToken: pageToken, }); if (page.warnings) { for (const warning of page.warnings) { @@ -378,9 +393,9 @@ function generateUserUsageReport() { const row = [ report.date, report.entity.userEmail, - parameterValues['accounts:last_login_time'], - parameterValues['gmail:num_emails_received'], - parameterValues['drive:num_items_created'] + parameterValues["accounts:last_login_time"], + parameterValues["gmail:num_emails_received"], + parameterValues["drive:num_items_created"], ]; rows.push(row); } @@ -389,21 +404,28 @@ function generateUserUsageReport() { } while (pageToken); if (rows.length === 0) { - console.log('No results returned.'); + console.log("No results returned."); return; } - const spreadsheet = SpreadsheetApp.create('Google Workspace User Usage Report'); + const spreadsheet = SpreadsheetApp.create( + "Google Workspace User Usage Report", + ); const sheet = spreadsheet.getActiveSheet(); // Append the headers. - const headers = ['Date', 'User', 'Last Login', 'Num Emails Received', - 'Num Drive Files Created']; + const headers = [ + "Date", + "User", + "Last Login", + "Num Emails Received", + "Num Drive Files Created", + ]; sheet.appendRow(headers); // Append the results. sheet.getRange(2, 1, rows.length, headers.length).setValues(rows); - console.log('Report spreadsheet created: %s', spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } /** @@ -442,14 +464,18 @@ function getSubscriptions() { let pageToken; do { result = AdminReseller.Subscriptions.list({ - pageToken: pageToken + pageToken: pageToken, }); for (const sub of result.subscriptions) { const creationDate = new Date(); creationDate.setUTCSeconds(sub.creationTime); - console.log('customer ID: %s, date created: %s, plan name: %s, sku id: %s', - sub.customerId, creationDate.toDateString(), sub.plan.planName, - sub.skuId); + console.log( + "customer ID: %s, date created: %s, plan name: %s, sku id: %s", + sub.customerId, + creationDate.toDateString(), + sub.plan.planName, + sub.skuId, + ); } pageToken = result.nextPageToken; } while (pageToken); diff --git a/advanced/adsense.gs b/advanced/adsense.gs index 33e3488f2..24e09c476 100644 --- a/advanced/adsense.gs +++ b/advanced/adsense.gs @@ -20,14 +20,17 @@ function listAccounts() { let pageToken; do { - const response = AdSense.Accounts.list({pageToken: pageToken}); + const response = AdSense.Accounts.list({ pageToken: pageToken }); if (!response.accounts) { - console.log('No accounts found.'); + console.log("No accounts found."); return; } for (const account of response.accounts) { - console.log('Found account with resource name "%s" and display name "%s".', - account.name, account.displayName); + console.log( + 'Found account with resource name "%s" and display name "%s".', + account.name, + account.displayName, + ); } pageToken = response.nextPageToken; } while (pageToken); @@ -45,17 +48,22 @@ function listAdClients(accountName) { let pageToken; do { const response = AdSense.Accounts.Adclients.list(accountName, { - pageToken: pageToken + pageToken: pageToken, }); if (!response.adClients) { - console.log('No ad clients found for this account.'); + console.log("No ad clients found for this account."); return; } for (const adClient of response.adClients) { - console.log('Found ad client for product "%s" with resource name "%s".', - adClient.productCode, adClient.name); - console.log('Reporting dimension ID: %s', - adClient.reportingDimensionId ?? 'None'); + console.log( + 'Found ad client for product "%s" with resource name "%s".', + adClient.productCode, + adClient.name, + ); + console.log( + "Reporting dimension ID: %s", + adClient.reportingDimensionId ?? "None", + ); } pageToken = response.nextPageToken; } while (pageToken); @@ -73,15 +81,18 @@ function listAdUnits(adClientName) { do { const response = AdSense.Accounts.Adclients.Adunits.list(adClientName, { pageSize: 50, - pageToken: pageToken + pageToken: pageToken, }); if (!response.adUnits) { - console.log('No ad units found for this ad client.'); + console.log("No ad units found for this ad client."); return; } for (const adUnit of response.adUnits) { - console.log('Found ad unit with resource name "%s" and display name "%s".', - adUnit.name, adUnit.displayName); + console.log( + 'Found ad unit with resource name "%s" and display name "%s".', + adUnit.name, + adUnit.displayName, + ); } pageToken = response.nextPageToken; @@ -103,33 +114,42 @@ function generateReport(accountName, adClientReportingDimensionId) { const report = AdSense.Accounts.Reports.generate(accountName, { // Specify the desired ad client using a filter. - filters: ['AD_CLIENT_ID==' + escapeFilterParameter(adClientReportingDimensionId)], - metrics: ['PAGE_VIEWS', 'AD_REQUESTS', 'AD_REQUESTS_COVERAGE', 'CLICKS', - 'AD_REQUESTS_CTR', 'COST_PER_CLICK', 'AD_REQUESTS_RPM', - 'ESTIMATED_EARNINGS'], - dimensions: ['DATE'], - ...dateToJson('startDate', oneWeekAgo), - ...dateToJson('endDate', today), + filters: [ + `AD_CLIENT_ID==${escapeFilterParameter(adClientReportingDimensionId)}`, + ], + metrics: [ + "PAGE_VIEWS", + "AD_REQUESTS", + "AD_REQUESTS_COVERAGE", + "CLICKS", + "AD_REQUESTS_CTR", + "COST_PER_CLICK", + "AD_REQUESTS_RPM", + "ESTIMATED_EARNINGS", + ], + dimensions: ["DATE"], + ...dateToJson("startDate", oneWeekAgo), + ...dateToJson("endDate", today), // Sort by ascending date. - orderBy: ['+DATE'] + orderBy: ["+DATE"], }); if (!report.rows) { - console.log('No rows returned.'); + console.log("No rows returned."); return; } - const spreadsheet = SpreadsheetApp.create('AdSense Report'); + const spreadsheet = SpreadsheetApp.create("AdSense Report"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. sheet.appendRow(report.headers.map((header) => header.name)); // Append the results. - sheet.getRange(2, 1, report.rows.length, report.headers.length) - .setValues(report.rows.map((row) => row.cells.map((cell) => cell.value))); + sheet + .getRange(2, 1, report.rows.length, report.headers.length) + .setValues(report.rows.map((row) => row.cells.map((cell) => cell.value))); - console.log('Report spreadsheet created: %s', - spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } /** @@ -138,7 +158,7 @@ function generateReport(accountName, adClientReportingDimensionId) { * @return {string} The escaped parameter. */ function escapeFilterParameter(parameter) { - return parameter.replace('\\', '\\\\').replace(',', '\\,'); + return parameter.replace("\\", "\\\\").replace(",", "\\,"); } /** @@ -150,9 +170,9 @@ function escapeFilterParameter(parameter) { */ function dateToJson(paramName, value) { return { - [paramName + '.year']: value.getFullYear(), - [paramName + '.month']: value.getMonth() + 1, - [paramName + '.day']: value.getDate() + [`${paramName}.year`]: value.getFullYear(), + [`${paramName}.month`]: value.getMonth() + 1, + [`${paramName}.day`]: value.getDate(), }; } diff --git a/advanced/analytics.gs b/advanced/analytics.gs index a691ce4a2..5af7c298e 100644 --- a/advanced/analytics.gs +++ b/advanced/analytics.gs @@ -21,7 +21,7 @@ function listAccounts() { try { const accounts = Analytics.Management.Accounts.list(); if (!accounts.items || !accounts.items.length) { - console.log('No accounts found.'); + console.log("No accounts found."); return; } @@ -34,7 +34,7 @@ function listAccounts() { } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -46,20 +46,23 @@ function listWebProperties(accountId) { try { const webProperties = Analytics.Management.Webproperties.list(accountId); if (!webProperties.items || !webProperties.items.length) { - console.log('\tNo web properties found.'); + console.log("\tNo web properties found."); return; } for (let i = 0; i < webProperties.items.length; i++) { const webProperty = webProperties.items[i]; - console.log('\tWeb Property: name "%s", id "%s".', - webProperty.name, webProperty.id); + console.log( + '\tWeb Property: name "%s", id "%s".', + webProperty.name, + webProperty.id, + ); // List profiles in the web property. listProfiles(accountId, webProperty.id); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -73,21 +76,22 @@ function listProfiles(accountId, webPropertyId) { // due to the number of accounts or profiles you have, you may be able to // avoid it by adding a Utilities.sleep(1000) statement here. try { - const profiles = Analytics.Management.Profiles.list(accountId, - webPropertyId); + const profiles = Analytics.Management.Profiles.list( + accountId, + webPropertyId, + ); if (!profiles.items || !profiles.items.length) { - console.log('\t\tNo web properties found.'); + console.log("\t\tNo web properties found."); return; } for (let i = 0; i < profiles.items.length; i++) { const profile = profiles.items[i]; - console.log('\t\tProfile: name "%s", id "%s".', profile.name, - profile.id); + console.log('\t\tProfile: name "%s", id "%s".', profile.name, profile.id); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_analytics_accounts] @@ -101,28 +105,39 @@ function runReport(profileId) { const today = new Date(); const oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); - const startDate = Utilities.formatDate(oneWeekAgo, Session.getScriptTimeZone(), - 'yyyy-MM-dd'); - const endDate = Utilities.formatDate(today, Session.getScriptTimeZone(), - 'yyyy-MM-dd'); + const startDate = Utilities.formatDate( + oneWeekAgo, + Session.getScriptTimeZone(), + "yyyy-MM-dd", + ); + const endDate = Utilities.formatDate( + today, + Session.getScriptTimeZone(), + "yyyy-MM-dd", + ); - const tableId = 'ga:' + profileId; - const metric = 'ga:visits'; + const tableId = `ga:${profileId}`; + const metric = "ga:visits"; const options = { - 'dimensions': 'ga:source,ga:keyword', - 'sort': '-ga:visits,ga:source', - 'filters': 'ga:medium==organic', - 'max-results': 25 + dimensions: "ga:source,ga:keyword", + sort: "-ga:visits,ga:source", + filters: "ga:medium==organic", + "max-results": 25, }; - const report = Analytics.Data.Ga.get(tableId, startDate, endDate, metric, - options); + const report = Analytics.Data.Ga.get( + tableId, + startDate, + endDate, + metric, + options, + ); if (!report.rows) { - console.log('No rows returned.'); + console.log("No rows returned."); return; } - const spreadsheet = SpreadsheetApp.create('Google Analytics Report'); + const spreadsheet = SpreadsheetApp.create("Google Analytics Report"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. @@ -132,10 +147,10 @@ function runReport(profileId) { sheet.appendRow(headers); // Append the results. - sheet.getRange(2, 1, report.rows.length, headers.length) - .setValues(report.rows); + sheet + .getRange(2, 1, report.rows.length, headers.length) + .setValues(report.rows); - console.log('Report spreadsheet created: %s', - spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } // [END apps_script_analytics_reports] diff --git a/advanced/analyticsAdmin.gs b/advanced/analyticsAdmin.gs index 973388fd5..049829eae 100644 --- a/advanced/analyticsAdmin.gs +++ b/advanced/analyticsAdmin.gs @@ -21,17 +21,21 @@ function listAccounts() { try { accounts = AnalyticsAdmin.Accounts.list(); if (!accounts.items || !accounts.items.length) { - console.log('No accounts found.'); + console.log("No accounts found."); return; } for (let i = 0; i < accounts.items.length; i++) { const account = accounts.items[i]; - console.log('Account: name "%s", displayName "%s".', account.name, account.displayName); + console.log( + 'Account: name "%s", displayName "%s".', + account.name, + account.displayName, + ); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_analyticsadmin] diff --git a/advanced/analyticsData.gs b/advanced/analyticsData.gs index b881998d1..afacb4d91 100644 --- a/advanced/analyticsData.gs +++ b/advanced/analyticsData.gs @@ -23,68 +23,64 @@ function runReport() { * TODO(developer): Uncomment this variable and replace with your * Google Analytics 4 property ID before running the sample. */ - const propertyId = 'YOUR-GA4-PROPERTY-ID'; + const propertyId = "YOUR-GA4-PROPERTY-ID"; try { const metric = AnalyticsData.newMetric(); - metric.name = 'activeUsers'; + metric.name = "activeUsers"; const dimension = AnalyticsData.newDimension(); - dimension.name = 'city'; + dimension.name = "city"; const dateRange = AnalyticsData.newDateRange(); - dateRange.startDate = '2020-03-31'; - dateRange.endDate = 'today'; + dateRange.startDate = "2020-03-31"; + dateRange.endDate = "today"; const request = AnalyticsData.newRunReportRequest(); request.dimensions = [dimension]; request.metrics = [metric]; request.dateRanges = dateRange; - const report = AnalyticsData.Properties.runReport(request, - 'properties/' + propertyId); + const report = AnalyticsData.Properties.runReport( + request, + `properties/${propertyId}`, + ); if (!report.rows) { - console.log('No rows returned.'); + console.log("No rows returned."); return; } - const spreadsheet = SpreadsheetApp.create('Google Analytics Report'); + const spreadsheet = SpreadsheetApp.create("Google Analytics Report"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. - const dimensionHeaders = report.dimensionHeaders.map( - (dimensionHeader) => { - return dimensionHeader.name; - }); - const metricHeaders = report.metricHeaders.map( - (metricHeader) => { - return metricHeader.name; - }); + const dimensionHeaders = report.dimensionHeaders.map((dimensionHeader) => { + return dimensionHeader.name; + }); + const metricHeaders = report.metricHeaders.map((metricHeader) => { + return metricHeader.name; + }); const headers = [...dimensionHeaders, ...metricHeaders]; sheet.appendRow(headers); // Append the results. const rows = report.rows.map((row) => { - const dimensionValues = row.dimensionValues.map( - (dimensionValue) => { - return dimensionValue.value; - }); - const metricValues = row.metricValues.map( - (metricValues) => { - return metricValues.value; - }); + const dimensionValues = row.dimensionValues.map((dimensionValue) => { + return dimensionValue.value; + }); + const metricValues = row.metricValues.map((metricValues) => { + return metricValues.value; + }); return [...dimensionValues, ...metricValues]; }); - sheet.getRange(2, 1, report.rows.length, headers.length) - .setValues(rows); + sheet.getRange(2, 1, report.rows.length, headers.length).setValues(rows); - console.log('Report spreadsheet created: %s', - spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_analyticsdata] diff --git a/advanced/bigquery.gs b/advanced/bigquery.gs index a4127aa1b..5a1db81cb 100644 --- a/advanced/bigquery.gs +++ b/advanced/bigquery.gs @@ -20,17 +20,18 @@ function runQuery() { // Replace this value with the project ID listed in the Google // Cloud Platform project. - const projectId = 'XXXXXXXX'; + const projectId = "XXXXXXXX"; const request = { // TODO (developer) - Replace query with yours - query: 'SELECT refresh_date AS Day, term AS Top_Term, rank ' + - 'FROM `bigquery-public-data.google_trends.top_terms` ' + - 'WHERE rank = 1 ' + - 'AND refresh_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 WEEK) ' + - 'GROUP BY Day, Top_Term, rank ' + - 'ORDER BY Day DESC;', - useLegacySql: false + query: + "SELECT refresh_date AS Day, term AS Top_Term, rank " + + "FROM `bigquery-public-data.google_trends.top_terms` " + + "WHERE rank = 1 " + + "AND refresh_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 WEEK) " + + "GROUP BY Day, Top_Term, rank " + + "ORDER BY Day DESC;", + useLegacySql: false, }; let queryResults = BigQuery.Jobs.query(request, projectId); const jobId = queryResults.jobReference.jobId; @@ -47,22 +48,20 @@ function runQuery() { let rows = queryResults.rows; while (queryResults.pageToken) { queryResults = BigQuery.Jobs.getQueryResults(projectId, jobId, { - pageToken: queryResults.pageToken + pageToken: queryResults.pageToken, }); rows = rows.concat(queryResults.rows); } if (!rows) { - console.log('No rows returned.'); + console.log("No rows returned."); return; } - const spreadsheet = SpreadsheetApp.create('BigQuery Results'); + const spreadsheet = SpreadsheetApp.create("BigQuery Results"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. - const headers = queryResults.schema.fields.map(function(field) { - return field.name; - }); + const headers = queryResults.schema.fields.map((field) => field.name); sheet.appendRow(headers); // Append the results. @@ -76,7 +75,7 @@ function runQuery() { } sheet.getRange(2, 1, rows.length, headers.length).setValues(data); - console.log('Results spreadsheet created: %s', spreadsheet.getUrl()); + console.log("Results spreadsheet created: %s", spreadsheet.getUrl()); } // [END apps_script_bigquery_run_query] @@ -87,40 +86,40 @@ function runQuery() { function loadCsv() { // Replace this value with the project ID listed in the Google // Cloud Platform project. - const projectId = 'XXXXXXXX'; + const projectId = "XXXXXXXX"; // Create a dataset in the BigQuery UI (https://bigquery.cloud.google.com) // and enter its ID below. - const datasetId = 'YYYYYYYY'; + const datasetId = "YYYYYYYY"; // Sample CSV file of Google Trends data conforming to the schema below. // https://docs.google.com/file/d/0BwzA1Orbvy5WMXFLaTR1Z1p2UDg/edit - const csvFileId = '0BwzA1Orbvy5WMXFLaTR1Z1p2UDg'; + const csvFileId = "0BwzA1Orbvy5WMXFLaTR1Z1p2UDg"; // Create the table. - const tableId = 'pets_' + new Date().getTime(); + const tableId = `pets_${new Date().getTime()}`; let table = { tableReference: { projectId: projectId, datasetId: datasetId, - tableId: tableId + tableId: tableId, }, schema: { fields: [ - {name: 'week', type: 'STRING'}, - {name: 'cat', type: 'INTEGER'}, - {name: 'dog', type: 'INTEGER'}, - {name: 'bird', type: 'INTEGER'} - ] - } + { name: "week", type: "STRING" }, + { name: "cat", type: "INTEGER" }, + { name: "dog", type: "INTEGER" }, + { name: "bird", type: "INTEGER" }, + ], + }, }; try { table = BigQuery.Tables.insert(table, projectId, datasetId); - console.log('Table created: %s', table.id); + console.log("Table created: %s", table.id); } catch (err) { - console.log('unable to create table'); + console.log("unable to create table"); } // Load CSV data from Drive and convert to the correct format for upload. const file = DriveApp.getFileById(csvFileId); - const data = file.getBlob().setContentType('application/octet-stream'); + const data = file.getBlob().setContentType("application/octet-stream"); // Create the data upload job. const job = { @@ -129,17 +128,17 @@ function loadCsv() { destinationTable: { projectId: projectId, datasetId: datasetId, - tableId: tableId + tableId: tableId, }, - skipLeadingRows: 1 - } - } + skipLeadingRows: 1, + }, + }, }; try { const jobResult = BigQuery.Jobs.insert(job, projectId, data); console.log(`Load job started. Status: ${jobResult.status.state}`); } catch (err) { - console.log('unable to insert job'); + console.log("unable to insert job"); } } // [END apps_script_bigquery_load_csv] diff --git a/advanced/calendar.gs b/advanced/calendar.gs index f41a54fda..1d7387b4f 100644 --- a/advanced/calendar.gs +++ b/advanced/calendar.gs @@ -24,16 +24,15 @@ function listCalendars() { do { calendars = Calendar.CalendarList.list({ maxResults: 100, - pageToken: pageToken - + pageToken: pageToken, }); if (!calendars.items || calendars.items.length === 0) { - console.log('No calendars found.'); + console.log("No calendars found."); return; } // Print the calendar id and calendar summary for (const calendar of calendars.items) { - console.log('%s (ID: %s)', calendar.summary, calendar.id); + console.log("%s (ID: %s)", calendar.summary, calendar.id); } pageToken = calendars.nextPageToken; } while (pageToken); @@ -46,33 +45,33 @@ function listCalendars() { * @see https://developers.google.com/calendar/api/v3/reference/events/insert */ function createEvent() { - const calendarId = 'primary'; + const calendarId = "primary"; const start = getRelativeDate(1, 12); const end = getRelativeDate(1, 13); // event details for creating event. let event = { - summary: 'Lunch Meeting', - location: 'The Deli', - description: 'To discuss our plans for the presentation next week.', + summary: "Lunch Meeting", + location: "The Deli", + description: "To discuss our plans for the presentation next week.", start: { - dateTime: start.toISOString() + dateTime: start.toISOString(), }, end: { - dateTime: end.toISOString() + dateTime: end.toISOString(), }, attendees: [ - {email: 'gduser1@workspacesample.dev'}, - {email: 'gduser2@workspacesample.dev'} + { email: "gduser1@workspacesample.dev" }, + { email: "gduser2@workspacesample.dev" }, ], // Red background. Use Calendar.Colors.get() for the full list. - colorId: 11 + colorId: 11, }; try { // call method to insert/create new event in provided calandar event = Calendar.Events.insert(event, calendarId); - console.log('Event ID: ' + event.id); + console.log(`Event ID: ${event.id}`); } catch (err) { - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } @@ -100,27 +99,27 @@ function getRelativeDate(daysOffset, hour) { * @see https://developers.google.com/calendar/api/v3/reference/events/list */ function listNext10Events() { - const calendarId = 'primary'; + const calendarId = "primary"; const now = new Date(); const events = Calendar.Events.list(calendarId, { timeMin: now.toISOString(), singleEvents: true, - orderBy: 'startTime', - maxResults: 10 + orderBy: "startTime", + maxResults: 10, }); if (!events.items || events.items.length === 0) { - console.log('No events found.'); + console.log("No events found."); return; } for (const event of events.items) { if (event.start.date) { // All-day event. const start = new Date(event.start.date); - console.log('%s (%s)', event.summary, start.toLocaleDateString()); + console.log("%s (%s)", event.summary, start.toLocaleDateString()); continue; } const start = new Date(event.start.dateTime); - console.log('%s (%s)', event.summary, start.toLocaleString()); + console.log("%s (%s)", event.summary, start.toLocaleString()); } } // [END calendar_list_events] @@ -138,9 +137,9 @@ function listNext10Events() { function logSyncedEvents(calendarId, fullSync) { const properties = PropertiesService.getUserProperties(); const options = { - maxResults: 100 + maxResults: 100, }; - const syncToken = properties.getProperty('syncToken'); + const syncToken = properties.getProperty("syncToken"); if (syncToken && !fullSync) { options.syncToken = syncToken; } else { @@ -157,34 +156,36 @@ function logSyncedEvents(calendarId, fullSync) { } catch (e) { // Check to see if the sync token was invalidated by the server; // if so, perform a full sync instead. - if (e.message === 'Sync token is no longer valid, a full sync is required.') { - properties.deleteProperty('syncToken'); + if ( + e.message === "Sync token is no longer valid, a full sync is required." + ) { + properties.deleteProperty("syncToken"); logSyncedEvents(calendarId, true); return; } throw new Error(e.message); } if (events.items && events.items.length === 0) { - console.log('No events found.'); + console.log("No events found."); return; } for (const event of events.items) { - if (event.status === 'cancelled') { - console.log('Event id %s was cancelled.', event.id); + if (event.status === "cancelled") { + console.log("Event id %s was cancelled.", event.id); return; } if (event.start.date) { const start = new Date(event.start.date); - console.log('%s (%s)', event.summary, start.toLocaleDateString()); + console.log("%s (%s)", event.summary, start.toLocaleDateString()); return; } // Events that don't last all day; they have defined start times. const start = new Date(event.start.dateTime); - console.log('%s (%s)', event.summary, start.toLocaleString()); + console.log("%s (%s)", event.summary, start.toLocaleString()); } pageToken = events.nextPageToken; } while (pageToken); - properties.setProperty('syncToken', events.nextSyncToken); + properties.setProperty("syncToken", events.nextSyncToken); } // [END calendar_log_synced_events] @@ -200,44 +201,44 @@ function logSyncedEvents(calendarId, fullSync) { * to the etag of the new event when it was created. */ function conditionalUpdate() { - const calendarId = 'primary'; + const calendarId = "primary"; const start = getRelativeDate(1, 12); const end = getRelativeDate(1, 13); let event = { - summary: 'Lunch Meeting', - location: 'The Deli', - description: 'To discuss our plans for the presentation next week.', + summary: "Lunch Meeting", + location: "The Deli", + description: "To discuss our plans for the presentation next week.", start: { - dateTime: start.toISOString() + dateTime: start.toISOString(), }, end: { - dateTime: end.toISOString() + dateTime: end.toISOString(), }, attendees: [ - {email: 'gduser1@workspacesample.dev'}, - {email: 'gduser2@workspacesample.dev'} + { email: "gduser1@workspacesample.dev" }, + { email: "gduser2@workspacesample.dev" }, ], // Red background. Use Calendar.Colors.get() for the full list. - colorId: 11 + colorId: 11, }; event = Calendar.Events.insert(event, calendarId); - console.log('Event ID: ' + event.getId()); + console.log(`Event ID: ${event.getId()}`); // Wait 30 seconds to see if the event has been updated outside this script. Utilities.sleep(30 * 1000); // Try to update the event, on the condition that the event state has not // changed since the event was created. - event.location = 'The Coffee Shop'; + event.location = "The Coffee Shop"; try { event = Calendar.Events.update( - event, - calendarId, - event.id, - {}, - {'If-Match': event.etag} + event, + calendarId, + event.id, + {}, + { "If-Match": event.etag }, ); - console.log('Successfully updated event: ' + event.id); + console.log(`Successfully updated event: ${event.id}`); } catch (e) { - console.log('Fetch threw an exception: ' + e); + console.log(`Fetch threw an exception: ${e}`); } } // [END calendar_conditional_update] @@ -252,38 +253,43 @@ function conditionalUpdate() { * to the etag of the last known state of the event. */ function conditionalFetch() { - const calendarId = 'primary'; + const calendarId = "primary"; const start = getRelativeDate(1, 12); const end = getRelativeDate(1, 13); let event = { - summary: 'Lunch Meeting', - location: 'The Deli', - description: 'To discuss our plans for the presentation next week.', + summary: "Lunch Meeting", + location: "The Deli", + description: "To discuss our plans for the presentation next week.", start: { - dateTime: start.toISOString() + dateTime: start.toISOString(), }, end: { - dateTime: end.toISOString() + dateTime: end.toISOString(), }, attendees: [ - {email: 'gduser1@workspacesample.dev'}, - {email: 'gduser2@workspacesample.dev'} + { email: "gduser1@workspacesample.dev" }, + { email: "gduser2@workspacesample.dev" }, ], // Red background. Use Calendar.Colors.get() for the full list. - colorId: 11 + colorId: 11, }; try { // insert event event = Calendar.Events.insert(event, calendarId); - console.log('Event ID: ' + event.getId()); + console.log(`Event ID: ${event.getId()}`); // Re-fetch the event each second, but only get a result if it has changed. for (let i = 0; i < 30; i++) { Utilities.sleep(1000); - event = Calendar.Events.get(calendarId, event.id, {}, {'If-None-Match': event.etag}); - console.log('New event description: ' + event.start.dateTime); + event = Calendar.Events.get( + calendarId, + event.id, + {}, + { "If-None-Match": event.etag }, + ); + console.log(`New event description: ${event.start.dateTime}`); } } catch (e) { - console.log('Fetch threw an exception: ' + e); + console.log(`Fetch threw an exception: ${e}`); } } // [END calendar_conditional_fetch] diff --git a/advanced/chat.gs b/advanced/chat.gs index 9cb506934..e8d366a5c 100644 --- a/advanced/chat.gs +++ b/advanced/chat.gs @@ -21,11 +21,11 @@ */ function postMessageWithUserCredentials(spaceName) { try { - const message = {'text': 'Hello world!'}; + const message = { text: "Hello world!" }; Chat.Spaces.Messages.create(message, spaceName); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to create message with error %s', err.message); + console.log("Failed to create message with error %s", err.message); } } // [END chat_post_message_with_user_credentials] @@ -40,16 +40,17 @@ function postMessageWithAppCredentials(spaceName) { // See https://developers.google.com/chat/api/guides/auth/service-accounts // for details on how to obtain a service account OAuth token. const appToken = getToken_(); - const message = {'text': 'Hello world!'}; + const message = { text: "Hello world!" }; Chat.Spaces.Messages.create( - message, - spaceName, - {}, - // Authenticate with the service account token. - {'Authorization': 'Bearer ' + appToken}); + message, + spaceName, + {}, + // Authenticate with the service account token. + { Authorization: `Bearer ${appToken}` }, + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to create message with error %s', err.message); + console.log("Failed to create message with error %s", err.message); } } // [END chat_post_message_with_app_credentials] @@ -62,11 +63,11 @@ function postMessageWithAppCredentials(spaceName) { function getSpace(spaceName) { try { const space = Chat.Spaces.get(spaceName); - console.log('Space display name: %s', space.displayName); - console.log('Space type: %s', space.spaceType); + console.log("Space display name: %s", space.displayName); + console.log("Space type: %s", space.spaceType); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to get space with error %s', err.message); + console.log("Failed to get space with error %s", err.message); } } // [END chat_get_space] @@ -77,11 +78,11 @@ function getSpace(spaceName) { */ function createSpace() { try { - const space = {'displayName': 'New Space', 'spaceType': 'SPACE'}; + const space = { displayName: "New Space", spaceType: "SPACE" }; Chat.Spaces.create(space); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to create space with error %s', err.message); + console.log("Failed to create space with error %s", err.message); } } // [END chat_create_space] @@ -98,21 +99,24 @@ function listMemberships(spaceName) { do { response = Chat.Spaces.Members.list(spaceName, { pageSize: 10, - pageToken: pageToken + pageToken: pageToken, }); if (!response.memberships || response.memberships.length === 0) { pageToken = response.nextPageToken; continue; } - response.memberships.forEach((membership) => console.log( - 'Member resource name: %s (type: %s)', - membership.name, - membership.member.type)); + for (const membership of response.memberships) { + console.log( + "Member: %s, Role: %s", + membership.member.displayName, + membership.role, + ); + } pageToken = response.nextPageToken; } while (pageToken); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END chat_list_memberships] diff --git a/advanced/classroom.gs b/advanced/classroom.gs index 1dc7c8a54..72f8b7a1e 100644 --- a/advanced/classroom.gs +++ b/advanced/classroom.gs @@ -22,23 +22,23 @@ function listCourses() { * @see https://developers.google.com/classroom/reference/rest/v1/courses/list */ const optionalArgs = { - pageSize: 10 + pageSize: 10, // Use other query parameters here if needed. }; try { const response = Classroom.Courses.list(optionalArgs); const courses = response.courses; if (!courses || courses.length === 0) { - console.log('No courses found.'); + console.log("No courses found."); return; } // Print the course names and IDs of the available courses. for (const course in courses) { - console.log('%s (%s)', courses[course].name, courses[course].id); + console.log("%s (%s)", courses[course].name, courses[course].id); } } catch (err) { // TODO (developer)- Handle Courses.list() exception from Classroom API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_classroom_list_courses] diff --git a/advanced/displayvideo.gs b/advanced/displayvideo.gs index a01ac190d..6d5b13522 100644 --- a/advanced/displayvideo.gs +++ b/advanced/displayvideo.gs @@ -26,13 +26,16 @@ function listPartners() { // Print out the ID and name of each for (let i = 0; i < partners.partners.length; i++) { const partner = partners.partners[i]; - console.log('Found partner with ID %s and name "%s".', - partner.partnerId, partner.displayName); + console.log( + 'Found partner with ID %s and name "%s".', + partner.partnerId, + partner.displayName, + ); } } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dv360_list_partners] @@ -43,27 +46,30 @@ function listPartners() { * Note the use of paging tokens to retrieve the whole list. */ function listActiveCampaigns() { - const advertiserId = '1234567'; // Replace with your advertiser ID. + const advertiserId = "1234567"; // Replace with your advertiser ID. let result; let pageToken; try { do { result = DisplayVideo.Advertisers.Campaigns.list(advertiserId, { - 'filter': 'entityStatus="ENTITY_STATUS_ACTIVE"', - 'pageToken': pageToken + filter: 'entityStatus="ENTITY_STATUS_ACTIVE"', + pageToken: pageToken, }); if (result.campaigns) { for (let i = 0; i < result.campaigns.length; i++) { const campaign = result.campaigns[i]; - console.log('Found campaign with ID %s and name "%s".', - campaign.campaignId, campaign.displayName); + console.log( + 'Found campaign with ID %s and name "%s".', + campaign.campaignId, + campaign.displayName, + ); } } pageToken = result.nextPageToken; } while (pageToken); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dv360_list_active_campaigns] @@ -73,20 +79,24 @@ function listActiveCampaigns() { * Updates the display name of a line item */ function updateLineItemName() { - const advertiserId = '1234567'; // Replace with your advertiser ID. - const lineItemId = '123456789'; //Replace with your line item ID. + const advertiserId = "1234567"; // Replace with your advertiser ID. + const lineItemId = "123456789"; //Replace with your line item ID. const updateMask = "displayName"; - const lineItemDef = {displayName: 'New Line Item Name (updated from Apps Script!)'}; + const lineItemDef = { + displayName: "New Line Item Name (updated from Apps Script!)", + }; try { - const lineItem = DisplayVideo.Advertisers.LineItems - .patch(lineItemDef, advertiserId, lineItemId, {updateMask:updateMask}); - - + const lineItem = DisplayVideo.Advertisers.LineItems.patch( + lineItemDef, + advertiserId, + lineItemId, + { updateMask: updateMask }, + ); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dv360_update_line_item_name] diff --git a/advanced/docs.gs b/advanced/docs.gs index ee4e7e191..24aff334e 100644 --- a/advanced/docs.gs +++ b/advanced/docs.gs @@ -21,15 +21,10 @@ * @return {string} documentId */ function createDocument() { - try { - // Create document with title - const document = Docs.Documents.create({'title': 'My New Document'}); - console.log('Created document with ID: ' + document.documentId); - return document.documentId; - } catch (e) { - // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); - } + // Create document with title + const document = Docs.Documents.create({ title: "My New Document" }); + console.log(`Created document with ID: ${document.documentId}`); + return document.documentId; } // [END docs_create_document] @@ -45,43 +40,44 @@ function findAndReplace(documentId, findTextToReplacementMap) { const requests = []; for (const findText in findTextToReplacementMap) { const replaceText = findTextToReplacementMap[findText]; - // One option for replacing all text is to specify all tab IDs. - const request = { + + // Replace all text across all tabs. + const replaceAllTextRequest = { replaceAllText: { containsText: { text: findText, - matchCase: true + matchCase: true, }, replaceText: replaceText, - tabsCriteria: { - tabIds: [TAB_ID_1, TAB_ID_2, TAB_ID_3], - } - } + }, }; - // Another option is to omit TabsCriteria if you are replacing across all tabs. - const request = { + + // Replace all text across specific tabs. + const _replaceAllTextWithTabsCriteria = { replaceAllText: { - containsText: { - text: findText, - matchCase: true + ...replaceAllTextRequest.replaceAllText, + tabsCriteria: { + tabIds: [TAB_ID_1, TAB_ID_2, TAB_ID_3], }, - replaceText: replaceText - } + }, }; - requests.push(request); + requests.push(replaceAllTextRequest); } - try { - const response = Docs.Documents.batchUpdate({'requests': requests}, documentId); - const replies = response.replies; - for (const [index] of replies.entries()) { - const numReplacements = replies[index].replaceAllText.occurrencesChanged || 0; - console.log('Request %s performed %s replacements.', index, numReplacements); - } - return replies; - } catch (e) { - // TODO (developer) - Handle exception - console.log('Failed with error : %s', e.message); + const response = Docs.Documents.batchUpdate( + { requests: requests }, + documentId, + ); + const replies = response.replies; + for (const [index] of replies.entries()) { + const numReplacements = + replies[index].replaceAllText.occurrencesChanged || 0; + console.log( + "Request %s performed %s replacements.", + index, + numReplacements, + ); } + return replies; } // [END docs_find_and_replace_text] @@ -95,42 +91,42 @@ function findAndReplace(documentId, findTextToReplacementMap) { * @see https://developers.google.com/docs/api/reference/rest/v1/documents/batchUpdate */ function insertAndStyleText(documentId, text) { - const requests = [{ - insertText: { - location: { - index: 1, - // A tab can be specified using its ID. When omitted, the request is - // applied to the first tab. - // tabId: TAB_ID - }, - text: text - } - }, - { - updateTextStyle: { - range: { - startIndex: 1, - endIndex: text.length + 1 + const requests = [ + { + insertText: { + location: { + index: 1, + // A tab can be specified using its ID. When omitted, the request is + // applied to the first tab. + // tabId: TAB_ID + }, + text: text, }, - textStyle: { - fontSize: { - magnitude: 12, - unit: 'PT' + }, + { + updateTextStyle: { + range: { + startIndex: 1, + endIndex: text.length + 1, }, - weightedFontFamily: { - fontFamily: 'Calibri' - } + textStyle: { + fontSize: { + magnitude: 12, + unit: "PT", + }, + weightedFontFamily: { + fontFamily: "Calibri", + }, + }, + fields: "weightedFontFamily, fontSize", }, - fields: 'weightedFontFamily, fontSize' - } - }]; - try { - const response =Docs.Documents.batchUpdate({'requests': requests}, documentId); - return response.replies; - } catch (e) { - // TODO (developer) - Handle exception - console.log('Failed with an error %s', e.message); - } + }, + ]; + const response = Docs.Documents.batchUpdate( + { requests: requests }, + documentId, + ); + return response.replies; } // [END docs_insert_and_style_text] @@ -142,31 +138,28 @@ function insertAndStyleText(documentId, text) { * @see https://developers.google.com/docs/api/reference/rest/v1/documents/get */ function readFirstParagraph(documentId) { - try { - // Get the document using document ID - const document = Docs.Documents.get(documentId, {'includeTabsContent': true}); - const firstTab = document.tabs[0]; - const bodyElements = firstTab.documentTab.body.content; - for (let i = 0; i < bodyElements.length; i++) { - const structuralElement = bodyElements[i]; - // Print the first paragraph text present in document - if (structuralElement.paragraph) { - const paragraphElements = structuralElement.paragraph.elements; - let paragraphText = ''; + // Get the document using document ID + const document = Docs.Documents.get(documentId, { + includeTabsContent: true, + }); + const firstTab = document.tabs[0]; + const bodyElements = firstTab.documentTab.body.content; + for (let i = 0; i < bodyElements.length; i++) { + const structuralElement = bodyElements[i]; + // Print the first paragraph text present in document + if (structuralElement.paragraph) { + const paragraphElements = structuralElement.paragraph.elements; + let paragraphText = ""; - for (let j = 0; j < paragraphElements.length; j++) { - const paragraphElement = paragraphElements[j]; - if (paragraphElement.textRun !== null) { - paragraphText += paragraphElement.textRun.content; - } + for (let j = 0; j < paragraphElements.length; j++) { + const paragraphElement = paragraphElements[j]; + if (paragraphElement.textRun !== null) { + paragraphText += paragraphElement.textRun.content; } - console.log(paragraphText); - return paragraphText; } + console.log(paragraphText); + return paragraphText; } - } catch (e) { - // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); } } // [END docs_read_first_paragraph] diff --git a/advanced/doubleclick.gs b/advanced/doubleclick.gs index 1d556465b..22bd7284a 100644 --- a/advanced/doubleclick.gs +++ b/advanced/doubleclick.gs @@ -26,13 +26,16 @@ function listUserProfiles() { // Print out the user ID and name of each for (let i = 0; i < profiles.items.length; i++) { const profile = profiles.items[i]; - console.log('Found profile with ID %s and name "%s".', - profile.profileId, profile.userName); + console.log( + 'Found profile with ID %s and name "%s".', + profile.profileId, + profile.userName, + ); } } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_doubleclick_list_user_profiles] @@ -43,29 +46,32 @@ function listUserProfiles() { * Note the use of paging tokens to retrieve the whole list. */ function listActiveCampaigns() { - const profileId = '1234567'; // Replace with your profile ID. - const fields = 'nextPageToken,campaigns(id,name)'; + const profileId = "1234567"; // Replace with your profile ID. + const fields = "nextPageToken,campaigns(id,name)"; let result; let pageToken; try { do { result = DoubleClickCampaigns.Campaigns.list(profileId, { - 'archived': false, - 'fields': fields, - 'pageToken': pageToken + archived: false, + fields: fields, + pageToken: pageToken, }); if (result.campaigns) { for (let i = 0; i < result.campaigns.length; i++) { const campaign = result.campaigns[i]; - console.log('Found campaign with ID %s and name "%s".', - campaign.id, campaign.name); + console.log( + 'Found campaign with ID %s and name "%s".', + campaign.id, + campaign.name, + ); } } pageToken = result.nextPageToken; } while (pageToken); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_doubleclick_list_active_campaigns] @@ -76,25 +82,29 @@ function listActiveCampaigns() { * The campaign is set to last for one month. */ function createAdvertiserAndCampaign() { - const profileId = '1234567'; // Replace with your profile ID. + const profileId = "1234567"; // Replace with your profile ID. const advertiser = { - name: 'Example Advertiser', - status: 'APPROVED' + name: "Example Advertiser", + status: "APPROVED", }; try { - const advertiserId = DoubleClickCampaigns.Advertisers - .insert(advertiser, profileId).id; + const advertiserId = DoubleClickCampaigns.Advertisers.insert( + advertiser, + profileId, + ).id; const landingPage = { advertiserId: advertiserId, archived: false, - name: 'Example landing page', - url: 'https://www.google.com' + name: "Example landing page", + url: "https://www.google.com", }; - const landingPageId = DoubleClickCampaigns.AdvertiserLandingPages - .insert(landingPage, profileId).id; + const landingPageId = DoubleClickCampaigns.AdvertiserLandingPages.insert( + landingPage, + profileId, + ).id; const campaignStart = new Date(); // End campaign after 1 month. @@ -104,14 +114,14 @@ function createAdvertiserAndCampaign() { const campaign = { advertiserId: advertiserId, defaultLandingPageId: landingPageId, - name: 'Example campaign', - startDate: Utilities.formatDate(campaignStart, 'GMT', 'yyyy-MM-dd'), - endDate: Utilities.formatDate(campaignEnd, 'GMT', 'yyyy-MM-dd') + name: "Example campaign", + startDate: Utilities.formatDate(campaignStart, "GMT", "yyyy-MM-dd"), + endDate: Utilities.formatDate(campaignEnd, "GMT", "yyyy-MM-dd"), }; DoubleClickCampaigns.Campaigns.insert(campaign, profileId); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_doubleclick_create_advertiser_and_campaign] diff --git a/advanced/doubleclickbidmanager.gs b/advanced/doubleclickbidmanager.gs index 9645ad7d2..c513622ab 100644 --- a/advanced/doubleclickbidmanager.gs +++ b/advanced/doubleclickbidmanager.gs @@ -26,13 +26,16 @@ function listQueries() { // Print out the ID and name of each for (let i = 0; i < queries.queries.length; i++) { const query = queries.queries[i]; - console.log('Found query with ID %s and name "%s".', - query.queryId, query.metadata.title); + console.log( + 'Found query with ID %s and name "%s".', + query.queryId, + query.metadata.title, + ); } } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dcbm_list_queries] @@ -46,51 +49,56 @@ function createAndRunQuery() { let execution; //We leave the default date range blank for the report run to //use the value defined during query creation - let defaultDateRange = {} - let partnerId = "1234567" //Replace with your Partner ID - let query = { - "metadata": { - "title": "Apps Script Example Report", - "dataRange": { - "range": "YEAR_TO_DATE" + const defaultDateRange = {}; + const partnerId = "1234567"; //Replace with your Partner ID + const query = { + metadata: { + title: "Apps Script Example Report", + dataRange: { + range: "YEAR_TO_DATE", }, - "format": "CSV" + format: "CSV", }, - "params": { - "type": "STANDARD", - "groupBys": [ + params: { + type: "STANDARD", + groupBys: [ "FILTER_PARTNER", "FILTER_PARTNER_NAME", "FILTER_ADVERTISER", "FILTER_ADVERTISER_NAME", ], - "filters": [ - {"type": "FILTER_PARTNER","value": partnerId} - ], - "metrics": [ - "METRIC_IMPRESSIONS" - ] + filters: [{ type: "FILTER_PARTNER", value: partnerId }], + metrics: ["METRIC_IMPRESSIONS"], }, - "schedule": { - "frequency": "ONE_TIME" - } - } + schedule: { + frequency: "ONE_TIME", + }, + }; try { result = DoubleClickBidManager.Queries.create(query); if (result.queryId) { - console.log('Created query with ID %s and name "%s".', - result.queryId, result.metadata.title); - execution = DoubleClickBidManager.Queries.run(defaultDateRange, result.queryId); - if(execution.key){ - console.log('Created query report with query ID %s and report ID "%s".', - execution.key.queryId, execution.key.reportId); + console.log( + 'Created query with ID %s and name "%s".', + result.queryId, + result.metadata.title, + ); + execution = DoubleClickBidManager.Queries.run( + defaultDateRange, + result.queryId, + ); + if (execution.key) { + console.log( + 'Created query report with query ID %s and report ID "%s".', + execution.key.queryId, + execution.key.reportId, + ); } } } catch (e) { // TODO (Developer) - Handle exception - console.log(e) - console.log('Failed with error: %s', e.error); + console.log(e); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dcbm_create_and_run_query] @@ -100,27 +108,32 @@ function createAndRunQuery() { * Fetches a report file */ function fetchReport() { - const queryId = '1234567'; // Replace with your query ID. + const queryId = "1234567"; // Replace with your query ID. const orderBy = "key.reportId desc"; try { - const report = DoubleClickBidManager.Queries.Reports.list(queryId, {orderBy:orderBy}); - if(report.reports){ + const report = DoubleClickBidManager.Queries.Reports.list(queryId, { + orderBy: orderBy, + }); + if (report.reports) { const firstReport = report.reports[0]; - if(firstReport.metadata.status.state == 'DONE'){ - const reportFile = UrlFetchApp.fetch(firstReport.metadata.googleCloudStoragePath) - console.log("Printing report content to log...") - console.log(reportFile.getContentText()) - } - else{ - console.log("Report status is %s, and is not available for download", firstReport.metadata.status.state) + if (firstReport.metadata.status.state === "DONE") { + const reportFile = UrlFetchApp.fetch( + firstReport.metadata.googleCloudStoragePath, + ); + console.log("Printing report content to log..."); + console.log(reportFile.getContentText()); + } else { + console.log( + "Report status is %s, and is not available for download", + firstReport.metadata.status.state, + ); } } - } catch (e) { // TODO (Developer) - Handle exception - console.log(e) - console.log('Failed with error: %s', e.error); + console.log(e); + console.log("Failed with error: %s", e.error); } } // [END apps_script_dcbm_fetch_report] diff --git a/advanced/drive.gs b/advanced/drive.gs index a0ff1ab18..dce8adadf 100644 --- a/advanced/drive.gs +++ b/advanced/drive.gs @@ -21,17 +21,17 @@ function uploadFile() { try { // Makes a request to fetch a URL. - const image = UrlFetchApp.fetch('http://goo.gl/nd7zjB').getBlob(); + const image = UrlFetchApp.fetch("http://goo.gl/nd7zjB").getBlob(); let file = { - name: 'google_logo.png', - mimeType: 'image/png' + name: "google_logo.png", + mimeType: "image/png", }; // Create a file in the user's Drive. - file = Drive.Files.create(file, image, {'fields': 'id,size'}); - console.log('ID: %s, File size (bytes): %s', file.id, file.size); + file = Drive.Files.create(file, image, { fields: "id,size" }); + console.log("ID: %s, File size (bytes): %s", file.id, file.size); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to upload file with error %s', err.message); + console.log("Failed to upload file with error %s", err.message); } } // [END drive_upload_file] @@ -41,7 +41,8 @@ function uploadFile() { * Lists the top-level folders in the user's Drive. */ function listRootFolders() { - const query = '"root" in parents and trashed = false and ' + + const query = + '"root" in parents and trashed = false and ' + 'mimeType = "application/vnd.google-apps.folder"'; let folders; let pageToken = null; @@ -50,20 +51,20 @@ function listRootFolders() { folders = Drive.Files.list({ q: query, pageSize: 100, - pageToken: pageToken + pageToken: pageToken, }); if (!folders.files || folders.files.length === 0) { - console.log('All folders found.'); + console.log("All folders found."); return; } for (let i = 0; i < folders.files.length; i++) { const folder = folders.files[i]; - console.log('%s (ID: %s)', folder.name, folder.id); + console.log("%s (ID: %s)", folder.name, folder.id); } pageToken = folders.nextPageToken; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } while (pageToken); } @@ -79,19 +80,22 @@ function listRootFolders() { function addAppProperty(fileId) { try { let file = { - 'appProperties': { - 'department': 'Sales' - } + appProperties: { + department: "Sales", + }, }; // Updates a file to add an app property. - file = Drive.Files.update(file, fileId, null, {'fields': 'id,appProperties'}); + file = Drive.Files.update(file, fileId, null, { + fields: "id,appProperties", + }); console.log( - 'ID: %s, appProperties: %s', - file.id, - JSON.stringify(file.appProperties, null, 2)); + "ID: %s, appProperties: %s", + file.id, + JSON.stringify(file.appProperties, null, 2), + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END drive_add_custom_property] @@ -103,26 +107,29 @@ function addAppProperty(fileId) { */ function listRevisions(fileId) { let revisions; - const pageToken = null; + let pageToken = null; do { try { - revisions = Drive.Revisions.list( - fileId, - {'fields': 'revisions(modifiedTime,size),nextPageToken'}); + revisions = Drive.Revisions.list(fileId, { + fields: "revisions(modifiedTime,size),nextPageToken", + }); if (!revisions.revisions || revisions.revisions.length === 0) { - console.log('All revisions found.'); + console.log("All revisions found."); return; } for (let i = 0; i < revisions.revisions.length; i++) { const revision = revisions.revisions[i]; const date = new Date(revision.modifiedTime); - console.log('Date: %s, File size (bytes): %s', date.toLocaleString(), - revision.size); + console.log( + "Date: %s, File size (bytes): %s", + date.toLocaleString(), + revision.size, + ); } pageToken = revisions.nextPageToken; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } while (pageToken); } diff --git a/advanced/driveActivity.gs b/advanced/driveActivity.gs index b139dfe72..3ca6e7290 100644 --- a/advanced/driveActivity.gs +++ b/advanced/driveActivity.gs @@ -19,15 +19,15 @@ * unique users that performed the activity. */ function getUsersActivity() { - const fileId = 'YOUR_FILE_ID_HERE'; + const fileId = "YOUR_FILE_ID_HERE"; let pageToken; const users = {}; do { - let result = AppsActivity.Activities.list({ - 'drive.fileId': fileId, - 'source': 'drive.google.com', - 'pageToken': pageToken + const result = AppsActivity.Activities.list({ + "drive.fileId": fileId, + source: "drive.google.com", + pageToken: pageToken, }); const activities = result.activities; for (let i = 0; i < activities.length; i++) { diff --git a/advanced/driveLabels.gs b/advanced/driveLabels.gs index 004a35089..e52c62ee3 100644 --- a/advanced/driveLabels.gs +++ b/advanced/driveLabels.gs @@ -25,17 +25,17 @@ function listLabels() { try { const response = DriveLabels.Labels.list({ publishedOnly: true, - pageToken: pageToken + pageToken: pageToken, }); pageToken = response.nextPageToken; labels = labels.concat(response.labels); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to list labels with error %s', err.message); + console.log("Failed to list labels with error %s", err.message); } } while (pageToken != null); - console.log('Found %d labels', labels.length); + console.log("Found %d labels", labels.length); } // [END apps_script_drive_labels_list_labels] @@ -46,13 +46,17 @@ function listLabels() { */ function getLabel(labelName) { try { - const label = DriveLabels.Labels.get(labelName, {view: 'LABEL_VIEW_FULL'}); + const label = DriveLabels.Labels.get(labelName, { + view: "LABEL_VIEW_FULL", + }); const title = label.properties.title; const fieldsLength = label.fields.length; - console.log(`Fetched label with title: '${title}' and ${fieldsLength} fields.`); + console.log( + `Fetched label with title: '${title}' and ${fieldsLength} fields.`, + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to get label with error %s', err.message); + console.log("Failed to get label with error %s", err.message); } } // [END apps_script_drive_labels_get_label] @@ -69,56 +73,71 @@ function listLabelsOnDriveItem(fileId) { try { const appliedLabels = Drive.Files.listLabels(fileId); - console.log('%d label(s) are applied to this file', appliedLabels.labels.length); + console.log( + "%d label(s) are applied to this file", + appliedLabels.labels.length, + ); - appliedLabels.labels.forEach((appliedLabel) => { + for (const appliedLabel of appliedLabels.labels) { // Resource name of the label at the applied revision. - const labelName = 'labels/' + appliedLabel.id + '@' + appliedLabel.revisionId; + const labelName = `labels/${appliedLabel.id}@${appliedLabel.revisionId}`; - console.log('Fetching Label: %s', labelName); - const label = DriveLabels.Labels.get(labelName, {view: 'LABEL_VIEW_FULL'}); + console.log("Fetching Label: %s", labelName); + const label = DriveLabels.Labels.get(labelName, { + view: "LABEL_VIEW_FULL", + }); - console.log('Label Title: %s', label.properties.title); + console.log("Label Title: %s", label.properties.title); - Object.keys(appliedLabel.fields).forEach((fieldId) => { + for (const fieldId of Object.keys(appliedLabel.fields)) { const fieldValue = appliedLabel.fields[fieldId]; - const field = label.fields.find((f) => f.id == fieldId); + const field = label.fields.find((f) => f.id === fieldId); - console.log(`Field ID: ${field.id}, Display Name: ${field.properties.displayName}`); + console.log( + `Field ID: ${field.id}, Display Name: ${field.properties.displayName}`, + ); switch (fieldValue.valueType) { - case 'text': - console.log('Text: %s', fieldValue.text[0]); + case "text": + console.log("Text: %s", fieldValue.text[0]); break; - case 'integer': - console.log('Integer: %d', fieldValue.integer[0]); + case "integer": + console.log("Integer: %d", fieldValue.integer[0]); break; - case 'dateString': - console.log('Date: %s', fieldValue.dateString[0]); + case "dateString": + console.log("Date: %s", fieldValue.dateString[0]); break; - case 'user': - const user = fieldValue.user.map((user) => { - return `${user.emailAddress}: ${user.displayName}`; - }).join(', '); + case "user": { + const user = fieldValue.user + .map((user) => { + return `${user.emailAddress}: ${user.displayName}`; + }) + .join(", "); console.log(`User: ${user}`); break; - case 'selection': + } + case "selection": { const choices = fieldValue.selection.map((choiceId) => { - return field.selectionOptions.choices.find((choice) => choice.id === choiceId); + return field.selectionOptions.choices.find( + (choice) => choice.id === choiceId, + ); }); - const selection = choices.map((choice) => { - return `${choice.id}: ${choice.properties.displayName}`; - }).join(', '); + const selection = choices + .map((choice) => { + return `${choice.id}: ${choice.properties.displayName}`; + }) + .join(", "); console.log(`Selection: ${selection}`); break; + } default: - console.log('Unknown: %s', fieldValue.valueType); + console.log("Unknown: %s", fieldValue.valueType); console.log(fieldValue.value); } - }); - }); + } + } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_drive_labels_list_labels_on_drive_item] diff --git a/advanced/events.gs b/advanced/events.gs index 2d5a1383f..914344102 100644 --- a/advanced/events.gs +++ b/advanced/events.gs @@ -38,7 +38,7 @@ function createSubscription(targetResource, eventTypes, pubsubTopic) { console.log(operation); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to create subscription with error %s', err.message); + console.log("Failed to create subscription with error %s", err.message); } } // [END events_create_subscription] @@ -57,7 +57,7 @@ function listSubscriptions(filter) { console.log(response); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to list subscriptions with error %s', err.message); + console.log("Failed to list subscriptions with error %s", err.message); } } // [END events_list_subscriptions] @@ -76,7 +76,7 @@ function getSubscription(name) { console.log(subscription); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to get subscription with error %s', err.message); + console.log("Failed to get subscription with error %s", err.message); } } // [END events_get_subscription] @@ -92,14 +92,17 @@ function getSubscription(name) { */ function patchSubscription(name) { try { - const operation = WorkspaceEvents.Subscriptions.patch({ - // Setting the TTL to 0 seconds extends the subscription to its maximum expiration time. - ttl: '0s', - }, name); + const operation = WorkspaceEvents.Subscriptions.patch( + { + // Setting the TTL to 0 seconds extends the subscription to its maximum expiration time. + ttl: "0s", + }, + name, + ); console.log(operation); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to update subscription with error %s', err.message); + console.log("Failed to update subscription with error %s", err.message); } } // [END events_patch_subscription] @@ -119,7 +122,7 @@ function reactivateSubscription(name) { console.log(operation); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to reactivate subscription with error %s', err.message); + console.log("Failed to reactivate subscription with error %s", err.message); } } // [END events_reactivate_subscription] @@ -138,7 +141,7 @@ function deleteSubscription(name) { console.log(operation); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to delete subscription with error %s', err.message); + console.log("Failed to delete subscription with error %s", err.message); } } // [END events_delete_subscription] @@ -158,7 +161,7 @@ function getOperation(name) { console.log(operation); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to get operation with error %s', err.message); + console.log("Failed to get operation with error %s", err.message); } } // [END events_get_operation] diff --git a/advanced/gmail.gs b/advanced/gmail.gs index ec08431bf..3753c9f50 100644 --- a/advanced/gmail.gs +++ b/advanced/gmail.gs @@ -20,8 +20,7 @@ */ function listLabelInfo() { try { - const response = - Gmail.Users.Labels.list('me'); + const response = Gmail.Users.Labels.list("me"); for (let i = 0; i < response.labels.length; i++) { const label = response.labels[i]; console.log(JSON.stringify(label)); @@ -41,14 +40,14 @@ function listInboxSnippets() { try { let pageToken; do { - const threadList = Gmail.Users.Threads.list('me', { - q: 'label:inbox', - pageToken: pageToken + const threadList = Gmail.Users.Threads.list("me", { + q: "label:inbox", + pageToken: pageToken, }); if (threadList.threads && threadList.threads.length > 0) { - threadList.threads.forEach(function (thread) { - console.log('Snippet: %s', thread.snippet); - }); + for (const thread of threadList.threads) { + console.log(`Snippet: ${thread.snippet}`); + } } pageToken = threadList.nextPageToken; } while (pageToken); @@ -58,7 +57,6 @@ function listInboxSnippets() { } // [END gmail_inbox_snippets] - // [START gmail_history] /** * Gets a history record ID associated with the most @@ -69,12 +67,12 @@ function logRecentHistory() { try { // Get the history ID associated with the most recent // sent message. - const sent = Gmail.Users.Threads.list('me', { - q: 'label:sent', - maxResults: 1 + const sent = Gmail.Users.Threads.list("me", { + q: "label:sent", + maxResults: 1, }); if (!sent.threads || !sent.threads[0]) { - console.log('No sent threads found.'); + console.log("No sent threads found."); return; } const historyId = sent.threads[0].historyId; @@ -84,26 +82,26 @@ function logRecentHistory() { let pageToken; const changed = []; do { - const recordList = Gmail.Users.History.list('me', { + const recordList = Gmail.Users.History.list("me", { startHistoryId: historyId, - pageToken: pageToken + pageToken: pageToken, }); const history = recordList.history; if (history && history.length > 0) { - history.forEach(function (record) { - record.messages.forEach(function (message) { + for (const record of history) { + for (const message of record.messages) { if (changed.indexOf(message.id) === -1) { changed.push(message.id); } - }); - }); + } + } } pageToken = recordList.nextPageToken; } while (pageToken); - changed.forEach(function (id) { - console.log('Message Changed: %s', id); - }); + for (const id of changed) { + console.log("Message Changed: %s", id); + } } catch (err) { console.log(err); } @@ -116,10 +114,10 @@ function logRecentHistory() { */ function getRawMessage() { try { - const messageId = Gmail.Users.Messages.list('me').messages[0].id; + const messageId = Gmail.Users.Messages.list("me").messages[0].id; console.log(messageId); - const message = Gmail.Users.Messages.get('me', messageId, { - 'format': 'raw' + const message = Gmail.Users.Messages.get("me", messageId, { + format: "raw", }); // Get raw content as base64url encoded string. @@ -137,19 +135,19 @@ function getRawMessage() { */ function listMessages() { // The special value 'me' indicates the authenticated user. - const userId = 'me'; + const userId = "me"; // Define optional parameters for the request. const options = { maxResults: 10, // Limit the number of messages returned. - q: 'is:unread', // Search for unread messages. + q: "is:unread", // Search for unread messages. }; try { // Call the Gmail.Users.Messages.list method. const response = Gmail.Users.Messages.list(userId, options); const messages = response.messages; - console.log('Unread Messages:'); + console.log("Unread Messages:"); for (const message of messages) { console.log(`- Message ID: ${message.id}`); diff --git a/advanced/iot.gs b/advanced/iot.gs index 4f9739183..84636baf8 100644 --- a/advanced/iot.gs +++ b/advanced/iot.gs @@ -18,17 +18,16 @@ * Lists the registries for the configured project and region. */ function listRegistries() { - const projectId = 'your-project-id'; - const cloudRegion = 'us-central1'; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion; + const projectId = "your-project-id"; + const cloudRegion = "us-central1"; + const parent = `projects/${projectId}/locations/${cloudRegion}`; const response = CloudIoT.Projects.Locations.Registries.list(parent); console.log(response); if (response.deviceRegistries) { - response.deviceRegistries.forEach( - function(registry) { - console.log(registry.id); - }); + for (const registry of response.deviceRegistries) { + console.log(registry.id); + } } } // [END apps_script_iot_list_registries] @@ -38,24 +37,29 @@ function listRegistries() { * Creates a registry. */ function createRegistry() { - const cloudRegion = 'us-central1'; - const name = 'your-registry-name'; - const projectId = 'your-project-id'; - const topic = 'your-pubsub-topic'; + const cloudRegion = "us-central1"; + const name = "your-registry-name"; + const projectId = "your-project-id"; + const topic = "your-pubsub-topic"; - const pubsubTopic = 'projects/' + projectId + '/topics/' + topic; + const pubsubTopic = `projects/${projectId}/topics/${topic}`; const registry = { - 'eventNotificationConfigs': [{ - // From - https://console.cloud.google.com/cloudpubsub - pubsubTopicName: pubsubTopic - }], - 'id': name + eventNotificationConfigs: [ + { + // From - https://console.cloud.google.com/cloudpubsub + pubsubTopicName: pubsubTopic, + }, + ], + id: name, }; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion; + const parent = `projects/${projectId}/locations/${cloudRegion}`; - const response = CloudIoT.Projects.Locations.Registries.create(registry, parent); - console.log('Created registry: ' + response.id); + const response = CloudIoT.Projects.Locations.Registries.create( + registry, + parent, + ); + console.log(`Created registry: ${response.id}`); } // [END apps_script_iot_create_registry] @@ -64,15 +68,15 @@ function createRegistry() { * Describes a registry. */ function getRegistry() { - const cloudRegion = 'us-central1'; - const name = 'your-registry-name'; - const projectId = 'your-project-id'; + const cloudRegion = "us-central1"; + const name = "your-registry-name"; + const projectId = "your-project-id"; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion; - const registryName = parent + '/registries/' + name; + const parent = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parent}/registries/${name}`; const response = CloudIoT.Projects.Locations.Registries.get(registryName); - console.log('Retrieved registry: ' + response.id); + console.log(`Retrieved registry: ${response.id}`); } // [END apps_script_iot_get_registry] @@ -81,16 +85,16 @@ function getRegistry() { * Deletes a registry. */ function deleteRegistry() { - const cloudRegion = 'us-central1'; - const name = 'your-registry-name'; - const projectId = 'your-project-id'; + const cloudRegion = "us-central1"; + const name = "your-registry-name"; + const projectId = "your-project-id"; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion; - const registryName = parent + '/registries/' + name; + const parent = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parent}/registries/${name}`; const response = CloudIoT.Projects.Locations.Registries.remove(registryName); // Successfully removed registry if exception was not thrown. - console.log('Deleted registry: ' + name); + console.log(`Deleted registry: ${name}`); } // [END apps_script_iot_delete_registry] @@ -99,21 +103,21 @@ function deleteRegistry() { * Lists the devices in the given registry. */ function listDevicesForRegistry() { - const cloudRegion = 'us-central1'; - const name = 'your-registry-name'; - const projectId = 'your-project-id'; + const cloudRegion = "us-central1"; + const name = "your-registry-name"; + const projectId = "your-project-id"; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion; - const registryName = parent + '/registries/' + name; + const parent = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parent}/registries/${name}`; - const response = CloudIoT.Projects.Locations.Registries.Devices.list(registryName); + const response = + CloudIoT.Projects.Locations.Registries.Devices.list(registryName); - console.log('Registry contains the following devices: '); + console.log("Registry contains the following devices: "); if (response.devices) { - response.devices.forEach( - function(device) { - console.log('\t' + device.id); - }); + for (const device of response.devices) { + console.log(`\t${device.id}`); + } } } // [END apps_script_iot_list_devices] @@ -123,24 +127,27 @@ function listDevicesForRegistry() { * Creates a device without credentials. */ function createDevice() { - const cloudRegion = 'us-central1'; - const name = 'your-device-name'; - const projectId = 'your-project-id'; - const registry = 'your-registry-name'; + const cloudRegion = "us-central1"; + const name = "your-device-name"; + const projectId = "your-project-id"; + const registry = "your-registry-name"; - console.log('Creating device: ' + name + ' in Registry: ' + registry); - const parent = 'projects/' + projectId + '/locations/' + cloudRegion + '/registries/' + registry; + console.log(`Creating device: ${name} in Registry: ${registry}`); + const parent = `projects/${projectId}/locations/${cloudRegion}/registries/${registry}`; const device = { id: name, gatewayConfig: { - gatewayType: 'NON_GATEWAY', - gatewayAuthMethod: 'ASSOCIATION_ONLY' - } + gatewayType: "NON_GATEWAY", + gatewayAuthMethod: "ASSOCIATION_ONLY", + }, }; - const response = CloudIoT.Projects.Locations.Registries.Devices.create(device, parent); - console.log('Created device:' + response.name); + const response = CloudIoT.Projects.Locations.Registries.Devices.create( + device, + parent, + ); + console.log(`Created device:${response.name}`); } // [END apps_script_iot_create_unauth_device] @@ -155,34 +162,39 @@ function createRsaDevice() { // // **NOTE** Be sure to insert the newline charaters in the string constant. const cert = - '-----BEGIN CERTIFICATE-----\n' + - 'your-PUBLIC-certificate-b64-bytes\n' + - '...\n' + - 'more-PUBLIC-certificate-b64-bytes==\n' + - '-----END CERTIFICATE-----\n'; - - const cloudRegion = 'us-central1'; - const name = 'your-device-name'; - const projectId = 'your-project-id'; - const registry = 'your-registry-name'; - - const parent = 'projects/' + projectId + '/locations/' + cloudRegion + '/registries/' + registry; + "-----BEGIN CERTIFICATE-----\n" + + "your-PUBLIC-certificate-b64-bytes\n" + + "...\n" + + "more-PUBLIC-certificate-b64-bytes==\n" + + "-----END CERTIFICATE-----\n"; + + const cloudRegion = "us-central1"; + const name = "your-device-name"; + const projectId = "your-project-id"; + const registry = "your-registry-name"; + + const parent = `projects/${projectId}/locations/${cloudRegion}/registries/${registry}`; const device = { id: name, gatewayConfig: { - gatewayType: 'NON_GATEWAY', - gatewayAuthMethod: 'ASSOCIATION_ONLY' + gatewayType: "NON_GATEWAY", + gatewayAuthMethod: "ASSOCIATION_ONLY", }, - credentials: [{ - publicKey: { - format: 'RSA_X509_PEM', - key: cert - } - }] + credentials: [ + { + publicKey: { + format: "RSA_X509_PEM", + key: cert, + }, + }, + ], }; - const response = CloudIoT.Projects.Locations.Registries.Devices.create(device, parent); - console.log('Created device:' + response.name); + const response = CloudIoT.Projects.Locations.Registries.Devices.create( + device, + parent, + ); + console.log(`Created device:${response.name}`); } // [END apps_script_iot_create_rsa_device] @@ -191,17 +203,17 @@ function createRsaDevice() { * Deletes a device from the given registry. */ function deleteDevice() { - const cloudRegion = 'us-central1'; - const name = 'your-device-name'; - const projectId = 'your-project-id'; - const registry = 'your-registry-name'; + const cloudRegion = "us-central1"; + const name = "your-device-name"; + const projectId = "your-project-id"; + const registry = "your-registry-name"; - const parent = 'projects/' + projectId + '/locations/' + cloudRegion + '/registries/' + registry; - const deviceName = parent + '/devices/' + name; + const parent = `projects/${projectId}/locations/${cloudRegion}/registries/${registry}`; + const deviceName = `${parent}/devices/${name}`; - const response = CloudIoT.Projects.Locations.Registries.Devices.remove(deviceName); + const response = + CloudIoT.Projects.Locations.Registries.Devices.remove(deviceName); // If no exception thrown, device was successfully removed - console.log('Successfully deleted device: ' + deviceName); + console.log(`Successfully deleted device: ${deviceName}`); } // [END apps_script_iot_delete_device] - diff --git a/advanced/people.gs b/advanced/people.gs index 10cf68d09..b9df1b75c 100644 --- a/advanced/people.gs +++ b/advanced/people.gs @@ -21,14 +21,14 @@ function getConnections() { try { // Get the list of connections/contacts of user's profile - const people = People.People.Connections.list('people/me', { - personFields: 'names,emailAddresses' + const people = People.People.Connections.list("people/me", { + personFields: "names,emailAddresses", }); // Print the connections/contacts - console.log('Connections: %s', JSON.stringify(people, null, 2)); + console.log("Connections: %s", JSON.stringify(people, null, 2)); } catch (err) { // TODO (developers) - Handle exception here - console.log('Failed to get the connection with an error %s', err.message); + console.log("Failed to get the connection with an error %s", err.message); } } // [END people_get_connections] @@ -42,14 +42,14 @@ function getSelf() { try { // Get own user's profile using People.getBatchGet() method const people = People.People.getBatchGet({ - resourceNames: ['people/me'], - personFields: 'names,emailAddresses' + resourceNames: ["people/me"], + personFields: "names,emailAddresses", // Use other query parameter here if needed }); - console.log('Myself: %s', JSON.stringify(people, null, 2)); + console.log("Myself: %s", JSON.stringify(people, null, 2)); } catch (err) { // TODO (developer) -Handle exception - console.log('Failed to get own profile with an error %s', err.message); + console.log("Failed to get own profile with an error %s", err.message); } } // [END people_get_self_profile] @@ -63,14 +63,14 @@ function getSelf() { function getAccount(accountId) { try { // Get the Account details using account ID. - const people = People.People.get('people/' + accountId, { - personFields: 'names,emailAddresses' + const people = People.People.get(`people/${accountId}`, { + personFields: "names,emailAddresses", }); // Print the profile details of Account. - console.log('Public Profile: %s', JSON.stringify(people, null, 2)); + console.log("Public Profile: %s", JSON.stringify(people, null, 2)); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed to get account with an error %s', err.message); + console.log("Failed to get account with an error %s", err.message); } } // [END people_get_account] @@ -86,12 +86,15 @@ function getContactGroup(name) { try { const people = People.ContactGroups.list(); // Finds the contact group for the person where the name matches. - const group = people['contactGroups'].find((group) => group['name'] === name); + const group = people.contactGroups.find((group) => group.name === name); // Prints the contact group - console.log('Group: %s', JSON.stringify(group, null, 2)); + console.log("Group: %s", JSON.stringify(group, null, 2)); } catch (err) { // TODO (developers) - Handle exception - console.log('Failed to get the contact group with an error %s', err.message); + console.log( + "Failed to get the contact group with an error %s", + err.message, + ); } } @@ -107,17 +110,19 @@ function getContactGroup(name) { function getContactByEmail(email) { try { // Gets the person with that email address by iterating over all contacts. - const people = People.People.Connections.list('people/me', { - personFields: 'names,emailAddresses' + const people = People.People.Connections.list("people/me", { + personFields: "names,emailAddresses", }); - const contact = people['connections'].find((connection) => { - return connection['emailAddresses'].some((emailAddress) => emailAddress['value'] === email); + const contact = people.connections.find((connection) => { + return connection.emailAddresses.some( + (emailAddress) => emailAddress.value === email, + ); }); // Prints the contact. - console.log('Contact: %s', JSON.stringify(contact, null, 2)); + console.log("Contact: %s", JSON.stringify(contact, null, 2)); } catch (err) { // TODO (developers) - Handle exception - console.log('Failed to get the connection with an error %s', err.message); + console.log("Failed to get the connection with an error %s", err.message); } } @@ -133,12 +138,12 @@ function getFullName() { // Gets the person by specifying resource name/account ID // in the first parameter of People.People.get. // This example gets the person for the user running the script. - const people = People.People.get('people/me', {personFields: 'names'}); + const people = People.People.get("people/me", { personFields: "names" }); // Prints the full name (given name + family name) - console.log(`${people['names'][0]['givenName']} ${people['names'][0]['familyName']}`); + console.log(`${people.names[0].givenName} ${people.names[0].familyName}`); } catch (err) { // TODO (developers) - Handle exception - console.log('Failed to get the connection with an error %s', err.message); + console.log("Failed to get the connection with an error %s", err.message); } } @@ -154,12 +159,14 @@ function getPhoneNumbers() { // Gets the person by specifying resource name/account ID // in the first parameter of People.People.get. // This example gets the person for the user running the script. - const people = People.People.get('people/me', {personFields: 'phoneNumbers'}); + const people = People.People.get("people/me", { + personFields: "phoneNumbers", + }); // Prints the phone numbers. - console.log(people['phoneNumbers']); + console.log(people.phoneNumbers); } catch (err) { // TODO (developers) - Handle exception - console.log('Failed to get the connection with an error %s', err.message); + console.log("Failed to get the connection with an error %s", err.message); } } @@ -175,14 +182,18 @@ function getPhone() { // Gets the person by specifying resource name/account ID // in the first parameter of People.People.get. // This example gets the person for the user running the script. - const people = People.People.get('people/me', {personFields: 'phoneNumbers'}); + const people = People.People.get("people/me", { + personFields: "phoneNumbers", + }); // Gets phone number by type, such as home or work. - const phoneNumber = people['phoneNumbers'].find((phone) => phone['type'] === 'home')['value']; + const phoneNumber = people.phoneNumbers.find( + (phone) => phone.type === "home", + ).value; // Prints the phone numbers. console.log(phoneNumber); } catch (err) { // TODO (developers) - Handle exception - console.log('Failed to get the connection with an error %s', err.message); + console.log("Failed to get the connection with an error %s", err.message); } } diff --git a/advanced/sheets.gs b/advanced/sheets.gs index cac5df416..d124b7a70 100644 --- a/advanced/sheets.gs +++ b/advanced/sheets.gs @@ -14,7 +14,7 @@ * limitations under the License. */ // TODO (developer)- Replace the spreadsheet ID and sheet ID with yours values. -const yourspreadsheetId = '1YdrrmXSjpi4Tz-UuQ0eUKtdzQuvpzRLMoPEz3niTTVU'; +const yourspreadsheetId = "1YdrrmXSjpi4Tz-UuQ0eUKtdzQuvpzRLMoPEz3niTTVU"; const yourpivotSourceDataSheetId = 635809130; const yourdestinationSheetId = 83410180; // [START sheets_read_range] @@ -25,15 +25,18 @@ const yourdestinationSheetId = 83410180; */ function readRange(spreadsheetId = yourspreadsheetId) { try { - const response = Sheets.Spreadsheets.Values.get(spreadsheetId, 'Sheet1!A1:D5'); + const response = Sheets.Spreadsheets.Values.get( + spreadsheetId, + "Sheet1!A1:D5", + ); if (response.values) { console.log(response.values); return; } - console.log('Failed to get range of values from spreadsheet'); + console.log("Failed to get range of values from spreadsheet"); } catch (e) { // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END sheets_read_range] @@ -46,39 +49,40 @@ function readRange(spreadsheetId = yourspreadsheetId) { */ function writeToMultipleRanges(spreadsheetId = yourspreadsheetId) { // Specify some values to write to the sheet. - const columnAValues = [ - ['Item', 'Wheel', 'Door', 'Engine'] - ]; + const columnAValues = [["Item", "Wheel", "Door", "Engine"]]; const rowValues = [ - ['Cost', 'Stocked', 'Ship Date'], - ['$20.50', '4', '3/1/2016'] + ["Cost", "Stocked", "Ship Date"], + ["$20.50", "4", "3/1/2016"], ]; const request = { - 'valueInputOption': 'USER_ENTERED', - 'data': [ + valueInputOption: "USER_ENTERED", + data: [ { - 'range': 'Sheet1!A1:A4', - 'majorDimension': 'COLUMNS', - 'values': columnAValues + range: "Sheet1!A1:A4", + majorDimension: "COLUMNS", + values: columnAValues, }, { - 'range': 'Sheet1!B1:D2', - 'majorDimension': 'ROWS', - 'values': rowValues - } - ] + range: "Sheet1!B1:D2", + majorDimension: "ROWS", + values: rowValues, + }, + ], }; try { - const response = Sheets.Spreadsheets.Values.batchUpdate(request, spreadsheetId); + const response = Sheets.Spreadsheets.Values.batchUpdate( + request, + spreadsheetId, + ); if (response) { console.log(response); return; } - console.log('response null'); + console.log("response null"); } catch (e) { // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END sheets_write_range] @@ -90,30 +94,35 @@ function writeToMultipleRanges(spreadsheetId = yourspreadsheetId) { * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate */ function addSheet(spreadsheetId = yourspreadsheetId) { - const requests = [{ - 'addSheet': { - 'properties': { - 'title': 'Deposits', - 'gridProperties': { - 'rowCount': 20, - 'columnCount': 12 + const requests = [ + { + addSheet: { + properties: { + title: "Deposits", + gridProperties: { + rowCount: 20, + columnCount: 12, + }, + tabColor: { + red: 1.0, + green: 0.3, + blue: 0.4, + }, }, - 'tabColor': { - 'red': 1.0, - 'green': 0.3, - 'blue': 0.4 - } - } - } - }]; + }, + }, + ]; try { - const response = - Sheets.Spreadsheets.batchUpdate({'requests': requests}, spreadsheetId); - console.log('Created sheet with ID: ' + - response.replies[0].addSheet.properties.sheetId); + const response = Sheets.Spreadsheets.batchUpdate( + { requests: requests }, + spreadsheetId, + ); + console.log( + `Created sheet with ID: ${response.replies[0].addSheet.properties.sheetId}`, + ); } catch (e) { // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END sheets_add_new_sheet] @@ -127,75 +136,81 @@ function addSheet(spreadsheetId = yourspreadsheetId) { * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate */ function addPivotTable( - spreadsheetId = yourspreadsheetId, - pivotSourceDataSheetId= yourpivotSourceDataSheetId, - destinationSheetId= yourdestinationSheetId) { - const requests = [{ - 'updateCells': { - 'rows': { - 'values': [ - { - 'pivotTable': { - 'source': { - 'sheetId': pivotSourceDataSheetId, - 'startRowIndex': 0, - 'startColumnIndex': 0, - 'endRowIndex': 20, - 'endColumnIndex': 7 - }, - 'rows': [ - { - 'sourceColumnOffset': 0, - 'showTotals': true, - 'sortOrder': 'ASCENDING', - 'valueBucket': { - 'buckets': [ - { - 'stringValue': 'West' - } - ] - } + spreadsheetId = yourspreadsheetId, + pivotSourceDataSheetId = yourpivotSourceDataSheetId, + destinationSheetId = yourdestinationSheetId, +) { + const requests = [ + { + updateCells: { + rows: { + values: [ + { + pivotTable: { + source: { + sheetId: pivotSourceDataSheetId, + startRowIndex: 0, + startColumnIndex: 0, + endRowIndex: 20, + endColumnIndex: 7, }, - { - 'sourceColumnOffset': 1, - 'showTotals': true, - 'sortOrder': 'DESCENDING', - 'valueBucket': {} - } - ], - 'columns': [ - { - 'sourceColumnOffset': 4, - 'sortOrder': 'ASCENDING', - 'showTotals': true, - 'valueBucket': {} - } - ], - 'values': [ - { - 'summarizeFunction': 'SUM', - 'sourceColumnOffset': 3 - } - ], - 'valueLayout': 'HORIZONTAL' - } - } - ] - }, - 'start': { - 'sheetId': destinationSheetId, - 'rowIndex': 49, - 'columnIndex': 0 + rows: [ + { + sourceColumnOffset: 0, + showTotals: true, + sortOrder: "ASCENDING", + valueBucket: { + buckets: [ + { + stringValue: "West", + }, + ], + }, + }, + { + sourceColumnOffset: 1, + showTotals: true, + sortOrder: "DESCENDING", + valueBucket: {}, + }, + ], + columns: [ + { + sourceColumnOffset: 4, + sortOrder: "ASCENDING", + showTotals: true, + valueBucket: {}, + }, + ], + values: [ + { + summarizeFunction: "SUM", + sourceColumnOffset: 3, + }, + ], + valueLayout: "HORIZONTAL", + }, + }, + ], + }, + start: { + sheetId: destinationSheetId, + rowIndex: 49, + columnIndex: 0, + }, + fields: "pivotTable", }, - 'fields': 'pivotTable' - } - }]; + }, + ]; try { - const response = Sheets.Spreadsheets.batchUpdate({'requests': requests}, spreadsheetId); + const response = Sheets.Spreadsheets.batchUpdate( + { requests: requests }, + spreadsheetId, + ); // The Pivot table will appear anchored to cell A50 of the destination sheet. } catch (e) { // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END sheets_add_pivot_table] diff --git a/advanced/shoppingContent.gs b/advanced/shoppingContent.gs index 22cc7e2c8..1aed2e8d6 100644 --- a/advanced/shoppingContent.gs +++ b/advanced/shoppingContent.gs @@ -21,35 +21,37 @@ function productInsert() { const merchantId = 123456; // Replace this with your Merchant Center ID. // Create a product resource and insert it const productResource = { - 'offerId': 'book123', - 'title': 'A Tale of Two Cities', - 'description': 'A classic novel about the French Revolution', - 'link': 'http://my-book-shop.com/tale-of-two-cities.html', - 'imageLink': 'http://my-book-shop.com/tale-of-two-cities.jpg', - 'contentLanguage': 'en', - 'targetCountry': 'US', - 'channel': 'online', - 'availability': 'in stock', - 'condition': 'new', - 'googleProductCategory': 'Media > Books', - 'productType': 'Media > Books', - 'gtin': '9780007350896', - 'price': { - 'value': '2.50', - 'currency': 'USD' + offerId: "book123", + title: "A Tale of Two Cities", + description: "A classic novel about the French Revolution", + link: "http://my-book-shop.com/tale-of-two-cities.html", + imageLink: "http://my-book-shop.com/tale-of-two-cities.jpg", + contentLanguage: "en", + targetCountry: "US", + channel: "online", + availability: "in stock", + condition: "new", + googleProductCategory: "Media > Books", + productType: "Media > Books", + gtin: "9780007350896", + price: { + value: "2.50", + currency: "USD", + }, + shipping: [ + { + country: "US", + service: "Standard shipping", + price: { + value: "0.99", + currency: "USD", + }, + }, + ], + shippingWeight: { + value: "2", + unit: "pounds", }, - 'shipping': [{ - 'country': 'US', - 'service': 'Standard shipping', - 'price': { - 'value': '0.99', - 'currency': 'USD' - } - }], - 'shippingWeight': { - 'value': '2', - 'unit': 'pounds' - } }; try { @@ -58,7 +60,7 @@ function productInsert() { console.log(response); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_shopping_product_insert] @@ -76,22 +78,22 @@ function productList() { do { const products = ShoppingContent.Products.list(merchantId, { pageToken: pageToken, - maxResults: maxResults + maxResults: maxResults, }); - console.log('Page ' + pageNum); + console.log(`Page ${pageNum}`); if (products.resources) { for (let i = 0; i < products.resources.length; i++) { - console.log('Item [' + i + '] ==> ' + products.resources[i]); + console.log(`Item [${i}] ==> ${products.resources[i]}`); } } else { - console.log('No more products in account ' + merchantId); + console.log(`No more products in account ${merchantId}`); } pageToken = products.nextPageToken; pageNum++; } while (pageToken); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_shopping_product_list] @@ -106,36 +108,36 @@ function productList() { function custombatch(productResource1, productResource2, productResource3) { const merchantId = 123456; // Replace this with your Merchant Center ID. custombatchResource = { - 'entries': [ + entries: [ { - 'batchId': 1, - 'merchantId': merchantId, - 'method': 'insert', - 'productId': 'book124', - 'product': productResource1 + batchId: 1, + merchantId: merchantId, + method: "insert", + productId: "book124", + product: productResource1, }, { - 'batchId': 2, - 'merchantId': merchantId, - 'method': 'insert', - 'productId': 'book125', - 'product': productResource2 + batchId: 2, + merchantId: merchantId, + method: "insert", + productId: "book125", + product: productResource2, }, { - 'batchId': 3, - 'merchantId': merchantId, - 'method': 'insert', - 'productId': 'book126', - 'product': productResource3 - } - ] + batchId: 3, + merchantId: merchantId, + method: "insert", + productId: "book126", + product: productResource3, + }, + ], }; try { const response = ShoppingContent.Products.custombatch(custombatchResource); console.log(response); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_shopping_product_batch_insert] @@ -160,30 +162,31 @@ function updateAccountTax() { accountId: accountId, rules: [ { - 'useGlobalRate': true, - 'locationId': 21135, - 'shippingTaxed': true, - 'country': 'US' + useGlobalRate: true, + locationId: 21135, + shippingTaxed: true, + country: "US", }, { - 'ratePercent': 3, - 'locationId': 21136, - 'country': 'US' + ratePercent: 3, + locationId: 21136, + country: "US", }, { - 'ratePercent': 2, - 'locationId': 21160, - 'shippingTaxed': true, - 'country': 'US' - } - ] + ratePercent: 2, + locationId: 21160, + shippingTaxed: true, + country: "US", + }, + ], }; - console.log(ShoppingContent.Accounttax - .update(taxInfo, merchantId, accountId)); + console.log( + ShoppingContent.Accounttax.update(taxInfo, merchantId, accountId), + ); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_shopping_account_info] diff --git a/advanced/slides.gs b/advanced/slides.gs index d8532df0b..1a14b0e8a 100644 --- a/advanced/slides.gs +++ b/advanced/slides.gs @@ -22,13 +22,14 @@ */ function createPresentation() { try { - const presentation = - Slides.Presentations.create({'title': 'MyNewPresentation'}); - console.log('Created presentation with ID: ' + presentation.presentationId); + const presentation = Slides.Presentations.create({ + title: "MyNewPresentation", + }); + console.log(`Created presentation with ID: ${presentation.presentationId}`); return presentation.presentationId; } catch (e) { // TODO (developer) - Handle exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_create_presentation] @@ -44,23 +45,29 @@ function createSlide(presentationId) { // You can specify the ID to use for the slide, as long as it's unique. const pageId = Utilities.getUuid(); - const requests = [{ - 'createSlide': { - 'objectId': pageId, - 'insertionIndex': 1, - 'slideLayoutReference': { - 'predefinedLayout': 'TITLE_AND_TWO_COLUMNS' - } - } - }]; + const requests = [ + { + createSlide: { + objectId: pageId, + insertionIndex: 1, + slideLayoutReference: { + predefinedLayout: "TITLE_AND_TWO_COLUMNS", + }, + }, + }, + ]; try { - const slide = - Slides.Presentations.batchUpdate({'requests': requests}, presentationId); - console.log('Created Slide with ID: ' + slide.replies[0].createSlide.objectId); + const slide = Slides.Presentations.batchUpdate( + { requests: requests }, + presentationId, + ); + console.log( + `Created Slide with ID: ${slide.replies[0].createSlide.objectId}`, + ); return slide; } catch (e) { // TODO (developer) - Handle Exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_create_slide] @@ -77,13 +84,14 @@ function readPageElementIds(presentationId, pageId) { // You can use a field mask to limit the data the API retrieves // in a get request, or what fields are updated in an batchUpdate. try { - const response = Slides.Presentations.Pages.get( - presentationId, pageId, {'fields': 'pageElements.objectId'}); + const response = Slides.Presentations.Pages.get(presentationId, pageId, { + fields: "pageElements.objectId", + }); console.log(response); return response; } catch (e) { // TODO (developer) - Handle Exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_read_page] @@ -101,47 +109,53 @@ function addTextBox(presentationId, pageId) { // as long as the ID is unique. const pageElementId = Utilities.getUuid(); - const requests = [{ - 'createShape': { - 'objectId': pageElementId, - 'shapeType': 'TEXT_BOX', - 'elementProperties': { - 'pageObjectId': pageId, - 'size': { - 'width': { - 'magnitude': 150, - 'unit': 'PT' + const requests = [ + { + createShape: { + objectId: pageElementId, + shapeType: "TEXT_BOX", + elementProperties: { + pageObjectId: pageId, + size: { + width: { + magnitude: 150, + unit: "PT", + }, + height: { + magnitude: 50, + unit: "PT", + }, + }, + transform: { + scaleX: 1, + scaleY: 1, + translateX: 200, + translateY: 100, + unit: "PT", }, - 'height': { - 'magnitude': 50, - 'unit': 'PT' - } }, - 'transform': { - 'scaleX': 1, - 'scaleY': 1, - 'translateX': 200, - 'translateY': 100, - 'unit': 'PT' - } - } - } - }, { - 'insertText': { - 'objectId': pageElementId, - 'text': 'My Added Text Box', - 'insertionIndex': 0 - } - }]; + }, + }, + { + insertText: { + objectId: pageElementId, + text: "My Added Text Box", + insertionIndex: 0, + }, + }, + ]; try { - const response = - Slides.Presentations.batchUpdate({'requests': requests}, presentationId); - console.log('Created Textbox with ID: ' + - response.replies[0].createShape.objectId); + const response = Slides.Presentations.batchUpdate( + { requests: requests }, + presentationId, + ); + console.log( + `Created Textbox with ID: ${response.replies[0].createShape.objectId}`, + ); return response; } catch (e) { // TODO (developer) - Handle Exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_add_text_box] @@ -155,37 +169,41 @@ function addTextBox(presentationId, pageId) { * @see https://developers.google.com/slides/api/reference/rest/v1/presentations/batchUpdate */ function formatShapeText(presentationId, shapeId) { - const requests = [{ - 'updateTextStyle': { - 'objectId': shapeId, - 'fields': 'foregroundColor,bold,italic,fontFamily,fontSize,underline', - 'style': { - 'foregroundColor': { - 'opaqueColor': { - 'themeColor': 'ACCENT5' - } + const requests = [ + { + updateTextStyle: { + objectId: shapeId, + fields: "foregroundColor,bold,italic,fontFamily,fontSize,underline", + style: { + foregroundColor: { + opaqueColor: { + themeColor: "ACCENT5", + }, + }, + bold: true, + italic: true, + underline: true, + fontFamily: "Corsiva", + fontSize: { + magnitude: 18, + unit: "PT", + }, + }, + textRange: { + type: "ALL", }, - 'bold': true, - 'italic': true, - 'underline': true, - 'fontFamily': 'Corsiva', - 'fontSize': { - 'magnitude': 18, - 'unit': 'PT' - } }, - 'textRange': { - 'type': 'ALL' - } - } - }]; + }, + ]; try { - const response = - Slides.Presentations.batchUpdate({'requests': requests}, presentationId); + const response = Slides.Presentations.batchUpdate( + { requests: requests }, + presentationId, + ); return response.replies; } catch (e) { // TODO (developer) - Handle Exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_format_shape_text] @@ -203,7 +221,9 @@ function saveThumbnailImage(i) { const presentation = SlidesApp.getActivePresentation(); // Get the thumbnail of specified page const thumbnail = Slides.Presentations.Pages.getThumbnail( - presentation.getId(), presentation.getSlides()[i].getObjectId()); + presentation.getId(), + presentation.getSlides()[i].getObjectId(), + ); // fetch the URL to the thumbnail image. const response = UrlFetchApp.fetch(thumbnail.contentUrl); const image = response.getBlob(); @@ -212,7 +232,7 @@ function saveThumbnailImage(i) { console.log(file.getUrl()); } catch (e) { // TODO (developer) - Handle Exception - console.log('Failed with error %s', e.message); + console.log("Failed with error %s", e.message); } } // [END apps_script_slides_save_thumbnail] diff --git a/advanced/tagManager.gs b/advanced/tagManager.gs index 3d15f8d8e..6d595e47c 100644 --- a/advanced/tagManager.gs +++ b/advanced/tagManager.gs @@ -26,66 +26,63 @@ function createContainerVersion(accountPath) { // sure the container is unique. try { const container = TagManager.Accounts.Containers.create( - { - 'name': 'appscript tagmanager container ' + date.getTime(), - 'usageContext': ['WEB'] - }, - accountPath); + { + name: `appscript tagmanager container ${date.getTime()}`, + usageContext: ["WEB"], + }, + accountPath, + ); const containerPath = container.path; // Creates a workspace in the container to track entity changes. const workspace = TagManager.Accounts.Containers.Workspaces.create( - {'name': 'appscript workspace', 'description': 'appscript workspace'}, - containerPath); + { name: "appscript workspace", description: "appscript workspace" }, + containerPath, + ); const workspacePath = workspace.path; // Creates a random value variable. const variable = TagManager.Accounts.Containers.Workspaces.Variables.create( - {'name': 'apps script variable', 'type': 'r'}, - workspacePath); + { name: "apps script variable", type: "r" }, + workspacePath, + ); // Creates a trigger that fires on any page view. const trigger = TagManager.Accounts.Containers.Workspaces.Triggers.create( - {'name': 'apps script trigger', 'type': 'PAGEVIEW'}, - workspacePath); + { name: "apps script trigger", type: "PAGEVIEW" }, + workspacePath, + ); // Creates a arbitary pixel that fires the tag on all page views. const tag = TagManager.Accounts.Containers.Workspaces.Tags.create( - { - 'name': 'apps script tag', - 'type': 'img', - 'liveOnly': false, - 'parameter': [ - {'type': 'boolean', 'key': 'useCacheBuster', 'value': 'true'}, { - 'type': 'template', - 'key': 'cacheBusterQueryParam', - 'value': 'gtmcb' - }, - {'type': 'template', 'key': 'url', 'value': '//example.com'} - ], - 'firingTriggerId': [trigger.triggerId] - }, - workspacePath); + { + name: "apps script tag", + type: "img", + liveOnly: false, + parameter: [ + { type: "boolean", key: "useCacheBuster", value: "true" }, + { + type: "template", + key: "cacheBusterQueryParam", + value: "gtmcb", + }, + { type: "template", key: "url", value: "//example.com" }, + ], + firingTriggerId: [trigger.triggerId], + }, + workspacePath, + ); // Creates a container version with the variabe, trigger, and tag. - const version = TagManager.Accounts.Containers.Workspaces - .create_version( - {'name': 'apps script version'}, workspacePath) - .containerVersion; + const version = TagManager.Accounts.Containers.Workspaces.create_version( + { name: "apps script version" }, + workspacePath, + ).containerVersion; console.log(version); return version; } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_tag_manager_create_version] // [START apps_script_tag_manager_publish_version] -/** - * Retrieves the container path from a container version path. - * @param {string} versionPath The version path. - * @return {string} The container path. - */ -function grabContainerPath(versionPath) { - const pathParts = versionPath.split('/'); - return pathParts.slice(0, 4).join('/'); -} /** * Publishes a container version publically to the world and creates a quick @@ -94,35 +91,27 @@ function grabContainerPath(versionPath) { */ function publishVersionAndQuickPreviewDraft(version) { try { - const containerPath = grabContainerPath(version.path); + const pathParts = version.path.split("/"); + const containerPath = pathParts.slice(0, 4).join("/"); // Publish the input container version. TagManager.Accounts.Containers.Versions.publish(version.path); const workspace = TagManager.Accounts.Containers.Workspaces.create( - {'name': 'appscript workspace', 'description': 'appscript workspace'}, - containerPath); + { name: "appscript workspace", description: "appscript workspace" }, + containerPath, + ); const workspaceId = workspace.path; // Quick previews the current container draft. - const quickPreview = TagManager.Accounts.Containers.Workspaces - .quick_preview(workspace.path); + const quickPreview = + TagManager.Accounts.Containers.Workspaces.quick_preview(workspace.path); console.log(quickPreview); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_tag_manager_publish_version] // [START apps_script_tag_manager_create_user_environment] -/** - * Retrieves the container path from a container version path. - * @param {string} versionPath The version path. - * @return {string} The container path. - */ -function grabContainerPath(versionPath) { - const pathParts = versionPath.split('/'); - return pathParts.slice(0, 4).join('/'); -} - /** * Creates and reauthorizes a user environment in a container that points * to a container version passed in as an argument. @@ -131,23 +120,27 @@ function grabContainerPath(versionPath) { function createAndReauthorizeUserEnvironment(version) { try { // Creates a container version. - const containerPath = grabContainerPath(version.path); + const pathParts = version.path.split("/"); + const containerPath = pathParts.slice(0, 4).join("/"); // Creates a user environment that points to a container version. const environment = TagManager.Accounts.Containers.Environments.create( - { - 'name': 'test_environment', - 'type': 'user', - 'containerVersionId': version.containerVersionId - }, - containerPath); - console.log('Original user environment: ' + environment); + { + name: "test_environment", + type: "user", + containerVersionId: version.containerVersionId, + }, + containerPath, + ); + console.log(`Original user environment: ${environment}`); // Reauthorizes the user environment that points to a container version. TagManager.Accounts.Containers.Environments.reauthorize( - {}, environment.path); - console.log('Reauthorized user environment: ' + environment); + {}, + environment.path, + ); + console.log(`Reauthorized user environment: ${environment}`); } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_tag_manager_create_user_environment] @@ -163,20 +156,19 @@ function logAllAccountUserPermissionsWithContainerAccess(accountPath) { TagManager.Accounts.User_permissions.list(accountPath).userPermission; for (let i = 0; i < userPermissions.length; i++) { const userPermission = userPermissions[i]; - if ('emailAddress' in userPermission) { + if ("emailAddress" in userPermission) { const containerAccesses = userPermission.containerAccess; for (let j = 0; j < containerAccesses.length; j++) { const containerAccess = containerAccesses[j]; console.log( - 'emailAddress:' + userPermission.emailAddress + - ' containerId:' + containerAccess.containerId + - ' containerAccess:' + containerAccess.permission); + `emailAddress:${userPermission.emailAddress} containerId:${containerAccess.containerId} containerAccess:${containerAccess.permission}`, + ); } } } } catch (e) { // TODO (Developer) - Handle exceptions - console.log('Failed with error: $s', e.error); + console.log("Failed with error: $s", e.error); } } // [END apps_script_tag_manager_log] diff --git a/advanced/tasks.gs b/advanced/tasks.gs index af1e3bd9c..f73603986 100644 --- a/advanced/tasks.gs +++ b/advanced/tasks.gs @@ -24,17 +24,21 @@ function listTaskLists() { const taskLists = Tasks.Tasklists.list(); // If taskLists are available then print all tasklists. if (!taskLists.items) { - console.log('No task lists found.'); + console.log("No task lists found."); return; } // Print the tasklist title and tasklist id. for (let i = 0; i < taskLists.items.length; i++) { const taskList = taskLists.items[i]; - console.log('Task list with title "%s" and ID "%s" was found.', taskList.title, taskList.id); + console.log( + 'Task list with title "%s" and ID "%s" was found.', + taskList.title, + taskList.id, + ); } } catch (err) { // TODO (developer) - Handle exception from Task API - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } } // [END tasks_lists_task_lists] @@ -51,17 +55,21 @@ function listTasks(taskListId) { const tasks = Tasks.Tasks.list(taskListId); // If tasks are available then print all task of given tasklists. if (!tasks.items) { - console.log('No tasks found.'); + console.log("No tasks found."); return; } // Print the task title and task id of specified tasklist. for (let i = 0; i < tasks.items.length; i++) { const task = tasks.items[i]; - console.log('Task with title "%s" and ID "%s" was found.', task.title, task.id); + console.log( + 'Task with title "%s" and ID "%s" was found.', + task.title, + task.id, + ); } } catch (err) { // TODO (developer) - Handle exception from Task API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END tasks_list_tasks] @@ -75,8 +83,8 @@ function listTasks(taskListId) { function addTask(taskListId) { // Task details with title and notes for inserting new task let task = { - title: 'Pick up dry cleaning', - notes: 'Remember to get this done!' + title: "Pick up dry cleaning", + notes: "Remember to get this done!", }; try { // Call insert method with taskDetails and taskListId to insert Task to specified tasklist. @@ -85,7 +93,7 @@ function addTask(taskListId) { console.log('Task with ID "%s" was created.', task.id); } catch (err) { // TODO (developer) - Handle exception from Tasks.insert() of Task API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END tasks_add_task] diff --git a/advanced/test_adminSDK.gs b/advanced/test_adminSDK.gs index fb825fe04..dfa840f05 100644 --- a/advanced/test_adminSDK.gs +++ b/advanced/test_adminSDK.gs @@ -18,7 +18,7 @@ * Tests listAllUsers function of adminSDK.gs */ function itShouldListAllUsers() { - console.log('> itShouldListAllUsers'); + console.log("> itShouldListAllUsers"); listAllUsers(); } @@ -26,7 +26,7 @@ function itShouldListAllUsers() { * Tests getUser function of adminSDK.gs */ function itShouldGetUser() { - console.log('> itShouldGetUser'); + console.log("> itShouldGetUser"); getUser(); } @@ -34,7 +34,7 @@ function itShouldGetUser() { * Tests addUser function of adminSDK.gs */ function itShouldAddUser() { - console.log('> itShouldAddUser'); + console.log("> itShouldAddUser"); addUser(); } @@ -42,7 +42,7 @@ function itShouldAddUser() { * Tests createAlias function of adminSDK.gs */ function itShouldCreateAlias() { - console.log('> itShouldCreateAlias'); + console.log("> itShouldCreateAlias"); createAlias(); } @@ -50,7 +50,7 @@ function itShouldCreateAlias() { * Tests listAllGroups function of adminSDK.gs */ function itShouldListAllGroups() { - console.log('> itShouldListAllGroups'); + console.log("> itShouldListAllGroups"); listAllGroups(); } @@ -58,7 +58,7 @@ function itShouldListAllGroups() { * Tests addGroupMember function of adminSDK.gs */ function itShouldAddGroupMember() { - console.log('> itShouldAddGroupMember'); + console.log("> itShouldAddGroupMember"); addGroupMember(); } @@ -66,7 +66,7 @@ function itShouldAddGroupMember() { * Tests migrateMessages function of adminSDK.gs */ function itShouldMigrateMessages() { - console.log('> itShouldMigrateMessages'); + console.log("> itShouldMigrateMessages"); migrateMessages(); } @@ -74,7 +74,7 @@ function itShouldMigrateMessages() { * Tests getGroupSettings function of adminSDK.gs */ function itShouldGetGroupSettings() { - console.log('> itShouldGetGroupSettings'); + console.log("> itShouldGetGroupSettings"); getGroupSettings(); } @@ -82,7 +82,7 @@ function itShouldGetGroupSettings() { * Tests updateGroupSettings function of adminSDK.gs */ function itShouldUpdateGroupSettings() { - console.log('> itShouldUpdateGroupSettings'); + console.log("> itShouldUpdateGroupSettings"); updateGroupSettings(); } @@ -90,7 +90,7 @@ function itShouldUpdateGroupSettings() { * Tests getLicenseAssignments function of adminSDK.gs */ function itShouldGetLicenseAssignments() { - console.log('> itShouldGetLicenseAssignments'); + console.log("> itShouldGetLicenseAssignments"); getLicenseAssignments(); } @@ -98,7 +98,7 @@ function itShouldGetLicenseAssignments() { * Tests insertLicenseAssignment function of adminSDK.gs */ function itShouldInsertLicenseAssignment() { - console.log('> itShouldInsertLicenseAssignment'); + console.log("> itShouldInsertLicenseAssignment"); insertLicenseAssignment(); } @@ -106,7 +106,7 @@ function itShouldInsertLicenseAssignment() { * Tests generateLoginActivityReport function of adminSDK.gs */ function itShouldGenerateLoginActivityReport() { - console.log('> itShouldGenerateLoginActivityReport'); + console.log("> itShouldGenerateLoginActivityReport"); generateLoginActivityReport(); } @@ -114,7 +114,7 @@ function itShouldGenerateLoginActivityReport() { * Tests generateUserUsageReport function of adminSDK.gs */ function itShouldGenerateUserUsageReport() { - console.log('> itShouldGenerateUserUsageReport'); + console.log("> itShouldGenerateUserUsageReport"); generateUserUsageReport(); } @@ -122,7 +122,7 @@ function itShouldGenerateUserUsageReport() { * Tests getSubscriptions function of adminSDK.gs */ function itShouldGetSubscriptions() { - console.log('> itShouldGetSubscriptions'); + console.log("> itShouldGetSubscriptions"); getSubscriptions(); } diff --git a/advanced/test_adsense.gs b/advanced/test_adsense.gs index 1b7ef1e24..366eb76cf 100644 --- a/advanced/test_adsense.gs +++ b/advanced/test_adsense.gs @@ -15,14 +15,14 @@ */ // Replace with correct values -const accountName = 'account name'; -const clientName = 'ad client name'; +const accountName = "account name"; +const clientName = "ad client name"; /** * Tests listAccounts function of adsense.gs */ function itShouldListAccounts() { - console.log('> itShouldListAccounts'); + console.log("> itShouldListAccounts"); listAccounts(); } @@ -30,7 +30,7 @@ function itShouldListAccounts() { * Tests listAdClients function of adsense.gs */ function itShouldListAdClients() { - console.log('> itShouldListAdClients'); + console.log("> itShouldListAdClients"); listAdClients(accountName); } @@ -38,7 +38,7 @@ function itShouldListAdClients() { * Tests listAdUnits function of adsense.gs */ function itShouldListAdUnits() { - console.log('> itShouldListAdUnits'); + console.log("> itShouldListAdUnits"); listAdUnits(clientName); } diff --git a/advanced/test_analytics.gs b/advanced/test_analytics.gs index 505974c2b..fce53a9d1 100644 --- a/advanced/test_analytics.gs +++ b/advanced/test_analytics.gs @@ -15,13 +15,13 @@ */ // Replace with the required profileId -const profileId = 'abcd'; +const profileId = "abcd"; /** * Tests listAccounts function of analytics.gs */ function itShouldListAccounts() { - console.log('> itShouldListAccounts'); + console.log("> itShouldListAccounts"); listAccounts(); } @@ -29,7 +29,7 @@ function itShouldListAccounts() { * Tests runReport function of analytics.gs */ function itShouldRunReport() { - console.log('> itShouldRunReport'); + console.log("> itShouldRunReport"); runReport(profileId); } diff --git a/advanced/test_bigquery.gs b/advanced/test_bigquery.gs index d79373b2f..79c4633ce 100644 --- a/advanced/test_bigquery.gs +++ b/advanced/test_bigquery.gs @@ -18,7 +18,7 @@ * Tests runQuery function of adminSDK.gs */ function itShouldRunQuery() { - console.log('> itShouldRunQuery'); + console.log("> itShouldRunQuery"); runQuery(); } @@ -26,7 +26,7 @@ function itShouldRunQuery() { * Tests loadCsv function of adminSDK.gs */ function itShouldLoadCsv() { - console.log('> itShouldLoadCsv'); + console.log("> itShouldLoadCsv"); loadCsv(); } diff --git a/advanced/test_calendar.gs b/advanced/test_calendar.gs index ceec9a2a4..0e41d35d0 100644 --- a/advanced/test_calendar.gs +++ b/advanced/test_calendar.gs @@ -18,7 +18,7 @@ * Tests listCalendars function of calendar.gs */ function itShouldListCalendars() { - console.log('> itShouldListCalendars'); + console.log("> itShouldListCalendars"); listCalendars(); } @@ -26,7 +26,7 @@ function itShouldListCalendars() { * Tests createEvent function of calendars.gs */ function itShouldCreateEvent() { - console.log('> itShouldCreateEvent'); + console.log("> itShouldCreateEvent"); createEvent(); } @@ -34,18 +34,18 @@ function itShouldCreateEvent() { * Tests gerRelativeDate function of calendar.gs */ function itShouldGetRelativeDate() { - console.log('> itShouldGetRelativeDate'); - console.log('no offset: ' + getRelativeDate(0, 0)); - console.log('4 hour offset: ' + getRelativeDate(0, 4)); - console.log('1 day offset: ' + getRelativeDate(1, 0)); - console.log('1 day and 3 hour off set: ' + getRelativeDate(1, 3)); + console.log("> itShouldGetRelativeDate"); + console.log(`no offset: ${getRelativeDate(0, 0)}`); + console.log(`4 hour offset: ${getRelativeDate(0, 4)}`); + console.log(`1 day offset: ${getRelativeDate(1, 0)}`); + console.log(`1 day and 3 hour off set: ${getRelativeDate(1, 3)}`); } /** * Tests listNext10Events function of calendar.gs */ function itShouldListNext10Events() { - console.log('> itShouldListNext10Events'); + console.log("> itShouldListNext10Events"); listNext10Events(); } @@ -53,16 +53,16 @@ function itShouldListNext10Events() { * Tests logSyncedEvents function of calendar.gs */ function itShouldLogSyncedEvents() { - console.log('> itShouldLogSyncedEvents'); - logSyncedEvents('primary', true); - logSyncedEvents('primary', false); + console.log("> itShouldLogSyncedEvents"); + logSyncedEvents("primary", true); + logSyncedEvents("primary", false); } /** * Tests conditionalUpdate function of calendar.gs */ function itShouldConditionalUpdate() { - console.log('> itShouldConditionalUpdate (takes 30 seconds)'); + console.log("> itShouldConditionalUpdate (takes 30 seconds)"); conditionalUpdate(); } @@ -70,7 +70,7 @@ function itShouldConditionalUpdate() { * Tests conditionalFetch function of calendar.gs */ function itShouldConditionalFetch() { - console.log('> itShouldConditionalFetch'); + console.log("> itShouldConditionalFetch"); conditionalFetch(); } diff --git a/advanced/test_classroom.gs b/advanced/test_classroom.gs index bbe2d7625..723b1b5f9 100644 --- a/advanced/test_classroom.gs +++ b/advanced/test_classroom.gs @@ -18,7 +18,7 @@ * Tests listCourses function of classroom.gs */ function itShouldListCourses() { - console.log('> itShouldListCourses'); + console.log("> itShouldListCourses"); listCourses(); } diff --git a/advanced/test_displayvideo.gs b/advanced/test_displayvideo.gs index b7a454cab..c114ededf 100644 --- a/advanced/test_displayvideo.gs +++ b/advanced/test_displayvideo.gs @@ -18,7 +18,7 @@ * Tests listPartners function of displayvideo.gs */ function itShouldListPartners() { - console.log('> itShouldListPartners'); + console.log("> itShouldListPartners"); listPartners(); } @@ -26,7 +26,7 @@ function itShouldListPartners() { * Tests listActiveCampaigns function of displayvideo.gs */ function itShouldListActiveCampaigns() { - console.log('> itShouldListActiveCampaigns'); + console.log("> itShouldListActiveCampaigns"); listActiveCampaigns(); } @@ -34,7 +34,7 @@ function itShouldListActiveCampaigns() { * Tests updateLineItemName function of displayvideo.gs */ function itShouldUpdateLineItemName() { - console.log('> itShouldUpdateLineItemName'); + console.log("> itShouldUpdateLineItemName"); updateLineItemName(); } diff --git a/advanced/test_docs.gs b/advanced/test_docs.gs index 97bbd35ce..b13242c02 100644 --- a/advanced/test_docs.gs +++ b/advanced/test_docs.gs @@ -14,17 +14,17 @@ * limitations under the License. */ // TODO (developer) - Replace with your documentId -const documentId='1EaLpBfuo3bMUeP6_P34auuQroh3bCWi6hLDppY6J6us'; +const documentId = "1EaLpBfuo3bMUeP6_P34auuQroh3bCWi6hLDppY6J6us"; /** * A simple exists assertion check. Expects a value to exist. Errors if DNE. * @param {any} value A value that is expected to exist. */ function expectToExist(value) { if (!value) { - console.log('DNE'); + console.log("DNE"); return; } - console.log('TEST: Exists'); + console.log("TEST: Exists"); } /** @@ -35,13 +35,12 @@ function expectToExist(value) { */ function expectToEqual(expected, actual) { if (actual !== expected) { - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); return; } - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); } - /** * Runs all tests. */ @@ -61,15 +60,14 @@ function itShouldCreateDocument() { deleteFileOnCleanup(documentId); } - /** * Insert text with style. */ function itShouldInsertTextWithStyle() { const documentId = createDocument(); expectToExist(documentId); - const text='This is the sample document'; - const replies=insertAndStyleText(documentId, text); + const text = "This is the sample document"; + const replies = insertAndStyleText(documentId, text); expectToEqual(2, replies.length); deleteFileOnCleanup(documentId); } @@ -80,11 +78,11 @@ function itShouldInsertTextWithStyle() { function itShouldReplaceText() { const documentId = createDocument(); expectToExist(documentId); - const text='This is the sample document'; - const response=insertAndStyleText(documentId, text); + const text = "This is the sample document"; + const response = insertAndStyleText(documentId, text); expectToEqual(2, response.replies.length); - const findTextToReplacementMap={'sample': 'test', 'document': 'Doc'}; - const replies=findAndReplace(documentId, findTextToReplacementMap); + const findTextToReplacementMap = { sample: "test", document: "Doc" }; + const replies = findAndReplace(documentId, findTextToReplacementMap); expectToEqual(2, replies.length); deleteFileOnCleanup(documentId); } @@ -93,7 +91,7 @@ function itShouldReplaceText() { * Read first paragraph */ function itShouldReadFirstParagraph() { - const paragraphText=readFirstParagraph(documentId); + const paragraphText = readFirstParagraph(documentId); expectToExist(paragraphText); expectToEqual(89, paragraphText.length); } diff --git a/advanced/test_doubleclick.gs b/advanced/test_doubleclick.gs index c0efee4b8..3f9f4e98d 100644 --- a/advanced/test_doubleclick.gs +++ b/advanced/test_doubleclick.gs @@ -18,7 +18,7 @@ * Tests listUserProfiles function of doubleclick.gs */ function itShouldListUserProfiles() { - console.log('> itShouldListUserProfiles'); + console.log("> itShouldListUserProfiles"); listUserProfiles(); } @@ -26,7 +26,7 @@ function itShouldListUserProfiles() { * Tests listActiveCampaigns function of doubleclick.gs */ function itShouldListActiveCampaigns() { - console.log('> itShouldListActiveCampaigns'); + console.log("> itShouldListActiveCampaigns"); listActiveCampaigns(); } @@ -34,7 +34,7 @@ function itShouldListActiveCampaigns() { * Tests createAdvertiserAndCampaign function of doubleclick.gs */ function itShouldCreateAdvertiserAndCampaign() { - console.log('> itShouldCreateAdvertiserAndCampaign'); + console.log("> itShouldCreateAdvertiserAndCampaign"); createAdvertiserAndCampaign(); } diff --git a/advanced/test_doubleclickbidmanager.gs b/advanced/test_doubleclickbidmanager.gs index fd2bc596f..4961c4cbc 100644 --- a/advanced/test_doubleclickbidmanager.gs +++ b/advanced/test_doubleclickbidmanager.gs @@ -18,7 +18,7 @@ * Tests listQueries function of doubleclickbidmanager.gs */ function itShouldListQueries() { - console.log('> itShouldListQueries'); + console.log("> itShouldListQueries"); listQueries(); } @@ -26,7 +26,7 @@ function itShouldListQueries() { * Tests createAndRunQuery function of doubleclickbidmanager.gs */ function itShouldCreateAndRunQuery() { - console.log('> itShouldCreateAndRunQuery'); + console.log("> itShouldCreateAndRunQuery"); createAndRunQuery(); } @@ -34,7 +34,7 @@ function itShouldCreateAndRunQuery() { * Tests fetchReport function of doubleclickbidmanager.gs */ function itShouldFetchReport() { - console.log('> itShouldFetchReport'); + console.log("> itShouldFetchReport"); fetchReport(); } diff --git a/advanced/test_drive.gs b/advanced/test_drive.gs index f3ebd5eeb..5e48fee30 100644 --- a/advanced/test_drive.gs +++ b/advanced/test_drive.gs @@ -21,9 +21,9 @@ */ function expectToExist(value) { if (value) { - console.log('TEST: Exists'); + console.log("TEST: Exists"); } else { - throw new Error('TEST: DNE'); + throw new Error("TEST: DNE"); } } @@ -34,9 +34,9 @@ function expectToExist(value) { * To test drive.gs please add drive services */ function expectToEqual(actual, expected) { - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); if (actual !== expected) { - console.log('TEST: actual: %s expected: %s', actual, expected); + console.log("TEST: actual: %s expected: %s", actual, expected); } } @@ -46,8 +46,8 @@ function expectToEqual(actual, expected) { * To test drive.gs please add drive services */ function createTestFolder() { - DriveApp.createFolder('test1'); - DriveApp.createFolder('test2'); + DriveApp.createFolder("test1"); + DriveApp.createFolder("test2"); } /** @@ -56,7 +56,7 @@ function createTestFolder() { * To test drive.gs please add drive services */ function fileCleanUp() { - DriveApp.getFilesByName('google_logo.png').next().setTrashed(true); + DriveApp.getFilesByName("google_logo.png").next().setTrashed(true); } /** @@ -65,8 +65,8 @@ function fileCleanUp() { * To test getFoldersByName() please add drive services */ function folderCleanUp() { - DriveApp.getFoldersByName('test1').next().setTrashed(true); - DriveApp.getFoldersByName('test2').next().setTrashed(true); + DriveApp.getFoldersByName("test1").next().setTrashed(true); + DriveApp.getFoldersByName("test2").next().setTrashed(true); } /** @@ -79,7 +79,7 @@ function folderCleanUp() { */ function checkUploadFile() { uploadFile(); - const fileId = DriveApp.getFilesByName('google_logo.png').next().getId(); + const fileId = DriveApp.getFilesByName("google_logo.png").next().getId(); expectToExist(fileId); return fileId; } @@ -93,7 +93,7 @@ function checkListRootFolders() { const folders = DriveApp.getFolders(); while (folders.hasNext()) { const folder = folders.next(); - console.log(folder.getName() + ' ' + folder.getId()); + console.log(`${folder.getName()} ${folder.getId()}`); } listRootFolders(); folderCleanUp(); @@ -105,8 +105,10 @@ function checkListRootFolders() { */ function checkAddCustomProperty(fileId) { addCustomProperty(fileId); - expectToEqual(Drive.Properties.get(fileId, 'department', - {visibility: 'PUBLIC'}).value, 'Sales'); + expectToEqual( + Drive.Properties.get(fileId, "department", { visibility: "PUBLIC" }).value, + "Sales", + ); } /** diff --git a/advanced/test_gmail.gs b/advanced/test_gmail.gs index 494871f66..04c2da6ea 100644 --- a/advanced/test_gmail.gs +++ b/advanced/test_gmail.gs @@ -19,12 +19,12 @@ * Add gmail services to run */ function RUN_ALL_TESTS() { - console.log('> ltShouldListLabelInfo'); + console.log("> ltShouldListLabelInfo"); listLabelInfo(); - console.log('> ltShouldListInboxSnippets'); + console.log("> ltShouldListInboxSnippets"); listInboxSnippets(); - console.log('> ltShouldLogRecentHistory'); + console.log("> ltShouldLogRecentHistory"); logRecentHistory(); - console.log('> ltShouldGetRawMessage'); + console.log("> ltShouldGetRawMessage"); getRawMessage(); } diff --git a/advanced/test_people.gs b/advanced/test_people.gs index 07e1e09e0..6cf360cea 100644 --- a/advanced/test_people.gs +++ b/advanced/test_people.gs @@ -20,10 +20,10 @@ * to tests people.gs add people api services */ function RUN_ALL_TESTS() { - console.log('> itShouldGetConnections'); + console.log("> itShouldGetConnections"); getConnections(); - console.log('> itShouldGetSelf'); // Requires the scope userinfo.profile + console.log("> itShouldGetSelf"); // Requires the scope userinfo.profile getSelf(); - console.log('> itShouldGetAccount'); - getAccount('me'); + console.log("> itShouldGetAccount"); + getAccount("me"); } diff --git a/advanced/test_sheets.gs b/advanced/test_sheets.gs index 345214c06..e8bbfdb4a 100644 --- a/advanced/test_sheets.gs +++ b/advanced/test_sheets.gs @@ -22,7 +22,7 @@ * @return {string} spreadsheet */ function createTestSpreadsheet() { - const spreadsheet = SpreadsheetApp.create('Test Spreadsheet'); + const spreadsheet = SpreadsheetApp.create("Test Spreadsheet"); for (let i = 0; i < 3; ++i) { spreadsheet.appendRow([1, 2, 3]); } @@ -41,10 +41,10 @@ function populateValues(spreadsheetId) { for (let i = 0; i < 10; ++i) { values[i] = []; for (let j = 0; j < 10; ++j) { - values[i].push('Hello'); + values[i].push("Hello"); } } - const range = 'A1:J10'; + const range = "A1:J10"; SpreadsheetApp.openById(spreadsheetId).getRange(range).setValues(values); SpreadsheetApp.flush(); } @@ -55,7 +55,7 @@ function populateValues(spreadsheetId) { * @return {string} spreadsheet ID */ function itShouldReadRange() { - console.log('> itShouldReadRange'); + console.log("> itShouldReadRange"); spreadsheetId = createTestSpreadsheet(); populateValues(spreadsheetId); readRange(spreadsheetId); @@ -67,13 +67,13 @@ function itShouldReadRange() { * @param {string} spreadsheetId */ function itShouldAddPivotTable(spreadsheetId) { - console.log('> itShouldAddPivotTable'); + console.log("> itShouldAddPivotTable"); const spreadsheet = SpreadsheetApp.openById(spreadsheetId); const sheets = spreadsheet.getSheets(); sheetId = sheets[0].getSheetId(); addPivotTable(spreadsheetId, sheetId, sheetId); SpreadsheetApp.flush(); - console.log('Created pivot table'); + console.log("Created pivot table"); } /** @@ -81,9 +81,9 @@ function itShouldAddPivotTable(spreadsheetId) { */ function RUN_ALL_TEST() { const spreadsheetId = itShouldReadRange(); - console.log('> itShouldWriteToMultipleRanges'); + console.log("> itShouldWriteToMultipleRanges"); writeToMultipleRanges(spreadsheetId); - console.log('> itShouldAddSheet'); + console.log("> itShouldAddSheet"); addSheet(spreadsheetId); itShouldAddPivotTable(spreadsheetId); } diff --git a/advanced/test_shoppingContent.gs b/advanced/test_shoppingContent.gs index 14cc296c2..fd0f80057 100644 --- a/advanced/test_shoppingContent.gs +++ b/advanced/test_shoppingContent.gs @@ -23,7 +23,7 @@ const productResource3 = {}; * Tests productInsert function of shoppingContent.gs */ function itShouldProductInsert() { - console.log('> itShouldPproductInsert'); + console.log("> itShouldPproductInsert"); productInsert(); } @@ -31,7 +31,7 @@ function itShouldProductInsert() { * Tests productList function of shoppingContent.gs */ function itShouldProductList() { - console.log('> itShouldProductList'); + console.log("> itShouldProductList"); productList(); } @@ -39,7 +39,7 @@ function itShouldProductList() { * Tests custombatch function of shoppingContent.gs */ function itShouldCustombatch() { - console.log('> itShouldCustombatch'); + console.log("> itShouldCustombatch"); custombatch(productResource1, productResource2, productResource3); } @@ -47,7 +47,7 @@ function itShouldCustombatch() { * Tests updateAccountTax function of shoppingContent.gs */ function itShouldUpdateAccountTax() { - console.log('> itShouldUpdateAccountTax'); + console.log("> itShouldUpdateAccountTax"); updateAccountTax(); } diff --git a/advanced/test_slides.gs b/advanced/test_slides.gs index 156221503..fcc5bb5a5 100644 --- a/advanced/test_slides.gs +++ b/advanced/test_slides.gs @@ -20,10 +20,10 @@ */ function expectToExist(value) { if (!value) { - console.log('DNE'); + console.log("DNE"); return; } - console.log('TEST: Exists'); + console.log("TEST: Exists"); } /** @@ -33,10 +33,10 @@ function expectToExist(value) { */ function expectToEqual(expected, actual) { if (actual !== expected) { - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); return; } - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); } /** * Creates a presentation. @@ -46,52 +46,57 @@ function expectToEqual(expected, actual) { */ function addShape(presentationId, pageId) { // Create a new square textbox, using the supplied element ID. - const elementId = 'MyTextBox_01'; + const elementId = "MyTextBox_01"; const pt350 = { magnitude: 350, - unit: 'PT' + unit: "PT", }; - const requests = [{ - createShape: { - objectId: elementId, - shapeType: 'ELLIPSE', - elementProperties: { - pageObjectId: pageId, - size: { - height: pt350, - width: pt350 + const requests = [ + { + createShape: { + objectId: elementId, + shapeType: "ELLIPSE", + elementProperties: { + pageObjectId: pageId, + size: { + height: pt350, + width: pt350, + }, + transform: { + scaleX: 1, + scaleY: 1, + translateX: 350, + translateY: 100, + unit: "PT", + }, }, - transform: { - scaleX: 1, - scaleY: 1, - translateX: 350, - translateY: 100, - unit: 'PT' - } - } - } - }, + }, + }, - // Insert text into the box, using the supplied element ID. - { - insertText: { - objectId: elementId, - insertionIndex: 0, - text: 'Text Formatted!' - } - }]; + // Insert text into the box, using the supplied element ID. + { + insertText: { + objectId: elementId, + insertionIndex: 0, + text: "Text Formatted!", + }, + }, + ]; // Execute the request. - const createTextboxWithTextResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - const createShapeResponse = createTextboxWithTextResponse.replies[0].createShape; - console.log('Created textbox with ID: %s', createShapeResponse.objectId); + const createTextboxWithTextResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + const createShapeResponse = + createTextboxWithTextResponse.replies[0].createShape; + console.log("Created textbox with ID: %s", createShapeResponse.objectId); // [END slides_create_textbox_with_text] return createShapeResponse.objectId; } - /** * Runs all tests. */ @@ -112,14 +117,13 @@ function itShouldCreateAPresentation() { deleteFileOnCleanup(presentationId); } - /** * Creates a new slide. */ function itShouldCreateASlide() { - console.log('> itShouldCreateASlide'); + console.log("> itShouldCreateASlide"); const presentationId = createPresentation(); - const slideId=createSlide(presentationId); + const slideId = createSlide(presentationId); expectToExist(slideId); deleteFileOnCleanup(presentationId); } @@ -129,7 +133,7 @@ function itShouldCreateASlide() { */ function itShouldCreateATextboxWithText() { const presentationId = createPresentation(); - const slide=createSlide(presentationId); + const slide = createSlide(presentationId); const pageId = slide.replies[0].createSlide.objectId; const response = addTextBox(presentationId, pageId); expectToEqual(2, response.replies.length); @@ -143,7 +147,7 @@ function itShouldCreateATextboxWithText() { */ function itShouldReadPage() { const presentationId = createPresentation(); - const slide=createSlide(presentationId); + const slide = createSlide(presentationId); const pageId = slide.replies[0].createSlide.objectId; const response = readPageElementIds(presentationId, pageId); expectToEqual(3, response.pageElements.length); @@ -154,10 +158,10 @@ function itShouldReadPage() { */ function itShouldFormatShapes() { const presentationId = createPresentation(); - const slide=createSlide(presentationId); + const slide = createSlide(presentationId); const pageId = slide.replies[0].createSlide.objectId; - const shapeId=addShape(presentationId, pageId); - const replies=formatShapeText(presentationId, shapeId); + const shapeId = addShape(presentationId, pageId); + const replies = formatShapeText(presentationId, shapeId); expectToExist(replies); deleteFileOnCleanup(presentationId); } diff --git a/advanced/test_tagManager.gs b/advanced/test_tagManager.gs index 42053dd27..b79c1367b 100644 --- a/advanced/test_tagManager.gs +++ b/advanced/test_tagManager.gs @@ -15,7 +15,7 @@ */ // Before running tagManager tests create a test tagMAnager account // and replace the value below with its account path -const path = 'accounts/6007387289'; +const path = "accounts/6007387289"; /** * Tests createContainerVersion function of tagManager.gs @@ -23,7 +23,7 @@ const path = 'accounts/6007387289'; * @return {object} version The container version */ function itShouldCreateContainerVersion(accountPath) { - console.log('> itShouldCreateContainerVersion'); + console.log("> itShouldCreateContainerVersion"); const version = createContainerVersion(accountPath); return version; } @@ -33,7 +33,7 @@ function itShouldCreateContainerVersion(accountPath) { * @param {object} version tag managers container version */ function itShouldPublishVersionAndQuickPreviewDraft(version) { - console.log('> itShouldPublishVersionAndQuickPreviewDraft'); + console.log("> itShouldPublishVersionAndQuickPreviewDraft"); publishVersionAndQuickPreviewDraft(version); } @@ -42,7 +42,7 @@ function itShouldPublishVersionAndQuickPreviewDraft(version) { * @param {object} version tag managers container version */ function itShouldCreateAndReauthorizeUserEnvironment(version) { - console.log('> itShouldCreateAndReauthorizeUserEnvironment'); + console.log("> itShouldCreateAndReauthorizeUserEnvironment"); createAndReauthorizeUserEnvironment(version); } @@ -51,7 +51,7 @@ function itShouldCreateAndReauthorizeUserEnvironment(version) { * @param {string} accountPath Tag manager account's path */ function itShouldLogAllAccountUserPermissionsWithContainerAccess(accountPath) { - console.log('> itShouldLogAllAccountUserPermissionsWithContainerAccess'); + console.log("> itShouldLogAllAccountUserPermissionsWithContainerAccess"); logAllAccountUserPermissionsWithContainerAccess(accountPath); } /** diff --git a/advanced/test_tasks.gs b/advanced/test_tasks.gs index b38668fcd..536c17428 100644 --- a/advanced/test_tasks.gs +++ b/advanced/test_tasks.gs @@ -24,7 +24,7 @@ * tests listTaskLists of tasks.gs */ function itShouldListTaskLists() { - console.log('> itShouldListTaskLists'); + console.log("> itShouldListTaskLists"); listTaskLists(); } @@ -32,7 +32,7 @@ function itShouldListTaskLists() { * tests listTasks of tasks.gs */ function itShouldListTasks() { - console.log('> itShouldListTasks'); + console.log("> itShouldListTasks"); const taskId = Tasks.Tasklists.list().items[0].id; listTasks(taskId); } @@ -41,7 +41,7 @@ function itShouldListTasks() { * tests addTask of tasks.gs */ function itShouldAddTask() { - console.log('> itShouldAddTask'); + console.log("> itShouldAddTask"); const taskId = Tasks.Tasklists.list().items[0].id; addTask(taskId); } diff --git a/advanced/test_youtube.gs b/advanced/test_youtube.gs index 6afd7454d..72a9f1c1d 100644 --- a/advanced/test_youtube.gs +++ b/advanced/test_youtube.gs @@ -18,12 +18,12 @@ * Run all tests */ function RUN_ALL_TESTS() { - console.log('> itShouldSearchByKeyword'); + console.log("> itShouldSearchByKeyword"); searchByKeyword(); - console.log('> itShouldRetrieveMyUploads'); + console.log("> itShouldRetrieveMyUploads"); retrieveMyUploads(); - console.log('> itShouldAddSubscription'); + console.log("> itShouldAddSubscription"); addSubscription(); - console.log('> itShouldCreateSlides'); + console.log("> itShouldCreateSlides"); createSlides(); } diff --git a/advanced/test_youtubeAnalytics.gs b/advanced/test_youtubeAnalytics.gs index 5211bfb83..041a1478b 100644 --- a/advanced/test_youtubeAnalytics.gs +++ b/advanced/test_youtubeAnalytics.gs @@ -18,7 +18,7 @@ * Tests createReport function of youtubeAnalytics.gs */ function itShouldCreateReport() { - console.log('> itShouldCreateReport'); + console.log("> itShouldCreateReport"); createReport(); } diff --git a/advanced/test_youtubeContentId.gs b/advanced/test_youtubeContentId.gs index 350c88de7..ae64a9e2a 100644 --- a/advanced/test_youtubeContentId.gs +++ b/advanced/test_youtubeContentId.gs @@ -18,7 +18,7 @@ * Tests claimYourVideoWithMonetizePolicy function of youtubeContentId.gs */ function itShouldClaimVideoWithMonetizePolicy() { - console.log('> itShouldClaimVideoWithMonetizePolicy'); + console.log("> itShouldClaimVideoWithMonetizePolicy"); claimYourVideoWithMonetizePolicy(); } @@ -26,7 +26,7 @@ function itShouldClaimVideoWithMonetizePolicy() { * Tests updateAssetOwnership function of youtubeContentId.gs */ function itShouldUpdateAssetOwnership() { - console.log('> itShouldUpdateAssetOwnership'); + console.log("> itShouldUpdateAssetOwnership"); updateAssetOwnership(); } @@ -34,7 +34,7 @@ function itShouldUpdateAssetOwnership() { * Tests releaseClaim function of youtubeContentId.gs */ function itShouldReleaseClaim() { - console.log('> itShouldReleaseClaim'); + console.log("> itShouldReleaseClaim"); releaseClaim(); } diff --git a/advanced/youtube.gs b/advanced/youtube.gs index 87a2f86d8..645c6719f 100644 --- a/advanced/youtube.gs +++ b/advanced/youtube.gs @@ -22,20 +22,20 @@ */ function searchByKeyword() { try { - const results = YouTube.Search.list('id,snippet', { - q: 'dogs', - maxResults: 25 + const results = YouTube.Search.list("id,snippet", { + q: "dogs", + maxResults: 25, }); if (results === null) { - console.log('Unable to search videos'); + console.log("Unable to search videos"); return; } - results.items.forEach((item)=> { - console.log('[%s] Title: %s', item.id.videoId, item.snippet.title); - }); + for (const item of results.items) { + console.log("[%s] Title: %s", item.id.videoId, item.snippet.title); + } } catch (err) { // TODO (developer) - Handle exceptions from Youtube API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END apps_script_youtube_search] @@ -51,11 +51,11 @@ function searchByKeyword() { function retrieveMyUploads() { try { // @see https://developers.google.com/youtube/v3/docs/channels/list - const results = YouTube.Channels.list('contentDetails', { - mine: true + const results = YouTube.Channels.list("contentDetails", { + mine: true, }); if (!results || results.items.length === 0) { - console.log('No Channels found.'); + console.log("No Channels found."); return; } for (let i = 0; i < results.items.length; i++) { @@ -67,27 +67,29 @@ function retrieveMyUploads() { let nextPageToken = null; do { // @see: https://developers.google.com/youtube/v3/docs/playlistItems/list - const playlistResponse = YouTube.PlaylistItems.list('snippet', { + const playlistResponse = YouTube.PlaylistItems.list("snippet", { playlistId: playlistId, maxResults: 25, - pageToken: nextPageToken + pageToken: nextPageToken, }); if (!playlistResponse || playlistResponse.items.length === 0) { - console.log('No Playlist found.'); + console.log("No Playlist found."); break; } for (let j = 0; j < playlistResponse.items.length; j++) { const playlistItem = playlistResponse.items[j]; - console.log('[%s] Title: %s', - playlistItem.snippet.resourceId.videoId, - playlistItem.snippet.title); + console.log( + "[%s] Title: %s", + playlistItem.snippet.resourceId.videoId, + playlistItem.snippet.title, + ); } nextPageToken = playlistResponse.nextPageToken; } while (nextPageToken); } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with err %s', err.message); + console.log("Failed with err %s", err.message); } } // [END apps_script_youtube_uploads] @@ -99,26 +101,30 @@ function retrieveMyUploads() { */ function addSubscription() { // Replace this channel ID with the channel ID you want to subscribe to - const channelId = 'UC_x5XG1OV2P6uZZ5FSM9Ttw'; + const channelId = "UC_x5XG1OV2P6uZZ5FSM9Ttw"; const resource = { snippet: { resourceId: { - kind: 'youtube#channel', - channelId: channelId - } - } + kind: "youtube#channel", + channelId: channelId, + }, + }, }; try { - const response = YouTube.Subscriptions.insert(resource, 'snippet'); - console.log('Added subscription for channel title : %s', response.snippet.title); + const response = YouTube.Subscriptions.insert(resource, "snippet"); + console.log( + "Added subscription for channel title : %s", + response.snippet.title, + ); } catch (e) { - if (e.message.match('subscriptionDuplicate')) { - console.log('Cannot subscribe; already subscribed to channel: ' + - channelId); + if (e.message.match("subscriptionDuplicate")) { + console.log( + `Cannot subscribe; already subscribed to channel: ${channelId}`, + ); } else { // TODO (developer) - Handle exception - console.log('Error adding subscription: ' + e.message); + console.log(`Error adding subscription: ${e.message}`); } } } @@ -129,8 +135,8 @@ function addSubscription() { * Creates a slide presentation with 10 videos from the YouTube search `YOUTUBE_QUERY`. * The YouTube Advanced Service must be enabled before using this sample. */ -const PRESENTATION_TITLE = 'San Francisco, CA'; -const YOUTUBE_QUERY = 'San Francisco, CA'; +const PRESENTATION_TITLE = "San Francisco, CA"; +const YOUTUBE_QUERY = "San Francisco, CA"; /** * Gets a list of YouTube videos. @@ -139,17 +145,17 @@ const YOUTUBE_QUERY = 'San Francisco, CA'; * @see https://developers.google.com/youtube/v3/docs/search/list */ function getYouTubeVideosJSON(query) { - const youTubeResults = YouTube.Search.list('id,snippet', { + const youTubeResults = YouTube.Search.list("id,snippet", { q: query, - type: 'video', - maxResults: 10 + type: "video", + maxResults: 10, }); - return youTubeResults.items.map((item)=> { + return youTubeResults.items.map((item) => { return { - url: 'https://youtu.be/' + item.id.videoId, + url: `https://youtu.be/${item.id.videoId}`, title: item.snippet.title, - thumbnailUrl: item.snippet.thumbnails.high.url + thumbnailUrl: item.snippet.thumbnails.high.url, }; }); } @@ -162,22 +168,31 @@ function createSlides() { try { const youTubeVideos = getYouTubeVideosJSON(YOUTUBE_QUERY); const presentation = SlidesApp.create(PRESENTATION_TITLE); - presentation.getSlides()[0].getPageElements()[0].asShape() - .getText().setText(PRESENTATION_TITLE); + presentation + .getSlides()[0] + .getPageElements()[0] + .asShape() + .getText() + .setText(PRESENTATION_TITLE); if (!presentation) { - console.log('Unable to create presentation'); + console.log("Unable to create presentation"); return; } // Add slides with videos and log the presentation URL to the user. - youTubeVideos.forEach((video)=> { + for (const video of youTubeVideos) { const slide = presentation.appendSlide(); - slide.insertVideo(video.url, - 0, 0, presentation.getPageWidth(), presentation.getPageHeight()); - }); + slide.insertVideo( + video.url, + 0, + 0, + presentation.getPageWidth(), + presentation.getPageHeight(), + ); + } console.log(presentation.getUrl()); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_youtube_slides] diff --git a/advanced/youtubeAnalytics.gs b/advanced/youtubeAnalytics.gs index cfb0edda0..13b4ad9c9 100644 --- a/advanced/youtubeAnalytics.gs +++ b/advanced/youtubeAnalytics.gs @@ -20,8 +20,8 @@ */ function createReport() { // Retrieve info about the user's YouTube channel. - const channels = YouTube.Channels.list('id,contentDetails', { - mine: true + const channels = YouTube.Channels.list("id,contentDetails", { + mine: true, }); const channelId = channels.items[0].id; @@ -31,39 +31,39 @@ function createReport() { const lastMonth = new Date(today.getTime() - oneMonthInMillis); const metrics = [ - 'views', - 'estimatedMinutesWatched', - 'averageViewDuration', - 'subscribersGained' + "views", + "estimatedMinutesWatched", + "averageViewDuration", + "subscribersGained", ]; const result = YouTubeAnalytics.Reports.query({ - ids: 'channel==' + channelId, + ids: `channel==${channelId}`, startDate: formatDateString(lastMonth), endDate: formatDateString(today), - metrics: metrics.join(','), - dimensions: 'day', - sort: 'day' + metrics: metrics.join(","), + dimensions: "day", + sort: "day", }); if (!result.rows) { - console.log('No rows returned.'); + console.log("No rows returned."); return; } - const spreadsheet = SpreadsheetApp.create('YouTube Analytics Report'); + const spreadsheet = SpreadsheetApp.create("YouTube Analytics Report"); const sheet = spreadsheet.getActiveSheet(); // Append the headers. - const headers = result.columnHeaders.map((columnHeader)=> { + const headers = result.columnHeaders.map((columnHeader) => { return formatColumnName(columnHeader.name); }); sheet.appendRow(headers); // Append the results. - sheet.getRange(2, 1, result.rows.length, headers.length) - .setValues(result.rows); + sheet + .getRange(2, 1, result.rows.length, headers.length) + .setValues(result.rows); - console.log('Report spreadsheet created: %s', - spreadsheet.getUrl()); + console.log("Report spreadsheet created: %s", spreadsheet.getUrl()); } /** @@ -72,7 +72,7 @@ function createReport() { * @return {string} The formatted date. */ function formatDateString(date) { - return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy-MM-dd'); + return Utilities.formatDate(date, Session.getScriptTimeZone(), "yyyy-MM-dd"); } /** @@ -82,7 +82,7 @@ function formatDateString(date) { * @example "averageViewPercentage" becomes "Average View Percentage". */ function formatColumnName(columnName) { - let name = columnName.replace(/([a-z])([A-Z])/g, '$1 $2'); + let name = columnName.replace(/([a-z])([A-Z])/g, "$1 $2"); name = name.slice(0, 1).toUpperCase() + name.slice(1); return name; } diff --git a/advanced/youtubeContentId.gs b/advanced/youtubeContentId.gs index 22d37737c..f91bec1f7 100644 --- a/advanced/youtubeContentId.gs +++ b/advanced/youtubeContentId.gs @@ -21,29 +21,33 @@ */ function claimYourVideoWithMonetizePolicy() { // The ID of the content owner that you are acting on behalf of. - const onBehalfOfContentOwner = 'replaceWithYourContentOwnerID'; + const onBehalfOfContentOwner = "replaceWithYourContentOwnerID"; // A YouTube video ID to claim. In this example, the video must be uploaded // to one of your onBehalfOfContentOwner's linked channels. - const videoId = 'replaceWithYourVideoID'; - const assetId = 'replaceWithYourAssetID'; + const videoId = "replaceWithYourVideoID"; + const assetId = "replaceWithYourAssetID"; const claimToInsert = { - 'videoId': videoId, - 'assetId': assetId, - 'contentType': 'audiovisual', + videoId: videoId, + assetId: assetId, + contentType: "audiovisual", // Set the claim policy to monetize. You can also specify a policy ID here // instead of policy rules. // For details, please refer to the YouTube Content ID API Policies // documentation: // https://developers.google.com/youtube/partner/docs/v1/policies - 'policy': {'rules': [{'action': 'monetize'}]} + policy: { rules: [{ action: "monetize" }] }, }; try { - const claimInserted = YouTubeContentId.Claims.insert(claimToInsert, - {'onBehalfOfContentOwner': onBehalfOfContentOwner}); - console.log('Claim created on video %s: %s', videoId, claimInserted); + const claimInserted = YouTubeContentId.Claims.insert(claimToInsert, { + onBehalfOfContentOwner: onBehalfOfContentOwner, + }); + console.log("Claim created on video %s: %s", videoId, claimInserted); } catch (e) { - console.log('Failed to create claim on video %s, error: %s', - videoId, e.message); + console.log( + "Failed to create claim on video %s, error: %s", + videoId, + e.message, + ); } } // [END apps_script_youtube_claim] @@ -56,30 +60,33 @@ function claimYourVideoWithMonetizePolicy() { */ function updateAssetOwnership() { // The ID of the content owner that you are acting on behalf of. - const onBehalfOfContentOwner = 'replaceWithYourContentOwnerID'; + const onBehalfOfContentOwner = "replaceWithYourContentOwnerID"; // Replace values with your asset id - const assetId = 'replaceWithYourAssetID'; + const assetId = "replaceWithYourAssetID"; // The new ownership here would replace your existing ownership on the asset. const myAssetOwnership = { - 'general': [ + general: [ { - 'ratio': 100, - 'owner': onBehalfOfContentOwner, - 'type': 'include', - 'territories': [ - 'US', - 'CA' - ] - } - ] + ratio: 100, + owner: onBehalfOfContentOwner, + type: "include", + territories: ["US", "CA"], + }, + ], }; try { - const updatedOwnership = YouTubeContentId.Ownership.update(myAssetOwnership, - assetId, {'onBehalfOfContentOwner': onBehalfOfContentOwner}); - console.log('Ownership updated on asset %s: %s', assetId, updatedOwnership); + const updatedOwnership = YouTubeContentId.Ownership.update( + myAssetOwnership, + assetId, + { onBehalfOfContentOwner: onBehalfOfContentOwner }, + ); + console.log("Ownership updated on asset %s: %s", assetId, updatedOwnership); } catch (e) { - console.log('Ownership update failed on asset %s, error: %s', - assetId, e.message); + console.log( + "Ownership update failed on asset %s, error: %s", + assetId, + e.message, + ); } } // [END apps_script_youtube_update_asset_ownership] @@ -92,19 +99,22 @@ function updateAssetOwnership() { */ function releaseClaim() { // The ID of the content owner that you are acting on behalf of. - const onBehalfOfContentOwner = 'replaceWithYourContentOwnerID'; + const onBehalfOfContentOwner = "replaceWithYourContentOwnerID"; // The ID of the claim to be released. - const claimId = 'replaceWithYourClaimID'; + const claimId = "replaceWithYourClaimID"; // To release the claim, change the resource's status to inactive. const claimToBeReleased = { - 'status': 'inactive' + status: "inactive", }; try { - const claimReleased = YouTubeContentId.Claims.patch(claimToBeReleased, - claimId, {'onBehalfOfContentOwner': onBehalfOfContentOwner}); - console.log('Claim %s was released: %s', claimId, claimReleased); + const claimReleased = YouTubeContentId.Claims.patch( + claimToBeReleased, + claimId, + { onBehalfOfContentOwner: onBehalfOfContentOwner }, + ); + console.log("Claim %s was released: %s", claimId, claimReleased); } catch (e) { - console.log('Failed to release claim %s, error: %s', claimId, e.message); + console.log("Failed to release claim %s, error: %s", claimId, e.message); } } // [END apps_script_youtube_release_claim] diff --git a/ai/email-classifier/Cards.gs b/ai/email-classifier/Cards.gs index 55ffe0ea4..aee2c54c6 100644 --- a/ai/email-classifier/Cards.gs +++ b/ai/email-classifier/Cards.gs @@ -35,7 +35,9 @@ function buildHomepageCard() { // Create a card header const cardHeader = CardService.newCardHeader(); - cardHeader.setImageUrl('https://fonts.gstatic.com/s/i/googlematerialicons/label_important/v20/googblue-24dp/1x/gm_label_important_googblue_24dp.png'); + cardHeader.setImageUrl( + "https://fonts.gstatic.com/s/i/googlematerialicons/label_important/v20/googblue-24dp/1x/gm_label_important_googblue_24dp.png", + ); cardHeader.setImageStyle(CardService.ImageStyle.CIRCLE); cardHeader.setTitle("Email Classifier"); @@ -50,27 +52,27 @@ function buildHomepageCard() { // Create "Classify emails" button const classifyButton = createFilledButton({ - text: 'Classify emails', - functionName: 'main', - color: '#007bff', - icon: 'new_label' + text: "Classify emails", + functionName: "main", + color: "#007bff", + icon: "new_label", }); buttonSet.addButton(classifyButton); // Create "Create Labels" button const createLabelsButtton = createFilledButton({ - text: 'Create labels', - functionName: 'createLabels', - color: '#34A853', - icon: 'add' + text: "Create labels", + functionName: "createLabels", + color: "#34A853", + icon: "add", }); // Create "Remove Labels" button const removeLabelsButtton = createFilledButton({ - text: 'Remove labels', - functionName: 'removeLabels', - color: '#FF0000', - icon: 'delete' + text: "Remove labels", + functionName: "removeLabels", + color: "#FF0000", + icon: "delete", }); if (labelsCreated()) { @@ -99,7 +101,7 @@ function buildHomepageCard() { * - icon: The material icon to display on the button. * @returns {!TextButton} - The created text button. */ -function createFilledButton({text, functionName, color, icon}) { +function createFilledButton({ text, functionName, color, icon }) { // Create a new text button const textButton = CardService.newTextButton(); @@ -153,28 +155,34 @@ function buildNotificationResponse(notificationText) { function showSpreadsheetLink(spreadsheetUrl) { const updatedCardBuilder = CardService.newCardBuilder(); - updatedCardBuilder.setHeader(CardService.newCardHeader().setTitle('Sheet generated!')); + updatedCardBuilder.setHeader( + CardService.newCardHeader().setTitle("Sheet generated!"), + ); const updatedSection = CardService.newCardSection() - .addWidget(CardService.newTextParagraph() - .setText('Click to open the sheet:') + .addWidget( + CardService.newTextParagraph().setText("Click to open the sheet:"), ) - .addWidget(CardService.newTextButton() - .setText('Open Sheet') - .setOpenLink(CardService.newOpenLink() - .setUrl(spreadsheetUrl) - .setOpenAs(CardService.OpenAs.FULL_SCREEN) // Opens in a new browser tab/window - .setOnClose(CardService.OnClose.NOTHING) // Does nothing when the tab is closed - ) + .addWidget( + CardService.newTextButton().setText("Open Sheet").setOpenLink( + CardService.newOpenLink() + .setUrl(spreadsheetUrl) + .setOpenAs(CardService.OpenAs.FULL_SCREEN) // Opens in a new browser tab/window + .setOnClose(CardService.OnClose.NOTHING), // Does nothing when the tab is closed + ), ) - .addWidget(CardService.newTextButton() // Optional: Add a button to go back or refresh - .setText('Go Back') - .setOnClickAction(CardService.newAction() - .setFunctionName('onHomepageTrigger')) // Go back to the initial state + .addWidget( + CardService.newTextButton() // Optional: Add a button to go back or refresh + .setText("Go Back") + .setOnClickAction( + CardService.newAction().setFunctionName("onHomepageTrigger"), + ), // Go back to the initial state ); updatedCardBuilder.addSection(updatedSection); - const newNavigation = CardService.newNavigation().updateCard(updatedCardBuilder.build()); + const newNavigation = CardService.newNavigation().updateCard( + updatedCardBuilder.build(), + ); return CardService.newActionResponseBuilder() .setNavigation(newNavigation) // This updates the current card in the UI diff --git a/ai/email-classifier/ClassifyEmail.gs b/ai/email-classifier/ClassifyEmail.gs index cda44a7ce..3991aee05 100644 --- a/ai/email-classifier/ClassifyEmail.gs +++ b/ai/email-classifier/ClassifyEmail.gs @@ -21,7 +21,8 @@ * @param {string} body The body of the email. * @returns {string} The prompt for classifying an email. */ -const classifyEmailPrompt = (subject, body) => ` +const classifyEmailPrompt = (subject, body) => + ` Objective: You are an AI assistant tasked with classifying email threads. Analyze the entire email thread provided below and determine the single most appropriate classification label. Your response must conform to the provided schema. **Classification Labels & Descriptions:** @@ -70,9 +71,9 @@ function classifyEmail(subject, messages) { body.push(`Message ${i + 1}:`); body.push(`From: ${message.getFrom()}`); body.push(`To:${message.getTo()}`); - body.push('Body:'); + body.push("Body:"); body.push(message.getPlainBody()); - body.push('---'); + body.push("---"); } // Prepare the request payload @@ -82,10 +83,10 @@ function classifyEmail(subject, messages) { role: "user", parts: [ { - text: classifyEmailPrompt(subject, body.join('\n')) - } - ] - } + text: classifyEmailPrompt(subject, body.join("\n")), + }, + ], + }, ], generationConfig: { temperature: 0, @@ -103,22 +104,22 @@ function classifyEmail(subject, messages) { enum: Object.keys(classificationLabels), }, reason: { - type: 'string' - } - } - } - } + type: "string", + }, + }, + }, + }, }; // Prepare the request options const options = { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${ScriptApp.getOAuthToken()}` + Authorization: `Bearer ${ScriptApp.getOAuthToken()}`, }, - contentType: 'application/json', + contentType: "application/json", muteHttpExceptions: true, // Set to true to inspect the error response - payload: JSON.stringify(payload) + payload: JSON.stringify(payload), }; // Make the API request @@ -130,4 +131,3 @@ function classifyEmail(subject, messages) { const classification = JSON.parse(text); return classification; } - diff --git a/ai/email-classifier/Code.gs b/ai/email-classifier/Code.gs index c802e8192..661534fba 100644 --- a/ai/email-classifier/Code.gs +++ b/ai/email-classifier/Code.gs @@ -28,18 +28,21 @@ function main() { const sevenDaysAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); // Create a Sheet - const headers = ['Subject', 'Classification', 'Reason']; + const headers = ["Subject", "Classification", "Reason"]; const spreadsheet = createSheetWithHeaders(headers); // Format the date for the Gmail search query (YYYY/MM/DD) // Using Utilities.formatDate ensures correct formatting based on script // timezone const formattedDate = Utilities.formatDate( - sevenDaysAgo, Session.getScriptTimeZone(), 'yyyy/MM/dd'); + sevenDaysAgo, + Session.getScriptTimeZone(), + "yyyy/MM/dd", + ); // Construct the search query const query = `is:unread after:${formattedDate} in:inbox`; - console.log('Searching for emails with query: ' + query); + console.log(`Searching for emails with query: ${query}`); // Search for threads matching the query // Note: GmailApp.search() returns threads where *at least one* message @@ -50,14 +53,14 @@ function main() { for (const thread of threads) { const messages = thread.getMessages(); const subject = thread.getFirstMessageSubject(); - const {classification, reason} = classifyEmail(subject, messages); + const { classification, reason } = classifyEmail(subject, messages); console.log(`Classification: ${classification}, Reason: ${reason}`); thread.addLabel(classificationLabels[classification].gmailLabel); - if (classification === 'needs-response') { + if (classification === "needs-response") { const draft = draftEmail(subject, messages); - thread.createDraftReplyAll(null, {htmlBody: draft}); + thread.createDraftReplyAll(null, { htmlBody: draft }); } addDataToSheet(spreadsheet, hyperlink(thread), classification, reason); diff --git a/ai/email-classifier/Constants.gs b/ai/email-classifier/Constants.gs index 2908b83ba..6799835aa 100644 --- a/ai/email-classifier/Constants.gs +++ b/ai/email-classifier/Constants.gs @@ -14,10 +14,10 @@ * limitations under the License. */ -const PROJECT_ID = ''; -const LOCATION = 'us-central1'; +const PROJECT_ID = ""; +const LOCATION = "us-central1"; const API_ENDPOINT = `${LOCATION}-aiplatform.googleapis.com`; -const MODEL = 'gemini-2.5-pro-preview-05-06'; -const GENERATE_CONTENT_API = 'generateContent'; +const MODEL = "gemini-2.5-pro-preview-05-06"; +const GENERATE_CONTENT_API = "generateContent"; const API_URL = `https://${API_ENDPOINT}/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL}:${GENERATE_CONTENT_API}`; -const ME = ''; +const ME = ""; diff --git a/ai/email-classifier/DraftEmail.gs b/ai/email-classifier/DraftEmail.gs index f016386ba..b1b8ac32c 100644 --- a/ai/email-classifier/DraftEmail.gs +++ b/ai/email-classifier/DraftEmail.gs @@ -21,7 +21,8 @@ * @param {string} body The body of the email thread. * @returns {string} The prompt string. */ -const draftEmailPrompt = (subject, body) => ` +const draftEmailPrompt = (subject, body) => + ` You are an AI assistant. Based on the following email thread: Subject: ${subject} @@ -74,9 +75,9 @@ function draftEmail(subject, messages) { body.push(`Message ${i + 1}:`); body.push(`From: ${message.getFrom()}`); body.push(`To:${message.getTo()}`); - body.push('Body:'); + body.push("Body:"); body.push(message.getPlainBody()); - body.push('---'); + body.push("---"); } // Prepare the request payload @@ -86,10 +87,10 @@ function draftEmail(subject, messages) { role: "user", parts: [ { - text: draftEmailPrompt(subject, body.join('\n')) - } - ] - } + text: draftEmailPrompt(subject, body.join("\n")), + }, + ], + }, ], generationConfig: { temperature: 0, @@ -97,19 +98,19 @@ function draftEmail(subject, messages) { topP: 0.1, seed: 37, maxOutputTokens: 1024, - responseMimeType: 'text/plain' - } + responseMimeType: "text/plain", + }, }; // Prepare the request options const options = { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${ScriptApp.getOAuthToken()}` + Authorization: `Bearer ${ScriptApp.getOAuthToken()}`, }, - contentType: 'application/json', + contentType: "application/json", muteHttpExceptions: true, // Set to true to inspect the error response - payload: JSON.stringify(payload) + payload: JSON.stringify(payload), }; // Make the API request @@ -128,14 +129,14 @@ function draftEmail(subject, messages) { * @returns {string|null} The HTML content or null if not found. */ function extractHtmlContent(textString) { - // The regex pattern: - // ````html` (literal start marker) - // `(.*?)` (capturing group for any character, non-greedily, including newlines) - // ` ``` ` (literal end marker) - // `s` flag makes '.' match any character including newlines. - const match = textString.match(/```html(.*?)```/s); - if (match && match[1]) { - return match[1]; // Return the content of the first capturing group - } - return null; // Or an empty string, depending on desired behavior if not found + // The regex pattern: + // ````html` (literal start marker) + // `(.*?)` (capturing group for any character, non-greedily, including newlines) + // ` ``` ` (literal end marker) + // `s` flag makes '.' match any character including newlines. + const match = textString.match(/```html(.*?)```/s); + if (match?.[1]) { + return match[1]; // Return the content of the first capturing group + } + return null; // Or an empty string, depending on desired behavior if not found } diff --git a/ai/email-classifier/Labels.gs b/ai/email-classifier/Labels.gs index 4f6505ad3..dc4835be0 100644 --- a/ai/email-classifier/Labels.gs +++ b/ai/email-classifier/Labels.gs @@ -16,19 +16,19 @@ const classificationLabels = { "action-required": { - "name": "🚨 Action Required", - "textColor": '#ffffff', - "backgroundColor": "#1c4587" + name: "🚨 Action Required", + textColor: "#ffffff", + backgroundColor: "#1c4587", }, "needs-response": { - "name": "↪️ Needs Response", - "textColor": '#ffffff', - "backgroundColor": "#16a765" + name: "↪️ Needs Response", + textColor: "#ffffff", + backgroundColor: "#16a765", }, "for-your-info": { - "name": "ℹ️ For Your Info", - "textColor": '#000000', - "backgroundColor": "#fad165" + name: "ℹ️ For Your Info", + textColor: "#000000", + backgroundColor: "#fad165", }, }; @@ -46,19 +46,23 @@ function createLabels() { if (!gmailLabel) { gmailLabel = GmailApp.createLabel(name); - Gmail.Users.Labels.update({ - name: name, - color: { - textColor: textColor, - backgroundColor: backgroundColor - } - }, 'me', fetchLabelId(name)); + Gmail.Users.Labels.update( + { + name: name, + color: { + textColor: textColor, + backgroundColor: backgroundColor, + }, + }, + "me", + fetchLabelId(name), + ); } classificationLabel.gmailLabel = gmailLabel; } - console.log('Labels created.'); + console.log("Labels created."); return buildHomepageCard(); } @@ -69,7 +73,7 @@ function createLabels() { function labelsCreated() { for (const labelName in classificationLabels) { const { name } = classificationLabels[labelName]; - let gmailLabel = GmailApp.getUserLabelByName(name); + const gmailLabel = GmailApp.getUserLabelByName(name); if (!gmailLabel) { return false; @@ -85,7 +89,7 @@ function labelsCreated() { * @returns {string} The ID of the label. */ function fetchLabelId(name) { - return Gmail.Users.Labels.list('me').labels.find(_ => _.name === name).id; + return Gmail.Users.Labels.list("me").labels.find((_) => _.name === name).id; } /** @@ -96,13 +100,13 @@ function fetchLabelId(name) { function removeLabels() { for (const labelName in classificationLabels) { const classificationLabel = classificationLabels[labelName]; - let gmailLabel = GmailApp.getUserLabelByName(classificationLabel.name); + const gmailLabel = GmailApp.getUserLabelByName(classificationLabel.name); if (gmailLabel) { gmailLabel.deleteLabel(); - delete classificationLabel.gmailLabel; + classificationLabel.gmailLabel = undefined; } } - console.log('Labels removed.'); + console.log("Labels removed."); return buildHomepageCard(); } diff --git a/ai/email-classifier/Sheet.gs b/ai/email-classifier/Sheet.gs index b665d757a..4b354f693 100644 --- a/ai/email-classifier/Sheet.gs +++ b/ai/email-classifier/Sheet.gs @@ -57,27 +57,33 @@ function hyperlink(thread) { * @param {!Spreadsheet} ss The spreadsheet to add the table to. */ function addTable(ss) { - const values = Object.keys(classificationLabels).map(label => { + const values = Object.keys(classificationLabels).map((label) => { return { userEnteredValue: label }; }); const addTableRequest = { - requests: [{ - addTable: { - table: { - name: 'Email classification', - range: { - sheetId: 0, - startColumnIndex: 0, - endColumnIndex: 2, + requests: [ + { + addTable: { + table: { + name: "Email classification", + range: { + sheetId: 0, + startColumnIndex: 0, + endColumnIndex: 2, + }, + columnProperties: [ + { + columnIndex: 1, + columnType: "DROPDOWN", + dataValidationRule: { + condition: { type: "ONE_OF_LIST", values: values }, + }, + }, + ], }, - columnProperties: [{ - columnIndex: 1, - columnType: 'DROPDOWN', - dataValidationRule: { condition: { type: 'ONE_OF_LIST', values: values } } - }], - } - } - }] + }, + }, + ], }; Sheets.Spreadsheets.batchUpdate(addTableRequest, ss.getId()); diff --git a/ai/gmail-sentiment-analysis/Cards.gs b/ai/gmail-sentiment-analysis/Cards.gs index 566c1ca47..9f6525c6c 100644 --- a/ai/gmail-sentiment-analysis/Cards.gs +++ b/ai/gmail-sentiment-analysis/Cards.gs @@ -14,30 +14,27 @@ See the License for the specific language governing permissions and limitations under the License. */ - /** * Builds the card for to display in the sidepanel of gmail. * @return {CardService.Card} The card to show to the user. */ -function buildCard_GmailHome(notifyOk=false){ - const imageUrl ='https://icons.iconarchive.com/icons/roundicons/100-free-solid/48/spy-icon.png'; - const image = CardService.newImage() - .setImageUrl(imageUrl); +function buildCard_GmailHome(notifyOk = false) { + const imageUrl = + "https://icons.iconarchive.com/icons/roundicons/100-free-solid/48/spy-icon.png"; + const image = CardService.newImage().setImageUrl(imageUrl); const cardHeader = CardService.newCardHeader() .setImageUrl(imageUrl) .setImageStyle(CardService.ImageStyle.CIRCLE) .setTitle("Analyze your GMail"); - - const action = CardService.newAction() - .setFunctionName('analyzeSentiment'); + + const action = CardService.newAction().setFunctionName("analyzeSentiment"); const button = CardService.newTextButton() - .setText('Identify angry customers') + .setText("Identify angry customers") .setOnClickAction(action) .setTextButtonStyle(CardService.TextButtonStyle.FILLED); - const buttonSet = CardService.newButtonSet() - .addButton(button); + const buttonSet = CardService.newButtonSet().addButton(button); const section = CardService.newCardSection() .setHeader("Emails sentiment analysis") @@ -47,21 +44,20 @@ function buildCard_GmailHome(notifyOk=false){ .setHeader(cardHeader) .addSection(section); -/** - * This builds the card that contains the footer that informs - * the user about the successful execution of the Add-on. - */ + /** + * This builds the card that contains the footer that informs + * the user about the successful execution of the Add-on. + */ -if(notifyOk==true){ - let fixedFooter = CardService.newFixedFooter() - .setPrimaryButton( + if (notifyOk === true) { + const fixedFooter = CardService.newFixedFooter().setPrimaryButton( CardService.newTextButton() .setText("Analysis complete") .setOnClickAction( - CardService.newAction() - .setFunctionName( - "buildCard_GmailHome"))); - card.setFixedFooter(fixedFooter); -} + CardService.newAction().setFunctionName("buildCard_GmailHome"), + ), + ); + card.setFixedFooter(fixedFooter); + } return card.build(); -} \ No newline at end of file +} diff --git a/ai/gmail-sentiment-analysis/Code.gs b/ai/gmail-sentiment-analysis/Code.gs index 7b353e735..b599ca2cf 100644 --- a/ai/gmail-sentiment-analysis/Code.gs +++ b/ai/gmail-sentiment-analysis/Code.gs @@ -21,4 +21,3 @@ limitations under the License. function onHomepage(e) { return buildCard_GmailHome(); } - diff --git a/ai/gmail-sentiment-analysis/Gmail.gs b/ai/gmail-sentiment-analysis/Gmail.gs index 1bf87b1a9..901268d75 100644 --- a/ai/gmail-sentiment-analysis/Gmail.gs +++ b/ai/gmail-sentiment-analysis/Gmail.gs @@ -19,7 +19,7 @@ limitations under the License. * @return {CardService.Card} The card to show to the user. */ -function analyzeSentiment(){ +function analyzeSentiment() { emailSentiment(); return buildCard_GmailHome(true); } @@ -27,7 +27,7 @@ function analyzeSentiment(){ /** * Gets the last 10 threads in the inbox and the corresponding messages. * Fetches the label that should be applied to negative messages. - * The processSentiment is called on each message + * The processSentiment is called on each message * and tested with RegExp to check for a negative answer from the model */ @@ -37,13 +37,13 @@ function emailSentiment() { const label_upset = GmailApp.getUserLabelByName("UPSET TONE 😡"); let currentPrediction; - for (let i = 0 ; i < msgs.length; i++) { + for (let i = 0; i < msgs.length; i++) { for (let j = 0; j < msgs[i].length; j++) { - let emailText = msgs[i][j].getPlainBody(); + const emailText = msgs[i][j].getPlainBody(); currentPrediction = processSentiment(emailText); - if(currentPrediction === true){ + if (currentPrediction === true) { label_upset.addToThread(msgs[i][j].getThread()); } } } -} \ No newline at end of file +} diff --git a/ai/gmail-sentiment-analysis/Vertex.gs b/ai/gmail-sentiment-analysis/Vertex.gs index f93a86829..8b9d2b1d6 100644 --- a/ai/gmail-sentiment-analysis/Vertex.gs +++ b/ai/gmail-sentiment-analysis/Vertex.gs @@ -14,16 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -const PROJECT_ID = [ADD YOUR GCP PROJECT ID HERE]; -const VERTEX_AI_LOCATION = 'europe-west2'; -const MODEL_ID = 'gemini-2.5-pro'; -const SERVICE_ACCOUNT_KEY = PropertiesService.getScriptProperties().getProperty('service_account_key'); +const PROJECT_ID = "ADD YOUR GCP PROJECT ID HERE"; +const VERTEX_AI_LOCATION = "europe-west2"; +const MODEL_ID = "gemini-2.5-pro"; +const SERVICE_ACCOUNT_KEY = PropertiesService.getScriptProperties().getProperty( + "service_account_key", +); /** * Packages prompt and necessary settings, then sends a request to - * Vertex API. + * Vertex API. * A check is performed to see if the response from Vertex AI contains FALSE as a value. - * Returns the outcome of that check which is a boolean. + * Returns the outcome of that check which is a boolean. * * @param emailText - Email message that is sent to the model. */ @@ -32,33 +34,37 @@ function processSentiment(emailText) { const prompt = `Analyze the following message: ${emailText}. If the sentiment of this message is negative, answer with FALSE. If the sentiment of this message is neutral or positive, answer with TRUE. Do not use any other words than the ones requested in this prompt as a response!`; const request = { - "contents": [{ - "role": "user", - "parts": [{ - "text": prompt - }] - }], - "generationConfig": { - "temperature": 0.9, - "maxOutputTokens": 1024, - - } + contents: [ + { + role: "user", + parts: [ + { + text: prompt, + }, + ], + }, + ], + generationConfig: { + temperature: 0.9, + maxOutputTokens: 1024, + }, }; const credentials = credentialsForVertexAI(); const fetchOptions = { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${credentials.accessToken}` + Authorization: `Bearer ${credentials.accessToken}`, }, - contentType: 'application/json', + contentType: "application/json", muteHttpExceptions: true, - payload: JSON.stringify(request) - } + payload: JSON.stringify(request), + }; - const url = `https://${VERTEX_AI_LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/` - + `locations/${VERTEX_AI_LOCATION}/publishers/google/models/${MODEL_ID}:generateContent` + const url = + `https://${VERTEX_AI_LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/` + + `locations/${VERTEX_AI_LOCATION}/publishers/google/models/${MODEL_ID}:generateContent`; const response = UrlFetchApp.fetch(url, fetchOptions); const payload = JSON.parse(response.getContentText()); @@ -66,13 +72,12 @@ function processSentiment(emailText) { const regex = /FALSE/; return regex.test(payload.candidates[0].content.parts[0].text); - } /** * Gets credentials required to call Vertex API using a Service Account. * Requires use of Service Account Key stored with project - * + * * @return {!Object} Containing the Cloud Project Id and the access token. */ @@ -85,13 +90,13 @@ function credentialsForVertexAI() { const parsedCredentials = JSON.parse(credentials); const service = OAuth2.createService("Vertex") - .setTokenUrl('https://oauth2.googleapis.com/token') - .setPrivateKey(parsedCredentials['private_key']) - .setIssuer(parsedCredentials['client_email']) + .setTokenUrl("https://oauth2.googleapis.com/token") + .setPrivateKey(parsedCredentials.private_key) + .setIssuer(parsedCredentials.client_email) .setPropertyStore(PropertiesService.getScriptProperties()) .setScope("https://www.googleapis.com/auth/cloud-platform"); return { - projectId: parsedCredentials['project_id'], + projectId: parsedCredentials.project_id, accessToken: service.getAccessToken(), - } -} \ No newline at end of file + }; +} diff --git a/calendar/quickstart/quickstart.gs b/calendar/quickstart/quickstart.gs index 026aedc6d..d48c40dc2 100644 --- a/calendar/quickstart/quickstart.gs +++ b/calendar/quickstart/quickstart.gs @@ -19,14 +19,14 @@ * @see https://developers.google.com/calendar/api/v3/reference/events/list */ function listUpcomingEvents() { - const calendarId = 'primary'; + const calendarId = "primary"; // Add query parameters in optionalArgs const optionalArgs = { - timeMin: (new Date()).toISOString(), + timeMin: new Date().toISOString(), showDeleted: false, singleEvents: true, maxResults: 10, - orderBy: 'startTime' + orderBy: "startTime", // use other optional query parameter here as needed. }; try { @@ -34,7 +34,7 @@ function listUpcomingEvents() { const response = Calendar.Events.list(calendarId, optionalArgs); const events = response.items; if (events.length === 0) { - console.log('No upcoming events found'); + console.log("No upcoming events found"); return; } // Print the calendar events @@ -43,11 +43,11 @@ function listUpcomingEvents() { if (!when) { when = event.start.date; } - console.log('%s (%s)', event.summary, when); + console.log("%s (%s)", event.summary, when); } } catch (err) { // TODO (developer) - Handle exception from Calendar API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END calendar_quickstart] diff --git a/chat/advanced-service/AppAuthenticationUtils.gs b/chat/advanced-service/AppAuthenticationUtils.gs index 87af3ba93..4d38fee20 100644 --- a/chat/advanced-service/AppAuthenticationUtils.gs +++ b/chat/advanced-service/AppAuthenticationUtils.gs @@ -22,7 +22,7 @@ // For more information on app authentication, see // https://developers.google.com/workspace/chat/authenticate-authorize-chat-app -const APP_AUTH_OAUTH_SCOPES = ['https://www.googleapis.com/auth/chat.bot']; +const APP_AUTH_OAUTH_SCOPES = ["https://www.googleapis.com/auth/chat.bot"]; // Warning: This example uses a service account private key, it should always be stored in a // secure location. const SERVICE_ACCOUNT = { @@ -54,7 +54,7 @@ function getService_() { */ function getHeaderWithAppCredentials() { return { - 'Authorization': `Bearer ${getService_().getAccessToken()}` + Authorization: `Bearer ${getService_().getAccessToken()}`, }; } diff --git a/chat/advanced-service/Main.gs b/chat/advanced-service/Main.gs index b029ef102..48300da5a 100644 --- a/chat/advanced-service/Main.gs +++ b/chat/advanced-service/Main.gs @@ -1,12 +1,12 @@ /** * Copyright 2024 Google LLC - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,21 +26,21 @@ // [START chat_create_membership_user_cred] /** * This sample shows how to create membership with user credential for a human user - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.memberships' * referenced in the manifest file (appsscript.json). */ function createMembershipUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const membership = { member: { // TODO(developer): Replace USER_NAME here - name: 'users/USER_NAME', + name: "users/USER_NAME", // User type for the membership - type: 'HUMAN' - } + type: "HUMAN", + }, }; // Make the request @@ -54,21 +54,21 @@ function createMembershipUserCred() { // [START chat_create_membership_user_cred_for_app] /** * This sample shows how to create membership with app credential for an app - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.memberships.app' * referenced in the manifest file (appsscript.json). */ function createMembershipUserCredForApp() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const membership = { member: { // Member name for app membership, do not change this - name: 'users/app', + name: "users/app", // User type for the membership - type: 'BOT' - } + type: "BOT", + }, }; // Make the request @@ -82,19 +82,19 @@ function createMembershipUserCredForApp() { // [START chat_create_membership_user_cred_for_group] /** * This sample shows how to create membership with user credential for a group - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.memberships' * referenced in the manifest file (appsscript.json). */ function createMembershipUserCredForGroup() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const membership = { groupMember: { // TODO(developer): Replace GROUP_NAME here - name: 'groups/GROUP_NAME' - } + name: "groups/GROUP_NAME", + }, }; // Make the request @@ -105,66 +105,106 @@ function createMembershipUserCredForGroup() { } // [END chat_create_membership_user_cred_for_group] - // [START chat_create_message_app_cred] /** * This sample shows how to create message with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function createMessageAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const message = { - text: '👋🌎 Hello world! I created this message by calling ' + - 'the Chat API\'s `messages.create()` method.', - cardsV2 : [{ card: { - header: { - title: 'About this message', - imageUrl: 'https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg' + text: + "👋🌎 Hello world! I created this message by calling " + + "the Chat API's `messages.create()` method.", + cardsV2: [ + { + card: { + header: { + title: "About this message", + imageUrl: + "https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg", + }, + sections: [ + { + header: "Contents", + widgets: [ + { + textParagraph: { + text: + "🔡 Text which can include " + + "hyperlinks 🔗, emojis 😄🎉, and @mentions 🗣️.", + }, + }, + { + textParagraph: { + text: + "🖼️ A card to display visual elements" + + "and request information such as text 🔤, " + + "dates and times 📅, and selections ☑️.", + }, + }, + { + textParagraph: { + text: + "👉🔘 An accessory widget which adds " + + "a button to the bottom of a message.", + }, + }, + ], + }, + { + header: "What's next", + collapsible: true, + widgets: [ + { + textParagraph: { + text: "❤️ Add a reaction.", + }, + }, + { + textParagraph: { + text: + "🔄 Update " + + "or ❌ delete " + + "the message.", + }, + }, + ], + }, + ], + }, }, - sections: [{ - header: 'Contents', - widgets: [{ textParagraph: { - text: '🔡 Text which can include ' + - 'hyperlinks 🔗, emojis 😄🎉, and @mentions 🗣️.' - }}, { textParagraph: { - text: '🖼️ A card to display visual elements' + - 'and request information such as text 🔤, ' + - 'dates and times 📅, and selections ☑️.' - }}, { textParagraph: { - text: '👉🔘 An accessory widget which adds ' + - 'a button to the bottom of a message.' - }} - ]}, { - header: "What's next", - collapsible: true, - widgets: [{ textParagraph: { - text: "❤️ Add a reaction." - }}, { textParagraph: { - text: "🔄 Update " + - "or ❌ delete " + - "the message." - } - }] - } - ] - }}], - accessoryWidgets: [{ buttonList: { buttons: [{ - text: 'View documentation', - icon: { materialIcon: { name: 'link' }}, - onClick: { openLink: { - url: 'https://developers.google.com/workspace/chat/create-messages' - }} - }]}}] + ], + accessoryWidgets: [ + { + buttonList: { + buttons: [ + { + text: "View documentation", + icon: { materialIcon: { name: "link" } }, + onClick: { + openLink: { + url: "https://developers.google.com/workspace/chat/create-messages", + }, + }, + }, + ], + }, + }, + ], }; const parameters = {}; // Make the request const response = Chat.Spaces.Messages.create( - message, parent, parameters, getHeaderWithAppCredentials() + message, + parent, + parameters, + getHeaderWithAppCredentials(), ); // Handle the response @@ -175,23 +215,24 @@ function createMessageAppCred() { // [START chat_create_message_user_cred] /** * This sample shows how to create message with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const message = { - text: '👋🌎 Hello world!' + - 'Text messages can contain things like:\n\n' + - '* Hyperlinks 🔗\n' + - '* Emojis 😄🎉\n' + - '* Mentions of other Chat users `@` \n\n' + - 'For details, see the ' + - '.' + text: + "👋🌎 Hello world!" + + "Text messages can contain things like:\n\n" + + "* Hyperlinks 🔗\n" + + "* Emojis 😄🎉\n" + + "* Mentions of other Chat users `@` \n\n" + + "For details, see the " + + ".", }; // Make the request @@ -205,18 +246,18 @@ function createMessageUserCred() { // [START chat_create_message_user_cred_at_mention] /** * This sample shows how to create message with user credential with a user mention - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCredAtMention() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; const message = { // The user with USER_NAME will be mentioned if they are in the space // TODO(developer): Replace USER_NAME here - text: 'Hello !' + text: "Hello !", }; // Make the request @@ -230,22 +271,22 @@ function createMessageUserCredAtMention() { // [START chat_create_message_user_cred_message_id] /** * This sample shows how to create message with user credential with message id - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCredMessageId() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Message id lets chat apps get, update or delete a message without needing // to store the system assigned ID in the message's resource name - const messageId = 'client-MESSAGE-ID'; - const message = { text: 'Hello with user credential!' }; + const messageId = "client-MESSAGE-ID"; + const message = { text: "Hello with user credential!" }; // Make the request const response = Chat.Spaces.Messages.create(message, parent, { - messageId: messageId + messageId: messageId, }); // Handle the response @@ -256,22 +297,22 @@ function createMessageUserCredMessageId() { // [START chat_create_message_user_cred_request_id] /** * This sample shows how to create message with user credential with request id - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCredRequestId() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Specifying an existing request ID returns the message created with // that ID instead of creating a new message - const requestId = 'REQUEST_ID'; - const message = { text: 'Hello with user credential!' }; + const requestId = "REQUEST_ID"; + const message = { text: "Hello with user credential!" }; // Make the request const response = Chat.Spaces.Messages.create(message, parent, { - requestId: requestId + requestId: requestId, }); // Handle the response @@ -282,29 +323,29 @@ function createMessageUserCredRequestId() { // [START chat_create_message_user_cred_thread_key] /** * This sample shows how to create message with user credential with thread key - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCredThreadKey() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Creates the message as a reply to the thread specified by thread_key // If it fails, the message starts a new thread instead - const messageReplyOption = 'REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD'; + const messageReplyOption = "REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"; const message = { - text: 'Hello with user credential!', + text: "Hello with user credential!", thread: { // Thread key specifies a thread and is unique to the chat app // that sets it - threadKey: 'THREAD_KEY' - } + threadKey: "THREAD_KEY", + }, }; // Make the request const response = Chat.Spaces.Messages.create(message, parent, { - messageReplyOption: messageReplyOption + messageReplyOption: messageReplyOption, }); // Handle the response @@ -315,29 +356,29 @@ function createMessageUserCredThreadKey() { // [START chat_create_message_user_cred_thread_name] /** * This sample shows how to create message with user credential with thread name - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.create' * referenced in the manifest file (appsscript.json). */ function createMessageUserCredThreadName() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here. - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Creates the message as a reply to the thread specified by thread.name // If it fails, the message starts a new thread instead - const messageReplyOption = 'REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD'; + const messageReplyOption = "REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"; const message = { - text: 'Hello with user credential!', + text: "Hello with user credential!", thread: { // Resource name of a thread that uniquely identify a thread // TODO(developer): Replace SPACE_NAME and THREAD_NAME here - name: 'spaces/SPACE_NAME/threads/THREAD_NAME' - } + name: "spaces/SPACE_NAME/threads/THREAD_NAME", + }, }; // Make the request const response = Chat.Spaces.Messages.create(message, parent, { - messageReplyOption: messageReplyOption + messageReplyOption: messageReplyOption, }); // Handle the response @@ -348,16 +389,16 @@ function createMessageUserCredThreadName() { // [START chat_create_space_user_cred] /** * This sample shows how to create space with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.spaces.create' * referenced in the manifest file (appsscript.json). */ function createSpaceUserCred() { // Initialize request argument(s) const space = { - spaceType: 'SPACE', + spaceType: "SPACE", // TODO(developer): Replace DISPLAY_NAME here - displayName: 'DISPLAY_NAME' + displayName: "DISPLAY_NAME", }; // Make the request @@ -371,18 +412,22 @@ function createSpaceUserCred() { // [START chat_delete_message_app_cred] /** * This sample shows how to delete a message with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function deleteMessageAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; const parameters = {}; // Make the request - const response = Chat.Spaces.Messages.remove(name, parameters, getHeaderWithAppCredentials()); + const response = Chat.Spaces.Messages.remove( + name, + parameters, + getHeaderWithAppCredentials(), + ); // Handle the response console.log(response); @@ -392,14 +437,14 @@ function deleteMessageAppCred() { // [START chat_delete_message_user_cred] /** * This sample shows how to delete a message with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages' * referenced in the manifest file (appsscript.json). */ function deleteMessageUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; // Make the request const response = Chat.Spaces.Messages.remove(name); @@ -412,18 +457,22 @@ function deleteMessageUserCred() { // [START chat_get_membership_app_cred] /** * This sample shows how to get membership with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function getMembershipAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MEMBER_NAME here - const name = 'spaces/SPACE_NAME/members/MEMBER_NAME'; + const name = "spaces/SPACE_NAME/members/MEMBER_NAME"; const parameters = {}; // Make the request - const response = Chat.Spaces.Members.get(name, parameters, getHeaderWithAppCredentials()); + const response = Chat.Spaces.Members.get( + name, + parameters, + getHeaderWithAppCredentials(), + ); // Handle the response console.log(response); @@ -433,14 +482,14 @@ function getMembershipAppCred() { // [START chat_get_membership_user_cred] /** * This sample shows how to get membership with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.memberships.readonly' * referenced in the manifest file (appsscript.json). */ function getMembershipUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MEMBER_NAME here - const name = 'spaces/SPACE_NAME/members/MEMBER_NAME'; + const name = "spaces/SPACE_NAME/members/MEMBER_NAME"; // Make the request const response = Chat.Spaces.Members.get(name); @@ -453,18 +502,22 @@ function getMembershipUserCred() { // [START chat_get_message_app_cred] /** * This sample shows how to get message with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function getMessageAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; const parameters = {}; // Make the request - const response = Chat.Spaces.Messages.get(name, parameters, getHeaderWithAppCredentials()); + const response = Chat.Spaces.Messages.get( + name, + parameters, + getHeaderWithAppCredentials(), + ); // Handle the response console.log(response); @@ -474,14 +527,14 @@ function getMessageAppCred() { // [START chat_get_message_user_cred] /** * This sample shows how to get message with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.readonly' * referenced in the manifest file (appsscript.json). */ function getMessageUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; // Make the request const response = Chat.Spaces.Messages.get(name); @@ -494,18 +547,22 @@ function getMessageUserCred() { // [START chat_get_space_app_cred] /** * This sample shows how to get space with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function getSpaceAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const name = 'spaces/SPACE_NAME'; + const name = "spaces/SPACE_NAME"; const parameters = {}; // Make the request - const response = Chat.Spaces.get(name, parameters, getHeaderWithAppCredentials()); + const response = Chat.Spaces.get( + name, + parameters, + getHeaderWithAppCredentials(), + ); // Handle the response console.log(response); @@ -515,14 +572,14 @@ function getSpaceAppCred() { // [START chat_get_space_user_cred] /** * This sample shows how to get space with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.spaces.readonly' * referenced in the manifest file (appsscript.json). */ function getSpaceUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const name = 'spaces/SPACE_NAME'; + const name = "spaces/SPACE_NAME"; // Make the request const response = Chat.Spaces.get(name); @@ -535,14 +592,14 @@ function getSpaceUserCred() { // [START chat_list_memberships_app_cred] /** * This sample shows how to list memberships with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function listMembershipsAppCred() { -// Initialize request argument(s) + // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Filter membership by type (HUMAN or BOT) or role (ROLE_MEMBER or // ROLE_MANAGER) const filter = 'member.type = "HUMAN"'; @@ -552,14 +609,20 @@ function listMembershipsAppCred() { let pageToken = null; do { // Request response pages - responsePage = Chat.Spaces.Members.list(parent, { - filter: filter, - pageSize: 10, - pageToken: pageToken - }, getHeaderWithAppCredentials()); + responsePage = Chat.Spaces.Members.list( + parent, + { + filter: filter, + pageSize: 10, + pageToken: pageToken, + }, + getHeaderWithAppCredentials(), + ); // Handle response pages if (responsePage.memberships) { - responsePage.memberships.forEach((membership) => console.log(membership)); + for (const membership of responsePage.memberships) { + console.log(membership); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; @@ -570,14 +633,14 @@ function listMembershipsAppCred() { // [START chat_list_memberships_user_cred] /** * This sample shows how to list memberships with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.memberships.readonly' * referenced in the manifest file (appsscript.json). */ function listMembershipsUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Filter membership by type (HUMAN or BOT) or role (ROLE_MEMBER or // ROLE_MANAGER) const filter = 'member.type = "HUMAN"'; @@ -590,11 +653,13 @@ function listMembershipsUserCred() { responsePage = Chat.Spaces.Members.list(parent, { filter: filter, pageSize: 10, - pageToken: pageToken + pageToken: pageToken, }); // Handle response pages if (responsePage.memberships) { - responsePage.memberships.forEach((membership) => console.log(membership)); + for (const membership of responsePage.memberships) { + console.log(membership); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; @@ -605,14 +670,14 @@ function listMembershipsUserCred() { // [START chat_list_messages_user_cred] /** * This sample shows how to list messages with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages.readonly' * referenced in the manifest file (appsscript.json). */ function listMessagesUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const parent = 'spaces/SPACE_NAME'; + const parent = "spaces/SPACE_NAME"; // Iterate through the response pages using page tokens let responsePage; @@ -621,11 +686,13 @@ function listMessagesUserCred() { // Request response pages responsePage = Chat.Spaces.Messages.list(parent, { pageSize: 10, - pageToken: pageToken + pageToken: pageToken, }); // Handle response pages if (responsePage.messages) { - responsePage.messages.forEach((message) => console.log(message)); + for (const message of responsePage.messages) { + console.log(message); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; @@ -636,7 +703,7 @@ function listMessagesUserCred() { // [START chat_list_spaces_app_cred] /** * This sample shows how to list spaces with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ @@ -650,14 +717,19 @@ function listSpacesAppCred() { let pageToken = null; do { // Request response pages - responsePage = Chat.Spaces.list({ - filter: filter, - pageSize: 10, - pageToken: pageToken - }, getHeaderWithAppCredentials()); + responsePage = Chat.Spaces.list( + { + filter: filter, + pageSize: 10, + pageToken: pageToken, + }, + getHeaderWithAppCredentials(), + ); // Handle response pages if (responsePage.spaces) { - responsePage.spaces.forEach((space) => console.log(space)); + for (const space of responsePage.spaces) { + console.log(space); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; @@ -668,7 +740,7 @@ function listSpacesAppCred() { // [START chat_list_spaces_user_cred] /** * This sample shows how to list spaces with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.spaces.readonly' * referenced in the manifest file (appsscript.json). */ @@ -685,11 +757,13 @@ function listSpacesUserCred() { responsePage = Chat.Spaces.list({ filter: filter, pageSize: 10, - pageToken: pageToken + pageToken: pageToken, }); // Handle response pages if (responsePage.spaces) { - responsePage.spaces.forEach((space) => console.log(space)); + for (const space of responsePage.spaces) { + console.log(space); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; @@ -701,28 +775,33 @@ function listSpacesUserCred() { /** * This sample shows how to set up a named space with one initial member with * user credential. - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.spaces.create' * referenced in the manifest file (appsscript.json). */ function setUpSpaceUserCred() { // Initialize request argument(s) const space = { - spaceType: 'SPACE', + spaceType: "SPACE", // TODO(developer): Replace DISPLAY_NAME here - displayName: 'DISPLAY_NAME' + displayName: "DISPLAY_NAME", }; - const memberships = [{ - member: { - // TODO(developer): Replace USER_NAME here - name: 'users/USER_NAME', - // User type for the membership - type: 'HUMAN' - } - }]; + const memberships = [ + { + member: { + // TODO(developer): Replace USER_NAME here + name: "users/USER_NAME", + // User type for the membership + type: "HUMAN", + }, + }, + ]; // Make the request - const response = Chat.Spaces.setup({ space: space, memberships: memberships }); + const response = Chat.Spaces.setup({ + space: space, + memberships: memberships, + }); // Handle the response console.log(response); @@ -732,29 +811,41 @@ function setUpSpaceUserCred() { // [START chat_update_message_app_cred] /** * This sample shows how to update a message with app credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.bot' * used by service accounts. */ function updateMessageAppCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; const message = { - text: 'Text updated with app credential!', - cardsV2 : [{ card: { header: { - title: 'Card updated with app credential!', - imageUrl: 'https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg' - }}}] + text: "Text updated with app credential!", + cardsV2: [ + { + card: { + header: { + title: "Card updated with app credential!", + imageUrl: + "https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg", + }, + }, + }, + ], }; // The field paths to update. Separate multiple values with commas or use // `*` to update all field paths. - const updateMask = 'text,cardsV2'; + const updateMask = "text,cardsV2"; // Make the request - const response = Chat.Spaces.Messages.patch(message, name, { - updateMask: updateMask - }, getHeaderWithAppCredentials()); + const response = Chat.Spaces.Messages.patch( + message, + name, + { + updateMask: updateMask, + }, + getHeaderWithAppCredentials(), + ); // Handle the response console.log(response); @@ -764,24 +855,24 @@ function updateMessageAppCred() { // [START chat_update_message_user_cred] /** * This sample shows how to update a message with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.messages' * referenced in the manifest file (appsscript.json). */ function updateMessageUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME and MESSAGE_NAME here - const name = 'spaces/SPACE_NAME/messages/MESSAGE_NAME'; + const name = "spaces/SPACE_NAME/messages/MESSAGE_NAME"; const message = { - text: 'Updated with user credential!' + text: "Updated with user credential!", }; // The field paths to update. Separate multiple values with commas or use // `*` to update all field paths. - const updateMask = 'text'; + const updateMask = "text"; // Make the request const response = Chat.Spaces.Messages.patch(message, name, { - updateMask: updateMask + updateMask: updateMask, }); // Handle the response @@ -792,24 +883,24 @@ function updateMessageUserCred() { // [START chat_update_space_user_cred] /** * This sample shows how to update a space with user credential - * + * * It relies on the OAuth2 scope 'https://www.googleapis.com/auth/chat.spaces' * referenced in the manifest file (appsscript.json). */ function updateSpaceUserCred() { // Initialize request argument(s) // TODO(developer): Replace SPACE_NAME here - const name = 'spaces/SPACE_NAME'; + const name = "spaces/SPACE_NAME"; const space = { - displayName: 'New space display name' + displayName: "New space display name", }; // The field paths to update. Separate multiple values with commas or use // `*` to update all field paths. - const updateMask = 'displayName'; + const updateMask = "displayName"; // Make the request const response = Chat.Spaces.patch(space, name, { - updateMask: updateMask + updateMask: updateMask, }); // Handle the response diff --git a/chat/quickstart/Code.gs b/chat/quickstart/Code.gs index 5610da27d..783548120 100644 --- a/chat/quickstart/Code.gs +++ b/chat/quickstart/Code.gs @@ -33,11 +33,13 @@ function listSpaces() { // Request response pages responsePage = Chat.Spaces.list({ filter: filter, - pageToken: pageToken + pageToken: pageToken, }); // Handle response pages if (responsePage.spaces) { - responsePage.spaces.forEach((space) => console.log(space)); + for (const space of responsePage.spaces) { + console.log(space); + } } // Update the page token to the next one pageToken = responsePage.nextPageToken; diff --git a/classroom/quickstart/quickstart.gs b/classroom/quickstart/quickstart.gs index 1b61dc5fd..144efeaaf 100644 --- a/classroom/quickstart/quickstart.gs +++ b/classroom/quickstart/quickstart.gs @@ -22,7 +22,7 @@ function listCourses() { * @see https://developers.google.com/classroom/reference/rest/v1/courses/list */ const optionalArgs = { - pageSize: 10 + pageSize: 10, // Use other parameter here if needed }; try { @@ -30,17 +30,17 @@ function listCourses() { const response = Classroom.Courses.list(optionalArgs); const courses = response.courses; if (!courses || courses.length === 0) { - console.log('No courses found.'); + console.log("No courses found."); return; } // Print the course names and IDs of the courses for (const course of courses) { - console.log('%s (%s)', course.name, course.id); + console.log("%s (%s)", course.name, course.id); } } catch (err) { // TODO (developer)- Handle Courses.list() exception from Classroom API // get errors like PERMISSION_DENIED/INVALID_ARGUMENT/NOT_FOUND - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END classroom_quickstart] diff --git a/classroom/snippets/addAlias.gs b/classroom/snippets/addAlias.gs index b48888bd1..3fa494144 100644 --- a/classroom/snippets/addAlias.gs +++ b/classroom/snippets/addAlias.gs @@ -21,14 +21,18 @@ */ function addAlias(course_id) { const alias = { - 'alias': 'p:bio_101' + alias: "p:bio_101", }; try { - const course_alias = Classroom.Courses.Aliases.create(resource=alias, courseId=course_id); - console.log('%s successfully added as an alias!', course_alias.alias); + const course_alias = Classroom.Courses.Aliases.create(alias, course_id); + console.log("%s successfully added as an alias!", course_alias.alias); } catch (err) { // TODO (developer) - Handle exception - console.log('Request to add alias %s failed with error %s.', alias.alias, err.message); + console.log( + "Request to add alias %s failed with error %s.", + alias.alias, + err.message, + ); } } // [END classroom_add_alias] diff --git a/classroom/snippets/courseUpdate.gs b/classroom/snippets/courseUpdate.gs index ececcd627..89efe0539 100644 --- a/classroom/snippets/courseUpdate.gs +++ b/classroom/snippets/courseUpdate.gs @@ -23,14 +23,14 @@ function courseUpdate(courseId) { try { // Get the course using course ID let course = Classroom.Courses.get(courseId); - course.section = 'Period 3'; - course.room = '302'; + course.section = "Period 3"; + course.room = "302"; // Update the course course = Classroom.Courses.update(course, courseId); console.log('Course "%s" updated.', course.name); } catch (e) { // TODO (developer) - Handle exception - console.log('Failed to update the course with error %s', e.message); + console.log("Failed to update the course with error %s", e.message); } } // [END classroom_update_course] diff --git a/classroom/snippets/createAlias.gs b/classroom/snippets/createAlias.gs index 090342fde..a82e586b8 100644 --- a/classroom/snippets/createAlias.gs +++ b/classroom/snippets/createAlias.gs @@ -19,23 +19,28 @@ */ function createAlias() { let course = { - id: 'p:bio_101', - name: '10th Grade Biology', - section: 'Period 2', - descriptionHeading: 'Welcome to 10th Grade Biology', - description: 'We\'ll be learning about the structure of living creatures from a combination ' + - 'of textbooks, guest lectures, and lab work. Expect to be excited!', - room: '301', - ownerId: 'me', - courseState: 'PROVISIONED' + id: "p:bio_101", + name: "10th Grade Biology", + section: "Period 2", + descriptionHeading: "Welcome to 10th Grade Biology", + description: + "We'll be learning about the structure of living creatures from a combination " + + "of textbooks, guest lectures, and lab work. Expect to be excited!", + room: "301", + ownerId: "me", + courseState: "PROVISIONED", }; try { // Create the course using course details. course = Classroom.Courses.create(course); - console.log('Course created: %s (%s)', course.name, course.id); + console.log("Course created: %s (%s)", course.name, course.id); } catch (err) { // TODO (developer) - Handle Courses.create() exception - console.log('Failed to create course %s with an error %s', course.name, err.message); + console.log( + "Failed to create course %s with an error %s", + course.name, + err.message, + ); } } // [END classroom_create_alias] diff --git a/classroom/snippets/createCourse.gs b/classroom/snippets/createCourse.gs index 8aa5c87f3..1f4a6a04d 100644 --- a/classroom/snippets/createCourse.gs +++ b/classroom/snippets/createCourse.gs @@ -21,23 +21,28 @@ */ function createCourse() { let course = { - name: '10th Grade Biology', - section: 'Period 2', - descriptionHeading: 'Welcome to 10th Grade Biology', - description: 'We\'ll be learning about the structure of living creatures from a combination ' + - 'of textbooks, guest lectures, and lab work. Expect to be excited!', - room: '301', - ownerId: 'me', - courseState: 'PROVISIONED' + name: "10th Grade Biology", + section: "Period 2", + descriptionHeading: "Welcome to 10th Grade Biology", + description: + "We'll be learning about the structure of living creatures from a combination " + + "of textbooks, guest lectures, and lab work. Expect to be excited!", + room: "301", + ownerId: "me", + courseState: "PROVISIONED", }; try { // Create the course using course details. course = Classroom.Courses.create(course); - console.log('Course created: %s (%s)', course.name, course.id); + console.log("Course created: %s (%s)", course.name, course.id); return course.id; } catch (err) { // TODO (developer) - Handle Courses.create() exception - console.log('Failed to create course %s with an error %s', course.name, err.message); + console.log( + "Failed to create course %s with an error %s", + course.name, + err.message, + ); } } // [END classroom_create_course] diff --git a/classroom/snippets/getCourse.gs b/classroom/snippets/getCourse.gs index 25e1b3ffb..436f2d527 100644 --- a/classroom/snippets/getCourse.gs +++ b/classroom/snippets/getCourse.gs @@ -26,7 +26,11 @@ function getCourse(courseId) { console.log('Course "%s" found. ', course.name); } catch (err) { // TODO (developer) - Handle Courses.get() exception of Handle Classroom API - console.log('Failed to found course %s with error %s ', courseId, err.message); + console.log( + "Failed to found course %s with error %s ", + courseId, + err.message, + ); } } // [END classroom_get_course] diff --git a/classroom/snippets/listCourses.gs b/classroom/snippets/listCourses.gs index 474dd04ef..b5771c739 100644 --- a/classroom/snippets/listCourses.gs +++ b/classroom/snippets/listCourses.gs @@ -23,23 +23,23 @@ function listCourses() { const pageToken = null; const optionalArgs = { pageToken: pageToken, - pageSize: 100 + pageSize: 100, }; try { const response = Classroom.Courses.list(optionalArgs); courses = response.courses; if (courses.length === 0) { - console.log('No courses found.'); + console.log("No courses found."); return; } // Print the courses available in classroom - console.log('Courses:'); - for ( const course in courses) { - console.log('%s (%s)', courses[course].name, courses[course].id); + console.log("Courses:"); + for (const course in courses) { + console.log("%s (%s)", courses[course].name, courses[course].id); } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END classroom_list_courses] diff --git a/classroom/snippets/patchCourse.gs b/classroom/snippets/patchCourse.gs index 56d97978a..e9197b039 100644 --- a/classroom/snippets/patchCourse.gs +++ b/classroom/snippets/patchCourse.gs @@ -20,20 +20,15 @@ * @see https://developers.google.com/classroom/reference/rest/v1/courses/patch */ function coursePatch(courseId) { - let course = { - 'section': 'Period 3', - 'room': '302' + const course = { + section: "Period 3", + room: "302", }; - const mask = { - updateMask: 'section,room' + const options = { + updateMask: "section,room", }; - try { - // Update section and room in course. - course = Classroom.Courses.patch(body=course, id=courseId, updateMask=mask); - console.log('Course "%s" updated.', course.name); - } catch (err) { - // TODO (developer) - Handle Courses.patch() exception - console.log('Failed to update the course. Error message: %s', err.message); - } + // Update section and room in course. + const updatedCourse = Classroom.Courses.patch(course, courseId, options); + console.log(`Course "${updatedCourse.name}" updated.`); } // [END classroom_patch_course] diff --git a/classroom/snippets/test_classroom_snippets.gs b/classroom/snippets/test_classroom_snippets.gs index 7a024d6a6..dd7e8d480 100644 --- a/classroom/snippets/test_classroom_snippets.gs +++ b/classroom/snippets/test_classroom_snippets.gs @@ -19,7 +19,7 @@ * @return {string} courseId course id of created course */ function itShouldCreateCourse() { - console.log('> itShouldCreateCourse'); + console.log("> itShouldCreateCourse"); const courseId = createCourse(); return courseId; } @@ -29,7 +29,7 @@ function itShouldCreateCourse() { * @param {string} courseId course id */ function itShouldGetCourse(courseId) { - console.log('> itShouldGetCourse'); + console.log("> itShouldGetCourse"); getCourse(courseId); } @@ -37,7 +37,7 @@ function itShouldGetCourse(courseId) { * Tests createAlias function of createAlias.gs */ function itShouldCreateAlias() { - console.log('> itShouldCreateAlias'); + console.log("> itShouldCreateAlias"); createAlias(); } @@ -46,7 +46,7 @@ function itShouldCreateAlias() { * @param {string} courseId course id */ function itShouldAddAlias(courseId) { - console.log('> itShouldAddAlias'); + console.log("> itShouldAddAlias"); addAlias(courseId); } @@ -55,7 +55,7 @@ function itShouldAddAlias(courseId) { * @param {string} courseId course id */ function itShouldUpdateCourse(courseId) { - console.log('> itShouldUpdateCourse'); + console.log("> itShouldUpdateCourse"); courseUpdate(courseId); } @@ -64,7 +64,7 @@ function itShouldUpdateCourse(courseId) { * @param {string} courseId course id */ function itShouldPatchCourse(courseId) { - console.log('> itShouldPatchCourse'); + console.log("> itShouldPatchCourse"); coursePatch(courseId); } @@ -72,7 +72,7 @@ function itShouldPatchCourse(courseId) { * Tests listCourses function of listCourses.gs */ function itShouldListCourses() { - console.log('> itShouldListCourses'); + console.log("> itShouldListCourses"); listCourses(); } diff --git a/data-studio/auth.gs b/data-studio/auth.gs index c595c188a..e88476bd6 100644 --- a/data-studio/auth.gs +++ b/data-studio/auth.gs @@ -19,11 +19,9 @@ * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypeOAuth2() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.OAUTH2) - .build(); + return cc.newAuthTypeResponse().setAuthType(cc.AuthType.OAUTH2).build(); } // [END apps_script_data_studio_get_auth_type_oauth2] @@ -32,12 +30,13 @@ function getAuthType() { * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypePathUserPass() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.PATH_USER_PASS) - .setHelpUrl('https://www.example.org/connector-auth-help') - .build(); + return cc + .newAuthTypeResponse() + .setAuthType(cc.AuthType.PATH_USER_PASS) + .setHelpUrl("https://www.example.org/connector-auth-help") + .build(); } // [END apps_script_data_studio_get_auth_type_path_user_pass] @@ -46,12 +45,13 @@ function getAuthType() { * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypeUserPass() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.USER_PASS) - .setHelpUrl('https://www.example.org/connector-auth-help') - .build(); + return cc + .newAuthTypeResponse() + .setAuthType(cc.AuthType.USER_PASS) + .setHelpUrl("https://www.example.org/connector-auth-help") + .build(); } // [END apps_script_data_studio_get_auth_type_user_pass] @@ -60,12 +60,13 @@ function getAuthType() { * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypeUserToken() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.USER_TOKEN) - .setHelpUrl('https://www.example.org/connector-auth-help') - .build(); + return cc + .newAuthTypeResponse() + .setAuthType(cc.AuthType.USER_TOKEN) + .setHelpUrl("https://www.example.org/connector-auth-help") + .build(); } // [END apps_script_data_studio_get_auth_type_user_token] @@ -74,12 +75,13 @@ function getAuthType() { * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypeKey() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.KEY) - .setHelpUrl('https://www.example.org/connector-auth-help') - .build(); + return cc + .newAuthTypeResponse() + .setAuthType(cc.AuthType.KEY) + .setHelpUrl("https://www.example.org/connector-auth-help") + .build(); } // [END apps_script_data_studio_get_auth_type_key] @@ -88,11 +90,9 @@ function getAuthType() { * Returns the Auth Type of this connector. * @return {object} The Auth type. */ -function getAuthType() { +function getAuthTypeNone() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.NONE) - .build(); + return cc.newAuthTypeResponse().setAuthType(cc.AuthType.NONE).build(); } // [END apps_script_data_studio_get_auth_type_none] @@ -100,7 +100,7 @@ function getAuthType() { /** * Resets the auth service. */ -function resetAuth() { +function resetAuthOAuth2() { getOAuthService().reset(); } // [END apps_script_data_studio_auth_reset_oauth2] @@ -109,11 +109,11 @@ function resetAuth() { /** * Resets the auth service. */ -function resetAuth() { +function resetAuthPathUser() { const userProperties = PropertiesService.getUserProperties(); - userProperties.deleteProperty('dscc.path'); - userProperties.deleteProperty('dscc.username'); - userProperties.deleteProperty('dscc.password'); + userProperties.deleteProperty("dscc.path"); + userProperties.deleteProperty("dscc.username"); + userProperties.deleteProperty("dscc.password"); } // [END apps_script_data_studio_auth_reset_path_user] @@ -121,10 +121,10 @@ function resetAuth() { /** * Resets the auth service. */ -function resetAuth() { +function resetAuthUser() { const userProperties = PropertiesService.getUserProperties(); - userProperties.deleteProperty('dscc.username'); - userProperties.deleteProperty('dscc.password'); + userProperties.deleteProperty("dscc.username"); + userProperties.deleteProperty("dscc.password"); } // [END apps_script_data_studio_auth_reset_user] @@ -132,10 +132,10 @@ function resetAuth() { /** * Resets the auth service. */ -function resetAuth() { +function resetAuthUserToken() { const userTokenProperties = PropertiesService.getUserProperties(); - userTokenProperties.deleteProperty('dscc.username'); - userTokenProperties.deleteProperty('dscc.password'); + userTokenProperties.deleteProperty("dscc.username"); + userTokenProperties.deleteProperty("dscc.password"); } // [END apps_script_data_studio_auth_reset_user_token] @@ -143,9 +143,9 @@ function resetAuth() { /** * Resets the auth service. */ -function resetAuth() { +function resetAuthKey() { const userProperties = PropertiesService.getUserProperties(); - userProperties.deleteProperty('dscc.key'); + userProperties.deleteProperty("dscc.key"); } // [END apps_script_data_studio_auth_reset_key] @@ -154,7 +154,7 @@ function resetAuth() { * Returns true if the auth service has access. * @return {boolean} True if the auth service has access. */ -function isAuthValid() { +function isAuthValidOAuth2() { return getOAuthService().hasAccess(); } // [END apps_script_data_studio_auth_valid_oauth2] @@ -164,11 +164,11 @@ function isAuthValid() { * Returns true if the auth service has access. * @return {boolean} True if the auth service has access. */ -function isAuthValid() { +function isAuthValidPathUserPass() { const userProperties = PropertiesService.getUserProperties(); - const path = userProperties.getProperty('dscc.path'); - const userName = userProperties.getProperty('dscc.username'); - const password = userProperties.getProperty('dscc.password'); + const path = userProperties.getProperty("dscc.path"); + const userName = userProperties.getProperty("dscc.username"); + const password = userProperties.getProperty("dscc.password"); // This assumes you have a validateCredentials function that // can validate if the userName and password are correct. return validateCredentials(path, userName, password); @@ -180,10 +180,10 @@ function isAuthValid() { * Returns true if the auth service has access. * @return {boolean} True if the auth service has access. */ -function isAuthValid() { +function isAuthValidUserPass() { const userProperties = PropertiesService.getUserProperties(); - const userName = userProperties.getProperty('dscc.username'); - const password = userProperties.getProperty('dscc.password'); + const userName = userProperties.getProperty("dscc.username"); + const password = userProperties.getProperty("dscc.password"); // This assumes you have a validateCredentials function that // can validate if the userName and password are correct. return validateCredentials(userName, password); @@ -195,10 +195,10 @@ function isAuthValid() { * Returns true if the auth service has access. * @return {boolean} True if the auth service has access. */ -function isAuthValid() { +function isAuthValidUserToken() { const userProperties = PropertiesService.getUserProperties(); - const userName = userProperties.getProperty('dscc.username'); - const token = userProperties.getProperty('dscc.token'); + const userName = userProperties.getProperty("dscc.username"); + const token = userProperties.getProperty("dscc.token"); // This assumes you have a validateCredentials function that // can validate if the userName and token are correct. return validateCredentials(userName, token); @@ -210,9 +210,9 @@ function isAuthValid() { * Returns true if the auth service has access. * @return {boolean} True if the auth service has access. */ -function isAuthValid() { +function isAuthValidKey() { const userProperties = PropertiesService.getUserProperties(); - const key = userProperties.getProperty('dscc.key'); + const key = userProperties.getProperty("dscc.key"); // This assumes you have a validateKey function that can validate // if the key is valid. return validateKey(key); @@ -225,15 +225,15 @@ function isAuthValid() { * @return {Service} The OAuth Service */ function getOAuthService() { - return OAuth2.createService('exampleService') - .setAuthorizationBaseUrl('...') - .setTokenUrl('...') - .setClientId('...') - .setClientSecret('...') - .setPropertyStore(PropertiesService.getUserProperties()) - .setCallbackFunction('authCallback') - .setScope('...'); -}; + return OAuth2.createService("exampleService") + .setAuthorizationBaseUrl("...") + .setTokenUrl("...") + .setClientId("...") + .setClientSecret("...") + .setPropertyStore(PropertiesService.getUserProperties()) + .setCallbackFunction("authCallback") + .setScope("..."); +} // [END apps_script_data_studio_auth_library] // [START apps_script_data_studio_auth_callback] @@ -245,11 +245,10 @@ function getOAuthService() { function authCallback(request) { const authorized = getOAuthService().handleCallback(request); if (authorized) { - return HtmlService.createHtmlOutput('Success! You can close this tab.'); - } else { - return HtmlService.createHtmlOutput('Denied. You can close this tab'); - }; -}; + return HtmlService.createHtmlOutput("Success! You can close this tab."); + } + return HtmlService.createHtmlOutput("Denied. You can close this tab"); +} // [END apps_script_data_studio_auth_callback] // [START apps_script_data_studio_auth_urls] @@ -269,7 +268,7 @@ function get3PAuthorizationUrls() { * @param {Request} request The set credentials request. * @return {object} An object with an errorCode. */ -function setCredentials(request) { +function setCredentialsPathUserPass(request) { const creds = request.userPass; const path = creds.path; const username = creds.username; @@ -282,15 +281,15 @@ function setCredentials(request) { const validCreds = checkForValidCreds(path, username, password); if (!validCreds) { return { - errorCode: 'INVALID_CREDENTIALS' + errorCode: "INVALID_CREDENTIALS", }; } const userProperties = PropertiesService.getUserProperties(); - userProperties.setProperty('dscc.path', path); - userProperties.setProperty('dscc.username', username); - userProperties.setProperty('dscc.password', password); + userProperties.setProperty("dscc.path", path); + userProperties.setProperty("dscc.username", username); + userProperties.setProperty("dscc.password", password); return { - errorCode: 'NONE' + errorCode: "NONE", }; } // [END apps_script_data_studio_auth_set_credentials_path_user_pass] @@ -301,7 +300,7 @@ function setCredentials(request) { * @param {Request} request The set credentials request. * @return {object} An object with an errorCode. */ -function setCredentials(request) { +function setCredentialsUserPass(request) { const creds = request.userPass; const username = creds.username; const password = creds.password; @@ -313,14 +312,14 @@ function setCredentials(request) { const validCreds = checkForValidCreds(username, password); if (!validCreds) { return { - errorCode: 'INVALID_CREDENTIALS' + errorCode: "INVALID_CREDENTIALS", }; } const userProperties = PropertiesService.getUserProperties(); - userProperties.setProperty('dscc.username', username); - userProperties.setProperty('dscc.password', password); + userProperties.setProperty("dscc.username", username); + userProperties.setProperty("dscc.password", password); return { - errorCode: 'NONE' + errorCode: "NONE", }; } // [END apps_script_data_studio_auth_set_credentials_user_pass] @@ -331,7 +330,7 @@ function setCredentials(request) { * @param {Request} request The set credentials request. * @return {object} An object with an errorCode. */ -function setCredentials(request) { +function setCredentialsUserToken(request) { const creds = request.userToken; const username = creds.username; const token = creds.token; @@ -343,14 +342,14 @@ function setCredentials(request) { const validCreds = checkForValidCreds(username, token); if (!validCreds) { return { - errorCode: 'INVALID_CREDENTIALS' + errorCode: "INVALID_CREDENTIALS", }; } const userProperties = PropertiesService.getUserProperties(); - userProperties.setProperty('dscc.username', username); - userProperties.setProperty('dscc.token', token); + userProperties.setProperty("dscc.username", username); + userProperties.setProperty("dscc.token", token); return { - errorCode: 'NONE' + errorCode: "NONE", }; } // [END apps_script_data_studio_auth_set_credentials_user_token] @@ -361,7 +360,7 @@ function setCredentials(request) { * @param {Request} request The set credentials request. * @return {object} An object with an errorCode. */ -function setCredentials(request) { +function setCredentialsKey(request) { const key = request.key; // Optional @@ -371,13 +370,13 @@ function setCredentials(request) { const validKey = checkForValidKey(key); if (!validKey) { return { - errorCode: 'INVALID_CREDENTIALS' + errorCode: "INVALID_CREDENTIALS", }; } const userProperties = PropertiesService.getUserProperties(); - userProperties.setProperty('dscc.key', key); + userProperties.setProperty("dscc.key", key); return { - errorCode: 'NONE' + errorCode: "NONE", }; } // [END apps_script_data_studio_auth_set_credentials_key] diff --git a/data-studio/build.gs b/data-studio/build.gs index 82a6d1299..5484d8667 100644 --- a/data-studio/build.gs +++ b/data-studio/build.gs @@ -24,16 +24,18 @@ function getConfig() { const cc = DataStudioApp.createCommunityConnector(); const config = cc.getConfig(); - config.newInfo() - .setId('instructions') - .setText('Enter npm package names to fetch their download count.'); - - config.newTextInput() - .setId('package') - .setName('Enter a single package name.') - .setHelpText('for example, googleapis or lighthouse') - .setPlaceholder('googleapis') - .setAllowOverride(true); + config + .newInfo() + .setId("instructions") + .setText("Enter npm package names to fetch their download count."); + + config + .newTextInput() + .setId("package") + .setName("Enter a single package name.") + .setHelpText("for example, googleapis or lighthouse") + .setPlaceholder("googleapis") + .setAllowOverride(true); config.setDateRangeRequired(true); @@ -53,21 +55,24 @@ function getFields() { const types = cc.FieldType; const aggregations = cc.AggregationType; - fields.newDimension() - .setId('packageName') - .setName('Package Name') - .setType(types.TEXT); - - fields.newDimension() - .setId('day') - .setName('Day') - .setType(types.YEAR_MONTH_DAY); - - fields.newMetric() - .setId('downloads') - .setName('Downloads') - .setType(types.NUMBER) - .setAggregation(aggregations.SUM); + fields + .newDimension() + .setId("packageName") + .setName("Package Name") + .setType(types.TEXT); + + fields + .newDimension() + .setId("day") + .setName("Day") + .setType(types.YEAR_MONTH_DAY); + + fields + .newMetric() + .setId("downloads") + .setName("Downloads") + .setType(types.NUMBER) + .setAggregation(aggregations.SUM); return fields; } @@ -79,7 +84,7 @@ function getFields() { */ function getSchema(request) { const fields = getFields().build(); - return {'schema': fields}; + return { schema: fields }; } // [END apps_script_data_studio_build_get_fields] @@ -93,21 +98,24 @@ function getSchema(request) { */ function responseToRows(requestedFields, response, packageName) { // Transform parsed data and filter for requested fields - return response.map(function(dailyDownload) { - let row = []; - requestedFields.asArray().forEach(function(field) { + return response.map((dailyDownload) => { + const row = []; + for (const field of requestedFields.asArray()) { switch (field.getId()) { - case 'day': - return row.push(dailyDownload.day.replace(/-/g, '')); - case 'downloads': - return row.push(dailyDownload.downloads); - case 'packageName': - return row.push(packageName); + case "day": + row.push(dailyDownload.day.replace(/-/g, "")); + break; + case "downloads": + row.push(dailyDownload.downloads); + break; + case "packageName": + row.push(packageName); + break; default: - return row.push(''); + row.push(""); } - }); - return {values: row}; + } + return { values: row }; }); } @@ -117,27 +125,29 @@ function responseToRows(requestedFields, response, packageName) { * @return {object} The data. */ function getData(request) { - const requestedFieldIds = request.fields.map(function(field) { - return field.name; - }); + const requestedFieldIds = request.fields.map((field) => field.name); const requestedFields = getFields().forIds(requestedFieldIds); // Fetch and parse data from API const url = [ - 'https://api.npmjs.org/downloads/range/', + "https://api.npmjs.org/downloads/range/", request.dateRange.startDate, - ':', + ":", request.dateRange.endDate, - '/', - request.configParams.package + "/", + request.configParams.package, ]; - const response = UrlFetchApp.fetch(url.join('')); + const response = UrlFetchApp.fetch(url.join("")); const parsedResponse = JSON.parse(response).downloads; - const rows = responseToRows(requestedFields, parsedResponse, request.configParams.package); + const rows = responseToRows( + requestedFields, + parsedResponse, + request.configParams.package, + ); return { schema: requestedFields.build(), - rows: rows + rows: rows, }; } // [END apps_script_data_studio_build_get_data] @@ -149,8 +159,6 @@ function getData(request) { */ function getAuthType() { const cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.NONE) - .build(); + return cc.newAuthTypeResponse().setAuthType(cc.AuthType.NONE).build(); } // [END apps_script_data_studio_build_get_auth_type] diff --git a/data-studio/caas.gs b/data-studio/caas.gs index 26407dba2..637d8451d 100644 --- a/data-studio/caas.gs +++ b/data-studio/caas.gs @@ -15,21 +15,22 @@ */ // [START apps_script_data_studio_caas_example] -var sqlString = '' + - 'SELECT ' + - ' _TABLE_SUFFIX AS yyyymm, ' + - ' ROUND(SUM(IF(fcp.start < @fast_fcp, fcp.density, 0)), 4) AS fast_fcp, ' + - ' ROUND(SUM(IF(fcp.start >= 1000 AND fcp.start < 3000, fcp.density, 0)), 4) AS avg_fcp, ' + - ' ROUND(SUM(IF(fcp.start >= 3000, fcp.density, 0)), 4) AS slow_fcp ' + - 'FROM ' + - ' `chrome-ux-report.all.*`, ' + - ' UNNEST(first_contentful_paint.histogram.bin) AS fcp ' + - 'WHERE ' + - ' origin = @url ' + - 'GROUP BY ' + - ' yyyymm ' + - 'ORDER BY ' + - ' yyyymm '; +const sqlString = + "" + + "SELECT " + + " _TABLE_SUFFIX AS yyyymm, " + + " ROUND(SUM(IF(fcp.start < @fast_fcp, fcp.density, 0)), 4) AS fast_fcp, " + + " ROUND(SUM(IF(fcp.start >= 1000 AND fcp.start < 3000, fcp.density, 0)), 4) AS avg_fcp, " + + " ROUND(SUM(IF(fcp.start >= 3000, fcp.density, 0)), 4) AS slow_fcp " + + "FROM " + + " `chrome-ux-report.all.*`, " + + " UNNEST(first_contentful_paint.histogram.bin) AS fcp " + + "WHERE " + + " origin = @url " + + "GROUP BY " + + " yyyymm " + + "ORDER BY " + + " yyyymm "; /** * Gets the config. @@ -37,19 +38,21 @@ var sqlString = '' + * @return {Config} The Community Connector config. */ function getConfig(request) { - var cc = DataStudioApp.createCommunityConnector(); - var config = cc.getConfig(); + const cc = DataStudioApp.createCommunityConnector(); + const config = cc.getConfig(); - config.newTextInput() - .setId('projectId') - .setName('BigQuery Billing Project ID') - .setPlaceholder('556727765207'); + config + .newTextInput() + .setId("projectId") + .setName("BigQuery Billing Project ID") + .setPlaceholder("556727765207"); - config.newTextInput() - .setId('url') - .setName('Enter your url') - .setAllowOverride(true) - .setPlaceholder('www.example.com'); + config + .newTextInput() + .setId("url") + .setName("Enter your url") + .setAllowOverride(true) + .setPlaceholder("www.example.com"); config.setDateRangeRequired(true); @@ -62,29 +65,29 @@ function getConfig(request) { * @return {Fields} The Community Connector fields. */ function getFields() { - var cc = DataStudioApp.createCommunityConnector(); - var fields = cc.getFields(); - var types = cc.FieldType; + const cc = DataStudioApp.createCommunityConnector(); + const fields = cc.getFields(); + const types = cc.FieldType; - fields.newDimension() - .setId('yyyymm') - .setName('yyyymm') - .setType(types.YEAR_MONTH); + fields + .newDimension() + .setId("yyyymm") + .setName("yyyymm") + .setType(types.YEAR_MONTH); - fields.newMetric() - .setId('fast_fcp') - .setName('fast_fcp') - .setType(types.NUMBER); + fields + .newMetric() + .setId("fast_fcp") + .setName("fast_fcp") + .setType(types.NUMBER); - fields.newMetric() - .setId('avg_fcp') - .setName('avg_fcp') - .setType(types.NUMBER); + fields.newMetric().setId("avg_fcp").setName("avg_fcp").setType(types.NUMBER); - fields.newMetric() - .setId('slow_fcp') - .setName('slow_fcp') - .setType(types.NUMBER); + fields + .newMetric() + .setId("slow_fcp") + .setName("slow_fcp") + .setType(types.NUMBER); return fields; } @@ -96,7 +99,7 @@ function getFields() { */ function getSchema(request) { return { - schema: getFields().build() + schema: getFields().build(), }; } @@ -106,38 +109,41 @@ function getSchema(request) { * @return {object} The data response. */ function getData(request) { - var url = (request.configParams && request.configParams.url); - var projectId = (request.configParams && request.configParams.projectId); - var authToken = ScriptApp.getOAuthToken(); - var response = { + const url = request.configParams?.url; + const projectId = request.configParams?.projectId; + const authToken = ScriptApp.getOAuthToken(); + const response = { dataConfig: { - type: 'BIGQUERY', + type: "BIGQUERY", bigQueryConnectorConfig: { billingProjectId: projectId, query: sqlString, useStandardSql: true, - queryParameters: [{ - name: 'url', - parameterType: { - type: 'STRING' + queryParameters: [ + { + name: "url", + parameterType: { + type: "STRING", + }, + parameterValue: { + value: url, + }, }, - parameterValue: { - value: url - } - }, { - name: 'fast_fcp', - parameterType: { - type: 'INT64' + { + name: "fast_fcp", + parameterType: { + type: "INT64", + }, + parameterValue: { + value: `${1000}`, + }, }, - parameterValue: { - value: '' + 1000 - } - }] - } + ], + }, }, authConfig: { - accessToken: authToken - } + accessToken: authToken, + }, }; return response; } @@ -147,9 +153,7 @@ function getData(request) { * @return {object} The auth type. */ function getAuthType() { - var cc = DataStudioApp.createCommunityConnector(); - return cc.newAuthTypeResponse() - .setAuthType(cc.AuthType.NONE) - .build(); + const cc = DataStudioApp.createCommunityConnector(); + return cc.newAuthTypeResponse().setAuthType(cc.AuthType.NONE).build(); } // [END apps_script_data_studio_caas_example] diff --git a/data-studio/data-source.gs b/data-studio/data-source.gs index 349f10e76..df7f8046a 100644 --- a/data-studio/data-source.gs +++ b/data-studio/data-source.gs @@ -15,41 +15,41 @@ */ // [START apps_script_data_studio_params] -var configParams = [ +const configParams = [ { - type: 'TEXTINPUT', - name: 'ZipCode', - displayName: 'ZIP Code', + type: "TEXTINPUT", + name: "ZipCode", + displayName: "ZIP Code", parameterControl: { - allowOverride: true - } + allowOverride: true, + }, }, { - type: 'SELECT_SINGLE', - name: 'units', - displayName: 'Units', + type: "SELECT_SINGLE", + name: "units", + displayName: "Units", parameterControl: { - allowOverride: true + allowOverride: true, }, options: [ { - label: 'Metric', - value: 'metric' + label: "Metric", + value: "metric", }, { - label: 'Imperial', - value: 'imperial' + label: "Imperial", + value: "imperial", }, { - label: 'Kelvin', - value: 'kelvin' - } - ] + label: "Kelvin", + value: "kelvin", + }, + ], }, { - type: 'TEXTINPUT', - name: 'Days', - displayName: 'Days to forecast' - } + type: "TEXTINPUT", + name: "Days", + displayName: "Days to forecast", + }, ]; // [END apps_script_data_studio_params] diff --git a/data-studio/errors.gs b/data-studio/errors.gs index f48fd1a7c..e1a65eed1 100644 --- a/data-studio/errors.gs +++ b/data-studio/errors.gs @@ -15,18 +15,23 @@ */ // [START apps_script_data_studio_error_ds_user] -// Admin and non-admin users will see the following error. -try { - // Code that might fail. -} catch (e) { - throw new Error('DS_USER:This will be shown to admin & non-admin.'); +function showErrorToAllUsers() { + try { + // Code that might fail. + throw new Error("Something went wrong"); + } catch (e) { + throw new Error("DS_USER:This will be shown to admin & non-admin."); + } } -// Only admin users will see the following error. -try { - // Code that might fail. -} catch (e) { - throw new Error('This message will only be shown to admin users'); +function showErrorToAdminUsers() { + // Only admin users will see the following error. + try { + // Code that might fail. + throw new Error("Something went wrong"); + } catch (e) { + throw new Error("This message will only be shown to admin users"); + } } // [END apps_script_data_studio_error_ds_user] @@ -39,13 +44,16 @@ try { * otherwise. false by default. */ function throwConnectorError(message, userSafe) { - userSafe = (typeof userSafe !== 'undefined' && - typeof userSafe === 'boolean') ? userSafe : false; - if (userSafe) { - message = 'DS_USER:' + message; + let safeMessage = message; + const isUserSafe = + typeof userSafe !== "undefined" && typeof userSafe === "boolean" + ? userSafe + : false; + if (isUserSafe) { + safeMessage = `DS_USER:${message}`; } - throw new Error(message); + throw new Error(safeMessage); } // [END apps_script_data_studio_error_helper] @@ -58,20 +66,28 @@ function throwConnectorError(message, userSafe) { */ function logConnectorError(originalError, message) { const logEntry = [ - 'Original error (Message): ', + "Original error (Message): ", originalError, - '(', message, ')' + "(", + message, + ")", ]; - console.error(logEntry.join('')); // Log to Stackdriver. + console.error(logEntry.join("")); // Log to Stackdriver. } // [END apps_script_data_studio_error_logging] // [START apps_script_data_studio_error_error] -// Error message that will be shown to a non-admin users. -try { - // Code that might fail. -} catch (e) { - logConnectorError(e, 'quota_hour_exceeded'); // Log to Stackdriver. - throwConnectorError('You\'ve exceeded the hourly quota. Try again later.', true); +function showErrorToNonAdminUsers() { + // Error message that will be shown to a non-admin users. + try { + // Code that might fail. + throw new Error("Something went wrong"); + } catch (e) { + logConnectorError(e, "quota_hour_exceeded"); // Log to Stackdriver. + throwConnectorError( + "You've exceeded the hourly quota. Try again later.", + true, + ); + } } // [END apps_script_data_studio_error_error] diff --git a/data-studio/links.gs b/data-studio/links.gs index 93dec8118..f837de089 100644 --- a/data-studio/links.gs +++ b/data-studio/links.gs @@ -16,20 +16,20 @@ // [START apps_script_data_studio_links] // These variables should be filled in as necessary for your connector. -var configJSON; -var templateId; -var deploymentId; +let configJSON; +let templateId; +let deploymentId; -var params = []; +const params = []; const jsonString = JSON.stringify(configJSON); const encoded = encodeURIComponent(jsonString); -params.push('connectorConfig=' + encoded); +params.push(`connectorConfig=${encoded}`); -params.push('reportTemplateId=' + templateId); +params.push(`reportTemplateId=${templateId}`); -params.push('connectorId=' + deploymentId); +params.push(`connectorId=${deploymentId}`); -const joinedParams = params.join('&'); -const URL = 'https://datastudio.google.com/datasources/create?' + joinedParams; +const joinedParams = params.join("&"); +const URL = `https://datastudio.google.com/datasources/create?${joinedParams}`; // [END apps_script_data_studio_links] diff --git a/data-studio/semantics.gs b/data-studio/semantics.gs index 8b6af6837..aeea28370 100644 --- a/data-studio/semantics.gs +++ b/data-studio/semantics.gs @@ -17,23 +17,24 @@ // [START apps_script_data_studio_manual] const schema = [ { - 'name': 'Income', - 'label': 'Income (in USD)', - 'dataType': 'NUMBER', - 'semantics': { - 'conceptType': 'METRIC', - 'semanticGroup': 'CURRENCY', - 'semanticType': 'CURRENCY_USD' - } - }, { - 'name': 'Filing Year', - 'label': 'Year in which you filed the taxes.', - 'dataType': 'STRING', - 'semantics': { - 'conceptType': 'METRIC', - 'semanticGroup': 'DATE_OR_TIME', - 'semanticType': 'YEAR' - } - } + name: "Income", + label: "Income (in USD)", + dataType: "NUMBER", + semantics: { + conceptType: "METRIC", + semanticGroup: "CURRENCY", + semanticType: "CURRENCY_USD", + }, + }, + { + name: "Filing Year", + label: "Year in which you filed the taxes.", + dataType: "STRING", + semantics: { + conceptType: "METRIC", + semanticGroup: "DATE_OR_TIME", + semanticType: "YEAR", + }, + }, ]; // [END apps_script_data_studio_manual] diff --git a/docs/cursorInspector/cursorInspector.gs b/docs/cursorInspector/cursorInspector.gs index a4fa4c810..65ed3a113 100644 --- a/docs/cursorInspector/cursorInspector.gs +++ b/docs/cursorInspector/cursorInspector.gs @@ -16,8 +16,9 @@ * Runs when the document is opened. */ function onOpen() { - DocumentApp.getUi().createMenu('Inspector') - .addItem('Show sidebar', 'showSidebar') + DocumentApp.getUi() + .createMenu("Inspector") + .addItem("Show sidebar", "showSidebar") .addToUi(); } @@ -26,9 +27,11 @@ function onOpen() { */ function showSidebar() { DocumentApp.getUi().showSidebar( - HtmlService.createTemplateFromFile('Sidebar').evaluate() - .setTitle('Cursor Inspector') - .setWidth(350)); + HtmlService.createTemplateFromFile("Sidebar") + .evaluate() + .setTitle("Cursor Inspector") + .setWidth(350), + ); } /** @@ -45,28 +48,28 @@ function include(file) { * @return {Object} The infomration. */ function getDocumentInfo() { - var document = DocumentApp.getActiveDocument(); - var cursor = document.getCursor(); - var selection = document.getSelection(); - var result = {}; + const document = DocumentApp.getActiveDocument(); + const cursor = document.getCursor(); + const selection = document.getSelection(); + const result = {}; if (cursor) { result.cursor = { element: getElementInfo(cursor.getElement()), offset: cursor.getOffset(), surroundingText: cursor.getSurroundingText().getText(), - surroundingTextOffset: cursor.getSurroundingTextOffset() + surroundingTextOffset: cursor.getSurroundingTextOffset(), }; } if (selection) { result.selection = { - selectedElements: selection.getSelectedElements().map(function(selectedElement) { - return { + selectedElements: selection + .getSelectedElements() + .map((selectedElement) => ({ element: getElementInfo(selectedElement.getElement()), partial: selectedElement.isPartial(), startOffset: selectedElement.getStartOffset(), - endOffsetInclusive: selectedElement.getEndOffsetInclusive() - }; - }) + endOffsetInclusive: selectedElement.getEndOffsetInclusive(), + })), }; } return result; @@ -79,6 +82,6 @@ function getDocumentInfo() { */ function getElementInfo(element) { return { - type: String(element.getType()) + type: String(element.getType()), }; } diff --git a/docs/dialog2sidebar/Code.gs b/docs/dialog2sidebar/Code.gs index 0d91872ed..4de8c366f 100644 --- a/docs/dialog2sidebar/Code.gs +++ b/docs/dialog2sidebar/Code.gs @@ -18,18 +18,19 @@ * Runs when the document opens, populating the menu. */ function onOpen() { - DocumentApp.getUi().createMenu('Sidebar') - .addItem('Show', 'showSidebar') - .addToUi(); + DocumentApp.getUi() + .createMenu("Sidebar") + .addItem("Show", "showSidebar") + .addToUi(); } /** * Shows the sidebar in the document. */ function showSidebar() { - var page = HtmlService.createTemplateFromFile('Sidebar') - .evaluate() - .setTitle('Sidebar'); + const page = HtmlService.createTemplateFromFile("Sidebar") + .evaluate() + .setTitle("Sidebar"); DocumentApp.getUi().showSidebar(page); } @@ -38,11 +39,10 @@ function showSidebar() { * @return {string} The dialog ID. */ function openDialog() { - var dialogId = Utilities.base64Encode(Math.random()); - var template = HtmlService.createTemplateFromFile('Dialog'); + const dialogId = Utilities.base64Encode(Math.random()); + const template = HtmlService.createTemplateFromFile("Dialog"); template.dialogId = dialogId; - var page = template.evaluate() - .setTitle('Dialog'); + const page = template.evaluate().setTitle("Dialog"); DocumentApp.getUi().showDialog(page); return dialogId; } diff --git a/docs/quickstart/quickstart.gs b/docs/quickstart/quickstart.gs index 5ef105882..bf5e059c6 100644 --- a/docs/quickstart/quickstart.gs +++ b/docs/quickstart/quickstart.gs @@ -20,8 +20,8 @@ * @see https://developers.google.com/docs/api/reference/rest/v1/documents/get */ function printDocTitle() { - const documentId = '195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE'; - const doc = Docs.Documents.get(documentId, {'includeTabsContent': true}); + const documentId = "195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE"; + const doc = Docs.Documents.get(documentId, { includeTabsContent: true }); console.log(`The title of the doc is: ${doc.title}`); } // [END docs_quickstart] diff --git a/docs/translate/translate.gs b/docs/translate/translate.gs index 38f7fc5b9..56729bb17 100644 --- a/docs/translate/translate.gs +++ b/docs/translate/translate.gs @@ -34,9 +34,10 @@ * running in, inspect e.authMode. */ function onOpen(e) { - DocumentApp.getUi().createAddonMenu() - .addItem('Start', 'showSidebar') - .addToUi(); + DocumentApp.getUi() + .createAddonMenu() + .addItem("Start", "showSidebar") + .addToUi(); } /** @@ -60,8 +61,8 @@ function onInstall(e) { * the mobile add-on version. */ function showSidebar() { - const ui = HtmlService.createHtmlOutputFromFile('sidebar') - .setTitle('Translate'); + const ui = + HtmlService.createHtmlOutputFromFile("sidebar").setTitle("Translate"); DocumentApp.getUi().showSidebar(ui); } @@ -98,7 +99,7 @@ function getSelectedText() { } } } - if (!text.length) throw new Error('Please select some text.'); + if (!text.length) throw new Error("Please select some text."); return text; } @@ -114,8 +115,8 @@ function getSelectedText() { function getPreferences() { const userProperties = PropertiesService.getUserProperties(); return { - originLang: userProperties.getProperty('originLang'), - destLang: userProperties.getProperty('destLang') + originLang: userProperties.getProperty("originLang"), + destLang: userProperties.getProperty("destLang"), }; } @@ -136,13 +137,13 @@ function getPreferences() { function getTextAndTranslation(origin, dest, savePrefs) { if (savePrefs) { PropertiesService.getUserProperties() - .setProperty('originLang', origin) - .setProperty('destLang', dest); + .setProperty("originLang", origin) + .setProperty("destLang", dest); } - const text = getSelectedText().join('\n'); + const text = getSelectedText().join("\n"); return { text: text, - translation: translateText(text, origin, dest) + translation: translateText(text, origin, dest), }; } @@ -160,9 +161,12 @@ function insertText(newText) { if (selection) { let replaced = false; const elements = selection.getSelectedElements(); - if (elements.length === 1 && elements[0].getElement().getType() === - DocumentApp.ElementType.INLINE_IMAGE) { - throw new Error('Can\'t insert text into an image.'); + if ( + elements.length === 1 && + elements[0].getElement().getType() === + DocumentApp.ElementType.INLINE_IMAGE + ) { + throw new Error("Can't insert text into an image."); } for (let i = 0; i < elements.length; ++i) { if (elements[i].isPartial()) { @@ -215,17 +219,20 @@ function insertText(newText) { // If the cursor follows or preceds a non-space character, insert a space // between the character and the translation. Otherwise, just insert the // translation. - if (surroundingTextOffset > 0) { - if (surroundingText.charAt(surroundingTextOffset - 1) !== ' ') { - newText = ' ' + newText; + let textToInsert = newText; + if (surroundingText) { + if (surroundingTextOffset > 0) { + if (surroundingText.charAt(surroundingTextOffset - 1) !== " ") { + textToInsert = ` ${textToInsert}`; + } } - } - if (surroundingTextOffset < surroundingText.length) { - if (surroundingText.charAt(surroundingTextOffset) !== ' ') { - newText += ' '; + if (surroundingTextOffset < surroundingText.length) { + if (surroundingText.charAt(surroundingTextOffset) !== " ") { + textToInsert += " "; + } } } - cursor.insertText(newText); + cursor.insertText(textToInsert); } } diff --git a/drive/activity-v2/quickstart.gs b/drive/activity-v2/quickstart.gs index 662d2060b..792bf13e5 100644 --- a/drive/activity-v2/quickstart.gs +++ b/drive/activity-v2/quickstart.gs @@ -20,7 +20,7 @@ */ function listDriveActivity() { const request = { - pageSize: 10 + pageSize: 10, // Use other parameter here if needed. }; try { @@ -28,10 +28,10 @@ function listDriveActivity() { const response = DriveActivity.Activity.query(request); const activities = response.activities; if (!activities || activities.length === 0) { - console.log('No activity.'); + console.log("No activity."); return; } - console.log('Recent activity:'); + console.log("Recent activity:"); for (const activity of activities) { // get time information of activity. const time = getTimeInfo(activity); @@ -42,11 +42,11 @@ function listDriveActivity() { // get target information of activity. const targets = activity.targets.map(getTargetInfo); // print the time,actor,action and targets of drive activity. - console.log('%s: %s, %s, %s', time, actors, action, targets); + console.log("%s: %s, %s, %s", time, actors, action, targets); } } catch (err) { // TODO (developer) - Handle error from drive activity API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -58,7 +58,7 @@ function getOneOf(object) { for (const key in object) { return key; } - return 'unknown'; + return "unknown"; } /** @@ -66,13 +66,13 @@ function getOneOf(object) { * @return {string} Returns a time associated with an activity. */ function getTimeInfo(activity) { - if ('timestamp' in activity) { + if ("timestamp" in activity) { return activity.timestamp; } - if ('timeRange' in activity) { + if ("timeRange" in activity) { return activity.timeRange.endTime; } - return 'unknown'; + return "unknown"; } /** @@ -88,10 +88,10 @@ function getActionInfo(actionDetail) { * @return {string} Returns user information, or the type of user if not a known user. */ function getUserInfo(user) { - if ('knownUser' in user) { + if ("knownUser" in user) { const knownUser = user.knownUser; const isMe = knownUser.isCurrentUser || false; - return isMe ? 'people/me' : knownUser.personName; + return isMe ? "people/me" : knownUser.personName; } return getOneOf(user); } @@ -101,7 +101,7 @@ function getUserInfo(user) { * @return {string} Returns actor information, or the type of actor if not a user. */ function getActorInfo(actor) { - if ('user' in actor) { + if ("user" in actor) { return getUserInfo(actor.user); } return getOneOf(actor); @@ -112,19 +112,19 @@ function getActorInfo(actor) { * @return {string} Returns the type of a target and an associated title. */ function getTargetInfo(target) { - if ('driveItem' in target) { - const title = target.driveItem.title || 'unknown'; - return 'driveItem:"' + title + '"'; + if ("driveItem" in target) { + const title = target.driveItem.title || "unknown"; + return `driveItem:"${title}"`; } - if ('drive' in target) { - const title = target.drive.title || 'unknown'; - return 'drive:"' + title + '"'; + if ("drive" in target) { + const title = target.drive.title || "unknown"; + return `drive:"${title}"`; } - if ('fileComment' in target) { + if ("fileComment" in target) { const parent = target.fileComment.parent || {}; - const title = parent.title || 'unknown'; - return 'fileComment:"' + title + '"'; + const title = parent.title || "unknown"; + return `fileComment:"${title}"`; } - return getOneOf(target) + ':unknown'; + return `${getOneOf(target)}:unknown`; } // [END drive_activity_v2_quickstart] diff --git a/drive/activity/quickstart.gs b/drive/activity/quickstart.gs index c3fbf0fed..8b6c6f912 100644 --- a/drive/activity/quickstart.gs +++ b/drive/activity/quickstart.gs @@ -18,30 +18,35 @@ * Lists activity for a Drive user. */ function listActivity() { - var optionalArgs = { - 'source': 'drive.google.com', - 'drive.ancestorId': 'root', - 'pageSize': 10 + const optionalArgs = { + source: "drive.google.com", + "drive.ancestorId": "root", + pageSize: 10, }; - var response = AppsActivity.Activities.list(optionalArgs); - var activities = response.activities; + const response = AppsActivity.Activities.list(optionalArgs); + const activities = response.activities; if (activities && activities.length > 0) { - console.log('Recent activity:'); + console.log("Recent activity:"); for (i = 0; i < activities.length; i++) { - var activity = activities[i]; - var event = activity.combinedEvent; - var user = event.user; - var target = event.target; + const activity = activities[i]; + const event = activity.combinedEvent; + const user = event.user; + const target = event.target; if (user == null || target == null) { - continue; } else { - var time = new Date(Number(event.eventTimeMillis)); - console.log('%s: %s, %s, %s (%s)', time, user.name, - event.primaryEventType, target.name, target.mimeType); + const time = new Date(Number(event.eventTimeMillis)); + console.log( + "%s: %s, %s, %s (%s)", + time, + user.name, + event.primaryEventType, + target.name, + target.mimeType, + ); } } } else { - console.log('No recent activity'); + console.log("No recent activity"); } } // [END drive_activity_quickstart] diff --git a/drive/quickstart/quickstart.gs b/drive/quickstart/quickstart.gs index 47087ec83..d075b68da 100644 --- a/drive/quickstart/quickstart.gs +++ b/drive/quickstart/quickstart.gs @@ -21,16 +21,16 @@ function listFiles() { try { // Files.list method returns the list of files in drive. const files = Drive.Files.list({ - fields: 'nextPageToken, items(id, title)', - maxResults: 10 + fields: "nextPageToken, items(id, title)", + maxResults: 10, }).items; // Print the title and id of files available in drive for (const file of files) { - console.log('%s (%s)', file.title, file.id); + console.log("%s (%s)", file.title, file.id); } } catch (err) { // TODO(developer)-Handle Files.list() exception - console.log('failed with error %s', err.message); + console.log("failed with error %s", err.message); } } // [END drive_quickstart] diff --git a/forms-api/demos/AppsScriptFormsAPIWebApp/Code.gs b/forms-api/demos/AppsScriptFormsAPIWebApp/Code.gs index aa0a5f9e2..bd1b47bd6 100644 --- a/forms-api/demos/AppsScriptFormsAPIWebApp/Code.gs +++ b/forms-api/demos/AppsScriptFormsAPIWebApp/Code.gs @@ -13,5 +13,5 @@ // limitations under the License. function doGet() { - return HtmlService.createTemplateFromFile('Main').evaluate(); -} \ No newline at end of file + return HtmlService.createTemplateFromFile("Main").evaluate(); +} diff --git a/forms-api/demos/AppsScriptFormsAPIWebApp/FormsAPI.gs b/forms-api/demos/AppsScriptFormsAPIWebApp/FormsAPI.gs index 6e36d003c..2c778531f 100644 --- a/forms-api/demos/AppsScriptFormsAPIWebApp/FormsAPI.gs +++ b/forms-api/demos/AppsScriptFormsAPIWebApp/FormsAPI.gs @@ -13,11 +13,11 @@ // limitations under the License. // Global constants. Customize as needed. -const formsAPIUrl = 'https://forms.googleapis.com/v1/forms/'; -const formId = ''; -const topicName = 'projects/'; +const formsAPIUrl = "https://forms.googleapis.com/v1/forms/"; +const formId = ""; +const topicName = "projects/"; -// To setup pub/sub topics, see: +// To setup pub/sub topics, see: // https://cloud.google.com/pubsub/docs/building-pubsub-messaging-system /** @@ -28,24 +28,24 @@ function create(title) { const accessToken = ScriptApp.getOAuthToken(); const jsonTitle = JSON.stringify({ info: { - title: title - } + title: title, + }, }); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken + headers: { + Authorization: `Bearer ${accessToken}`, }, - 'method': 'post', - 'contentType': 'application/json', - 'payload': jsonTitle + method: "post", + contentType: "application/json", + payload: jsonTitle, }; - console.log('Forms API POST options was: ' + JSON.stringify(options)); + console.log(`Forms API POST options was: ${JSON.stringify(options)}`); const response = UrlFetchApp.fetch(formsAPIUrl, options); - console.log('Response from Forms API was: ' + JSON.stringify(response)); + console.log(`Response from Forms API was: ${JSON.stringify(response)}`); - return ('' + response); + return `${response}`; } /** @@ -56,21 +56,20 @@ function get(formId) { const accessToken = ScriptApp.getOAuthToken(); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'get' + method: "get", }; try { const response = UrlFetchApp.fetch(formsAPIUrl + formId, options); - console.log('Response from Forms API was: ' + response); - return ('' + response); + console.log(`Response from Forms API was: ${response}`); + return `${response}`; } catch (e) { console.log(JSON.stringify(e)); - return ('Error:' + JSON.stringify(e) + - '

Unable to find Form with formId:
' + formId); + return `Error:${JSON.stringify(e)}

Unable to find Form with formId:
${formId}`; } } @@ -83,30 +82,35 @@ function batchUpdate(formId) { // Request body to add a description to a Form const update = { - 'requests': [{ - 'updateFormInfo': { - 'info': { - 'description': 'Please complete this quiz based on this week\'s readings for class.' + requests: [ + { + updateFormInfo: { + info: { + description: + "Please complete this quiz based on this week's readings for class.", + }, + updateMask: "description", }, - 'updateMask': 'description' - } - }] - } + }, + ], + }; const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken + headers: { + Authorization: `Bearer ${accessToken}`, }, - 'method': 'post', - 'contentType': 'application/json', - 'payload': JSON.stringify(update), - 'muteHttpExceptions': true, + method: "post", + contentType: "application/json", + payload: JSON.stringify(update), + muteHttpExceptions: true, }; - const response = UrlFetchApp.fetch(formsAPIUrl + formId + ':batchUpdate', - options); - console.log('Response code from API: ' + response.getResponseCode()); - return (response.getResponseCode()); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}:batchUpdate`, + options, + ); + console.log(`Response code from API: ${response.getResponseCode()}`); + return response.getResponseCode(); } /** @@ -117,21 +121,23 @@ function responsesGet(formId, responseId) { const accessToken = ScriptApp.getOAuthToken(); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'get' + method: "get", }; try { - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'responses/' + - responseId, options); - console.log('Response from Forms.responses.get was: ' + response); - return ('' + response); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/responses/${responseId}`, + options, + ); + console.log(`Response from Forms.responses.get was: ${response}`); + return `${response}`; } catch (e) { console.log(JSON.stringify(e)); - return ('Error:' + JSON.stringify(e)) + return `Error:${JSON.stringify(e)}`; } } @@ -143,21 +149,23 @@ function responsesList(formId) { const accessToken = ScriptApp.getOAuthToken(); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'get' + method: "get", }; try { - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'responses', - options); - console.log('Response from Forms.responses was: ' + response); - return ('' + response); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/responses`, + options, + ); + console.log(`Response from Forms.responses was: ${response}`); + return `${response}`; } catch (e) { console.log(JSON.stringify(e)); - return ('Error:' + JSON.stringify(e)) + return `Error:${JSON.stringify(e)}`; } } @@ -169,33 +177,35 @@ function createWatch(formId) { const accessToken = ScriptApp.getOAuthToken(); const myWatch = { - 'watch': { - 'target': { - 'topic': { - 'topicName': topicName - } + watch: { + target: { + topic: { + topicName: topicName, + }, }, - 'eventType': 'RESPONSES', - } + eventType: "RESPONSES", + }, }; - console.log('myWatch is: ' + JSON.stringify(myWatch)); + console.log(`myWatch is: ${JSON.stringify(myWatch)}`); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken + headers: { + Authorization: `Bearer ${accessToken}`, }, - 'method': 'post', - 'contentType': 'application/json', - 'payload': JSON.stringify(myWatch), - 'muteHttpExceptions': false, + method: "post", + contentType: "application/json", + payload: JSON.stringify(myWatch), + muteHttpExceptions: false, }; - console.log('options are: ' + JSON.stringify(options)); - console.log('formsAPIURL was: ' + formsAPIUrl); + console.log(`options are: ${JSON.stringify(options)}`); + console.log(`formsAPIURL was: ${formsAPIUrl}`); - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'watches', - options); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/watches`, + options, + ); console.log(response); - return ('' + response); + return `${response}`; } /** @@ -205,51 +215,54 @@ function createWatch(formId) { function deleteWatch(formId, watchId) { const accessToken = ScriptApp.getOAuthToken(); - console.log('formsAPIUrl is: ' + formsAPIUrl); + console.log(`formsAPIUrl is: ${formsAPIUrl}`); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'delete', - 'muteHttpExceptions': false, + method: "delete", + muteHttpExceptions: false, }; try { - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'watches/' + - watchId, options); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/watches/${watchId}`, + options, + ); console.log(response); - return ('' + response); + return `${response}`; } catch (e) { - console.log('API Error: ' + JSON.stringify(e)); - return (JSON.stringify(e)); + console.log(`API Error: ${JSON.stringify(e)}`); + return JSON.stringify(e); } - } -/** +/** * Forms API Method: forms.watches.list * GET https://forms.googleapis.com/v1/forms/{formId}/watches */ function watchesList(formId) { - console.log('formId is: ' + formId); + console.log(`formId is: ${formId}`); const accessToken = ScriptApp.getOAuthToken(); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'get' + method: "get", }; try { - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'watches', - options); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/watches`, + options, + ); console.log(response); - return ('' + response); + return `${response}`; } catch (e) { - console.log('API Error: ' + JSON.stringify(e)); - return (JSON.stringify(e)); + console.log(`API Error: ${JSON.stringify(e)}`); + return JSON.stringify(e); } } @@ -261,20 +274,22 @@ function renewWatch(formId, watchId) { const accessToken = ScriptApp.getOAuthToken(); const options = { - 'headers': { - Authorization: 'Bearer ' + accessToken, - Accept: 'application/json' + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", }, - 'method': 'post' + method: "post", }; try { - const response = UrlFetchApp.fetch(formsAPIUrl + formId + '/' + 'watches/' + - watchId + ':renew', options); + const response = UrlFetchApp.fetch( + `${formsAPIUrl + formId}/watches/${watchId}:renew`, + options, + ); console.log(response); - return ('' + response); + return `${response}`; } catch (e) { - console.log('API Error: ' + JSON.stringify(e)); - return (JSON.stringify(e)); + console.log(`API Error: ${JSON.stringify(e)}`); + return JSON.stringify(e); } } diff --git a/forms-api/snippets/retrieve_all_responses.gs b/forms-api/snippets/retrieve_all_responses.gs index c7d865e6d..f3437150f 100644 --- a/forms-api/snippets/retrieve_all_responses.gs +++ b/forms-api/snippets/retrieve_all_responses.gs @@ -1,35 +1,40 @@ -# Copyright 2022 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - # [START forms_retrieve_all_responses] - function callFormsAPI() { - console.log('Calling the Forms API!'); - const formId = ''; +// [START forms_retrieve_all_responses] +function callFormsAPI() { + console.log("Calling the Forms API!"); + const formId = ""; // Get OAuth Token - const OAuthToken = ScriptApp.getOAuthToken(); - console.log('OAuth token is: ' + OAuthToken); - const formsAPIUrl = 'https://forms.googleapis.com/v1/forms/' + formId + '/' + 'responses'; - console.log('formsAPIUrl is: ' + formsAPIUrl); - const options = { - 'headers': { - Authorization: 'Bearer ' + OAuthToken, - Accept: 'application/json' + const OAuthToken = ScriptApp.getOAuthToken(); + console.log(`OAuth token is: ${OAuthToken}`); + + const formsAPIUrl = `https://forms.googleapis.com/v1/forms/${formId}/responses`; + console.log(`formsAPIUrl is: ${formsAPIUrl}`); + + const options = { + headers: { + Authorization: `Bearer ${OAuthToken}`, + Accept: "application/json", }, - 'method': 'get' - }; -const response = UrlFetchApp.fetch(formsAPIUrl, options); - console.log('Response from forms.responses was: ' + response); + method: "get", + }; + + const response = UrlFetchApp.fetch(formsAPIUrl, options); + console.log(`Response from forms.responses was: ${response}`); } -# [END forms_retrieve_all_responses] +// [END forms_retrieve_all_responses] diff --git a/forms/notifications/notification.gs b/forms/notifications/notification.gs index 8a8667e91..df77bac50 100644 --- a/forms/notifications/notification.gs +++ b/forms/notifications/notification.gs @@ -28,20 +28,21 @@ * A global constant String holding the title of the add-on. This is * used to identify the add-on in the notification emails. */ -const ADDON_TITLE = 'Form Notifications'; +const ADDON_TITLE = "Form Notifications"; /** * A global constant 'notice' text to include with each email * notification. */ -const NOTICE = 'Form Notifications was created as an sample add-on, and is' + - ' meant for' + -'demonstration purposes only. It should not be used for complex or important' + -'workflows. The number of notifications this add-on produces are limited by the' + -'owner\'s available email quota; it will not send email notifications if the' + -'owner\'s daily email quota has been exceeded. Collaborators using this add-on on' + -'the same form will be able to adjust the notification settings, but will not be' + -'able to disable the notification triggers set by other collaborators.'; +const NOTICE = + "Form Notifications was created as an sample add-on, and is" + + " meant for" + + "demonstration purposes only. It should not be used for complex or important" + + "workflows. The number of notifications this add-on produces are limited by the" + + "owner's available email quota; it will not send email notifications if the" + + "owner's daily email quota has been exceeded. Collaborators using this add-on on" + + "the same form will be able to adjust the notification settings, but will not be" + + "able to disable the notification triggers set by other collaborators."; /** * Adds a custom menu to the active form to show the add-on sidebar. @@ -53,13 +54,13 @@ const NOTICE = 'Form Notifications was created as an sample add-on, and is' + function onOpen(e) { try { FormApp.getUi() - .createAddonMenu() - .addItem('Configure notifications', 'showSidebar') - .addItem('About', 'showAbout') - .addToUi(); + .createAddonMenu() + .addItem("Configure notifications", "showSidebar") + .addItem("About", "showAbout") + .addToUi(); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -82,12 +83,14 @@ function onInstall(e) { */ function showSidebar() { try { - const ui = HtmlService.createHtmlOutputFromFile('sidebar') - .setTitle('Form Notifications'); + const ui = + HtmlService.createHtmlOutputFromFile("sidebar").setTitle( + "Form Notifications", + ); FormApp.getUi().showSidebar(ui); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -97,13 +100,13 @@ function showSidebar() { */ function showAbout() { try { - const ui = HtmlService.createHtmlOutputFromFile('about') - .setWidth(420) - .setHeight(270); - FormApp.getUi().showModalDialog(ui, 'About Form Notifications'); + const ui = HtmlService.createHtmlOutputFromFile("about") + .setWidth(420) + .setHeight(270); + FormApp.getUi().showModalDialog(ui, "About Form Notifications"); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -120,7 +123,7 @@ function saveSettings(settings) { adjustFormSubmitTrigger(); } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -149,13 +152,13 @@ function getSettings() { for (let i = 0; i < textItems.length; i++) { settings.textItems.push({ title: textItems[i].getTitle(), - id: textItems[i].getId() + id: textItems[i].getId(), }); } return settings; } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -168,8 +171,8 @@ function adjustFormSubmitTrigger() { const triggers = ScriptApp.getUserTriggers(form); const settings = PropertiesService.getDocumentProperties(); const triggerNeeded = - settings.getProperty('creatorNotify') === 'true' || - settings.getProperty('respondentNotify') === 'true'; + settings.getProperty("creatorNotify") === "true" || + settings.getProperty("respondentNotify") === "true"; // Create a new trigger if required; delete existing trigger // if it is not needed. @@ -181,16 +184,16 @@ function adjustFormSubmitTrigger() { } } if (triggerNeeded && !existingTrigger) { - const trigger = ScriptApp.newTrigger('respondToFormSubmit') - .forForm(form) - .onFormSubmit() - .create(); + const trigger = ScriptApp.newTrigger("respondToFormSubmit") + .forForm(form) + .onFormSubmit() + .create(); } else if (!triggerNeeded && existingTrigger) { ScriptApp.deleteTrigger(existingTrigger); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -211,8 +214,10 @@ function respondToFormSubmit(e) { // been supplied yet -- if so, warn the active user via email (if possible). // This check is required when using triggers with add-ons to maintain // functional triggers. - if (authInfo.getAuthorizationStatus() === - ScriptApp.AuthorizationStatus.REQUIRED) { + if ( + authInfo.getAuthorizationStatus() === + ScriptApp.AuthorizationStatus.REQUIRED + ) { // Re-authorization is required. In this case, the user needs to be alerted // that they need to reauthorize; the normal trigger action is not // conducted, since authorization needs to be provided first. Send at @@ -225,24 +230,25 @@ function respondToFormSubmit(e) { // Check if the form creator needs to be notified; if so, construct and // send the notification. - if (settings.getProperty('creatorNotify') === 'true') { + if (settings.getProperty("creatorNotify") === "true") { sendCreatorNotification(); } // Check if the form respondent needs to be notified; if so, construct and // send the notification. Be sure to respect the remaining email quota. - if (settings.getProperty('respondentNotify') === 'true' && - MailApp.getRemainingDailyQuota() > 0) { + if ( + settings.getProperty("respondentNotify") === "true" && + MailApp.getRemainingDailyQuota() > 0 + ) { sendRespondentNotification(e.response); } } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } - /** * Called when the user needs to reauthorize. Sends the user of the * add-on an email explaining the need to reauthorize and provides @@ -253,27 +259,30 @@ function sendReauthorizationRequest() { try { const settings = PropertiesService.getDocumentProperties(); const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); - const lastAuthEmailDate = settings.getProperty('lastAuthEmailDate'); + const lastAuthEmailDate = settings.getProperty("lastAuthEmailDate"); const today = new Date().toDateString(); if (lastAuthEmailDate !== today) { if (MailApp.getRemainingDailyQuota() > 0) { const template = - HtmlService.createTemplateFromFile('authorizationEmail'); + HtmlService.createTemplateFromFile("authorizationEmail"); template.url = authInfo.getAuthorizationUrl(); template.notice = NOTICE; const message = template.evaluate(); - MailApp.sendEmail(Session.getEffectiveUser().getEmail(), - 'Authorization Required', - message.getContent(), { - name: ADDON_TITLE, - htmlBody: message.getContent() - }); + MailApp.sendEmail( + Session.getEffectiveUser().getEmail(), + "Authorization Required", + message.getContent(), + { + name: ADDON_TITLE, + htmlBody: message.getContent(), + }, + ); } - settings.setProperty('lastAuthEmailDate', today); + settings.setProperty("lastAuthEmailDate", today); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -286,8 +295,8 @@ function sendCreatorNotification() { try { const form = FormApp.getActiveForm(); const settings = PropertiesService.getDocumentProperties(); - let responseStep = settings.getProperty('responseStep'); - responseStep = responseStep ? parseInt(responseStep) : 10; + let responseStep = settings.getProperty("responseStep"); + responseStep = responseStep ? Number.parseInt(responseStep) : 10; // If the total number of form responses is an even multiple of the // response step setting, send a notification email(s) to the form @@ -295,10 +304,11 @@ function sendCreatorNotification() { // will be sent when there are 10, 20, 30, etc. total form responses // received. if (form.getResponses().length % responseStep === 0) { - const addresses = settings.getProperty('creatorEmail').split(','); + const addresses = settings.getProperty("creatorEmail").split(","); if (MailApp.getRemainingDailyQuota() > addresses.length) { - const template = - HtmlService.createTemplateFromFile('creatorNotification'); + const template = HtmlService.createTemplateFromFile( + "creatorNotification", + ); template.summary = form.getSummaryUrl(); template.responses = form.getResponses().length; template.title = form.getTitle(); @@ -306,17 +316,20 @@ function sendCreatorNotification() { template.formUrl = form.getEditUrl(); template.notice = NOTICE; const message = template.evaluate(); - MailApp.sendEmail(settings.getProperty('creatorEmail'), - form.getTitle() + ': Form submissions detected', - message.getContent(), { - name: ADDON_TITLE, - htmlBody: message.getContent() - }); + MailApp.sendEmail( + settings.getProperty("creatorEmail"), + `${form.getTitle()}: Form submissions detected`, + message.getContent(), + { + name: ADDON_TITLE, + htmlBody: message.getContent(), + }, + ); } } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } @@ -330,26 +343,31 @@ function sendRespondentNotification(response) { try { const form = FormApp.getActiveForm(); const settings = PropertiesService.getDocumentProperties(); - const emailId = settings.getProperty('respondentEmailItemId'); - const emailItem = form.getItemById(parseInt(emailId)); - const respondentEmail = response.getResponseForItem(emailItem) - .getResponse(); + const emailId = settings.getProperty("respondentEmailItemId"); + const emailItem = form.getItemById(Number.parseInt(emailId)); + const respondentEmail = response + .getResponseForItem(emailItem) + .getResponse(); if (respondentEmail) { - const template = - HtmlService.createTemplateFromFile('respondentNotification'); - template.paragraphs = settings.getProperty('responseText').split('\n'); + const template = HtmlService.createTemplateFromFile( + "respondentNotification", + ); + template.paragraphs = settings.getProperty("responseText").split("\n"); template.notice = NOTICE; const message = template.evaluate(); - MailApp.sendEmail(respondentEmail, - settings.getProperty('responseSubject'), - message.getContent(), { - name: form.getTitle(), - htmlBody: message.getContent() - }); + MailApp.sendEmail( + respondentEmail, + settings.getProperty("responseSubject"), + message.getContent(), + { + name: form.getTitle(), + htmlBody: message.getContent(), + }, + ); } } catch (e) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', e.error); + console.log("Failed with error: %s", e.error); } } // [END apps_script_forms_notifications_quickstart] diff --git a/gmail-sentiment-analysis/Cards.gs b/gmail-sentiment-analysis/Cards.gs index 1c1fe6df4..288fe65e3 100644 --- a/gmail-sentiment-analysis/Cards.gs +++ b/gmail-sentiment-analysis/Cards.gs @@ -25,7 +25,9 @@ function buildHomepageCard() { // Create a card header const cardHeader = CardService.newCardHeader(); - cardHeader.setImageUrl('https://fonts.gstatic.com/s/i/googlematerialicons/mail/v6/black-24dp/1x/gm_mail_black_24dp.png'); + cardHeader.setImageUrl( + "https://fonts.gstatic.com/s/i/googlematerialicons/mail/v6/black-24dp/1x/gm_mail_black_24dp.png", + ); cardHeader.setImageStyle(CardService.ImageStyle.CIRCLE); cardHeader.setTitle("Analyze your Gmail"); @@ -39,11 +41,19 @@ function buildHomepageCard() { const buttonSet = CardService.newButtonSet(); // Create "Generate sample emails" button - const generateButton = createFilledButton('Generate sample emails', 'generateSampleEmails', '#34A853'); + const generateButton = createFilledButton( + "Generate sample emails", + "generateSampleEmails", + "#34A853", + ); buttonSet.addButton(generateButton); // Create "Analyze emails" button - const analyzeButton = createFilledButton('Analyze emails', 'analyzeSentiment', '#FF0000'); + const analyzeButton = createFilledButton( + "Analyze emails", + "analyzeSentiment", + "#FF0000", + ); buttonSet.addButton(analyzeButton); // Add the button set to the section @@ -104,4 +114,4 @@ function buildNotificationResponse(notificationText) { // Build and return the action response return actionResponseBuilder.build(); -} \ No newline at end of file +} diff --git a/gmail-sentiment-analysis/Code.gs b/gmail-sentiment-analysis/Code.gs index c803c5690..135079d81 100644 --- a/gmail-sentiment-analysis/Code.gs +++ b/gmail-sentiment-analysis/Code.gs @@ -22,4 +22,4 @@ limitations under the License. */ function onHomepageTrigger(e) { return buildHomepageCard(); -} \ No newline at end of file +} diff --git a/gmail-sentiment-analysis/Gmail.gs b/gmail-sentiment-analysis/Gmail.gs index 593ee3ba1..3e6fd2368 100644 --- a/gmail-sentiment-analysis/Gmail.gs +++ b/gmail-sentiment-analysis/Gmail.gs @@ -36,9 +36,15 @@ function analyzeAndLabelEmailSentiment() { const labelNames = ["HAPPY TONE 😊", "NEUTRAL TONE 😐", "UPSET TONE 😡"]; // Get or create labels for each sentiment - const positiveLabel = GmailApp.getUserLabelByName(labelNames[0]) || GmailApp.createLabel(labelNames[0]); - const neutralLabel = GmailApp.getUserLabelByName(labelNames[1]) || GmailApp.createLabel(labelNames[1]); - const negativeLabel = GmailApp.getUserLabelByName(labelNames[2]) || GmailApp.createLabel(labelNames[2]); + const positiveLabel = + GmailApp.getUserLabelByName(labelNames[0]) || + GmailApp.createLabel(labelNames[0]); + const neutralLabel = + GmailApp.getUserLabelByName(labelNames[1]) || + GmailApp.createLabel(labelNames[1]); + const negativeLabel = + GmailApp.getUserLabelByName(labelNames[2]) || + GmailApp.createLabel(labelNames[2]); // Get the first 10 threads in the inbox const threads = GmailApp.getInboxThreads(0, 10); @@ -55,11 +61,11 @@ function analyzeAndLabelEmailSentiment() { const sentiment = processSentiment(emailBody); // Apply the appropriate label based on the sentiment - if (sentiment === 'positive') { + if (sentiment === "positive") { thread.addLabel(positiveLabel); - } else if (sentiment === 'neutral') { + } else if (sentiment === "neutral") { thread.addLabel(neutralLabel); - } else if (sentiment === 'negative') { + } else if (sentiment === "negative") { thread.addLabel(negativeLabel); } } @@ -78,32 +84,32 @@ function generateSampleEmails() { // Define sample emails const sampleEmails = [ { - subject: 'Thank you for amazing service!', - body: 'Hi, I really enjoyed working with you. Thank you again!', - name: 'Customer A' + subject: "Thank you for amazing service!", + body: "Hi, I really enjoyed working with you. Thank you again!", + name: "Customer A", }, { - subject: 'Request for information', - body: 'Hello, I need more information on your recent product launch. Thank you.', - name: 'Customer B' + subject: "Request for information", + body: "Hello, I need more information on your recent product launch. Thank you.", + name: "Customer B", }, { - subject: 'Complaint!', - body: '', + subject: "Complaint!", + body: "", htmlBody: `

Hello, You are late in delivery, again.

Please contact me ASAP before I cancel our subscription.

`, - name: 'Customer C' - } + name: "Customer C", + }, ]; // Send each sample email for (const email of sampleEmails) { GmailApp.sendEmail(userEmail, email.subject, email.body, { name: email.name, - htmlBody: email.htmlBody + htmlBody: email.htmlBody, }); } // Return a notification return buildNotificationResponse("Successfully generated sample emails"); -} \ No newline at end of file +} diff --git a/gmail-sentiment-analysis/Vertex.gs b/gmail-sentiment-analysis/Vertex.gs index 959ebdc52..2bc307226 100644 --- a/gmail-sentiment-analysis/Vertex.gs +++ b/gmail-sentiment-analysis/Vertex.gs @@ -15,13 +15,13 @@ limitations under the License. */ // Replace with your project ID -const PROJECT_ID = '[ADD YOUR GCP PROJECT ID HERE]'; +const PROJECT_ID = "[ADD YOUR GCP PROJECT ID HERE]"; // Location for your Vertex AI model -const VERTEX_AI_LOCATION = 'us-central1'; +const VERTEX_AI_LOCATION = "us-central1"; // Model ID to use for sentiment analysis -const MODEL_ID = 'gemini-2.5-flash'; +const MODEL_ID = "gemini-2.5-flash"; /** * Sends the email text to Vertex AI for sentiment analysis. @@ -40,10 +40,10 @@ function processSentiment(emailText) { role: "user", parts: [ { - text: `Analyze the sentiment of the following message: ${emailText}` - } - ] - } + text: `Analyze the sentiment of the following message: ${emailText}`, + }, + ], + }, ], generationConfig: { temperature: 0.9, @@ -55,22 +55,22 @@ function processSentiment(emailText) { properties: { response: { type: "string", - enum: ["positive", "negative", "neutral"] - } - } - } - } + enum: ["positive", "negative", "neutral"], + }, + }, + }, + }, }; // Prepare the request options const options = { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${ScriptApp.getOAuthToken()}` + Authorization: `Bearer ${ScriptApp.getOAuthToken()}`, }, - contentType: 'application/json', + contentType: "application/json", muteHttpExceptions: true, // Set to true to inspect the error response - payload: JSON.stringify(payload) + payload: JSON.stringify(payload), }; // Make the API request @@ -78,8 +78,10 @@ function processSentiment(emailText) { // Parse the response. There are two levels of JSON responses to parse. const parsedResponse = JSON.parse(response.getContentText()); - const sentimentResponse = JSON.parse(parsedResponse.candidates[0].content.parts[0].text).response; + const sentimentResponse = JSON.parse( + parsedResponse.candidates[0].content.parts[0].text, + ).response; // Return the sentiment return sentimentResponse; -} \ No newline at end of file +} diff --git a/gmail/add-ons/quickstart.gs b/gmail/add-ons/quickstart.gs index 4afbf310b..036838b19 100644 --- a/gmail/add-ons/quickstart.gs +++ b/gmail/add-ons/quickstart.gs @@ -26,91 +26,99 @@ */ function buildAddOn(e) { // Activate temporary Gmail add-on scopes. - var accessToken = e.messageMetadata.accessToken; + const accessToken = e.messageMetadata.accessToken; GmailApp.setCurrentMessageAccessToken(accessToken); - var messageId = e.messageMetadata.messageId; - var message = GmailApp.getMessageById(messageId); - + const messageId = e.messageMetadata.messageId; + const message = GmailApp.getMessageById(messageId); + // Get user and thread labels as arrays to enable quick sorting and indexing. - var threadLabels = message.getThread().getLabels(); - var labels = getLabelArray(GmailApp.getUserLabels()); - var labelsInUse = getLabelArray(threadLabels); - + const threadLabels = message.getThread().getLabels(); + const labels = getLabelArray(GmailApp.getUserLabels()); + const labelsInUse = getLabelArray(threadLabels); + // Create a section for that contains all user Labels. - var section = CardService.newCardSection() - .setHeader("Available User Labels"); + const section = CardService.newCardSection().setHeader( + 'Available User Labels', + ); // Create a checkbox group for user labels that are added to prior section. - var checkboxGroup = CardService.newSelectionInput() + const checkboxGroup = CardService.newSelectionInput() .setType(CardService.SelectionInputType.CHECK_BOX) - .setFieldName('labels') - .setOnChangeAction(CardService.newAction().setFunctionName('toggleLabel')); - + .setFieldName("labels") + .setOnChangeAction(CardService.newAction().setFunctionName("toggleLabel")); + // Add checkbox with name and selected value for each User Label. - for(var i = 0; i < labels.length; i++) { - checkboxGroup.addItem(labels[i], labels[i], labelsInUse.indexOf(labels[i])!= -1); + for (let i = 0; i < labels.length; i++) { + checkboxGroup.addItem( + labels[i], + labels[i], + labelsInUse.indexOf(labels[i]) !== -1, + ); } - + // Add the checkbox group to the section. section.addWidget(checkboxGroup); - + // Build the main card after adding the section. - var card = CardService.newCardBuilder() - .setHeader(CardService.newCardHeader() - .setTitle('Quick Label') - .setImageUrl('https://www.gstatic.com/images/icons/material/system/1x/label_googblue_48dp.png')) - .addSection(section) + const card = CardService.newCardBuilder() + .setHeader( + CardService.newCardHeader() + .setTitle("Quick Label") + .setImageUrl( + "https://www.gstatic.com/images/icons/material/system/1x/label_googblue_48dp.png", + ), + ) + .addSection(section) .build(); - + return [card]; -} +} /** - * Updates the labels on the current thread based on + * Updates the labels on the current thread based on * user selections. Runs via the OnChangeAction for * each CHECK_BOX created. * * @param {Object} e The data provided by the Gmail UI. -*/ -function toggleLabel(e){ - var selected = e.formInputs.labels; - + */ +function toggleLabel(e) { + const selected = e.formInputs.labels; + // Activate temporary Gmail add-on scopes. - var accessToken = e.messageMetadata.accessToken; + const accessToken = e.messageMetadata.accessToken; GmailApp.setCurrentMessageAccessToken(accessToken); - var messageId = e.messageMetadata.messageId; - var message = GmailApp.getMessageById(messageId); - var thread = message.getThread(); - - if (selected != null){ - for each (var label in GmailApp.getUserLabels()) { - if(selected.indexOf(label.getName()) != -1){ - thread.addLabel(label); - } - else { - thread.removeLabel(label); - } - } - } - else { - for each (var label in GmailApp.getUserLabels()) { + const messageId = e.messageMetadata.messageId; + const message = GmailApp.getMessageById(messageId); + const thread = message.getThread(); + + if (selected != null) { + for (const label of GmailApp.getUserLabels()) { + if (selected.indexOf(label.getName()) !== -1) { + thread.addLabel(label); + } else { + thread.removeLabel(label); + } + } + } else { + for (const label of GmailApp.getUserLabels()) { thread.removeLabel(label); } } } /** - * Converts an GmailLabel object to a array of strings. + * Converts an GmailLabel object to a array of strings. * Used for easy sorting and to determine if a value exists. * * @param {labelsObjects} A GmailLabel object array. * @return {lables[]} An array of labels names as strings. -*/ -function getLabelArray(labelsObjects){ - var labels = []; - for(var i = 0; i < labelsObjects.length; i++) { + */ +function getLabelArray(labelsObjects) { + const labels = []; + + for (let i = 0; i < labelsObjects.length; i++) { labels[i] = labelsObjects[i].getName(); } labels.sort(); diff --git a/gmail/inlineimage/inlineimage.gs b/gmail/inlineimage/inlineimage.gs index 0ca113c6f..1047e2d25 100644 --- a/gmail/inlineimage/inlineimage.gs +++ b/gmail/inlineimage/inlineimage.gs @@ -1,4 +1,3 @@ - /** * Copyright 2022 Google LLC * @@ -22,15 +21,18 @@ function sendEmailToMyself() { function sendEmailWithInlineImage(toAddress) { const options = {}; - const imageName = 'cat_emoji'; + const imageName = "cat_emoji"; // The URL "cid:cat_emoji" means that the inline attachment named "cat_emoji" would be used. - options['htmlBody'] = 'Welcome! Cat Emoji'; - options['inlineImages'] = {[imageName]: Utilities.newBlob(getImageBinary(), 'image/png', imageName)}; - GmailApp.sendEmail(toAddress, 'Welcome!', 'Welcome!', options); + options.htmlBody = `Welcome! Cat Emoji`; + options.inlineImages = { + [imageName]: Utilities.newBlob(getImageBinary(), "image/png", imageName), + }; + GmailApp.sendEmail(toAddress, "Welcome!", "Welcome!", options); } function getImageBinary() { // Cat Face Emoji from https://github.com/googlefonts/noto-emoji/blob/main/png/32/emoji_u1f431.png, Base64 encoded. - const catPngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+BJREFUeNrsV01ME1EQnpaltPK3iAT0oAsxMSYmlIOaGBO2etCDMTVq8CYl3jRBvehBI0YPehIPxhvFkxo1gHpQE9P15+KtROJFI6sxhEKwW6FY27o6s/vabpd9tPUn8eAkj8e+nTffzDez814B/kX5oXT4/7A9GceAk12Xg/IkThIOFUfIJb9XfgNYxCmMI8iWNLTXZNVx2zYEGTiwOUKe/wZ4xAJOIhIbXAdQuo2/dacB6i8gP7X0dA43hSsEJ+eJST9UtZv2fIdyr5d1wMyRsMkcBSd6y2WCRT5C0RrgZKN6K4C3x1FfcFw1QSFvYP4sWk4SE1F426gyRyVo/mbqzdUgiK6BoEcBkv35yAsBcEUoGRIZ8uwA+PYAQHeNgPsHzUv1MjYyfT0lwZ1S4Cz6DNNG8LoMX8+XLfz/9XZhXwUOaMUJTQJ8OYnRvSqs1VpAyCEaTu++T5p7aa7AgXGTzlfmRsq93cCKbHHE1qjt7FAAORvZidyqwm1E7BuNlORtoRoNou8iK0INi1DQ+emhWqBhpqQdm5HKK8JoWTVhB8o5wv02k+bA7moFX5ICfKmV7cQfErdDBys6MNTpLAzeS4AynirLoLagQ+jyLOw7G3PaI9lbsT0FQfuOwMkpwwmS8KkW6N1Vv6wDJ67NwfDjebPaxr9C/L5kV5GthWj/Cjrt2jlwkrGXiyUZUGPZIjYcWOgeGhrqxSHnGaAFKqVE5rq/sXqOa1ysK923pFahSF/u9Oaf3yS2wJsvm/2szhRrCuhBfjGzV6xyZ6Gr6Tm0eT8YLwYON8HAjbhhrH9/Y97Y+eE4KFEzOqlNgCvHmg2dK0ebjci1pI76DXn9d/OdkNa9sGdNOOrbOXGC1wciC1lRTus1sNIT40ZJwIHjU0VrkcE1IPu93D2f063wMbkB4ukWTU1uJAbUvr6+kAvpP44PhyllDdWfJcGVkbauepJngCehS7Mw/MgsNtnvg5GLrcumiBjwuFPgqUopq3dHAjwG6Mw/xzPStEeF8OkWCG6vNWhuP/TRmOMPJQM8x8zkrbVGWqzyNHYQ6oQELGbrFWTgKhGJDGh5LWLi5ofFbtEzC6sxej/WwZICQ6P7zsSMiNXpjAFO0nXkE/jX18DoyyTOniXgJDtb78B0ah281raNsV5DTU9xMXCR9QAl1HExbL82WT8rKr7ou7Tx3H+gASOvgqt3E8Y7azHyyge7baDUrbi8A+nXpAsdiC57IWHX8PN/ATxkB3dkoNyCrEA0Bj5a0ZUMN5ADAfsFokLgQXb+j3JxKrjnB9nvBpFTpLmjnM77ZzhG2fH+X/5t+SnAAE+HjvApIyOGAAAAAElFTkSuQmCC'; + const catPngBase64 = + "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+BJREFUeNrsV01ME1EQnpaltPK3iAT0oAsxMSYmlIOaGBO2etCDMTVq8CYl3jRBvehBI0YPehIPxhvFkxo1gHpQE9P15+KtROJFI6sxhEKwW6FY27o6s/vabpd9tPUn8eAkj8e+nTffzDez814B/kX5oXT4/7A9GceAk12Xg/IkThIOFUfIJb9XfgNYxCmMI8iWNLTXZNVx2zYEGTiwOUKe/wZ4xAJOIhIbXAdQuo2/dacB6i8gP7X0dA43hSsEJ+eJST9UtZv2fIdyr5d1wMyRsMkcBSd6y2WCRT5C0RrgZKN6K4C3x1FfcFw1QSFvYP4sWk4SE1F426gyRyVo/mbqzdUgiK6BoEcBkv35yAsBcEUoGRIZ8uwA+PYAQHeNgPsHzUv1MjYyfT0lwZ1S4Cz6DNNG8LoMX8+XLfz/9XZhXwUOaMUJTQJ8OYnRvSqs1VpAyCEaTu++T5p7aa7AgXGTzlfmRsq93cCKbHHE1qjt7FAAORvZidyqwm1E7BuNlORtoRoNou8iK0INi1DQ+emhWqBhpqQdm5HKK8JoWTVhB8o5wv02k+bA7moFX5ICfKmV7cQfErdDBys6MNTpLAzeS4AynirLoLagQ+jyLOw7G3PaI9lbsT0FQfuOwMkpwwmS8KkW6N1Vv6wDJ67NwfDjebPaxr9C/L5kV5GthWj/Cjrt2jlwkrGXiyUZUGPZIjYcWOgeGhrqxSHnGaAFKqVE5rq/sXqOa1ysK923pFahSF/u9Oaf3yS2wJsvm/2szhRrCuhBfjGzV6xyZ6Gr6Tm0eT8YLwYON8HAjbhhrH9/Y97Y+eE4KFEzOqlNgCvHmg2dK0ebjci1pI76DXn9d/OdkNa9sGdNOOrbOXGC1wciC1lRTus1sNIT40ZJwIHjU0VrkcE1IPu93D2f063wMbkB4ukWTU1uJAbUvr6+kAvpP44PhyllDdWfJcGVkbauepJngCehS7Mw/MgsNtnvg5GLrcumiBjwuFPgqUopq3dHAjwG6Mw/xzPStEeF8OkWCG6vNWhuP/TRmOMPJQM8x8zkrbVGWqzyNHYQ6oQELGbrFWTgKhGJDGh5LWLi5ofFbtEzC6sxej/WwZICQ6P7zsSMiNXpjAFO0nXkE/jX18DoyyTOniXgJDtb78B0ah281raNsV5DTU9xMXCR9QAl1HExbL82WT8rKr7ou7Tx3H+gASOvgqt3E8Y7azHyyge7baDUrbi8A+nXpAsdiC57IWHX8PN/ATxkB3dkoNyCrEA0Bj5a0ZUMN5ADAfsFokLgQXb+j3JxKrjnB9nvBpFTpLmjnM77ZzhG2fH+X/5t+SnAAE+HjvApIyOGAAAAAElFTkSuQmCC"; return Utilities.base64Decode(catPngBase64); } diff --git a/gmail/markup/Code.gs b/gmail/markup/Code.gs index d4f65f6ed..492ec96d8 100644 --- a/gmail/markup/Code.gs +++ b/gmail/markup/Code.gs @@ -4,16 +4,16 @@ */ function testSchemas() { try { - const htmlBody = HtmlService.createHtmlOutputFromFile('mail_template').getContent(); + const htmlBody = + HtmlService.createHtmlOutputFromFile("mail_template").getContent(); MailApp.sendEmail({ to: Session.getActiveUser().getEmail(), - subject: 'Test Email markup - ' + new Date(), - htmlBody: htmlBody + subject: `Test Email markup - ${new Date()}`, + htmlBody: htmlBody, }); } catch (err) { console.log(err.message); } } // [END gmail_send_email_with_markup] - diff --git a/gmail/quickstart/quickstart.gs b/gmail/quickstart/quickstart.gs index 51ca6a28c..eb3460d91 100644 --- a/gmail/quickstart/quickstart.gs +++ b/gmail/quickstart/quickstart.gs @@ -22,20 +22,20 @@ function listLabels() { try { // Gmail.Users.Labels.list() API returns the list of all Labels in user's mailbox - const response = Gmail.Users.Labels.list('me'); + const response = Gmail.Users.Labels.list("me"); if (!response || response.labels.length === 0) { // TODO (developer) - No labels are returned from the response - console.log('No labels found.'); + console.log("No labels found."); return; } // Print the Labels that are available. - console.log('Labels:'); - for (const label of response.labels ) { - console.log('- %s', label.name); + console.log("Labels:"); + for (const label of response.labels) { + console.log("- %s", label.name); } } catch (err) { // TODO (developer) - Handle exception on Labels.list() API - console.log('Labels.list() API failed with error %s', err.toString()); + console.log("Labels.list() API failed with error %s", err.toString()); } } // [END gmail_quickstart] diff --git a/gmail/sendingEmails/sendingEmails.gs b/gmail/sendingEmails/sendingEmails.gs index f8e8e0067..7bac9ee89 100644 --- a/gmail/sendingEmails/sendingEmails.gs +++ b/gmail/sendingEmails/sendingEmails.gs @@ -28,7 +28,7 @@ function sendEmails() { for (const row of data) { const emailAddress = row[0]; // First column const message = row[1]; // Second column - const subject = 'Sending emails from a Spreadsheet'; + const subject = "Sending emails from a Spreadsheet"; MailApp.sendEmail(emailAddress, subject, message); // Send emails to emailAddresses which are presents in First column } } catch (err) { @@ -42,7 +42,7 @@ function sendEmails() { * Sends non-duplicate emails with data from the current spreadsheet. */ function sendNonDuplicateEmails() { - const EMAIL_SENT = 'email sent'; //This constant is used to write the message in Column C of Sheet + const EMAIL_SENT = "email sent"; //This constant is used to write the message in Column C of Sheet try { const sheet = SpreadsheetApp.getActiveSheet(); // Get the active sheet in spreadsheet const startRow = 2; // First row of data to process @@ -55,11 +55,11 @@ function sendNonDuplicateEmails() { const message = row[1]; // Second column const emailSent = row[2]; // Third column if (emailSent === EMAIL_SENT) { - console.log('Email already sent'); + console.log("Email already sent"); return; } - const subject = 'Sending emails from a Spreadsheet'; - MailApp.sendEmail(emailAddress, subject, message);// Send emails to emailAddresses which are presents in First column + const subject = "Sending emails from a Spreadsheet"; + MailApp.sendEmail(emailAddress, subject, message); // Send emails to emailAddresses which are presents in First column sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT); SpreadsheetApp.flush(); // Make sure the cell is updated right away in case the script is interrupted } diff --git a/mashups/sheets2calendar.gs b/mashups/sheets2calendar.gs index 5461cb4ab..4fdfb9ab9 100644 --- a/mashups/sheets2calendar.gs +++ b/mashups/sheets2calendar.gs @@ -6,7 +6,7 @@ */ function createEventsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,15 +15,13 @@ function createEventsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Create an event for each row. - data.forEach(function(row) { + for (const row of data) { const title = row[0]; const description = row[1]; const emailsStr = row[2]; // Split the emails into an array and remove extra whitespace. - const emails = emailsStr.split(',').map(function(email) { - return email.trim(); - }); + const emails = emailsStr.split(",").map((email) => email.trim()); const now = new Date(); // Start the event at the next hour mark. @@ -37,14 +35,15 @@ function createEventsFromSpreadsheet() { end.setMinutes(end.getMinutes() + 30); // Create the calendar event and invite the guests. - const event = CalendarApp.createEvent(title, start, end) - .setDescription(description); - emails.forEach(function(email) { + const event = CalendarApp.createEvent(title, start, end).setDescription( + description, + ); + for (const email of emails) { event.addGuest(email); - }); + } // Add yourself as a guest and mark yourself as attending. event.addGuest(Session.getActiveUser().getEmail()); event.setMyStatus(CalendarApp.GuestStatus.YES); - }); + } } diff --git a/mashups/sheets2chat.gs b/mashups/sheets2chat.gs index 81ee9fe77..11a82626a 100644 --- a/mashups/sheets2chat.gs +++ b/mashups/sheets2chat.gs @@ -25,31 +25,37 @@ function sendChatMessageOnEdit(e) { // Construct the message to send, based on the old and new value of the cell. let changeMessage; if (oldValue && value) { - changeMessage = Utilities.formatString('changed from "%s" to "%s"', - oldValue, value); + changeMessage = Utilities.formatString( + 'changed from "%s" to "%s"', + oldValue, + value, + ); } else if (value) { changeMessage = Utilities.formatString('set to "%s"', value); } else { - changeMessage = 'cleared'; + changeMessage = "cleared"; } const message = Utilities.formatString( - 'The range %s was %s. <%s|Open spreadsheet>.', - range.getA1Notation(), changeMessage, ss.getUrl()); + "The range %s was %s. <%s|Open spreadsheet>.", + range.getA1Notation(), + changeMessage, + ss.getUrl(), + ); // Follow these steps to create an incomming webhook URL for your chat room: // https://developers.google.com/hangouts/chat/how-tos/webhooks#define_an_incoming_webhook - const webhookUrl = 'ENTER INCOMMING WEBHOOK URL HERE'; + const webhookUrl = "ENTER INCOMMING WEBHOOK URL HERE"; // Use the spreadsheet's ID as a thread key, so that all messages go into the // same thread. - const url = webhookUrl + '&threadKey=' + ss.getId(); + const url = `${webhookUrl}&threadKey=${ss.getId()}`; // Send the message. UrlFetchApp.fetch(url, { - method: 'post', - contentType: 'application/json', + method: "post", + contentType: "application/json", payload: JSON.stringify({ - text: message - }) + text: message, + }), }); } diff --git a/mashups/sheets2contacts.gs b/mashups/sheets2contacts.gs index 746034396..63a0a1ac7 100644 --- a/mashups/sheets2contacts.gs +++ b/mashups/sheets2contacts.gs @@ -5,7 +5,7 @@ */ function createContactsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; const data = sheet.getDataRange().getValues(); @@ -13,10 +13,10 @@ function createContactsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Send a contact for each row. - data.forEach(function(row) { + for (const row of data) { const firstName = row[0]; const lastName = row[1]; const email = row[2]; ContactsApp.createContact(firstName, lastName, email); - }); + } } diff --git a/mashups/sheets2docs.gs b/mashups/sheets2docs.gs index 7b0c78c61..37449d7d1 100644 --- a/mashups/sheets2docs.gs +++ b/mashups/sheets2docs.gs @@ -6,7 +6,7 @@ */ function createDocsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,19 +15,17 @@ function createDocsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Create a document for each row. - data.forEach(function(row) { + for (const row of data) { const title = row[0]; const content = row[1]; const emailsStr = row[2]; // Split the emails into an array and remove extra whitespace. - const emails = emailsStr.split(',').map(function(email) { - return email.trim(); - }); + const emails = emailsStr.split(",").map((email) => email.trim()); // Create the document, append the content, and share it out. const doc = DocumentApp.create(title); doc.getBody().appendParagraph(content); doc.addEditors(emails); - }); + } } diff --git a/mashups/sheets2drive.gs b/mashups/sheets2drive.gs index 8d869f0b9..9391e92c3 100644 --- a/mashups/sheets2drive.gs +++ b/mashups/sheets2drive.gs @@ -6,7 +6,7 @@ */ function createDriveFilesFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,22 +15,20 @@ function createDriveFilesFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Create a PDF in Google Drive for each row. - data.forEach(function(row) { + for (const row of data) { const fileName = row[0]; const htmlContent = row[1]; const emailsStr = row[2]; // Split the emails into an array and remove extra whitespace. - const emails = emailsStr.split(',').map(function(email) { - return email.trim(); - }); + const emails = emailsStr.split(",").map((email) => email.trim()); // Convert the HTML content to PDF. - const html = Utilities.newBlob(htmlContent, 'text/html'); - const pdf = html.getAs('application/pdf'); + const html = Utilities.newBlob(htmlContent, "text/html"); + const pdf = html.getAs("application/pdf"); // Create the Drive file and share it out. const file = DriveApp.createFile(pdf).setName(fileName); file.addEditors(emails); - }); + } } diff --git a/mashups/sheets2forms.gs b/mashups/sheets2forms.gs index fe14a8536..24d987129 100644 --- a/mashups/sheets2forms.gs +++ b/mashups/sheets2forms.gs @@ -6,7 +6,7 @@ */ function createFormsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,19 +15,17 @@ function createFormsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Create a form for each row. - data.forEach(function(row) { + for (const row of data) { const title = row[0]; const question = row[1]; const emailsStr = row[2]; // Split the emails into an array and remove extra whitespace. - const emails = emailsStr.split(',').map(function(email) { - return email.trim(); - }); + const emails = emailsStr.split(",").map((email) => email.trim()); // Create the form, append the question, and share it out. const form = FormApp.create(title); form.addTextItem().setTitle(question); form.addEditors(emails); - }); + } } diff --git a/mashups/sheets2gmail.gs b/mashups/sheets2gmail.gs index 7d5ed23ff..491fd13fb 100644 --- a/mashups/sheets2gmail.gs +++ b/mashups/sheets2gmail.gs @@ -6,7 +6,7 @@ */ function sendEmailsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,14 +15,14 @@ function sendEmailsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Send an email for each row. - data.forEach(function(row) { + for (const row of data) { const subject = row[0]; const htmlMessage = row[1]; const emails = row[2]; // Send the email. - GmailApp.sendEmail(emails, subject, '', { - htmlBody: htmlMessage + GmailApp.sendEmail(emails, subject, "", { + htmlBody: htmlMessage, }); - }); + } } diff --git a/mashups/sheets2maps.gs b/mashups/sheets2maps.gs index 33e4d29c6..170f33384 100644 --- a/mashups/sheets2maps.gs +++ b/mashups/sheets2maps.gs @@ -14,15 +14,15 @@ function COUNTY(address) { const results = Maps.newGeocoder().geocode(address).results; if (!results || results.length === 0) { - throw new Error('Unknown address'); + throw new Error("Unknown address"); } /** @type {{long_name: string, types: string[]}[]} */ const addressComponents = results[0].address_components; - const counties = addressComponents.filter(function(component) { - return component.types.indexOf('administrative_area_level_2') >= 0; - }); + const counties = addressComponents.filter( + (component) => component.types.indexOf("administrative_area_level_2") >= 0, + ); if (!counties.length) { - throw new Error('Unable to determine county'); + throw new Error("Unable to determine county"); } return counties[0].long_name; } diff --git a/mashups/sheets2slides.gs b/mashups/sheets2slides.gs index 6a140911a..78d8881ee 100644 --- a/mashups/sheets2slides.gs +++ b/mashups/sheets2slides.gs @@ -6,7 +6,7 @@ */ function createPresentationsFromSpreadsheet() { // Open the spreadsheet and get the data. - const ss = SpreadsheetApp.openByUrl('ENTER SPREADSHEET URL HERE'); + const ss = SpreadsheetApp.openByUrl("ENTER SPREADSHEET URL HERE"); const sheet = ss.getSheets()[0]; /** @type {string[][]} */ const data = sheet.getDataRange().getValues(); @@ -15,22 +15,23 @@ function createPresentationsFromSpreadsheet() { data.splice(sheet.getFrozenRows()); // Create a presentation for each row. - data.forEach(function(row) { + for (const row of data) { const title = row[0]; const content = row[1]; const emailsStr = row[2]; // Split the emails into an array and remove extra whitespace. - const emails = emailsStr.split(',').map(function(email) { - return email.trim(); - }); + const emails = emailsStr.split(",").map((email) => email.trim()); // Create the presentation, insert a new slide at the start, append the content, // and share it out. const presentation = SlidesApp.create(title); - const slide = presentation.insertSlide(0, SlidesApp.PredefinedLayout.MAIN_POINT); + const slide = presentation.insertSlide( + 0, + SlidesApp.PredefinedLayout.MAIN_POINT, + ); const textBox = slide.getShapes()[0]; textBox.getText().appendParagraph(content); presentation.addEditors(emails); - }); + } } diff --git a/mashups/sheets2translate.gs b/mashups/sheets2translate.gs index a863e8378..5f41d422c 100644 --- a/mashups/sheets2translate.gs +++ b/mashups/sheets2translate.gs @@ -11,8 +11,8 @@ function onEdit() { const range = SpreadsheetApp.getActiveRange(); const value = range.getValue(); - if (typeof value === 'string') { - const translated = LanguageApp.translate(value, '', 'en'); + if (typeof value === "string") { + const translated = LanguageApp.translate(value, "", "en"); range.setNote(translated); } } diff --git a/package.json b/package.json index c7f6ddc20..7948c8844 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ "typescript": "^5.9.3" }, "scripts": { - "lint": "biome check .", - "format": "biome check --write .", + "lint": "tsx .github/scripts/biome-gs.ts lint", + "format": "tsx .github/scripts/biome-gs.ts format", "check": "tsx .github/scripts/check-gs.ts" }, "type": "module", diff --git a/people/quickstart/quickstart.gs b/people/quickstart/quickstart.gs index a4b9512bc..68e13047b 100644 --- a/people/quickstart/quickstart.gs +++ b/people/quickstart/quickstart.gs @@ -50,22 +50,26 @@ function listConnectionNames() { // Use the People API to list the connections of the logged in user. // See: https://developers.google.com/people/api/rest/v1/people.connections/list if (!People || !People.People || !People.People.Connections) { - throw new Error('People service not enabled.'); + throw new Error("People service not enabled."); } - const connections = People.People.Connections.list('people/me', { + const connections = People.People.Connections.list("people/me", { pageSize: 10, - personFields: 'names,emailAddresses', + personFields: "names,emailAddresses", }); if (!connections.connections) { - console.log('No connections found.'); + console.log("No connections found."); return; } - connections.connections.forEach((person) => { - if (person.names && person.names.length > 0 && person.names[0].displayName) { + for (const person of connections.connections) { + if ( + person.names && + person.names.length > 0 && + person.names[0].displayName + ) { console.log(person.names[0].displayName); } else { - console.log('No display name found for connection.'); + console.log("No display name found for connection."); } - }); + } } // [END people_quickstart] diff --git a/picker/code.gs b/picker/code.gs index 3c0c363a4..2d60f0d1c 100644 --- a/picker/code.gs +++ b/picker/code.gs @@ -38,7 +38,7 @@ function showPicker() { } // Ensure the Drive API is enabled. if (!Drive) { - throw new Error('Please enable the Drive advanced service.'); + throw new Error("Please enable the Drive advanced service."); } /** @@ -47,7 +47,7 @@ if (!Drive) { * @return {Object} The file resource. */ function getFile(fileId) { - return Drive.Files.get(fileId, {fields: '*'}); + return Drive.Files.get(fileId, { fields: "*" }); } /** diff --git a/service/jdbc.gs b/service/jdbc.gs index 4f783b36b..17d21b044 100644 --- a/service/jdbc.gs +++ b/service/jdbc.gs @@ -19,15 +19,15 @@ * You can find the "Instance connection name" in the Google Cloud * Platform Console, on the instance Overview page. */ -const connectionName = 'Instance_connection_name'; -const rootPwd = 'root_password'; -const user = 'user_name'; -const userPwd = 'user_password'; -const db = 'database_name'; +const connectionName = "Instance_connection_name"; +const rootPwd = "root_password"; +const user = "user_name"; +const userPwd = "user_password"; +const db = "database_name"; -const root = 'root'; -const instanceUrl = 'jdbc:google:mysql://' + connectionName; -const dbUrl = instanceUrl + '/' + db; +const root = "root"; +const instanceUrl = `jdbc:google:mysql://${connectionName}`; +const dbUrl = `${instanceUrl}/${db}`; // [START apps_script_jdbc_create] /** @@ -36,10 +36,10 @@ const dbUrl = instanceUrl + '/' + db; function createDatabase() { try { const conn = Jdbc.getCloudSqlConnection(instanceUrl, root, rootPwd); - conn.createStatement().execute('CREATE DATABASE ' + db); + conn.createStatement().execute(`CREATE DATABASE ${db}`); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -50,15 +50,15 @@ function createUser() { try { const conn = Jdbc.getCloudSqlConnection(dbUrl, root, rootPwd); - const stmt = conn.prepareStatement('CREATE USER ? IDENTIFIED BY ?'); + const stmt = conn.prepareStatement("CREATE USER ? IDENTIFIED BY ?"); stmt.setString(1, user); stmt.setString(2, userPwd); stmt.execute(); - conn.createStatement().execute('GRANT ALL ON `%`.* TO ' + user); + conn.createStatement().execute(`GRANT ALL ON \`%\`.* TO ${user}`); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -68,12 +68,16 @@ function createUser() { function createTable() { try { const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd); - conn.createStatement().execute('CREATE TABLE entries ' + - '(guestName VARCHAR(255), content VARCHAR(255), ' + - 'entryID INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(entryID));'); + conn + .createStatement() + .execute( + "CREATE TABLE entries " + + "(guestName VARCHAR(255), content VARCHAR(255), " + + "entryID INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(entryID));", + ); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END apps_script_jdbc_create] @@ -86,14 +90,15 @@ function writeOneRecord() { try { const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd); - const stmt = conn.prepareStatement('INSERT INTO entries ' + - '(guestName, content) values (?, ?)'); - stmt.setString(1, 'First Guest'); - stmt.setString(2, 'Hello, world'); + const stmt = conn.prepareStatement( + "INSERT INTO entries " + "(guestName, content) values (?, ?)", + ); + stmt.setString(1, "First Guest"); + stmt.setString(2, "Hello, world"); stmt.execute(); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -106,11 +111,12 @@ function writeManyRecords() { conn.setAutoCommit(false); const start = new Date(); - const stmt = conn.prepareStatement('INSERT INTO entries ' + - '(guestName, content) values (?, ?)'); + const stmt = conn.prepareStatement( + "INSERT INTO entries " + "(guestName, content) values (?, ?)", + ); for (let i = 0; i < 500; i++) { - stmt.setString(1, 'Name ' + i); - stmt.setString(2, 'Hello, world ' + i); + stmt.setString(1, `Name ${i}`); + stmt.setString(2, `Hello, world ${i}`); stmt.addBatch(); } @@ -119,10 +125,10 @@ function writeManyRecords() { conn.close(); const end = new Date(); - console.log('Time elapsed: %sms for %s rows.', end - start, batch.length); + console.log("Time elapsed: %sms for %s rows.", end - start, batch.length); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -136,11 +142,12 @@ function writeManyRecordsUsingExecuteBatch() { conn.setAutoCommit(false); const start = new Date(); - const stmt = conn.prepareStatement('INSERT INTO entries ' + - '(guestName, content) values (?, ?)'); + const stmt = conn.prepareStatement( + "INSERT INTO entries " + "(guestName, content) values (?, ?)", + ); const params = []; for (let i = 0; i < 500; i++) { - params.push(['Name ' + i, 'Hello, world ' + i]); + params.push([`Name ${i}`, `Hello, world ${i}`]); } const batch = stmt.executeBatch(params); @@ -148,10 +155,10 @@ function writeManyRecordsUsingExecuteBatch() { conn.close(); const end = new Date(); - console.log('Time elapsed: %sms for %s rows.', end - start, batch.length); + console.log("Time elapsed: %sms for %s rows.", end - start, batch.length); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END apps_script_jdbc_write] @@ -166,13 +173,13 @@ function readFromTable() { const start = new Date(); const stmt = conn.createStatement(); stmt.setMaxRows(1000); - const results = stmt.executeQuery('SELECT * FROM entries'); + const results = stmt.executeQuery("SELECT * FROM entries"); const numCols = results.getMetaData().getColumnCount(); while (results.next()) { - let rowString = ''; + let rowString = ""; for (let col = 0; col < numCols; col++) { - rowString += results.getString(col + 1) + '\t'; + rowString += `${results.getString(col + 1)}\t`; } console.log(rowString); } @@ -181,10 +188,10 @@ function readFromTable() { stmt.close(); const end = new Date(); - console.log('Time elapsed: %sms', end - start); + console.log("Time elapsed: %sms", end - start); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } @@ -198,25 +205,25 @@ function readFromTableUsingGetRows() { const start = new Date(); const stmt = conn.createStatement(); stmt.setMaxRows(1000); - const results = stmt.executeQuery('SELECT * FROM entries'); + const results = stmt.executeQuery("SELECT * FROM entries"); const numCols = results.getMetaData().getColumnCount(); const getRowArgs = []; for (let col = 0; col < numCols; col++) { getRowArgs.push(`getString(${col + 1})`); } - const rows = results.getRows(getRowArgs.join(',')); + const rows = results.getRows(getRowArgs.join(",")); for (let i = 0; i < rows.length; i++) { - console.log(rows[i].join('\t')); + console.log(rows[i].join("\t")); } results.close(); stmt.close(); const end = new Date(); - console.log('Time elapsed: %sms', end - start); + console.log("Time elapsed: %sms", end - start); } catch (err) { // TODO(developer) - Handle exception from the API - console.log('Failed with an error %s', err.message); + console.log("Failed with an error %s", err.message); } } // [END apps_script_jdbc_read] diff --git a/service/propertyService.gs b/service/propertyService.gs index 593ab0dfb..df0797370 100644 --- a/service/propertyService.gs +++ b/service/propertyService.gs @@ -25,13 +25,15 @@ function saveSingleProperty() { const userProperties = PropertiesService.getUserProperties(); const documentProperties = PropertiesService.getDocumentProperties(); - scriptProperties.setProperty('SERVER_URL', 'http://www.example.com/'); - userProperties.setProperty('DISPLAY_UNITS', 'metric'); - documentProperties.setProperty('SOURCE_DATA_ID', - '1j3GgabZvXUF177W0Zs_2v--H6SPCQb4pmZ6HsTZYT5k'); + scriptProperties.setProperty("SERVER_URL", "http://www.example.com/"); + userProperties.setProperty("DISPLAY_UNITS", "metric"); + documentProperties.setProperty( + "SOURCE_DATA_ID", + "1j3GgabZvXUF177W0Zs_2v--H6SPCQb4pmZ6HsTZYT5k", + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_save_data_single_value] } @@ -45,13 +47,13 @@ function saveMultipleProperties() { // Set multiple script properties in one call. const scriptProperties = PropertiesService.getScriptProperties(); scriptProperties.setProperties({ - 'cow': 'moo', - 'sheep': 'baa', - 'chicken': 'cluck' + cow: "moo", + sheep: "baa", + chicken: "cluck", }); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_save_data_multiple_value] } @@ -64,11 +66,11 @@ function readSingleProperty() { try { // Get the value for the user property 'DISPLAY_UNITS'. const userProperties = PropertiesService.getUserProperties(); - const units = userProperties.getProperty('DISPLAY_UNITS'); - console.log('values of units %s', units); + const units = userProperties.getProperty("DISPLAY_UNITS"); + console.log("values of units %s", units); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_read_data_single_value] } @@ -83,11 +85,11 @@ function readAllProperties() { const scriptProperties = PropertiesService.getScriptProperties(); const data = scriptProperties.getProperties(); for (const key in data) { - console.log('Key: %s, Value: %s', key, data[key]); + console.log("Key: %s, Value: %s", key, data[key]); } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_read_multiple_data_value] } @@ -100,12 +102,12 @@ function updateProperty() { try { // Change the unit type in the user property 'DISPLAY_UNITS'. const userProperties = PropertiesService.getUserProperties(); - let units = userProperties.getProperty('DISPLAY_UNITS'); - units = 'imperial'; // Only changes local value, not stored value. - userProperties.setProperty('DISPLAY_UNITS', units); // Updates stored value. + let units = userProperties.getProperty("DISPLAY_UNITS"); + units = "imperial"; // Only changes local value, not stored value. + userProperties.setProperty("DISPLAY_UNITS", units); // Updates stored value. } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_modify_data] } @@ -118,10 +120,10 @@ function deleteSingleProperty() { try { // Delete the user property 'DISPLAY_UNITS'. const userProperties = PropertiesService.getUserProperties(); - userProperties.deleteProperty('DISPLAY_UNITS'); + userProperties.deleteProperty("DISPLAY_UNITS"); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_delete_data_single_value] } @@ -138,7 +140,7 @@ function deleteAllUserProperties() { userProperties.deleteAllProperties(); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } // [END apps_script_property_service_delete_all_data] } diff --git a/service/test_jdbc.gs b/service/test_jdbc.gs index 875fc30ab..dafc6f3c4 100644 --- a/service/test_jdbc.gs +++ b/service/test_jdbc.gs @@ -14,12 +14,11 @@ * limitations under the License. */ - /** * Tests createDatabase function of jdbc.gs */ function itShouldCreateDatabase() { - console.log('itShouldCreateDatabase'); + console.log("itShouldCreateDatabase"); createDatabase(); } @@ -27,7 +26,7 @@ function itShouldCreateDatabase() { * Tests createUser function of jdbc.gs */ function itShouldCreateUser() { - console.log('itShouldCreateUser'); + console.log("itShouldCreateUser"); createUser(); } @@ -35,7 +34,7 @@ function itShouldCreateUser() { * Tests createTable function of jdbc.gs */ function itShouldCreateTable() { - console.log('itShouldCreateTable'); + console.log("itShouldCreateTable"); createTable(); } @@ -43,7 +42,7 @@ function itShouldCreateTable() { * Tests writeOneRecord function of jdbc.gs */ function itShouldWriteOneRecord() { - console.log('itShouldWriteOneRecord'); + console.log("itShouldWriteOneRecord"); writeOneRecord(); } @@ -51,7 +50,7 @@ function itShouldWriteOneRecord() { * Tests writeManyRecords function of jdbc.gs */ function itShouldWriteManyRecords() { - console.log('itShouldWriteManyRecords'); + console.log("itShouldWriteManyRecords"); writeManyRecords(); } @@ -59,16 +58,15 @@ function itShouldWriteManyRecords() { * Tests writeManyRecordsUsingExecuteBatch function of jdbc.gs */ function itShouldWriteManyRecordsUsingExecuteBatch() { - console.log('itShouldWriteManyRecordsUsingExecuteBatch'); + console.log("itShouldWriteManyRecordsUsingExecuteBatch"); writeManyRecordsUsingExecuteBatch(); } - /** * Tests readFromTable function of jdbc.gs */ function itShouldReadFromTable() { - console.log('itShouldReadFromTable'); + console.log("itShouldReadFromTable"); readFromTable(); } @@ -76,7 +74,7 @@ function itShouldReadFromTable() { * Tests readFromTableUsingGetRows function of jdbc.gs */ function itShouldReadFromTableUsingGetRows() { - console.log('itShouldReadFromTableUsingGetRows'); + console.log("itShouldReadFromTableUsingGetRows"); readFromTableUsingGetRows(); } diff --git a/service/test_propertyServices.gs b/service/test_propertyServices.gs index a2fbbca6e..e7ae93e9d 100644 --- a/service/test_propertyServices.gs +++ b/service/test_propertyServices.gs @@ -18,19 +18,19 @@ * Run all tests for propertyService.gs */ function RUN_ALL_TESTS() { - console.log('> itShouldSaveSingleProperty'); + console.log("> itShouldSaveSingleProperty"); saveSingleProperty(); - console.log('> itShouldSaveMultipleProperties'); + console.log("> itShouldSaveMultipleProperties"); saveMultipleProperties(); - console.log('> itShouldReadSingleProperty'); + console.log("> itShouldReadSingleProperty"); readSingleProperty(); - console.log('> itShouldReadAllProperties'); + console.log("> itShouldReadAllProperties"); readAllProperties(); // The tests below are successful if they run without any extra output - console.log('> itShouldUpdateProperty'); + console.log("> itShouldUpdateProperty"); updateProperty(); - console.log('> itShouldDeleteSingleProperty'); + console.log("> itShouldDeleteSingleProperty"); deleteSingleProperty(); - console.log('> itShouldDeleteAllUserProperties'); + console.log("> itShouldDeleteAllUserProperties"); deleteAllUserProperties(); } diff --git a/sheets/api/helpers.gs b/sheets/api/helpers.gs index 68ad23f58..6244b09af 100644 --- a/sheets/api/helpers.gs +++ b/sheets/api/helpers.gs @@ -1,4 +1,4 @@ -let filesToDelete = []; +const filesToDelete = []; /** * Helper methods for Google Sheets tests. */ @@ -6,20 +6,20 @@ function Helpers() { this.filesToDelete = []; } -Helpers.prototype.reset = function() { +Helpers.prototype.reset = function () { this.filesToDelete = []; }; -Helpers.prototype.deleteFileOnCleanup = function(id) { +Helpers.prototype.deleteFileOnCleanup = function (id) { this.filesToDelete.push(id); }; -Helpers.prototype.cleanup = function() { +Helpers.prototype.cleanup = () => { filesToDelete.forEach(Drive.Files.remove); }; -Helpers.prototype.createTestSpreadsheet = function() { - const spreadsheet = SpreadsheetApp.create('Test Spreadsheet'); +Helpers.prototype.createTestSpreadsheet = function () { + const spreadsheet = SpreadsheetApp.create("Test Spreadsheet"); for (let i = 0; i < 3; ++i) { spreadsheet.appendRow([1, 2, 3]); } @@ -27,18 +27,18 @@ Helpers.prototype.createTestSpreadsheet = function() { return spreadsheet.getId(); }; -Helpers.prototype.populateValues = function(spreadsheetId) { +Helpers.prototype.populateValues = (spreadsheetId) => { const batchUpdateRequest = Sheets.newBatchUpdateSpreadsheetRequest(); const repeatCellRequest = Sheets.newRepeatCellRequest(); - let values = []; + const values = []; for (let i = 0; i < 10; ++i) { values[i] = []; for (let j = 0; j < 10; ++j) { - values[i].push('Hello'); + values[i].push("Hello"); } } - let range = 'A1:J10'; + const range = "A1:J10"; SpreadsheetApp.openById(spreadsheetId).getRange(range).setValues(values); SpreadsheetApp.flush(); }; diff --git a/sheets/api/spreadsheet_snippets.gs b/sheets/api/spreadsheet_snippets.gs index 4d08b67b3..021f97689 100644 --- a/sheets/api/spreadsheet_snippets.gs +++ b/sheets/api/spreadsheet_snippets.gs @@ -17,7 +17,7 @@ /** * Google Sheets API Snippets. */ -function Snippets() {}; +function Snippets() {} // [START sheets_create] /** @@ -29,7 +29,7 @@ Snippets.prototype.create = (title) => { // This code uses the Sheets Advanced Service, but for most use cases // the built-in method SpreadsheetApp.create() is more appropriate. try { - let sheet = Sheets.newSpreadsheet(); + const sheet = Sheets.newSpreadsheet(); sheet.properties = Sheets.newSpreadsheetProperties(); sheet.properties.title = title; const spreadsheet = Sheets.Spreadsheets.create(sheet); @@ -37,7 +37,7 @@ Snippets.prototype.create = (title) => { return spreadsheet.spreadsheetId; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_create] @@ -51,42 +51,43 @@ Snippets.prototype.create = (title) => { * @param {string} replacement the string to replace the old data * @returns {*} the updated spreadsheet */ -Snippets.prototype.batchUpdate = (spreadsheetId, title, - find, replacement) => { +Snippets.prototype.batchUpdate = (spreadsheetId, title, find, replacement) => { // This code uses the Sheets Advanced Service, but for most use cases // the built-in method SpreadsheetApp.getActiveSpreadsheet() // .getRange(range).setValues(values) is more appropriate. try { // Change the spreadsheet's title. - let updateSpreadsheetPropertiesRequest = + const updateSpreadsheetPropertiesRequest = Sheets.newUpdateSpreadsheetPropertiesRequest(); updateSpreadsheetPropertiesRequest.properties = Sheets.newSpreadsheetProperties(); updateSpreadsheetPropertiesRequest.properties.title = title; - updateSpreadsheetPropertiesRequest.fields = 'title'; + updateSpreadsheetPropertiesRequest.fields = "title"; // Find and replace text. - let findReplaceRequest = Sheets.newFindReplaceRequest(); + const findReplaceRequest = Sheets.newFindReplaceRequest(); findReplaceRequest.find = find; findReplaceRequest.replacement = replacement; findReplaceRequest.allSheets = true; - let requests = [Sheets.newRequest(), Sheets.newRequest()]; + const requests = [Sheets.newRequest(), Sheets.newRequest()]; requests[0].updateSpreadsheetProperties = updateSpreadsheetPropertiesRequest; requests[1].findReplace = findReplaceRequest; - let batchUpdateRequest = Sheets.newBatchUpdateSpreadsheetRequest(); + const batchUpdateRequest = Sheets.newBatchUpdateSpreadsheetRequest(); batchUpdateRequest.requests = requests; // Add additional requests (operations) - const result = - Sheets.Spreadsheets.batchUpdate(batchUpdateRequest, spreadsheetId); + const result = Sheets.Spreadsheets.batchUpdate( + batchUpdateRequest, + spreadsheetId, + ); return result; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_batch_update] @@ -98,7 +99,7 @@ Snippets.prototype.batchUpdate = (spreadsheetId, title, * @param {string} range specifying the start and end cells of the range * @returns {*} Values in the range */ -Snippets.prototype.getValues = function(spreadsheetId, range) { +Snippets.prototype.getValues = (spreadsheetId, range) => { // This code uses the Sheets Advanced Service, but for most use cases // the built-in method SpreadsheetApp.getActiveSpreadsheet() // .getRange(range).getValues(values) is more appropriate. @@ -108,7 +109,7 @@ Snippets.prototype.getValues = function(spreadsheetId, range) { return result; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_get_values] @@ -120,8 +121,7 @@ Snippets.prototype.getValues = function(spreadsheetId, range) { * @param {list} _ranges The span of ranges * @returns {*} spreadsheet information and values */ -Snippets.prototype.batchGetValues = (spreadsheetId, - _ranges) => { +Snippets.prototype.batchGetValues = (spreadsheetId, _ranges) => { // This code uses the Sheets Advanced Service, but for most use cases // the built-in method SpreadsheetApp.getActiveSpreadsheet() // .getRange(range).getValues(values) is more appropriate. @@ -132,12 +132,13 @@ Snippets.prototype.batchGetValues = (spreadsheetId, ranges = _ranges; // [END_EXCLUDE] try { - const result = - Sheets.Spreadsheets.Values.batchGet(spreadsheetId, {ranges: ranges}); + const result = Sheets.Spreadsheets.Values.batchGet(spreadsheetId, { + ranges: ranges, + }); return result; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_batch_get_values] @@ -153,15 +154,19 @@ Snippets.prototype.batchGetValues = (spreadsheetId, * @param {list>} _values list of string lists to input * @returns {*} spreadsheet with updated values */ -Snippets.prototype.updateValues = (spreadsheetId, range, - valueInputOption, _values) => { +Snippets.prototype.updateValues = ( + spreadsheetId, + range, + valueInputOption, + _values, +) => { // This code uses the Sheets Advanced Service, but for most use cases // the built-in method SpreadsheetApp.getActiveSpreadsheet() // .getRange(range).setValues(values) is more appropriate. let values = [ [ // Cell values ... - ] + ], // Additional rows ... ]; // [START_EXCLUDE silent] @@ -169,14 +174,18 @@ Snippets.prototype.updateValues = (spreadsheetId, range, // [END_EXCLUDE] try { - let valueRange = Sheets.newValueRange(); + const valueRange = Sheets.newValueRange(); valueRange.values = values; - const result = Sheets.Spreadsheets.Values.update(valueRange, - spreadsheetId, range, {valueInputOption: valueInputOption}); + const result = Sheets.Spreadsheets.Values.update( + valueRange, + spreadsheetId, + range, + { valueInputOption: valueInputOption }, + ); return result; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_update_values] @@ -192,39 +201,44 @@ Snippets.prototype.updateValues = (spreadsheetId, range, * @param {list>} _values list of string values to input * @returns {*} spreadsheet with updated values */ -Snippets.prototype.batchUpdateValues = - (spreadsheetId, range, valueInputOption, - _values) => { - // This code uses the Sheets Advanced Service, but for most use cases - // the built-in method SpreadsheetApp.getActiveSpreadsheet() - // .getRange(range).setValues(values) is more appropriate. - let values = [ - [ - // Cell values ... - ] - // Additional rows ... - ]; - // [START_EXCLUDE silent] - values = _values; - // [END_EXCLUDE] - - try { - let valueRange = Sheets.newValueRange(); - valueRange.range = range; - valueRange.values = values; - - let batchUpdateRequest = Sheets.newBatchUpdateValuesRequest(); - batchUpdateRequest.data = valueRange; - batchUpdateRequest.valueInputOption = valueInputOption; - - const result = Sheets.Spreadsheets.Values.batchUpdate(batchUpdateRequest, - spreadsheetId); - return result; - } catch (err) { - // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); - } - }; +Snippets.prototype.batchUpdateValues = ( + spreadsheetId, + range, + valueInputOption, + _values, +) => { + // This code uses the Sheets Advanced Service, but for most use cases + // the built-in method SpreadsheetApp.getActiveSpreadsheet() + // .getRange(range).setValues(values) is more appropriate. + let values = [ + [ + // Cell values ... + ], + // Additional rows ... + ]; + // [START_EXCLUDE silent] + values = _values; + // [END_EXCLUDE] + + try { + const valueRange = Sheets.newValueRange(); + valueRange.range = range; + valueRange.values = values; + + const batchUpdateRequest = Sheets.newBatchUpdateValuesRequest(); + batchUpdateRequest.data = valueRange; + batchUpdateRequest.valueInputOption = valueInputOption; + + const result = Sheets.Spreadsheets.Values.batchUpdate( + batchUpdateRequest, + spreadsheetId, + ); + return result; + } catch (err) { + // TODO (developer) - Handle exception + console.log("Failed with error %s", err.message); + } +}; // [END sheets_batch_update_values] // [START sheets_append_values] @@ -238,31 +252,39 @@ Snippets.prototype.batchUpdateValues = * @param {list} _values list of rows of values to input * @returns {*} spreadsheet with appended values */ -Snippets.prototype.appendValues = (spreadsheetId, range, - valueInputOption, _values) => { +Snippets.prototype.appendValues = ( + spreadsheetId, + range, + valueInputOption, + _values, +) => { let values = [ [ // Cell values ... - ] + ], // Additional rows ... ]; // [START_EXCLUDE silent] values = _values; // [END_EXCLUDE] try { - let valueRange = Sheets.newRowData(); + const valueRange = Sheets.newRowData(); valueRange.values = values; - let appendRequest = Sheets.newAppendCellsRequest(); + const appendRequest = Sheets.newAppendCellsRequest(); appendRequest.sheetId = spreadsheetId; appendRequest.rows = [valueRange]; - const result = Sheets.Spreadsheets.Values.append(valueRange, spreadsheetId, - range, {valueInputOption: valueInputOption}); + const result = Sheets.Spreadsheets.Values.append( + valueRange, + spreadsheetId, + range, + { valueInputOption: valueInputOption }, + ); return result; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_append_values] @@ -278,7 +300,7 @@ Snippets.prototype.pivotTable = (spreadsheetId) => { const spreadsheet = SpreadsheetApp.openById(spreadsheetId); // Create two sheets for our pivot table, assume we have one. - let sheet = spreadsheet.getSheets()[0]; + const sheet = spreadsheet.getSheets()[0]; sheet.copyTo(spreadsheet); const sourceSheetId = spreadsheet.getSheets()[0].getSheetId(); @@ -287,7 +309,7 @@ Snippets.prototype.pivotTable = (spreadsheetId) => { // Create pivot table const pivotTable = Sheets.newPivotTable(); - let gridRange = Sheets.newGridRange(); + const gridRange = Sheets.newGridRange(); gridRange.sheetId = sourceSheetId; gridRange.startRowIndex = 0; gridRange.startColumnIndex = 0; @@ -295,52 +317,54 @@ Snippets.prototype.pivotTable = (spreadsheetId) => { gridRange.endColumnIndex = 7; pivotTable.source = gridRange; - let pivotRows = Sheets.newPivotGroup(); + const pivotRows = Sheets.newPivotGroup(); pivotRows.sourceColumnOffset = 1; pivotRows.showTotals = true; - pivotRows.sortOrder = 'ASCENDING'; + pivotRows.sortOrder = "ASCENDING"; pivotTable.rows = pivotRows; - let pivotColumns = Sheets.newPivotGroup(); + const pivotColumns = Sheets.newPivotGroup(); pivotColumns.sourceColumnOffset = 4; - pivotColumns.sortOrder = 'ASCENDING'; + pivotColumns.sortOrder = "ASCENDING"; pivotColumns.showTotals = true; pivotTable.columns = pivotColumns; - let pivotValue = Sheets.newPivotValue(); - pivotValue.summarizeFunction = 'COUNTA'; + const pivotValue = Sheets.newPivotValue(); + pivotValue.summarizeFunction = "COUNTA"; pivotValue.sourceColumnOffset = 4; pivotTable.values = [pivotValue]; // Create other metadata for the updateCellsRequest - let cellData = Sheets.newCellData(); + const cellData = Sheets.newCellData(); cellData.pivotTable = pivotTable; - let rows = Sheets.newRowData(); + const rows = Sheets.newRowData(); rows.values = cellData; - let start = Sheets.newGridCoordinate(); + const start = Sheets.newGridCoordinate(); start.sheetId = targetSheetId; start.rowIndex = 0; start.columnIndex = 0; - let updateCellsRequest = Sheets.newUpdateCellsRequest(); + const updateCellsRequest = Sheets.newUpdateCellsRequest(); updateCellsRequest.rows = rows; updateCellsRequest.start = start; - updateCellsRequest.fields = 'pivotTable'; + updateCellsRequest.fields = "pivotTable"; // Batch update our spreadsheet - let batchUpdate = Sheets.newBatchUpdateSpreadsheetRequest(); - let updateCellsRawRequest = Sheets.newRequest(); + const batchUpdate = Sheets.newBatchUpdateSpreadsheetRequest(); + const updateCellsRawRequest = Sheets.newRequest(); updateCellsRawRequest.updateCells = updateCellsRequest; batchUpdate.requests = [updateCellsRawRequest]; - const response = Sheets.Spreadsheets.batchUpdate(batchUpdate, - spreadsheetId); + const response = Sheets.Spreadsheets.batchUpdate( + batchUpdate, + spreadsheetId, + ); return response; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_pivot_tables] @@ -353,7 +377,7 @@ Snippets.prototype.pivotTable = (spreadsheetId) => { */ Snippets.prototype.conditionalFormatting = (spreadsheetId) => { try { - let myRange = Sheets.newGridRange(); + const myRange = Sheets.newGridRange(); myRange.sheetId = 0; myRange.startRowIndex = 0; myRange.endRowIndex = 11; @@ -361,58 +385,58 @@ Snippets.prototype.conditionalFormatting = (spreadsheetId) => { myRange.endColumnIndex = 4; // Request 1 - let rule1ConditionalValue = Sheets.newConditionValue(); - rule1ConditionalValue.userEnteredValue = '=GT($D2,median($D$2:$D$11))'; + const rule1ConditionalValue = Sheets.newConditionValue(); + rule1ConditionalValue.userEnteredValue = "=GT($D2,median($D$2:$D$11))"; - let rule1ConditionFormat = Sheets.newCellFormat(); + const rule1ConditionFormat = Sheets.newCellFormat(); rule1ConditionFormat.textFormat = Sheets.newTextFormat(); rule1ConditionFormat.textFormat.foregroundColor = Sheets.newColor(); rule1ConditionFormat.textFormat.foregroundColor.red = 0.8; - let rule1Condition = Sheets.newBooleanCondition(); - rule1Condition.type = 'CUSTOM_FORMULA'; + const rule1Condition = Sheets.newBooleanCondition(); + rule1Condition.type = "CUSTOM_FORMULA"; rule1Condition.values = [rule1ConditionalValue]; - let rule1BooleanRule = Sheets.newBooleanRule(); + const rule1BooleanRule = Sheets.newBooleanRule(); rule1BooleanRule.condition = rule1Condition; rule1BooleanRule.format = rule1ConditionFormat; - let rule1 = Sheets.newConditionalFormatRule(); + const rule1 = Sheets.newConditionalFormatRule(); rule1.ranges = [myRange]; rule1.booleanRule = rule1BooleanRule; - let request1 = Sheets.newRequest(); - let addConditionalFormatRuleRequest1 = + const request1 = Sheets.newRequest(); + const addConditionalFormatRuleRequest1 = Sheets.newAddConditionalFormatRuleRequest(); addConditionalFormatRuleRequest1.rule = rule1; addConditionalFormatRuleRequest1.index = 0; request1.addConditionalFormatRule = addConditionalFormatRuleRequest1; // Request 2 - let rule2ConditionalValue = Sheets.newConditionValue(); - rule2ConditionalValue.userEnteredValue = '=LT($D2,median($D$2:$D$11))'; + const rule2ConditionalValue = Sheets.newConditionValue(); + rule2ConditionalValue.userEnteredValue = "=LT($D2,median($D$2:$D$11))"; - let rule2ConditionFormat = Sheets.newCellFormat(); + const rule2ConditionFormat = Sheets.newCellFormat(); rule2ConditionFormat.textFormat = Sheets.newTextFormat(); rule2ConditionFormat.textFormat.foregroundColor = Sheets.newColor(); rule2ConditionFormat.textFormat.foregroundColor.red = 1; rule2ConditionFormat.textFormat.foregroundColor.green = 0.4; rule2ConditionFormat.textFormat.foregroundColor.blue = 0.4; - let rule2Condition = Sheets.newBooleanCondition(); - rule2Condition.type = 'CUSTOM_FORMULA'; + const rule2Condition = Sheets.newBooleanCondition(); + rule2Condition.type = "CUSTOM_FORMULA"; rule2Condition.values = [rule2ConditionalValue]; - let rule2BooleanRule = Sheets.newBooleanRule(); + const rule2BooleanRule = Sheets.newBooleanRule(); rule2BooleanRule.condition = rule2Condition; rule2BooleanRule.format = rule2ConditionFormat; - let rule2 = Sheets.newConditionalFormatRule(); + const rule2 = Sheets.newConditionalFormatRule(); rule2.ranges = [myRange]; rule2.booleanRule = rule2BooleanRule; - let request2 = Sheets.newRequest(); - let addConditionalFormatRuleRequest2 = + const request2 = Sheets.newRequest(); + const addConditionalFormatRuleRequest2 = Sheets.newAddConditionalFormatRuleRequest(); addConditionalFormatRuleRequest2.rule = rule2; addConditionalFormatRuleRequest2.index = 0; @@ -420,14 +444,16 @@ Snippets.prototype.conditionalFormatting = (spreadsheetId) => { // Batch send the requests const requests = [request1, request2]; - let batchUpdate = Sheets.newBatchUpdateSpreadsheetRequest(); + const batchUpdate = Sheets.newBatchUpdateSpreadsheetRequest(); batchUpdate.requests = requests; - const response = - Sheets.Spreadsheets.batchUpdate(batchUpdate, spreadsheetId); + const response = Sheets.Spreadsheets.batchUpdate( + batchUpdate, + spreadsheetId, + ); return response; } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } }; // [END sheets_conditional_formatting] diff --git a/sheets/api/test_spreadsheet_snippets.gs b/sheets/api/test_spreadsheet_snippets.gs index 80f3796b8..a0c5305ec 100644 --- a/sheets/api/test_spreadsheet_snippets.gs +++ b/sheets/api/test_spreadsheet_snippets.gs @@ -1,5 +1,5 @@ -let snippets = new Snippets(); -let helpers = new Helpers(); +const snippets = new Snippets(); +const helpers = new Helpers(); /** * A simple exists assertion check. Expects a value to exist. Errors if DNE. @@ -7,9 +7,9 @@ let helpers = new Helpers(); */ function expectToExist(value) { if (value) { - console.log('TEST: Exists'); + console.log("TEST: Exists"); } else { - throw new Error('TEST: DNE'); + throw new Error("TEST: DNE"); } } @@ -20,9 +20,9 @@ function expectToExist(value) { * @param {any} expected The expected value. */ function expectToEqual(actual, expected) { - console.log('TEST: actual: %s = expected: %s', actual, expected); + console.log("TEST: actual: %s = expected: %s", actual, expected); if (actual !== expected) { - console.log('TEST: actual: %s expected: %s', actual, expected); + console.log("TEST: actual: %s expected: %s", actual, expected); } } @@ -45,7 +45,7 @@ function RUN_ALL_TESTS() { * Tests creating a spreadsheet. */ function itShouldCreateASpreadsheet() { - const spreadsheetId = snippets.create('Title'); + const spreadsheetId = snippets.create("Title"); expectToExist(spreadsheetId); helpers.deleteFileOnCleanup(spreadsheetId); } @@ -56,8 +56,12 @@ function itShouldCreateASpreadsheet() { function itShouldBatchUpdateASpreadsheet() { const spreadsheetId = helpers.createTestSpreadsheet(); helpers.populateValues(spreadsheetId); - const result = snippets.batchUpdate(spreadsheetId, 'New Title', - 'Hello', 'Goodbye'); + const result = snippets.batchUpdate( + spreadsheetId, + "New Title", + "Hello", + "Goodbye", + ); const replies = result.replies; expectToEqual(replies.length, 2); const findReplaceResponse = replies[1].findReplace; @@ -70,7 +74,7 @@ function itShouldBatchUpdateASpreadsheet() { function itShouldGetSpreadsheetValues() { const spreadsheetId = helpers.createTestSpreadsheet(); helpers.populateValues(spreadsheetId); - const result = snippets.getValues(spreadsheetId, 'A1:C2'); + const result = snippets.getValues(spreadsheetId, "A1:C2"); const values = result.values; expectToEqual(values.length, 2); expectToEqual(values[0].length, 3); @@ -82,8 +86,7 @@ function itShouldGetSpreadsheetValues() { function itShouldBatchGetSpreadsheetValues() { const spreadsheetId = helpers.createTestSpreadsheet(); helpers.populateValues(spreadsheetId); - const result = snippets.batchGetValues(spreadsheetId, - ['A1:A3', 'B1:C1']); + const result = snippets.batchGetValues(spreadsheetId, ["A1:A3", "B1:C1"]); expectToExist(result); expectToEqual(result.valueRanges.length, 2); expectToEqual(result.valueRanges[0].values.length, 3); @@ -94,8 +97,10 @@ function itShouldBatchGetSpreadsheetValues() { */ function itShouldUpdateSpreadsheetValues() { const spreadsheetId = helpers.createTestSpreadsheet(); - const result = snippets.updateValues(spreadsheetId, 'A1:B2', - 'USER_ENTERED', [['A', 'B'], ['C', 'D']]); + const result = snippets.updateValues(spreadsheetId, "A1:B2", "USER_ENTERED", [ + ["A", "B"], + ["C", "D"], + ]); expectToEqual(result.updatedRows, 2); expectToEqual(result.updatedColumns, 2); expectToEqual(result.updatedCells, 4); @@ -106,8 +111,15 @@ function itShouldUpdateSpreadsheetValues() { */ function itShouldBatchUpdateSpreadsheetValues() { const spreadsheetId = helpers.createTestSpreadsheet(); - const result = snippets.batchUpdateValues(spreadsheetId, 'A1:B2', - 'USER_ENTERED', [['A', 'B'], ['C', 'D']]); + const result = snippets.batchUpdateValues( + spreadsheetId, + "A1:B2", + "USER_ENTERED", + [ + ["A", "B"], + ["C", "D"], + ], + ); expectToEqual(result.totalUpdatedRows, 2); expectToEqual(result.totalUpdatedColumns, 2); expectToEqual(result.totalUpdatedCells, 4); @@ -119,8 +131,15 @@ function itShouldBatchUpdateSpreadsheetValues() { function itShouldAppendValuesToASpreadsheet() { const spreadsheetId = helpers.createTestSpreadsheet(); helpers.populateValues(spreadsheetId); - const result = snippets.appendValues(spreadsheetId, 'Sheet1', - 'USER_ENTERED', [['A', 'B'], ['C', 'D']]); + const result = snippets.appendValues( + spreadsheetId, + "Sheet1", + "USER_ENTERED", + [ + ["A", "B"], + ["C", "D"], + ], + ); const updates = result.updates; expectToEqual(updates.updatedRows, 2); expectToEqual(updates.updatedColumns, 2); diff --git a/sheets/customFunctions/btc.gs b/sheets/customFunctions/btc.gs index 1670b4241..c47ba9beb 100644 --- a/sheets/customFunctions/btc.gs +++ b/sheets/customFunctions/btc.gs @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + // See https://support.coinbase.com/customer/en/portal/articles/1914910-how-can-i-generate-api-keys-within-coinbase-commerce- -var COINBASE_API_TOKEN = ''; // TODO +const COINBASE_API_TOKEN = ""; // TODO /** * Get's the bitcoin price at a date. * @@ -24,17 +24,20 @@ var COINBASE_API_TOKEN = ''; // TODO * @customfunction */ function BTC(date) { - var dateObject = new Date(); + let dateObject = new Date(); if (date) { dateObject = new Date(date); } - var dateString = Utilities.formatDate(dateObject, "GMT", "yyyy-MM-dd"); - var res = UrlFetchApp.fetch("https://api.coinbase.com/v2/prices/BTC-USD/spot?date=" + dateString, { - headers: { - "CB-VERSION": "2016-10-10", - Authorization: "Bearer " + COINBASE_API_TOKEN - } - }); - var json = JSON.parse(res.getContentText()); + const dateString = Utilities.formatDate(dateObject, "GMT", "yyyy-MM-dd"); + const res = UrlFetchApp.fetch( + `https://api.coinbase.com/v2/prices/BTC-USD/spot?date=${dateString}`, + { + headers: { + "CB-VERSION": "2016-10-10", + Authorization: `Bearer ${COINBASE_API_TOKEN}`, + }, + }, + ); + const json = JSON.parse(res.getContentText()); return json.data.amount; } diff --git a/sheets/customFunctions/customFunctions.gs b/sheets/customFunctions/customFunctions.gs index 9fe44c0ac..27e632423 100644 --- a/sheets/customFunctions/customFunctions.gs +++ b/sheets/customFunctions/customFunctions.gs @@ -26,13 +26,13 @@ function onOpen() { try { const spreadsheet = SpreadsheetApp.getActive(); const menuItems = [ - {name: 'Prepare sheet...', functionName: 'prepareSheet_'}, - {name: 'Generate step-by-step...', functionName: 'generateStepByStep_'} + { name: "Prepare sheet...", functionName: "prepareSheet_" }, + { name: "Generate step-by-step...", functionName: "generateStepByStep_" }, ]; - spreadsheet.addMenu('Directions', menuItems); + spreadsheet.addMenu("Directions", menuItems); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -43,10 +43,10 @@ function onOpen() { * @return {Number} The distance in miles. */ function metersToMiles(meters) { - if (typeof meters !== 'number') { + if (typeof meters !== "number") { return null; } - return meters / 1000 * 0.621371; + return (meters / 1000) * 0.621371; } /** @@ -66,22 +66,24 @@ function drivingDistance(origin, destination) { */ function prepareSheet_() { try { - const sheet = SpreadsheetApp.getActiveSheet().setName('Settings'); + const sheet = SpreadsheetApp.getActiveSheet().setName("Settings"); const headers = [ - 'Start Address', - 'End Address', - 'Driving Distance (meters)', - 'Driving Distance (miles)']; + "Start Address", + "End Address", + "Driving Distance (meters)", + "Driving Distance (miles)", + ]; const initialData = [ - '350 5th Ave, New York, NY 10118', - '405 Lexington Ave, New York, NY 10174']; - sheet.getRange('A1:D1').setValues([headers]).setFontWeight('bold'); - sheet.getRange('A2:B2').setValues([initialData]); + "350 5th Ave, New York, NY 10118", + "405 Lexington Ave, New York, NY 10174", + ]; + sheet.getRange("A1:D1").setValues([headers]).setFontWeight("bold"); + sheet.getRange("A2:B2").setValues([initialData]); sheet.setFrozenRows(1); sheet.autoResizeColumns(1, 4); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -92,35 +94,46 @@ function prepareSheet_() { function generateStepByStep_() { try { const spreadsheet = SpreadsheetApp.getActive(); - const settingsSheet = spreadsheet.getSheetByName('Settings'); + const settingsSheet = spreadsheet.getSheetByName("Settings"); settingsSheet.activate(); // Prompt the user for a row number. - const selectedRow = Browser - .inputBox('Generate step-by-step', 'Please enter the row number of' + - ' the' + ' addresses to use' + ' (for example, "2"):', - Browser.Buttons.OK_CANCEL); - if (selectedRow === 'cancel') { + const selectedRow = Browser.inputBox( + "Generate step-by-step", + "Please enter the row number of" + + " the" + + " addresses to use" + + ' (for example, "2"):', + Browser.Buttons.OK_CANCEL, + ); + if (selectedRow === "cancel") { return; } const rowNumber = Number(selectedRow); - if (isNaN(rowNumber) || rowNumber < 2 || - rowNumber > settingsSheet.getLastRow()) { - Browser.msgBox('Error', - Utilities.formatString('Row "%s" is not valid.', selectedRow), - Browser.Buttons.OK); + if ( + Number.isNaN(rowNumber) || + rowNumber < 2 || + rowNumber > settingsSheet.getLastRow() + ) { + Browser.msgBox( + "Error", + Utilities.formatString('Row "%s" is not valid.', selectedRow), + Browser.Buttons.OK, + ); return; } - // Retrieve the addresses in that row. const row = settingsSheet.getRange(rowNumber, 1, 1, 2); const rowValues = row.getValues(); const origin = rowValues[0][0]; const destination = rowValues[0][1]; if (!origin || !destination) { - Browser.msgBox('Error', 'Row does not contain two addresses.', - Browser.Buttons.OK); + Browser.msgBox( + "Error", + "Row does not contain two addresses.", + Browser.Buttons.OK, + ); return; } @@ -128,51 +141,57 @@ function generateStepByStep_() { const directions = getDirections_(origin, destination); // Create a new sheet and append the steps in the directions. - const sheetName = 'Driving Directions for Row ' + rowNumber; + const sheetName = `Driving Directions for Row ${rowNumber}`; let directionsSheet = spreadsheet.getSheetByName(sheetName); if (directionsSheet) { directionsSheet.clear(); directionsSheet.activate(); } else { - directionsSheet = - spreadsheet.insertSheet(sheetName, spreadsheet.getNumSheets()); + directionsSheet = spreadsheet.insertSheet( + sheetName, + spreadsheet.getNumSheets(), + ); } - const sheetTitle = Utilities - .formatString('Driving Directions from %s to %s', origin, destination); + const sheetTitle = Utilities.formatString( + "Driving Directions from %s to %s", + origin, + destination, + ); const headers = [ - [sheetTitle, '', ''], - ['Step', 'Distance (Meters)', 'Distance (Miles)'] + [sheetTitle, "", ""], + ["Step", "Distance (Meters)", "Distance (Miles)"], ]; const newRows = []; for (const step of directions.routes[0].legs[0].steps) { // Remove HTML tags from the instructions. const instructions = step.html_instructions - .replace(/
|/g, '\n').replace(/<.*?>/g, ''); - newRows.push([ - instructions, - step.distance.value - ]); + .replace(/
|/g, "\n") + .replace(/<.*?>/g, ""); + newRows.push([instructions, step.distance.value]); } directionsSheet.getRange(1, 1, headers.length, 3).setValues(headers); - directionsSheet.getRange(headers.length + 1, 1, newRows.length, 2) - .setValues(newRows); - directionsSheet.getRange(headers.length + 1, 3, newRows.length, 1) - .setFormulaR1C1('=METERSTOMILES(R[0]C[-1])'); + directionsSheet + .getRange(headers.length + 1, 1, newRows.length, 2) + .setValues(newRows); + directionsSheet + .getRange(headers.length + 1, 3, newRows.length, 1) + .setFormulaR1C1("=METERSTOMILES(R[0]C[-1])"); // Format the new sheet. - directionsSheet.getRange('A1:C1').merge().setBackground('#ddddee'); - directionsSheet.getRange('A1:2').setFontWeight('bold'); + directionsSheet.getRange("A1:C1").merge().setBackground("#ddddee"); + directionsSheet.getRange("A1:2").setFontWeight("bold"); directionsSheet.setColumnWidth(1, 500); - directionsSheet.getRange('B2:C').setVerticalAlignment('top'); - directionsSheet.getRange('C2:C').setNumberFormat('0.00'); - const stepsRange = directionsSheet.getDataRange() - .offset(2, 0, directionsSheet.getLastRow() - 2); - setAlternatingRowBackgroundColors_(stepsRange, '#ffffff', '#eeeeee'); + directionsSheet.getRange("B2:C").setVerticalAlignment("top"); + directionsSheet.getRange("C2:C").setNumberFormat("0.00"); + const stepsRange = directionsSheet + .getDataRange() + .offset(2, 0, directionsSheet.getLastRow() - 2); + setAlternatingRowBackgroundColors_(stepsRange, "#ffffff", "#eeeeee"); directionsSheet.setFrozenRows(2); SpreadsheetApp.flush(); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -213,10 +232,9 @@ function getDirections_(origin, destination) { directionFinder.setOrigin(origin); directionFinder.setDestination(destination); const directions = directionFinder.getDirections(); - if (directions.status !== 'OK') { + if (directions.status !== "OK") { throw directions.error_message; } return directions; } // [END apps_script_sheets_custom_functions_quickstart] - diff --git a/sheets/dateAddAndSubtract/dateAddAndSubtract.gs b/sheets/dateAddAndSubtract/dateAddAndSubtract.gs index f17fd19ad..f27ace8e5 100644 --- a/sheets/dateAddAndSubtract/dateAddAndSubtract.gs +++ b/sheets/dateAddAndSubtract/dateAddAndSubtract.gs @@ -23,8 +23,16 @@ /** * The list of valid unit identifiers. */ -var VALID_UNITS = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second', - 'millisecond']; +const VALID_UNITS = [ + "year", + "month", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", +]; /** * Runs when the add-on is installed. @@ -39,9 +47,10 @@ function onInstall() { * current spreadsheet when a function is run. */ function onOpen() { - SpreadsheetApp.getUi().createAddonMenu() - .addItem('Use in this spreadsheet', 'use') - .addToUi(); + SpreadsheetApp.getUi() + .createAddonMenu() + .addItem("Use in this spreadsheet", "use") + .addToUi(); } /** @@ -49,11 +58,12 @@ function onOpen() { * shows a popup informing the user of the new functions that are available. */ function use() { - var title = 'Date Custom Functions'; - var message = 'The functions DATEADD and DATESUBTRACT are now available in ' + - 'this spreadsheet. More information is available in the function help ' + - 'box that appears when you start using them in a formula.'; - var ui = SpreadsheetApp.getUi(); + const title = "Date Custom Functions"; + const message = + "The functions DATEADD and DATESUBTRACT are now available in " + + "this spreadsheet. More information is available in the function help " + + "box that appears when you start using them in a formula."; + const ui = SpreadsheetApp.getUi(); ui.alert(title, message, ui.ButtonSet.OK); } @@ -71,8 +81,8 @@ function use() { * @customFunction */ function DATEADD(date, unit, amount) { - var args = toArray(arguments); // eslint-disable-line prefer-rest-params - return multimap(args, function(date, unit, amount) { + const args = [date, unit, amount]; + return multimap(args, (date, unit, amount) => { validateParameters(date, unit, amount); return moment(date).add(unit, amount).toDate(); }); @@ -104,8 +114,8 @@ function DATETEST(date, unit, amount) { * @customFunction */ function DATESUBTRACT(date, unit, amount) { - var args = toArray(arguments); // eslint-disable-line prefer-rest-params - return multimap(args, function(date, unit, amount) { + const args = [date, unit, amount]; + return multimap(args, (date, unit, amount) => { validateParameters(date, unit, amount); return moment(date).subtract(unit, amount).toDate(); }); @@ -119,17 +129,30 @@ function DATESUBTRACT(date, unit, amount) { * @param {number} amount The amount of the specified unit to add/subtract. */ function validateParameters(date, unit, amount) { - if (date == undefined || typeof date == 'number' || !moment(date).isValid()) { - throw Utilities.formatString('Parameter 1 expects a date value, but "%s" ' + - 'cannot be coerced to a date.', date); + if ( + date === undefined || + typeof date === "number" || + !moment(date).isValid() + ) { + throw Utilities.formatString( + 'Parameter 1 expects a date value, but "%s" ' + + "cannot be coerced to a date.", + date, + ); } if (VALID_UNITS.indexOf(moment.normalizeUnits(unit)) < 0) { - throw Utilities.formatString('Parameter 2 expects a unit identifier, but ' + - '"%s" is not a valid identifier.', unit); + throw Utilities.formatString( + "Parameter 2 expects a unit identifier, but " + + '"%s" is not a valid identifier.', + unit, + ); } - if (isNaN(Number(amount))) { - throw Utilities.formatString('Parameter 3 expects a number value, but ' + - '"%s" cannot be coerced to a number.', amount); + if (Number.isNaN(Number(amount))) { + throw Utilities.formatString( + "Parameter 3 expects a number value, but " + + '"%s" cannot be coerced to a number.', + amount, + ); } } @@ -143,38 +166,36 @@ function validateParameters(date, unit, amount) { */ function multimap(args, func) { // Determine the length of the arrays. - var lengths = args.map(function(arg) { - if (arg instanceof Array) { + const lengths = args.map((arg) => { + if (Array.isArray(arg)) { return arg.length; - } else { - return 0; } + return 0; }); - var max = Math.max.apply(null, lengths); + const max = Math.max.apply(null, lengths); // If there aren't any arrays, just call the function. - if (max == 0) { + if (max === 0) { return func(...args); } // Ensure all the arrays are the same length. // Arrays of length 1 are exempted, since they are assumed to be rows/columns // that should apply to each row/column in the other sets. - lengths.forEach(function(length) { - if (length != max && length > 1) { - throw new Error('All input ranges must be the same size: ' + max); + for (const length of lengths) { + if (length !== max && length > 1) { + throw new Error(`All input ranges must be the same size: ${max}`); } - }); + } // Recursively apply the map function to each element in the arrays. - var result = []; - for (var i = 0; i < max; i++) { - var params = args.map(function(arg) { - if (arg instanceof Array) { - return arg.length == 1 ? arg[0] : arg[i]; - } else { - return arg; + const result = []; + for (let i = 0; i < max; i++) { + const params = args.map((arg) => { + if (Array.isArray(arg)) { + return arg.length === 1 ? arg[0] : arg[i]; } + return arg; }); result.push(multimap(params, func)); } diff --git a/sheets/forms/forms.gs b/sheets/forms/forms.gs index 1e803de5b..db3bf7438 100644 --- a/sheets/forms/forms.gs +++ b/sheets/forms/forms.gs @@ -19,12 +19,14 @@ * A special function that inserts a custom menu when the spreadsheet opens. */ function onOpen() { - const menu = [{name: 'Set up conference', functionName: 'setUpConference_'}]; + const menu = [ + { name: "Set up conference", functionName: "setUpConference_" }, + ]; try { - SpreadsheetApp.getActive().addMenu('Conference', menu); + SpreadsheetApp.getActive().addMenu("Conference", menu); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -34,23 +36,25 @@ function onOpen() { * to react to form responses. */ function setUpConference_() { - if (ScriptProperties.getProperty('calId')) { - Browser.msgBox('Your conference is already set up. Look in Google Drive!'); + if (ScriptProperties.getProperty("calId")) { + Browser.msgBox("Your conference is already set up. Look in Google Drive!"); } try { const ss = SpreadsheetApp.getActive(); - const sheet = ss.getSheetByName('Conference Setup'); + const sheet = ss.getSheetByName("Conference Setup"); const range = sheet.getDataRange(); const values = range.getValues(); setUpCalendar_(values, range); setUpForm_(ss, values); - ScriptApp.newTrigger('onFormSubmit').forSpreadsheet(ss).onFormSubmit() - .create(); - ss.removeMenu('Conference'); + ScriptApp.newTrigger("onFormSubmit") + .forSpreadsheet(ss) + .onFormSubmit() + .create(); + ss.removeMenu("Conference"); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -62,24 +66,25 @@ function setUpConference_() { */ function setUpCalendar_(values, range) { try { - const cal = CalendarApp.createCalendar('Conference Calendar'); - for (var i = 1; i < values.length; i++) { + const cal = CalendarApp.createCalendar("Conference Calendar"); + for (let i = 1; i < values.length; i++) { const session = values[i]; const title = session[0]; const start = joinDateAndTime_(session[1], session[2]); const end = joinDateAndTime_(session[1], session[3]); - const options = {location: session[4], sendInvites: true}; - const event = cal.createEvent(title, start, end, options) - .setGuestsCanSeeGuests(false); + const options = { location: session[4], sendInvites: true }; + const event = cal + .createEvent(title, start, end, options) + .setGuestsCanSeeGuests(false); session[5] = event.getId(); } range.setValues(values); // Store the ID for the Calendar, which is needed to retrieve events by ID. - ScriptProperties.setProperty('calId', cal.getId()); + ScriptProperties.setProperty("calId", cal.getId()); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -91,10 +96,10 @@ function setUpCalendar_(values, range) { * @return {Date} A Date object representing the combined date and time. */ function joinDateAndTime_(date, time) { - date = new Date(date); - date.setHours(time.getHours()); - date.setMinutes(time.getMinutes()); - return date; + const newDate = new Date(date); + newDate.setHours(time.getHours()); + newDate.setMinutes(time.getMinutes()); + return newDate; } /** @@ -122,21 +127,24 @@ function setUpForm_(ss, values) { try { // Create the form and add a multiple-choice question for each timeslot. - const form = FormApp.create('Conference Form'); + const form = FormApp.create("Conference Form"); form.setDestination(FormApp.DestinationType.SPREADSHEET, ss.getId()); - form.addTextItem().setTitle('Name').setRequired(true); - form.addTextItem().setTitle('Email').setRequired(true); + form.addTextItem().setTitle("Name").setRequired(true); + form.addTextItem().setTitle("Email").setRequired(true); for (const day of schedule) { - const header = form.addSectionHeaderItem().setTitle( - 'Sessions for ' + day); + const header = form + .addSectionHeaderItem() + .setTitle(`Sessions for ${day}`); for (const time of schedule[day]) { - const item = form.addMultipleChoiceItem().setTitle(time + ' ' + day) - .setChoiceValues(schedule[day][time]); + const item = form + .addMultipleChoiceItem() + .setTitle(`${time} ${day}`) + .setChoiceValues(schedule[day][time]); } } } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -148,20 +156,24 @@ function setUpForm_(ss, values) { * see https://developers.google.com/apps-script/understanding_events */ function onFormSubmit(e) { - const user = {name: e.namedValues['Name'][0], - email: e.namedValues['Email'][0]}; + const user = { + name: e.namedValues.Name[0], + email: e.namedValues.Email[0], + }; // Grab the session data again so that we can match it to the user's choices. const response = []; try { values = SpreadsheetApp.getActive() - .getSheetByName('Conference Setup').getDataRange().getValues(); + .getSheetByName("Conference Setup") + .getDataRange() + .getValues(); for (let i = 1; i < values.length; i++) { const session = values[i]; const title = session[0]; const day = session[1].toLocaleDateString(); const time = session[2].toLocaleTimeString(); - const timeslot = time + ' ' + day; + const timeslot = `${time} ${day}`; // For every selection in the response, find the matching timeslot and // title in the spreadsheet and add the session data to the response array. @@ -173,7 +185,7 @@ function onFormSubmit(e) { sendDoc_(user, response); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -184,14 +196,14 @@ function onFormSubmit(e) { */ function sendInvites_(user, response) { try { - const id = ScriptProperties.getProperty('calId'); + const id = ScriptProperties.getProperty("calId"); const cal = CalendarApp.getCalendarById(id); for (let i = 0; i < response.length; i++) { cal.getEventSeriesById(response[i][5]).addGuest(user.email); } } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } @@ -202,16 +214,22 @@ function sendInvites_(user, response) { */ function sendDoc_(user, response) { try { - const doc = DocumentApp.create('Conference Itinerary for ' + user.name) - .addEditor(user.email); + const doc = DocumentApp.create( + `Conference Itinerary for ${user.name}`, + ).addEditor(user.email); const body = doc.getBody(); - let table = [['Session', 'Date', 'Time', 'Location']]; + let table = [["Session", "Date", "Time", "Location"]]; for (let i = 0; i < response.length; i++) { - table.push([response[i][0], response[i][1].toLocaleDateString(), - response[i][2].toLocaleTimeString(), response[i][4]]); + table.push([ + response[i][0], + response[i][1].toLocaleDateString(), + response[i][2].toLocaleTimeString(), + response[i][4], + ]); } - body.insertParagraph(0, doc.getName()) - .setHeading(DocumentApp.ParagraphHeading.HEADING1); + body + .insertParagraph(0, doc.getName()) + .setHeading(DocumentApp.ParagraphHeading.HEADING1); table = body.appendTable(table); table.getRow(0).editAsText().setBold(true); doc.saveAndClose(); @@ -220,13 +238,12 @@ function sendDoc_(user, response) { MailApp.sendEmail({ to: user.email, subject: doc.getName(), - body: 'Thanks for registering! Here\'s your itinerary: ' + doc.getUrl(), - attachments: doc.getAs(MimeType.PDF) + body: `Thanks for registering! Here's your itinerary: ${doc.getUrl()}`, + attachments: doc.getAs(MimeType.PDF), }); } catch (e) { // TODO (Developer) - Handle Exception - console.log('Failed with error: %s' + e.error); + console.log(`Failed with error: %s${e.error}`); } } // [END apps_script_sheets_custom_form_responses_quickstart] - diff --git a/sheets/maps/maps.gs b/sheets/maps/maps.gs index 8db93b06d..59069c9ec 100644 --- a/sheets/maps/maps.gs +++ b/sheets/maps/maps.gs @@ -20,32 +20,49 @@ */ function restaurantLocationsMap() { // Get the sheet named 'restaurants' - var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('restaurants'); + const sheet = + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("restaurants"); // Store the restaurant name and address data in a 2-dimensional array called // restaurantInfo. This is the data in cells A2:B4 - var restaurantInfo = sheet.getRange(2, 1, sheet.getLastRow() - 1, 2).getValues(); + const restaurantInfo = sheet + .getRange(2, 1, sheet.getLastRow() - 1, 2) + .getValues(); // Create a new StaticMap - var restaurantMap = Maps.newStaticMap(); + const restaurantMap = Maps.newStaticMap(); // Create a new UI Application, which we use to display the map - var ui = UiApp.createApplication(); + const ui = UiApp.createApplication(); // Create a grid widget to use for displaying the text of the restaurant names // and addresses. Start by populating the header row in the grid. - var grid = ui.createGrid(restaurantInfo.length + 1, 3); - grid.setWidget(0, 0, ui.createLabel('Store #').setStyleAttribute('fontWeight', 'bold')); - grid.setWidget(0, 1, ui.createLabel('Store Name').setStyleAttribute('fontWeight', 'bold')); - grid.setWidget(0, 2, ui.createLabel('Address').setStyleAttribute('fontWeight', 'bold')); + const grid = ui.createGrid(restaurantInfo.length + 1, 3); + grid.setWidget( + 0, + 0, + ui.createLabel("Store #").setStyleAttribute("fontWeight", "bold"), + ); + grid.setWidget( + 0, + 1, + ui.createLabel("Store Name").setStyleAttribute("fontWeight", "bold"), + ); + grid.setWidget( + 0, + 2, + ui.createLabel("Address").setStyleAttribute("fontWeight", "bold"), + ); // For each entry in restaurantInfo, create a map marker with the address and // the style we want. Also add the address info for this restaurant to the // grid widget. - for (var i = 0; i < restaurantInfo.length; i++) { - restaurantMap.setMarkerStyle(Maps.StaticMap.MarkerSize.MID, - Maps.StaticMap.Color.GREEN, - i + 1); + for (let i = 0; i < restaurantInfo.length; i++) { + restaurantMap.setMarkerStyle( + Maps.StaticMap.MarkerSize.MID, + Maps.StaticMap.Color.GREEN, + i + 1, + ); restaurantMap.addMarker(restaurantInfo[i][1]); grid.setWidget(i + 1, 0, ui.createLabel((i + 1).toString())); @@ -56,7 +73,9 @@ function restaurantLocationsMap() { // Create a Flow Panel widget. We add the map and the grid to this panel. // The height needs to be able to accomodate the number of restaurants, so we // use a calculation to scale it based on the number of restaurants. - var panel = ui.createFlowPanel().setSize('500px', 515 + (restaurantInfo.length * 25) + 'px'); + const panel = ui + .createFlowPanel() + .setSize("500px", `${515 + restaurantInfo.length * 25}px`); // Get the URL of the restaurant map and use that to create an image and add // it to the panel. Next add the grid to the panel. @@ -66,9 +85,9 @@ function restaurantLocationsMap() { // Finally, add the panel widget to our UI instance, and set its height, // width, and title. ui.add(panel); - ui.setHeight(515 + (restaurantInfo.length * 25)); + ui.setHeight(515 + restaurantInfo.length * 25); ui.setWidth(500); - ui.setTitle('Restaurant Locations'); + ui.setTitle("Restaurant Locations"); // Make the UI visible in the spreadsheet. SpreadsheetApp.getActiveSpreadsheet().show(ui); @@ -82,72 +101,75 @@ function restaurantLocationsMap() { */ function getDrivingDirections() { // Set starting and ending addresses - var start = '1600 Amphitheatre Pkwy, Mountain View, CA 94043'; - var end = '345 Spear St, San Francisco, CA 94105'; + const start = "1600 Amphitheatre Pkwy, Mountain View, CA 94043"; + const end = "345 Spear St, San Francisco, CA 94105"; // These regular expressions will be used to strip out // unneeded HTML tags - var r1 = new RegExp('', 'g'); - var r2 = new RegExp('', 'g'); - var r3 = new RegExp('
', 'g'); - var r4 = new RegExp('
', 'g'); + const r1 = //g; + const r2 = /<\/b>/g; + const r3 = /
/g; + const r4 = /<\/div>/g; // points is used for storing the points in the step-by-step directions - var points = []; + let points = []; // currentLabel is used for number the steps in the directions - var currentLabel = 0; + let currentLabel = 0; // This will be the map on which we display the path - var map = Maps.newStaticMap().setSize(500, 350); + const map = Maps.newStaticMap().setSize(500, 350); // Create a new UI Application, which we use to display the map - var ui = UiApp.createApplication(); + const ui = UiApp.createApplication(); // Create a Flow Panel widget, which we use for the directions text - var directionsPanel = ui.createFlowPanel(); + const directionsPanel = ui.createFlowPanel(); // Create a new DirectionFinder with our start and end addresses, and request the directions // The response is a JSON object, which contains the directions - var directions = Maps.newDirectionFinder().setOrigin(start).setDestination(end).getDirections(); + const directions = Maps.newDirectionFinder() + .setOrigin(start) + .setDestination(end) + .getDirections(); // Much of this code is based on the template referenced in // http://googleappsdeveloper.blogspot.com/2010/06/automatically-generate-maps-and.html - for (var i in directions.routes) { - for (var j in directions.routes[i].legs) { - for (var k in directions.routes[i].legs[j].steps) { + for (const i in directions.routes) { + for (const j in directions.routes[i].legs) { + for (const k in directions.routes[i].legs[j].steps) { // Parse out the current step in the directions - var step = directions.routes[i].legs[j].steps[k]; + const step = directions.routes[i].legs[j].steps[k]; // Call Maps.decodePolyline() to decode the polyline for // this step into an array of latitudes and longitudes - var path = Maps.decodePolyline(step.polyline.points); + const path = Maps.decodePolyline(step.polyline.points); points = points.concat(path); // Pull out the direction information from step.html_instructions // Because we only want to display text, we will strip out the // HTML tags that are present in the html_instructions - var text = step.html_instructions; - text = text.replace(r1, ' '); - text = text.replace(r2, ' '); - text = text.replace(r3, ' '); - text = text.replace(r4, ' '); + let text = step.html_instructions; + text = text.replace(r1, " "); + text = text.replace(r2, " "); + text = text.replace(r3, " "); + text = text.replace(r4, " "); // Add each step in the directions to the directionsPanel - directionsPanel.add(ui.createLabel((++currentLabel) + ' - ' + text)); + directionsPanel.add(ui.createLabel(`${++currentLabel} - ${text}`)); } } } // be conservative and only sample 100 times to create our polyline path - var lpoints=[]; + let lpoints = []; if (points.length < 200) { lpoints = points; } else { - var pCount = (points.length / 2); - var step = parseInt(pCount / 100); - for (var i = 0; i < 100; ++i) { + const pCount = points.length / 2; + const step = Number.parseInt(pCount / 100); + for (let i = 0; i < 100; ++i) { lpoints.push(points[i * step * 2]); - lpoints.push(points[(i * step * 2) + 1]); + lpoints.push(points[i * step * 2 + 1]); } } @@ -155,14 +177,14 @@ function getDrivingDirections() { if (lpoints.length > 0) { // Maps.encodePolyline turns an array of latitudes and longitudes // into an encoded polyline - var pline = Maps.encodePolyline(lpoints); + const pline = Maps.encodePolyline(lpoints); // Once we have the encoded polyline, add that path to the map map.addPath(pline); } // Create a FlowPanel to hold the map - var panel = ui.createFlowPanel().setSize('500px', '350px'); + const panel = ui.createFlowPanel().setSize("500px", "350px"); // Get the URL of the map and use that to create an image and add // it to the panel. @@ -173,7 +195,7 @@ function getDrivingDirections() { ui.add(directionsPanel); // Next set the title, height, and width of the UI instance - ui.setTitle('Driving Directions'); + ui.setTitle("Driving Directions"); ui.setHeight(525); ui.setWidth(500); @@ -188,33 +210,37 @@ function getDrivingDirections() { */ function analyzeLocations() { // Select the sheet named 'geocoder and elevation' - var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('geocoder and elevation'); + const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName( + "geocoder and elevation", + ); // Store the address data in an array called // locationInfo. This is the data in cells A2:A20 - var locationInfo = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues(); + const locationInfo = sheet + .getRange(2, 1, sheet.getLastRow() - 1, 1) + .getValues(); // Set up some values to use for comparisons. // latitudes run from -90 to 90, so we start with a max of -90 for comparison - var maxLatitude = -90; - var indexOfMaxLatitude = 0; + let maxLatitude = -90; + let indexOfMaxLatitude = 0; // Set the starting max elevation to 0, or sea level - var maxElevation = 0; - var indexOfMaxElevation = 0; + let maxElevation = 0; + let indexOfMaxElevation = 0; // geoResults will hold the JSON results array that we get when calling geocode() - var geoResults; + let geoResults; // elevationResults will hold the results object that we get when calling sampleLocation() - var elevationResults; + let elevationResults; // lat and lng will temporarily hold the latitude and longitude of each // address - var lat; - var lng; + let lat; + let lng; - for (var i = 0; i < locationInfo.length; i++) { + for (let i = 0; i < locationInfo.length; i++) { // Get the latitude and longitude for an address. For more details on // the JSON results array, geoResults, see // http://code.google.com/apis/maps/documentation/geocoding/#Results @@ -228,7 +254,10 @@ function analyzeLocations() { // elevation. For more details on the JSON-formatted results object, // elevationResults, see // http://code.google.com/apis/maps/documentation/elevation/#ElevationResponses - elevationResults = Maps.newElevationSampler().sampleLocation(parseFloat(lat), parseFloat(lng)); + elevationResults = Maps.newElevationSampler().sampleLocation( + Number.parseFloat(lat), + Number.parseFloat(lng), + ); // Check to see if the current latitude is greater than our max latitude // so far. If so, set maxLatitude and indexOfMaxLatitude @@ -240,7 +269,10 @@ function analyzeLocations() { // Check if elevationResults has a good status and also if the current // elevation is greater than the max elevation so far. If so, set // maxElevation and indexOfMaxElevation - if (elevationResults.status == 'OK' && elevationResults.results[0].elevation > maxElevation) { + if ( + elevationResults.status === "OK" && + elevationResults.results[0].elevation > maxElevation + ) { maxElevation = elevationResults.results[0].elevation; indexOfMaxElevation = i; } @@ -248,9 +280,8 @@ function analyzeLocations() { // User Browser.msgBox as a simple way to display the info about highest // elevation and northernmost office. - Browser.msgBox('The US Google office with the highest elevation is: ' + - locationInfo[indexOfMaxElevation] + - '. The northernmost US Google office is: ' + - locationInfo[indexOfMaxLatitude]); + Browser.msgBox( + `The US Google office with the highest elevation is: ${locationInfo[indexOfMaxElevation]}. The northernmost US Google office is: ${locationInfo[indexOfMaxLatitude]}`, + ); } // [END apps_script_sheets_analyze_locations] diff --git a/sheets/next18/Constants.gs b/sheets/next18/Constants.gs index f49f81d15..8f7fc2e85 100644 --- a/sheets/next18/Constants.gs +++ b/sheets/next18/Constants.gs @@ -14,23 +14,22 @@ * limitations under the License. */ - /* Salesforce config */ // Salesforce OAuth configuration, which you get by creating a developer project // with OAuth authentication on Salesforce. -var SALESFORCE_CLIENT_ID = ''; -var SALESFORCE_CLIENT_SECRET = ''; +const SALESFORCE_CLIENT_ID = ""; +const SALESFORCE_CLIENT_SECRET = ""; // The Salesforce instance to talk to. -var SALESFORCE_INSTANCE = 'na1'; +const SALESFORCE_INSTANCE = "na1"; /* Invoice generation config */ // The ID of a Google Doc that is used as a template. Defaults to // https://docs.google.com/document/d/1awKvXXMOQomdD68PGMpP5j1kNZwk_2Z0wBbwUgjKKws/view -var INVOICE_TEMPLATE = '1awKvXXMOQomdD68PGMpP5j1kNZwk_2Z0wBbwUgjKKws'; +const INVOICE_TEMPLATE = "1awKvXXMOQomdD68PGMpP5j1kNZwk_2Z0wBbwUgjKKws"; // The ID of a Drive folder that the generated invoices are created in. Create // a new folder that your Google account has edit access to. -var INVOICES_FOLDER = ''; +const INVOICES_FOLDER = ""; diff --git a/sheets/next18/Invoice.gs b/sheets/next18/Invoice.gs index fc043c137..030cbe3f2 100644 --- a/sheets/next18/Invoice.gs +++ b/sheets/next18/Invoice.gs @@ -14,24 +14,24 @@ * limitations under the License. */ - /** * Generates invoices based on the selected rows in the spreadsheet. Assumes * that the Salesforce accountId is in the first selected column and the * amount owed is the 4th selected column. */ function generateInvoices() { - var range = SpreadsheetApp.getActiveRange(); - var values = range.getDisplayValues(); - var sheet = SpreadsheetApp.getActiveSheet(); + const range = SpreadsheetApp.getActiveRange(); + const values = range.getDisplayValues(); + const sheet = SpreadsheetApp.getActiveSheet(); - for (var i = 0; i < values.length; i++) { - var row = values[i]; - var accountId = row[0]; - var amount = row[3]; - var invoiceUrl = generateInvoice(accountId, amount); - sheet.getRange(range.getRow() + i, range.getLastColumn() + 1) - .setValue(invoiceUrl); + for (let i = 0; i < values.length; i++) { + const row = values[i]; + const accountId = row[0]; + const amount = row[3]; + const invoiceUrl = generateInvoice(accountId, amount); + sheet + .getRange(range.getRow() + i, range.getLastColumn() + 1) + .setValue(invoiceUrl); } } @@ -44,22 +44,28 @@ function generateInvoices() { * @return {string} the url of the created invoice */ function generateInvoice(accountId, amount) { - var folder = DriveApp.getFolderById(INVOICES_FOLDER); - var copied = DriveApp.getFileById(INVOICE_TEMPLATE) - .makeCopy('Invoice for ' + accountId, folder); - var invoice = DocumentApp.openById(copied.getId()); - var results = fetchSoqlResults( - 'select Name, BillingAddress from Account where Id = \'' + - accountId + '\''); - var account = results['records'][0]; + const folder = DriveApp.getFolderById(INVOICES_FOLDER); + const copied = DriveApp.getFileById(INVOICE_TEMPLATE).makeCopy( + `Invoice for ${accountId}`, + folder, + ); + const invoice = DocumentApp.openById(copied.getId()); + const results = fetchSoqlResults( + `select Name, BillingAddress from Account where Id = '${accountId}'`, + ); + const account = results.records[0]; - invoice.getBody().replaceText( - '{{account name}}', account['Name']); - invoice.getBody().replaceText( - '{{account address}}', account['BillingAddress']['street']); - invoice.getBody().replaceText( - '{{date}}', Utilities.formatDate(new Date(), 'GMT', 'yyyy-MM-dd')); - invoice.getBody().replaceText('{{amount}}', amount); + invoice.getBody().replaceText("{{account name}}", account.Name); + invoice + .getBody() + .replaceText("{{account address}}", account.BillingAddress.street); + invoice + .getBody() + .replaceText( + "{{date}}", + Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd"), + ); + invoice.getBody().replaceText("{{amount}}", amount); invoice.saveAndClose(); return invoice.getUrl(); } @@ -68,18 +74,19 @@ function generateInvoice(accountId, amount) { * Generates a report in Google Slides with a chart generated from the sheet. */ function generateReport() { - var sheet = SpreadsheetApp.getActiveSheet(); - var chart = sheet.newChart() + const sheet = SpreadsheetApp.getActiveSheet(); + const chart = sheet + .newChart() .asColumnChart() - .addRange(sheet.getRange('A:A')) - .addRange(sheet.getRange('C:D')) + .addRange(sheet.getRange("A:A")) + .addRange(sheet.getRange("C:D")) .setNumHeaders(1) .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) - .setOption('useFirstColumnAsDomain', true) - .setOption('isStacked', 'absolute') - .setOption('title', 'Expected Payments') - .setOption('treatLabelsAsText', false) - .setXAxisTitle('AccountId') + .setOption("useFirstColumnAsDomain", true) + .setOption("isStacked", "absolute") + .setOption("title", "Expected Payments") + .setOption("treatLabelsAsText", false) + .setXAxisTitle("AccountId") .setPosition(3, 1, 114, 138) .build(); @@ -88,15 +95,16 @@ function generateReport() { // Force the chart to be created before adding it to the presentation SpreadsheetApp.flush(); - var preso = SlidesApp.create('Invoicing Report'); - var titleSlide = preso.getSlides()[0]; + const preso = SlidesApp.create("Invoicing Report"); + const titleSlide = preso.getSlides()[0]; - var titleShape = titleSlide.getPlaceholder( - SlidesApp.PlaceholderType.CENTERED_TITLE).asShape(); - titleShape.getText().setText('Invoicing Report'); + const titleShape = titleSlide + .getPlaceholder(SlidesApp.PlaceholderType.CENTERED_TITLE) + .asShape(); + titleShape.getText().setText("Invoicing Report"); - var newSlide = preso.appendSlide(SlidesApp.PredefinedLayout.BLANK); + const newSlide = preso.appendSlide(SlidesApp.PredefinedLayout.BLANK); newSlide.insertSheetsChart(chart); - showLinkDialog(preso.getUrl(), 'Open report', 'Report created'); + showLinkDialog(preso.getUrl(), "Open report", "Report created"); } diff --git a/sheets/next18/Salesforce.gs b/sheets/next18/Salesforce.gs index 73fad8593..32add7759 100644 --- a/sheets/next18/Salesforce.gs +++ b/sheets/next18/Salesforce.gs @@ -14,20 +14,20 @@ * limitations under the License. */ - /** * Creates an add-on menu, the main entry point for this add-on */ function onOpen() { - SpreadsheetApp.getUi().createAddonMenu() - .addItem('Login To Salesforce', 'login') - .addItem('Run SOQL Query', 'promptQuery') - .addSeparator() - .addItem('Logout From Salesforce', 'logout') - .addSeparator() - .addItem('Generate Invoices', 'generateInvoices') - .addItem('Generate Report', 'generateReport') - .addToUi(); + SpreadsheetApp.getUi() + .createAddonMenu() + .addItem("Login To Salesforce", "login") + .addItem("Run SOQL Query", "promptQuery") + .addSeparator() + .addItem("Logout From Salesforce", "logout") + .addSeparator() + .addItem("Generate Invoices", "generateInvoices") + .addItem("Generate Report", "generateReport") + .addToUi(); } /** Ensure the menu is created when the add-on is installed */ @@ -40,10 +40,13 @@ function onInstall() { * Salesforce. */ function login() { - var salesforce = getSalesforceService(); + const salesforce = getSalesforceService(); if (!salesforce.hasAccess()) { - showLinkDialog(salesforce.getAuthorizationUrl(), - 'Sign-in to Salesforce', 'Sign-in'); + showLinkDialog( + salesforce.getAuthorizationUrl(), + "Sign-in to Salesforce", + "Sign-in", + ); } } @@ -55,7 +58,7 @@ function login() { * @param {string} title the title of the dialog */ function showLinkDialog(url, message, title) { - var template = HtmlService.createTemplateFromFile('LinkDialog'); + const template = HtmlService.createTemplateFromFile("LinkDialog"); template.url = url; template.message = message; SpreadsheetApp.getUi().showModalDialog(template.evaluate(), title); @@ -68,13 +71,14 @@ function showLinkDialog(url, message, title) { * @return {Object} a Salesforce OAuth2 service */ function getSalesforceService() { - return OAuth2.createService('salesforce') + return OAuth2.createService("salesforce") .setAuthorizationBaseUrl( - 'https://login.salesforce.com/services/oauth2/authorize') - .setTokenUrl('https://login.salesforce.com/services/oauth2/token') + "https://login.salesforce.com/services/oauth2/authorize", + ) + .setTokenUrl("https://login.salesforce.com/services/oauth2/token") .setClientId(SALESFORCE_CLIENT_ID) .setClientSecret(SALESFORCE_CLIENT_SECRET) - .setCallbackFunction('authCallback') + .setCallbackFunction("authCallback") .setPropertyStore(PropertiesService.getUserProperties()); } @@ -86,11 +90,11 @@ function getSalesforceService() { * @return {Object} HTMLOutput to render the callback as a web page */ function authCallback(request) { - var salesforce = getSalesforceService(); - var isAuthorized = salesforce.handleCallback(request); - var message = isAuthorized ? - 'Success! You can close this tab and the dialog in Sheets.' - : 'Denied. You can close this tab and the dialog in Sheets.'; + const salesforce = getSalesforceService(); + const isAuthorized = salesforce.handleCallback(request); + const message = isAuthorized + ? "Success! You can close this tab and the dialog in Sheets." + : "Denied. You can close this tab and the dialog in Sheets."; return HtmlService.createHtmlOutput(message); } @@ -101,11 +105,13 @@ function authCallback(request) { * sheet. */ function promptQuery() { - var ui = SpreadsheetApp.getUi(); - var response = ui.prompt('Run SOQL Query', - 'Enter your query, ex: "select Id from Opportunity"', - ui.ButtonSet.OK_CANCEL); - var query = response.getResponseText(); + const ui = SpreadsheetApp.getUi(); + const response = ui.prompt( + "Run SOQL Query", + 'Enter your query, ex: "select Id from Opportunity"', + ui.ButtonSet.OK_CANCEL, + ); + const query = response.getResponseText(); if (response.getSelectedButton() === ui.Button.OK) { executeQuery(query); } @@ -117,28 +123,29 @@ function promptQuery() { * @param {string} query the SOQL to execute */ function executeQuery(query) { - var response = fetchSoqlResults(query); - var outputSheet = SpreadsheetApp.getActive().insertSheet(); - var records = response['records']; - var fields = getFields(records[0]); + const response = fetchSoqlResults(query); + const outputSheet = SpreadsheetApp.getActive().insertSheet(); + const records = response.records; + const fields = getFields(records[0]); // Builds the new sheet's contents as a 2D array that can be passed in // to setValues() at once. This gives better performance than updating // a single cell at a time. - var outputValues = []; + const outputValues = []; outputValues.push(fields); - for (var i = 0; i < records.length; i++) { - var row = []; - var record = records[i]; - for (var j = 0; j < fields.length; j++) { - var fieldName = fields[j]; + for (let i = 0; i < records.length; i++) { + const row = []; + const record = records[i]; + for (let j = 0; j < fields.length; j++) { + const fieldName = fields[j]; row.push(record[fieldName]); } outputValues.push(row); } - outputSheet.getRange(1, 1, outputValues.length, fields.length) - .setValues(outputValues); + outputSheet + .getRange(1, 1, outputValues.length, fields.length) + .setValues(outputValues); } /** @@ -148,22 +155,22 @@ function executeQuery(query) { * @return {Object} the API response from Salesforce, as a parsed JSON object. */ function fetchSoqlResults(query) { - var salesforce = getSalesforceService(); + const salesforce = getSalesforceService(); if (!salesforce.hasAccess()) { - throw new Error('Please login first'); - } else { - var params = { - 'headers': { - 'Authorization': 'Bearer ' + salesforce.getAccessToken(), - 'Content-Type': 'application/json' - } - }; - var url = 'https://' + SALESFORCE_INSTANCE + - '.salesforce.com/services/data/v30.0/query'; - var response = UrlFetchApp.fetch(url + - '?q=' + encodeURIComponent(query), params); - return JSON.parse(response.getContentText()); + throw new Error("Please login first"); } + const params = { + headers: { + Authorization: `Bearer ${salesforce.getAccessToken()}`, + "Content-Type": "application/json", + }, + }; + const url = `https://${SALESFORCE_INSTANCE}.salesforce.com/services/data/v30.0/query`; + const response = UrlFetchApp.fetch( + `${url}?q=${encodeURIComponent(query)}`, + params, + ); + return JSON.parse(response.getContentText()); } /** @@ -174,9 +181,9 @@ function fetchSoqlResults(query) { * @return {Array} an array of string keys of that record */ function getFields(record) { - var fields = []; - for (var field in record) { - if (record.hasOwnProperty(field) && field !== 'attributes') { + const fields = []; + for (const field in record) { + if (Object.hasOwn(record, field) && field !== "attributes") { fields.push(field); } } diff --git a/sheets/quickstart/quickstart.gs b/sheets/quickstart/quickstart.gs index 917be5ed9..d48d468fe 100644 --- a/sheets/quickstart/quickstart.gs +++ b/sheets/quickstart/quickstart.gs @@ -21,20 +21,23 @@ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get */ function logNamesAndMajors() { - const spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'; - const rangeName = 'Class Data!A2:E'; + const spreadsheetId = "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"; + const rangeName = "Class Data!A2:E"; try { // Get the values from the spreadsheet using spreadsheetId and range. - const values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values; + const values = Sheets.Spreadsheets.Values.get( + spreadsheetId, + rangeName, + ).values; // Print the values from spreadsheet if values are available. if (!values) { - console.log('No data found.'); + console.log("No data found."); return; } - console.log('Name, Major:'); + console.log("Name, Major:"); for (const row in values) { // Print columns A and E, which correspond to indices 0 and 4. - console.log(' - %s, %s', values[row][0], values[row][4]); + console.log(" - %s, %s", values[row][0], values[row][4]); } } catch (err) { // TODO (developer) - Handle Values.get() exception from Sheet API diff --git a/sheets/removingDuplicates/removingDuplicates.gs b/sheets/removingDuplicates/removingDuplicates.gs index 384ad55f7..ba2b5b283 100644 --- a/sheets/removingDuplicates/removingDuplicates.gs +++ b/sheets/removingDuplicates/removingDuplicates.gs @@ -24,7 +24,7 @@ function removeDuplicates() { const data = sheet.getDataRange().getValues(); // [END apps_script_sheets_sheet] const uniqueData = {}; - for (let row of data) { + for (const row of data) { const key = row.join(); // [START apps_script_sheets_duplicate] uniqueData[key] = uniqueData[key] || row; diff --git a/slides/SpeakerNotesScript/scriptGen.gs b/slides/SpeakerNotesScript/scriptGen.gs index d89938f84..dacf645c4 100644 --- a/slides/SpeakerNotesScript/scriptGen.gs +++ b/slides/SpeakerNotesScript/scriptGen.gs @@ -32,9 +32,10 @@ function onInstall(e) { * @param {object} e The onOpen event. */ function onOpen(e) { - SlidesApp.getUi().createAddonMenu() - .addItem('Generate Script Document', 'generateSlidesScript') - .addToUi(); + SlidesApp.getUi() + .createAddonMenu() + .addItem("Generate Script Document", "generateSlidesScript") + .addToUi(); } /** @@ -43,12 +44,12 @@ function onOpen(e) { */ function generateSlidesScript() { const presentation = SlidesApp.getActivePresentation(); - const docTitle = presentation.getName() + ' Script'; + const docTitle = `${presentation.getName()} Script`; const slides = presentation.getSlides(); // Creates a document in the user's home Drive directory. const speakerNotesDoc = DocumentApp.create(docTitle); - console.log('Created document with id %s', speakerNotesDoc.getId()); + console.log("Created document with id %s", speakerNotesDoc.getId()); const docBody = speakerNotesDoc.getBody(); const header = docBody.appendParagraph(docTitle); @@ -57,14 +58,20 @@ function generateSlidesScript() { // Iterate through each slide and extract the speaker notes // into the document body. for (let i = 0; i < slides.length; i++) { - const section = docBody.appendParagraph('Slide ' + (i + 1)) - .setHeading(DocumentApp.ParagraphHeading.HEADING2); + const section = docBody + .appendParagraph(`Slide ${i + 1}`) + .setHeading(DocumentApp.ParagraphHeading.HEADING2); - const notes = slides[i].getNotesPage().getSpeakerNotesShape().getText().asString(); - docBody.appendParagraph(notes) - .appendHorizontalRule(); + const notes = slides[i] + .getNotesPage() + .getSpeakerNotesShape() + .getText() + .asString(); + docBody.appendParagraph(notes).appendHorizontalRule(); } - SlidesApp.getUi().alert(speakerNotesDoc.getName() + ' has been created in your Drive files.'); + SlidesApp.getUi().alert( + `${speakerNotesDoc.getName()} has been created in your Drive files.`, + ); } // [END apps_script_slides_speaker_notes_script] diff --git a/slides/api/Helpers.gs b/slides/api/Helpers.gs index 1c52172de..9a42364e1 100644 --- a/slides/api/Helpers.gs +++ b/slides/api/Helpers.gs @@ -21,113 +21,129 @@ function Helpers() { this.filesToDelete = []; } -Helpers.prototype.reset = function() { +Helpers.prototype.reset = function () { this.filesToDelete = []; }; -Helpers.prototype.deleteFileOnCleanup = function(id) { +Helpers.prototype.deleteFileOnCleanup = function (id) { this.filesToDelete.push(id); }; -Helpers.prototype.cleanup = function() { +Helpers.prototype.cleanup = function () { this.filesToDelete.forEach(Drive.Files.remove); }; -Helpers.prototype.createTestPresentation = function() { +Helpers.prototype.createTestPresentation = function () { const presentation = Slides.Presentations.create({ - title: 'Test Preso' + title: "Test Preso", }); this.deleteFileOnCleanup(presentation.presentationId); return presentation.presentationId; }; -Helpers.prototype.addSlides = function(presentationId, num, layout) { - let requests = []; - let slideIds = []; +Helpers.prototype.addSlides = (presentationId, num, layout) => { + const requests = []; + const slideIds = []; for (let i = 0; i < num; ++i) { - slideIds.push('slide_' + i); + slideIds.push(`slide_${i}`); requests.push({ createSlide: { objectId: slideIds[i], slideLayoutReference: { - predefinedLayout: layout - } - } + predefinedLayout: layout, + }, + }, }); } - Slides.Presentations.batchUpdate({requests: requests}, presentationId); + Slides.Presentations.batchUpdate({ requests: requests }, presentationId); return slideIds; }; -Helpers.prototype.createTestTextbox = function(presentationId, pageId, callback) { - const boxId = 'MyTextBox_01'; +Helpers.prototype.createTestTextbox = (presentationId, pageId, callback) => { + const boxId = "MyTextBox_01"; const pt350 = { magnitude: 350, - unit: 'PT' + unit: "PT", }; - const requests = [{ - createShape: { - objectId: boxId, - shapeType: 'TEXT_BOX', - elementProperties: { - pageObjectId: pageId, - size: { - height: pt350, - width: pt350 + const requests = [ + { + createShape: { + objectId: boxId, + shapeType: "TEXT_BOX", + elementProperties: { + pageObjectId: pageId, + size: { + height: pt350, + width: pt350, + }, + transform: { + scaleX: 1, + scaleY: 1, + translateX: 350, + translateY: 100, + unit: "PT", + }, }, - transform: { - scaleX: 1, - scaleY: 1, - translateX: 350, - translateY: 100, - unit: 'PT' - } - } - } - }, { - insertText: { - objectId: boxId, - insertionIndex: 0, - text: 'New Box Text Inserted' - } - }]; - const createTextboxResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); + }, + }, + { + insertText: { + objectId: boxId, + insertionIndex: 0, + text: "New Box Text Inserted", + }, + }, + ]; + const createTextboxResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); return createTextboxResponse.replies[0].createShape.objectId; }; -Helpers.prototype.createTestSheetsChart = function(presentationId, pageId, - spreadsheetId, sheetChartId, callback) { - const chartId = 'MyChart_01'; +Helpers.prototype.createTestSheetsChart = ( + presentationId, + pageId, + spreadsheetId, + sheetChartId, + callback, +) => { + const chartId = "MyChart_01"; const emu4M = { magnitude: 4000000, - unit: 'EMU' + unit: "EMU", }; - const requests = [{ - createSheetsChart: { - objectId: chartId, - spreadsheetId: spreadsheetId, - chartId: sheetChartId, - linkingMode: 'LINKED', - elementProperties: { - pageObjectId: pageId, - size: { - height: emu4M, - width: emu4M + const requests = [ + { + createSheetsChart: { + objectId: chartId, + spreadsheetId: spreadsheetId, + chartId: sheetChartId, + linkingMode: "LINKED", + elementProperties: { + pageObjectId: pageId, + size: { + height: emu4M, + width: emu4M, + }, + transform: { + scaleX: 1, + scaleY: 1, + translateX: 100000, + translateY: 100000, + unit: "EMU", + }, }, - transform: { - scaleX: 1, - scaleY: 1, - translateX: 100000, - translateY: 100000, - unit: 'EMU' - } - } - } - }]; - const createSheetsChartResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); + }, + }, + ]; + const createSheetsChartResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); return createSheetsChartResponse.replies[0].createSheetsChart.objectId; -}; \ No newline at end of file +}; diff --git a/slides/api/Snippets.gs b/slides/api/Snippets.gs index 39a56bef6..cabb19447 100644 --- a/slides/api/Snippets.gs +++ b/slides/api/Snippets.gs @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const title = 'my title'; +const title = "my title"; // [START slides_create_presentation] /** @@ -23,16 +23,19 @@ const title = 'my title'; function createPresentation() { try { const presentation = Slides.Presentations.create({ - title: title + title: title, }); - console.log('Created presentation with ID: %s', presentation.presentationId); + console.log( + "Created presentation with ID: %s", + presentation.presentationId, + ); return presentation; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_presentation] // [START slides_copy_presentation] @@ -42,11 +45,11 @@ function createPresentation() { * @returns {*} the copy's presentation id */ function copyPresentation(presentationId) { - const copyTitle = 'Copy Title'; + const copyTitle = "Copy Title"; let copyFile = { title: copyTitle, - parents: [{id: 'root'}] + parents: [{ id: "root" }], }; try { copyFile = Drive.Files.copy(copyFile, presentationId); @@ -56,9 +59,9 @@ function copyPresentation(presentationId) { return presentationCopyId; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_copy_presentation] // [START slides_create_slide] @@ -71,31 +74,39 @@ function copyPresentation(presentationId) { function createSlide(presentationId, pageId) { // See Presentation.insertSlide(...) to learn how to add a slide using SlidesApp. // http://developers.google.com/apps-script/reference/slides/presentation#appendslidelayout - const requests = [{ - createSlide: { - objectId: pageId, - insertionIndex: '1', - slideLayoutReference: { - predefinedLayout: 'TITLE_AND_TWO_COLUMNS' - } - } - }]; + const requests = [ + { + createSlide: { + objectId: pageId, + insertionIndex: "1", + slideLayoutReference: { + predefinedLayout: "TITLE_AND_TWO_COLUMNS", + }, + }, + }, + ]; // If you wish to populate the slide with elements, add element create requests here, // using the pageId. // Execute the request. try { - const createSlideResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Created slide with ID: %s', createSlideResponse.replies[0].createSlide.objectId); + const createSlideResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log( + "Created slide with ID: %s", + createSlideResponse.replies[0].createSlide.objectId, + ); return createSlideResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_slide] // [START slides_create_textbox_with_text] @@ -106,56 +117,60 @@ function createSlide(presentationId, pageId) { * @returns {*} */ function createTextboxWithText(presentationId, pageId) { - const elementId = 'MyTextBox_01'; + const elementId = "MyTextBox_01"; const pt350 = { magnitude: 350, - unit: 'PT' + unit: "PT", }; const requests = [ { createShape: { objectId: elementId, - shapeType: 'TEXT_BOX', + shapeType: "TEXT_BOX", elementProperties: { pageObjectId: pageId, size: { height: pt350, - width: pt350 + width: pt350, }, transform: { scaleX: 1, scaleY: 1, translateX: 350, translateY: 100, - unit: 'PT' - } - } - } + unit: "PT", + }, + }, + }, }, // Insert text into the box, using the supplied element ID. { insertText: { objectId: elementId, insertionIndex: 0, - text: 'New Box Text Inserted!' - } - } + text: "New Box Text Inserted!", + }, + }, ]; // Execute the request. try { - const createTextboxWithTextResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - const createShapeResponse = createTextboxWithTextResponse.replies[0].createShape; - console.log('Created textbox with ID: %s', createShapeResponse.objectId); + const createTextboxWithTextResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + const createShapeResponse = + createTextboxWithTextResponse.replies[0].createShape; + console.log("Created textbox with ID: %s", createShapeResponse.objectId); return createTextboxWithTextResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_textbox_with_text] // [START slides_create_image] @@ -166,13 +181,14 @@ function createTextboxWithText(presentationId, pageId) { * @returns {*} */ function createImage(presentationId, pageId) { - let requests = []; - const imageId = 'MyImage_01'; - const imageUrl = 'https://www.google.com/images/branding/googlelogo/2x/' + - 'googlelogo_color_272x92dp.png'; + const requests = []; + const imageId = "MyImage_01"; + const imageUrl = + "https://www.google.com/images/branding/googlelogo/2x/" + + "googlelogo_color_272x92dp.png"; const emu4M = { magnitude: 4000000, - unit: 'EMU' + unit: "EMU", }; requests.push({ createImage: { @@ -182,34 +198,40 @@ function createImage(presentationId, pageId) { pageObjectId: pageId, size: { height: emu4M, - width: emu4M + width: emu4M, }, transform: { scaleX: 1, scaleY: 1, translateX: 100000, translateY: 100000, - unit: 'EMU' - } - } - } + unit: "EMU", + }, + }, + }, }); // Execute the request. try { - const response = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); + const response = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); const createImageResponse = response.replies; - console.log('Created image with ID: %s', createImageResponse[0].createImage.objectId); + console.log( + "Created image with ID: %s", + createImageResponse[0].createImage.objectId, + ); return createImageResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_image] // [START slides_text_merging] @@ -220,10 +242,12 @@ function createImage(presentationId, pageId) { * @returns {*[]} */ function textMerging(templatePresentationId, dataSpreadsheetId) { - let responses = []; - const dataRangeNotation = 'Customers!A2:M6'; + const responses = []; + const dataRangeNotation = "Customers!A2:M6"; try { - let values = SpreadsheetApp.openById(dataSpreadsheetId).getRange(dataRangeNotation).getValues(); + const values = SpreadsheetApp.openById(dataSpreadsheetId) + .getRange(dataRangeNotation) + .getValues(); // For each record, create a new merged presentation. for (let i = 0; i < values.length; ++i) { @@ -233,64 +257,76 @@ function textMerging(templatePresentationId, dataSpreadsheetId) { const totalPortfolio = row[11]; // total portfolio in column 12 // Duplicate the template presentation using the Drive API. - const copyTitle = customerName + ' presentation'; + const copyTitle = `${customerName} presentation`; let copyFile = { title: copyTitle, - parents: [{id: 'root'}] + parents: [{ id: "root" }], }; copyFile = Drive.Files.copy(copyFile, templatePresentationId); const presentationCopyId = copyFile.id; // Create the text merge (replaceAllText) requests for this presentation. - const requests = [{ - replaceAllText: { - containsText: { - text: '{{customer-name}}', - matchCase: true + const requests = [ + { + replaceAllText: { + containsText: { + text: "{{customer-name}}", + matchCase: true, + }, + replaceText: customerName, }, - replaceText: customerName - } - }, { - replaceAllText: { - containsText: { - text: '{{case-description}}', - matchCase: true + }, + { + replaceAllText: { + containsText: { + text: "{{case-description}}", + matchCase: true, + }, + replaceText: caseDescription, }, - replaceText: caseDescription - } - }, { - replaceAllText: { - containsText: { - text: '{{total-portfolio}}', - matchCase: true + }, + { + replaceAllText: { + containsText: { + text: "{{total-portfolio}}", + matchCase: true, + }, + replaceText: `${totalPortfolio}`, }, - replaceText: totalPortfolio + '' - } - }]; + }, + ]; // Execute the requests for this presentation. - const result = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationCopyId); + const result = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationCopyId, + ); // Count the total number of replacements made. let numReplacements = 0; - result.replies.forEach(function(reply) { + for (const reply of result.replies) { numReplacements += reply.replaceAllText.occurrencesChanged; - }); - console.log('Created presentation for %s with ID: %s', customerName, presentationCopyId); - console.log('Replaced %s text instances', numReplacements); + } + console.log( + "Created presentation for %s with ID: %s", + customerName, + presentationCopyId, + ); + console.log("Replaced %s text instances", numReplacements); // [START_EXCLUDE silent] responses.push(result.replies); - if (responses.length === values.length) { // return for the last value + if (responses.length === values.length) { + // return for the last value return responses; } // [END_EXCLUDE] } } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_text_merging] // [START slides_image_merging] @@ -305,10 +341,10 @@ function imageMerging(templatePresentationId, imageUrl, customerName) { const logoUrl = imageUrl; const customerGraphicUrl = imageUrl; - const copyTitle = customerName + ' presentation'; + const copyTitle = `${customerName} presentation`; let copyFile = { title: copyTitle, - parents: [{id: 'root'}] + parents: [{ id: "root" }], }; try { @@ -316,43 +352,49 @@ function imageMerging(templatePresentationId, imageUrl, customerName) { const presentationCopyId = copyFile.id; // Create the image merge (replaceAllShapesWithImage) requests. - const requests = [{ - replaceAllShapesWithImage: { - imageUrl: logoUrl, - imageReplaceMethod: 'CENTER_INSIDE', - containsText: { - text: '{{company-logo}}', - matchCase: true - } - } - }, { - replaceAllShapesWithImage: { - imageUrl: customerGraphicUrl, - imageReplaceMethod: 'CENTER_INSIDE', - containsText: { - text: '{{customer-graphic}}', - matchCase: true - } - } - }]; + const requests = [ + { + replaceAllShapesWithImage: { + imageUrl: logoUrl, + imageReplaceMethod: "CENTER_INSIDE", + containsText: { + text: "{{company-logo}}", + matchCase: true, + }, + }, + }, + { + replaceAllShapesWithImage: { + imageUrl: customerGraphicUrl, + imageReplaceMethod: "CENTER_INSIDE", + containsText: { + text: "{{customer-graphic}}", + matchCase: true, + }, + }, + }, + ]; // Execute the requests for this presentation. - let batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationCopyId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationCopyId, + ); let numReplacements = 0; - batchUpdateResponse.replies.forEach(function(reply) { + for (const reply of batchUpdateResponse.replies) { numReplacements += reply.replaceAllShapesWithImage.occurrencesChanged; - }); - console.log('Created merged presentation with ID: %s', presentationCopyId); - console.log('Replaced %s shapes with images.', numReplacements); + } + console.log("Created merged presentation with ID: %s", presentationCopyId); + console.log("Replaced %s shapes with images.", numReplacements); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_image_merging] // [START slides_simple_text_replace] @@ -364,34 +406,40 @@ function imageMerging(templatePresentationId, imageUrl, customerName) { * @returns {*} */ function simpleTextReplace(presentationId, shapeId, replacementText) { - const requests = [{ - deleteText: { - objectId: shapeId, - textRange: { - type: 'ALL' - } - } - }, { - insertText: { - objectId: shapeId, - insertionIndex: 0, - text: replacementText - } - }]; + const requests = [ + { + deleteText: { + objectId: shapeId, + textRange: { + type: "ALL", + }, + }, + }, + { + insertText: { + objectId: shapeId, + insertionIndex: 0, + text: replacementText, + }, + }, + ]; // Execute the requests. try { - const batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Replaced text in shape with ID: %s', shapeId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log("Replaced text in shape with ID: %s", shapeId); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_simple_text_replace] // [START slides_text_style_update] @@ -404,76 +452,83 @@ function simpleTextReplace(presentationId, shapeId, replacementText) { * @returns {*} */ function textStyleUpdate(presentationId, shapeId) { - const requests = [{ - updateTextStyle: { - objectId: shapeId, - textRange: { - type: 'FIXED_RANGE', - startIndex: 0, - endIndex: 5 - }, - style: { - bold: true, - italic: true - }, - fields: 'bold,italic' - } - }, { - updateTextStyle: { - objectId: shapeId, - textRange: { - type: 'FIXED_RANGE', - startIndex: 5, - endIndex: 10 - }, - style: { - fontFamily: 'Times New Roman', - fontSize: { - magnitude: 14, - unit: 'PT' + const requests = [ + { + updateTextStyle: { + objectId: shapeId, + textRange: { + type: "FIXED_RANGE", + startIndex: 0, + endIndex: 5, + }, + style: { + bold: true, + italic: true, }, - foregroundColor: { - opaqueColor: { - rgbColor: { - blue: 1.0, - green: 0.0, - red: 0.0 - } - } - } + fields: "bold,italic", }, - fields: 'foregroundColor,fontFamily,fontSize' - } - }, { - updateTextStyle: { - objectId: shapeId, - textRange: { - type: 'FIXED_RANGE', - startIndex: 10, - endIndex: 15 + }, + { + updateTextStyle: { + objectId: shapeId, + textRange: { + type: "FIXED_RANGE", + startIndex: 5, + endIndex: 10, + }, + style: { + fontFamily: "Times New Roman", + fontSize: { + magnitude: 14, + unit: "PT", + }, + foregroundColor: { + opaqueColor: { + rgbColor: { + blue: 1.0, + green: 0.0, + red: 0.0, + }, + }, + }, + }, + fields: "foregroundColor,fontFamily,fontSize", }, - style: { - link: { - url: 'www.example.com' - } + }, + { + updateTextStyle: { + objectId: shapeId, + textRange: { + type: "FIXED_RANGE", + startIndex: 10, + endIndex: 15, + }, + style: { + link: { + url: "www.example.com", + }, + }, + fields: "link", }, - fields: 'link' - } - }]; + }, + ]; // Execute the requests. try { - const batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Updated the text style for shape with ID: %s', shapeId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log("Updated the text style for shape with ID: %s", shapeId); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_text_style_update] // [START slides_create_bulleted_text] @@ -481,29 +536,34 @@ function textStyleUpdate(presentationId, shapeId) { * Add arrow-diamond-disc bullets to all text in the shape. */ function createBulletedText(presentationId, shapeId) { - const requests = [{ - createParagraphBullets: { - objectId: shapeId, - textRange: { - type: 'ALL' + const requests = [ + { + createParagraphBullets: { + objectId: shapeId, + textRange: { + type: "ALL", + }, + bulletPreset: "BULLET_ARROW_DIAMOND_DISC", }, - bulletPreset: 'BULLET_ARROW_DIAMOND_DISC' - } - }]; + }, + ]; // Execute the requests. try { - const batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Added bullets to text in shape with ID: %s', shapeId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log("Added bullets to text in shape with ID: %s", shapeId); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_bulleted_text] // [START slides_create_sheets_chart] @@ -520,45 +580,50 @@ function createBulletedText(presentationId, shapeId) { function createSheetsChart(presentationId, pageId, shapeId, sheetChartId) { const emu4M = { magnitude: 4000000, - unit: 'EMU' + unit: "EMU", }; - const presentationChartId = 'MyEmbeddedChart'; - const requests = [{ - createSheetsChart: { - objectId: presentationChartId, - spreadsheetId: shapeId, - chartId: sheetChartId, - linkingMode: 'LINKED', - elementProperties: { - pageObjectId: pageId, - size: { - height: emu4M, - width: emu4M + const presentationChartId = "MyEmbeddedChart"; + const requests = [ + { + createSheetsChart: { + objectId: presentationChartId, + spreadsheetId: shapeId, + chartId: sheetChartId, + linkingMode: "LINKED", + elementProperties: { + pageObjectId: pageId, + size: { + height: emu4M, + width: emu4M, + }, + transform: { + scaleX: 1, + scaleY: 1, + translateX: 100000, + translateY: 100000, + unit: "EMU", + }, }, - transform: { - scaleX: 1, - scaleY: 1, - translateX: 100000, - translateY: 100000, - unit: 'EMU' - } - } - } - }]; + }, + }, + ]; // Execute the request. try { - const batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Added a linked Sheets chart with ID: %s', presentationChartId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log("Added a linked Sheets chart with ID: %s", presentationChartId); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_create_sheets_chart] // [START slides_refresh_sheets_chart] @@ -569,23 +634,31 @@ function createSheetsChart(presentationId, pageId, shapeId, sheetChartId) { * @returns {*} */ function refreshSheetsChart(presentationId, presentationChartId) { - const requests = [{ - refreshSheetsChart: { - objectId: presentationChartId - } - }]; + const requests = [ + { + refreshSheetsChart: { + objectId: presentationChartId, + }, + }, + ]; // Execute the request. try { - const batchUpdateResponse = Slides.Presentations.batchUpdate({ - requests: requests - }, presentationId); - console.log('Refreshed a linked Sheets chart with ID: %s', presentationChartId); + const batchUpdateResponse = Slides.Presentations.batchUpdate( + { + requests: requests, + }, + presentationId, + ); + console.log( + "Refreshed a linked Sheets chart with ID: %s", + presentationChartId, + ); return batchUpdateResponse; } catch (err) { // TODO (Developer) - Handle exception - console.log('Failed with error: %s', err.error); + console.log("Failed with error: %s", err.error); } -}; +} // [END slides_refresh_sheets_chart] diff --git a/slides/api/Tests.gs b/slides/api/Tests.gs index de5046ba7..0e36e7f5d 100644 --- a/slides/api/Tests.gs +++ b/slides/api/Tests.gs @@ -17,11 +17,11 @@ const helpers = new Helpers(); // Constants const IMAGE_URL = - 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'; -const TEMPLATE_PRESENTATION_ID = '1iwq83aR9SIQbqVY-3ozLkJjKhdXErfS_m3zD8VZhtFA'; -const DATA_SPREADSHEET_ID = '1Y3GVGdJHDzlyMB9aLDWV2o_e2RstzUHK1iLDaBgbMwc'; + "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"; +const TEMPLATE_PRESENTATION_ID = "1iwq83aR9SIQbqVY-3ozLkJjKhdXErfS_m3zD8VZhtFA"; +const DATA_SPREADSHEET_ID = "1Y3GVGdJHDzlyMB9aLDWV2o_e2RstzUHK1iLDaBgbMwc"; const CHART_ID = 1107320627; -const CUSTOMER_NAME = 'Fake Customer'; +const CUSTOMER_NAME = "Fake Customer"; /** * A simple existance assertion. Logs if the value is falsy. @@ -29,7 +29,7 @@ const CUSTOMER_NAME = 'Fake Customer'; */ function expectToExist(value) { if (!value) { - console.log('DNE'); + console.log("DNE"); } } @@ -40,7 +40,7 @@ function expectToExist(value) { */ function expectToEqual(expected, actual) { if (actual !== expected) { - console.log('actual: %s expected: %s', actual, expected); + console.log("actual: %s expected: %s", actual, expected); } } @@ -66,7 +66,7 @@ function RUN_ALL_TESTS() { * Creates a presentation. */ function itShouldCreateAPresentation() { - console.log('> itShouldCreateAPresentation'); + console.log("> itShouldCreateAPresentation"); const presentation = createPresentation(); expectToExist(presentation.presentationId); helpers.deleteFileOnCleanup(presentation.presentationId); @@ -76,9 +76,9 @@ function itShouldCreateAPresentation() { * Copies a presentation. */ function itShouldCopyAPresentation() { - console.log('> itShouldCopyAPresentation'); + console.log("> itShouldCopyAPresentation"); const presentationId = helpers.createTestPresentation(); - const copyId = copyPresentation(presentationId, 'My Duplicate, Presentation'); + const copyId = copyPresentation(presentationId, "My Duplicate, Presentation"); expectToExist(copyId); helpers.deleteFileOnCleanup(copyId); } @@ -87,10 +87,10 @@ function itShouldCopyAPresentation() { * Creates a new slide. */ function itShouldCreateASlide() { - console.log('> itShouldCreateASlide'); + console.log("> itShouldCreateASlide"); const presentationId = helpers.createTestPresentation(); - helpers.addSlides(presentationId, 3, 'TITLE_AND_TWO_COLUMNS'); - const pageId = 'my_page_id'; + helpers.addSlides(presentationId, 3, "TITLE_AND_TWO_COLUMNS"); + const pageId = "my_page_id"; const response = createSlide(presentationId, pageId); expectToExist(response.replies[0].createSlide.objectId); } @@ -99,9 +99,9 @@ function itShouldCreateASlide() { * Creates a slide with text. */ function itShouldCreateATextboxWithText() { - console.log('> itShouldCreateATextboxWithText'); + console.log("> itShouldCreateATextboxWithText"); const presentationId = helpers.createTestPresentation(); - const ids = helpers.addSlides(presentationId, 3, 'TITLE_AND_TWO_COLUMNS'); + const ids = helpers.addSlides(presentationId, 3, "TITLE_AND_TWO_COLUMNS"); const pageId = ids[0]; const response = createTextboxWithText(presentationId, pageId); expectToEqual(2, response.replies.length); @@ -113,9 +113,9 @@ function itShouldCreateATextboxWithText() { * Adds an image to a slide. */ function itShouldCreateAnImage() { - console.log('> itShouldCreateAnImage'); + console.log("> itShouldCreateAnImage"); const presentationId = helpers.createTestPresentation(); - const ids = helpers.addSlides(presentationId, 1, 'BLANK'); + const ids = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = ids[0]; const response = createImage(presentationId, pageId); expectToEqual(1, response.length); @@ -127,29 +127,33 @@ function itShouldCreateAnImage() { * Merges presentation text from a spreadsheet. */ function itShouldMergeText() { - console.log('> itShouldMergeText'); - let responses = textMerging(TEMPLATE_PRESENTATION_ID, DATA_SPREADSHEET_ID); + console.log("> itShouldMergeText"); + const responses = textMerging(TEMPLATE_PRESENTATION_ID, DATA_SPREADSHEET_ID); expectToEqual(5, responses.length); - responses.forEach(function(response) { + for (const response of responses) { let numReplacements = 0; - response.forEach(function(res) { + for (const res of response) { numReplacements += res.replaceAllText.occurrencesChanged; - }); + } expectToEqual(4, numReplacements); - }); + } } /** * Merges images into a spreadsheet. */ function itShouldImageMerge() { - console.log('> itShouldImageMerge'); - let response = imageMerging(TEMPLATE_PRESENTATION_ID, IMAGE_URL, CUSTOMER_NAME); + console.log("> itShouldImageMerge"); + const response = imageMerging( + TEMPLATE_PRESENTATION_ID, + IMAGE_URL, + CUSTOMER_NAME, + ); expectToEqual(2, response.replies.length); let numReplacements = 0; - response.replies.forEach(function(reply) { + for (const reply of response.replies) { numReplacements += reply.replaceAllShapesWithImage.occurrencesChanged; - }); + } expectToEqual(2, numReplacements); } @@ -157,12 +161,12 @@ function itShouldImageMerge() { * Replaces a text box with some text. */ function itShouldSimpleTextReplace() { - console.log('> itShouldSimpleTextReplace'); + console.log("> itShouldSimpleTextReplace"); const presentationId = helpers.createTestPresentation(); - const pageIds = helpers.addSlides(presentationId, 1, 'BLANK'); + const pageIds = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = pageIds[0]; const boxId = helpers.createTestTextbox(presentationId, pageId); - const response = simpleTextReplace(presentationId, boxId, 'MY NEW TEXT'); + const response = simpleTextReplace(presentationId, boxId, "MY NEW TEXT"); expectToEqual(2, response.replies.length); } @@ -170,9 +174,9 @@ function itShouldSimpleTextReplace() { * Updates style for text. */ function itShouldTextStyleUpdate() { - console.log('> itShouldTextStyleUpdate'); + console.log("> itShouldTextStyleUpdate"); const presentationId = helpers.createTestPresentation(); - const pageIds = helpers.addSlides(presentationId, 1, 'BLANK'); + const pageIds = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = pageIds[0]; const boxId = helpers.createTestTextbox(presentationId, pageId); const response = textStyleUpdate(presentationId, boxId); @@ -183,9 +187,9 @@ function itShouldTextStyleUpdate() { * Creates bulleted text. */ function itShouldCreateBulletedText() { - console.log('> itShouldCreateBulletedText'); + console.log("> itShouldCreateBulletedText"); const presentationId = helpers.createTestPresentation(); - const pageIds = helpers.addSlides(presentationId, 1, 'BLANK'); + const pageIds = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = pageIds[0]; const boxId = helpers.createTestTextbox(presentationId, pageId); const response = createBulletedText(presentationId, boxId); @@ -196,11 +200,16 @@ function itShouldCreateBulletedText() { * Adds a sheets chart in a presentation. */ function itShouldCreateSheetsChart() { - console.log('> itShouldCreateSheetsChart'); + console.log("> itShouldCreateSheetsChart"); const presentationId = helpers.createTestPresentation(); - const pageIds = helpers.addSlides(presentationId, 1, 'BLANK'); + const pageIds = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = pageIds[0]; - const response = createSheetsChart(presentationId, pageId, DATA_SPREADSHEET_ID, CHART_ID); + const response = createSheetsChart( + presentationId, + pageId, + DATA_SPREADSHEET_ID, + CHART_ID, + ); expectToEqual(1, response.replies.length); const chartId = response.replies[0].createSheetsChart.objectId; expectToExist(chartId); @@ -210,12 +219,16 @@ function itShouldCreateSheetsChart() { * Refreshes a sheets chart in a presentation. */ function itShouldRefreshSheetsChart() { - console.log('> itShouldRefreshSheetsChart'); + console.log("> itShouldRefreshSheetsChart"); const presentationId = helpers.createTestPresentation(); - const pageIds = helpers.addSlides(presentationId, 1, 'BLANK'); + const pageIds = helpers.addSlides(presentationId, 1, "BLANK"); const pageId = pageIds[0]; - const sheetChartId = helpers.createTestSheetsChart(presentationId, pageId, DATA_SPREADSHEET_ID, - CHART_ID); + const sheetChartId = helpers.createTestSheetsChart( + presentationId, + pageId, + DATA_SPREADSHEET_ID, + CHART_ID, + ); const response = refreshSheetsChart(presentationId, sheetChartId); expectToEqual(1, response.replies.length); -} \ No newline at end of file +} diff --git a/slides/imageSlides/add_image/add_image.gs b/slides/imageSlides/add_image/add_image.gs new file mode 100644 index 000000000..80892e5b3 --- /dev/null +++ b/slides/imageSlides/add_image/add_image.gs @@ -0,0 +1,27 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_slides_image_add_image] +/** + * Adds an image to a presentation at a given slide index. + * @param {string} imageUrl The image URL + * @param {number} index The slide index to add the image to + */ +function addImageSlide(imageUrl, index) { + const slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); + const image = slide.insertImage(imageUrl); +} +// [END apps_script_slides_image_add_image] diff --git a/slides/imageSlides/add_image_slide/add_image_slide.gs b/slides/imageSlides/add_image_slide/add_image_slide.gs new file mode 100644 index 000000000..0997ec257 --- /dev/null +++ b/slides/imageSlides/add_image_slide/add_image_slide.gs @@ -0,0 +1,35 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_slides_image_add_image_slide] +/** + * Creates a single slide using the image from the given link; + * used directly by foreach(), hence the parameters are fixed. + * @param {string} imageUrl A String object representing an image URL + * @param {number} index The index into the array; unused (req'd by forEach) + */ +function addImageSlide(imageUrl, index) { + const slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); + const image = slide.insertImage(imageUrl); + const imgWidth = image.getWidth(); + const imgHeight = image.getHeight(); + const pageWidth = deck.getPageWidth(); + const pageHeight = deck.getPageHeight(); + const newX = pageWidth / 2 - imgWidth / 2; + const newY = pageHeight / 2 - imgHeight / 2; + image.setLeft(newX).setTop(newY); +} +// [END apps_script_slides_image_add_image_slide] diff --git a/slides/imageSlides/create/create.gs b/slides/imageSlides/create/create.gs new file mode 100644 index 000000000..38ef2e699 --- /dev/null +++ b/slides/imageSlides/create/create.gs @@ -0,0 +1,20 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_slides_image_create] +const NAME = "My favorite images"; +const deck = SlidesApp.create(NAME); +// [END apps_script_slides_image_create] diff --git a/slides/imageSlides/full/full.gs b/slides/imageSlides/full/full.gs new file mode 100644 index 000000000..a4c97db63 --- /dev/null +++ b/slides/imageSlides/full/full.gs @@ -0,0 +1,61 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_slides_image_full_script] +const NAME = "My favorite images"; +const presentation = SlidesApp.create(NAME); + +/** + * Creates a single slide using the image from the given link; + * used directly by foreach(), hence the parameters are fixed. + * @param {string} imageUrl A String object representing an image URL + * @param {number} index The index into the array; unused (req'd by forEach) + */ +function addImageSlide(imageUrl, index) { + const slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK); + const image = slide.insertImage(imageUrl); + const imgWidth = image.getWidth(); + const imgHeight = image.getHeight(); + const pageWidth = presentation.getPageWidth(); + const pageHeight = presentation.getPageHeight(); + const newX = pageWidth / 2 - imgWidth / 2; + const newY = pageHeight / 2 - imgHeight / 2; + image.setLeft(newX).setTop(newY); +} + +/** + * The driver application features an array of image URLs, setting of the + * main title & subtitle, and creation of individual slides for each image. + */ +function main() { + const images = [ + "http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", + "http://www.google.com/services/images/phone-animation-results_2x.png", + "http://www.google.com/services/images/section-work-card-img_2x.jpg", + "http://gsuite.google.com/img/icons/product-lockup.png", + "http://gsuite.google.com/img/home-hero_2x.jpg", + ]; + const [title, subtitle] = presentation.getSlides()[0].getPageElements(); + title.asShape().getText().setText(NAME); + subtitle + .asShape() + .getText() + .setText("Google Apps Script\nSlides Service demo"); + for (const imageUrl of images) { + addImageSlide(imageUrl); + } +} +// [END apps_script_slides_image_full_script] diff --git a/slides/imageSlides/imageSlides.gs b/slides/imageSlides/imageSlides.gs deleted file mode 100644 index 3214fa630..000000000 --- a/slides/imageSlides/imageSlides.gs +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START apps_script_slides_image_create] -const NAME = 'My favorite images'; -const deck = SlidesApp.create(NAME); -// [END apps_script_slides_image_create] - -// [START apps_script_slides_image_add_image] -/** - * Adds an image to a presentation at a given slide index. - * @param {string} imageUrl The image URL - * @param {number} index The slide index to add the image to - */ - function addImageSlide(imageUrl, index) { - const slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); - const image = slide.insertImage(imageUrl); - } -// [END apps_script_slides_image_add_image] - -// [START apps_script_slides_image_main] -/** - * Adds images to a slides presentation. - */ -function main() { - const images = [ - 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png', - 'http://www.google.com/services/images/phone-animation-results_2x.png', - 'http://www.google.com/services/images/section-work-card-img_2x.jpg', - 'http://gsuite.google.com/img/icons/product-lockup.png', - 'http://gsuite.google.com/img/home-hero_2x.jpg' - ]; - const [title, subtitle] = deck.getSlides()[0].getPageElements(); - title.asShape().getText().setText(NAME); - subtitle.asShape().getText().setText('Google Apps Script\nSlides Service demo'); - images.forEach(addImageSlide); -} -// [END apps_script_slides_image_main] - -// [START apps_script_slides_image_add_image_slide] -/** - * Creates a single slide using the image from the given link; - * used directly by foreach(), hence the parameters are fixed. - * @param {string} imageUrl A String object representing an image URL - * @param {number} index The index into the array; unused (req'd by forEach) - */ -function addImageSlide(imageUrl, index) { - const slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); - const image = slide.insertImage(imageUrl); - const imgWidth = image.getWidth(); - const imgHeight = image.getHeight(); - const pageWidth = deck.getPageWidth(); - const pageHeight = deck.getPageHeight(); - const newX = pageWidth/2. - imgWidth/2.; - const newY = pageHeight/2. - imgHeight/2.; - image.setLeft(newX).setTop(newY); -} -// [END apps_script_slides_image_add_image_slide] - - -// [START apps_script_slides_image_full_script] -const NAME = 'My favorite images'; -const presentation = SlidesApp.create(NAME); - -/** - * Creates a single slide using the image from the given link; - * used directly by foreach(), hence the parameters are fixed. - * @param {string} imageUrl A String object representing an image URL - * @param {number} index The index into the array; unused (req'd by forEach) - */ -function addImageSlide(imageUrl, index) { - const slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK); - const image = slide.insertImage(imageUrl); - const imgWidth = image.getWidth(); - const imgHeight = image.getHeight(); - const pageWidth = presentation.getPageWidth(); - const pageHeight = presentation.getPageHeight(); - const newX = pageWidth/2. - imgWidth/2.; - const newY = pageHeight/2. - imgHeight/2.; - image.setLeft(newX).setTop(newY); -} - -/** - * The driver application features an array of image URLs, setting of the - * main title & subtitle, and creation of individual slides for each image. - */ -function main() { - const images = [ - 'http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png', - 'http://www.google.com/services/images/phone-animation-results_2x.png', - 'http://www.google.com/services/images/section-work-card-img_2x.jpg', - 'http://gsuite.google.com/img/icons/product-lockup.png', - 'http://gsuite.google.com/img/home-hero_2x.jpg' - ]; - const [title, subtitle] = presentation.getSlides()[0].getPageElements(); - title.asShape().getText().setText(NAME); - subtitle.asShape().getText().setText('Google Apps Script\nSlides Service demo'); - images.forEach(addImageSlide); -} -// [END apps_script_slides_image_full_script] diff --git a/slides/imageSlides/main/main.gs b/slides/imageSlides/main/main.gs new file mode 100644 index 000000000..f753c4e4e --- /dev/null +++ b/slides/imageSlides/main/main.gs @@ -0,0 +1,39 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_slides_image_main] +/** + * Adds images to a slides presentation. + */ +function main() { + const images = [ + "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", + "http://www.google.com/services/images/phone-animation-results_2x.png", + "http://www.google.com/services/images/section-work-card-img_2x.jpg", + "http://gsuite.google.com/img/icons/product-lockup.png", + "http://gsuite.google.com/img/home-hero_2x.jpg", + ]; + const [title, subtitle] = deck.getSlides()[0].getPageElements(); + title.asShape().getText().setText(NAME); + subtitle + .asShape() + .getText() + .setText("Google Apps Script\nSlides Service demo"); + for (const imageUrl of images) { + addImageSlide(imageUrl); + } +} +// [END apps_script_slides_image_main] diff --git a/slides/progress/progress.gs b/slides/progress/progress.gs index f4fc1c9fd..7e32b8282 100644 --- a/slides/progress/progress.gs +++ b/slides/progress/progress.gs @@ -17,7 +17,7 @@ /** * @OnlyCurrentDoc Adds progress bars to a presentation. */ -const BAR_ID = 'PROGRESS_BAR_ID'; +const BAR_ID = "PROGRESS_BAR_ID"; const BAR_HEIGHT = 10; // px /** @@ -37,10 +37,11 @@ function onInstall(e) { * @param {object} e The onOpen event. */ function onOpen(e) { - SlidesApp.getUi().createAddonMenu() - .addItem('Show progress bar', 'createBars') - .addItem('Hide progress bar', 'deleteBars') - .addToUi(); + SlidesApp.getUi() + .createAddonMenu() + .addItem("Show progress bar", "createBars") + .addItem("Hide progress bar", "deleteBars") + .addToUi(); } /** @@ -51,13 +52,18 @@ function createBars() { const presentation = SlidesApp.getActivePresentation(); const slides = presentation.getSlides(); for (let i = 0; i < slides.length; ++i) { - const ratioComplete = (i / (slides.length - 1)); + const ratioComplete = i / (slides.length - 1); const x = 0; const y = presentation.getPageHeight() - BAR_HEIGHT; const barWidth = presentation.getPageWidth() * ratioComplete; if (barWidth > 0) { - const bar = slides[i].insertShape(SlidesApp.ShapeType.RECTANGLE, x, y, - barWidth, BAR_HEIGHT); + const bar = slides[i].insertShape( + SlidesApp.ShapeType.RECTANGLE, + x, + y, + barWidth, + BAR_HEIGHT, + ); bar.getBorder().setTransparent(); bar.setLinkUrl(BAR_ID); } @@ -73,9 +79,11 @@ function deleteBars() { for (let i = 0; i < slides.length; ++i) { const elements = slides[i].getPageElements(); for (const el of elements) { - if (el.getPageElementType() === SlidesApp.PageElementType.SHAPE && + if ( + el.getPageElementType() === SlidesApp.PageElementType.SHAPE && el.asShape().getLink() && - el.asShape().getLink().getUrl() === BAR_ID) { + el.asShape().getLink().getUrl() === BAR_ID + ) { el.remove(); } } diff --git a/slides/quickstart/quickstart.gs b/slides/quickstart/quickstart.gs index 4093fe865..8cf58a251 100644 --- a/slides/quickstart/quickstart.gs +++ b/slides/quickstart/quickstart.gs @@ -20,19 +20,23 @@ * https://docs.google.com/presentation/d/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc/edit */ function logSlidesAndElements() { - const presentationId = '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc'; + const presentationId = "1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc"; try { // Gets the specified presentation using presentationId const presentation = Slides.Presentations.get(presentationId); const slides = presentation.slides; // Print the number of slides and elements in presentation - console.log('The presentation contains %s slides:', slides.length); - for ( let i = 0; i < slides.length; i++) { - console.log('- Slide # %s contains %s elements.', i + 1, slides[i].pageElements.length); + console.log("The presentation contains %s slides:", slides.length); + for (let i = 0; i < slides.length; i++) { + console.log( + "- Slide # %s contains %s elements.", + i + 1, + slides[i].pageElements.length, + ); } } catch (err) { // TODO (developer) - Handle Presentation.get() exception from Slides API - console.log('Failed to found Presentation with error %s', err.message); + console.log("Failed to found Presentation with error %s", err.message); } } // [END slides_quickstart] diff --git a/slides/selection/selection.gs b/slides/selection/selection.gs index c8acaf346..8b12f32aa 100644 --- a/slides/selection/selection.gs +++ b/slides/selection/selection.gs @@ -19,7 +19,9 @@ const selection = SlidesApp.getActivePresentation().getSelection(); // [END apps_script_slides_get_selection] // [START apps_script_slides_get_current_page] -const currentPage = SlidesApp.getActivePresentation().getSelection().getCurrentPage(); +const currentPage = SlidesApp.getActivePresentation() + .getSelection() + .getCurrentPage(); // [END apps_script_slides_get_current_page] /** @@ -32,84 +34,89 @@ function slidesSelectionTypes() { let currentPage; switch (selectionType) { case SlidesApp.SelectionType.NONE: - console.log('Nothing selected'); + console.log("Nothing selected"); break; case SlidesApp.SelectionType.CURRENT_PAGE: currentPage = selection.getCurrentPage(); - console.log('Selection is a page with ID: ' + currentPage.getObjectId()); + console.log(`Selection is a page with ID: ${currentPage.getObjectId()}`); break; - case SlidesApp.SelectionType.PAGE_ELEMENT: + case SlidesApp.SelectionType.PAGE_ELEMENT: { const pageElements = selection.getPageElementRange().getPageElements(); - console.log('There are ' + pageElements.length + ' page elements selected.'); + console.log(`There are ${pageElements.length} page elements selected.`); break; - case SlidesApp.SelectionType.TEXT: + } + case SlidesApp.SelectionType.TEXT: { const tableCellRange = selection.getTableCellRange(); if (tableCellRange !== null) { const tableCell = tableCellRange.getTableCells()[0]; - console.log('Selected text is in a table at row ' + - tableCell.getRowIndex() + ', column ' + - tableCell.getColumnIndex()); + console.log( + `Selected text is in a table at row ${tableCell.getRowIndex()}, column ${tableCell.getColumnIndex()}`, + ); } const textRange = selection.getTextRange(); if (textRange.getStartIndex() === textRange.getEndIndex()) { - console.log('Text cursor position: ' + textRange.getStartIndex()); + console.log(`Text cursor position: ${textRange.getStartIndex()}`); } else { - console.log('Selection is a text range from: ' + textRange.getStartIndex() + ' to: ' + - textRange.getEndIndex() + ' is selected'); + console.log( + `Selection is a text range from: ${textRange.getStartIndex()} to: ${textRange.getEndIndex()} is selected`, + ); } break; - case SlidesApp.SelectionType.TABLE_CELL: + } + case SlidesApp.SelectionType.TABLE_CELL: { const tableCells = selection.getTableCellRange().getTableCells(); const table = tableCells[0].getParentTable(); - console.log('There are ' + tableCells.length + ' table cells selected.'); + console.log(`There are ${tableCells.length} table cells selected.`); break; - case SlidesApp.SelectionType.PAGE: + } + case SlidesApp.SelectionType.PAGE: { const pages = selection.getPageRange().getPages(); - console.log('There are ' + pages.length + ' pages selected.'); + console.log(`There are ${pages.length} pages selected.`); break; + } default: break; } -// [END apps_script_slides_selection_type] + // [END apps_script_slides_selection_type] } /** * Selecting the current page */ function slideSelect() { -// [START apps_script_slides_select] -// Select the first slide as the current page selection and remove any previous selection. + // [START apps_script_slides_select] + // Select the first slide as the current page selection and remove any previous selection. const selection = SlidesApp.getActivePresentation().getSelection(); const slide = SlidesApp.getActivePresentation().getSlides()[0]; slide.selectAsCurrentPage(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.CURRENT_PAGE -// selection.getCurrentPage() = slide -// -// [END apps_script_slides_select] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.CURRENT_PAGE + // selection.getCurrentPage() = slide + // + // [END apps_script_slides_select] } /** * Selecting a page element. */ function selectPageElement() { -// [START apps_script_slides_select_page_element] + // [START apps_script_slides_select_page_element] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const pageElement = slide.getPageElements()[0]; // Only select this page element and remove any previous selection. pageElement.select(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = pageElement -// -// [END apps_script_slides_select_page_element] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = pageElement + // + // [END apps_script_slides_select_page_element] } /** * Selecting multiple page elements */ function selectMultiplePageElement() { -// [START apps_script_slides_select_multiple_page_elements] + // [START apps_script_slides_select_multiple_page_elements] const slide = SlidesApp.getActivePresentation().getSlides()[0]; // First select the slide page, as the current page selection. slide.selectAsCurrentPage(); @@ -118,20 +125,20 @@ function selectMultiplePageElement() { for (let i = 0; i < pageElements.length; i++) { pageElements[i].select(false); } -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements() = pageElements -// -// [END apps_script_slides_select_multiple_page_elements] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements() = pageElements + // + // [END apps_script_slides_select_multiple_page_elements] } /** *This shows how selection can be transformed by manipulating * selected page elements. */ function slideTransformSelection() { -// [START apps_script_slides_transform_selection] + // [START apps_script_slides_transform_selection] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const shape1 = slide.getPageElements()[0].asShape(); const shape2 = slide.getPageElements()[1].asShape(); @@ -146,107 +153,107 @@ function slideTransformSelection() { // // Remove one shape. shape2.remove(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements() = [shape1] -// -// [END apps_script_slides_transform_selection] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.PAGE_ELEMENT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements() = [shape1] + // + // [END apps_script_slides_transform_selection] } /** * Range selection within text contained in a shape. */ function slidesRangeSelection() { -// [START apps_script_slides_range_selection_in_shape] + // [START apps_script_slides_range_selection_in_shape] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const shape = slide.getPageElements()[0].asShape(); - shape.getText().setText('Hello'); + shape.getText().setText("Hello"); // Range selection: Select the text range 'He'. shape.getText().getRange(0, 2).select(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.TEXT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = shape -// selection.getTextRange().getStartIndex() = 0 -// selection.getTextRange().getEndIndex() = 2 -// -// [END apps_script_slides_range_selection_in_shape] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.TEXT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = shape + // selection.getTextRange().getStartIndex() = 0 + // selection.getTextRange().getEndIndex() = 2 + // + // [END apps_script_slides_range_selection_in_shape] } /** * Cursor selection within text contained in a shape. */ function slidesCursorSelection() { -// [START apps_script_slides_cursor_selection_in_shape] + // [START apps_script_slides_cursor_selection_in_shape] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const shape = slide.getPageElements()[0].asShape(); - shape.getText().setText('Hello'); + shape.getText().setText("Hello"); // Cursor selection: Place the cursor after 'H' like 'H|ello'. shape.getText().getRange(1, 1).select(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.TEXT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = shape -// selection.getTextRange().getStartIndex() = 1 -// selection.getTextRange().getEndIndex() = 1 -// -// [END apps_script_slides_cursor_selection_in_shape] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.TEXT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = shape + // selection.getTextRange().getStartIndex() = 1 + // selection.getTextRange().getEndIndex() = 1 + // + // [END apps_script_slides_cursor_selection_in_shape] } /** * Range selection in table cell. */ function slideRangeSelection() { -// [START apps_script_slides_range_selection_in_table] + // [START apps_script_slides_range_selection_in_table] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const table = slide.getPageElements()[0].asTable(); const tableCell = table.getCell(0, 1); - tableCell.getText().setText('Hello'); + tableCell.getText().setText("Hello"); // Range selection: Select the text range 'He'. tableCell.getText().getRange(0, 2).select(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.TEXT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = table -// selection.getTableCellRange().getTableCells()[0] = tableCell -// selection.getTextRange().getStartIndex() = 0 -// selection.getTextRange().getEndIndex() = 2 -// -// [END apps_script_slides_range_selection_in_table] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.TEXT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = table + // selection.getTableCellRange().getTableCells()[0] = tableCell + // selection.getTextRange().getStartIndex() = 0 + // selection.getTextRange().getEndIndex() = 2 + // + // [END apps_script_slides_range_selection_in_table] } /** * Cursor selection in table cell. */ function cursorSelection() { -// [START apps_script_slides_cursor_selection_in_table] + // [START apps_script_slides_cursor_selection_in_table] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const table = slide.getPageElements()[0].asTable(); const tableCell = table.getCell(0, 1); - tableCell.getText().setText('Hello'); + tableCell.getText().setText("Hello"); // Cursor selection: Place the cursor after 'H' like 'H|ello'. tableCell.getText().getRange(1, 1).select(); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.TEXT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = table -// selection.getTableCellRange().getTableCells()[0] = tableCell -// selection.getTextRange().getStartIndex() = 1 -// selection.getTextRange().getEndIndex() = 1 -// -// [END apps_script_slides_cursor_selection_in_table] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.TEXT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = table + // selection.getTableCellRange().getTableCells()[0] = tableCell + // selection.getTextRange().getStartIndex() = 1 + // selection.getTextRange().getEndIndex() = 1 + // + // [END apps_script_slides_cursor_selection_in_table] } /** * This shows how the selection can be transformed by editing the selected text. */ function selectTransformation() { -// [START apps_script_slides_selection_transformation] + // [START apps_script_slides_selection_transformation] const slide = SlidesApp.getActivePresentation().getSlides()[0]; const shape = slide.getPageElements()[0].asShape(); const textRange = shape.getText(); - textRange.setText('World'); + textRange.setText("World"); // Select all the text 'World'. textRange.select(); // State of selection @@ -258,46 +265,46 @@ function selectTransformation() { // selection.getTextRange().getEndIndex() = 6 // // Add some text to the shape, and the selection will be transformed. - textRange.insertText(0, 'Hello '); + textRange.insertText(0, "Hello "); -// State of selection -// -// selection.getSelectionType() = SlidesApp.SelectionType.TEXT -// selection.getCurrentPage() = slide -// selection.getPageElementRange().getPageElements()[0] = shape -// selection.getTextRange().getStartIndex() = 0 -// selection.getTextRange().getEndIndex() = 12 -// -// [END apps_script_slides_selection_transformation] + // State of selection + // + // selection.getSelectionType() = SlidesApp.SelectionType.TEXT + // selection.getCurrentPage() = slide + // selection.getPageElementRange().getPageElements()[0] = shape + // selection.getTextRange().getStartIndex() = 0 + // selection.getTextRange().getEndIndex() = 12 + // + // [END apps_script_slides_selection_transformation] } /** * The following example shows how to unselect any current selections on a page * by setting that page as the current page. */ function slidesUnselectingCurrentPage() { -// [START apps_script_slides_unselecting] -// Unselect one or more page elements already selected. -// -// In case one or more page elements in the first slide are selected, setting the -// same (or any other) slide page as the current page would do the unselect. -// + // [START apps_script_slides_unselecting] + // Unselect one or more page elements already selected. + // + // In case one or more page elements in the first slide are selected, setting the + // same (or any other) slide page as the current page would do the unselect. + // const slide = SlidesApp.getActivePresentation().getSlides()[0]; slide.selectAsCurrentPage(); -// [END apps_script_slides_unselecting] + // [END apps_script_slides_unselecting] } /** * The following example shows how to unselect any current selections on a page * by selecting one page element, thus removing all other items from the selection. */ function slideUnselectingPageElements() { -// [START apps_script_slides_selecting] -// Unselect one or more page elements already selected. -// -// In case one or more page elements in the first slide are selected, -// selecting any pageElement in the first slide (or any other pageElement) would -// do the unselect and select that pageElement. -// + // [START apps_script_slides_selecting] + // Unselect one or more page elements already selected. + // + // In case one or more page elements in the first slide are selected, + // selecting any pageElement in the first slide (or any other pageElement) would + // do the unselect and select that pageElement. + // const slide = SlidesApp.getActivePresentation().getSlides()[0]; slide.getPageElements()[0].select(); -// [END apps_script_slides_selecting] + // [END apps_script_slides_selecting] } diff --git a/slides/style/style.gs b/slides/style/style.gs index deeb02f7b..51b2b0b82 100644 --- a/slides/style/style.gs +++ b/slides/style/style.gs @@ -14,94 +14,127 @@ * limitations under the License. */ function setTextHelloWorld() { -// [START apps_script_slides_hello] + // [START apps_script_slides_hello] try { // Get the first slide of active presentation const slide = SlidesApp.getActivePresentation().getSlides()[0]; // Insert shape in the slide with dimensions - const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 100, 200, 300, 60); + const shape = slide.insertShape( + SlidesApp.ShapeType.TEXT_BOX, + 100, + 200, + 300, + 60, + ); const textRange = shape.getText(); // Set text in TEXT_BOX - textRange.setText('Hello world!'); - console.log('Start: ' + textRange.getStartIndex() + '; End: ' + - textRange.getEndIndex() + '; Content: ' + textRange.asString()); + textRange.setText("Hello world!"); + console.log( + `Start: ${textRange.getStartIndex()}; End: ${textRange.getEndIndex()}; Content: ${textRange.asString()}`, + ); const subRange = textRange.getRange(0, 5); - console.log('Sub-range Start: ' + subRange.getStartIndex() + '; Sub-range End: ' + - subRange.getEndIndex() + '; Sub-range Content: ' + subRange.asString()); + console.log( + `Sub-range Start: ${subRange.getStartIndex()}; Sub-range End: ${subRange.getEndIndex()}; Sub-range Content: ${subRange.asString()}`, + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } -// [END apps_script_slides_hello] + // [END apps_script_slides_hello] } /** * Insert Text in shape. */ function insertText() { -// [START apps_script_slides_insert_text] + // [START apps_script_slides_insert_text] try { // Get the first slide of active presentation const slide = SlidesApp.getActivePresentation().getSlides()[0]; // Insert shape in the slide with dimensions - const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 100, 200, 300, 60); + const shape = slide.insertShape( + SlidesApp.ShapeType.TEXT_BOX, + 100, + 200, + 300, + 60, + ); const textRange = shape.getText(); - textRange.setText('Hello world!'); + textRange.setText("Hello world!"); textRange.clear(6, 11); // Insert text in TEXT_BOX - textRange.insertText(6, 'galaxy'); - console.log('Start: ' + textRange.getStartIndex() + '; End: ' + - textRange.getEndIndex() + '; Content: ' + textRange.asString()); + textRange.insertText(6, "galaxy"); + console.log( + `Start: ${textRange.getStartIndex()}; End: ${textRange.getEndIndex()}; Content: ${textRange.asString()}`, + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } -// [END apps_script_slides_insert_text] + // [END apps_script_slides_insert_text] } /** * Style the text */ function styleText() { -// [START apps_script_slides_style_text] + // [START apps_script_slides_style_text] try { // Get the first slide of active presentation const slide = SlidesApp.getActivePresentation().getSlides()[0]; // Insert shape in the slide with dimensions - const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 100, 200, 300, 60); + const shape = slide.insertShape( + SlidesApp.ShapeType.TEXT_BOX, + 100, + 200, + 300, + 60, + ); const textRange = shape.getText(); // Set text in TEXT_BOX - textRange.setText('Hello '); + textRange.setText("Hello "); // Append text in TEXT_BOX - const insertedText = textRange.appendText('world!'); + const insertedText = textRange.appendText("world!"); // Style the text with url,bold - insertedText.getTextStyle() - .setBold(true) - .setLinkUrl('www.example.com') - .setForegroundColor('#ff0000'); + insertedText + .getTextStyle() + .setBold(true) + .setLinkUrl("www.example.com") + .setForegroundColor("#ff0000"); const helloRange = textRange.getRange(0, 5); - console.log('Text: ' + helloRange.asString() + '; Bold: ' + helloRange.getTextStyle().isBold()); - console.log('Text: ' + insertedText.asString() + '; Bold: ' + - insertedText.getTextStyle().isBold()); - console.log('Text: ' + textRange.asString() + '; Bold: ' + textRange.getTextStyle().isBold()); + console.log( + `Text: ${helloRange.asString()}; Bold: ${helloRange.getTextStyle().isBold()}`, + ); + console.log( + `Text: ${insertedText.asString()}; Bold: ${insertedText.getTextStyle().isBold()}`, + ); + console.log( + `Text: ${textRange.asString()}; Bold: ${textRange.getTextStyle().isBold()}`, + ); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } -// [END apps_script_slides_style_text] + // [END apps_script_slides_style_text] } /** * Style the paragraph */ function paragraphStyling() { -// [START apps_script_slides_paragraph_styling] + // [START apps_script_slides_paragraph_styling] try { // Get the first slide of active presentation const slide = SlidesApp.getActivePresentation().getSlides()[0]; // Insert shape in the slide with dimensions - const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 50, 300, 300); + const shape = slide.insertShape( + SlidesApp.ShapeType.TEXT_BOX, + 50, + 50, + 300, + 300, + ); const textRange = shape.getText(); // Set the text in the shape/TEXT_BOX - textRange.setText('Paragraph 1\nParagraph2\nParagraph 3\nParagraph 4'); + textRange.setText("Paragraph 1\nParagraph2\nParagraph 3\nParagraph 4"); const paragraphs = textRange.getParagraphs(); // Style the paragraph alignment center. for (let i = 0; i <= 3; i++) { @@ -110,36 +143,47 @@ function paragraphStyling() { } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } -// [END apps_script_slides_paragraph_styling] + // [END apps_script_slides_paragraph_styling] } /** * Style the list */ function listStyling() { -// [START apps_script_slides_list_styling] + // [START apps_script_slides_list_styling] try { // Get the first slide of active presentation const slide = SlidesApp.getActivePresentation().getSlides()[0]; // Insert shape in the slide with dimensions - const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 50, 300, 300); + const shape = slide.insertShape( + SlidesApp.ShapeType.TEXT_BOX, + 50, + 50, + 300, + 300, + ); // Add and style the list const textRange = shape.getText(); - textRange.appendText('Item 1\n') - .appendText('\tItem 2\n') - .appendText('\t\tItem 3\n') - .appendText('Item 4'); + textRange + .appendText("Item 1\n") + .appendText("\tItem 2\n") + .appendText("\t\tItem 3\n") + .appendText("Item 4"); // Preset patterns of glyphs for lists in text. - textRange.getListStyle().applyListPreset(SlidesApp.ListPreset.DIGIT_ALPHA_ROMAN); + textRange + .getListStyle() + .applyListPreset(SlidesApp.ListPreset.DIGIT_ALPHA_ROMAN); const paragraphs = textRange.getParagraphs(); for (let i = 0; i < paragraphs.length; i++) { const listStyle = paragraphs[i].getRange().getListStyle(); - console.log('Paragraph ' + (i + 1) + '\'s nesting level: ' + listStyle.getNestingLevel()); + console.log( + `Paragraph ${i + 1}'s nesting level: ${listStyle.getNestingLevel()}`, + ); } } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with an error %s ', err.message); + console.log("Failed with an error %s ", err.message); } -// [END apps_script_slides_list_styling] + // [END apps_script_slides_list_styling] } diff --git a/slides/style/test_style.gs b/slides/style/test_style.gs index c09cb62ff..5bc882c74 100644 --- a/slides/style/test_style.gs +++ b/slides/style/test_style.gs @@ -18,14 +18,14 @@ * runs all the test */ function RUN_ALL_TESTS() { - console.log('> itShouldSetTextHelloWorld'); + console.log("> itShouldSetTextHelloWorld"); setTextHelloWorld(); - console.log('> itShouldInsertText'); + console.log("> itShouldInsertText"); insertText(); - console.log('> itShouldStyleText'); + console.log("> itShouldStyleText"); styleText(); - console.log('> itShouldStyleParagraph'); + console.log("> itShouldStyleParagraph"); paragraphStyling(); - console.log('> itShouldListStyling'); + console.log("> itShouldListStyling"); listStyling(); } diff --git a/slides/translate/translate.gs b/slides/translate/translate.gs index 757e9266c..9f80ddff1 100644 --- a/slides/translate/translate.gs +++ b/slides/translate/translate.gs @@ -23,9 +23,10 @@ * @param {Event} event The open event. */ function onOpen(event) { - SlidesApp.getUi().createAddonMenu() - .addItem('Open Translate', 'showSidebar') - .addToUi(); + SlidesApp.getUi() + .createAddonMenu() + .addItem("Open Translate", "showSidebar") + .addToUi(); } /** @@ -40,9 +41,8 @@ function onInstall(event) { * Opens a sidebar in the document containing the add-on's user interface. */ function showSidebar() { - const ui = HtmlService - .createHtmlOutputFromFile('sidebar') - .setTitle('Translate'); + const ui = + HtmlService.createHtmlOutputFromFile("sidebar").setTitle("Translate"); SlidesApp.getUi().showSidebar(ui); } @@ -53,26 +53,27 @@ function showSidebar() { */ function getElementTexts(elements) { let texts = []; - elements.forEach((element)=> { + for (const element of elements) { switch (element.getPageElementType()) { case SlidesApp.PageElementType.GROUP: - element.asGroup().getChildren().forEach((child)=> { + for (const child of element.asGroup().getChildren()) { texts = texts.concat(getElementTexts(child)); - }); + } break; - case SlidesApp.PageElementType.TABLE: + case SlidesApp.PageElementType.TABLE: { const table = element.asTable(); - for (let y = 0; y < table.getNumColumns(); ++y) { - for (let x = 0; x < table.getNumRows(); ++x) { - texts.push(table.getCell(x, y).getText()); + for (let r = 0; r < table.getNumRows(); ++r) { + for (let c = 0; c < table.getNumColumns(); ++c) { + texts.push(table.getCell(r, c).getText()); } } break; + } case SlidesApp.PageElementType.SHAPE: texts.push(element.asShape().getText()); break; } - }); + } return texts; } @@ -89,30 +90,33 @@ function translateSelectedElements(targetLanguage) { let texts = []; switch (selectionType) { case SlidesApp.SelectionType.PAGE: - selection.getPageRange().getPages().forEach((page)=> { + for (const page of selection.getPageRange().getPages()) { texts = texts.concat(getElementTexts(page.getPageElements())); - }); + } break; - case SlidesApp.SelectionType.PAGE_ELEMENT: + case SlidesApp.SelectionType.PAGE_ELEMENT: { const pageElements = selection.getPageElementRange().getPageElements(); texts = texts.concat(getElementTexts(pageElements)); break; + } case SlidesApp.SelectionType.TABLE_CELL: - selection.getTableCellRange().getTableCells().forEach((cell)=> { + for (const cell of selection.getTableCellRange().getTableCells()) { texts.push(cell.getText()); - }); + } break; case SlidesApp.SelectionType.TEXT: - selection.getPageElementRange().getPageElements().forEach((element) =>{ + for (const element of selection.getPageElementRange().getPageElements()) { texts.push(element.asShape().getText()); - }); + } break; } // Translate all elements in-place. - texts.forEach((text)=> { - text.setText(LanguageApp.translate(text.asRenderedString(), '', targetLanguage)); - }); + for (const text of texts) { + text.setText( + LanguageApp.translate(text.asRenderedString(), "", targetLanguage), + ); + } return texts.length; } diff --git a/solutions/attendance-chat-app/final/Code.gs b/solutions/attendance-chat-app/final/Code.gs index c62c93a1c..79f42cdc4 100644 --- a/solutions/attendance-chat-app/final/Code.gs +++ b/solutions/attendance-chat-app/final/Code.gs @@ -6,9 +6,9 @@ */ function onAddToSpace(event) { console.info(event); - var message = 'Thank you for adding me to '; - if (event.space.type === 'DM') { - message += 'a DM, ' + event.user.displayName + '!'; + let message = "Thank you for adding me to "; + if (event.space.type === "DM") { + message += `a DM, ${event.user.displayName}!`; } else { message += event.space.displayName; } @@ -22,16 +22,16 @@ function onAddToSpace(event) { */ function onRemoveFromSpace(event) { console.info(event); - console.log('Chat app removed from ', event.space.name); + console.log("Chat app removed from ", event.space.name); } -var DEFAULT_IMAGE_URL = 'https://goo.gl/bMqzYS'; -var HEADER = { +const DEFAULT_IMAGE_URL = "https://goo.gl/bMqzYS"; +const HEADER = { header: { - title : 'Attendance Chat app', - subtitle : 'Log your vacation time', - imageUrl : DEFAULT_IMAGE_URL - } + title: "Attendance Chat app", + subtitle: "Log your vacation time", + imageUrl: DEFAULT_IMAGE_URL, + }, }; /** @@ -41,17 +41,22 @@ var HEADER = { */ function createCardResponse(widgets) { return { - cards: [HEADER, { - sections: [{ - widgets: widgets - }] - }] + cards: [ + HEADER, + { + sections: [ + { + widgets: widgets, + }, + ], + }, + ], }; } -var REASON = { - SICK: 'Out sick', - OTHER: 'Out of office' +const REASON = { + SICK: "Out sick", + OTHER: "Out of office", }; /** * Responds to a MESSAGE event triggered in Google Chat. @@ -60,54 +65,64 @@ var REASON = { */ function onMessage(event) { console.info(event); - var reason = REASON.OTHER; - var name = event.user.displayName; - var userMessage = event.message.text; + let reason = REASON.OTHER; + const name = event.user.displayName; + const userMessage = event.message.text; // If the user said that they were 'sick', adjust the image in the // header sent in response. - if (userMessage.indexOf('sick') > -1) { + if (userMessage.indexOf("sick") > -1) { // Hospital material icon - HEADER.header.imageUrl = 'https://goo.gl/mnZ37b'; + HEADER.header.imageUrl = "https://goo.gl/mnZ37b"; reason = REASON.SICK; - } else if (userMessage.indexOf('vacation') > -1) { + } else if (userMessage.indexOf("vacation") > -1) { // Spa material icon - HEADER.header.imageUrl = 'https://goo.gl/EbgHuc'; + HEADER.header.imageUrl = "https://goo.gl/EbgHuc"; } - var widgets = [{ - textParagraph: { - text: 'Hello, ' + name + '.
Are you taking time off today?' - } - }, { - buttons: [{ - textButton: { - text: 'Set vacation in Gmail', - onClick: { - action: { - actionMethodName: 'turnOnAutoResponder', - parameters: [{ - key: 'reason', - value: reason - }] - } - } - } - }, { - textButton: { - text: 'Block out day in Calendar', - onClick: { - action: { - actionMethodName: 'blockOutCalendar', - parameters: [{ - key: 'reason', - value: reason - }] - } - } - } - }] - }]; + const widgets = [ + { + textParagraph: { + text: `Hello, ${name}.
Are you taking time off today?`, + }, + }, + { + buttons: [ + { + textButton: { + text: "Set vacation in Gmail", + onClick: { + action: { + actionMethodName: "turnOnAutoResponder", + parameters: [ + { + key: "reason", + value: reason, + }, + ], + }, + }, + }, + }, + { + textButton: { + text: "Block out day in Calendar", + onClick: { + action: { + actionMethodName: "blockOutCalendar", + parameters: [ + { + key: "reason", + value: reason, + }, + ], + }, + }, + }, + }, + ], + }, + ]; return createCardResponse(widgets); } @@ -119,36 +134,40 @@ function onMessage(event) { */ function onCardClick(event) { console.info(event); - var message = ''; - var reason = event.action.parameters[0].value; - if (event.action.actionMethodName == 'turnOnAutoResponder') { + let message = ""; + const reason = event.action.parameters[0].value; + if (event.action.actionMethodName === "turnOnAutoResponder") { turnOnAutoResponder(reason); - message = 'Turned on vacation settings.'; - } else if (event.action.actionMethodName == 'blockOutCalendar') { + message = "Turned on vacation settings."; + } else if (event.action.actionMethodName === "blockOutCalendar") { blockOutCalendar(reason); - message = 'Blocked out your calendar for the day.'; + message = "Blocked out your calendar for the day."; } else { message = "I'm sorry; I'm not sure which button you clicked."; } return { text: message }; } -var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; +const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; /** * Turns on the user's vacation response for today in Gmail. * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER */ function turnOnAutoResponder(reason) { - var currentTime = (new Date()).getTime(); - Gmail.Users.Settings.updateVacation({ - enableAutoReply: true, - responseSubject: reason, - responseBodyHtml: "I'm out of the office today; will be back on the next business day.

Created by Attendance Chat app!", - restrictToContacts: true, - restrictToDomain: true, - startTime: currentTime, - endTime: currentTime + ONE_DAY_MILLIS - }, 'me'); + const currentTime = new Date().getTime(); + Gmail.Users.Settings.updateVacation( + { + enableAutoReply: true, + responseSubject: reason, + responseBodyHtml: + "I'm out of the office today; will be back on the next business day.

Created by Attendance Chat app!", + restrictToContacts: true, + restrictToDomain: true, + startTime: currentTime, + endTime: currentTime + ONE_DAY_MILLIS, + }, + "me", + ); } /** @@ -156,5 +175,9 @@ function turnOnAutoResponder(reason) { * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER */ function blockOutCalendar(reason) { - CalendarApp.createAllDayEvent(reason, new Date(), new Date(Date.now() + ONE_DAY_MILLIS)); + CalendarApp.createAllDayEvent( + reason, + new Date(), + new Date(Date.now() + ONE_DAY_MILLIS), + ); } diff --git a/solutions/attendance-chat-app/step-3/Code.gs b/solutions/attendance-chat-app/step-3/Code.gs index fc47fd758..6f10f0716 100644 --- a/solutions/attendance-chat-app/step-3/Code.gs +++ b/solutions/attendance-chat-app/step-3/Code.gs @@ -8,17 +8,15 @@ function onAddToSpace(event) { console.info(event); - var message = ""; + let message = ""; if (event.space.type === "DM") { - message = "Thank you for adding me to a DM, " + - event.user.displayName + "!"; + message = `Thank you for adding me to a DM, ${event.user.displayName}!`; } else { - message = "Thank you for adding me to " + - event.space.displayName; + message = `Thank you for adding me to ${event.space.displayName}`; } - return { "text": message }; + return { text: message }; } /** diff --git a/solutions/attendance-chat-app/step-4/Code.gs b/solutions/attendance-chat-app/step-4/Code.gs index fc47fd758..6f10f0716 100644 --- a/solutions/attendance-chat-app/step-4/Code.gs +++ b/solutions/attendance-chat-app/step-4/Code.gs @@ -8,17 +8,15 @@ function onAddToSpace(event) { console.info(event); - var message = ""; + let message = ""; if (event.space.type === "DM") { - message = "Thank you for adding me to a DM, " + - event.user.displayName + "!"; + message = `Thank you for adding me to a DM, ${event.user.displayName}!`; } else { - message = "Thank you for adding me to " + - event.space.displayName; + message = `Thank you for adding me to ${event.space.displayName}`; } - return { "text": message }; + return { text: message }; } /** diff --git a/solutions/attendance-chat-app/step-5/Code.gs b/solutions/attendance-chat-app/step-5/Code.gs index 3aad2a4c5..83f227e40 100644 --- a/solutions/attendance-chat-app/step-5/Code.gs +++ b/solutions/attendance-chat-app/step-5/Code.gs @@ -8,17 +8,15 @@ function onAddToSpace(event) { console.info(event); - var message = ""; + let message = ""; if (event.space.type === "DM") { - message = "Thank you for adding me to a DM, " + - event.user.displayName + "!"; + message = `Thank you for adding me to a DM, ${event.user.displayName}!`; } else { - message = "Thank you for adding me to " + - event.space.displayName; + message = `Thank you for adding me to ${event.space.displayName}`; } - return { "text": message }; + return { text: message }; } /** @@ -40,13 +38,16 @@ function onRemoveFromSpace(event) { */ function createCardResponse(widgets) { return { - "cards": [ + cards: [ header, { - "sections": [{ - "widgets": widgets - }] - }] + sections: [ + { + widgets: widgets, + }, + ], + }, + ], }; } @@ -57,13 +58,15 @@ function createCardResponse(widgets) { * @return JSON-formatted response */ function onMessage(event) { - var userMessage = event.message.text; + const userMessage = event.message.text; - var widgets = [{ - "textParagraph": { - "text": "You said: " + userMessage - } - }]; + const widgets = [ + { + textParagraph: { + text: `You said: ${userMessage}`, + }, + }, + ]; return createCardResponse(widgets); -} \ No newline at end of file +} diff --git a/solutions/attendance-chat-app/step-6/Code.gs b/solutions/attendance-chat-app/step-6/Code.gs index 84707a15f..a7803a9af 100644 --- a/solutions/attendance-chat-app/step-6/Code.gs +++ b/solutions/attendance-chat-app/step-6/Code.gs @@ -8,17 +8,15 @@ function onAddToSpace(event) { console.info(event); - var message = ""; + let message = ""; if (event.space.type === "DM") { - message = "Thank you for adding me to a DM, " + - event.user.displayName + "!"; + message = `Thank you for adding me to a DM, ${event.user.displayName}!`; } else { - message = "Thank you for adding me to " + - event.space.displayName; + message = `Thank you for adding me to ${event.space.displayName}`; } - return { "text": message }; + return { text: message }; } /** @@ -32,13 +30,13 @@ function onRemoveFromSpace(event) { console.info("Chat app removed from ", event.space.name); } -var DEFAULT_IMAGE_URL = "https://goo.gl/bMqzYS"; -var header = { - "header": { - "title" : "Attendance Chat app", - "subtitle" : "Log your vacation time", - "imageUrl" : DEFAULT_IMAGE_URL - } +const DEFAULT_IMAGE_URL = "https://goo.gl/bMqzYS"; +const header = { + header: { + title: "Attendance Chat app", + subtitle: "Log your vacation time", + imageUrl: DEFAULT_IMAGE_URL, + }, }; /** @@ -49,18 +47,21 @@ var header = { */ function createCardResponse(widgets) { return { - "cards": [ + cards: [ header, { - "sections": [{ - "widgets": widgets - }] - }] + sections: [ + { + widgets: widgets, + }, + ], + }, + ], }; } -var REASON_SICK = "Out sick"; -var REASON_OTHER = "Out of office"; +const REASON_SICK = "Out sick"; +const REASON_OTHER = "Out of office"; /** * Responds to a MESSAGE event triggered in Google Chat. @@ -71,58 +72,64 @@ var REASON_OTHER = "Out of office"; function onMessage(event) { console.info(event); - var reason = REASON_OTHER; - var name = event.user.displayName; - var userMessage = event.message.text; + let reason = REASON_OTHER; + const name = event.user.displayName; + const userMessage = event.message.text; // If the user said that they were "sick", adjust the image in the // header sent in response. if (userMessage.indexOf("sick") > -1) { - // Hospital material icon header.header.imageUrl = "https://goo.gl/mnZ37b"; reason = REASON_SICK; - } else if (userMessage.indexOf("vacation") > -1) { - // Spa material icon header.header.imageUrl = "https://goo.gl/EbgHuc"; } - var widgets = [{ - "textParagraph": { - "text": "Hello, " + name + - ".
Are you taking time off today?" - } - }, { - "buttons": [{ - "textButton": { - "text": "Set vacation in Gmail", - "onClick": { - "action": { - "actionMethodName": "turnOnAutoResponder", - "parameters": [{ - "key": "reason", - "value": reason - }] - } - } - } - }, { - "textButton": { - "text": "Block out day in Calendar", - "onClick": { - "action": { - "actionMethodName": "blockOutCalendar", - "parameters": [{ - "key": "reason", - "value": reason - }] - } - } - } - }] - }]; + const widgets = [ + { + textParagraph: { + text: `Hello, ${name}.
Are you taking time off today?`, + }, + }, + { + buttons: [ + { + textButton: { + text: "Set vacation in Gmail", + onClick: { + action: { + actionMethodName: "turnOnAutoResponder", + parameters: [ + { + key: "reason", + value: reason, + }, + ], + }, + }, + }, + }, + { + textButton: { + text: "Block out day in Calendar", + onClick: { + action: { + actionMethodName: "blockOutCalendar", + parameters: [ + { + key: "reason", + value: reason, + }, + ], + }, + }, + }, + }, + ], + }, + ]; return createCardResponse(widgets); } @@ -136,23 +143,23 @@ function onMessage(event) { function onCardClick(event) { console.info(event); - var message = ""; - var reason = event.action.parameters[0].value; + let message = ""; + const reason = event.action.parameters[0].value; - if (event.action.actionMethodName == "turnOnAutoResponder") { + if (event.action.actionMethodName === "turnOnAutoResponder") { turnOnAutoResponder(reason); message = "Turned on vacation settings."; - } else if (event.action.actionMethodName == "blockOutCalendar") { + } else if (event.action.actionMethodName === "blockOutCalendar") { blockOutCalendar(reason); message = "Blocked out your calendar for the day."; } else { message = "I'm sorry; I'm not sure which button you clicked."; } - return { "text": message }; + return { text: message }; } -var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; +const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; /** * Turns on the user's vacation response for today in Gmail. @@ -160,17 +167,21 @@ var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; * @param reason the reason for vacation, either REASON_SICK or REASON_OTHER */ function turnOnAutoResponder(reason) { - var currentTime = (new Date()).getTime(); - - Gmail.Users.Settings.updateVacation({ - "enableAutoReply": true, - "responseSubject": reason, - "responseBodyHtml": "I'm out of the office today; will be back on the next business day.

Created by Attendance Chat app!", - "restrictToContacts": true, - "restrictToDomain": true, - "startTime": currentTime, - "endTime": currentTime + ONE_DAY_MILLIS - }, "me"); + const currentTime = new Date().getTime(); + + Gmail.Users.Settings.updateVacation( + { + enableAutoReply: true, + responseSubject: reason, + responseBodyHtml: + "I'm out of the office today; will be back on the next business day.

Created by Attendance Chat app!", + restrictToContacts: true, + restrictToDomain: true, + startTime: currentTime, + endTime: currentTime + ONE_DAY_MILLIS, + }, + "me", + ); } /** @@ -179,5 +190,9 @@ function turnOnAutoResponder(reason) { * @param reason the reason for vacation, either REASON_SICK or REASON_OTHER */ function blockOutCalendar(reason) { - CalendarApp.createAllDayEvent(reason, new Date(), new Date(Date.now() + ONE_DAY_MILLIS)); + CalendarApp.createAllDayEvent( + reason, + new Date(), + new Date(Date.now() + ONE_DAY_MILLIS), + ); } diff --git a/solutions/ooo-assistant/Chat.gs b/solutions/ooo-assistant/Chat.gs index 0a8f3a59b..abb25f0c5 100644 --- a/solutions/ooo-assistant/Chat.gs +++ b/solutions/ooo-assistant/Chat.gs @@ -21,7 +21,7 @@ const APP_COMMAND = "app command"; * @param {Object} event the event object from Google Workspace Add On */ function onAddedToSpace(event) { - return sendCreateMessageAction(createCardMessage(help(APP_COMMAND))); + return sendCreateMessageAction(createCardMessage(help(APP_COMMAND))); } /** @@ -53,17 +53,25 @@ function onAppCommand(event) { */ function onRemovedFromSpace(event) { const space = event.chat.removedFromSpacePayload.space; - console.info(`Chat app removed from ${(space.name || "this chat")}`); + console.info(`Chat app removed from ${space.name || "this chat"}`); } // ---------------------- // Util functions // ---------------------- -function createTextMessage(text) { return { text: text }; } +function createTextMessage(text) { + return { text: text }; +} -function createCardMessage(card) { return { cardsV2: [{ card: card }]}; } +function createCardMessage(card) { + return { cardsV2: [{ card: card }] }; +} function sendCreateMessageAction(message) { - return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: message }}}}; + return { + hostAppDataAction: { + chatDataAction: { createMessageAction: { message: message } }, + }, + }; } diff --git a/solutions/ooo-assistant/Common.gs b/solutions/ooo-assistant/Common.gs index f6499ad42..e8b0d2e53 100644 --- a/solutions/ooo-assistant/Common.gs +++ b/solutions/ooo-assistant/Common.gs @@ -35,18 +35,39 @@ function onHomepage() { function help(featureName = UNIVERSAL_ACTION) { return { header: addOnCardHeader(), - sections: [{ widgets: [{ - decoratedText: { text: "Hi! 👋 Feel free to use the following " + featureName + "s:", wrapText: true }}, { - decoratedText: { text: "⛔ Block day out: I will block out your calendar for today.", wrapText: true }}, { - decoratedText: { text: "↩️ Set auto reply: I will set an OOO auto reply in your Gmail.", wrapText: true } - }]}] + sections: [ + { + widgets: [ + { + decoratedText: { + text: `Hi! 👋 Feel free to use the following ${featureName}s:`, + wrapText: true, + }, + }, + { + decoratedText: { + text: "⛔ Block day out: I will block out your calendar for today.", + wrapText: true, + }, + }, + { + decoratedText: { + text: "↩️ Set auto reply: I will set an OOO auto reply in your Gmail.", + wrapText: true, + }, + }, + ], + }, + ], }; } // Block day out action: Adds an all-day event to the user's Google Calendar. function blockDayOut() { blockOutCalendar(); - return createActionResponseCard('Your calendar is now blocked out for today.') + return createActionResponseCard( + "Your calendar is now blocked out for today.", + ); } // Creates an OOO event in the user's Calendar. @@ -58,40 +79,46 @@ function blockOutCalendar() { date.setSeconds(0); date.setMilliseconds(0); return date.toISOString(); - } - + } + const event = { start: { dateTime: getDateAndHours(9, 0) }, end: { dateTime: getDateAndHours(17, 0) }, - eventType: 'outOfOffice', - summary: 'OOO', + eventType: "outOfOffice", + summary: "OOO", outOfOfficeProperties: { - autoDeclineMode: 'declineOnlyNewConflictingInvitations', - declineMessage: 'Declined because OOO.', - } - } - Calendar.Events.insert(event, 'primary'); + autoDeclineMode: "declineOnlyNewConflictingInvitations", + declineMessage: "Declined because OOO.", + }, + }; + Calendar.Events.insert(event, "primary"); } // Set auto reply action: Set OOO auto reply in the user's Gmail . function setAutoReply() { turnOnAutoResponder(); - return createActionResponseCard('The out of office auto reply has been turned on.') + return createActionResponseCard( + "The out of office auto reply has been turned on.", + ); } // Turns on the user's vacation response for today in Gmail. function turnOnAutoResponder() { const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; - const currentTime = (new Date()).getTime(); - Gmail.Users.Settings.updateVacation({ - enableAutoReply: true, - responseSubject: 'I am OOO today', - responseBodyHtml: 'I am OOO today.

Created by OOO Assistant add-on!', - restrictToContacts: true, - restrictToDomain: true, - startTime: currentTime, - endTime: currentTime + ONE_DAY_MILLIS - }, 'me'); + const currentTime = new Date().getTime(); + Gmail.Users.Settings.updateVacation( + { + enableAutoReply: true, + responseSubject: "I am OOO today", + responseBodyHtml: + "I am OOO today.

Created by OOO Assistant add-on!", + restrictToContacts: true, + restrictToDomain: true, + startTime: currentTime, + endTime: currentTime + ONE_DAY_MILLIS, + }, + "me", + ); } // ---------------------- @@ -100,20 +127,31 @@ function turnOnAutoResponder() { function addOnCardHeader() { return { - title: "OOO Assistant", - subtitle: "Helping manage your OOO", - imageUrl: "https://goo.gle/3SfMkjb", - }; + title: "OOO Assistant", + subtitle: "Helping manage your OOO", + imageUrl: "https://goo.gle/3SfMkjb", + }; } // Create an action response card function createActionResponseCard(text) { return { header: addOnCardHeader(), - sections: [{ widgets: [{ decoratedText: { - startIcon: { iconUrl: "https://fonts.gstatic.com/s/i/short-term/web/system/1x/task_alt_gm_grey_48dp.png" }, - text: text, - wrapText: true - }}]}] + sections: [ + { + widgets: [ + { + decoratedText: { + startIcon: { + iconUrl: + "https://fonts.gstatic.com/s/i/short-term/web/system/1x/task_alt_gm_grey_48dp.png", + }, + text: text, + wrapText: true, + }, + }, + ], + }, + ], }; } diff --git a/tasks/quickstart/quickstart.gs b/tasks/quickstart/quickstart.gs index fae31d265..248dac399 100644 --- a/tasks/quickstart/quickstart.gs +++ b/tasks/quickstart/quickstart.gs @@ -20,7 +20,7 @@ */ function listTaskLists() { const optionalArgs = { - maxResults: 10 + maxResults: 10, }; try { // Returns all the authenticated user's task lists. @@ -28,15 +28,15 @@ function listTaskLists() { const taskLists = response.items; // Print task list of user if available. if (!taskLists || taskLists.length === 0) { - console.log('No task lists found.'); + console.log("No task lists found."); return; } for (const taskList of taskLists) { - console.log('%s (%s)', taskList.title, taskList.id); + console.log("%s (%s)", taskList.title, taskList.id); } } catch (err) { // TODO (developer) - Handle exception from Task API - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END tasks_quickstart] diff --git a/tasks/simpleTasks/simpleTasks.gs b/tasks/simpleTasks/simpleTasks.gs index 1843ccc9c..922ccadd9 100644 --- a/tasks/simpleTasks/simpleTasks.gs +++ b/tasks/simpleTasks/simpleTasks.gs @@ -19,8 +19,9 @@ * @return {HtmlOutput} The HTML page to be served. */ function doGet() { - return HtmlService.createTemplateFromFile('page').evaluate() - .setTitle('Simple Tasks'); + return HtmlService.createTemplateFromFile("page") + .evaluate() + .setTitle("Simple Tasks"); } /** @@ -28,16 +29,14 @@ function doGet() { * @return {Array.} The task list data. */ function getTaskLists() { - var taskLists = Tasks.Tasklists.list().getItems(); + const taskLists = Tasks.Tasklists.list().getItems(); if (!taskLists) { return []; } - return taskLists.map(function(taskList) { - return { - id: taskList.getId(), - name: taskList.getTitle() - }; - }); + return taskLists.map((taskList) => ({ + id: taskList.getId(), + name: taskList.getTitle(), + })); } /** @@ -46,20 +45,18 @@ function getTaskLists() { * @return {Array.} The task data. */ function getTasks(taskListId) { - var tasks = Tasks.Tasks.list(taskListId).getItems(); + const tasks = Tasks.Tasks.list(taskListId).getItems(); if (!tasks) { return []; } - return tasks.map(function(task) { - return { + return tasks + .map((task) => ({ id: task.getId(), title: task.getTitle(), notes: task.getNotes(), - completed: Boolean(task.getCompleted()) - }; - }).filter(function(task) { - return task.title; - }); + completed: Boolean(task.getCompleted()), + })) + .filter((task) => task.title); } /** @@ -69,11 +66,11 @@ function getTasks(taskListId) { * @param {Boolean} completed True if the task should be marked as complete, false otherwise. */ function setCompleted(taskListId, taskId, completed) { - var task = Tasks.newTask(); + const task = Tasks.newTask(); if (completed) { - task.setStatus('completed'); + task.setStatus("completed"); } else { - task.setStatus('needsAction'); + task.setStatus("needsAction"); task.setCompleted(null); } Tasks.Tasks.patch(task, taskListId, taskId); @@ -85,6 +82,6 @@ function setCompleted(taskListId, taskId, completed) { * @param {String} title The title of the new task. */ function addTask(taskListId, title) { - var task = Tasks.newTask().setTitle(title); + const task = Tasks.newTask().setTitle(title); Tasks.Tasks.insert(task, taskListId); } diff --git a/templates/custom-functions/Code.gs b/templates/custom-functions/Code.gs index 97b1325ff..5151073dc 100644 --- a/templates/custom-functions/Code.gs +++ b/templates/custom-functions/Code.gs @@ -27,7 +27,7 @@ * @customfunction */ function SAY_HELLO(name) { - return 'Hello ' + name; + return `Hello ${name}`; } /** @@ -40,11 +40,12 @@ function SAY_HELLO(name) { * @customfunction */ function INCREMENT(input) { - if (input instanceof Array) { + if (Array.isArray(input)) { // Recurse to process an array. return input.map(INCREMENT); - } else if (!(typeof input === 'number')) { - throw new Error('Input contains a cell value that is not a number'); + } + if (!(typeof input === "number")) { + throw new Error("Input contains a cell value that is not a number"); } // Otherwise process as a single value. return input + 1; @@ -60,15 +61,19 @@ function INCREMENT(input) { * @customfunction */ function CORNER_SUM(input) { - if (!(input instanceof Array)) { + if (!Array.isArray(input)) { // Handle non-range inputs by putting them in an array. return CORNER_SUM([[input]]); // eslint-disable-line new-cap } // Range processing here. - var maxRowIndex = input.length - 1; - var maxColIndex = input[0].length - 1; - return input[0][0] + input[0][maxColIndex] + - input[maxRowIndex][0] + input[maxRowIndex][maxColIndex]; + const maxRowIndex = input.length - 1; + const maxColIndex = input[0].length - 1; + return ( + input[0][0] + + input[0][maxColIndex] + + input[maxRowIndex][0] + + input[maxRowIndex][maxColIndex] + ); } /** @@ -82,14 +87,14 @@ function CORNER_SUM(input) { * @customfunction */ function POWERS_AND_ROOTS(input) { - if (input instanceof Array) { - throw new Error('Invalid: Range input not permitted'); + if (Array.isArray(input)) { + throw new Error("Invalid: Range input not permitted"); } // Value processing and range generation here. - var headers = ['x', input + '^x', input + '^(1/x)']; - var result = [headers]; - for (var i = 1; i <= 10; i++) { - result.push([i, Math.pow(input, i), Math.pow(input, 1/i)]); + const headers = ["x", `${input}^x`, `${input}^(1/x)`]; + const result = [headers]; + for (let i = 1; i <= 10; i++) { + result.push([i, input ** i, input ** (1 / i)]); } return result; } @@ -104,12 +109,12 @@ function POWERS_AND_ROOTS(input) { */ function GET_DAY_OF_YEAR(date) { if (!(date instanceof Date)) { - throw new Error('Invalid: Date input required'); + throw new Error("Invalid: Date input required"); } // Date processing here. - var firstOfYear = new Date(date.getFullYear(), 0, 0); - var diff = date - firstOfYear; - var oneDay = 1000 * 60 * 60 * 24; + const firstOfYear = new Date(date.getFullYear(), 0, 0); + const diff = date - firstOfYear; + const oneDay = 1000 * 60 * 60 * 24; return Math.floor(diff / oneDay); } @@ -123,19 +128,22 @@ function GET_DAY_OF_YEAR(date) { */ function CONVERT_DURATION_TO_SECONDS(duration) { if (!(duration instanceof Date)) { - throw new Error('Invalid: Duration input required'); + throw new Error("Invalid: Duration input required"); } // Getting elapsed times from duration-formatted cells in Sheets requires // subtracting the reference date from the cell value (while correcting for // timezones). - var spreadsheetTimezone = - SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(); - var dateString = Utilities.formatDate(duration, spreadsheetTimezone, - 'EEE, d MMM yyyy HH:mm:ss'); - var date = new Date(dateString); - var epoch = new Date('Dec 30, 1899 00:00:00'); - var durationInMilliseconds = date.getTime() - epoch.getTime(); + const spreadsheetTimezone = + SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(); + const dateString = Utilities.formatDate( + duration, + spreadsheetTimezone, + "EEE, d MMM yyyy HH:mm:ss", + ); + const date = new Date(dateString); + const epoch = new Date("Dec 30, 1899 00:00:00"); + const durationInMilliseconds = date.getTime() - epoch.getTime(); // Duration processing here. return Math.round(durationInMilliseconds / 1000); diff --git a/templates/docs-addon/Code.gs b/templates/docs-addon/Code.gs index 1c4ad0c29..342d16c5e 100644 --- a/templates/docs-addon/Code.gs +++ b/templates/docs-addon/Code.gs @@ -18,8 +18,8 @@ * @OnlyCurrentDoc Limits the script to only accessing the current document. */ -var DIALOG_TITLE = 'Example Dialog'; -var SIDEBAR_TITLE = 'Example Sidebar'; +const DIALOG_TITLE = "Example Dialog"; +const SIDEBAR_TITLE = "Example Sidebar"; /** * Adds a custom menu with items to show the sidebar and dialog. @@ -28,10 +28,10 @@ var SIDEBAR_TITLE = 'Example Sidebar'; */ function onOpen(e) { DocumentApp.getUi() - .createAddonMenu() - .addItem('Show sidebar', 'showSidebar') - .addItem('Show dialog', 'showDialog') - .addToUi(); + .createAddonMenu() + .addItem("Show sidebar", "showSidebar") + .addItem("Show dialog", "showDialog") + .addToUi(); } /** @@ -49,9 +49,9 @@ function onInstall(e) { * project file. */ function showSidebar() { - var ui = HtmlService.createTemplateFromFile('Sidebar') - .evaluate() - .setTitle(SIDEBAR_TITLE); + const ui = HtmlService.createTemplateFromFile("Sidebar") + .evaluate() + .setTitle(SIDEBAR_TITLE); DocumentApp.getUi().showSidebar(ui); } @@ -60,10 +60,10 @@ function showSidebar() { * project file. */ function showDialog() { - var ui = HtmlService.createTemplateFromFile('Dialog') - .evaluate() - .setWidth(400) - .setHeight(150); + const ui = HtmlService.createTemplateFromFile("Dialog") + .evaluate() + .setWidth(400) + .setHeight(150); DocumentApp.getUi().showModalDialog(ui, DIALOG_TITLE); } diff --git a/templates/forms-addon/Code.gs b/templates/forms-addon/Code.gs index 295256f4b..93d96aac8 100644 --- a/templates/forms-addon/Code.gs +++ b/templates/forms-addon/Code.gs @@ -18,8 +18,8 @@ * @OnlyCurrentDoc Limits the script to only accessing the current form. */ -var DIALOG_TITLE = 'Example Dialog'; -var SIDEBAR_TITLE = 'Example Sidebar'; +const DIALOG_TITLE = "Example Dialog"; +const SIDEBAR_TITLE = "Example Sidebar"; /** * Adds a custom menu with items to show the sidebar and dialog. @@ -28,10 +28,10 @@ var SIDEBAR_TITLE = 'Example Sidebar'; */ function onOpen(e) { FormApp.getUi() - .createAddonMenu() - .addItem('Show sidebar', 'showSidebar') - .addItem('Show dialog', 'showDialog') - .addToUi(); + .createAddonMenu() + .addItem("Show sidebar", "showSidebar") + .addItem("Show dialog", "showDialog") + .addToUi(); } /** @@ -49,9 +49,9 @@ function onInstall(e) { * project file. */ function showSidebar() { - var ui = HtmlService.createTemplateFromFile('Sidebar') - .evaluate() - .setTitle(SIDEBAR_TITLE); + const ui = HtmlService.createTemplateFromFile("Sidebar") + .evaluate() + .setTitle(SIDEBAR_TITLE); FormApp.getUi().showSidebar(ui); } @@ -60,10 +60,10 @@ function showSidebar() { * project file. */ function showDialog() { - var ui = HtmlService.createTemplateFromFile('Dialog') - .evaluate() - .setWidth(350) - .setHeight(180); + const ui = HtmlService.createTemplateFromFile("Dialog") + .evaluate() + .setWidth(350) + .setHeight(180); FormApp.getUi().showModalDialog(ui, DIALOG_TITLE); } @@ -75,15 +75,15 @@ function showDialog() { */ function addFormItem(itemData) { // Use data collected from sidebar to manipulate the form. - var form = FormApp.getActiveForm(); + const form = FormApp.getActiveForm(); switch (itemData.type) { - case 'Date': + case "Date": form.addDateItem().setTitle(itemData.name); break; - case 'Scale': + case "Scale": form.addScaleItem().setTitle(itemData.name); break; - case 'Text': + case "Text": form.addTextItem().setTitle(itemData.name); break; } @@ -98,8 +98,8 @@ function addFormItem(itemData) { */ function getTriggerState() { // Retrieve and return the information requested by the dialog. - var properties = PropertiesService.getDocumentProperties(); - return properties.getProperty('triggerId') != null; + const properties = PropertiesService.getDocumentProperties(); + return properties.getProperty("triggerId") != null; } /** @@ -112,27 +112,27 @@ function adjustFormSubmitTrigger(enableTrigger) { // Use data collected from dialog to manipulate form. // Determine existing state of trigger on the server. - var form = FormApp.getActiveForm(); - var properties = PropertiesService.getDocumentProperties(); - var triggerId = properties.getProperty('triggerId'); + const form = FormApp.getActiveForm(); + const properties = PropertiesService.getDocumentProperties(); + const triggerId = properties.getProperty("triggerId"); if (!enableTrigger && triggerId != null) { // Delete the existing trigger. - var triggers = ScriptApp.getUserTriggers(form); - for (var i = 0; i < triggers.length; i++) { - if (triggers[i].getUniqueId() == triggerId) { + const triggers = ScriptApp.getUserTriggers(form); + for (let i = 0; i < triggers.length; i++) { + if (triggers[i].getUniqueId() === triggerId) { ScriptApp.deleteTrigger(triggers[i]); break; } } - properties.deleteProperty('triggerId'); + properties.deleteProperty("triggerId"); } else if (enableTrigger && triggerId == null) { // Create a new trigger. - var trigger = ScriptApp.newTrigger('respondToFormSubmit') - .forForm(form) - .onFormSubmit() - .create(); - properties.setProperty('triggerId', trigger.getUniqueId()); + const trigger = ScriptApp.newTrigger("respondToFormSubmit") + .forForm(form) + .onFormSubmit() + .create(); + properties.setProperty("triggerId", trigger.getUniqueId()); } } @@ -146,19 +146,19 @@ function adjustFormSubmitTrigger(enableTrigger) { */ function respondToFormSubmit(e) { if (MailApp.getRemainingDailyQuota() > 0) { - var form = FormApp.getActiveForm(); - var message = 'There have been ' + form.getResponses().length + - ' response(s) so far. Latest Response:\n'; - var itemResponses = e.response.getItemResponses(); - for (var i = 0; i < itemResponses.length; i++) { - var itemTitle = itemResponses[i].getItem().getTitle(); - var itemResponse = JSON.stringify(itemResponses[i].getResponse()); - message += itemTitle + ': ' + itemResponse + '\n'; + const form = FormApp.getActiveForm(); + let message = `There have been ${form.getResponses().length} response(s) so far. Latest Response:\n`; + const itemResponses = e.response.getItemResponses(); + for (let i = 0; i < itemResponses.length; i++) { + const itemTitle = itemResponses[i].getItem().getTitle(); + const itemResponse = JSON.stringify(itemResponses[i].getResponse()); + message += `${itemTitle}: ${itemResponse}\n`; } MailApp.sendEmail( - Session.getEffectiveUser().getEmail(), - 'Form response received for form ' + form.getTitle(), - message, - {name: 'Forms Add-on Template'}); + Session.getEffectiveUser().getEmail(), + `Form response received for form ${form.getTitle()}`, + message, + { name: "Forms Add-on Template" }, + ); } } diff --git a/templates/sheets-addon/Code.gs b/templates/sheets-addon/Code.gs index 2c862bf51..ded5eda52 100644 --- a/templates/sheets-addon/Code.gs +++ b/templates/sheets-addon/Code.gs @@ -18,8 +18,8 @@ * @OnlyCurrentDoc Limits the script to only accessing the current spreadsheet. */ -var DIALOG_TITLE = 'Example Dialog'; -var SIDEBAR_TITLE = 'Example Sidebar'; +const DIALOG_TITLE = "Example Dialog"; +const SIDEBAR_TITLE = "Example Sidebar"; /** * Adds a custom menu with items to show the sidebar and dialog. @@ -28,10 +28,10 @@ var SIDEBAR_TITLE = 'Example Sidebar'; */ function onOpen(e) { SpreadsheetApp.getUi() - .createAddonMenu() - .addItem('Show sidebar', 'showSidebar') - .addItem('Show dialog', 'showDialog') - .addToUi(); + .createAddonMenu() + .addItem("Show sidebar", "showSidebar") + .addItem("Show dialog", "showDialog") + .addToUi(); } /** @@ -49,9 +49,9 @@ function onInstall(e) { * project file. */ function showSidebar() { - var ui = HtmlService.createTemplateFromFile('Sidebar') - .evaluate() - .setTitle(SIDEBAR_TITLE); + const ui = HtmlService.createTemplateFromFile("Sidebar") + .evaluate() + .setTitle(SIDEBAR_TITLE); SpreadsheetApp.getUi().showSidebar(ui); } @@ -60,10 +60,10 @@ function showSidebar() { * project file. */ function showDialog() { - var ui = HtmlService.createTemplateFromFile('Dialog') - .evaluate() - .setWidth(400) - .setHeight(190); + const ui = HtmlService.createTemplateFromFile("Dialog") + .evaluate() + .setWidth(400) + .setHeight(190); SpreadsheetApp.getUi().showModalDialog(ui, DIALOG_TITLE); } @@ -74,7 +74,7 @@ function showDialog() { */ function getActiveValue() { // Retrieve and return the information requested by the sidebar. - var cell = SpreadsheetApp.getActiveSheet().getActiveCell(); + const cell = SpreadsheetApp.getActiveSheet().getActiveCell(); return cell.getValue(); } @@ -85,7 +85,7 @@ function getActiveValue() { */ function setActiveValue(value) { // Use data collected from sidebar to manipulate the sheet. - var cell = SpreadsheetApp.getActiveSheet().getActiveCell(); + const cell = SpreadsheetApp.getActiveSheet().getActiveCell(); cell.setValue(value); } @@ -97,13 +97,13 @@ function setActiveValue(value) { */ function modifySheets(action) { // Use data collected from dialog to manipulate the spreadsheet. - var ss = SpreadsheetApp.getActiveSpreadsheet(); - var currentSheet = ss.getActiveSheet(); - if (action == 'create') { + const ss = SpreadsheetApp.getActiveSpreadsheet(); + const currentSheet = ss.getActiveSheet(); + if (action === "create") { ss.insertSheet(); - } else if (action == 'copy') { + } else if (action === "copy") { currentSheet.copyTo(ss); - } else if (action == 'clear') { + } else if (action === "clear") { currentSheet.clear(); } } diff --git a/templates/sheets-import/APICode.gs b/templates/sheets-import/APICode.gs index 5bbdb7d9a..89df3401c 100644 --- a/templates/sheets-import/APICode.gs +++ b/templates/sheets-import/APICode.gs @@ -20,15 +20,15 @@ * @return {Array} list of potential columns. */ function getColumnOptions() { - var columns = []; + const columns = []; // TODO: Replace this section, adding a column entry for each data of // interest. id should be an identifier that can be used to locate // the data in the data request response, and label should be the name // to associate with that data in the UI. - columns.push({id: 'DATA_ITEM1_ID', label: 'Data Item 1 label'}); - columns.push({id: 'DATA_ITEM2_ID', label: 'Data Item 2 label'}); - columns.push({id: 'DATA_ITEM3_ID', label: 'Data Item 3 label'}); + columns.push({ id: "DATA_ITEM1_ID", label: "Data Item 1 label" }); + columns.push({ id: "DATA_ITEM2_ID", label: "Data Item 2 label" }); + columns.push({ id: "DATA_ITEM3_ID", label: "Data Item 3 label" }); return columns; } @@ -48,7 +48,7 @@ function getColumnOptions() { * @return {object[]|null} Pages of data. */ function getDataPage(columns, pageNumber, pageSize, opt_settings) { - var data = null; + const data = null; /** * TODO: This function needs to be implemented based on the particular * details of the data source you are extracting data from. For example, @@ -80,5 +80,5 @@ function getDataPage(columns, pageNumber, pageSize, opt_settings) { * */ - return data; + return data; } diff --git a/templates/sheets-import/Auth.gs b/templates/sheets-import/Auth.gs index f303e4bb5..9cc3cb995 100644 --- a/templates/sheets-import/Auth.gs +++ b/templates/sheets-import/Auth.gs @@ -24,13 +24,13 @@ */ function getService() { /* TODO: Fill in the following required parameters for your data source. */ - var service = OAuth2.createService('ENTER_SERVICE_NAME_HERE') - .setAuthorizationBaseUrl('ENTER_BASE_URL_HERE') - .setTokenUrl('ENTER_TOKEN_URL_HERE') - .setClientId('ENTER_CLIENT_ID_HERE') - .setClientSecret('ENTER_CLIENT_SECRET_HERE') - .setCallbackFunction('authCallback') - .setPropertyStore(PropertiesService.getUserProperties()); + const service = OAuth2.createService("ENTER_SERVICE_NAME_HERE") + .setAuthorizationBaseUrl("ENTER_BASE_URL_HERE") + .setTokenUrl("ENTER_TOKEN_URL_HERE") + .setClientId("ENTER_CLIENT_ID_HERE") + .setClientSecret("ENTER_CLIENT_SECRET_HERE") + .setCallbackFunction("authCallback") + .setPropertyStore(PropertiesService.getUserProperties()); /* TODO: Do any app-specific OAuth property setting here. * For details, see: @@ -50,23 +50,22 @@ function getService() { * @return {HTML} A auth callback HTML page. */ function authCallback(request) { - var template = HtmlService.createTemplateFromFile('AuthCallbackView'); + const template = HtmlService.createTemplateFromFile("AuthCallbackView"); template.user = Session.getEffectiveUser().getEmail(); template.isAuthorized = false; template.error = null; - var title; + let title; try { - var service = getService(); - var authorized = service.handleCallback(request); + const service = getService(); + const authorized = service.handleCallback(request); template.isAuthorized = authorized; - title = authorized ? 'Access Granted' : 'Access Denied'; + title = authorized ? "Access Granted" : "Access Denied"; } catch (e) { template.error = e; - title = 'Access Error'; + title = "Access Error"; } template.title = title; - return template.evaluate() - .setTitle(title); + return template.evaluate().setTitle(title); } /** diff --git a/templates/sheets-import/Configurations.gs b/templates/sheets-import/Configurations.gs index 3f40fb100..a672f4fa7 100644 --- a/templates/sheets-import/Configurations.gs +++ b/templates/sheets-import/Configurations.gs @@ -14,15 +14,15 @@ * limitations under the License. */ -var REPORT_SET_KEY = 'Import.ReportSet'; -var SCHEDULE_TRIGGER_ID = 'Import.scheduled.triggerId'; +const REPORT_SET_KEY = "Import.ReportSet"; +const SCHEDULE_TRIGGER_ID = "Import.scheduled.triggerId"; /** * Update type enum used when adding or deleting a report. */ -var UPDATE_TYPE = { +const UPDATE_TYPE = { ADD: 1, - REMOVE: 2 + REMOVE: 2, }; /** @@ -33,14 +33,14 @@ var UPDATE_TYPE = { * or null if no such report exists. */ function getReportConfig(reportId) { - var config = getObjectFromProperties(reportId); + const config = getObjectFromProperties(reportId); if (!config) { return null; } // Sheet name may have been changed manually, so // get the current one. - var ss = SpreadsheetApp.getActiveSpreadsheet(); - var sheet = getSheetById(ss, parseInt(config.sheetId)); + const ss = SpreadsheetApp.getActiveSpreadsheet(); + const sheet = getSheetById(ss, Number.parseInt(config.sheetId)); config.sheetName = !sheet ? null : sheet.getName(); return config; } @@ -52,8 +52,8 @@ function getReportConfig(reportId) { * @return {object} The saved configuration. */ function saveReportConfig(config) { - var previous = getReportConfig(config.reportId); - if (config.reportId === 'new-report') { + const previous = getReportConfig(config.reportId); + if (config.reportId === "new-report") { config.reportId = newReportId(); config.lastRun = null; config.owner = Session.getEffectiveUser().getEmail(); @@ -63,7 +63,10 @@ function saveReportConfig(config) { if (previous == null) { return config; } - return _.extend(previous, config); + return { + ...previous, + ...config, + }; } /** @@ -85,8 +88,10 @@ function canEditReport(config) { if (!config) { return false; } - return config.scheduled == false || - Session.getEffectiveUser().getEmail() == config.owner; + return ( + config.scheduled === false || + Session.getEffectiveUser().getEmail() === config.owner + ); } /** @@ -97,12 +102,15 @@ function canEditReport(config) { * would be exceeded. */ function isOverScheduleLimit(config) { - var previous = getReportConfig(config.reportId); - var currentUser = Session.getEffectiveUser().getEmail(); - var isScheduled = config == null ? false : config.scheduled; - var wasScheduled = previous == null ? false : previous.scheduled; - return (isScheduled && wasScheduled != true && - getScheduledReports(currentUser).length >= MAX_SCHEDULED_REPORTS); + const previous = getReportConfig(config.reportId); + const currentUser = Session.getEffectiveUser().getEmail(); + const isScheduled = config == null ? false : config.scheduled; + const wasScheduled = previous == null ? false : previous.scheduled; + return ( + isScheduled && + wasScheduled !== true && + getScheduledReports(currentUser).length >= MAX_SCHEDULED_REPORTS + ); } /** @@ -111,7 +119,7 @@ function isOverScheduleLimit(config) { * @return {Object} */ function getAllReports() { - var properties = PropertiesService.getDocumentProperties(); + const properties = PropertiesService.getDocumentProperties(); return JSON.parse(properties.getProperty(REPORT_SET_KEY)); } @@ -124,14 +132,13 @@ function getAllReports() { * reports. */ function getScheduledReports(opt_user) { - var scheduledReports = []; - _.keys(getAllReports()).forEach(function(reportId) { - var config = getReportConfig(reportId); - if (config && config.scheduled && - (!opt_user || opt_user == config.owner)) { + const scheduledReports = []; + for (const reportId of Object.keys(getAllReports())) { + const config = getReportConfig(reportId); + if (config?.scheduled && (!opt_user || opt_user === config.owner)) { scheduledReports.push(config); } - }); + } return scheduledReports; } @@ -144,16 +151,16 @@ function getScheduledReports(opt_user) { * @param {String} reportName report name (only needed for ADD). */ function updateReportSet(updateType, reportId, reportName) { - var properties = PropertiesService.getDocumentProperties(); - var lock = LockService.getDocumentLock(); + const properties = PropertiesService.getDocumentProperties(); + const lock = LockService.getDocumentLock(); lock.waitLock(2000); - var reportSet = JSON.parse(properties.getProperty(REPORT_SET_KEY)); + let reportSet = JSON.parse(properties.getProperty(REPORT_SET_KEY)); if (reportSet == null) { reportSet = {}; } - if (updateType == UPDATE_TYPE.ADD) { + if (updateType === UPDATE_TYPE.ADD) { reportSet[reportId] = reportName; - } else if (updateType == UPDATE_TYPE.REMOVE) { + } else if (updateType === UPDATE_TYPE.REMOVE) { delete reportSet[reportId]; } properties.setProperty(REPORT_SET_KEY, JSON.stringify(reportSet)); @@ -171,13 +178,16 @@ function updateReportSet(updateType, reportId, reportName) { * @return {Object} the updated report configuration. */ function updateOnImport(config, sheet, lastRun) { - var update = { + const update = { sheetId: sheet.getSheetId().toString(), - lastRun: lastRun + lastRun: lastRun, }; saveObjectToProperties(config.reportId, update); update.sheetName = sheet.getName(); - return _.extend(config, update); + return { + ...config, + ...update, + }; } /** @@ -187,9 +197,7 @@ function updateOnImport(config, sheet, lastRun) { * @return {Array} column ID strings. */ function getColumnIds(config) { - return _.map(config.columns, function(col) { - return col.column; - }); + return config.columns.map((col) => col.column); } /** @@ -197,7 +205,7 @@ function getColumnIds(config) { * @return {string|null} the trigger ID or null if the trigger is not set. */ function getTriggerId() { - var properties = PropertiesService.getUserProperties(); + const properties = PropertiesService.getUserProperties(); return properties.getProperty(SCHEDULE_TRIGGER_ID); } @@ -206,7 +214,7 @@ function getTriggerId() { * @param {Trigger} trigger the trigger whose ID should be saved. */ function saveTriggerId(trigger) { - var properties = PropertiesService.getUserProperties(); + const properties = PropertiesService.getUserProperties(); properties.setProperty(SCHEDULE_TRIGGER_ID, trigger.getUniqueId()); } @@ -214,6 +222,6 @@ function saveTriggerId(trigger) { * Remove the saved trigger ID. */ function removeTriggerId() { - var properties = PropertiesService.getUserProperties(); + const properties = PropertiesService.getUserProperties(); properties.deleteProperty(SCHEDULE_TRIGGER_ID); } diff --git a/templates/sheets-import/Server.gs b/templates/sheets-import/Server.gs index aeca91075..7da382cbd 100644 --- a/templates/sheets-import/Server.gs +++ b/templates/sheets-import/Server.gs @@ -18,26 +18,26 @@ * @OnlyCurrentDoc Limits the script to only accessing the current spreadsheet. */ -var _ = Underscore.load(); +const _ = Underscore.load(); /** * TODO: Replace the following with the name of the service you are importing * from and the name of the add-on you are building, respectively. */ -var DATA_ALIAS = 'MyDataSource'; -var ADDON_NAME = 'YOUR_ADDON_NAME_HERE'; -var SIDEBAR_TITLE = 'Import Control Center'; -var MAX_SCHEDULED_REPORTS = 24; -var IMPORT_PAGE_SIZE = 30; +const DATA_ALIAS = "MyDataSource"; +const ADDON_NAME = "YOUR_ADDON_NAME_HERE"; +const SIDEBAR_TITLE = "Import Control Center"; +const MAX_SCHEDULED_REPORTS = 24; +const IMPORT_PAGE_SIZE = 30; /** * Error code enum; this gets passed to the sidebar for use there as well. */ -var ERROR_CODES = { +const ERROR_CODES = { AUTO_UPDATE_LIMIT: 1, ILLEGAL_EDIT: 2, ILLEGAL_DELETE: 3, - IMPORT_FAILED: 4 + IMPORT_FAILED: 4, }; /** @@ -46,9 +46,9 @@ var ERROR_CODES = { */ function onOpen(e) { SpreadsheetApp.getUi() - .createAddonMenu() - .addItem('Import control center', 'showSidebar') - .addToUi(); + .createAddonMenu() + .addItem("Import control center", "showSidebar") + .addToUi(); } /** @@ -65,8 +65,8 @@ function onInstall(e) { * project file. */ function showSidebar() { - var service = getService(); - var template = HtmlService.createTemplateFromFile('Sidebar'); + const service = getService(); + const template = HtmlService.createTemplateFromFile("Sidebar"); template.user = Session.getEffectiveUser().getEmail(); template.dataSource = DATA_ALIAS; template.isAuthorized = service.hasAccess(); @@ -74,8 +74,7 @@ function showSidebar() { if (!template.isAuthorized) { template.authorizationUrl = service.getAuthorizationUrl(); } - var page = template.evaluate() - .setTitle(SIDEBAR_TITLE); + const page = template.evaluate().setTitle(SIDEBAR_TITLE); SpreadsheetApp.getUi().showSidebar(page); } @@ -86,21 +85,21 @@ function showSidebar() { * @return {Object} a collection of saved report data and column options. */ function getInitialDataForSidebar() { - var reportSet = getAllReports(); - var reportList = []; - _.each(reportSet, function(val, key) { - reportList.push({'name': val, 'reportId': key}); + const reportSet = getAllReports(); + const reportList = []; + _.each(reportSet, (val, key) => { + reportList.push({ name: val, reportId: key }); }); - reportList.sort(function(a, b) { + reportList.sort((a, b) => { if (a.name > b.name) { - return 1; -} + return 1; + } if (a.name < b.name) { - return -1; -} + return -1; + } return 0; }); - return {reports: reportList, columns: getColumnOptions()}; + return { reports: reportList, columns: getColumnOptions() }; } /** @@ -110,7 +109,7 @@ function getInitialDataForSidebar() { * @return {object} The report config. */ function switchToReport(reportId) { - var config = getReportConfig(reportId); + const config = getReportConfig(reportId); activateById(config.sheetId); return config; } @@ -122,27 +121,29 @@ function switchToReport(reportId) { * @return {object} the (possibly updated) report configuration. */ function runImport(reportId) { - var ss = SpreadsheetApp.getActiveSpreadsheet(); - var config = getReportConfig(reportId); + const ss = SpreadsheetApp.getActiveSpreadsheet(); + let config = getReportConfig(reportId); // Acquire the sheet to place the import results in, // then clear and format it. // Update the saved config with sheet/time information. - var sheet = activateReportSheet(config); - var columnIds = getColumnIds(config); - var lastRun = new Date().toString(); + const sheet = activateReportSheet(config); + const columnIds = getColumnIds(config); + const lastRun = new Date().toString(); config = updateOnImport(config, sheet, lastRun); // Call for pages of API information to place in the sheet, one // page at a time. - var pageNumber = 0; - var firstRow = 2; + let pageNumber = 0; + let firstRow = 2; try { - var page; + let page; do { page = getDataPage(columnIds, pageNumber, IMPORT_PAGE_SIZE, config); if (page) { - sheet.getRange(firstRow, 1, page.length, page[0].length).setValues(page); + sheet + .getRange(firstRow, 1, page.length, page[0].length) + .setValues(page); firstRow += page.length; pageNumber++; SpreadsheetApp.flush(); @@ -153,10 +154,10 @@ function runImport(reportId) { throw ERROR_CODES.IMPORT_FAILED; } - for (var i = 1; i <= sheet.getLastColumn(); i++) { + for (let i = 1; i <= sheet.getLastColumn(); i++) { sheet.autoResizeColumn(i); } - ss.toast('Report ' + config.name + ' updated.'); + ss.toast(`Report ${config.name} updated.`); return config; } @@ -166,7 +167,7 @@ function runImport(reportId) { * @return {Object} the updated report configuration. */ function saveReport(config) { - var existingConfig = getReportConfig(config.reportId); + const existingConfig = getReportConfig(config.reportId); if (existingConfig != null) { activateById(existingConfig.sheetId); // Check: users are not allowed to save edits to reports @@ -181,7 +182,7 @@ function saveReport(config) { throw ERROR_CODES.AUTO_UPDATE_LIMIT; } - var result = saveReportConfig(config); + const result = saveReportConfig(config); adjustScheduleTrigger(); return result; } @@ -210,24 +211,23 @@ function removeReport(reportId) { * @return {Sheet} */ function activateReportSheet(config) { - var ss = SpreadsheetApp.getActiveSpreadsheet(); - var sheet = getSheetById(ss, parseInt(config.sheetId)); + const ss = SpreadsheetApp.getActiveSpreadsheet(); + let sheet = getSheetById(ss, Number.parseInt(config.sheetId)); if (sheet == null) { sheet = ss.insertSheet(); sheet.setName(getUniqueSheetName(ss, config.name)); } sheet.activate(); - var headers = _.map(config.columns, function(col) { - return col.label; - }); + const headers = _.map(config.columns, (col) => col.label); sheet.clear(); sheet.clearNotes(); sheet.setFrozenRows(1); - sheet.getRange('1:1') - .setFontWeight('bold') - .setBackground('#000000') - .setFontColor('#ffffff'); + sheet + .getRange("1:1") + .setFontWeight("bold") + .setBackground("#000000") + .setFontColor("#ffffff"); sheet.getRange(1, 1, 1, headers.length).setValues([headers]); return sheet; } @@ -239,13 +239,14 @@ function activateReportSheet(config) { * ensures that every scheduled report will be updated once a day. */ function respondToHourlyTrigger() { - var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); + const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); // Check if the actions of the trigger require authorizations that have not // been supplied yet -- if so, warn the active user via email (if possible). // This check is required when using triggers with add-ons to maintain // functional triggers. - if (authInfo.getAuthorizationStatus() == - ScriptApp.AuthorizationStatus.REQUIRED) { + if ( + authInfo.getAuthorizationStatus() === ScriptApp.AuthorizationStatus.REQUIRED + ) { // Re-authorization is required. In this case, the user needs to be alerted // that they need to reauthorize; the normal trigger action is not // conducted, since it authorization needs to be provided first. Send at @@ -253,10 +254,12 @@ function respondToHourlyTrigger() { // of the add-on. sendReauthorizationRequest(); } else { - var potentials = getScheduledReports(Session.getEffectiveUser().getEmail()); - for (var i = 0; i < potentials.length; i++) { - var lastRun = potentials[i].lastRun; - if (!lastRun || isOlderThanADay(lastRun) ) { + const potentials = getScheduledReports( + Session.getEffectiveUser().getEmail(), + ); + for (let i = 0; i < potentials.length; i++) { + const lastRun = potentials[i].lastRun; + if (!lastRun || isOlderThanADay(lastRun)) { runImport(potentials[i].reportId); return; } @@ -271,24 +274,26 @@ function respondToHourlyTrigger() { * a day to prevent spamming the users of the add-on. */ function sendReauthorizationRequest() { - var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); - var properties = PropertiesService.getUserProperties(); - var LAST_AUTH_EMAIL_KEY = 'Import.reauth.lastAuthEmailDate'; - var lastAuthEmailDate = properties.getProperty(LAST_AUTH_EMAIL_KEY); - var today = new Date().toDateString(); - if (lastAuthEmailDate != today) { + const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); + const properties = PropertiesService.getUserProperties(); + const LAST_AUTH_EMAIL_KEY = "Import.reauth.lastAuthEmailDate"; + const lastAuthEmailDate = properties.getProperty(LAST_AUTH_EMAIL_KEY); + const today = new Date().toDateString(); + if (lastAuthEmailDate !== today) { if (MailApp.getRemainingDailyQuota() > 0) { - var template = - HtmlService.createTemplateFromFile('AuthorizationEmail'); + const template = HtmlService.createTemplateFromFile("AuthorizationEmail"); template.url = authInfo.getAuthorizationUrl(); template.addonName = ADDON_NAME; - var message = template.evaluate(); - MailApp.sendEmail(Session.getEffectiveUser().getEmail(), - 'Add-on Authorization Required', - message.getContent(), { + const message = template.evaluate(); + MailApp.sendEmail( + Session.getEffectiveUser().getEmail(), + "Add-on Authorization Required", + message.getContent(), + { name: ADDON_NAME, - htmlBody: message.getContent() - }); + htmlBody: message.getContent(), + }, + ); } properties.setProperty(LAST_AUTH_EMAIL_KEY, today); } @@ -299,22 +304,23 @@ function sendReauthorizationRequest() { * by the current user are present; turn it off otherwise. */ function adjustScheduleTrigger() { - var existingTriggerId = getTriggerId(); - var user = Session.getEffectiveUser().getEmail(); - var triggerNeeded = getScheduledReports(user).length > 0; + const existingTriggerId = getTriggerId(); + const user = Session.getEffectiveUser().getEmail(); + const triggerNeeded = getScheduledReports(user).length > 0; // Create a new trigger if required; delete existing trigger // if it is not needed. if (triggerNeeded && existingTriggerId == null) { - var trigger = ScriptApp.newTrigger('respondToHourlyTrigger') - .timeBased() - .everyHours(1) - .create(); + const trigger = ScriptApp.newTrigger("respondToHourlyTrigger") + .timeBased() + .everyHours(1) + .create(); saveTriggerId(trigger); } else if (!triggerNeeded && existingTriggerId != null) { - var existingTrigger = getUserTriggerById( - SpreadsheetApp.getActiveSpreadsheet(), - existingTriggerId); + const existingTrigger = getUserTriggerById( + SpreadsheetApp.getActiveSpreadsheet(), + existingTriggerId, + ); if (existingTrigger != null) { ScriptApp.deleteTrigger(existingTrigger); } diff --git a/templates/sheets-import/Utilities.gs b/templates/sheets-import/Utilities.gs index 080beb63f..e014cb668 100644 --- a/templates/sheets-import/Utilities.gs +++ b/templates/sheets-import/Utilities.gs @@ -31,9 +31,9 @@ function include(filename) { * @return {Boolean} */ function isOlderThanADay(dateStr) { - var now = (new Date()).getTime(); - var then = Date.parse(dateStr); - return (then + 24 * 60 * 60 * 1000) < now; + const now = new Date().getTime(); + const then = Date.parse(dateStr); + return then + 24 * 60 * 60 * 1000 < now; } /** @@ -45,10 +45,10 @@ function isOlderThanADay(dateStr) { * user properties. */ function saveObjectToProperties(prefix, obj) { - var properties = PropertiesService.getDocumentProperties(); - _.each(obj, function(val, key) { - var propKey = prefix + '.' + key; - properties.setProperty(propKey, JSON.stringify(val)); + const properties = PropertiesService.getDocumentProperties(); + _.each(obj, (val, key) => { + const propKey = `${prefix}.${key}`; + properties.setProperty(propKey, JSON.stringify(val)); }); } @@ -62,14 +62,14 @@ function saveObjectToProperties(prefix, obj) { * properties service. Will return null if the prefix is unrecognized. */ function getObjectFromProperties(prefix) { - var properties = PropertiesService.getDocumentProperties(); - var obj = {}; - _.each(properties.getProperties(), function(val, key) { + const properties = PropertiesService.getDocumentProperties(); + const obj = {}; + _.each(properties.getProperties(), (val, key) => { if (key.indexOf(prefix) > -1) { obj[key.substr(prefix.length + 1)] = JSON.parse(val); } }); - if (_.keys(obj).length == 0) { + if (_.keys(obj).length === 0) { return null; } return obj; @@ -81,8 +81,8 @@ function getObjectFromProperties(prefix) { * @param {String} prefix label of properties to remove. */ function deleteObjectFromProperties(prefix) { - var properties = PropertiesService.getDocumentProperties(); - _.each(properties.getProperties(), function(val, key) { + const properties = PropertiesService.getDocumentProperties(); + _.each(properties.getProperties(), (val, key) => { if (key.indexOf(prefix) > -1) { properties.deleteProperty(key); } @@ -108,8 +108,8 @@ function getSheetById(ss, sheetId) { if (sheetId === null) { return null; } - var sheets = ss.getSheets(); - for (var i = 0; i < sheets.length; i++) { + const sheets = ss.getSheets(); + for (let i = 0; i < sheets.length; i++) { if (sheets[i].getSheetId() === sheetId) { return sheets[i]; } @@ -129,10 +129,10 @@ function getSheetById(ss, sheetId) { * given base title. */ function getUniqueSheetName(spreadsheet, baseName) { - var sheetName = baseName; - var i = 2; + let sheetName = baseName; + let i = 2; while (spreadsheet.getSheetByName(sheetName) != null) { - sheetName = baseName + ' ' + i++; + sheetName = `${baseName} ${i++}`; } return sheetName; } @@ -146,9 +146,9 @@ function getUniqueSheetName(spreadsheet, baseName) { * @return {Trigger} corresponding user trigger, or null if not found. */ function getUserTriggerById(spreadsheet, triggerId) { - var triggers = ScriptApp.getUserTriggers(spreadsheet); - for (var i = 0; i < triggers.length; i++) { - if (triggers[i].getUniqueId() == triggerId) { + const triggers = ScriptApp.getUserTriggers(spreadsheet); + for (let i = 0; i < triggers.length; i++) { + if (triggers[i].getUniqueId() === triggerId) { return triggers[i]; } } @@ -161,8 +161,8 @@ function getUserTriggerById(spreadsheet, triggerId) { * @param {String} sheetId the sheet ID. */ function activateById(sheetId) { - var ss = SpreadsheetApp.getActiveSpreadsheet(); - var sheet = getSheetById(ss, parseInt(sheetId)); + const ss = SpreadsheetApp.getActiveSpreadsheet(); + const sheet = getSheetById(ss, Number.parseInt(sheetId)); if (sheet != null) { sheet.activate(); } diff --git a/templates/standalone/helloWorld.gs b/templates/standalone/helloWorld.gs index a9794babf..4faf15d6e 100644 --- a/templates/standalone/helloWorld.gs +++ b/templates/standalone/helloWorld.gs @@ -20,10 +20,12 @@ function createAndSendDocument() { try { // Create a new Google Doc named 'Hello, world!' - const doc = DocumentApp.create('Hello, world!'); + const doc = DocumentApp.create("Hello, world!"); // Access the body of the document, then add a paragraph. - doc.getBody().appendParagraph('This document was created by Google Apps Script.'); + doc + .getBody() + .appendParagraph("This document was created by Google Apps Script."); // Get the URL of the document. const url = doc.getUrl(); @@ -35,13 +37,13 @@ function createAndSendDocument() { const subject = doc.getName(); // Append a new string to the "url" variable to use as an email body. - const body = 'Link to your doc: ' + url; + const body = `Link to your doc: ${url}`; // Send yourself an email with a link to the document. GmailApp.sendEmail(email, subject, body); } catch (err) { // TODO (developer) - Handle exception - console.log('Failed with error %s', err.message); + console.log("Failed with error %s", err.message); } } // [END apps_script_hello_world] diff --git a/templates/web-app/Code.gs b/templates/web-app/Code.gs index 57bf21b16..03f29a2c8 100644 --- a/templates/web-app/Code.gs +++ b/templates/web-app/Code.gs @@ -25,18 +25,17 @@ * @return {HTML} The web app's HTML. */ function doGet(e) { - var template = HtmlService.createTemplateFromFile('Index'); + const template = HtmlService.createTemplateFromFile("Index"); // Retrieve and process any URL parameters, as necessary. if (e.parameter.folderId) { template.folderId = e.parameter.folderId; } else { - template.folderId = 'root'; + template.folderId = "root"; } // Build and return HTML in IFRAME sandbox mode. - return template.evaluate() - .setTitle('Web App Window Title'); + return template.evaluate().setTitle("Web App Window Title"); } /** @@ -50,24 +49,24 @@ function doGet(e) { * the root folder name. */ function getFolderContents(folderId) { - var topFolder; - var contents = { - children: [] + let topFolder; + const contents = { + children: [], }; - if (folderId == 'root') { + if (folderId === "root") { topFolder = DriveApp.getRootFolder(); } else { // May throw exception if the folderId is invalid or app // doesn't have permission to access. topFolder = DriveApp.getFolderById(folderId); } - contents.rootName = topFolder.getName() + '/'; + contents.rootName = `${topFolder.getName()}/`; - var files = topFolder.getFiles(); - var numFiles = 0; + const files = topFolder.getFiles(); + let numFiles = 0; while (files.hasNext() && numFiles < 20) { - var file = files.next(); + const file = files.next(); contents.children.push(file.getName()); numFiles++; } diff --git a/triggers/form/Code.gs b/triggers/form/Code.gs index d1c15846c..d3cc9a958 100644 --- a/triggers/form/Code.gs +++ b/triggers/form/Code.gs @@ -19,36 +19,39 @@ * @param {event} e The Form submit event. */ function respondToFormSubmit(e) { - const addonTitle = 'My Add-on Title'; + const addonTitle = "My Add-on Title"; const props = PropertiesService.getDocumentProperties(); const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL); // Check if the actions of the trigger requires authorization that has not // been granted yet; if so, warn the user via email. This check is required // when using triggers with add-ons to maintain functional triggers. - if (authInfo.getAuthorizationStatus() === - ScriptApp.AuthorizationStatus.REQUIRED) { + if ( + authInfo.getAuthorizationStatus() === ScriptApp.AuthorizationStatus.REQUIRED + ) { // Re-authorization is required. In this case, the user needs to be alerted // that they need to re-authorize; the normal trigger action is not // conducted, since it requires authorization first. Send at most one // "Authorization Required" email per day to avoid spamming users. - const lastAuthEmailDate = props.getProperty('lastAuthEmailDate'); + const lastAuthEmailDate = props.getProperty("lastAuthEmailDate"); const today = new Date().toDateString(); if (lastAuthEmailDate !== today) { if (MailApp.getRemainingDailyQuota() > 0) { - const html = HtmlService.createTemplateFromFile('AuthorizationEmail'); + const html = HtmlService.createTemplateFromFile("AuthorizationEmail"); html.url = authInfo.getAuthorizationUrl(); html.addonTitle = addonTitle; const message = html.evaluate(); - MailApp.sendEmail(Session.getEffectiveUser().getEmail(), - 'Authorization Required', - message.getContent(), { - name: addonTitle, - htmlBody: message.getContent() - } + MailApp.sendEmail( + Session.getEffectiveUser().getEmail(), + "Authorization Required", + message.getContent(), + { + name: addonTitle, + htmlBody: message.getContent(), + }, ); } - props.setProperty('lastAuthEmailDate', today); + props.setProperty("lastAuthEmailDate", today); } } else { // Authorization has been granted, so continue to respond to the trigger. diff --git a/triggers/test_triggers.gs b/triggers/test_triggers.gs index d567c8cf2..a2bbbc4e5 100644 --- a/triggers/test_triggers.gs +++ b/triggers/test_triggers.gs @@ -18,7 +18,7 @@ * Tests createTimeDrivenTrigger function of trigger.gs */ function itShouldCreateTimeDrivenTriggers() { - console.log('> itShouldCreateTimeDrivenTriggers'); + console.log("> itShouldCreateTimeDrivenTriggers"); createTimeDrivenTriggers(); } @@ -26,7 +26,7 @@ function itShouldCreateTimeDrivenTriggers() { * Tests createSpreadsheetOpenTrigger function of triggers.gs */ function itShouldCreateSpreadsheetOpenTrigger() { - console.log('> itShouldCreateSpreadsheetOpenTrigger'); + console.log("> itShouldCreateSpreadsheetOpenTrigger"); createSpreadsheetOpenTrigger(); } @@ -34,7 +34,7 @@ function itShouldCreateSpreadsheetOpenTrigger() { * Tests deleteTrigger function of triggers.gs */ function itShouldDeleteTrigger() { - console.log('> itShouldDeleteTrigger'); + console.log("> itShouldDeleteTrigger"); deleteTrigger(); } diff --git a/triggers/triggers.gs b/triggers/triggers.gs index 34db5e9cf..cdb25f73f 100644 --- a/triggers/triggers.gs +++ b/triggers/triggers.gs @@ -23,9 +23,9 @@ function onOpen(e) { // Add a custom menu to the spreadsheet. SpreadsheetApp.getUi() // Or DocumentApp, SlidesApp, or FormApp. - .createMenu('Custom Menu') - .addItem('First item', 'menuItem1') - .addToUi(); + .createMenu("Custom Menu") + .addItem("First item", "menuItem1") + .addToUi(); } // [END apps_script_triggers_onopen] // [START apps_script_triggers_onedit] @@ -37,7 +37,7 @@ function onOpen(e) { function onEdit(e) { // Set a comment on the edited cell to indicate when it was changed. const range = e.range; - range.setNote('Last modified: ' + new Date()); + range.setNote(`Last modified: ${new Date()}`); } // [END apps_script_triggers_onedit] // [START apps_script_triggers_onselectionchange] @@ -49,10 +49,12 @@ function onEdit(e) { function onSelectionChange(e) { // Set background to red if a single empty cell is selected. const range = e.range; - if (range.getNumRows() === 1 && + if ( + range.getNumRows() === 1 && range.getNumColumns() === 1 && - range.getCell(1, 1).getValue() === '') { - range.setBackground('red'); + range.getCell(1, 1).getValue() === "" + ) { + range.setBackground("red"); } } // [END apps_script_triggers_onselectionchange] @@ -73,16 +75,13 @@ function onInstall(e) { */ function createTimeDrivenTriggers() { // Trigger every 6 hours. - ScriptApp.newTrigger('myFunction') - .timeBased() - .everyHours(6) - .create(); + ScriptApp.newTrigger("myFunction").timeBased().everyHours(6).create(); // Trigger every Monday at 09:00. - ScriptApp.newTrigger('myFunction') - .timeBased() - .onWeekDay(ScriptApp.WeekDay.MONDAY) - .atHour(9) - .create(); + ScriptApp.newTrigger("myFunction") + .timeBased() + .onWeekDay(ScriptApp.WeekDay.MONDAY) + .atHour(9) + .create(); } // [END apps_script_triggers_time] // [START apps_script_triggers_open] @@ -92,10 +91,7 @@ function createTimeDrivenTriggers() { */ function createSpreadsheetOpenTrigger() { const ss = SpreadsheetApp.getActive(); - ScriptApp.newTrigger('myFunction') - .forSpreadsheet(ss) - .onOpen() - .create(); + ScriptApp.newTrigger("myFunction").forSpreadsheet(ss).onOpen().create(); } // [END apps_script_triggers_open] // [START apps_script_triggers_delete] diff --git a/ui/communication/basic/code.gs b/ui/communication/basic/code.gs index 6c09d505f..7080180b0 100644 --- a/ui/communication/basic/code.gs +++ b/ui/communication/basic/code.gs @@ -1,7 +1,7 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function doSomething() { - console.log('I was called!'); + console.log("I was called!"); } diff --git a/ui/communication/failure/code.gs b/ui/communication/failure/code.gs index d914b2306..73c076128 100644 --- a/ui/communication/failure/code.gs +++ b/ui/communication/failure/code.gs @@ -1,8 +1,8 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function getUnreadEmails() { // 'got' instead of 'get' will throw an error. return GmailApp.gotInboxUnreadCount(); -} \ No newline at end of file +} diff --git a/ui/communication/private/code.gs b/ui/communication/private/code.gs index 72c183710..109ae0c7a 100644 --- a/ui/communication/private/code.gs +++ b/ui/communication/private/code.gs @@ -1,13 +1,13 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function getBankBalance() { - var email = Session.getActiveUser().getEmail() + const email = Session.getActiveUser().getEmail(); return deepSecret_(email); } function deepSecret_(email) { - // Do some secret calculations - return email + ' has $1,000,000 in the bank.'; -} \ No newline at end of file + // Do some secret calculations + return `${email} has $1,000,000 in the bank.`; +} diff --git a/ui/communication/runner.gs b/ui/communication/runner.gs index cdce4eadb..4935e09d7 100644 --- a/ui/communication/runner.gs +++ b/ui/communication/runner.gs @@ -1,6 +1,6 @@ -var myRunner = google.script.run.withFailureHandler(onFailure); -var myRunner1 = myRunner.withSuccessHandler(onSuccess); -var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess); +const myRunner = google.script.run.withFailureHandler(onFailure); +const myRunner1 = myRunner.withSuccessHandler(onSuccess); +const myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess); myRunner1.doSomething(); myRunner1.doSomethingElse(); diff --git a/ui/communication/success/code.gs b/ui/communication/success/code.gs index 00f2c46ab..319af8f92 100644 --- a/ui/communication/success/code.gs +++ b/ui/communication/success/code.gs @@ -1,7 +1,7 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function getUnreadEmails() { return GmailApp.getInboxUnreadCount(); -} \ No newline at end of file +} diff --git a/ui/dialogs/alert/alert.gs b/ui/dialogs/alert/alert.gs new file mode 100644 index 000000000..42a18b450 --- /dev/null +++ b/ui/dialogs/alert/alert.gs @@ -0,0 +1,49 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_alert_dialogs] +/** + * Creates a custom menu when a user opens a Spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .createMenu("Custom Menu") + .addItem("Show alert", "showAlert") + .addToUi(); +} + +/** + * Shows an alert dialog. + */ +function showAlert() { + const ui = SpreadsheetApp.getUi(); // Same variations. + + const result = ui.alert( + "Please confirm", + "Are you sure you want to continue?", + ui.ButtonSet.YES_NO, + ); + + // Process the user's response. + if (result === ui.Button.YES) { + // User clicked "Yes". + ui.alert("Confirmation received."); + } else { + // User clicked "No" or X in the title bar. + ui.alert("Permission denied."); + } +} +// [END apps_script_alert_dialogs] diff --git a/ui/dialogs/page.html b/ui/dialogs/custom_dialog/Page.html similarity index 100% rename from ui/dialogs/page.html rename to ui/dialogs/custom_dialog/Page.html diff --git a/ui/dialogs/custom_dialog/custom_dialog.gs b/ui/dialogs/custom_dialog/custom_dialog.gs new file mode 100644 index 000000000..7a326ff45 --- /dev/null +++ b/ui/dialogs/custom_dialog/custom_dialog.gs @@ -0,0 +1,38 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_custom_dialog] +/** + * Creates a custom menu when a user opens a Spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .createMenu("Custom Menu") + .addItem("Show dialog", "showDialog") + .addToUi(); +} + +/** + * Shows a custom dialog. + */ +function showDialog() { + const html = HtmlService.createHtmlOutputFromFile("Page") + .setWidth(400) + .setHeight(300); + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .showModalDialog(html, "My custom dialog"); +} +// [END apps_script_custom_dialog] diff --git a/ui/dialogs/custom_sidebar/Page.html b/ui/dialogs/custom_sidebar/Page.html new file mode 100644 index 000000000..8e21f4a39 --- /dev/null +++ b/ui/dialogs/custom_sidebar/Page.html @@ -0,0 +1,15 @@ + + +Hello, world! + \ No newline at end of file diff --git a/ui/dialogs/custom_sidebar/custom_sidebar.gs b/ui/dialogs/custom_sidebar/custom_sidebar.gs new file mode 100644 index 000000000..f637fc7cf --- /dev/null +++ b/ui/dialogs/custom_sidebar/custom_sidebar.gs @@ -0,0 +1,38 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_custom_sidebar] +/** + * Creates a custom sidebar when a user opens a Spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .createMenu("Custom Menu") + .addItem("Show sidebar", "showSidebar") + .addToUi(); +} + +/** + * Shows a custom sidebar. + */ +function showSidebar() { + const html = HtmlService.createHtmlOutputFromFile("Page") + .setTitle("My custom sidebar") + .setWidth(300); + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .showSidebar(html); +} +// [END apps_script_custom_sidebar] diff --git a/ui/dialogs/dialogs.gs b/ui/dialogs/dialogs.gs deleted file mode 100644 index 2e1c6947f..000000000 --- a/ui/dialogs/dialogs.gs +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// [START apps_script_alert_dialogs] -/** - * Creates a custom menu when a user opens a Spreadsheet. - */ -function onOpen() { - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .createMenu('Custom Menu') - .addItem('Show alert', 'showAlert') - .addToUi(); -} - -/** - * Shows an alert dialog. - */ -function showAlert() { - var ui = SpreadsheetApp.getUi(); // Same variations. - - var result = ui.alert( - 'Please confirm', - 'Are you sure you want to continue?', - ui.ButtonSet.YES_NO); - - // Process the user's response. - if (result === ui.Button.YES) { - // User clicked "Yes". - ui.alert('Confirmation received.'); - } else { - // User clicked "No" or X in the title bar. - ui.alert('Permission denied.'); - } -} -// [END apps_script_alert_dialogs] - -// [START apps_script_prompt_dialog] -/** - * Creates a custom menu when a user opens a Spreadsheet. - */ -function onOpen() { - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .createMenu('Custom Menu') - .addItem('Show prompt', 'showPrompt') - .addToUi(); -} - -/** - * Shows a prompt dialog. - */ -function showPrompt() { - var ui = SpreadsheetApp.getUi(); // Same variations. - - var result = ui.prompt( - 'Let\'s get to know each other!', - 'Please enter your name:', - ui.ButtonSet.OK_CANCEL); - - // Process the user's response. - var button = result.getSelectedButton(); - var text = result.getResponseText(); - if (button === ui.Button.OK) { - // User clicked "OK". - ui.alert('Your name is ' + text + '.'); - } else if (button === ui.Button.CANCEL) { - // User clicked "Cancel". - ui.alert('I didn\'t get your name.'); - } else if (button === ui.Button.CLOSE) { - // User clicked X in the title bar. - ui.alert('You closed the dialog.'); - } -} -// [END apps_script_prompt_dialog] - -// [START apps_script_custom_dialog] -/** - * Creates a custom menu when a user opens a Spreadsheet. - */ -function onOpen() { - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .createMenu('Custom Menu') - .addItem('Show dialog', 'showDialog') - .addToUi(); -} - -/** - * Shows a custom dialog. - */ -function showDialog() { - var html = HtmlService.createHtmlOutputFromFile('Page') - .setWidth(400) - .setHeight(300); - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .showModalDialog(html, 'My custom dialog'); -} -// [END apps_script_custom_dialog] - -// [START apps_script_custom_sidebar] -/** - * Creates a custom sidebar when a user opens a Spreadsheet. - */ -function onOpen() { - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .createMenu('Custom Menu') - .addItem('Show sidebar', 'showSidebar') - .addToUi(); -} - -/** - * Shows a custom sidebar. - */ -function showSidebar() { - var html = HtmlService.createHtmlOutputFromFile('Page') - .setTitle('My custom sidebar') - .setWidth(300); - SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .showSidebar(html); -} -// [END apps_script_custom_sidebar] diff --git a/ui/dialogs/menus.gs b/ui/dialogs/menus.gs index 87b6ceef2..d9f9b9068 100644 --- a/ui/dialogs/menus.gs +++ b/ui/dialogs/menus.gs @@ -20,13 +20,12 @@ * Creates a custom menu. */ function onOpen() { - var ui = SpreadsheetApp.getUi(); + const ui = SpreadsheetApp.getUi(); // Or DocumentApp or FormApp. - ui.createMenu('Custom Menu') - .addItem('First item', 'menuItem1') + ui.createMenu("Custom Menu") + .addItem("First item", "menuItem1") .addSeparator() - .addSubMenu(ui.createMenu('Sub-menu') - .addItem('Second item', 'menuItem2')) + .addSubMenu(ui.createMenu("Sub-menu").addItem("Second item", "menuItem2")) .addToUi(); } @@ -35,7 +34,7 @@ function onOpen() { */ function menuItem1() { SpreadsheetApp.getUi() // Or DocumentApp or FormApp. - .alert('You clicked the first menu item!'); + .alert("You clicked the first menu item!"); } /** @@ -43,7 +42,7 @@ function menuItem1() { */ function menuItem2() { SpreadsheetApp.getUi() // Or DocumentApp or FormApp. - .alert('You clicked the second menu item!'); + .alert("You clicked the second menu item!"); } // [END apps_script_menu] @@ -52,7 +51,7 @@ function menuItem2() { * Shows a message box to the user. */ function showMessageBox() { - Browser.msgBox('You clicked it!'); + Browser.msgBox("You clicked it!"); } // [END apps_script_show_message_box] @@ -61,7 +60,7 @@ function showMessageBox() { * A function that can be invoked from a Google Sites link. */ function sitesLink() { - var recipient = Session.getActiveUser().getEmail(); - GmailApp.sendEmail(recipient, 'Email from your site', 'You clicked a link!'); + const recipient = Session.getActiveUser().getEmail(); + GmailApp.sendEmail(recipient, "Email from your site", "You clicked a link!"); } // [END apps_script_sites_link] diff --git a/ui/dialogs/prompt/prompt.gs b/ui/dialogs/prompt/prompt.gs new file mode 100644 index 000000000..18a438b1e --- /dev/null +++ b/ui/dialogs/prompt/prompt.gs @@ -0,0 +1,54 @@ +/** + * Copyright Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [START apps_script_prompt_dialog] +/** + * Creates a custom menu when a user opens a Spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. + .createMenu("Custom Menu") + .addItem("Show prompt", "showPrompt") + .addToUi(); +} + +/** + * Shows a prompt dialog. + */ +function showPrompt() { + const ui = SpreadsheetApp.getUi(); // Same variations. + + const result = ui.prompt( + "Let's get to know each other!", + "Please enter your name:", + ui.ButtonSet.OK_CANCEL, + ); + + // Process the user's response. + const button = result.getSelectedButton(); + const text = result.getResponseText(); + if (button === ui.Button.OK) { + // User clicked "OK". + ui.alert(`Your name is ${text}.`); + } else if (button === ui.Button.CANCEL) { + // User clicked "Cancel". + ui.alert("I didn't get your name."); + } else if (button === ui.Button.CLOSE) { + // User clicked X in the title bar. + ui.alert("You closed the dialog."); + } +} +// [END apps_script_prompt_dialog] diff --git a/ui/forms/code.gs b/ui/forms/code.gs index f7fda9d90..1b25f296d 100644 --- a/ui/forms/code.gs +++ b/ui/forms/code.gs @@ -1,9 +1,9 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function processForm(formObject) { - var formBlob = formObject.myFile; - var driveFile = DriveApp.createFile(formBlob); + const formBlob = formObject.myFile; + const driveFile = DriveApp.createFile(formBlob); return driveFile.getUrl(); -} \ No newline at end of file +} diff --git a/ui/sidebar/code.gs b/ui/sidebar/code.gs index e1079374a..017ca811f 100644 --- a/ui/sidebar/code.gs +++ b/ui/sidebar/code.gs @@ -1,13 +1,13 @@ // Use this code for Google Docs, Slides, Forms, or Sheets. function onOpen() { SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .createMenu('Dialog') - .addItem('Open', 'openDialog') - .addToUi(); + .createMenu("Dialog") + .addItem("Open", "openDialog") + .addToUi(); } function openDialog() { - var html = HtmlService.createHtmlOutputFromFile('Index'); + const html = HtmlService.createHtmlOutputFromFile("Index"); SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp. - .showModalDialog(html, 'Dialog title'); -} \ No newline at end of file + .showModalDialog(html, "Dialog title"); +} diff --git a/ui/user/code.gs b/ui/user/code.gs index 1290cf1ef..397e8a881 100644 --- a/ui/user/code.gs +++ b/ui/user/code.gs @@ -1,7 +1,7 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); + return HtmlService.createHtmlOutputFromFile("Index"); } function getEmail() { return Session.getActiveUser().getEmail(); -} \ No newline at end of file +} diff --git a/ui/webapp/code.gs b/ui/webapp/code.gs index 7549a3d10..191e1e122 100644 --- a/ui/webapp/code.gs +++ b/ui/webapp/code.gs @@ -1,3 +1,3 @@ function doGet() { - return HtmlService.createHtmlOutputFromFile('Index'); -} \ No newline at end of file + return HtmlService.createHtmlOutputFromFile("Index"); +} diff --git a/utils/logging.gs b/utils/logging.gs index 630f203b2..ab7cd6d83 100644 --- a/utils/logging.gs +++ b/utils/logging.gs @@ -28,24 +28,24 @@ function myFunction(parameters) { */ function measuringExecutionTime() { // A simple INFO log message, using sprintf() formatting. - console.info('Timing the %s function (%d arguments)', 'myFunction', 1); + console.info("Timing the %s function (%d arguments)", "myFunction", 1); // Log a JSON object at a DEBUG level. The log is labeled // with the message string in the log viewer, and the JSON content // is displayed in the expanded log structure under "jsonPayload". const parameters = { isValid: true, - content: 'some string', - timestamp: new Date() + content: "some string", + timestamp: new Date(), }; - console.log({message: 'Function Input', initialData: parameters}); - const label = 'myFunction() time'; // Labels the timing log entry. + console.log({ message: "Function Input", initialData: parameters }); + const label = "myFunction() time"; // Labels the timing log entry. console.time(label); // Starts the timer. try { myFunction(parameters); // Function to time. } catch (e) { // Logs an ERROR message. - console.error('myFunction() yielded an error: ' + e); + console.error(`myFunction() yielded an error: ${e}`); } console.timeEnd(label); // Stops the timer, logs execution duration. } @@ -58,11 +58,11 @@ function measuringExecutionTime() { * @param {string} email The email to send with the row data. */ function emailDataRow(rowNumber, email) { - console.log('Emailing data row ' + rowNumber + ' to ' + email); + console.log(`Emailing data row ${rowNumber} to ${email}`); const sheet = SpreadsheetApp.getActiveSheet(); const data = sheet.getDataRange().getValues(); - const rowData = data[rowNumber - 1].join(' '); - console.log('Row ' + rowNumber + ' data: ' + rowData); - MailApp.sendEmail(email, 'Data in row ' + rowNumber, rowData); + const rowData = data[rowNumber - 1].join(" "); + console.log(`Row ${rowNumber} data: ${rowData}`); + MailApp.sendEmail(email, `Data in row ${rowNumber}`, rowData); } // [END apps_script_logging_sheet_information] diff --git a/utils/test_logging.gs b/utils/test_logging.gs index 723aeafbe..de3838974 100644 --- a/utils/test_logging.gs +++ b/utils/test_logging.gs @@ -19,7 +19,7 @@ * @return {string} spreadsheet */ function createTestSpreadsheet() { - const spreadsheet = SpreadsheetApp.create('Test Spreadsheet'); + const spreadsheet = SpreadsheetApp.create("Test Spreadsheet"); for (let i = 0; i < 3; ++i) { spreadsheet.appendRow([1, 2, 3]); } @@ -39,10 +39,10 @@ function populateValues(spreadsheetId) { for (let i = 0; i < 10; ++i) { values[i] = []; for (let j = 0; j < 10; ++j) { - values[i].push('Hello'); + values[i].push("Hello"); } } - const range = 'A1:J10'; + const range = "A1:J10"; SpreadsheetApp.openById(spreadsheetId).getRange(range).setValues(values); SpreadsheetApp.flush(); } @@ -51,7 +51,7 @@ function populateValues(spreadsheetId) { * Test emailDataRow of logging.gs */ function itShouldEmailDataRow() { - console.log('> itShouldEmailDataRow'); + console.log("> itShouldEmailDataRow"); const email = Session.getActiveUser().getEmail(); const spreadsheetId = createTestSpreadsheet(); populateValues(spreadsheetId); @@ -63,7 +63,7 @@ function itShouldEmailDataRow() { * runs all the functions of logging.gs */ function RUN_ALL_TESTS() { - console.log('> itShouldMeasureExecutionTime'); + console.log("> itShouldMeasureExecutionTime"); measuringExecutionTime(); itShouldEmailDataRow(); }