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

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

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

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

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

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

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

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

Python

בדוגמה שלנו ל-Python נעשה שימוש ב-Flask framework. אפשר להוריד את קוד המקור המלא של כל ההדרכות מהדף Overview (סקירה כללית). הקוד של המדריך הזה נמצא בספרייה /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. אפשר להוריד את קוד המקור המלא של כל ההדרכות מהדף Overview (סקירה כללית).

מתקינים את 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, עוברים אל דף יצירת הפרויקט. אפשר לתת שם כלשהו לפרויקט החדש. לוחצים על יצירה.

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

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

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

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

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

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

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

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

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

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

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

    • ההגדרה 'גלוי לכולם' מיועדת לאפליקציות שיושקו בסופו של דבר למשתמשי קצה. אפליקציה ציבורית חייבת לעבור תהליך אישור לפני שהיא תפורסם למשתמשי הקצה, אבל אתם יכולים לציין משתמשים שיכולים להתקין ולבדוק אותה כטיוטה. זהו מצב לפני הפרסום, שמאפשר לבדוק ולפתח את התוסף לפני ששולחים אותו לאישור.
    • ההגדרה הפרטית מתאימה לפיתוח ולבדיקה פנימיים. רק משתמשים מאותו דומיין שבו נוצר הפרויקט יכולים להתקין אפליקציה פרטית. לכן, צריך להגדיר את החשיפה כ'פרטית' רק אם הפרויקט נוצר בדומיין עם מינוי ל-Google Workspace for Education, אחרת משתמשי הבדיקה לא יוכלו להפעיל תוספים ל-Classroom.
  • אם רוצים להגביל את ההתקנה לאדמינים של הדומיין, מגדירים את Installation Settings לערך 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. יש לספק את הפרטים הבאים:

  • מגדירים את User Type (סוג המשתמש) כ-External (חיצוני). לוחצים על יצירה.
  • בדף הבא, ממלאים את פרטי האפליקציה הנדרשים ואת פרטי הקשר. בקטע 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 שנדרשים לאפליקציה ממשתמשי הקצה.

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

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

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

התקנת התוסף

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

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

הגדרה של אפליקציית אינטרנט בסיסית עם שני מסלולים. בשלבים הבאים במדריך נרחיב את האפליקציה הזו, אז בינתיים פשוט יוצרים דף נחיתה לתוסף /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 יועברו אליה.

פיתוח גרסת build של מודול השרת*

יוצרים את הקובץ __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 ובודקים את הקוד. הנתיב הזה מגיע כשמשתמש הקצה מבקר באתר החברה. המסלול יוצר תגובה באמצעות התבנית index של Handlebars, ומעביר לתבנית אובייקט נתונים שמכיל את המשתנים 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.