יצירת תוסף ל-Classroom

זהו המדריך הראשון בסדרת המדריכים על התוספים ל-Classroom.

במדריך הזה נסביר איך לפתח אפליקציית אינטרנט ולפרסם אותה כתוסף ל-Classroom. בהדרכות עתידיות נרחיב את האפליקציה הזו.

במהלך המדריך הזה תלמדו:

  • יוצרים פרויקט חדש ב-Google Cloud עבור התוסף.
  • יוצרים אפליקציית אינטרנט בסיסית עם לחצני placeholder לכניסה.
  • לפרסם דף מוצר של התוסף ב-Google Workspace Marketplace.

בסיום, תוכלו להתקין את התוסף ולטעון אותו ב-iframe של התוספים ב-Classroom.

דרישות מוקדמות

בוחרים שפה כדי לראות את דרישות ההרשאה המתאימות:

Python

בדוגמה שלנו ל-Python נעשה שימוש ב-Flask framework. אפשר להוריד את קוד המקור המלא של כל ההדרכות מדף הסקירה הכללית. הקוד של המדריך הזה נמצא בספרייה /flask/01-basic-app/.

אם צריך, מתקינים את Python מגרסה 3.7 ואילך ומוודאים ש-pip זמין.

python -m ensurepip --upgrade

מומלץ גם להגדיר ולהפעיל סביבה וירטואלית חדשה של Python.

python3 -m venv .classroom-addon-env
source .classroom-addon-env/bin/activate

כל תיקיית משנה של מדריך בדוגמאות שהורדתם מכילה קובץ requirements.txt. אפשר להתקין במהירות את הספריות הנדרשות באמצעות pip. כדי להתקין את הספריות הנדרשות להדרכה הזו, מבצעים את הפעולות הבאות:

cd flask/01-basic-app
pip install -r requirements.txt

Node.js

בדוגמה שלנו ל-Node.js נעשה שימוש במסגרת Express. אפשר להוריד את קוד המקור המלא של כל ההדרכות מדף הסקירה הכללית.

אם צריך, מתקינים את NodeJS בגרסה 16.13 ואילך.

מתקינים את המודולים הנדרשים של הצמתים באמצעות npm.

npm install

Java

בדוגמה שלנו ב-Java נעשה שימוש ב-Spring Boot framework. אפשר להוריד את קוד המקור המלא של כל ההדרכות מדף הסקירה הכללית.

מתקינים את Java מגרסה 11 ואילך, אם היא עדיין לא מותקנת במחשב.

אפליקציות Spring Boot יכולות להשתמש ב-Gradle או ב-Maven כדי לטפל ב-builds ולנהל יחסי תלות. הדוגמה הזו כוללת את מעטפת Maven שמבטיחה פיתוח מוצלח בלי שתצטרכו להתקין את Maven בעצמכם.

כדי להריץ את הדוגמה שסיפקנו, מריצים את הפקודות הבאות בתיקייה שבה הורדת את הפרויקט כדי לוודא שיש לך את התנאים המוקדמים להרצת הפרויקט.

java --version
./mvnw --version

או ב-Windows:

java -version
mvnw.cmd --version

הגדרת פרויקט ב-Google Cloud

הגישה ל-Classroom API ולשיטות האימות הנדרשות מבוקרת על ידי פרויקטים ב-Google Cloud. בהוראות הבאות מוסבר איך יוצרים ומגדירים פרויקט חדש לשימוש עם התוסף.

יצירת הפרויקט

כדי ליצור פרויקט חדש ב-Google Cloud, נכנסים לדף ליצירת פרויקט. אפשר לתת שם כלשהו לפרויקט החדש. לוחצים על Create.

יצירת הפרויקט החדש תתבצע תוך כמה רגעים. בסיום, חשוב לבחור את הפרויקט. אפשר לבחור אותו בתפריט הנפתח לבחירת פרויקטים בחלק העליון של המסך, או ללחוץ על בחירת פרויקט בתפריט ההתראות בפינה השמאלית העליונה.

