Saturday, 29 May 2021

How to Schedule a Google Meeting with Google Calendar and Apps Script

This Apps Script sample shows how you can programmatically schedule video meetings inside Google Meet with one or more participants using the Google Calendar API. It can be useful for teachers who wish to schedule regular meetings with their students but instead of manually creating meeting invites, they can easily automate the whole process for the entire class.

Schedule Google Meeting

Setup Google Meeting with Apps Script

Give your meeting a title, the start date, the meeting duration, the list of attendees and how often you wanted to be reminded of the upcoming Google meeting. A new meeting event will be added to your Google Calendar and you’ll also be provided with a Google Meet link that you share with your students and colleagues through mail merge.

const createGoogleMeeting = () => {
  // The default calendar where this meeting should be created
  const calendarId = "primary";

  // Schedule a meeting for May 30, 2021 at 1:45 PM
  // January = 0, February = 1, March = 2, and so on
  const eventStartDate = new Date(2021, 4, 30, 13, 45);

  // Set the meeting duration to 45 minutes
  const eventEndDate = new Date(eventStartDate.getTime());
  eventEndDate.setMinutes(eventEndDate.getMinutes() + 45);

  const getEventDate = (eventDate) => {
    // Dates are computed as per the script's default timezone
    const timeZone = Session.getScriptTimeZone();

    // Format the datetime in `full-date T full-time` format
    return {
      timeZone,
      dateTime: Utilities.formatDate(
        eventDate,
        timeZone,
        "yyyy-MM-dd'T'HH:mm:ss"
      ),
    };
  };

  // Email addresses and names (optional) of meeting attendees
  const meetingAttendees = [
    {
      displayName: "Amit Agarwal",
      email: "amit@labnol.org",
      responseStatus: "accepted",
    },
    { email: "student1@school.edu", responseStatus: "needsAction" },
    { email: "student2@school.edu", responseStatus: "needsAction" },
    {
      displayName: "Angus McDonald",
      email: "assistant@school.edu",
      responseStatus: "tentative",
    },
  ];

  // Generate a random id
  const meetingRequestId = Utilities.getUuid();

  // Send an email reminder a day prior to the meeting and also
  // browser notifications15 minutes before the event start time
  const meetingReminders = [
    {
      method: "email",
      minutes: 24 * 60,
    },
    {
      method: "popup",
      minutes: 15,
    },
  ];

  const { hangoutLink, htmlLink } = Calendar.Events.insert(
    {
      summary: "Maths 101: Trigonometry Lecture",
      description: "Analyzing the graphs of Trigonometric Functions",
      location: "10 Hanover Square, NY 10005",
      attendees: meetingAttendees,
      conferenceData: {
        createRequest: {
          requestId: meetingRequestId,
          conferenceSolutionKey: {
            type: "hangoutsMeet",
          },
        },
      },
      start: getEventDate(eventStartDate),
      end: getEventDate(eventEndDate),
      guestsCanInviteOthers: false,
      guestsCanModify: false,
      status: "confirmed",
      reminders: {
        useDefault: false,
        overrides: meetingReminders,
      },
    },
    calendarId,
    { conferenceDataVersion: 1 }
  );

  Logger.log("Launch meeting in Google Meet: %s", hangoutLink);
  Logger.log("Open event inside Google Calendar: %s", htmlLink);
};

Also see: Generate Add to Calendar Links

Google Meeting with Recurring Schedule

The above code can be extended to create meetings that occur on a recurring schedule.

You need to simply add a recurrence attribute to the meeting event resource that specifies the recurring event in RRULE notation. For instance, the following rule will schedule a recurring video meeting for your Maths lecture every week on Monday, Thursday for 8 times.

{
  ...event,
  recurrence: ["RRULE:FREQ=WEEKLY;COUNT=8;INTERVAL=1;WKST=MO;BYDAY=MO,TH"];
}

Here are some other useful RRULE examples:

  • FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR - Occurs every week except on weekends
  • FREQ=MONTHLY;INTERVAL=2;BYDAY=TU - Occurs every Tuesday, every other month
  • INTERVAL=2;FREQ=WEEKLY - Occurs every other week
  • FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;BYMONTH=12 - Occurs every other week in December on Tuesday and Thursday
  • FREQ=MONTHLY;INTERVAL=2;BYDAY=1SU,-1SU - Occurs every other month on the first and last Sunday of the month


from Digital Inspiration https://ift.tt/2TsmUph

Thursday, 27 May 2021

How to Use PayPal Subscriptions API with Node.js

