إنشاء إضافة Classroom

هذه هي الجولة التفصيلية الأولى ضمن سلسلة التعليمات الإضافية في Classroom.

في هذه الجولة التفصيلية، تضع الأساس لتطوير تطبيق ويب ونشره كإضافة في Classroom. تعمل الخطوات التفصيلية المستقبلية على توسيع هذا التطبيق.

خلال هذه الجولة التفصيلية، تكمل ما يلي:

  • أنشِئ مشروعًا جديدًا على Google Cloud لتطبيق الويب.
  • يمكنك إنشاء هيكل رئيسي لتطبيق ويب باستخدام أزرار تسجيل الدخول النائبة.
  • انشر بطاقة بيانات متجر خاصة على Google Workspace Marketplace (GWM) لتطبيق الويب الخاص بك.

بعد الانتهاء، يمكنك تثبيت الإضافة وتحميلها في إطار iframe لإضافات Classroom.

المتطلبات الأساسية

اختَر إحدى اللغات أدناه للاطّلاع على المتطلبات الأساسية المناسبة:

Python

يستخدم مثال بايثون إطار عمل فلاسك. يمكنك تنزيل رمز المصدر الكامل لجميع الجولات التفصيلية من صفحة "نظرة عامة". يمكن العثور على رمز هذه الجولة التفصيلية في دليل /flask/01-basic-app/.

إذا لزم الأمر، ثبّت Python 3.7 أو أحدث وتأكد من توفّر pip.

python -m ensurepip --upgrade

ننصحك أيضًا بإعداد بيئة افتراضية جديدة بلغة بايثون وتفعيلها.

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 v16.13+.

ثبِّت وحدات العُقد المطلوبة باستخدام npm.

npm install

Java

يستخدم مثال Java إطار عمل Spring Boot. يمكنك تنزيل رمز المصدر الكامل لجميع الجولات التفصيلية من صفحة "نظرة عامة".

ثبّت Java 11 أو إصدارًا أحدث إذا لم يكن مثبّتًا على جهازك.

يمكن لتطبيقات Spring Boot استخدام Gradle أو Maven لمعالجة الإصدارات وإدارة التبعيات. يشمل هذا المثال برنامج تضمين Maven الذي يضمن تصميمًا ناجحًا بدون الحاجة إلى تثبيت Maven نفسه.

لكي تتمكن من تشغيل المثال المقدم، قم بتشغيل الأوامر التالية في الدليل الذي قمت فيه بتنزيل المشروع للتأكد من أن لديك المتطلبات الأساسية لتشغيل المشروع.

java --version
./mvnw --version

أو على Windows:

java -version
mvnw.cmd --version

إعداد مشروع على Google Cloud

تتحكم مشاريع Google Cloud في إمكانية الوصول إلى واجهة برمجة التطبيقات Classroom API وطرق المصادقة المطلوبة. تقودك الإرشادات التالية خلال الحد الأدنى من الخطوات لإنشاء وتكوين مشروع جديد لاستخدامه مع الإضافتك.

إنشاء المشروع

أنشِئ مشروعًا جديدًا على Google Cloud من خلال الانتقال إلى صفحة إنشاء المشروع. يمكنك إدخال أي اسم للمشروع الجديد. انقر على إنشاء.

يستغرق إنشاء المشروع الجديد بالكامل بضع لحظات. بعد الانتهاء من ذلك، تأكد من تحديد المشروع؛ يمكنك اختياره في القائمة المنسدلة لأداة اختيار المشروع في أعلى الشاشة، أو النقر على اختيار المشروع في قائمة الإشعارات في أعلى يسار الشاشة.

حدد المشروع في وحدة تحكم
Google Cloud

إرفاق حزمة تطوير البرامج (SDK) لأداة GWM بمشروع Google Cloud

انتقِل إلى متصفِّح مكتبة واجهة برمجة التطبيقات. ابحث عن Google Workspace Marketplace SDK. من المفترض أن تظهر حزمة SDK في قائمة النتائج.

تتيح بطاقة حزمة تطوير البرامج
(SDK) في Google Workspace Marketplace

اختَر بطاقة حزمة تطوير البرامج (SDK) لـ Google Workspace Marketplace، ثم انقر على تفعيل.

ضبط حزمة تطوير البرامج (SDK) الخاصة بأداة GWM

توفّر أداة GWM بطاقة بيانات يمكن للمستخدمين والمشرفين تثبيت الإضافة من خلالها. عليك ضبط شاشة موافقة OAuth وإعدادات التطبيق وبطاقة بيانات المتجر في GWM SDK للمتابعة.