בחירת הפרויקט במסוף Google Cloud

צירוף ה-SDK של Google Workspace Marketplace לפרויקט ב-Google Cloud

עוברים לדפדפן של ספריית ה-API. מחפשים את Google Workspace Marketplace SDK. ה-SDK אמור להופיע ברשימת התוצאות.

הכרטיס של Google Workspace Marketplace SDK

בוחרים את הכרטיס של Google Workspace Marketplace SDK ולוחצים על Enable (הפעלה).

הגדרת ה-SDK של Google Workspace Marketplace

Google Workspace Marketplace הוא המקום שבו המשתמשים והאדמינים מתקינים את התוסף. כדי להמשיך, מגדירים את הגדרת האפליקציה ואת רשימת האפליקציה בחנות ב-Marketplace SDK, וגם את מסך ההסכמה ל-OAuth.

הגדרת אפליקציה

עוברים לדף הגדרת האפליקציה ב-Marketplace SDK. יש לספק את הפרטים הבאים:

  • מגדירים את הרשאות הגישה לאפליקציה ל-Public או ל-Private.

    • ההגדרה 'גלוי לכולם' מיועדת לאפליקציות שיושקו בסופו של דבר למשתמשי קצה. אפליקציה ציבורית צריכה לעבור תהליך אישור לפני שהיא תפורסם למשתמשי הקצה, אבל אתם יכולים לציין משתמשים שיכולים להתקין ולבדוק אותה כטיוטה. זוהי סטטוס לפני הפרסום, שמאפשר לכם לבדוק ולפתח את התוסף לפני שליחתו לאישור.
    • ההגדרה הפרטית מתאימה לפיתוח ולבדיקה פנימית. רק משתמשים מאותו דומיין שבו נוצר הפרויקט יכולים להתקין אפליקציה פרטית. לכן, צריך להגדיר את החשיפה כ'פרטית' רק אם הפרויקט נוצר בדומיין עם מינוי ל-Google Workspace for Education, אחרת משתמשי הבדיקה לא יוכלו להפעיל תוספים ל-Classroom.
  • אם רוצים להגביל את ההתקנה לאדמינים של הדומיין, מגדירים את הגדרות ההתקנה ל-Admin Only install.

  • בקטע שילוב אפליקציות, בוחרים באפשרות תוסף Classroom. תתבקשו להזין את ה-URI המאובטח של הגדרת הקובץ המצורף. זוהי כתובת ה-URL שאתם מצפים שתיטען כשמשתמש יפתח את התוסף. לצורך המדריך הזה, הערך צריך להיות https://<your domain>/addon-discovery.

  • התחיליות הקבילות של URI לקובצי מצורף משמשות לאימות של כתובות ה-URI שמוגדרות ב-AddOnAttachment באמצעות השיטות courses.*.addOnAttachments.create ו-courses.*.addOnAttachments.patch. האימות הוא התאמה של קידומת מחרוזת מילולית, ואי אפשר להשתמש בתווים כלליים לחיפוש בשלב זה. מוסיפים לפחות את דומיין השורש של שרת התוכן, כמו https://localhost:5000/ או https://cdn.myedtech.com/.

  • מוסיפים את אותם היקפי הרשאות OAuth שצוינו במסך ההסכמה ל-OAuth בשלב הקודם.

  • ממלאים את השדות בהתאם לארגון שלכם בקטע Developer Links.

רישום חנות