Our Google add-on store uses PayPal Subscriptions with Digital Goods to process recurring payments and the invoices are sent to customers through Document Studio.

There are two steps.

  1. Customers makes the payment and completes the order on our website.
  2. PayPal sends a BILLING.SUBSCRIPTION.ACTIVATED webhook to a serverless function.
  3. The function (running on Firebase, Google Cloud) verifies the subscription and checks if the status is active.
  4. It invokes the Apps Script API to complete the order.

The cloud function was previously using the official PayPal SDK for Node.js but it has been recently deprecated and no longer supports the new PayPal subscriptions API endpoints. Migrating from the PayPal Node SDK to your own solution is relatively simple and involves two steps:

1. Get the PayPal Access Token

const { default: axios } = require("axios");

const getPayPalAccessToken = async () => {
  const client_id = "PayPal Client ID goes here";
  const client_secret = "PayPal Client Secret goes here";
  const options = {
    url: "https://api-m.paypal.com/v1/oauth2/token",
    method: "POST",
    headers: {
      Accept: "application/json",
      "Accept-Language": "en_US",
      "Content-Type": "application/x-www-form-urlencoded",
    },
    auth: {
      username: client_id,
      password: client_secret,
    },
    params: {
      grant_type: "client_credentials",
    },
  };
  const { status, data } = await axios(options);
  return data.access_token;
};

If you are planning to test your integration with your PayPal sandbox account instead of the production version, replace api-m.paypal.com in the requests with api-m.sandbox.paypal.com and use the sandbox client secret credentials.

2. Verify the Subscription

A successful request returns the HTTP 200 OK status code and a JSON response body.

const { default: axios } = require("axios");

const verifyPayPalSubscription = async (subscription_id) => {
  const token = await getPayPalAccessToken();
  const options = {
    method: "GET",
    url: `https://api-m.paypal.com/v1/billing/subscriptions/${subscription_id}`,
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
  };
  const { status, data = {} } = await axios(options);
  if (status === 200) {
    const { subscriber: { email_address } = {}, status } = data;
    return status === "ACTIVE";
  }
  return false;
};

Once the PayPal Subscription is found to be active, an HTTP request is made to the Google Apps Script API that sends the invoice and license to the customer. Learn more.



from Digital Inspiration https://ift.tt/34ljp68

Wednesday, 26 May 2021

How to Add a Watermark in Google Documents

Microsoft Word includes a useful “Insert Watermark” feature to help you easily add your brand’s logo image or a text stamp that fades behind the content of every page in the document. A company’s policy may require employees to add watermarks to indicate if any document is in draft stage or if the document is confidential and not meant for external distribution.

Microsoft Word Watermark

Insert Watermarks in Google Docs

Unlike Microsoft Word, there’s no built-in support for Watermarks in Google Docs but there’s a simple workaround - create a faded image with the text of your watermark and place that image behind the text of your document pages. Here’s how:

1. Create the watermark stamp

Launch MS Paint on your computer and create a simple watermark image in landscape mode with dark gray text. Please use a bold font like Impact with large font size as the large image can always be resized inside Google Docs but not vice-versa.

I’ve also added some ready-to-use image stamps on Canva and Imgur.

Upload Watermark Image

2. Upload Watermark to Google Docs

Inside Google Docs, go to the Insert menu, choose the Image submenu and select Upload from Computer. Upload the watermark image that you saved in the previous step to Google Docs.

3. Open Image Options

Right-click the uploaded image inside Google Docs and choose Image Options from the contextual menu.

Watermark Diagonal Image

4. Change Rotation

Expand the Image Options sidebar and, under the Size & Rotation section, set the angle to around 320° to make the watermark diagonal.

5. Send the Image Behind Text

  • Under the text wrapping section, choose Behind Text to send the watermark image behind the content of your document.
  • Under Position, choose the Fixed position option with the layout set as Center. This will position your watermark image right in the center of the page.
  • Under the Adjustments section, set the transparency level to around 80% to fade the watermark image in the background.

The Watermark Effect in Documents

Here’s how the final watermark effect will look like in your Google Document.

Watermark in Document

Tip: You can use Document Studio to generate PDF files from Google Forms and the watermarks would be also show up in your PDF document.



from Digital Inspiration https://ift.tt/3fkI0OP

Saturday, 15 May 2021

The Best Extensions for Google Chrome

Best Google Chrome extensions

Here’s a comprehensive list of the best extensions for Google Chrome that will help you do more and also enhance your web browsing experience.

