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

אם יש צורך, מתקינים את NodeJS v16.13+.

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

npm install

Java

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

מתקינים את Java 11+ אם הוא עדיין לא מותקן במחשב שלכם.

אפליקציות Springboo יכולות להשתמש ב-Gradle או ב-Maven כדי לטפל בגרסאות build ולנהל את יחסי התלות. הדוגמה הזו כוללת את ה-wrapper של Maven, שמבטיח שה-build יהיה תקין, בלי שתצטרכו להתקין את Maven עצמו.

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

java --version
./mvnw --version

או ב-Windows:

java -version
mvnw.cmd --version

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

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

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

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

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

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

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

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

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

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

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

דף האפליקציה שדרכו אדמינים ומשתמשים מתקינים את התוסף Google Workspace Marketplace. כדי להמשיך, מגדירים את App Configuration (הגדרת האפליקציה) ו-Store Listing של Marketplace SDK, ואת OAuth Consent Screen.

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

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

  • מגדירים את הרשאות גישה לאפליקציה לערך 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. האימות הוא התאמה מילולית לקידומת של מחרוזת, והוא לא מאפשר שימוש בתווים כלליים לחיפוש בשלב הזה. צריך להוסיף לפחות את הדומיין הבסיסי (root) של שרת התוכן, כמו https://localhost:5000/ או https://cdn.myedtech.com/.

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

  • ממלאים את השדות בהתאם לארגון בקטע קישורים למפתחים.

רישום חנות

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

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

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

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

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

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

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

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

@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.

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