עוברים לדף Store Listing ב-Marketplace SDK. יש לספק את הפרטים הבאים:

  • בקטע פרטי האפליקציה, מוסיפים שפה או מרחיבים את התפריט הנפתח לצד השפה שכבר רשומה. נותנים שם לאפליקציה ומתארים אותה. הפרטים האלה יופיעו בדף המוצר של התוסף ב-Google Workspace Marketplace. לוחצים על סיום כדי לשמור.
  • בוחרים קטגוריה לתוסף.
  • בקטע נכסי גרפיקה, מספקים תמונות לשדות הנדרשים. אפשר לשנות את הפרטים האלה מאוחר יותר, בינתיים אפשר להשתמש בתוויות placeholders.
  • בקטע Support Links (קישורי תמיכה), מזינים את כתובות ה-URL הנדרשות. אפשר להשתמש בתוויות placeholders אם הגדרתם את סטטוס החשיפה של האפליקציה ל-Private (פרטי) בשלב הקודם.

אם הגדרתם את הרשאות הגישה לאפליקציה לפרטי בשלב הקודם, לוחצים על פרסום. האפליקציה תהיה זמינה להתקנה באופן מיידי. אם מגדירים את החשיפה של האפליקציה לציבורית, מוסיפים כתובות אימייל של משתמשי הבדיקה באזור בודקי הטיוטה ולוחצים על שמירה של הטיוטה.

מסך ההסכמה של OAuth מופיע בפעם הראשונה שמשתמשים מאשרים את האפליקציה. במסך הזה הם מתבקשים לאפשר לאפליקציה גישה למידע האישי ולפרטי החשבון שלהם, בהתאם להיקפים שאתם מפעילים.

עוברים לדף היצירה של מסך ההסכמה ל-OAuth. יש לספק את הפרטים הבאים:

  • מגדירים את סוג המשתמש ל-חיצוני. לוחצים על Create.
  • בדף הבא, ממלאים את פרטי האפליקציה הנדרשים ואת הפרטים ליצירת קשר. בקטע Authorized Domains (דומיינים מורשים), מציינים את כל הדומיינים שמארחים את האפליקציה. לוחצים על שמירה והמשך.
  • מוסיפים את היקפי ההרשאות של OAuth הנדרשים לאפליקציית האינטרנט. במדריך להגדרת OAuth מוסבר בהרחבה על ההיקפים ועל המטרה שלהם.

    כדי ש-Google תשלח את פרמטר השאילתה login_hint, צריך לבקש לפחות אחד מההיקפים הבאים. הסבר מפורט יותר על ההתנהגות הזו זמין במדריך להגדרת OAuth:

    • https://www.googleapis.com/auth/userinfo.email (כבר כלול)
    • https://www.googleapis.com/auth/userinfo.profile (כבר כלול)

    ההיקפים הבאים ספציפיים לתוספים של Classroom:

    • https://www.googleapis.com/auth/classroom.addons.teacher
    • https://www.googleapis.com/auth/classroom.addons.student

    צריך לכלול גם את כל היקפי הרשאות Google API שהאפליקציה שלכם דורשת ממשתמשי הקצה.

    לוחצים על שמור והמשך.

  • מציינים את כתובות האימייל של חשבונות הבדיקה בדף Test users. לוחצים על שמירה והמשך.

מוודאים שההגדרות נכונות וחוזרים למרכז הבקרה.

התקנת התוסף

עכשיו אפשר להתקין את התוסף באמצעות הקישור בחלק העליון של הדף Store Listing של Marketplace SDK. לוחצים על View In Marketplace (הצגה ב-Marketplace) בחלק העליון של הדף כדי להציג את הכרטיס, ואז בוחרים באפשרות Install (התקנה).

פיתוח אפליקציית אינטרנט בסיסית

הגדרת שלד של אפליקציית אינטרנט עם שני מסלולים. בשלבים הבאים במדריך נרחיב את האפליקציה הזו, אז בינתיים פשוט יוצרים דף נחיתה לתוסף /addon-discovery ודף מדומה של דף הבית / עבור 'אתר החברה'.

דוגמה לאפליקציית אינטרנט ב-iframe

