สร้างส่วนเสริมของ Classroom

นี่เป็นคำแนะนำแรกในคำแนะนำแบบทีละขั้นเกี่ยวกับส่วนเสริมของ Classroom

ในคำแนะนำแบบทีละขั้นนี้ คุณได้วางรากฐานในการพัฒนาเว็บแอปพลิเคชันและเผยแพร่เป็นส่วนเสริมของ Classroom ขั้นตอนคำแนะนำแบบทีละขั้น ในอนาคตจะขยายแอปนี้

ระหว่างคำแนะนำแบบทีละขั้นนี้ คุณได้ทำตามขั้นตอนต่อไปนี้

  • สร้างโปรเจ็กต์ Google Cloud ใหม่สำหรับเว็บแอป
  • สร้างเว็บแอป Skeleton ที่มีปุ่มลงชื่อเข้าใช้ตัวยึดตำแหน่ง
  • เผยแพร่ข้อมูลผลิตภัณฑ์ใน Store ส่วนตัวของ Google Workspace Marketplace (GWM) สำหรับเว็บแอป

เมื่อเสร็จแล้ว คุณจะติดตั้งส่วนเสริมและโหลดใน 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 ใช้ตัวกรองต่อไปนี้เพื่อติดตั้งไลบรารีที่จำเป็นสำหรับคำแนะนำแบบทีละขั้นนี้

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 เพื่อจัดการบิลด์และจัดการทรัพยากร Dependency ได้ ตัวอย่างนี้มี Maven Wrapper ที่ช่วยให้มั่นใจได้ว่าบิลด์จะประสบความสำเร็จโดยที่คุณไม่ต้องติดตั้ง Maven

เพื่อให้เรียกใช้ตัวอย่างที่เราให้ไว้ได้ ให้เรียกใช้คำสั่งต่อไปนี้ในไดเรกทอรีที่คุณดาวน์โหลดโปรเจ็กต์เพื่อให้แน่ใจว่าคุณมีข้อกำหนดเบื้องต้นในการเรียกใช้โปรเจ็กต์

java --version
./mvnw --version

หรือบน Windows:

java -version
mvnw.cmd --version

ตั้งค่าโปรเจ็กต์ Google Cloud

โปรเจ็กต์ Google Cloud จะควบคุมสิทธิ์เข้าถึง Classroom API และวิธีการตรวจสอบสิทธิ์ที่จำเป็น วิธีการต่อไปนี้จะแนะนำขั้นตอนขั้นต่ำในการสร้างและกำหนดค่าโปรเจ็กต์ใหม่เพื่อใช้กับส่วนเสริม

สร้างโปรเจ็กต์

สร้างโปรเจ็กต์ Google Cloud ใหม่โดยไปที่หน้าการสร้างโปรเจ็กต์ คุณระบุชื่อให้กับโปรเจ็กต์ใหม่ได้ คลิก Create

ระบบจะใช้เวลาสักครู่ในการสร้างโปรเจ็กต์ใหม่ให้เสร็จสมบูรณ์ เมื่อทำเสร็จแล้ว อย่าลืมเลือกโปรเจ็กต์ โดยจะเลือกได้ในเมนูแบบเลื่อนลงสำหรับตัวเลือกโปรเจ็กต์ที่ด้านบนของหน้าจอ หรือคลิกเลือกโปรเจ็กต์ในเมนูการแจ้งเตือนที่ด้านขวาบน

เลือกโปรเจ็กต์ในคอนโซล Google Cloud

แนบ GWM SDK กับโปรเจ็กต์ Google Cloud

ไปที่เบราว์เซอร์ไลบรารี API ค้นหา Google Workspace Marketplace SDK คุณควรจะเห็น SDK ปรากฏในรายการผลการค้นหา

การ์ด Google Workspace Marketplace SDK

เลือกการ์ด SDK ของ Google Workspace Marketplace แล้วคลิกเปิดใช้

กำหนดค่า GWM SDK

GWM จะให้ข้อมูลที่ผู้ใช้และผู้ดูแลระบบติดตั้งส่วนเสริมของคุณ กำหนดค่าหน้าจอคำยินยอม OAuth และการกำหนดค่าแอปและข้อมูลผลิตภัณฑ์ใน Store ของ GWM SDK เพื่อดำเนินการต่อ

หน้าจอความยินยอมของ OAuth จะปรากฏขึ้นเมื่อผู้ใช้ให้สิทธิ์แอปของคุณเป็นครั้งแรก และจะแจ้งให้ผู้ใช้อนุญาตให้แอปเข้าถึงข้อมูลส่วนตัวและบัญชีของตนตามที่ขอบเขตที่คุณเปิดใช้

