Anexos de tipo de atividade

Este é o quinto tutorial da série sobre os complementos do Google Sala de Aula.

Neste tutorial, você vai modificar o exemplo da etapa anterior para produzir um anexo do tipo atividade. São todos os anexos que exigem um envio do estudante, como uma resposta por escrito, um teste ou outro artefato gerado pelo estudante.

É importante distinguir entre anexos de tipo de conteúdo e tipo de atividade. Os anexos de tipo de atividade diferem dos de tipo de conteúdo das seguintes maneiras:

  • Um botão "Entregar" aparece na parte de cima à direita do iframe da visualização do estudante.
  • Eles fornecem um identificador exclusivo para o trabalho do estudante.
  • O card de anexos aparece na interface do avaliador do Google Sala de Aula.
  • Eles podem definir uma nota para a atividade a que pertencem.

Confira o próximo tutorial para saber mais sobre a avaliação. Durante este tutorial, você vai concluir o seguinte:

  • Modifique as solicitações anteriores de criação de anexos para a API Classroom e crie um anexo do tipo atividade.
  • Implemente o armazenamento permanente para os envios dos estudantes.
  • Modifique a rota anterior da visualização do estudante para aceitar a entrada do estudante.
  • Forneça uma rota para veicular o iframe de revisão de trabalhos dos estudantes.

Depois de concluir, você pode criar anexos de atividades nas tarefas pela interface do Google Sala de Aula quando estiver conectado como professor. Os estudantes da turma também podem concluir a atividade no iframe e enviar uma resposta. O professor pode ver o envio do estudante na interface de avaliação do Google Sala de Aula.

Para este exemplo, reutilize o modelo de anexo do tutorial anterior, que mostra uma imagem de um monumento famoso e uma legenda com o nome dele. A atividade consiste em pedir ao estudante para informar o nome do ponto de referência.

Modificar a solicitação de criação de anexo

Navegue até a seção do código em que você criou um anexo de tipo de conteúdo no tutorial anterior. O item principal aqui é uma instância de um objeto AddOnAttachment, em que especificamos anteriormente o teacherViewUri, studentViewUri e title para o anexo.

Embora todos os anexos de complementos exijam esses três campos, a presença ou ausência de um studentWorkReviewUri determina se o anexo é do tipo atividade ou conteúdo. Uma solicitação CREATE com um studentWorkReviewUri preenchido se torna um anexo do tipo atividade, enquanto uma solicitação CREATE sem um studentWorkReviewUri se torna um anexo do tipo conteúdo.

A única modificação a ser feita nessa solicitação é preencher o campo studentWorkReviewUri. Adicione uma rota com um nome adequado aqui. Você vai implementá-la em uma etapa posterior.

Python

No exemplo fornecido, isso está no método create_attachments do arquivo webapp/attachment_routes.py.

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    # The presence of this field marks this as an activity-type attachment.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

Adicionar armazenamento permanente para anexos de tipo de conteúdo

Grave a resposta do estudante à nossa atividade. Você pode consultar depois, quando o professor visualizar o envio no iframe de revisão de trabalhos dos estudantes.

Configure um esquema de banco de dados para um Submission. O exemplo fornecido espera que os estudantes insiram o nome do ponto de referência mostrado em uma imagem. Um Submission contém os seguintes atributos:

  • attachment_id: um identificador exclusivo de um anexo. Atribuído pelo Classroom e retornado na resposta ao criar um anexo.
  • submission_id: um identificador de uma atividade enviada por um estudante. Atribuído pelo Google Sala de Aula e retornado na resposta getAddOnContext na visualização do estudante.
  • student_response: a resposta enviada pelo estudante.

Python

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

Navegue até o arquivo em que você definiu as tabelas anteriores (models.py se você estiver seguindo o exemplo fornecido). Adicione o seguinte na parte de baixo do arquivo.