تظهر شاشة موافقة 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.teacher
    • https://www.googleapis.com/auth/classroom.addons.student

    يمكنك أيضًا تضمين أي نطاقات أخرى لواجهة Google API يتطلبها تطبيقك من المستخدمين النهائيين.

    انقر على حفظ ومتابعة.

  • أدرِج عناوين البريد الإلكتروني لأي حسابات اختبار في صفحة المستخدمون التجريبيون. انقر على حفظ ومتابعة.

تأكد من صحة إعداداتك، ثم ارجع إلى لوحة التحكم.

إعدادات التطبيق

انتقِل إلى صفحة إعدادات التطبيق في حزمة تطوير البرامج (SDK) لأداة GWM. قدِّم المعلومات التالية:

  • اضبط مستوى رؤية التطبيق على Private. هذا الإعداد مناسب لأغراض الاختبار والتطوير، وهو الخيار المناسب لهذه الجولات التفصيلية. اختَر "Public" فقط إذا كنت جاهزًا لاستخدام الإضافة من قِبل الجمهور العام.

  • يمكنك ضبط إعدادات التثبيت على Admin Only install إذا أردت قصر التثبيت على مشرفي النطاق.

  • ضمن دمج التطبيقات، اختَر إضافة Classroom. سيُطلب منك إدخال معرّف الموارد المنتظم (URI) لإعداد المرفقات الآمن، وهو عنوان URL الذي تتوقّع أن يتم تحميله عندما يفتح المستخدم الإضافة. لأغراض هذه الجولة التفصيلية، يجب أن يكون هذا https://<your domain>/addon-discovery.

  • تُستخدَم بادئات معرِّف الموارد المنتظم (URI) للمرفقات المسموح بها للتحقّق من صحة عناوين URL التي تم ضبطها في AddOnAttachment باستخدام الطريقتَين courses.*.addOnAttachments.create وcourses.*.addOnAttachments.patch. ويعمل التحقق من الصحة على مطابقة بادئة السلسلة الحرفية، ولا يسمح باستخدام أحرف البدل في الوقت الحالي. يمكنك تركها فارغة في الوقت الحالي.

  • أضِف نطاقات OAuth نفسها كما هو موضَّح في شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth في الخطوة السابقة.

  • أكمِل الحقول المناسبة لمؤسستك ضمن روابط المطوّرين.

بطاقة بيانات المتجر

انتقِل إلى صفحة بطاقة بيانات المتجر في حزمة تطوير البرامج (SDK) لأداة GWM. قدِّم المعلومات التالية:

  • ضمن تفاصيل التطبيق، أضِف لغة أو وسِّع القائمة المنسدلة إلى جانب اللغة المدرَجة من قبل. أدخِل اسم التطبيق والأوصاف، والتي تظهر في صفحة بطاقة بيانات المتجر الإضافية ضمن Google Workspace. انقر على تم للحفظ.
  • اختَر فئة لإضافتك.
  • ضمن أصول الرسومات، أدخِل صورًا للحقول المطلوبة. ويمكن تغييرها لاحقًا، ويمكن أن تكون عناصر نائبة في حال ضبط مستوى رؤية التطبيق على خاص في الخطوة السابقة.
  • ضمن روابط الدعم، قدِّم عناوين URL المطلوبة. ويمكن أن تكون هذه عناصر نائبة في حال ضبط إذن الوصول إلى التطبيق على خاص في الخطوة السابقة.

انقر على نشر لحفظ الإعدادات. في حال ضبط مستوى رؤية التطبيق على خاص في الخطوة السابقة، سيصبح تطبيقك متاحًا للتثبيت على الفور. في حال ضبط إعداد مستوى رؤية التطبيق على متاح للجميع، يتم إرسال تطبيقك ليراجعه فريق GWM قبل أن يصبح متاحًا للتثبيت.

تثبيت الإضافة

يمكنك الآن تثبيت الإضافة باستخدام الرابط في أعلى صفحة بطاقة بيانات المتجر على حزمة تطوير البرامج (SDK) لأداة GWM. انقر على عنوان 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 above, 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

إعداد دليل التطبيقات

لأغراض هذا المثال، قم بهيكلة منطق التطبيق كوحدة بايثون. هذا هو دليل 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 أعلى تعريف الفئة للإشارة إلى الغرض من الفئة.

@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) لإعداد المرفقات الذي حددته في صفحة إعدادات التطبيق لحزمة GWM SDK.

تهانينا أنت جاهز للمتابعة إلى الخطوة التالية: تسجيل دخول المستخدمين باستخدام الدخول المُوحَّد (SSO) من Google.