זהו המדריך הראשון בסדרת המדריכים בנושא תוספים ל-Classroom.
במדריך הזה נסביר איך להכין את הבסיס לפיתוח אפליקציית אינטרנט ולפרסום שלה כתוסף ל-Classroom. שלבים עתידיים להדרכה הרחבת האפליקציה הזו.
במהלך ההסבר המפורט הזה תבצעו את הפעולות הבאות:
- יוצרים פרויקט חדש ב-Google Cloud עבור התוסף.
- יוצרים אפליקציית אינטרנט בסיסית עם לחצני כניסה למקום.
- פרסום דף מוצר של התוסף ב-Google Workspace Marketplace.
אחרי שמסיימים, אפשר להתקין את התוסף ולטעון אותו ב-iframe של תוספי Classroom.
דרישות מוקדמות
בוחרים שפה כדי לראות את הדרישות המוקדמות המתאימות:
Python
בדוגמה שלנו ל-Python השתמשנו ב-framework של Flask. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא של כל ההדרכות. הקוד של ההדרכה הספציפית הזו נמצא בספרייה /flask/01-basic-app/.
במקרה הצורך, מתקינים את Python 3.7 ואילך ומוודאים ש-pip זמין.
python -m ensurepip --upgradeמומלץ גם להגדיר ולהפעיל סביבה וירטואלית חדשה של Python.
python3 -m venv .classroom-addon-envsource .classroom-addon-env/bin/activate
כל ספריית משנה של הדרכה בדוגמאות שהורדתם מכילה קובץ requirements.txt. אפשר להתקין במהירות את הספריות הנדרשות באמצעות
pip. כדי להתקין את הספריות הנדרשות למדריך הזה, משתמשים בפקודה הבאה.
cd flask/01-basic-apppip install -r requirements.txt
Node.js
בדוגמה שלנו ל-Node.js אנחנו משתמשים ב-framework Express. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא של כל ההדרכות.
אם צריך, מתקינים את NodeJS בגרסה 16.13 ואילך.
מתקינים את מודולי הצומת הנדרשים באמצעות npm.
npm installJava
בדוגמה שלנו ל-Java נעשה שימוש ב-Spring Boot framework. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא של כל ההדרכות.
אם Java 11+ עדיין לא מותקנת במחשב, מתקינים אותה.
אפליקציות Spring Boot יכולות להשתמש ב-Gradle או ב-Maven כדי לטפל בבנייה ולנהל תלויות. הדוגמה הזו כוללת את Maven wrapper, שמאפשר לבצע build בהצלחה בלי להתקין את Maven עצמו.
כדי להריץ את הדוגמה שסיפקנו, מריצים את הפקודות הבאות בספרייה שאליה הורדתם את הפרויקט, כדי לוודא שיש לכם את הדרישות המוקדמות להרצת הפרויקט.
java --version./mvnw --version
או ב-Windows:
java -versionmvnw.cmd --version
הגדרת פרויקט ב-Google Cloud
הגישה ל-Classroom API ולשיטות האימות הנדרשות נשלטת על ידי פרויקטים ב-Google Cloud. בהוראות הבאות מפורטים השלבים המינימליים ליצירה ולהגדרה של פרויקט חדש לשימוש בתוסף.
יצירת הפרויקט
כדי ליצור פרויקט חדש ב-Google Cloud, עוברים אל הדף ליצירת פרויקט. אתם יכולים לתת לפרויקט החדש כל שם שתרצו. לוחצים על יצירה.
יצירת הפרויקט החדש נמשכת כמה רגעים. אחרי שמסיימים, חשוב לבחור את הפרויקט. אפשר לבחור אותו בתפריט הנפתח של בורר הפרויקטים בראש המסך, או ללחוץ על SELECT PROJECT בתפריט ההתראות בפינה השמאלית העליונה.
צירוף ה-SDK של Google Workspace Marketplace לפרויקט ב-Google Cloud
עוברים לדפדפן API Library. חיפוש של
Google Workspace Marketplace SDK. ה-SDK אמור להופיע ברשימת התוצאות.
בוחרים בכרטיס Google Workspace Marketplace SDK ולוחצים על הפעלה.
הגדרת Google Workspace Marketplace SDK
ב-Google Workspace Marketplace יש דף מוצר שדרכו משתמשים ואדמינים יכולים להתקין את התוסף שלכם. כדי להמשיך, צריך להגדיר את הגדרת האפליקציה ואת הכרטיס בחנות ב-Marketplace SDK, ואת מסך ההסכמה ל-OAuth.
הגדרת אפליקציה
עוברים לדף App Configuration (הגדרת האפליקציה) ב-Marketplace SDK. עליך לספק את הפרטים הבאים:
מגדירים את ניראות האפליקציה ל-
Publicאו ל-Private.- ההגדרה 'ציבורית' מיועדת לאפליקציות שבסופו של דבר יופצו למשתמשי קצה. אפליקציה ציבורית צריכה לעבור תהליך אישור לפני שהיא מתפרסמת למשתמשי קצה, אבל אתם יכולים לציין משתמשים שיכולים להתקין אותה ולבדוק אותה כטיוטה. זהו מצב לפני פרסום, שיאפשר לכם לבדוק ולפתח את התוסף לפני שתשלחו אותו לאישור.
- ההגדרה 'פרטי' מתאימה לבדיקות פנימיות ולפיתוח. אפליקציה פרטית יכולה להיות מותקנת רק על ידי משתמשים באותו דומיין שבו הפרויקט נוצר. לכן, צריך להגדיר את סטטוס החשיפה כפרטי רק אם הפרויקט נוצר בדומיין עם מינוי ל-Google Workspace for Education, אחרת משתמשי הבדיקה לא יוכלו להפעיל תוספים ל-Classroom.
אם רוצים להגביל את ההתקנה לאדמינים של הדומיין, מגדירים את הגדרות ההתקנה לערך
Admin Only install.בקטע App Integration (שילוב אפליקציות), בוחרים באפשרות Classroom add-on (תוסף ל-Classroom). תתבקשו להזין את ה-URI של הגדרת הקובץ המצורף מאובטח. זו כתובת ה-URL שאתם מצפים שתיטען כשמשתמש יפתח את התוסף. לצורך ההסבר המפורט הזה, צריך להגדיר את הערך הזה ל-
https://<your domain>/addon-discovery.ההגדרה Allowed Attachment URI Prefixes משמשת לאימות כתובות ה-URI שמוגדרות ב-
AddOnAttachmentבאמצעות השיטותcourses.*.addOnAttachments.createו-courses.*.addOnAttachments.patch. האימות הוא התאמה מדויקת של מחרוזת קידומת, ובשלב הזה אי אפשר להשתמש בתווים כלליים. מוסיפים לפחות את דומיין הבסיס של שרת התוכן, כמוhttps://localhost:5000/אוhttps://cdn.myedtech.com/.מוסיפים את אותם היקפי הרשאות של OAuth שמופיעים במסך ההסכמה ל-OAuth בשלב הקודם.
ממלאים את השדות בהתאם לארגון בקטע Developer Links (קישורים למפתחים).
רישום חנות
עוברים לדף Store Listing (דף העסק בחנות) של Marketplace SDK. עליך לספק את הפרטים הבאים:
- בקטע App Details, מוסיפים שפה או מרחיבים את התפריט הנפתח לצד השפה שכבר מופיעה. מזינים שם ותיאורים לאפליקציה. הם יופיעו בדף של התוסף ב-Google Workspace Marketplace. לוחצים על סיום כדי לשמור.
- בוחרים קטגוריה לתוסף.
- בקטע נכסי גרפיקה, מספקים תמונות בשדות החובה. אפשר לשנות את ההגדרות האלה מאוחר יותר, ואפשר להשתמש בהן כרגע כמשתני placeholder.
- בקטע קישורי תמיכה, מזינים את כתובות ה-URL הנדרשות. אפשר להשתמש במחזיקי מקום אם הגדרתם את חשיפת האפליקציה כפרטית בשלב הקודם.
אם בשלב הקודם הגדרתם את הרשאות הגישה לאפליקציה כפרטיות, לוחצים על פרסום והאפליקציה תהיה זמינה להתקנה באופן מיידי. אם הגדרתם את חשיפת האפליקציה לציבורית, מוסיפים כתובות אימייל באזור בודקי הטיוטה של כל משתמש שרוצים שיבדוק את האפליקציה, ולוחצים על שמירת הטיוטה.
מסך הסכמה ל-OAuth
מסך ההסכמה של OAuth מופיע כשמשתמשים מאשרים את האפליקציה שלכם בפעם הראשונה. במסך מוצגת בקשה לאפשר לאפליקציה לגשת למידע האישי ולפרטי החשבון שלהם, בהתאם להיקפי ההרשאות שהפעלתם.
עוברים לדף היצירה של מסך ההסכמה של OAuth. עליך לספק את הפרטים הבאים:
- מגדירים את סוג המשתמש בתור חיצוני. לוחצים על יצירה.
- בדף הבא, ממלאים את פרטי האפליקציה הנדרשים ואת פרטי יצירת הקשר. מזינים את הדומיינים שבהם מתארחת האפליקציה בקטע דומיינים מורשים. לוחצים על שמירה והמשך.
מוסיפים את היקפי ההרשאות של 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.teacherhttps://www.googleapis.com/auth/classroom.addons.student
צריך לכלול גם היקפי הרשאות של Google API אחרים שהאפליקציה דורשת ממשתמשי קצה.
לוחצים על שמור והמשך.
בדף משתמשי בדיקה מופיעה רשימה של כתובות האימייל של חשבונות בדיקה. לוחצים על שמירה והמשך.
מוודאים שההגדרות נכונות וחוזרים ללוח הבקרה.
התקנת התוסף
עכשיו אפשר להתקין את התוסף באמצעות הקישור שמופיע בחלק העליון של הדף Store Listing (דף האפליקציה בחנות) ב-Marketplace SDK. לוחצים על הצגה ב-Marketplace בחלק העליון של הדף כדי לראות את רשימת האפליקציות, ואז בוחרים באפשרות התקנה.
פיתוח אפליקציית אינטרנט בסיסית
הגדרת אפליקציית אינטרנט בסיסית עם שני נתיבים. השלבים הבאים במדריך הזה ירחיבו את האפליקציה הזו, אז בינתיים רק תיצור דף נחיתה לתוסף /addon-discovery ודף אינדקס לדוגמה / בשביל 'האתר של החברה'.

מטמיעים את שתי נקודות הקצה האלה:
-
/: מוצגת הודעת פתיחה ולחצן לסגירת הכרטיסייה הנוכחית ומסגרת ה-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 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 ובודקים את הקוד. הניתוב הזה מתבצע כשמשתמש הקצה מבקר בתוסף. שימו לב שהנתיב הזה משתמש בתבנית discovery Handlebars ובפריסת 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 מעל הגדרת המחלקה כדי לציין את מטרת המחלקה.
@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 של הגדרת הקובץ המצורף שציינתם בדף App Configuration (הגדרת האפליקציה) ב-Marketplace SDK.
מעולה! אפשר להמשיך לשלב הבא: כניסת משתמשים באמצעות SSO של Google.