ไปที่หน้าการสร้างหน้าจอขอความยินยอม OAuth ระบุข้อมูลต่อไปนี้

  • ตั้งค่าประเภทผู้ใช้เป็นภายนอก คลิก Create
  • ในหน้าถัดไปให้กรอกรายละเอียดแอปที่จำเป็นและข้อมูลติดต่อ ระบุโดเมนที่โฮสต์แอปของคุณในส่วนโดเมนที่ได้รับอนุญาต คลิกบันทึกและต่อไป
  • เพิ่มขอบเขต OAuth ที่เว็บแอปต้องการ โปรดดูคู่มือการกำหนดค่า OAuth เพื่อดูการพูดคุยอย่างเจาะลึกเกี่ยวกับขอบเขตและวัตถุประสงค์

    คุณต้องขอขอบเขตต่อไปนี้อย่างน้อย 1 รายการเพื่อให้ 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 อื่นๆ ที่แอปต้องใช้จากผู้ใช้ปลายทาง

    คลิกบันทึกและต่อไป

  • ระบุอีเมลของบัญชีทดสอบในหน้าผู้ใช้ทดสอบ คลิกบันทึกและต่อไป

ตรวจสอบว่าการตั้งค่าถูกต้อง แล้วกลับไปที่หน้าแดชบอร์ด

การกำหนดค่าแอป

ไปที่หน้าการกำหนดค่าแอปของ GWM SDK ระบุข้อมูลต่อไปนี้

  • ตั้งค่าระดับการเข้าถึงแอปเป็น Private การตั้งค่านี้เหมาะสำหรับวัตถุประสงค์ด้านการทดสอบและการพัฒนา และเป็นตัวเลือกที่เหมาะสมสำหรับคำแนะนำแบบทีละขั้นเหล่านี้ เลือก Public เมื่อคุณพร้อมให้บุคคลทั่วไปใช้ส่วนเสริมเท่านั้น

  • ตั้งค่าการตั้งค่าการติดตั้งเป็น Admin Only install หากคุณต้องการจำกัดการติดตั้งให้เฉพาะผู้ดูแลระบบโดเมนเท่านั้น

  • ในส่วนการผสานรวมแอป ให้เลือกส่วนเสริมของ Classroom ระบบจะแจ้งให้คุณป้อน URI การตั้งค่าไฟล์แนบที่ปลอดภัย ซึ่งเป็น URL ที่คุณคาดว่าจะโหลดเมื่อผู้ใช้เปิดส่วนเสริมของคุณ สำหรับจุดประสงค์ของคำแนะนำแบบทีละขั้นนี้ ค่านี้ควรเป็น https://<your domain>/addon-discovery

  • คำนำหน้า URI ของไฟล์แนบที่อนุญาตใช้เพื่อตรวจสอบ URI ที่ตั้งค่าไว้ใน AddOnAttachment โดยใช้เมธอด courses.*.addOnAttachments.create และ courses.*.addOnAttachments.patch การตรวจสอบความถูกต้องจะเป็นการจับคู่คำนำหน้าตามตัวอักษร และไม่อนุญาตให้ใช้ไวลด์การ์ดในขณะนี้ ตอนนี้คุณเว้นส่วนนี้ให้ว่างไว้ได้

  • เพิ่มขอบเขต OAuth เดียวกันกับที่มีให้ในหน้าจอขอความยินยอม OAuth ในขั้นตอนก่อนหน้า

  • กรอกข้อมูลในช่องต่างๆ ตามความเหมาะสมสำหรับองค์กรในส่วนลิงก์ของนักพัฒนาซอฟต์แวร์

ข้อมูลผลิตภัณฑ์ใน Store

ไปที่หน้าข้อมูลผลิตภัณฑ์ใน Store ของ GWM SDK ระบุข้อมูลต่อไปนี้

  • ในส่วนรายละเอียดแอป ให้เพิ่มภาษาหรือขยายเมนูแบบเลื่อนลงถัดจากภาษาที่อยู่ในรายการ ระบุชื่อแอปพลิเคชันและคำอธิบาย โดยชื่อเหล่านี้จะแสดงในหน้าข้อมูลผลิตภัณฑ์ใน Store ของ GWM ของส่วนเสริม คลิกเสร็จสิ้นเพื่อบันทึก
  • เลือกหมวดหมู่สำหรับส่วนเสริม
  • ในส่วนเนื้อหากราฟิก ให้ระบุรูปภาพสำหรับช่องที่ต้องกรอก คุณเปลี่ยนแปลงการตั้งค่าเหล่านี้ได้ในภายหลัง และเป็นตัวยึดตำแหน่งได้ หากคุณตั้งค่าระดับการเข้าถึงแอปเป็นส่วนตัวในขั้นตอนก่อนหน้า
  • ในส่วนลิงก์การสนับสนุน ให้ระบุ URL ที่ขอ ซึ่งอาจเป็นตัวยึดตำแหน่งหากคุณตั้งค่าระดับการเข้าถึงแอปเป็นส่วนตัวในขั้นตอนก่อนหน้า