The Best Google Chrome extensions

  • Vimium C — Browse the web, interact with web pages, navigate browser history using keyboard shortcuts. Inspired by Vim commands.
  • Fika - Read pages in a Kindle-style clean layout with beautiful typography while hiding the distracting parts.
  • PushBullet — Easily transfer web page links, text notes, or push photos and files from the computer to your phone and vice-versa.
  • OneTab — Save all your open tabs in a group and duplicate your session anytime later with a click.
  • Gmail Sender Icons - Quickly identify the sending domain of an email in Gmail without opening the message.
  • Bubble Cursor - The add-on makes it easy for you to click on links that are too small to select with your mouse or for typing inside input boxes.
  • Picture in Picture - Watch YouTube videos in an always-on-top floating window while you work on other tasks.
  • Zoho Annotator - A simple ad-free screenshot capture tool with a built-in editor for annotating images. Also integrates with Google Drive, OneDrive and Dropbox.
  • Loom - Record a screencast video with voice narration, include your webcam video and share instantly. Also see Screenity.
  • URL Render - Instead of clicking individual links on the Google search page, hover your mouse and instantly view the underlying page in a floating window.
  • Clipt - A universal clipboard for Android and desktop computers. Copy any text on your phone and instantly paste it on the desktop and vice-versa.
  • Hover Zoom - Hover your mouse over any thumbnail image on sites like Facebook and Amazon and the add-on will enlarge the image to its full size.
  • Quick Source Viewer - A better alternative to the native View Source option that displays both JS and CSS files in addition to HTML content.
  • Save To Drive - Right-click and save the current web page, or images on a page, to your Google Drive.
  • Google Input - Type text in any language of your choice using virtual keyboards, your handwriting and transliteration.
  • Google Dictionary - Use this add-on to view definitions of words and learn their correct pronunciation.
  • uBlacklist - Blocks specific sites and entire domains from appearing in your Google search results.
  • Gmail Notes - Attach sticky notes to your email message that are persistent and will show up the next time you open that same email inside Gmail.
  • Ugly Email - Some emails contain a tracking pixel that notifies the sender when their emails are read. This add-on blocks the tracking attempts.
  • Stylebot - Change the appearance of any web page with CSS selectors, permanently hide elements on a page and the changes persist across browser sessions.
  • Webtime Tracker — Keep track of how you spend your time on individual websites and visualize your Internet usage through graphs.
  • Skip Search - An address bar shortcut for the I'm lucky command that directly takes you to the most relevant website for your search query.
  • Single File - Download the entire web page into a single HTML file. The associated CSS files, fonts and images are also saved in the file.
  • Go Incognito - Open the current tab of your browser in a new incognito tab, useful for browsing news websites are behind paywalls.
  • Feeder - An excellent RSS feed reader that is accessible from the Chrome toolbar and supports notifications for your favorite feeds.
  • Scribe - Create step-by-step guides and tutorials by recording steps and publish them as PDF guides.
  • Visbug - A must-have design tool for web developers that brings powerful editing capabilities to the browser.
  • TabNotes - A minimalistic start page for Chrome that opens a simple notepad in each new tab.
  • Sitemod - Modify any website on the Internet through Chrome Dev Tools and create a permanent copy of the modified website with a unique, shareable URL.
  • iCloud Passwords - Access your Safari passwords that are saved inside iOS and Mac device from Chrome on Windows PCs.
  • Twitter Screenshots - Take beautiful, uncluttered screenshots of tweets with a click.
  • StayFocusd - It helps you limit the time you spend on distracting websites Facebook or Reddit by temporarily blocking the site when the allotted time has passed.
  • Black Menu - Create shortcuts to your favorite Google services and access your emails, calendar, videos and more in an easily accessible popup.


from Digital Inspiration https://ift.tt/3ybxFvX

Friday, 14 May 2021

How to Use Notion with Gmail and Google Sheets using Apps Script

Notion, my absolute favorite tool for storing all sorts of things from web pages to code snippets to recipes, just got better. They’ve released a public API and thus it will be a lot easier for developers to read and write to their Notion workspace from external apps.

For instance, you can create a document in Google Docs and export it to Notion while staying inside Docs. Google Sheets users can pull pages from Notion database into their spreadsheet. Any new submissions in Google Forms can be directly saved to Notion and so on!

Save Gmail Messages in Notion

I have put together a Gmail add-on that makes it easy for you to save email messages, or any other text content, from Gmail to your Notion workspace with a click. Here’s how the app works.

Step 1: Connect Gmail to Notion

002815