מטמיעים את שתי נקודות הקצה הבאות:

  • /: מוצגת הודעה של קבלת פנים וכפתור לסגירת הכרטיסייה הנוכחית וגם של ה-iframe של התוסף.
  • /addon-discovery: מוצגת הודעת פתיחה ושני לחצנים: אחד לסגירת ה-iframe של התוסף והשני לפתיחת אתר בכרטיסייה חדשה.

שימו לב שאנחנו מוסיפים לחצנים ליצירה ולסגירה של חלונות או של ה-iframe. בשלב הבא נסביר איך להשתמש בהן כדי להעביר את המשתמש בבטחה לכרטיסייה חדשה לצורך הרשאה.

יצירת סקריפט כלי

יוצרים ספרייה static/scripts. יוצרים קובץ חדש addon-utils.js. מוסיפים את שתי הפונקציות הבאות.

/**
 *   Opens a given destination route in a new window. This function uses
 *   window.open() so as to force window.opener to retain a reference to the
 *   iframe from which it was called.
 *   @param {string} destinationURL The endpoint to open, or "/" if none is
 *   provided.
 */
function openWebsiteInNewTab(destinationURL = '/') {
  window.open(destinationURL, '_blank');
}

/**
 *   Close the iframe by calling postMessage() in the host Classroom page. This
 *   function can be called directly when in a Classroom add-on iframe.
 *
 *   Alternatively, it can be used to close an add-on iframe in another window.
 *   For example, if an add-on iframe in Window 1 opens a link in a new Window 2
 *   using the openWebsiteInNewTab function, you can call
 *   window.opener.closeAddonIframe() from Window 2 to close the iframe in Window
 *   1.
 */
function closeAddonIframe() {
  window.parent.postMessage({
    type: 'Classroom',
    action: 'closeIframe',
  }, '*');
};

יצירת מסלולים

מטמיעים את נקודות הקצה /addon-discovery ו-/.

Python

הגדרת ספריית האפליקציה

לצורך הדוגמה הזו, נבנה את הלוגיקה של האפליקציה כמודול ב-Python. זוהי הספרייה webapp בדוגמה שצירפנו.

יוצרים ספרייה למודול השרת, למשל webapp. מעבירים את הספרייה static לספריית המודול. יוצרים גם ספרייה template בספריית המודול. קובצי ה-HTML יועברו אליה.

יצירת מודול השרת*

יוצרים את הקובץ __init__.py בתיקיית המודול ומוסיפים את ההצהרות והייבוא הבאים.

from flask import Flask
import config

app = Flask(__name__)
app.config.from_object(config.Config)

# Load other module script files. This import statement refers to the
# 'routes.py' file described below.
from webapp import routes

לאחר מכן יוצרים קובץ לטיפול במסלולים של אפליקציית האינטרנט. הערך הזה הוא webapp/routes.py בדוגמה שלנו. מטמיעים את שני המסלולים בקובץ הזה.

from webapp import app
import flask

@app.route("/")
def index():
    return flask.render_template("index.html",
                                message="You've reached the index page.")

@app.route("/classroom-addon")
def classroom_addon():
    return flask.render_template(
        "addon-discovery.html",
        message="You've reached the addon discovery page.")

שימו לב ששני המסלולים מעבירים משתנה message לתבניות Jinja המתאימות. המאפיין הזה שימושי לזיהוי הדף שאליו המשתמש הגיע.

יצירת קובצי תצורה והפעלה

יוצרים את הקבצים main.py ו-config.py בתיקיית השורש של האפליקציה. מגדירים את המפתח הסודי ב-config.py.

import os

class Config(object):
    # Note: A secret key is included in the sample so that it works.
    # If you use this code in your application, replace this with a truly secret
    # key. See https://flask.palletsprojects.com/quickstart/#sessions.
    SECRET_KEY = os.environ.get(
        'SECRET_KEY') or "REPLACE ME - this value is here as a placeholder."

בקובץ main.py, מייבאים את המודול ומפעילים את שרת Flask.

from webapp import app

