Anexos de tipo de conteúdo

Este é o quarto tutorial sobre os complementos do Google Sala de Aula série de tutoriais.

Neste tutorial, você vai interagir com a API Google Classroom para criar anexos. Você fornece rotas para os usuários visualizarem o conteúdo do anexo. O diferentes dependendo do papel do usuário na classe. Este tutorial abrange anexos do tipo conteúdo, que não precisam do envio do estudante.

Neste tutorial, você vai:

  • Recupere e use os seguintes parâmetros de consulta de complementos:
    • addOnToken: um token de autorização transmitido para a descoberta de anexo Visualizar.
    • itemId: um identificador exclusivo para os itens CourseWork, CourseWorkMaterial ou: Anúncio que recebe o anexo de complemento.
    • itemType: "courseWork", "courseWorkMaterials" ou "aviso".
    • courseId: um identificador exclusivo do curso do Google Sala de Aula de qual a atribuição está sendo criada.
    • attachmentId: um identificador exclusivo atribuído pelo Google Sala de Aula a uma anexo de complemento após a criação.
  • Implementar armazenamento permanente para anexos do tipo conteúdo.
  • Forneça rotas para criar anexos e exibir a visualização de professor e Iframes da visualização do estudante.
  • Faça as seguintes solicitações para a API de complementos do Google Sala de Aula:
    • Crie um novo anexo.
    • Confira o contexto do complemento, que identifica se o usuário conectado é um aluno ou professor.

Depois de terminar, você pode criar anexos do tipo conteúdo em tarefas por meio do na interface do Google Sala de Aula após fazer login como professor. Professores e estudantes em e a turma também pode acessar o conteúdo.

Ativar a API Classroom

Faça chamadas para a API Classroom a partir desta etapa. A API precisa ser ativada no projeto do Google Cloud antes de poder fazer chamadas para ele. Navegação à entrada da biblioteca da API Google Classroom e selecione Ativar.

Processar os parâmetros de consulta da visualização de descoberta de anexos

Como já foi discutido, o Google Sala de Aula transmite parâmetros de consulta quando ao carregar a visualização de descoberta de anexos no iframe:

  • courseId: o ID do curso atual do Google Sala de Aula.
  • itemId: um identificador exclusivo para os itens CourseWork, CourseWorkMaterial ou: Anúncio que recebe o anexo de complemento.
  • itemType: "courseWork", "courseWorkMaterials" ou "comunicado".
  • addOnToken: um token usado para autorizar determinados Ações dos complementos do Google Sala de Aula.
  • login_hint: o ID do Google do usuário atual.

Este tutorial aborda courseId, itemId, itemType e addOnToken. Retenha e transmita esses valores ao emitir chamadas para a API Classroom.

Como na etapa anterior do tutorial, armazene os valores de parâmetro de consulta transmitidos em nossa sessão. É importante que façamos isso quando a visualização de descoberta de anexos for porque essa é a única oportunidade para o Google Sala de Aula transmitir esses parâmetros de consulta.

Python

Acesse o arquivo do servidor Flask que fornece rotas para o anexo. Visualização de descoberta (attachment-discovery-routes.py se você estiver seguindo nossa exemplo fornecido). Na parte de cima da rota de destino do complemento (/classroom-addon em nosso exemplo fornecido), recupere e armazene o Parâmetros de consulta courseId, itemId, itemType e addOnToken.

# Retrieve the itemId, courseId, and addOnToken query parameters.
if flask.request.args.get("itemId"):
    flask.session["itemId"] = flask.request.args.get("itemId")
if flask.request.args.get("itemType"):
    flask.session["itemType"] = flask.request.args.get("itemType")
if flask.request.args.get("courseId"):
    flask.session["courseId"] = flask.request.args.get("courseId")
if flask.request.args.get("addOnToken"):
    flask.session["addOnToken"] = flask.request.args.get("addOnToken")

Grave esses valores na sessão somente se eles estiverem presentes. não estão transmitido novamente se o usuário retornar à visualização de descoberta de anexos mais tarde sem fechar o iframe.

Adicionar armazenamento permanente para anexos de tipo de conteúdo

Você precisa de um registro local de todos os anexos criados. Isso permite que você pesquise conteúdo selecionado pelo professor usando identificadores fornecidos pelo Google Sala de Aula.