Step 2: Allow Access to Notion pages - if you have multiple databases in your Notion workspace, you have an option to grant access to select databases and the rest will be inaccessible to the external app.

Authorize Notion

Step 3: Choose Email - open any email message in Gmail and you’ll have an option to edit the content of the email subject and body before sending the content to your Notion page. Please note that the app only supports plain text format at this time.

Send Email to Notion

Step 4: Open Notion - As soon as you hit the Send to Notion button, the content of the currently selected email message is added to your Notion database. You can click the All updates link in your Notion sidebar to view to recently added page.

Notion page

If you would like to try this Gmail to Notion app, please get in touch.

How to Use Notion with Google Apps Script

If you would to integrate your own Google add-on with Notion API, here’s a brief outline of the steps involved.

  1. Go to notion.so and click the Create New Integration button. You’ll be provided with a Client ID and Client Secret that you’ll need in a later step.

  2. Include the OAuth2 library in your Apps Script project and invoke the getRedirectUri method to get the OAuth2 redirect URL for the previous step.

const getNotionService = () => {
  return OAuth2.createService("Notion")
    .setAuthorizationBaseUrl("https://api.notion.com/v1/oauth/authorize")
    .setTokenUrl("https://api.notion.com/v1/oauth/token")
    .setClientId(CLIENT_ID)
    .setClientSecret(CLIENT_SECRET)
    .setCallbackFunction("authCallback")
    .setPropertyStore(PropertiesService.getUserProperties())
    .setCache(CacheService.getUserCache())
    .setTokenHeaders({
      Authorization: `Basic ${Utilities.base64Encode(
        `${CLIENT_ID}:${CLIENT_SECRET}`
      )}`,
    });
};

const authCallback = (request) => {
  const isAuthorized = getNotionService().handleCallback(request);
  return HtmlService.createHtmlOutput(
    isAuthorized ? "Success!" : "Access Denied!"
  );
};

const getRedirectUri = () => {
  console.log(OAuth2.getRedirectUri());
};
  1. Connect to Notion API - Make a Get HTTP request to the /vi/databases to fetch a list of all databases that the user has explicitly shared with authorized app.
function getDatabasesList() {
  var service = getNotionService();
  if (service.hasAccess()) {
    const url = "https://api.notion.com/v1/databases";
    const response = UrlFetchApp.fetch(url, {
      headers: {
        Authorization: `Bearer ${service.getAccessToken()}`,
        "Notion-Version": "2021-05-13",
      },
    });
    const { results = [] } = JSON.parse(response.getContentText());
    const databases = results
      .filter(({ object }) => object === "database")
      .map(({ id, title: [{ plain_text: title }] }) => ({ id, title }));
    console.log({ databases });
  } else {
    console.log("Please authorize access to Notion");
    console.log(service.getAuthorizationUrl());
  }
}

Gmail to Notion - Try the App

The Gmail to Notion app is in private beta. If you would like to use it with your Gmail or Google Workspace account, please get in touch for an invite.



from Digital Inspiration https://ift.tt/2Rj2VbO

Wednesday, 12 May 2021

Create React App with Multiple Entry Points

The Create React App frameworks lets you easily build single page applications but it doesn’t support multiple entry points. To give you an example, if a website outputs separate home pages for mobile and desktop clients, the pages could be sharing some common React components between them, and it may thus not be practical to build two completely separate React applications.

Also see: Bundle React App with Gulp

CRA doesn’t support multiple entry points but there are couple of ways to solve this problem.

Option 1 Eject from the Create React App using the npm run eject command and update the entry inside webpack.config.js file to include multiple entry points.

Option 2 Use an alternate build tool like Vite.js that includes support for multiple entry points out of the box.

Option 3 Use the rewired app - it lets you easily make changes and small tweaks to the default Webpack configuration without ejecting the app.

Option 4 Use REACT_APP environment variables to specify the target component and then use ES5 dynamic imports to load the corresponding app component as shown in this example.

React Multiple Entry Points

Multiple Entry Points for Create React App

If you intend to use the Create React App configuration without ejecting it, here’s a simple workaround that will help you define multiple entry points and the output will be bundle in separate folders.

Inside the src folder, create two components.

// ./src/Desktop.js
import React from "react";

const Desktop = () => {
  return <h1>For Desktop</h1>;
};

export default Desktop;
// ./src/Mobile.js
import React from "react";

const Mobile = () => {
  return <h1>For Mobile</h1>;
};

export default Mobile;

The default entry file index.js looks something like this:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

