إنشاء إضافة Classroom

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

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

خلال هذه الجولة الإرشادية، يمكنك إكمال ما يلي:

  • أنشئ مشروعًا جديدًا في Google Cloud لإضافة الميزة.
  • أنشئ إطارًا أساسيًا لتطبيق ويب يتضمّن أزرار علامة نائبة لتسجيل الدخول.
  • انشر بطاقة بيانات المتجر الخاصة بإضافة Google Workspace Marketplace.

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

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

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

Python

يستخدم مثال Python إطار عمل Flask. يمكنك تنزيل رمز المصدر الكامل لجميع الخطوات الإرشادية من صفحة "نظرة عامة". يمكن العثور على رمز هذه الخطوة المتعلّقة بالشرح في الدليل /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. اتّبِع الخطوات التالية لتثبيت المكتبات المطلوبة لهذا ال walkthrough.

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

Node.js

يستخدم مثال Node.js إطار عمل Express. يمكنك تنزيل رمز المصدر الكامل لجميع الخطوات الإرشادية من صفحة "نظرة عامة".

ثبِّت الإصدار 16.13 من NodeJS أو الإصدارات الأحدث إذا لزم الأمر.

ثبِّت وحدات العقدة المطلوبة باستخدام 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) في Google Workspace Marketplace بمشروع Google Cloud

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

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

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

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

يوفّر Google Workspace Marketplace بيانات المنتج التي يتم من خلالها تثبيت إضافتك من قِبل المستخدمين والمشرفين. عليك ضبط إعدادات التطبيق وبطاقة بيانات المتجر وشاشة طلب الموافقة المتعلّقة ببروتوكول OAuth في حزمة تطوير البرامج (SDK) لسوق التطبيقات لمتابعة الخطوات.

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

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

  • اضبط مستوى ظهور التطبيق على Public أو Private.

    • يُستخدَم الإعداد "متاح للجميع" للتطبيقات التي سيتم إصدارها في نهاية المطاف للمستخدمين النهائيين. يجب أن يخضع التطبيق العلني لعملية موافقة قبل أن يتم نشره للمستخدمين النهائيين، ولكن يمكنك تحديد المستخدمين الذين يمكنهم تثبيته واختباره كـ مسودة. هذه حالة ما قبل النشر تسمح لك باختبار إضافتك وتطويرها قبل إرسالها للحصول على الموافقة.
    • يكون الإعداد الخاص مناسبًا للاختبار والتطوير الداخليَين. لا يمكن تثبيت تطبيق خاص إلا من قِبل المستخدمين في النطاق نفسه الذي تم فيه إنشاء المشروع. لذلك، يجب ضبط مستوى العرض على "خاص" فقط إذا تم إنشاء المشروع في نطاق لديه اشتراك في Google Workspace for Education، وإلا لن يتمكّن المستخدمون التجريبيون من تشغيل تطبيقات Chrome الملحقة 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 (روابط المطوّرين).

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

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

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

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

تظهر شاشة طلب الموافقة على 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 يطلبها تطبيقك من المستخدمين النهائيين.

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

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

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

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

يمكنك الآن تثبيت الإضافة باستخدام الرابط في أعلى صفحة بطاقة بيانات المتجر الخاصة بحزمة SDK في Marketplace. انقر على App 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 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 فوق تعريف الفئة للإشارة إلى الغرض من الفئة.

@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 وتحمِّل الإضافة عنوان URL لإعداد المرفق الذي حدّدته في صفحة إعداد التطبيق ضمن حزمة تطوير البرامج (SDK) في Marketplace.

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