إنشاء إضافة Classroom

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

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

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

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

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

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

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

Python

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

إذا لزم الأمر، ثبِّت الإصدار 3.7 أو الإصدارات الأحدث من Python وتأكّد من توفّر 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 إطار العمل سريع. يمكنك تنزيل رمز المصدر الكامل لجميع الجولات التفصيلية من صفحة "نظرة عامة".

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

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

npm install

Java

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

تثبيت Java 11+ إذا لم يكن مثبّتًا على جهازك

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

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

java --version
./mvnw --version

أو على Windows:

java -version
mvnw.cmd --version

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

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

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

يمكنك إنشاء مشروع جديد على 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 البيانات التي يمكن للمستخدمين والمشرفين تثبيت الإضافة من خلالها. اضبط إعدادات التطبيق وقائمة بيانات المتجر في حزمة تطوير البرامج (SDK) في Marketplace وشاشة موافقة OAuth للمتابعة.

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

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

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

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

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

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

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

  • ضمن تفاصيل التطبيق، أضِف لغة أو وسِّع القائمة المنسدلة بجانب اللغة التي سبق أن أدرجتها. قدِّم "اسم تطبيق" وأوصافًا، وستظهر هذه في صفحة بطاقة بيانات المتجر الخاصة بإضافتك على 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 API أخرى يطلبها تطبيقك من المستخدمين النهائيين.

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

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

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

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

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

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

لأغراض هذا المثال، يجب إنشاء بنية منطق التطبيق كوحدة بايثون. هذا هو الدليل 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) لإعداد مُرفَقات الذي حدّدته في صفحة إعداد التطبيق في حزمة تطوير البرامج (SDK) الخاصة بالسوق.

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