if __name__ == "__main__":
    # Run the application over HTTPs with a locally stored certificate and key.
    # Defaults to https://localhost:5000.
    app.run(
        host="localhost",
        ssl_context=("localhost.pem", "localhost-key.pem"),
        debug=True)

Node.js

המסלולים רשומים בקובץ app.js באמצעות השורות הבאות.

const websiteRouter = require('./routes/index');
const addonRouter = require('./routes/classroom-addon');

app.use('/', websiteRouter);
app.use('/addon-discovery', addonRouter);

פותחים את /01-basic-app/routes/index.js ובודקים את הקוד. מגיעים למסלול הזה כשמשתמש הקצה מבקר באתר של החברה. המסלול יוצר תגובה באמצעות תבנית Handlebars‏ index ומעביר לתבנית אובייקט נתונים שמכיל את המשתנים title ו-message.

router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'Education Technology',
    message: 'Welcome to our website!'
  });
});

פותחים את המסלול השני /01-basic-app/routes/classroom-addon.js ובודקים את הקוד. המסלול הזה מגיע כשמשתמש הקצה מבקר בתוסף. שימו לב שהמסלול הזה משתמש בתבנית Handlebars‏ discovery ובנוסף בפריסה addon.hbs כדי להציג את הדף באופן שונה מהאתר של החברה.

router.get('/', function (req, res, next) {
  res.render('discovery', {
    layout: 'addon.hbs',
    title: 'Education Technology Classroom add-on',
    message: `Welcome.`
  });
});

Java

בדוגמת הקוד ב-Java נעשה שימוש במודולים כדי לארוז את השלבים של הדרכה המפורטת. מכיוון שזו ההדרכה הראשונה, הקוד נמצא במודול step_01_basic_app. לא צפוי שתטמיעו את הפרויקט באמצעות מודולים. במקום זאת, מומלץ לפתח פרויקט אחד תוך כדי ביצוע כל שלב בהדרכה.

יוצרים בכיתה הבקרה, Controller.java, בפרויקט לדוגמה הזה, כדי להגדיר את נקודות הקצה. בקובץ הזה, מייבאים את ההערה @GetMapping מהתלות spring-boot-starter-web.

import org.springframework.web.bind.annotation.GetMapping;

מוסיפים את ההערה של בקר מסגרת Spring מעל הגדרת הכיתה כדי לציין את מטרת הכיתה.

@org.springframework.stereotype.Controller
public class Controller {

לאחר מכן מטמיעים את שני המסלולים ומסלול נוסף לטיפול בשגיאות.

/** Returns the index page that will be displayed when the add-on opens in a
*   new tab.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the index page template if successful, or the onError method to
*   handle and display the error message.
*/
@GetMapping(value = {"/"})
public String index(Model model) {
  try {
    return "index";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Returns the add-on discovery page that will be displayed when the iframe
*   is first opened in Classroom.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the addon-discovery page.
*/
@GetMapping(value = {"/addon-discovery"})
public String addon_discovery(Model model) {
  try {
    return "addon-discovery";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Handles application errors.
*   @param errorMessage message to be displayed on the error page.
*   @param model the Model interface to pass error information to display on
*   the error page.
*   @return the error page.
*/
@GetMapping(value = {"/error"})
public String onError(String errorMessage, Model model) {
  model.addAttribute("error", errorMessage);
  return "error";
}

בדיקת התוסף

מפעילים את השרת. לאחר מכן, נכנסים ל-Google Classroom בתור אחד ממשתמשי הבדיקה בתפקיד מורה. עוברים לכרטיסייה עבודות ויוצרים מטלה חדשה. בוחרים את התוסף הרצוי מבורר התוספים. ה-iframe נפתח והתוסף טוען את URI להגדרת הקובץ המצורף שציינתם בדף הגדרת האפליקציה של Marketplace SDK.

מעולה! עכשיו אפשר להמשיך לשלב הבא: כניסת משתמשים באמצעות Google SSO.