Configure um esquema de banco de dados para um Attachment. Nosso exemplo apresenta que mostrem uma imagem e uma legenda. Uma Attachment contém as seguintes atributos:

  • attachment_id: um identificador exclusivo para um anexo. Atribuída por ao Google Sala de Aula e retornada na resposta ao criar anexo.
  • image_filename: o nome de arquivo local da imagem a ser exibida.
  • image_caption: a legenda a ser exibida com a imagem.
.

Python

Estenda a implementação do SQLite e da flask_sqlalchemy das etapas anteriores.

Navegue até o arquivo em que você definiu a tabela de usuários (models.py se você estiver seguindo o exemplo fornecido). Adicione o seguinte na parte de baixo do arquivo abaixo da classe User.

class Attachment(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The image filename to store.
    image_filename = db.Column(db.String(120))

    # The image caption to store.
    image_caption = db.Column(db.String(120))

Importar a nova classe de anexo para o arquivo do servidor com seu anexo rotas de trânsito.

Configurar novos trajetos

Para começar esta etapa do tutorial, configure algumas páginas novas no nosso aplicativo. Eles permitem que um usuário crie e visualize conteúdo usando nosso complemento.

Adicionar rotas de criação de anexos

Você precisa de páginas para que o professor selecione o conteúdo e resolva problemas na criação de anexos solicitações. Implementar a rota /attachment-options para mostrar as opções de conteúdo para o professor selecionar. Você também precisa de modelos para a seleção de conteúdo e páginas de confirmação de criação. Nossos exemplos fornecidos contêm modelos para isso, além de exibir as solicitações e respostas dos API Classroom.

Você também pode modificar sua visualização de descoberta de anexos atual página de destino para exibir as opções de conteúdo em vez de criar o novo /attachment-options. Recomendamos a criação de uma nova página para fins de exercício para preservar o comportamento do SSO implementado na segunda etapa do tutorial, como a revogação das permissões do app. Isso deve provar útil para criar e testar seu complemento.

Um professor pode selecionar um pequeno conjunto de imagens legendadas nas exemplo. Nós fornecemos quatro imagens de pontos de referência famosos cujas legendas são derivados dos nomes dos arquivos.

Python

No exemplo fornecido, isso está no arquivo webapp/attachment_routes.py.

@app.route("/attachment-options", methods=["GET", "POST"])
def attachment_options():
    """
    Render the attachment options page from the "attachment-options.html"
    template.

    This page displays a grid of images that the user can select using
    checkboxes.
    """

    # A list of the filenames in the static/images directory.
    image_filenames = os.listdir(os.path.join(app.static_folder, "images"))

    # The image_list_form_builder method creates a form that displays a grid
    # of images, checkboxes, and captions with a Submit button. All images
    # passed in image_filenames will be shown, and the captions will be the
    # title-cased filenames.

    # The form must be built dynamically due to limitations in WTForms. The
    # image_list_form_builder method therefore also returns a list of
    # attribute names in the form, which will be used by the HTML template
    # to properly render the form.
    form, var_names = image_list_form_builder(image_filenames)

    # If the form was submitted, validate the input and create the attachments.
    if form.validate_on_submit():

        # Build a dictionary that maps image filenames to captions.
        # There will be one dictionary entry per selected item in the form.
        filename_caption_pairs = construct_filename_caption_dictionary_list(
            form)

        # Check that the user selected at least one image, then proceed to
        # make requests to the Classroom API.
        if len(filename_caption_pairs) > 0:
            return create_attachments(filename_caption_pairs)
        else:
            return flask.render_template(
                "create-attachment.html",
                message="You didn't select any images.",
                form=form,
                var_names=var_names)

    return flask.render_template(
        "attachment-options.html",
        message=("You've reached the attachment options page. "
                "Select one or more images and click 'Create Attachment'."),
        form=form,
        var_names=var_names,
    )

Isso produz uma janela "Create Attachments" semelhante a esta:

Exemplo de Python: visualização de seleção de conteúdo

O professor pode selecionar várias imagens. Crie um anexo para cada imagem. que o professor selecionou no método create_attachments.

Emitir solicitações de criação de anexos

Agora que você sabe quais partes do conteúdo o professor quer anexar, enviar solicitações à API Classroom para criar anexos nos atribuição. Armazenar os detalhes do anexo no seu banco de dados depois de receber um da API Classroom.

Para começar, acesse uma instância do serviço Sala de Aula:

Python

No exemplo fornecido, isso está no arquivo webapp/attachment_routes.py.

def create_attachments(filename_caption_pairs):
    """
    Create attachments and show an acknowledgement page.

    Args:
        filename_caption_pairs: A dictionary that maps image filenames to
            captions.
    """
    # Get the Google Classroom service.
    classroom_service = googleapiclient.discovery.build(
        serviceName="classroom",
        version="v1",
        credentials=credentials)

Envie uma solicitação CREATE para o courses.courseWork.addOnAttachments. endpoint do Google Cloud. Para cada imagem selecionada pelo professor, primeiro crie uma Objeto AddOnAttachment:

Python

No exemplo fornecido, isso é uma continuação do create_attachments. .

# Create a new attachment for each image that was selected.
attachment_count = 0
for key, value in filename_caption_pairs.items():
    attachment_count += 1

    # Create a dictionary with values for the AddOnAttachment object fields.
    attachment = {
        # Specifies the route for a teacher user.
        "teacherViewUri": {
            "uri":
                flask.url_for(
                    "load_content_attachment", _scheme='https', _external=True),
        },
        # Specifies the route for a student user.
        "studentViewUri": {
            "uri":
                flask.url_for(
                    "load_content_attachment", _scheme='https', _external=True)
        },
        # The title of the attachment.
        "title": f"Attachment {attachment_count}",
    }

Pelo menos os campos teacherViewUri, studentViewUri e title precisam ser fornecido para cada anexo. teacherViewUri e studentViewUri representam os URLs que são carregados quando o anexo é aberto pelo em cada tipo de usuário.

Envie o objeto AddOnAttachment no corpo de uma solicitação para o endpoint addOnAttachments. Informe courseId, itemId, itemType e addOnToken em cada solicitação.

Python

No exemplo fornecido, isso é uma continuação do create_attachments. .

# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
    case "announcements":
        parent = classroom_service.courses().announcements()
    case "courseWorkMaterials":
        parent = classroom_service.courses().courseWorkMaterials()
    case _:
        parent = classroom_service.courses().courseWork()

# Issue a request to create the attachment.
resp = parent.addOnAttachments().create(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    addOnToken=flask.session["addOnToken"],
    body=attachment).execute()

Crie uma entrada para esse anexo no seu banco de dados local para poder mais tarde carregar o conteúdo correto. O Google Sala de Aula retorna um valor id exclusivo. na resposta à solicitação de criação, então use isso como a chave primária em nosso no seu banco de dados. O Google Sala de Aula transmite a attachmentId ao abrir as visualizações de professores e alunos:

Python

No exemplo fornecido, isso é uma continuação do create_attachments. .

# Store the value by id.
new_attachment = Attachment(
    # The new attachment's unique ID, returned in the CREATE response.
    attachment_id=resp.get("id"),
    image_filename=key,
    image_caption=value)
db.session.add(new_attachment)
db.session.commit()

Considere direcionar o usuário para uma página de confirmação neste momento, reconhecendo se os anexos foram criados.

Permitir anexos do seu complemento

Agora é um bom momento para adicionar os endereços apropriados ao Anexo Permitido O campo "Prefixos do URI" na Configuração do app do SDK do Google Workspace Marketplace página. Seu complemento só pode criar anexos de um dos prefixos de URI listados nesta página. Essa é uma medida de segurança para ajudar a reduzir a possibilidade de ataques "man-in-the-middle".

A abordagem mais simples é fornecer seu domínio de nível superior neste campo, por exemplo https://example.com. https://localhost:<your port number>/ iria funcionam se você estiver usando sua máquina local como o servidor da Web.

Adicionar trajetos para as visualizações de professores e alunos

Há quatro iframes em que um complemento do Google Sala de Aula pode ser carregado. Você criou apenas rotas que atendem ao iframe da visualização de descoberta de anexos. longe. Em seguida, adicione rotas para exibir também os iframes de visualização de professores e alunos.

O iframe da Visualização do professor é necessário para mostrar uma prévia do estudante mas também podem incluir informações adicionais ou edições atributos de machine learning.

A visualização do estudante é a página que aparece para cada estudante quando ele abre um anexo de complemento.

Para este exercício, crie uma única /load-content-attachment que atende às visualizações do professor e dos alunos. Usar a API Classroom para determinar se o usuário é professor ou estudante quando a página carrega.

Python

No exemplo fornecido, isso está no arquivo webapp/attachment_routes.py.

@app.route("/load-content-attachment")
def load_content_attachment():
    """
    Load the attachment for the user's role."""

    # Since this is a landing page for the Teacher and Student View iframes, we
    # need to preserve the incoming query parameters.
    if flask.request.args.get("itemId"):
        flask.session["itemId"] = flask.request.args.get("itemId")
    if flask.request.args.get("itemType"):
        flask.session["itemType"] = flask.request.args.get("itemType")
    if flask.request.args.get("courseId"):
        flask.session["courseId"] = flask.request.args.get("courseId")
    if flask.request.args.get("attachmentId"):
        flask.session["attachmentId"] = flask.request.args.get("attachmentId")

Lembre-se de que você também deve autenticar o usuário nesse momento. Você também precisa gerenciar o parâmetro de consulta login_hint aqui e encaminhar o usuário para seu fluxo de autorização, se necessário. Consulte os detalhes da orientação de login discutidos nos tutoriais anteriores para mais informações sobre esse fluxo.

Em seguida, envie uma solicitação para o endpoint getAddOnContext que corresponde ao item não é válido.

Python

No exemplo fornecido, isso é uma continuação load_content_attachment.

# Create an instance of the Classroom service.
classroom_service = googleapiclient.discovery.build(
    serviceName="classroom"
    version="v1",
    credentials=credentials)

# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
    case "announcements":
        parent = classroom_service.courses().announcements()
    case "courseWorkMaterials":
        parent = classroom_service.courses().courseWorkMaterials()
    case _:
        parent = classroom_service.courses().courseWork()

addon_context_response = parent.getAddOnContext(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"]).execute()

Esse método retorna informações sobre a função do usuário atual na classe. Alterar a visualização apresentada ao usuário dependendo da função dele. Exatamente um dos Os campos studentContext ou teacherContext são preenchidos na resposta objeto. Analise-os para determinar como se dirigir ao usuário.

De qualquer forma, use o valor do parâmetro de consulta attachmentId para saber quais para recuperar do nosso banco de dados. Esse parâmetro de consulta é fornecido quando abra os URIs de visualização de professor ou aluno.

Python

No exemplo fornecido, isso é uma continuação load_content_attachment.

# Determine which view we are in by testing the returned context type.
user_context = "student" if addon_context_response.get(
    "studentContext") else "teacher"

# Look up the attachment in the database.
attachment = Attachment.query.get(flask.session["attachmentId"])

# Set the text for the next page depending on the user's role.
message_str = f"I see that you're a {user_context}! "
message_str += (
    f"I've loaded the attachment with ID {attachment.attachment_id}. "
    if user_context == "teacher" else
    "Please enjoy this image of a famous landmark!")

# Show the content with the customized message text.
return flask.render_template(
    "show-content-attachment.html",
    message=message_str,
    image_filename=attachment.image_filename,
    image_caption=attachment.image_caption,
    responses=response_strings)

Testar o complemento

Siga estas etapas para testar a criação de anexos:

  • Faça login no [Google Sala de Aula] como um dos seus Professores:
  • Acesse a guia Atividades e crie uma Atividade.
  • Clique no botão Complementos abaixo da área de texto e selecione o complemento. O iframe é aberto, e o complemento carrega o URI de configuração de anexos que você especificado na página Configuração do app do SDK do Google Workspace Marketplace.
  • Escolha um conteúdo para anexar à tarefa.
  • Feche o iframe após a conclusão do fluxo de criação de anexos.

Um card de anexo vai aparecer na interface de criação de atividades no Google Google Sala de Aula. Clique no card para abrir o iframe do recurso Teacher View e confirmar. para verificar se o anexo correto é exibido. Clique no botão Atribuir.

Conclua as etapas a seguir para testar a experiência do estudante:

  • Em seguida, faça login no Google Sala de Aula como um usuário de teste aluno na mesma turma como usuário de teste professor.
  • Encontre a atividade de teste na guia "Atividades".
  • Expanda a atividade e clique no cartão do anexo para abrir a visualização dos alunos. iframe.

Confirme se o anexo correto aparece para o estudante.

Parabéns! Você está pronto para passar para a próxima etapa: criar do tipo de atividade.