Next, edit your package.json file and add commands, one per build target.

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "build:mobile": "cp src/Mobile.js src/App.js && npm run build && mv build build-mobile",
    "build:desktop": "cp src/Desktop.js src/App.js && npm run build && mv build build-desktop"
  }

Run npm run build:mobile when the build target is mobile or npm run build:desktop for the desktop entry point.



from Digital Inspiration https://ift.tt/3hlcMso

Tuesday, 11 May 2021

Google Sheets - Find Values in One Column that are Missing in Another Column

A small business maintains their staff roster in a simple Google Sheet - the column A of the sheet contains a list of all employee names and column B contains a list of employees who have been assigned to a project.

Items in column A that are not in column B

The immediate task is to identify staff members who are part of the organization but have not been assigned any project yet. In other words, the manager needs to figure out all employee names from column A who are not preset in column B.

There are two ways to solve this problem - visually and through formulas.

Using Visual Formatting

The first option would be to highlight cells in column A that are missing in column B.

Inside the Google Sheet, go to the Format menu and choose conditional formatting. Here select A2:A for the range field, choose Custom Formula from the Format Cells If dropdown and paste the formula:

=COUNTIF(B$2:B, A2)=0

The COUNTIF function will essentially count the occurrence of each item in Column A against the range of cells in Column B. If the count for an item in Column A is 0, it means that the cell value is not present in column B and the cell is highlighted with a different background color.

Visual Formatting - Missing Column Values

Find Missing Items in Another Column

The next approach uses Google Sheet formulas to create a list of items that are in Column A but missing in Column B.

We’ll make use of the FILTER function that, as the name suggests, returns only a filtered version of a range that meets a specific criteria. In our case, the criteria is similar to the one that we used in the visual formatting section.

Go to column C (or any blank column) and enter this formula in the first empty cell.

=FILTER(A2:A,ISNA(MATCH(A2:A,B2:B,0)))

Google Sheets MATCH function

The MATCH function returns the position of items in Column A in the range associated with Column B and it returns #N/A if the values is not found. When the result is used with ISNA, it returns true only when the match is not found.

Using Google Query Language

SQL geeks may also use the Google Query Language, we are used it with D3.js visualization, to print the list of names that are in Column B but not in Column B.

=QUERY(A2:A,
   "SELECT A WHERE A <> ''
    AND NOT A MATCHES '"&TEXTJOIN("|",TRUE,B2:B)&"'
    ORDER BY A")

missing values - Google Query

The matches operator in the where clause does a regex comparison and the order by clause in the query will automatically sort the output alphabetically.



from Digital Inspiration https://ift.tt/2RMLi3O

Saturday, 1 May 2021

Get Email Alerts When COVID-19 Vaccines Become Available Near You

India is currently in the midst of a second wave of the Coronavirus and this one is far more devastating than what we have seen last year. The country is reporting close to 400,000+ new cases every day but the actual count of daily infections could be much higher.

The COVID-19 vaccination program in India was earlier available to people above 45 years of age but starting today (May 1), anyone above the age of 18 years is eligible for Covid-19 vaccination.

Vaccine Availability

COVID-19 Vaccines Near Me

The government’s official website - cowin.gov.in - has a useful search section that allows you see the nearby vaccination centers in your city or zip code. You’ll also know how many vaccine doses are available at a specific center and the earliest date when the next batch of vaccine stocks are due.

Based on this public data, I have developed an open-source vaccine tracker that will monitor the vaccine availability near you and will send email alerts as stocks become available. The source code of the project is available on Github.

Build your own Covid-19 Vaccine Tracker

Step 1: To get started, click here to make a copy of the Vaccine Tracker Google Sheet in your Google Drive.

Step 2: Click the Vaccine Tracker menu (near the Help menu) and choose Enable as shown in the screenshot.

Vaccine Tracker Google Sheet

Step 3: You may see an authorization window. If you get an “unverified app” message, click the Advanced link and choose “Go to Vaccine Alerts”. The app is 100% safe and open-source.

Step 4: Go to Step 2 now and choose the Enable menu again to launch the tracker. Enter one more pin codes, the email address where you wish to receive the alerts and the age group for which you need to monitor vaccine availability.

Click the Create Email Alert button and your system is up and running. Google Sheets will run this monitor every day and send an email at 8 am indicating the availability of vaccines in your specified areas.

Here’s a copy of the email sent by the vaccine tracker.

Email Alert - Vaccine Tracker

And if you ever wish to stop Google Sheets from tracking vaccine availability, go to the same sheet and choose Disable from the menu.



from Digital Inspiration https://ift.tt/3xIj770