# Database model to represent a student submission.
class Submission(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    submission_id = db.Column(db.String(120), primary_key=True)

    # The unique identifier for the student's submission.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The student's response to the question prompt.
    student_response = db.Column(db.String(120))

Importe a nova classe Submission para o arquivo do servidor com suas rotas de processamento de anexos.

Modificar a rota da visualização do estudante

Em seguida, modifique a rota anterior da Visão do estudante para mostrar um pequeno formulário e aceitar entradas do estudante. É possível reutilizar a maior parte do código do tutorial anterior.

Localize o código do servidor que fornece a rota para a Visão do estudante. Essa é a rota especificada no campo studentViewUri ao criar um anexo. A primeira mudança a ser feita é extrair o submissionId da getAddOnContext resposta.

Python

No exemplo fornecido, isso está no método load_activity_attachment do arquivo webapp/attachment_routes.py.

# Issue a request to the courseWork.getAddOnContext endpoint
addon_context_response = classroom_service.courses().courseWork(
).getAddOnContext(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"]).execute()

# One of studentContext or teacherContext will be populated.
user_context = "student" if addon_context_response.get(
    "studentContext") else "teacher"

# If the user is a student...
if user_context == "student":
    # Extract the submissionId from the studentContext object.
    # This value is provided by Google Classroom.
    flask.session["submissionId"] = addon_context_response.get(
            "studentContext").get("submissionId")

Você também pode emitir uma solicitação para receber o status de envio do estudante. A resposta contém um valor SubmissionState, que indica estados como se o estudante abriu ou enviou o anexo. Isso pode ser útil se você quiser impedir edições em um envio entregue ou se quiser fornecer aos professores insights sobre o progresso dos estudantes:

Python

No exemplo fornecido, essa é uma continuação do método load_activity_attachment acima.

# Issue a request to get the status of the student submission.
submission_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().get(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"]).execute()

Por fim, busque as informações do anexo no banco de dados e disponibilize um formulário de entrada. O formulário no exemplo fornecido consiste em um campo de entrada de string e um botão de envio. Mostre a imagem do ponto de referência e peça para o estudante digitar o nome dele. Depois que eles responderem, registre a resposta no nosso banco de dados.

Python

No exemplo fornecido, essa é uma continuação do método load_activity_attachment acima.

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

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 complete the activity below.")

form = activity_form_builder()

if form.validate_on_submit():
    # Record the student's response in our database.

    # Check if the student has already submitted a response.
    # If so, update the response stored in the database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    if student_submission is not None:
        student_submission.student_response = form.student_response.data
    else:
        # Store the student's response by the submission ID.
        new_submission = Submission(
            submission_id=flask.session["submissionId"],
            attachment_id=flask.session["attachmentId"],
            student_response=form.student_response.data)
        db.session.add(new_submission)

    db.session.commit()

    return flask.render_template(
        "acknowledge-submission.html",
        message="Your response has been recorded. You can close the " \
            "iframe now.",
        instructions="Please Turn In your assignment if you have " \
            "completed all tasks."
    )

# Show the activity.
return flask.render_template(
    "show-activity-attachment.html",
    message=message_str,
    image_filename=attachment.image_filename,
    image_caption=attachment.image_caption,
    user_context=user_context,
    form=form,
    responses=response_strings)

Para diferenciar os usuários, desative a função de envio e mostre a resposta correta na visualização do professor.

Adicionar uma rota para o iframe de revisão de trabalhos dos estudantes

Por fim, adicione uma rota para veicular o iframe de revisão de trabalhos dos estudantes. O nome dessa rota precisa corresponder ao fornecido para o studentWorkReviewUri ao criar um anexo. Essa rota é aberta quando o professor visualiza a atividade enviada pelo estudante na interface do avaliador do Google Sala de Aula.

Você recebe o parâmetro de consulta submissionId quando o Google Sala de Aula abre o iframe de revisão de trabalhos dos estudantes. Use-o para recuperar o trabalho do estudante do seu banco de dados local:

Python

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

@app.route("/view-submission")
def view_submission():
    """
    Render a student submission using the show-student-submission.html template.
    """

    # Save the query parameters passed to the iframe in the session, just as we did
    # in previous routes. Abbreviated here for readability.
    add_iframe_query_parameters_to_session(flask.request.args)

    # For the sake of brevity in this example, we'll skip the conditional logic
    # to see if we need to authorize the user as we have done in previous steps.
    # We can assume that the user that reaches this route is a teacher that has
    # already authorized and created an attachment using the add-on.

    # In production, we recommend fully validating the user's authorization at
    # this stage as well.

    # Look up the student's submission in our database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    # Look up the attachment in the database.
    attachment = Attachment.query.get(student_submission.attachment_id)

    # Render the student's response alongside the correct answer.
    return flask.render_template(
        "show-student-submission.html",
        message=f"Loaded submission {student_submission.submission_id} for "\
            f"attachment {attachment.attachment_id}.",
        student_response=student_submission.student_response,
        correct_answer=attachment.image_caption)

Testar o complemento

Repita as etapas de teste do complemento do tutorial anterior. Você precisa ter um anexo que possa ser aberto pelo estudante.

Siga estas etapas para testar o anexo de atividade:

  • Faça login no Google Sala de Aula como um dos seus usuários de teste estudantes na mesma turma do usuário de teste professor.
  • Navegue até a guia Atividades e expanda a Atividade do teste.
  • Clique no card de anexo do complemento para abrir a visualização do estudante e enviar uma resposta para a atividade.
  • Feche o iframe depois de concluir a atividade. Se quiser, clique no botão Entregar.

Depois de concluir a atividade, nada vai mudar na Sala de Aula. Agora teste o iframe de avaliação de trabalhos dos estudantes:

  • Faça login no Google Sala de Aula como o usuário de teste professor.
  • Encontre a coluna da sua atividade de teste na guia Notas. Clique no nome da atividade de teste.
  • Encontre o card do usuário estudante de teste. Clique no anexo no card.

Confirme se a atividade correta aparece para o estudante.

Parabéns! Agora você pode passar para a próxima etapa: sincronizar notas de anexos.