คลิกเผยแพร่เพื่อบันทึกการตั้งค่า หากคุณตั้งค่าระดับการเข้าถึงแอปเป็นส่วนตัวในขั้นตอนก่อนหน้า แอปจะพร้อมติดตั้งทันที หากคุณตั้งค่าระดับการเข้าถึงแอปเป็นสาธารณะ แอปของคุณจะส่งไปให้ทีม GWM ตรวจสอบก่อนที่จะพร้อมให้ติดตั้ง

ติดตั้งส่วนเสริม

ตอนนี้คุณติดตั้งส่วนเสริมโดยใช้ลิงก์ที่ด้านบนของหน้าข้อมูลผลิตภัณฑ์ใน Store ของ GWM SDK ได้แล้ว คลิก URL ของแอปที่ด้านบนของหน้าเพื่อดูข้อมูล จากนั้นเลือกติดตั้ง

สร้างเว็บแอปพื้นฐาน

ตั้งค่าเว็บแอปพลิเคชันสำหรับสร้างโครงสร้างที่มี 2 เส้นทาง ขั้นตอนคำแนะนำแบบทีละขั้นในอนาคตจะขยายแอปพลิเคชันนี้ ดังนั้นให้สร้างหน้า Landing Page สำหรับส่วนเสริม /addon-discovery และหน้าดัชนีจำลอง / สำหรับ "เว็บไซต์บริษัท" ของเรา

ตัวอย่างเว็บแอปใน iframe

ใช้ปลายทาง 2 จุดนี้

  • /: แสดงข้อความต้อนรับและปุ่มปิดทั้งแท็บปัจจุบันและ iframe ของส่วนเสริม
  • /addon-discovery: แสดงข้อความต้อนรับและปุ่ม 2 ปุ่ม โดยปุ่มหนึ่งสำหรับปิด iframe ของส่วนเสริมและอีกปุ่มหนึ่งสำหรับเปิดเว็บไซต์ในแท็บใหม่

โปรดทราบว่าเรากำลังเพิ่มปุ่มเพื่อสร้างและปิดหน้าต่างหรือ iframe วิธีนี้จะสาธิตวิธีการนำผู้ใช้ไปยังแท็บใหม่อย่างปลอดภัย เพื่อขออนุญาตในคำแนะนำแบบทีละขั้น

สร้างสคริปต์ยูทิลิตี

สร้างไดเรกทอรี static/scripts สร้างไฟล์ใหม่ addon-utils.js เพิ่ม ฟังก์ชัน 2 อย่างต่อไปนี้

/**
 *   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

ตั้งค่าไดเรกทอรีของแอปพลิเคชัน

สำหรับวัตถุประสงค์ของตัวอย่างนี้ ให้จัดโครงสร้างตรรกะของแอปพลิเคชันเป็นโมดูล 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 ในตัวอย่างที่เราให้ไว้ ใช้ 2 เส้นทางในไฟล์นี้

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.")

โปรดทราบว่าเส้นทางของเราทั้ง 2 เส้นทางส่งตัวแปร 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!'
  });
});

เปิดเส้นทางที่ 2 /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 จากทรัพยากร Dependency spring-boot-starter-web

import org.springframework.web.bind.annotation.GetMapping;

ใส่คำอธิบายประกอบตัวควบคุมเฟรมเวิร์ก Spring ไว้เหนือคำจำกัดความคลาสเพื่อระบุวัตถุประสงค์ของคลาส

@org.springframework.stereotype.Controller
public class Controller {

จากนั้นให้ใช้ทั้ง 2 เส้นทางและเส้นทางเพิ่มเติมเพื่อจัดการข้อผิดพลาด

/** 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 ในฐานะผู้ใช้ทดสอบ Teacher ไปที่แท็บงานของชั้นเรียน แล้วสร้างงานใหม่ คลิกปุ่มส่วนเสริมใต้พื้นที่ข้อความ แล้วเลือกส่วนเสริม iframe จะเปิดขึ้นและส่วนเสริมจะโหลด URI การตั้งค่าไฟล์แนบที่คุณระบุในหน้าการกำหนดค่าแอปของ GWM SDK

ยินดีด้วย คุณก็พร้อมดำเนินการขั้นตอนถัดไปได้แล้ว ซึ่งก็คือการลงชื่อเข้าใช้ผู้ใช้ด้วย SSO ของ Google