From 2b5631758777e04ff5efbb57d740c6b7a5f99d3c Mon Sep 17 00:00:00 2001 From: endoooo Date: Thu, 29 Aug 2024 15:00:54 -0300 Subject: [PATCH 01/11] chore: refactored students notes page into students strands - removed `Notes.list_student_strands_notes/2` in favor of `LearningContext.list_student_strands/2` (they are not exactly the same function, but the base logic is, and one is replacing the other) - changed `/student_notes` route to `/student_strands` - renamed "Home" and "Notes" student menu items to "Report cards" and "Strands" respectively --- lib/lanttern/learning_context.ex | 56 +++++++ lib/lanttern/notes.ex | 68 -------- .../pages/student notes/student_notes_live.ex | 152 ------------------ .../student_notes_live.html.heex | 104 ------------ .../student_strands/student_strands_live.ex | 69 ++++++++ .../student_strands_live.html.heex | 28 ++++ .../live/shared/menu_component.ex | 11 +- lib/lanttern_web/router.ex | 2 +- test/lanttern/learning_context_test.exs | 104 ++++++++++++ test/lanttern/notes_test.exs | 117 -------------- .../student_strands_live_test.exs} | 27 ++-- 11 files changed, 275 insertions(+), 463 deletions(-) delete mode 100644 lib/lanttern_web/live/pages/student notes/student_notes_live.ex delete mode 100644 lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex create mode 100644 lib/lanttern_web/live/pages/student_strands/student_strands_live.ex create mode 100644 lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex rename test/lanttern_web/live/pages/{student_notes/student_notes_live_test.exs => student_strands/student_strands_live_test.exs} (55%) diff --git a/lib/lanttern/learning_context.ex b/lib/lanttern/learning_context.ex index b1c4c8c1..99b1a9da 100644 --- a/lib/lanttern/learning_context.ex +++ b/lib/lanttern/learning_context.ex @@ -50,6 +50,62 @@ defmodule Lanttern.LearningContext do {results |> maybe_preload(opts), meta} end + @doc """ + Returns the list of strands linked to the student. + + Strands are "linked to the student" through report cards: + + strand -> strand report -> report card -> student report card + + Results are ordered by cycle (desc), then by strand report position. + + Preloads subjects and years. + + ## Options: + + - `:cycles_ids` - filter results by given cycles, using the report card cycle + + ## Examples + + iex> list_student_strands(1) + [%Strand{}, ...] + + """ + @spec list_student_strands(student_id :: pos_integer(), opts :: Keyword.t()) :: [Strand.t()] + def list_student_strands(student_id, opts \\ []) do + from( + s in Strand, + left_join: sub in assoc(s, :subjects), + left_join: y in assoc(s, :years), + join: sr in assoc(s, :strand_reports), + join: rc in assoc(sr, :report_card), + join: c in assoc(rc, :school_cycle), + as: :cycles, + join: src in assoc(rc, :students_report_cards), + order_by: [desc: c.end_at, asc: c.start_at, asc: sr.position], + where: src.student_id == ^student_id, + preload: [subjects: sub, years: y] + ) + |> apply_list_student_strands_opts(opts) + |> Repo.all() + # we may have the same strand in more than one report card/strand report + |> Enum.uniq() + end + + defp apply_list_student_strands_opts(queryable, []), do: queryable + + defp apply_list_student_strands_opts(queryable, [{:cycles_ids, cycles_ids} | opts]) + when cycles_ids != [] do + from( + [_s, cycles: c] in queryable, + where: c.id in ^cycles_ids + ) + |> apply_list_student_strands_opts(opts) + end + + defp apply_list_student_strands_opts(queryable, [_opt | opts]), + do: apply_list_student_strands_opts(queryable, opts) + @doc """ Search strands by name. diff --git a/lib/lanttern/notes.ex b/lib/lanttern/notes.ex index 384f51c2..89cf3ada 100644 --- a/lib/lanttern/notes.ex +++ b/lib/lanttern/notes.ex @@ -65,74 +65,6 @@ defmodule Lanttern.Notes do |> Repo.all() end - @doc """ - Returns the list of student strand notes based on their report cards. - - The function lists all strands linked to the student report cards, ordering the results - by (report card) cycle descending and strand reports position ascending. - - The list is comprised of tuples of note (or `nil`) and strand. - - ### Options: - - `:cycles_ids` – filter results by given cycles - - ## Examples - - iex> list_student_strands_notes(user, opts) - [{%Note{}, %Strand{}}, ...] - - """ - @spec list_student_strands_notes(user :: User.t(), opts :: Keyword.t()) :: [ - {Note.t() | nil, Strand.t()} - ] - def list_student_strands_notes(%{current_profile: profile} = _user, opts \\ []) do - strand_student_notes_map = - from( - n in Note, - join: snr in assoc(n, :strand_note_relationship), - where: n.author_id == ^profile.id, - select: {n, snr} - ) - |> Repo.all() - |> Enum.map(fn {n, snr} -> - {snr.strand_id, n} - end) - |> Enum.into(%{}) - - from( - s in Strand, - join: sr in assoc(s, :strand_reports), - join: rc in assoc(sr, :report_card), - join: c in assoc(rc, :school_cycle), - as: :cycles, - join: src in assoc(rc, :students_report_cards), - order_by: [desc: c.end_at, asc: c.start_at, asc: sr.position], - where: src.student_id == ^profile.student_id - ) - |> apply_list_student_strands_notes_opts(opts) - |> Repo.all() - |> Enum.uniq() - |> maybe_preload(preloads: [:subjects, :years]) - |> Enum.map(fn strand -> - {Map.get(strand_student_notes_map, strand.id), strand} - end) - end - - defp apply_list_student_strands_notes_opts(queryable, []), do: queryable - - defp apply_list_student_strands_notes_opts(queryable, [{:cycles_ids, cycles_ids} | opts]) - when cycles_ids != [] do - from( - [_s, cycles: c] in queryable, - where: c.id in ^cycles_ids - ) - |> apply_list_student_strands_notes_opts(opts) - end - - defp apply_list_student_strands_notes_opts(queryable, [_opt | opts]), - do: apply_list_student_strands_notes_opts(queryable, opts) - @doc """ Returns the list of students of the given classes with their strand notes. diff --git a/lib/lanttern_web/live/pages/student notes/student_notes_live.ex b/lib/lanttern_web/live/pages/student notes/student_notes_live.ex deleted file mode 100644 index 9d313c1f..00000000 --- a/lib/lanttern_web/live/pages/student notes/student_notes_live.ex +++ /dev/null @@ -1,152 +0,0 @@ -defmodule LantternWeb.StudentNotesLive do - @moduledoc """ - Student home live view - """ - - use LantternWeb, :live_view - - alias Lanttern.LearningContext - alias Lanttern.Notes - alias Lanttern.Reporting - alias Lanttern.Schools - - import LantternWeb.FiltersHelpers - - # shared components - import LantternWeb.LearningContextComponents - alias LantternWeb.Notes.NoteComponent - alias LantternWeb.Filters.InlineFiltersComponent - import LantternWeb.SchoolsComponents - alias LantternWeb.Attachments.AttachmentAreaComponent - - @impl true - def mount(_params, _session, socket) do - school = - socket.assigns.current_user.current_profile.school_id - |> Schools.get_school!() - - student_report_cards_cycles = - Reporting.list_student_report_cards_cycles( - socket.assigns.current_user.current_profile.student_id - ) - - socket = - socket - |> assign(:school, school) - |> assign(:student_report_cards_cycles, student_report_cards_cycles) - |> assign(:strand, nil) - |> assign(:note, nil) - |> assign_user_filters([:cycles], socket.assigns.current_user) - |> stream_configure( - :student_strands_notes, - dom_id: fn {_, strand} -> - "strand-note-#{strand.id}" - end - ) - |> stream_configure( - :student_report_cards_for_strand, - dom_id: fn {student_report_card, _} -> - "student-report-card-#{student_report_card.id}" - end - ) - |> stream_student_strands_notes() - - {:ok, socket} - end - - defp stream_student_strands_notes(socket) do - student_strands_notes = - socket.assigns.current_user - |> Notes.list_student_strands_notes(cycles_ids: socket.assigns.selected_cycles_ids) - - has_student_strands_notes = student_strands_notes != [] - - socket - |> stream(:student_strands_notes, student_strands_notes, reset: true) - |> assign(:has_student_strands_notes, has_student_strands_notes) - end - - @impl true - def handle_params(params, _uri, socket) do - socket = - socket - |> assign_is_editing_note(params) - - {:noreply, socket} - end - - defp assign_is_editing_note(socket, params) do - case {params, socket.assigns.strand} do - {%{"is_editing_note" => "true"}, nil} -> - socket - |> push_patch(to: ~p"/student_notes", replace: true) - - {%{"is_editing_note" => "true"}, _strand} -> - socket - |> assign(:is_editing_note, true) - - _ -> - socket - |> assign(:is_editing_note, false) - end - end - - # event handlers - - @impl true - def handle_event("edit_note", %{"strand_id" => strand_id}, socket) do - strand = LearningContext.get_strand!(strand_id) - - student_id = - socket.assigns.current_user.current_profile.student_id - - note = - Notes.get_student_note( - student_id, - strand_id: strand_id - ) - - student_report_cards_for_strand = - Reporting.list_student_report_cards_linked_to_strand( - student_id, - strand_id - ) - - has_student_report_cards_for_strand = - student_report_cards_for_strand != [] - - socket = - socket - |> assign(:strand, strand) - |> assign(:note, note) - |> stream(:student_report_cards_for_strand, student_report_cards_for_strand, reset: true) - |> assign(:has_student_report_cards_for_strand, has_student_report_cards_for_strand) - |> push_patch(to: ~p"/student_notes?is_editing_note=true") - - {:noreply, socket} - end - - # info handlers - - @impl true - def handle_info({InlineFiltersComponent, {:apply, cycles_ids}}, socket) do - socket = - socket - |> assign(:selected_cycles_ids, cycles_ids) - |> save_profile_filters( - socket.assigns.current_user, - [:cycles] - ) - |> stream_student_strands_notes() - - {:noreply, socket} - end - - def handle_info({NoteComponent, {:saved, note}}, socket) do - {:noreply, assign(socket, :note, note)} - end - - def handle_info({NoteComponent, {:deleted, _}}, socket) do - {:noreply, assign(socket, :note, nil)} - end -end diff --git a/lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex b/lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex deleted file mode 100644 index 71f07e94..00000000 --- a/lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex +++ /dev/null @@ -1,104 +0,0 @@ -<.responsive_container class="pt-6 sm:pt-10"> - <.page_title_with_menu><%= gettext("My strands notes") %> - <.live_component - module={InlineFiltersComponent} - id="cycles-filter" - filter_items={@student_report_cards_cycles} - selected_items_ids={@selected_cycles_ids} - all_text={gettext("All cycles")} - class="mt-10" - notify_parent - /> -
- <.empty_state> - <%= gettext("No strands related to selected cycles") %> - -
- -<.responsive_grid :if={@has_student_strands_notes} id="student-strands-notes" phx-update="stream"> - <.strand_card - :for={{dom_id, {note, strand}} <- @streams.student_strands_notes} - id={dom_id} - strand={strand} - cover_image_url={strand.cover_image_url} - hide_description - class="shrink-0 w-64 sm:w-auto" - > - <:bottom_content> -
- <.button - theme={if note, do: "diff_light", else: "ghost"} - icon_name="hero-pencil-square" - phx-click={JS.push("edit_note", value: %{"strand_id" => strand.id})} - > - <%= if note, do: gettext("View/edit note"), else: gettext("Add note") %> - -
- - - -<.school_branding_footer school={@school} /> -<.slide_over - :if={@is_editing_note && @strand} - id="student-strand-note-overlay" - show={true} - on_cancel={JS.patch(~p"/student_notes")} -> - <:title><%= gettext("Strand note") %> -
-

<%= @strand.name %>

-

<%= @strand.type %>

-
- <.hr class="my-10" /> - <.live_component - module={NoteComponent} - id="student-strand-notes" - note={@note} - current_user={@current_user} - strand_id={@strand.id} - title={gettext("Notes")} - empty_msg={gettext("No notes for this strand yet")} - empty_add_note_msg={gettext("Add a strand note")} - allow_editing={true} - notify_parent - /> -
- <.live_component - module={AttachmentAreaComponent} - id="student-strand-note-attachemnts" - current_user={@current_user} - note_id={@note && @note.id} - title={gettext("Note's attachments")} - allow_editing - /> -
-
- <.hr class="my-10" /> -
<%= gettext("View note in report card context") %>
- -
- diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex new file mode 100644 index 00000000..b0041e04 --- /dev/null +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex @@ -0,0 +1,69 @@ +defmodule LantternWeb.StudentStrandsLive do + @moduledoc """ + Student home live view + """ + + use LantternWeb, :live_view + + alias Lanttern.LearningContext + alias Lanttern.Reporting + alias Lanttern.Schools + + import LantternWeb.FiltersHelpers + + # shared components + import LantternWeb.LearningContextComponents + alias LantternWeb.Filters.InlineFiltersComponent + import LantternWeb.SchoolsComponents + + @impl true + def mount(_params, _session, socket) do + school = + socket.assigns.current_user.current_profile.school_id + |> Schools.get_school!() + + student_report_cards_cycles = + Reporting.list_student_report_cards_cycles( + socket.assigns.current_user.current_profile.student_id + ) + + socket = + socket + |> assign(:school, school) + |> assign(:student_report_cards_cycles, student_report_cards_cycles) + |> assign_user_filters([:cycles], socket.assigns.current_user) + |> stream_student_strands() + + {:ok, socket} + end + + defp stream_student_strands(socket) do + student_strands = + LearningContext.list_student_strands( + socket.assigns.current_user.current_profile.student_id, + cycles_ids: socket.assigns.selected_cycles_ids + ) + + has_student_strands = student_strands != [] + + socket + |> stream(:student_strands, student_strands, reset: true) + |> assign(:has_student_strands, has_student_strands) + end + + # info handlers + + @impl true + def handle_info({InlineFiltersComponent, {:apply, cycles_ids}}, socket) do + socket = + socket + |> assign(:selected_cycles_ids, cycles_ids) + |> save_profile_filters( + socket.assigns.current_user, + [:cycles] + ) + |> stream_student_strands() + + {:noreply, socket} + end +end diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex new file mode 100644 index 00000000..869554f3 --- /dev/null +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex @@ -0,0 +1,28 @@ +<.responsive_container class="pt-6 sm:pt-10"> + <.page_title_with_menu><%= gettext("Strands") %> + <.live_component + module={InlineFiltersComponent} + id="cycles-filter" + filter_items={@student_report_cards_cycles} + selected_items_ids={@selected_cycles_ids} + all_text={gettext("All cycles")} + class="mt-10" + notify_parent + /> +
+ <.empty_state> + <%= gettext("No strands related to selected cycles") %> + +
+ +<.responsive_grid :if={@has_student_strands} id="student-strands" phx-update="stream"> + <.strand_card + :for={{dom_id, strand} <- @streams.student_strands} + id={dom_id} + strand={strand} + cover_image_url={strand.cover_image_url} + hide_description + class="shrink-0 w-64 sm:w-auto" + /> + +<.school_branding_footer school={@school} /> diff --git a/lib/lanttern_web/live/shared/menu_component.ex b/lib/lanttern_web/live/shared/menu_component.ex index 1daad866..2b05c949 100644 --- a/lib/lanttern_web/live/shared/menu_component.ex +++ b/lib/lanttern_web/live/shared/menu_component.ex @@ -58,10 +58,10 @@ defmodule LantternWeb.MenuComponent do <%= if @current_profile.type == "student" do %> <.nav_item active={@active_nav == :student_home} path={~p"/student"}> - <%= gettext("Home") %> + <%= gettext("Report cards") %> - <.nav_item active={@active_nav == :student_notes} path={~p"/student_notes"}> - <%= gettext("Notes") %> + <.nav_item active={@active_nav == :student_strands} path={~p"/student_strands"}> + <%= gettext("Strands") %> <%!-- use this li as placeholder when nav items % 3 != 0 (sm) or nav items % 2 != 0 --%> <%!--
  • --%> @@ -350,9 +350,10 @@ defmodule LantternWeb.MenuComponent do # student home LantternWeb.StudentHomeLive => :student_home, + LantternWeb.StudentReportCardLive => :student_home, - # student notes - LantternWeb.StudentNotesLive => :student_notes + # student strands + LantternWeb.StudentStrandsLive => :student_strands } def mount(socket) do diff --git a/lib/lanttern_web/router.ex b/lib/lanttern_web/router.ex index 2c6701f4..db18b4d3 100644 --- a/lib/lanttern_web/router.ex +++ b/lib/lanttern_web/router.ex @@ -129,7 +129,7 @@ defmodule LantternWeb.Router do {LantternWeb.Path, :put_path_in_socket} ] do live "/student", StudentHomeLive - live "/student_notes", StudentNotesLive + live "/student_strands", StudentStrandsLive end live_session :authenticated_user, diff --git a/test/lanttern/learning_context_test.exs b/test/lanttern/learning_context_test.exs index 7a2de580..63a8d469 100644 --- a/test/lanttern/learning_context_test.exs +++ b/test/lanttern/learning_context_test.exs @@ -99,6 +99,110 @@ defmodule Lanttern.LearningContextTest do assert expected_b.is_starred == false end + test "list_student_strand/2 returns all user strands related to students report cards" do + student = Lanttern.SchoolsFixtures.student_fixture() + + subject_1 = Lanttern.TaxonomyFixtures.subject_fixture() + subject_2 = Lanttern.TaxonomyFixtures.subject_fixture() + year = Lanttern.TaxonomyFixtures.year_fixture() + + strand_1 = + strand_fixture(%{subjects_ids: [subject_1.id, subject_2.id], years_ids: [year.id]}) + + strand_2 = strand_fixture() + strand_3 = strand_fixture() + strand_4 = strand_fixture() + + cycle_2024 = + Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2024-01-01], end_at: ~D[2024-12-31]) + + cycle_2023 = + Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2023-01-01], end_at: ~D[2023-12-31]) + + report_card_2024 = + Lanttern.ReportingFixtures.report_card_fixture(%{school_cycle_id: cycle_2024.id}) + + report_card_2023 = + Lanttern.ReportingFixtures.report_card_fixture(%{school_cycle_id: cycle_2023.id}) + + # create strand reports + + _strand_report_1_2024 = + Lanttern.ReportingFixtures.strand_report_fixture(%{ + report_card_id: report_card_2024.id, + strand_id: strand_1.id + }) + + _strand_report_2_2024 = + Lanttern.ReportingFixtures.strand_report_fixture(%{ + report_card_id: report_card_2024.id, + strand_id: strand_2.id + }) + + _strand_report_3_2023 = + Lanttern.ReportingFixtures.strand_report_fixture(%{ + report_card_id: report_card_2023.id, + strand_id: strand_3.id + }) + + _strand_report_4_2023 = + Lanttern.ReportingFixtures.strand_report_fixture(%{ + report_card_id: report_card_2023.id, + strand_id: strand_4.id + }) + + # create students report cards + _ = + Lanttern.ReportingFixtures.student_report_card_fixture(%{ + student_id: student.id, + report_card_id: report_card_2024.id + }) + + _ = + Lanttern.ReportingFixtures.student_report_card_fixture(%{ + student_id: student.id, + report_card_id: report_card_2023.id + }) + + # extra fixtures for filter testing + other_strand = strand_fixture() + other_report_card = Lanttern.ReportingFixtures.report_card_fixture() + + _other_strand_report = + Lanttern.ReportingFixtures.strand_report_fixture(%{ + report_card_id: other_report_card.id, + strand_id: other_strand.id + }) + + _other_student_report_card = + Lanttern.ReportingFixtures.student_report_card_fixture(%{ + student_id: student.id, + report_card_id: other_report_card.id + }) + + assert [ + expected_strand_1, + expected_strand_2, + expected_strand_3, + expected_strand_4 + ] = + LearningContext.list_student_strands( + student.id, + cycles_ids: [cycle_2023.id, cycle_2024.id] + ) + + assert expected_strand_1.id == strand_1.id + assert subject_1 in expected_strand_1.subjects + assert subject_2 in expected_strand_1.subjects + assert [year] == expected_strand_1.years + + assert expected_strand_2.id == strand_2.id + + assert expected_strand_3.id == strand_3.id + + assert expected_strand_4.id == strand_4.id + end + test "search_strands/2 returns all items matched by search" do _strand_1 = strand_fixture(%{name: "lorem ipsum xolor sit amet"}) strand_2 = strand_fixture(%{name: "lorem ipsum dolor sit amet"}) diff --git a/test/lanttern/notes_test.exs b/test/lanttern/notes_test.exs index 77add555..51970a66 100644 --- a/test/lanttern/notes_test.exs +++ b/test/lanttern/notes_test.exs @@ -245,123 +245,6 @@ defmodule Lanttern.NotesTest do assert expected_2.moment.id == moment_2.id end - test "list_student_strands_notes/2 returns all user strand notes related to students report cards" do - author = student_profile_fixture() - - subject_1 = Lanttern.TaxonomyFixtures.subject_fixture() - subject_2 = Lanttern.TaxonomyFixtures.subject_fixture() - year = Lanttern.TaxonomyFixtures.year_fixture() - - strand_1 = - strand_fixture(%{subjects_ids: [subject_1.id, subject_2.id], years_ids: [year.id]}) - - strand_2 = strand_fixture() - strand_3 = strand_fixture() - strand_4 = strand_fixture() - - cycle_2024 = - Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2024-01-01], end_at: ~D[2024-12-31]) - - cycle_2023 = - Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2023-01-01], end_at: ~D[2023-12-31]) - - report_card_2024 = - Lanttern.ReportingFixtures.report_card_fixture(%{school_cycle_id: cycle_2024.id}) - - report_card_2023 = - Lanttern.ReportingFixtures.report_card_fixture(%{school_cycle_id: cycle_2023.id}) - - # create strand reports - - _strand_report_1_2024 = - Lanttern.ReportingFixtures.strand_report_fixture(%{ - report_card_id: report_card_2024.id, - strand_id: strand_1.id - }) - - _strand_report_2_2024 = - Lanttern.ReportingFixtures.strand_report_fixture(%{ - report_card_id: report_card_2024.id, - strand_id: strand_2.id - }) - - _strand_report_3_2023 = - Lanttern.ReportingFixtures.strand_report_fixture(%{ - report_card_id: report_card_2023.id, - strand_id: strand_3.id - }) - - _strand_report_4_2023 = - Lanttern.ReportingFixtures.strand_report_fixture(%{ - report_card_id: report_card_2023.id, - strand_id: strand_4.id - }) - - # create students report cards - _ = - Lanttern.ReportingFixtures.student_report_card_fixture(%{ - student_id: author.student_id, - report_card_id: report_card_2024.id - }) - - _ = - Lanttern.ReportingFixtures.student_report_card_fixture(%{ - student_id: author.student_id, - report_card_id: report_card_2023.id - }) - - # create student notes in strand 1 and 3 - - strand_1_note = strand_note_fixture(%{current_profile: author}, strand_1.id) - strand_3_note = strand_note_fixture(%{current_profile: author}, strand_3.id) - - # extra fixtures for filter testing - other_strand = strand_fixture() - other_report_card = Lanttern.ReportingFixtures.report_card_fixture() - - _other_strand_1_note = - strand_note_fixture(%{current_profile: student_profile_fixture()}, strand_1.id) - - _other_strand_2_note = - strand_note_fixture(%{current_profile: student_profile_fixture()}, strand_2.id) - - _other_strand_report = - Lanttern.ReportingFixtures.strand_report_fixture(%{ - report_card_id: other_report_card.id, - strand_id: other_strand.id - }) - - _ = - Lanttern.ReportingFixtures.student_report_card_fixture(%{ - student_id: author.student_id, - report_card_id: other_report_card.id - }) - - assert [ - {^strand_1_note, expected_strand_1}, - {nil, expected_strand_2}, - {^strand_3_note, expected_strand_3}, - {nil, expected_strand_4} - ] = - Notes.list_student_strands_notes( - %{current_profile: author}, - cycles_ids: [cycle_2023.id, cycle_2024.id] - ) - - # assert expected_strand_1_note.id == strand_1_note.id - assert expected_strand_1.id == strand_1.id - assert subject_1 in expected_strand_1.subjects - assert subject_2 in expected_strand_1.subjects - assert [year] == expected_strand_1.years - - assert expected_strand_2.id == strand_2.id - - # assert expected_strand_3_note.id == strand_3_note.id - assert expected_strand_3.id == strand_3.id - - assert expected_strand_4.id == strand_4.id - end - test "list_classes_strand_notes/2 returns the list of classes students and their strand notes" do class_a = Lanttern.SchoolsFixtures.class_fixture(%{name: "A"}) class_b = Lanttern.SchoolsFixtures.class_fixture(%{name: "B"}) diff --git a/test/lanttern_web/live/pages/student_notes/student_notes_live_test.exs b/test/lanttern_web/live/pages/student_strands/student_strands_live_test.exs similarity index 55% rename from test/lanttern_web/live/pages/student_notes/student_notes_live_test.exs rename to test/lanttern_web/live/pages/student_strands/student_strands_live_test.exs index d2ba4afb..4dc8c1da 100644 --- a/test/lanttern_web/live/pages/student_notes/student_notes_live_test.exs +++ b/test/lanttern_web/live/pages/student_strands/student_strands_live_test.exs @@ -1,24 +1,23 @@ -defmodule LantternWeb.StudentNotesLiveTest do +defmodule LantternWeb.StudentStrandsLiveTest do use LantternWeb.ConnCase alias Lanttern.LearningContextFixtures - alias Lanttern.NotesFixtures alias Lanttern.ReportingFixtures - @live_view_path "/student_notes" + @live_view_path "/student_strands" setup [:register_and_log_in_student] - describe "Student home live view basic navigation" do + describe "Student strands live view basic navigation" do test "disconnected and connected mount", %{conn: conn} do conn = get(conn, @live_view_path) - assert html_response(conn, 200) =~ ~r"

    \s*My strands notes\s*<\/h1>" + assert html_response(conn, 200) =~ ~r"

    \s*Strands\s*<\/h1>" {:ok, _view, _html} = live(conn) end - test "list strands linked to report cards", %{conn: conn, student: student, user: user} do + test "list strands linked to report cards", %{conn: conn, student: student} do report_card = ReportingFixtures.report_card_fixture() _student_report_card = @@ -28,29 +27,25 @@ defmodule LantternWeb.StudentNotesLiveTest do allow_student_access: true }) - strand_with_note = LearningContextFixtures.strand_fixture(%{name: "AAA"}) - strand_without_note = LearningContextFixtures.strand_fixture(%{name: "BBB"}) - _strand_note = NotesFixtures.strand_note_fixture(user, strand_with_note.id) + strand_a = LearningContextFixtures.strand_fixture(%{name: "AAA"}) + strand_b = LearningContextFixtures.strand_fixture(%{name: "BBB"}) - _strand_with_note_report = + _strand_a_report = ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card.id, - strand_id: strand_with_note.id + strand_id: strand_a.id }) - _strand_without_note_report = + _strand_b_report = ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card.id, - strand_id: strand_without_note.id + strand_id: strand_b.id }) {:ok, view, _html} = live(conn, @live_view_path) assert view |> has_element?("h5", "AAA") - assert view |> has_element?("button", "View/edit note") - assert view |> has_element?("h5", "BBB") - assert view |> has_element?("button", "Add note") end end end From 0b89f71fd8912fe217f44874aa96b8d5b0fd987e Mon Sep 17 00:00:00 2001 From: endoooo Date: Thu, 29 Aug 2024 15:32:29 -0300 Subject: [PATCH 02/11] chore: added access to student strands page in guardian profile --- .../student_strands/student_strands_live.ex | 29 ++++++++++++++++--- .../live/shared/menu_component.ex | 7 +++-- lib/lanttern_web/router.ex | 3 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex index b0041e04..e111d165 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex @@ -3,6 +3,7 @@ defmodule LantternWeb.StudentStrandsLive do Student home live view """ + alias Lanttern.Identity.Profile use LantternWeb, :live_view alias Lanttern.LearningContext @@ -18,14 +19,21 @@ defmodule LantternWeb.StudentStrandsLive do @impl true def mount(_params, _session, socket) do + # check if user is guardian or student + check_if_user_has_access(socket.assigns.current_user.current_profile) + school = socket.assigns.current_user.current_profile.school_id |> Schools.get_school!() + student_id = + case socket.assigns.current_user.current_profile do + %{type: "student"} = profile -> profile.student_id + %{type: "guardian"} = profile -> profile.guardian_of_student_id + end + student_report_cards_cycles = - Reporting.list_student_report_cards_cycles( - socket.assigns.current_user.current_profile.student_id - ) + Reporting.list_student_report_cards_cycles(student_id) socket = socket @@ -37,10 +45,23 @@ defmodule LantternWeb.StudentStrandsLive do {:ok, socket} end + defp check_if_user_has_access(%{type: profile_type} = %Profile{}) + when profile_type in ["student", "guardian"], + do: nil + + defp check_if_user_has_access(_profile), + do: raise(LantternWeb.NotFoundError) + defp stream_student_strands(socket) do + student_id = + case socket.assigns.current_user.current_profile do + %{type: "student"} = profile -> profile.student_id + %{type: "guardian"} = profile -> profile.guardian_of_student_id + end + student_strands = LearningContext.list_student_strands( - socket.assigns.current_user.current_profile.student_id, + student_id, cycles_ids: socket.assigns.selected_cycles_ids ) diff --git a/lib/lanttern_web/live/shared/menu_component.ex b/lib/lanttern_web/live/shared/menu_component.ex index 2b05c949..3215e15c 100644 --- a/lib/lanttern_web/live/shared/menu_component.ex +++ b/lib/lanttern_web/live/shared/menu_component.ex @@ -70,10 +70,13 @@ defmodule LantternWeb.MenuComponent do <%= if @current_profile.type == "guardian" do %> <.nav_item active={@active_nav == :guardian_home} path={~p"/guardian"}> - <%= gettext("Home") %> + <%= gettext("Report cards") %> + + <.nav_item active={@active_nav == :student_strands} path={~p"/student_strands"}> + <%= gettext("Strands") %> <%!-- use this li as placeholder when nav items % 3 != 0 (sm) or nav items % 2 != 0 --%> -
  • + <%!--
  • --%> <% end %> diff --git a/lib/lanttern_web/router.ex b/lib/lanttern_web/router.ex index db18b4d3..e6cd9942 100644 --- a/lib/lanttern_web/router.ex +++ b/lib/lanttern_web/router.ex @@ -129,7 +129,6 @@ defmodule LantternWeb.Router do {LantternWeb.Path, :put_path_in_socket} ] do live "/student", StudentHomeLive - live "/student_strands", StudentStrandsLive end live_session :authenticated_user, @@ -138,6 +137,8 @@ defmodule LantternWeb.Router do {LantternWeb.UserAuth, :ensure_authenticated}, {LantternWeb.Path, :put_path_in_socket} ] do + live "/student_strands", StudentStrandsLive + live "/student_report_card/:id", StudentReportCardLive, :show live "/student_report_card/:id/strand_report/:strand_report_id", From 742857f5fa5cebdee3026ca9e5fca47785cec845 Mon Sep 17 00:00:00 2001 From: endoooo Date: Fri, 30 Aug 2024 10:42:30 -0300 Subject: [PATCH 03/11] feat: added support to strand report visualization (students/guardians) now students and guardians can access strand report even when the report card is not released - adjusted `LearningContext.list_student_strands/2` to include the (new) virtual fields `strand_report_id` and `report_cycle` in the returned strands schemas - created `Reporting.get_student_report_card_by_student_and_strand_report/2` - added `"/strand_report/:strand_report_id"` route and created a new `:ensure_authenticated_student_or_guardian` guard - added support to display the report cycle in `<.strand_card>` component - moved some page components to share components to allow reuse: `Assessments.StrandGoalDetailsOverlayComponent`, `Reporting.StrandReportAssessmentComponent`, `Reporting.StrandReportMomentsComponent`, `Reporting.StrandReportOverviewComponent` --- lib/lanttern/learning_context.ex | 11 +- lib/lanttern/learning_context/strand.ex | 5 + lib/lanttern/reporting.ex | 39 +++++ .../components/learning_context_components.ex | 3 + .../student_notes_component.ex | 2 +- .../student_report_card_strand_report_live.ex | 143 ++++++++++++++++++ ..._report_card_strand_report_live.html.heex} | 15 +- .../id/student_notes_component.ex | 79 ++++++++++ .../id}/student_strand_report_live.ex | 37 ++--- .../id/student_strand_report_live.html.heex | 103 +++++++++++++ .../student_strands/student_strands_live.ex | 6 + .../student_strands_live.html.heex | 1 + .../strand_goal_details_overlay_component.ex} | 9 +- .../live/shared/menu_component.ex | 16 +- .../strand_report_assessment_component.ex} | 19 +-- .../strand_report_moments_component.ex} | 20 +-- .../strand_report_overview_component.ex} | 13 +- lib/lanttern_web/router.ex | 15 +- lib/lanttern_web/user_auth.ex | 27 ++++ test/lanttern/learning_context_test.exs | 20 ++- test/lanttern/reporting_test.exs | 15 ++ .../id/student_strand_report_live_test.exs | 105 +++++++++++++ ...t_report_card_strand_report_live_test.exs} | 2 +- 23 files changed, 629 insertions(+), 76 deletions(-) create mode 100644 lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.ex rename lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/{student_strand_report_live.html.heex => student_report_card_strand_report_live.html.heex} (89%) create mode 100644 lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex rename lib/lanttern_web/live/pages/{student_report_card/id/strand_report/strand_report_id => student_strand_report/id}/student_strand_report_live.ex (76%) create mode 100644 lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex rename lib/lanttern_web/live/{pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex => shared/assessments/strand_goal_details_overlay_component.ex} (96%) rename lib/lanttern_web/live/{pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex => shared/reporting/strand_report_assessment_component.ex} (93%) rename lib/lanttern_web/live/{pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex => shared/reporting/strand_report_moments_component.ex} (89%) rename lib/lanttern_web/live/{pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex => shared/reporting/strand_report_overview_component.ex} (90%) create mode 100644 test/lanttern_web/live/pages/strand_report/id/student_strand_report_live_test.exs rename test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/{student_strand_report_live_test.exs => student_report_card_strand_report_live_test.exs} (98%) diff --git a/lib/lanttern/learning_context.ex b/lib/lanttern/learning_context.ex index 99b1a9da..27d64802 100644 --- a/lib/lanttern/learning_context.ex +++ b/lib/lanttern/learning_context.ex @@ -59,7 +59,11 @@ defmodule Lanttern.LearningContext do Results are ordered by cycle (desc), then by strand report position. - Preloads subjects and years. + Preloads subjects, years, and report cycle. + + The same strand can appear more than once, because it can + be linked to more than one report card at the same time. + The `report_card_id` and `report_cycle` can help differentiate them. ## Options: @@ -84,12 +88,11 @@ defmodule Lanttern.LearningContext do join: src in assoc(rc, :students_report_cards), order_by: [desc: c.end_at, asc: c.start_at, asc: sr.position], where: src.student_id == ^student_id, - preload: [subjects: sub, years: y] + preload: [subjects: sub, years: y], + select: %{s | strand_report_id: sr.id, report_cycle: c} ) |> apply_list_student_strands_opts(opts) |> Repo.all() - # we may have the same strand in more than one report card/strand report - |> Enum.uniq() end defp apply_list_student_strands_opts(queryable, []), do: queryable diff --git a/lib/lanttern/learning_context/strand.ex b/lib/lanttern/learning_context/strand.ex index c837ebc6..1c6bc84b 100644 --- a/lib/lanttern/learning_context/strand.ex +++ b/lib/lanttern/learning_context/strand.ex @@ -14,6 +14,7 @@ defmodule Lanttern.LearningContext.Strand do alias Lanttern.Notes.Note alias Lanttern.Notes.StrandNoteRelationship alias Lanttern.Reporting.StrandReport + alias Lanttern.Schools.Cycle alias Lanttern.Taxonomy.Subject alias Lanttern.Taxonomy.Year @@ -28,6 +29,8 @@ defmodule Lanttern.LearningContext.Strand do year_id: pos_integer(), years_ids: [pos_integer()], is_starred: boolean(), + strand_report_id: pos_integer(), + report_cycle: Cycle.t(), moments: [Moment.t()], assessment_points: [AssessmentPoint.t()], strand_reports: [StrandReport.t()], @@ -49,6 +52,8 @@ defmodule Lanttern.LearningContext.Strand do field :year_id, :id, virtual: true field :years_ids, {:array, :id}, virtual: true field :is_starred, :boolean, virtual: true + field :strand_report_id, :id, virtual: true + field :report_cycle, :map, virtual: true has_many :moments, Moment has_many :assessment_points, AssessmentPoint diff --git a/lib/lanttern/reporting.ex b/lib/lanttern/reporting.ex index b40d545e..be40f088 100644 --- a/lib/lanttern/reporting.ex +++ b/lib/lanttern/reporting.ex @@ -615,6 +615,45 @@ defmodule Lanttern.Reporting do |> maybe_preload(opts) end + @doc """ + Gets a single student report card based on given student and children strand report. + + Returns `nil` if the Student report card does not exist. + + ## Options + + - `:preloads` – preloads associated data + + ## Examples + + iex> get_student_report_card_by_student_and_strand_report(123, 123) + %StudentReportCard{} + + iex> get_student_report_card_by_student_and_strand_report(456, 456) + nil + + """ + @spec get_student_report_card_by_student_and_strand_report( + student_id :: pos_integer(), + strand_report_id :: pos_integer(), + opts :: Keyword.t() + ) :: StudentReportCard.t() | nil + def get_student_report_card_by_student_and_strand_report( + student_id, + strand_report_id, + opts \\ [] + ) do + from( + src in StudentReportCard, + join: rc in assoc(src, :report_card), + join: sr in assoc(rc, :strand_reports), + where: sr.id == ^strand_report_id, + where: src.student_id == ^student_id + ) + |> Repo.one() + |> maybe_preload(opts) + end + @doc """ Gets a single student report card by student and report card id. diff --git a/lib/lanttern_web/components/learning_context_components.ex b/lib/lanttern_web/components/learning_context_components.ex index 84f337cc..5d0c454f 100644 --- a/lib/lanttern_web/components/learning_context_components.ex +++ b/lib/lanttern_web/components/learning_context_components.ex @@ -94,6 +94,9 @@ defmodule LantternWeb.LearningContextComponents do

    + <.badge :if={@strand.report_cycle} theme="dark"> + <%= @strand.report_cycle.name %> + <.badge :for={subject <- @strand.subjects}> <%= Gettext.dgettext(LantternWeb.Gettext, "taxonomy", subject.name) %> diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex index f76671ab..85329458 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex +++ b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex @@ -1,4 +1,4 @@ -defmodule LantternWeb.StudentStrandReportLive.StudentNotesComponent do +defmodule LantternWeb.StudentReportCardStrandReportLive.StudentNotesComponent do use LantternWeb, :live_component alias Lanttern.Notes diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.ex b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.ex new file mode 100644 index 00000000..3a1bff2b --- /dev/null +++ b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.ex @@ -0,0 +1,143 @@ +defmodule LantternWeb.StudentReportCardStrandReportLive do + use LantternWeb, :live_view + + alias Lanttern.Identity.Profile + alias Lanttern.Reporting + import Lanttern.SupabaseHelpers, only: [object_url_to_render_url: 2] + + # page components + alias LantternWeb.StudentReportCardStrandReportLive.StudentNotesComponent + + # shared components + import LantternWeb.ReportingComponents + alias LantternWeb.Reporting.StrandReportOverviewComponent + alias LantternWeb.Reporting.StrandReportAssessmentComponent + alias LantternWeb.Reporting.StrandReportMomentsComponent + + @tabs %{ + "overview" => :overview, + "assessment" => :assessment, + "moments" => :moments, + "student_notes" => :student_notes + } + + # lifecycle + + @impl true + def mount(_params, _session, socket) do + socket = + socket + |> assign(:student_report_card, nil) + |> assign(:initialized, false) + + {:ok, socket, layout: {LantternWeb.Layouts, :app_logged_in_blank}} + end + + @impl true + def handle_params(params, _url, socket) do + socket = + socket + |> assign_student_report_card(params) + # check if user can view the strand report + |> check_if_user_has_access() + |> assign_strand_report(params) + |> assign_is_student() + |> assign(:params, params) + |> assign_current_tab(params) + |> assign(:initialized, true) + + {:noreply, socket} + end + + defp assign_student_report_card(%{assigns: %{initialized: false}} = socket, params) do + %{"student_report_card_id" => id} = params + + student_report_card = + Reporting.get_student_report_card!(id, + preloads: [ + :student, + report_card: :school_cycle + ] + ) + + assign(socket, :student_report_card, student_report_card) + end + + defp assign_student_report_card(socket, _params), do: socket + + defp check_if_user_has_access(%{assigns: %{student_report_card: nil}} = _socket), + do: raise(LantternWeb.NotFoundError) + + defp check_if_user_has_access(socket) do + %{current_user: current_user, student_report_card: student_report_card} = socket.assigns + # check if user can view the student strand report + # guardian and students can only view their own reports + # teachers can view only reports from their school + + report_card_student_id = student_report_card.student_id + report_card_student_school_id = student_report_card.student.school_id + allow_student_access = student_report_card.allow_student_access + allow_guardian_access = student_report_card.allow_guardian_access + + case current_user.current_profile do + %Profile{type: "guardian", guardian_of_student_id: student_id} + when student_id == report_card_student_id and allow_guardian_access -> + nil + + %Profile{type: "student", student_id: student_id} + when student_id == report_card_student_id and allow_student_access -> + nil + + %Profile{type: "teacher", school_id: school_id} + when school_id == report_card_student_school_id -> + nil + + _ -> + raise LantternWeb.NotFoundError + end + + socket + end + + defp assign_strand_report(%{assigns: %{initialized: false}} = socket, params) do + %{"strand_report_id" => strand_report_id} = params + student_report_card = socket.assigns.student_report_card + + strand_report = + Reporting.get_strand_report!(strand_report_id, + preloads: [strand: [:subjects, :years]] + ) + + cover_image_url = + object_url_to_render_url( + strand_report.cover_image_url || strand_report.strand.cover_image_url, + width: 1280, + height: 640 + ) + + page_title = + "#{strand_report.strand.name} • #{student_report_card.student.name} • #{student_report_card.report_card.name}" + + socket + |> assign(:strand_report, strand_report) + |> assign(:cover_image_url, cover_image_url) + |> assign(:page_title, page_title) + end + + defp assign_strand_report(socket, _params), do: socket + + defp assign_is_student(socket) do + # flag to control student notes UI + is_student = + socket.assigns.student_report_card.student_id == + socket.assigns.current_user.current_profile.student_id + + assign(socket, :is_student, is_student) + end + + defp assign_current_tab(socket, %{"tab" => tab}), + do: assign(socket, :current_tab, Map.get(@tabs, tab, :overview)) + + defp assign_current_tab(socket, _params), + do: assign(socket, :current_tab, :overview) +end diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex similarity index 89% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex rename to lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex index 97d02ca5..7a00fbb2 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex +++ b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex @@ -82,26 +82,35 @@
    <.live_component :if={@current_tab == :overview} - module={OverviewComponent} + module={StrandReportOverviewComponent} id="strand-overview" strand_report={@strand_report} + class="py-10" /> <.live_component :if={@current_tab == :assessment} - module={AssessmentComponent} + module={StrandReportAssessmentComponent} id="student-assessment" strand_report={@strand_report} student_report_card={@student_report_card} params={@params} + class="py-10" + base_path={ + ~p"/student_report_card/#{@student_report_card.id}/strand_report/#{@strand_report.id}?tab=assessment" + } /> <.live_component :if={@current_tab == :moments} - module={MomentsComponent} + module={StrandReportMomentsComponent} id="student-moments" strand_report={@strand_report} student_id={@student_report_card.student_id} student_report_card_id={@student_report_card.id} params={@params} + class="py-10" + base_path={ + ~p"/student_report_card/#{@student_report_card.id}/strand_report/#{@strand_report.id}?tab=moments" + } /> <.live_component :if={@current_tab == :student_notes} diff --git a/lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex b/lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex new file mode 100644 index 00000000..f76671ab --- /dev/null +++ b/lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex @@ -0,0 +1,79 @@ +defmodule LantternWeb.StudentStrandReportLive.StudentNotesComponent do + use LantternWeb, :live_component + + alias Lanttern.Notes + + # shared + alias LantternWeb.Attachments.AttachmentAreaComponent + alias LantternWeb.Notes.NoteComponent + + @impl true + def render(assigns) do + ~H""" +
    + <.responsive_container> + <.live_component + module={NoteComponent} + id="student-strand-notes" + note={@note} + current_user={@current_user} + strand_id={@strand_id} + title={ + if @is_student, + do: gettext("My strand notes"), + else: gettext("Student strand notes") + } + empty_msg={ + if @is_student, + do: gettext("You don't have any notes for this strand yet"), + else: gettext("No student notes for this strand") + } + empty_add_note_msg={gettext("Add a strand note")} + allow_editing={@is_student} + notify_component={@myself} + /> + <.live_component + :if={@note} + module={AttachmentAreaComponent} + id="student-strand-note-attachemnts" + class="mt-10" + current_user={@current_user} + note_id={@note.id} + title={gettext("Note's attachments")} + allow_editing={@is_student} + /> + +
    + """ + end + + # lifecycle + + @impl true + def mount(socket) do + {:ok, assign(socket, :is_editing, false)} + end + + @impl true + def update(%{action: {NoteComponent, {:saved, note}}}, socket) do + {:ok, assign(socket, :note, note)} + end + + def update(%{action: {NoteComponent, {:deleted, _note}}}, socket) do + {:ok, assign(socket, :note, nil)} + end + + def update(assigns, socket) do + %{student_id: student_id, strand_id: strand_id} = assigns + + note = + Notes.get_student_note(student_id, strand_id: strand_id) + + socket = + socket + |> assign(assigns) + |> assign(:note, note) + + {:ok, socket} + end +end diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.ex b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.ex similarity index 76% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.ex rename to lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.ex index 244dd502..85f6fca9 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.ex +++ b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.ex @@ -6,13 +6,12 @@ defmodule LantternWeb.StudentStrandReportLive do import Lanttern.SupabaseHelpers, only: [object_url_to_render_url: 2] # page components - alias LantternWeb.StudentStrandReportLive.OverviewComponent - alias LantternWeb.StudentStrandReportLive.AssessmentComponent - alias LantternWeb.StudentStrandReportLive.MomentsComponent alias LantternWeb.StudentStrandReportLive.StudentNotesComponent # shared components - import LantternWeb.ReportingComponents + alias LantternWeb.Reporting.StrandReportOverviewComponent + alias LantternWeb.Reporting.StrandReportAssessmentComponent + alias LantternWeb.Reporting.StrandReportMomentsComponent @tabs %{ "overview" => :overview, @@ -27,6 +26,7 @@ defmodule LantternWeb.StudentStrandReportLive do def mount(_params, _session, socket) do socket = socket + |> assign(:student_report_card, nil) |> assign(:initialized, false) {:ok, socket, layout: {LantternWeb.Layouts, :app_logged_in_blank}} @@ -37,7 +37,7 @@ defmodule LantternWeb.StudentStrandReportLive do socket = socket |> assign_student_report_card(params) - # check if user can view the student report + # check if user can view the strand report |> check_if_user_has_access() |> assign_strand_report(params) |> assign_is_student() @@ -49,10 +49,18 @@ defmodule LantternWeb.StudentStrandReportLive do end defp assign_student_report_card(%{assigns: %{initialized: false}} = socket, params) do - %{"id" => id} = params + %{"strand_report_id" => strand_report_id} = params + + # don't need to worry with other profile types + # (handled by :ensure_authenticated_student_or_guardian in router) + student_id = + case socket.assigns.current_user.current_profile do + %{type: "student"} = profile -> profile.student_id + %{type: "guardian"} = profile -> profile.guardian_of_student_id + end student_report_card = - Reporting.get_student_report_card!(id, + Reporting.get_student_report_card_by_student_and_strand_report(student_id, strand_report_id, preloads: [ :student, report_card: :school_cycle @@ -64,28 +72,23 @@ defmodule LantternWeb.StudentStrandReportLive do defp assign_student_report_card(socket, _params), do: socket + defp check_if_user_has_access(%{assigns: %{student_report_card: nil}} = _socket), + do: raise(LantternWeb.NotFoundError) + defp check_if_user_has_access(socket) do %{current_user: current_user, student_report_card: student_report_card} = socket.assigns # check if user can view the student strand report # guardian and students can only view their own reports - # teachers can view only reports from their school report_card_student_id = student_report_card.student_id - report_card_student_school_id = student_report_card.student.school_id - allow_student_access = student_report_card.allow_student_access - allow_guardian_access = student_report_card.allow_guardian_access case current_user.current_profile do %Profile{type: "guardian", guardian_of_student_id: student_id} - when student_id == report_card_student_id and allow_guardian_access -> + when student_id == report_card_student_id -> nil %Profile{type: "student", student_id: student_id} - when student_id == report_card_student_id and allow_student_access -> - nil - - %Profile{type: "teacher", school_id: school_id} - when school_id == report_card_student_school_id -> + when student_id == report_card_student_id -> nil _ -> diff --git a/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex new file mode 100644 index 00000000..9e40fe30 --- /dev/null +++ b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex @@ -0,0 +1,103 @@ +<.cover + size="sm" + theme="lime" + style={"background-image: url('#{@cover_image_url || "/images/cover-placeholder.jpg"}')"} +> + <:top> +
    + <.breadcrumbs with_bg> + <:item link={~p"/student_strands"}> + <%= gettext("Strands") %> + + <:item><%= gettext("Strand report") %> + + <.nav_menu_button /> +
    + +
    +

    <%= @strand_report.strand.name %>

    +

    + <%= @strand_report.strand.type %> +

    +
    +
    + <.badge theme="dark"> + <%= gettext("Cycle") %>: <%= @student_report_card.report_card.school_cycle.name %> + + <.badge :for={subject <- @strand_report.strand.subjects}> + <%= Gettext.dgettext(LantternWeb.Gettext, "taxonomy", subject.name) %> + + <.badge :for={year <- @strand_report.strand.years}> + <%= Gettext.dgettext(LantternWeb.Gettext, "taxonomy", year.name) %> + +
    + +
    + <.responsive_container class="flex items-center justify-between gap-10"> + <.nav_tabs id="strand-nav-tabs" class="flex-1 overflow-x-auto"> + <:tab + patch={~p"/strand_report/#{@strand_report}?tab=overview"} + is_current={@current_tab == :overview && "true"} + > + <%= gettext("Overview") %> + + <:tab + patch={~p"/strand_report/#{@strand_report}?tab=assessment"} + is_current={@current_tab == :assessment && "true"} + > + <%= gettext("Assessment") %> + + <:tab + patch={~p"/strand_report/#{@strand_report}?tab=moments"} + is_current={@current_tab == :moments && "true"} + > + <%= gettext("Moments") %> + + <:tab + patch={~p"/strand_report/#{@strand_report}?tab=student_notes"} + is_current={@current_tab == :student_notes && "true"} + > + <%= gettext("Student notes") %> + + + +
    +
    + <.live_component + :if={@current_tab == :overview} + module={StrandReportOverviewComponent} + id="strand-overview" + strand_report={@strand_report} + class="py-10" + /> + <.live_component + :if={@current_tab == :assessment} + module={StrandReportAssessmentComponent} + id="student-assessment" + strand_report={@strand_report} + student_report_card={@student_report_card} + params={@params} + class="py-10" + base_path={~p"/strand_report/#{@strand_report.id}?tab=assessment"} + /> + <.live_component + :if={@current_tab == :moments} + module={StrandReportMomentsComponent} + id="student-moments" + strand_report={@strand_report} + student_id={@student_report_card.student_id} + student_report_card_id={@student_report_card.id} + params={@params} + class="py-10" + base_path={~p"/strand_report/#{@strand_report.id}?tab=moments"} + /> + <.live_component + :if={@current_tab == :student_notes} + module={StudentNotesComponent} + id="student-strand-notes" + current_user={@current_user} + strand_id={@strand_report.strand_id} + student_id={@student_report_card.student_id} + is_student={@is_student} + /> +
    diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex index e111d165..28e8ddb9 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex @@ -40,6 +40,12 @@ defmodule LantternWeb.StudentStrandsLive do |> assign(:school, school) |> assign(:student_report_cards_cycles, student_report_cards_cycles) |> assign_user_filters([:cycles], socket.assigns.current_user) + # adjust dom id to prevent duplication + # (some strands can be in more than one report card at the same time) + |> stream_configure( + :student_strands, + dom_id: fn strand -> "student-strand-report-#{strand.strand_report_id}" end + ) |> stream_student_strands() {:ok, socket} diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex index 869554f3..dae80963 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex @@ -21,6 +21,7 @@ id={dom_id} strand={strand} cover_image_url={strand.cover_image_url} + navigate={~p"/strand_report/#{strand.strand_report_id}"} hide_description class="shrink-0 w-64 sm:w-auto" /> diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex similarity index 96% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex rename to lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex index 5dd6e1ee..8464bbf2 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex +++ b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex @@ -1,4 +1,4 @@ -defmodule LantternWeb.StudentStrandReportLive.StrandGoalDetailsComponent do +defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do use LantternWeb, :live_component alias Lanttern.Assessments @@ -182,11 +182,4 @@ defmodule LantternWeb.StudentStrandReportLive.StrandGoalDetailsComponent do |> stream(:moments_assessment_points_and_entries, moments_assessment_points_and_entries) |> assign(:has_formative_assessment, has_formative_assessment) end - - # # event handlers - - # @impl true - # def handle_event("set_info_level", %{"level" => level}, socket) do - # {:noreply, assign(socket, :info_level, level)} - # end end diff --git a/lib/lanttern_web/live/shared/menu_component.ex b/lib/lanttern_web/live/shared/menu_component.ex index 3215e15c..ed675e62 100644 --- a/lib/lanttern_web/live/shared/menu_component.ex +++ b/lib/lanttern_web/live/shared/menu_component.ex @@ -57,7 +57,7 @@ defmodule LantternWeb.MenuComponent do <% end %> <%= if @current_profile.type == "student" do %> - <.nav_item active={@active_nav == :student_home} path={~p"/student"}> + <.nav_item active={@active_nav == :student_report_card} path={~p"/student"}> <%= gettext("Report cards") %> <.nav_item active={@active_nav == :student_strands} path={~p"/student_strands"}> @@ -69,7 +69,7 @@ defmodule LantternWeb.MenuComponent do <% end %> <%= if @current_profile.type == "guardian" do %> - <.nav_item active={@active_nav == :guardian_home} path={~p"/guardian"}> + <.nav_item active={@active_nav == :student_report_card} path={~p"/guardian"}> <%= gettext("Report cards") %> <.nav_item active={@active_nav == :student_strands} path={~p"/student_strands"}> @@ -349,14 +349,18 @@ defmodule LantternWeb.MenuComponent do LantternWeb.GradesReportsLive => :grading, # guardian home - LantternWeb.GuardianHomeLive => :guardian_home, + LantternWeb.GuardianHomeLive => :student_report_card, # student home - LantternWeb.StudentHomeLive => :student_home, - LantternWeb.StudentReportCardLive => :student_home, + LantternWeb.StudentHomeLive => :student_report_card, + + # student report card + LantternWeb.StudentReportCardLive => :student_report_card, + LantternWeb.StudentReportCardStrandReportLive => :student_report_card, # student strands - LantternWeb.StudentStrandsLive => :student_strands + LantternWeb.StudentStrandsLive => :student_strands, + LantternWeb.StudentStrandReportLive => :student_strands } def mount(socket) do diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex similarity index 93% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex rename to lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex index 03f245b4..bf65cf76 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex @@ -1,10 +1,10 @@ -defmodule LantternWeb.StudentStrandReportLive.AssessmentComponent do +defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do use LantternWeb, :live_component alias Lanttern.Assessments # page components - alias LantternWeb.StudentStrandReportLive.StrandGoalDetailsComponent + alias LantternWeb.Assessments.StrandGoalDetailsOverlayComponent # shared components import LantternWeb.AssessmentsComponents @@ -13,7 +13,7 @@ defmodule LantternWeb.StudentStrandReportLive.AssessmentComponent do @impl true def render(assigns) do ~H""" -
    +
    <.responsive_container>

    <%= gettext( @@ -25,9 +25,7 @@ defmodule LantternWeb.StudentStrandReportLive.AssessmentComponent do

    <.link :for={{goal, entry, moment_entries} <- @strand_goals_student_entries} - patch={ - ~p"/student_report_card/#{@student_report_card.id}/strand_report/#{@strand_report.id}?tab=assessment&strand_goal_id=#{goal.id}" - } + patch={"#{@base_path}&strand_goal_id=#{goal.id}"} class={[ "group/card block mt-4", "sm:grid sm:grid-cols-[minmax(10px,_3fr)_minmax(10px,_2fr)]" @@ -94,15 +92,11 @@ defmodule LantternWeb.StudentStrandReportLive.AssessmentComponent do <.live_component :if={@strand_goal_id} - module={StrandGoalDetailsComponent} + module={StrandGoalDetailsOverlayComponent} id="assessment-point-details-component" strand_goal_id={@strand_goal_id} student_id={@student_report_card.student_id} - on_cancel={ - JS.patch( - ~p"/student_report_card/#{@student_report_card.id}/strand_report/#{@strand_report.id}?tab=assessment" - ) - } + on_cancel={JS.patch(@base_path)} />
    """ @@ -198,6 +192,7 @@ defmodule LantternWeb.StudentStrandReportLive.AssessmentComponent do def mount(socket) do socket = socket + |> assign(:class, nil) |> assign(:strand_goal_id, nil) |> assign(:initialized, false) diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex similarity index 89% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex rename to lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex index 1bd387da..f59a6fa4 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex @@ -1,4 +1,4 @@ -defmodule LantternWeb.StudentStrandReportLive.MomentsComponent do +defmodule LantternWeb.Reporting.StrandReportMomentsComponent do alias Lanttern.LearningContext use LantternWeb, :live_component @@ -11,7 +11,7 @@ defmodule LantternWeb.StudentStrandReportLive.MomentsComponent do @impl true def render(assigns) do ~H""" -
    +
    <.responsive_container>

    <%= gettext("Here you'll find information about the strand learning journey.") %> @@ -26,9 +26,7 @@ defmodule LantternWeb.StudentStrandReportLive.MomentsComponent do <.link :for={{dom_id, {moment, entries}} <- @streams.moments_and_entries} id={dom_id} - patch={ - ~p"/student_report_card/#{@student_report_card_id}/strand_report/#{@strand_report.id}?tab=moments&moment_id=#{moment.id}" - } + patch={"#{@base_path}&moment_id=#{moment.id}"} class="group block mt-4" > <.card_base class={[ @@ -62,16 +60,7 @@ defmodule LantternWeb.StudentStrandReportLive.MomentsComponent do <% end %> - <.slide_over - :if={@moment} - id="moment-overlay" - show={true} - on_cancel={ - JS.patch( - ~p"/student_report_card/#{@student_report_card_id}/strand_report/#{@strand_report.id}?tab=moments" - ) - } - > + <.slide_over :if={@moment} id="moment-overlay" show={true} on_cancel={JS.patch(@base_path)}> <:title><%= @moment.name %>

    <.moment_assessment_point_entry @@ -95,6 +84,7 @@ defmodule LantternWeb.StudentStrandReportLive.MomentsComponent do def mount(socket) do socket = socket + |> assign(:class, nil) |> assign(:moment, nil) |> assign(:initialized, false) |> stream_configure( diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex similarity index 90% rename from lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex rename to lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex index 7bf443b9..2f1499c5 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex @@ -1,4 +1,4 @@ -defmodule LantternWeb.StudentStrandReportLive.OverviewComponent do +defmodule LantternWeb.Reporting.StrandReportOverviewComponent do use LantternWeb, :live_component alias Lanttern.Rubrics @@ -9,7 +9,7 @@ defmodule LantternWeb.StudentStrandReportLive.OverviewComponent do @impl true def render(assigns) do ~H""" -
    +
    <.responsive_container> <.markdown :if={@strand_report.description} text={@strand_report.description} />
    @@ -44,6 +44,15 @@ defmodule LantternWeb.StudentStrandReportLive.OverviewComponent do # lifecycle + @impl true + def mount(socket) do + socket = + socket + |> assign(:class, nil) + + {:ok, socket} + end + @impl true def update(assigns, socket) do socket = diff --git a/lib/lanttern_web/router.ex b/lib/lanttern_web/router.ex index e6cd9942..0ef639f5 100644 --- a/lib/lanttern_web/router.ex +++ b/lib/lanttern_web/router.ex @@ -131,6 +131,17 @@ defmodule LantternWeb.Router do live "/student", StudentHomeLive end + live_session :authenticated_student_or_guardian, + layout: {LantternWeb.Layouts, :app_logged_in}, + on_mount: [ + {LantternWeb.UserAuth, :ensure_authenticated_student_or_guardian}, + {LantternWeb.Path, :put_path_in_socket} + ] do + live "/strand_report/:strand_report_id", + StudentStrandReportLive, + :show + end + live_session :authenticated_user, layout: {LantternWeb.Layouts, :app_logged_in}, on_mount: [ @@ -141,8 +152,8 @@ defmodule LantternWeb.Router do live "/student_report_card/:id", StudentReportCardLive, :show - live "/student_report_card/:id/strand_report/:strand_report_id", - StudentStrandReportLive, + live "/student_report_card/:student_report_card_id/strand_report/:strand_report_id", + StudentReportCardStrandReportLive, :show end end diff --git a/lib/lanttern_web/user_auth.ex b/lib/lanttern_web/user_auth.ex index 5783220b..fb271d08 100644 --- a/lib/lanttern_web/user_auth.ex +++ b/lib/lanttern_web/user_auth.ex @@ -253,6 +253,12 @@ defmodule LantternWeb.UserAuth do |> ensure_authenticated("guardian") end + def on_mount(:ensure_authenticated_student_or_guardian, _params, session, socket) do + socket + |> mount_current_user(session) + |> ensure_authenticated(["student", "guardian"]) + end + def on_mount(:redirect_if_user_is_authenticated, _params, session, socket) do socket = mount_current_user(socket, session) @@ -286,11 +292,32 @@ defmodule LantternWeb.UserAuth do end end + defp ensure_authenticated(socket, profile_types) when is_list(profile_types) do + case socket.assigns.current_user do + %User{current_profile: %{type: profile_type}} -> + if profile_type in profile_types do + {:cont, socket} + else + ensure_authenticated_redirect(socket) + end + + _ -> + ensure_authenticated_redirect(socket) + end + end + defp ensure_authenticated(socket, profile_type) do case socket.assigns.current_user do %User{current_profile: %{type: ^profile_type}} -> {:cont, socket} + _ -> + ensure_authenticated_redirect(socket) + end + end + + defp ensure_authenticated_redirect(socket) do + case socket.assigns.current_user do %User{current_profile: %{type: "teacher"}} -> socket = socket diff --git a/test/lanttern/learning_context_test.exs b/test/lanttern/learning_context_test.exs index 63a8d469..a0ffb61d 100644 --- a/test/lanttern/learning_context_test.exs +++ b/test/lanttern/learning_context_test.exs @@ -111,7 +111,9 @@ defmodule Lanttern.LearningContextTest do strand_2 = strand_fixture() strand_3 = strand_fixture() - strand_4 = strand_fixture() + + # use same strand in different reports + strand_4 = strand_2 cycle_2024 = Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2024-01-01], end_at: ~D[2024-12-31]) @@ -127,25 +129,25 @@ defmodule Lanttern.LearningContextTest do # create strand reports - _strand_report_1_2024 = + strand_report_1_2024 = Lanttern.ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card_2024.id, strand_id: strand_1.id }) - _strand_report_2_2024 = + strand_report_2_2024 = Lanttern.ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card_2024.id, strand_id: strand_2.id }) - _strand_report_3_2023 = + strand_report_3_2023 = Lanttern.ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card_2023.id, strand_id: strand_3.id }) - _strand_report_4_2023 = + strand_report_4_2023 = Lanttern.ReportingFixtures.strand_report_fixture(%{ report_card_id: report_card_2023.id, strand_id: strand_4.id @@ -195,12 +197,20 @@ defmodule Lanttern.LearningContextTest do assert subject_1 in expected_strand_1.subjects assert subject_2 in expected_strand_1.subjects assert [year] == expected_strand_1.years + assert expected_strand_1.strand_report_id == strand_report_1_2024.id + assert expected_strand_1.report_cycle == cycle_2024 assert expected_strand_2.id == strand_2.id + assert expected_strand_2.strand_report_id == strand_report_2_2024.id + assert expected_strand_2.report_cycle == cycle_2024 assert expected_strand_3.id == strand_3.id + assert expected_strand_3.strand_report_id == strand_report_3_2023.id + assert expected_strand_3.report_cycle == cycle_2023 assert expected_strand_4.id == strand_4.id + assert expected_strand_4.strand_report_id == strand_report_4_2023.id + assert expected_strand_4.report_cycle == cycle_2023 end test "search_strands/2 returns all items matched by search" do diff --git a/test/lanttern/reporting_test.exs b/test/lanttern/reporting_test.exs index 065182fe..118bc509 100644 --- a/test/lanttern/reporting_test.exs +++ b/test/lanttern/reporting_test.exs @@ -551,6 +551,21 @@ defmodule Lanttern.ReportingTest do assert expected.report_card == report_card end + test "get_student_report_card_by_student_and_strand_report/2 returns the student_report_card" do + student = SchoolsFixtures.student_fixture() + report_card = report_card_fixture() + + student_report_card = + student_report_card_fixture(%{student_id: student.id, report_card_id: report_card.id}) + + strand_report = strand_report_fixture(%{report_card_id: report_card.id}) + + assert Reporting.get_student_report_card_by_student_and_strand_report( + student.id, + strand_report.id + ) == student_report_card + end + test "get_student_report_card_by_student_and_parent_report/2 returns the student_report_card" do student = SchoolsFixtures.student_fixture() report_card = report_card_fixture() diff --git a/test/lanttern_web/live/pages/strand_report/id/student_strand_report_live_test.exs b/test/lanttern_web/live/pages/strand_report/id/student_strand_report_live_test.exs new file mode 100644 index 00000000..02ae779c --- /dev/null +++ b/test/lanttern_web/live/pages/strand_report/id/student_strand_report_live_test.exs @@ -0,0 +1,105 @@ +defmodule LantternWeb.StudentStrandReportLiveTest do + use LantternWeb.ConnCase + + import Lanttern.ReportingFixtures + + alias Lanttern.LearningContextFixtures + alias Lanttern.SchoolsFixtures + + @live_view_path_base "/strand_report" + + describe "Student strand report live view basic navigation" do + test "disconnected and connected mount", context do + %{conn: conn, student: student} = register_and_log_in_student(context) + + report_card = report_card_fixture(%{name: "Some report card name abc"}) + + _student_report_card = + student_report_card_fixture(%{report_card_id: report_card.id, student_id: student.id}) + + strand = LearningContextFixtures.strand_fixture(%{name: "Some strand name for report"}) + + strand_report = + strand_report_fixture(%{report_card_id: report_card.id, strand_id: strand.id}) + + conn = + get( + conn, + "#{@live_view_path_base}/#{strand_report.id}" + ) + + response = html_response(conn, 200) + assert response =~ ~r"

    \s*Some strand name for report\s*<\/h1>" + + {:ok, _view, _html} = live(conn) + end + + test "display student strand report correctly for students", context do + %{conn: conn, student: student} = register_and_log_in_student(context) + + cycle = SchoolsFixtures.cycle_fixture(%{name: "Cycle 2024"}) + + report_card = + report_card_fixture(%{school_cycle_id: cycle.id, name: "Some report card name abc"}) + + _student_report_card = + student_report_card_fixture(%{ + report_card_id: report_card.id, + student_id: student.id + }) + + strand = + LearningContextFixtures.strand_fixture(%{ + name: "Strand for report ABC" + }) + + strand_report = + strand_report_fixture(%{ + report_card_id: report_card.id, + strand_id: strand.id + }) + + {:ok, view, _html} = + live( + conn, + "#{@live_view_path_base}/#{strand_report.id}" + ) + + assert view |> has_element?("h1", "Strand for report ABC") + end + + test "display student strand report correctly for guardians", context do + %{conn: conn, student: student} = register_and_log_in_guardian(context) + + cycle = SchoolsFixtures.cycle_fixture(%{name: "Cycle 2024"}) + + report_card = + report_card_fixture(%{school_cycle_id: cycle.id, name: "Some report card name abc"}) + + _student_report_card = + student_report_card_fixture(%{ + report_card_id: report_card.id, + student_id: student.id + }) + + strand = + LearningContextFixtures.strand_fixture(%{ + name: "Strand for report ABC" + }) + + strand_report = + strand_report_fixture(%{ + report_card_id: report_card.id, + strand_id: strand.id + }) + + {:ok, view, _html} = + live( + conn, + "#{@live_view_path_base}/#{strand_report.id}" + ) + + assert view |> has_element?("h1", "Strand for report ABC") + end + end +end diff --git a/test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live_test.exs b/test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live_test.exs similarity index 98% rename from test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live_test.exs rename to test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live_test.exs index 02c93100..599dfb7d 100644 --- a/test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live_test.exs +++ b/test/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live_test.exs @@ -1,4 +1,4 @@ -defmodule LantternWeb.StudentStrandReportLiveTest do +defmodule LantternWeb.StudentReportCardStrandReportLiveTest do use LantternWeb.ConnCase import Lanttern.ReportingFixtures From ba0d11566aba61e2600e77ee26f041ea4e35fe3b Mon Sep 17 00:00:00 2001 From: endoooo Date: Fri, 30 Aug 2024 13:31:07 -0300 Subject: [PATCH 04/11] feat: added diff rubrics info in strand report overview - created `Rubrics.list_strand_diff_rubrics_for_student_id/2` - minor UI adjustment in `<.rubric_descriptors>` component --- lib/lanttern/rubrics.ex | 44 +++++++++- .../components/rubrics_components.ex | 8 +- ...t_report_card_strand_report_live.html.heex | 1 + .../id/student_strand_report_live.html.heex | 1 + .../strand_goal_details_overlay_component.ex | 10 +++ .../strand_report_assessment_component.ex | 11 +++ .../strand_report_moments_component.ex | 12 +++ .../strand_report_overview_component.ex | 88 +++++++++++++++---- test/lanttern/rubrics_test.exs | 73 ++++++++++++++- 9 files changed, 220 insertions(+), 28 deletions(-) diff --git a/lib/lanttern/rubrics.ex b/lib/lanttern/rubrics.ex index e238f1df..5d3fce51 100644 --- a/lib/lanttern/rubrics.ex +++ b/lib/lanttern/rubrics.ex @@ -94,8 +94,8 @@ defmodule Lanttern.Rubrics do Preloads scale, descriptors, and descriptors ordinal values. - Preloads curriculum item and curriculum component - (linked through strand goal/assessment point). + Preloads curriculum item and curriculum component, and marks + the rubric with `is_differentiation` based on strand goal/assessment point. View `get_full_rubric!/1` for more details on descriptors sorting. @@ -114,6 +114,46 @@ defmodule Lanttern.Rubrics do join: cc in assoc(ci, :curriculum_component), where: ap.strand_id == ^strand_id, order_by: ap.position, + select: %{ + r + | curriculum_item: %{ci | curriculum_component: cc}, + is_differentiation: ap.is_differentiation + } + ) + |> Repo.all() + end + + @doc """ + Returns the list of strand diff rubrics for given student. + + Preloads scale, descriptors, and descriptors ordinal values. + + Preloads curriculum item and curriculum component + (linked through strand goal/assessment point). + + View `get_full_rubric!/1` for more details on descriptors sorting. + + ## Examples + + iex> list_strand_rubrics() + [%Rubric{}, ...] + + """ + @spec list_strand_diff_rubrics_for_student_id( + student_id :: pos_integer(), + strand_id :: pos_integer() + ) :: [Rubric.t()] + def list_strand_diff_rubrics_for_student_id(student_id, strand_id) do + from( + r in full_rubric_query(), + join: drs in "differentiation_rubrics_students", + on: drs.rubric_id == r.id and drs.student_id == ^student_id, + join: pr in assoc(r, :parent_rubric), + join: ap in assoc(pr, :assessment_points), + join: ci in assoc(ap, :curriculum_item), + join: cc in assoc(ci, :curriculum_component), + where: ap.strand_id == ^strand_id, + order_by: ap.position, select: %{r | curriculum_item: %{ci | curriculum_component: cc}} ) |> Repo.all() diff --git a/lib/lanttern_web/components/rubrics_components.ex b/lib/lanttern_web/components/rubrics_components.ex index 97efa3b3..7f36faa2 100644 --- a/lib/lanttern_web/components/rubrics_components.ex +++ b/lib/lanttern_web/components/rubrics_components.ex @@ -41,7 +41,7 @@ defmodule LantternWeb.RubricsComponents do
    <%= if descriptor.scale_type == "numeric" do %> <.badge theme="dark"><%= descriptor.score %> @@ -50,11 +50,7 @@ defmodule LantternWeb.RubricsComponents do <%= descriptor.ordinal_value.name %> <% end %> - <.markdown - text={descriptor.descriptor} - size="sm" - class="flex-1 w-full p-2 border border-ltrn-lighter rounded-sm bg-ltrn-lightest" - /> + <.markdown text={descriptor.descriptor} size="sm" class="flex-1 w-full" />
    """ diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex index 7a00fbb2..43cf39c0 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex +++ b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex @@ -85,6 +85,7 @@ module={StrandReportOverviewComponent} id="strand-overview" strand_report={@strand_report} + student_id={@student_report_card.student_id} class="py-10" /> <.live_component diff --git a/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex index 9e40fe30..91cdca74 100644 --- a/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex +++ b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex @@ -68,6 +68,7 @@ module={StrandReportOverviewComponent} id="strand-overview" strand_report={@strand_report} + student_id={@student_report_card.student_id} class="py-10" /> <.live_component diff --git a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex index 8464bbf2..fcbd47f9 100644 --- a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex +++ b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex @@ -1,4 +1,14 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do + @moduledoc """ + Renders a strand goal info overlay. + + ### Required attrs: + + - `strand_goal_id` + - `student_id` + - `on_cancel` - a `%JS{}` struct to execute on overlay close + """ + use LantternWeb, :live_component alias Lanttern.Assessments diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex index bf65cf76..0da87bca 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex @@ -1,4 +1,15 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do + @moduledoc """ + Renders assessment info related to a `StrandReport`. + + ### Required attrs: + + -`strand_report` - `%StrandReport{}` + -`student_report_card` - `%StudentReportCard{}` + -`params` - the URL params from parent view `handle_params/3` + -`base_path` - the base URL path for overlay navigation control + """ + use LantternWeb, :live_component alias Lanttern.Assessments diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex index f59a6fa4..adb86155 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex @@ -1,4 +1,16 @@ defmodule LantternWeb.Reporting.StrandReportMomentsComponent do + @moduledoc """ + Renders moments info related to a `StrandReport`. + + ### Required attrs: + + -`strand_report` - `%StrandReport{}` + -`student_id` + -`student_report_card_id` + -`params` - the URL params from parent view `handle_params/3` + -`base_path` - the base URL path for overlay navigation control + """ + alias Lanttern.LearningContext use LantternWeb, :live_component diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex index 2f1499c5..6eb6f25f 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex @@ -1,7 +1,17 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do + @moduledoc """ + Renders the overview content of a `StrandReport`. + + ### Required attrs: + + - `strand_report` - `%StrandReport{}` + - `student_id` + """ + use LantternWeb, :live_component alias Lanttern.Rubrics + alias Lanttern.Rubrics.Rubric # shared components import LantternWeb.RubricsComponents @@ -14,25 +24,8 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do <.markdown :if={@strand_report.description} text={@strand_report.description} />

    <%= gettext("Strand rubrics") %>

    - <.card_base :for={{dom_id, rubric} <- @streams.rubrics} id={dom_id} class="mt-6"> -
    -

    - <%= rubric.curriculum_item.curriculum_component.name %> - <%= rubric.curriculum_item.name %> -

    -

    - <%= gettext("Criteria:") %> - <%= rubric.criteria %> -

    -
    -
    - <%!-- extra div with min-w-min prevent clamped right padding issue --%> - <%!-- https://stackoverflow.com/a/26892899 --%> -
    - <.rubric_descriptors rubric={rubric} /> -
    -
    - + <.rubric_card :for={{dom_id, rubric} <- @streams.rubrics} id={dom_id} rubric={rubric} /> + <.rubric_card :for={{dom_id, rubric} <- @streams.diff_rubrics} id={dom_id} rubric={rubric} />
    <.empty_state :if={!@strand_report.description && !@has_rubric}> <%= gettext("No strand report info yet.") %> @@ -42,6 +35,50 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do """ end + attr :id, :string, required: true + attr :rubric, Rubric, required: true + + def rubric_card(assigns) do + {is_diff, diff_type} = + case assigns.rubric do + %{is_differentiation: true} -> {true, :curriculum} + %{diff_for_rubric_id: parent_rubric} when not is_nil(parent_rubric) -> {true, :rubric} + _ -> {false, nil} + end + + assigns = + assigns + |> assign(:is_diff, is_diff) + |> assign(:diff_type, diff_type) + + ~H""" + <.card_base id={@id} class={["mt-6", if(@is_diff, do: "border border-ltrn-diff-accent")]}> +
    +

    + <%= if @diff_type == :curriculum, + do: gettext("Curriculum differentiation"), + else: gettext("Rubric differentiation") %> +

    +

    + <%= @rubric.curriculum_item.curriculum_component.name %> + <%= @rubric.curriculum_item.name %> +

    +

    + <%= gettext("Criteria:") %> + <%= @rubric.criteria %> +

    +
    +
    + <%!-- extra div with min-w-min prevent clamped right padding issue --%> + <%!-- https://stackoverflow.com/a/26892899 --%> +
    + <.rubric_descriptors rubric={@rubric} /> +
    +
    + + """ + end + # lifecycle @impl true @@ -59,6 +96,7 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do socket |> assign(assigns) |> stream_strand_rubrics() + |> stream_diff_rubrics() {:ok, socket} end @@ -71,4 +109,16 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do |> stream(:rubrics, rubrics) |> assign(:has_rubric, rubrics != []) end + + defp stream_diff_rubrics(socket) do + diff_rubrics = + Rubrics.list_strand_diff_rubrics_for_student_id( + socket.assigns.student_id, + socket.assigns.strand_report.strand_id + ) + + socket + |> stream(:diff_rubrics, diff_rubrics) + |> assign(:has_diff_rubric, diff_rubrics != []) + end end diff --git a/test/lanttern/rubrics_test.exs b/test/lanttern/rubrics_test.exs index e3ebf813..2544b57f 100644 --- a/test/lanttern/rubrics_test.exs +++ b/test/lanttern/rubrics_test.exs @@ -223,7 +223,8 @@ defmodule Lanttern.RubricsTest do assessment_point_fixture(%{ rubric_id: rubric_2.id, strand_id: strand.id, - curriculum_item_id: curriculum_item_2.id + curriculum_item_id: curriculum_item_2.id, + is_differentiation: true }) # extra fixtures for filter test @@ -241,6 +242,7 @@ defmodule Lanttern.RubricsTest do assert expected_descriptor_1_2.id == descriptor_1_2.id assert expected_rubric_1.curriculum_item.id == curriculum_item_1.id assert expected_rubric_1.curriculum_item.curriculum_component.id == curriculum_component.id + refute expected_rubric_1.is_differentiation assert expected_rubric_2.id == rubric_2.id [expected_descriptor_2_1, expected_descriptor_2_2] = expected_rubric_2.descriptors @@ -248,6 +250,75 @@ defmodule Lanttern.RubricsTest do assert expected_descriptor_2_2.id == descriptor_2_2.id assert expected_rubric_2.curriculum_item.id == curriculum_item_2.id assert expected_rubric_2.curriculum_item.curriculum_component.id == curriculum_component.id + assert expected_rubric_2.is_differentiation + end + + test "list_strand_diff_rubrics_for_student_id/2 returns all strand diff rubrics with descriptors preloaded and ordered correctly" do + scale = GradingFixtures.scale_fixture(%{type: "ordinal"}) + ov_1 = GradingFixtures.ordinal_value_fixture(%{scale_id: scale.id, normalized_value: 0.1}) + ov_2 = GradingFixtures.ordinal_value_fixture(%{scale_id: scale.id, normalized_value: 0.2}) + + rubric = rubric_fixture(%{scale_id: scale.id}) + diff_rubric = rubric_fixture(%{scale_id: scale.id, diff_for_rubric_id: rubric.id}) + + student = Lanttern.SchoolsFixtures.student_fixture() + + Lanttern.Repo.insert_all( + "differentiation_rubrics_students", + [[rubric_id: diff_rubric.id, student_id: student.id]] + ) + + descriptor_1 = + rubric_descriptor_fixture(%{ + rubric_id: diff_rubric.id, + scale_id: scale.id, + scale_type: scale.type, + ordinal_value_id: ov_1.id + }) + + descriptor_2 = + rubric_descriptor_fixture(%{ + rubric_id: diff_rubric.id, + scale_id: scale.id, + scale_type: scale.type, + ordinal_value_id: ov_2.id + }) + + strand = Lanttern.LearningContextFixtures.strand_fixture() + curriculum_component = Lanttern.CurriculaFixtures.curriculum_component_fixture() + + curriculum_item = + Lanttern.CurriculaFixtures.curriculum_item_fixture(%{ + curriculum_component_id: curriculum_component.id + }) + + _assessment_point = + assessment_point_fixture(%{ + rubric_id: rubric.id, + strand_id: strand.id, + curriculum_item_id: curriculum_item.id + }) + + # extra fixtures for filter test + other_strand = Lanttern.LearningContextFixtures.strand_fixture() + other_rubric = rubric_fixture(%{scale_id: scale.id}) + assessment_point_fixture(%{rubric_id: other_rubric.id, strand_id: other_strand.id}) + rubric_fixture(%{scale_id: scale.id}) + + [expected_diff_rubric] = + Rubrics.list_strand_diff_rubrics_for_student_id(student.id, strand.id) + + assert expected_diff_rubric.id == diff_rubric.id + + [expected_descriptor_1, expected_descriptor_2] = + expected_diff_rubric.descriptors + + assert expected_descriptor_1.id == descriptor_1.id + assert expected_descriptor_2.id == descriptor_2.id + assert expected_diff_rubric.curriculum_item.id == curriculum_item.id + + assert expected_diff_rubric.curriculum_item.curriculum_component.id == + curriculum_component.id end test "search_rubrics/2 returns all rubrics matched by search" do From 094512dc59be6afba1cc6fdd2bf196ba56461292 Mon Sep 17 00:00:00 2001 From: endoooo Date: Fri, 30 Aug 2024 14:23:33 -0300 Subject: [PATCH 05/11] chore: added support to render strand description as a fallback to strand report description --- .../strand_report_overview_component.ex | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex index 6eb6f25f..2d3eaeea 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex @@ -2,10 +2,11 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do @moduledoc """ Renders the overview content of a `StrandReport`. - ### Required attrs: + ### Required attrs - `strand_report` - `%StrandReport{}` - `student_id` + """ use LantternWeb, :live_component @@ -21,13 +22,13 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do ~H"""
    <.responsive_container> - <.markdown :if={@strand_report.description} text={@strand_report.description} /> -
    + <.markdown :if={@description} text={@description} /> +

    <%= gettext("Strand rubrics") %>

    <.rubric_card :for={{dom_id, rubric} <- @streams.rubrics} id={dom_id} rubric={rubric} /> <.rubric_card :for={{dom_id, rubric} <- @streams.diff_rubrics} id={dom_id} rubric={rubric} />
    - <.empty_state :if={!@strand_report.description && !@has_rubric}> + <.empty_state :if={!@description && !@has_rubric}> <%= gettext("No strand report info yet.") %> @@ -95,12 +96,32 @@ defmodule LantternWeb.Reporting.StrandReportOverviewComponent do socket = socket |> assign(assigns) + |> assign_description() |> stream_strand_rubrics() |> stream_diff_rubrics() {:ok, socket} end + defp assign_description(socket) do + # we try to use the strand report description + # and we fall back to the strand description + + description = + case socket.assigns.strand_report do + %{description: strand_report_desc} when is_binary(strand_report_desc) -> + strand_report_desc + + %{strand: %{description: strand_desc}} when is_binary(strand_desc) -> + strand_desc + + _ -> + nil + end + + assign(socket, :description, description) + end + defp stream_strand_rubrics(socket) do rubrics = Rubrics.list_strand_rubrics(socket.assigns.strand_report.strand_id) From b96113283aff0f2e226b07fcb3a04cc4585b845b Mon Sep 17 00:00:00 2001 From: endoooo Date: Fri, 30 Aug 2024 16:37:39 -0300 Subject: [PATCH 06/11] chore: adjuste student strands page to filter results by only one cycle - removed cycle badge from `<.strand_card>` component - adjusted `InlineFiltersComponent` to support `is_single` and `hide_all_opt` attrs, allowing the inline filter to have a tab-like UX --- .../components/learning_context_components.ex | 3 --- .../student_strands/student_strands_live.ex | 21 +++++++++++++++++++ .../student_strands_live.html.heex | 2 ++ .../filters/inline_filters_component.ex | 15 +++++++++++++ test/lanttern/learning_context_test.exs | 2 +- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/lanttern_web/components/learning_context_components.ex b/lib/lanttern_web/components/learning_context_components.ex index 5d0c454f..84f337cc 100644 --- a/lib/lanttern_web/components/learning_context_components.ex +++ b/lib/lanttern_web/components/learning_context_components.ex @@ -94,9 +94,6 @@ defmodule LantternWeb.LearningContextComponents do

    - <.badge :if={@strand.report_cycle} theme="dark"> - <%= @strand.report_cycle.name %> - <.badge :for={subject <- @strand.subjects}> <%= Gettext.dgettext(LantternWeb.Gettext, "taxonomy", subject.name) %> diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex index 28e8ddb9..056adbf9 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex @@ -40,6 +40,7 @@ defmodule LantternWeb.StudentStrandsLive do |> assign(:school, school) |> assign(:student_report_cards_cycles, student_report_cards_cycles) |> assign_user_filters([:cycles], socket.assigns.current_user) + |> adjust_cycles_filter() # adjust dom id to prevent duplication # (some strands can be in more than one report card at the same time) |> stream_configure( @@ -58,6 +59,26 @@ defmodule LantternWeb.StudentStrandsLive do defp check_if_user_has_access(_profile), do: raise(LantternWeb.NotFoundError) + # if no cycle is selected, select the most recent (the last one) + defp adjust_cycles_filter(%{assigns: %{selected_cycles_ids: []}} = socket) do + case socket.assigns.student_report_cards_cycles do + [] -> + socket + + cycles -> + last_cycle = List.last(cycles) + + socket + |> assign(:selected_cycles_ids, [last_cycle.id]) + |> save_profile_filters( + socket.assigns.current_user, + [:cycles] + ) + end + end + + defp adjust_cycles_filter(socket), do: socket + defp stream_student_strands(socket) do student_id = case socket.assigns.current_user.current_profile do diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex index dae80963..adf162d1 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex @@ -8,6 +8,8 @@ all_text={gettext("All cycles")} class="mt-10" notify_parent + is_single + hide_all_opt />
    <.empty_state> diff --git a/lib/lanttern_web/live/shared/filters/inline_filters_component.ex b/lib/lanttern_web/live/shared/filters/inline_filters_component.ex index e6eb06ac..d7f3899f 100644 --- a/lib/lanttern_web/live/shared/filters/inline_filters_component.ex +++ b/lib/lanttern_web/live/shared/filters/inline_filters_component.ex @@ -14,6 +14,7 @@ defmodule LantternWeb.Filters.InlineFiltersComponent do ~H"""
    <.badge_button + :if={!@hide_all_opt} id={"#{@id}-all"} phx-click={JS.push("toggle_all", target: @myself)} {get_select_all_attrs(@selected_items_ids)} @@ -74,6 +75,8 @@ defmodule LantternWeb.Filters.InlineFiltersComponent do socket = socket |> assign(:class, nil) + |> assign(:hide_all_opt, false) + |> assign(:is_single, false) |> assign(:all_text, gettext("All")) {:ok, socket} @@ -93,6 +96,12 @@ defmodule LantternWeb.Filters.InlineFiltersComponent do # event handlers @impl true + def handle_event("toggle_all", _params, %{assigns: %{is_single: true}} = socket) do + notify(__MODULE__, {:apply, []}, socket.assigns) + + {:noreply, socket} + end + def handle_event("toggle_all", _params, socket) do socket = socket @@ -102,6 +111,12 @@ defmodule LantternWeb.Filters.InlineFiltersComponent do {:noreply, socket} end + def handle_event("toggle_filter", %{"id" => id}, %{assigns: %{is_single: true}} = socket) do + notify(__MODULE__, {:apply, [id]}, socket.assigns) + + {:noreply, socket} + end + def handle_event("toggle_filter", %{"id" => id}, socket) do selected_items_ids = case id in socket.assigns.selected_items_ids do diff --git a/test/lanttern/learning_context_test.exs b/test/lanttern/learning_context_test.exs index a0ffb61d..f1a3758c 100644 --- a/test/lanttern/learning_context_test.exs +++ b/test/lanttern/learning_context_test.exs @@ -99,7 +99,7 @@ defmodule Lanttern.LearningContextTest do assert expected_b.is_starred == false end - test "list_student_strand/2 returns all user strands related to students report cards" do + test "list_student_strands/2 returns all user strands related to students report cards" do student = Lanttern.SchoolsFixtures.student_fixture() subject_1 = Lanttern.TaxonomyFixtures.subject_fixture() From ca234a2519eeb65086f5c6124ecd7c349f515f7f Mon Sep 17 00:00:00 2001 From: endoooo Date: Tue, 3 Sep 2024 08:32:52 -0300 Subject: [PATCH 07/11] chore: adjusted assessments visualization rules in strand reports the previous rule for assessments visualization in strand reports was that assessment points without student entries should not be displayed. as we move towards the idea of showing strands planning to students and families prior to report cards release, we'll need to show the assessment point even if there's no student entry for it. thinking about differentiation assessment points, we are now showing all the assessment points but we highlight the assessment points with entries (including moments assessments entries). in this commit, we also implemented a rule to hide the final assessment when the parent report card is not visible to the user. - adjusted `Assessments.list_strand_goals_student_entries/2` to list all the strand assessment points (even those without entries) and to ignore moments assessment points without entries - added support to `prevent_preview` in `<.assessment_point_entry_display>` component --- lib/lanttern/assessments.ex | 16 +- .../components/assessments_components.ex | 18 ++ ...t_report_card_strand_report_live.html.heex | 1 + .../id/student_strand_report_live.html.heex | 1 + .../strand_goal_details_overlay_component.ex | 14 +- .../strand_report_assessment_component.ex | 219 ++++++++++++------ .../strand_report_moments_component.ex | 3 +- test/lanttern/assessments_test.exs | 26 +-- 8 files changed, 202 insertions(+), 96 deletions(-) diff --git a/lib/lanttern/assessments.ex b/lib/lanttern/assessments.ex index 93978136..3ec23bd4 100644 --- a/lib/lanttern/assessments.ex +++ b/lib/lanttern/assessments.ex @@ -988,9 +988,9 @@ defmodule Lanttern.Assessments do @doc """ Returns the list of strand goals, goal entries, and related moment entries for the given student and strand. - Assessment points without entries are ignored. + Assessment points without entries will return `nil`. - Moments without entries will return `nil`. + Moments without entries are ignored. Ordered by `AssessmentPoint` positions. @@ -1003,12 +1003,12 @@ defmodule Lanttern.Assessments do """ - @spec list_strand_goals_student_entries(student_id :: pos_integer(), strand_id :: pos_integer()) :: + @spec list_strand_goals_for_student(student_id :: pos_integer(), strand_id :: pos_integer()) :: [ - {AssessmentPoint.t(), AssessmentPointEntry.t(), [AssessmentPointEntry.t() | nil]} + {AssessmentPoint.t(), AssessmentPointEntry.t() | nil, [AssessmentPointEntry.t()]} ] - def list_strand_goals_student_entries(student_id, strand_id) do + def list_strand_goals_for_student(student_id, strand_id) do goals_and_entries = from( ap in AssessmentPoint, @@ -1018,7 +1018,7 @@ defmodule Lanttern.Assessments do on: diff_r_s.student_id == ^student_id and diff_r_s.rubric_id == diff_r.id, join: ci in assoc(ap, :curriculum_item), join: cc in assoc(ci, :curriculum_component), - join: e in AssessmentPointEntry, + left_join: e in AssessmentPointEntry, on: e.assessment_point_id == ap.id and e.student_id == ^student_id, left_join: ov in assoc(e, :ordinal_value), left_join: s_ov in assoc(e, :student_ordinal_value), @@ -1038,7 +1038,7 @@ defmodule Lanttern.Assessments do |> Enum.map(fn {ap, e, ov, s_ov} -> { ap, - %{e | ordinal_value: ov, student_ordinal_value: s_ov} + e && %{e | ordinal_value: ov, student_ordinal_value: s_ov} } end) @@ -1046,7 +1046,7 @@ defmodule Lanttern.Assessments do from( ap in AssessmentPoint, join: m in assoc(ap, :moment), - left_join: e in AssessmentPointEntry, + join: e in AssessmentPointEntry, on: e.assessment_point_id == ap.id and e.student_id == ^student_id, left_join: ov in assoc(e, :ordinal_value), left_join: s_ov in assoc(e, :student_ordinal_value), diff --git a/lib/lanttern_web/components/assessments_components.ex b/lib/lanttern_web/components/assessments_components.ex index 0101decf..e1d0d666 100644 --- a/lib/lanttern_web/components/assessments_components.ex +++ b/lib/lanttern_web/components/assessments_components.ex @@ -86,9 +86,27 @@ defmodule LantternWeb.AssessmentsComponents do doc: "Requires `scale`, `ordinal_value`, and `student_ordinal_value` preloads" attr :show_student_assessment, :boolean, default: false + + attr :prevent_preview, :boolean, + default: false, + doc: "use `true` to hide the final assessment from user" + attr :id, :string, default: nil attr :class, :any, default: nil + def assessment_point_entry_display(%{prevent_preview: true} = assigns) do + ~H""" +
    +
    + <%= gettext("Final assessment not available yet") %> +
    +
    + """ + end + def assessment_point_entry_display(assigns) do # even if show_student_assessment is true, # we need to check if there's actually some student assessment diff --git a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex index 43cf39c0..69d1c939 100644 --- a/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex +++ b/lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex @@ -99,6 +99,7 @@ base_path={ ~p"/student_report_card/#{@student_report_card.id}/strand_report/#{@strand_report.id}?tab=assessment" } + current_profile={@current_user.current_profile} /> <.live_component :if={@current_tab == :moments} diff --git a/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex index 91cdca74..d4906e98 100644 --- a/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex +++ b/lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex @@ -80,6 +80,7 @@ params={@params} class="py-10" base_path={~p"/strand_report/#{@strand_report.id}?tab=assessment"} + current_profile={@current_user.current_profile} /> <.live_component :if={@current_tab == :moments} diff --git a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex index fcbd47f9..4c8df741 100644 --- a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex +++ b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex @@ -7,6 +7,7 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do - `strand_goal_id` - `student_id` - `on_cancel` - a `%JS{}` struct to execute on overlay close + - `prevent_preview` - should be `true` when user is not allowed to view the parent report card """ use LantternWeb, :live_component @@ -42,7 +43,11 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do
    - <.assessment_point_entry_display entry={@entry} show_student_assessment /> + <.assessment_point_entry_display + entry={@entry} + show_student_assessment + prevent_preview={@prevent_preview} + />
    <.icon name="hero-chat-bubble-oval-left" class="w-6 h-6 text-ltrn-teacher-accent" /> @@ -77,7 +82,11 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do <%= @rubric.criteria %>

    - <.report_scale scale={@strand_goal.scale} rubric={@rubric} entry={@entry} /> + <.report_scale + scale={@strand_goal.scale} + rubric={@rubric} + entry={!@prevent_preview && @entry} + />
    <%= gettext("Formative assessment") %>
    @@ -119,6 +128,7 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do def mount(socket) do socket = socket + |> assign(:prevent_preview, false) |> stream_configure( :moments_assessment_points_and_entries, dom_id: fn diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex index 0da87bca..bf3c9ebd 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex @@ -8,8 +8,10 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do -`student_report_card` - `%StudentReportCard{}` -`params` - the URL params from parent view `handle_params/3` -`base_path` - the base URL path for overlay navigation control + -`current_profile` - the current `%Profile{}` from `current_user` """ + alias Lanttern.Assessments.AssessmentPoint use LantternWeb, :live_component alias Lanttern.Assessments @@ -26,7 +28,8 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do ~H"""
    <.responsive_container> -

    +

    <%= gettext("Goals assessment entries") %>

    +

    <%= gettext( "Here you'll find information about the strand final and formative assessments." ) %> @@ -34,72 +37,39 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do

    <%= gettext("You can click the assessment card to view more details about it.") %>

    - <.link + <.goal_card :for={{goal, entry, moment_entries} <- @strand_goals_student_entries} patch={"#{@base_path}&strand_goal_id=#{goal.id}"} - class={[ - "group/card block mt-4", - "sm:grid sm:grid-cols-[minmax(10px,_3fr)_minmax(10px,_2fr)]" - ]} - > - <%!-- <.card_base class="flex flex-col sm:flex-row items-center gap-4 p-4"> --%> - <.card_base class={[ - "p-4 group-hover/card:bg-ltrn-mesh-cyan", - "sm:col-span-2 sm:grid sm:grid-cols-subgrid sm:items-center sm:gap-4" - ]}> -
    -

    - - <%= goal.curriculum_item.curriculum_component.name %> - - <%= goal.curriculum_item.name %> -

    -
    -
    - <.assessment_metadata_icon - :if={goal.is_differentiation || goal.has_diff_rubric_for_student} - type={:diff} - /> - <.assessment_metadata_icon :if={entry && entry.report_note} type={:teacher_comment} /> - <.assessment_metadata_icon - :if={entry && entry.student_report_note} - type={:student_comment} - /> - <.assessment_metadata_icon :if={goal.report_info} type={:info} /> - <.assessment_metadata_icon :if={goal.rubric_id} type={:rubric} /> -
    -
    - <.moment_entry :for={moment_entry <- moment_entries} entry={moment_entry} /> - <.tooltip><%= gettext("Formative assessment pattern") %> -
    -
    -
    - <.assessment_point_entry_display + goal={goal} + entry={entry} + moment_entries={moment_entries} + prevent_preview={@prevent_final_assessment_preview} + /> + <.empty_state :if={!@has_strand_goals_with_student_entries}> + <%= gettext("No assessment entries for this strand yet") %> + +
    +
    +

    + <%= gettext("Goals without assessment entries") %> +

    + <.toggle_expand_button + id="toggle-strand-goals-without-student-entries" + target_selector="#strand-goals-without-student-entries" + initial_is_expanded={false} + /> +
    + +
    <.live_component :if={@strand_goal_id} @@ -107,12 +77,95 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do id="assessment-point-details-component" strand_goal_id={@strand_goal_id} student_id={@student_report_card.student_id} + prevent_preview={@prevent_final_assessment_preview} on_cancel={JS.patch(@base_path)} />
    """ end + attr :goal, AssessmentPoint, required: true + attr :entry, :any, required: true + attr :moment_entries, :list, required: true + attr :patch, :string, required: true + attr :prevent_preview, :boolean, required: true + + defp goal_card(assigns) do + %{ + goal: goal, + entry: entry, + moment_entries: moment_entries + } = assigns + + render_icons_area = + goal.is_differentiation || + (entry && entry.report_note) || + (entry && entry.student_report_note) || + goal.report_info || + goal.rubric_id + + render_extra_fields_area = + render_icons_area || + moment_entries != [] + + assigns = + assigns + |> assign(:render_extra_fields_area, render_extra_fields_area) + |> assign(:render_icons_area, render_extra_fields_area) + + ~H""" + <.link + patch={@patch} + class={[ + "group/card block mt-4", + "sm:grid sm:grid-cols-[minmax(10px,_3fr)_minmax(10px,_2fr)]" + ]} + > + <.card_base class={[ + "p-4 group-hover/card:bg-ltrn-mesh-cyan", + "sm:col-span-2 sm:grid sm:grid-cols-subgrid sm:items-center sm:gap-4" + ]}> +
    +

    + + <%= @goal.curriculum_item.curriculum_component.name %> + + <%= @goal.curriculum_item.name %> +

    +
    +
    + <.assessment_metadata_icon + :if={@goal.is_differentiation || @goal.has_diff_rubric_for_student} + type={:diff} + /> + <.assessment_metadata_icon :if={@entry && @entry.report_note} type={:teacher_comment} /> + <.assessment_metadata_icon + :if={@entry && @entry.student_report_note} + type={:student_comment} + /> + <.assessment_metadata_icon :if={@goal.report_info} type={:info} /> + <.assessment_metadata_icon :if={@goal.rubric_id} type={:rubric} /> +
    +
    + <.moment_entry :for={moment_entry <- @moment_entries} entry={moment_entry} /> + <.tooltip><%= gettext("Formative assessment pattern") %> +
    +
    +
    + <.assessment_point_entry_display + entry={@entry} + show_student_assessment + prevent_preview={@prevent_preview} + class="mt-4 sm:mt-0" + /> + + + """ + end + attr :type, :atom, required: true defp assessment_metadata_icon(%{type: :diff} = assigns) do @@ -217,25 +270,45 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do |> assign(assigns) |> assign_strand_goals_student_entries(assigns) |> assign_strand_goal_id(assigns) + |> assign_prevent_final_assessment_preview() |> assign(:initialized, true) {:ok, socket} end defp assign_strand_goals_student_entries(%{assigns: %{initialized: false}} = socket, assigns) do - strand_goals_student_entries = - Assessments.list_strand_goals_student_entries( + all_strand_goals_student_entries = + Assessments.list_strand_goals_for_student( assigns.student_report_card.student_id, assigns.strand_report.strand_id ) strand_goals_ids = - strand_goals_student_entries + all_strand_goals_student_entries |> Enum.map(fn {strand_goal, _, _} -> "#{strand_goal.id}" end) + strand_goals_student_entries = + all_strand_goals_student_entries + |> Enum.filter(fn {_, entry, moments_entries} -> + not is_nil(entry) or moments_entries != [] + end) + + strand_goals_without_student_entries = + all_strand_goals_student_entries + |> Enum.filter(fn {_, entry, moments_entries} -> is_nil(entry) and moments_entries == [] end) + socket |> assign(:strand_goals_student_entries, strand_goals_student_entries) |> assign(:strand_goals_ids, strand_goals_ids) + |> assign(:strand_goals_without_student_entries, strand_goals_without_student_entries) + |> assign( + :has_strand_goals_with_student_entries, + strand_goals_student_entries != [] + ) + |> assign( + :has_strand_goals_without_student_entries, + strand_goals_without_student_entries != [] + ) end defp assign_strand_goals_student_entries(socket, _assigns), do: socket @@ -253,4 +326,18 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do end defp assign_strand_goal_id(socket, _assigns), do: assign(socket, :strand_goal_id, nil) + + defp assign_prevent_final_assessment_preview(socket) do + profile = socket.assigns.current_profile + + prevent_final_assessment_preview = + case {profile.type, socket.assigns.student_report_card} do + {"teacher", _} -> false + {"student", %{allow_student_access: true}} -> false + {"guardian", %{allow_guardian_access: true}} -> false + _ -> true + end + + assign(socket, :prevent_final_assessment_preview, prevent_final_assessment_preview) + end end diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex index adb86155..fc9d2993 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex @@ -25,7 +25,8 @@ defmodule LantternWeb.Reporting.StrandReportMomentsComponent do ~H"""
    <.responsive_container> -

    +

    <%= gettext("Strand moments") %>

    +

    <%= gettext("Here you'll find information about the strand learning journey.") %>

    diff --git a/test/lanttern/assessments_test.exs b/test/lanttern/assessments_test.exs index 483e49e4..44e32fb5 100644 --- a/test/lanttern/assessments_test.exs +++ b/test/lanttern/assessments_test.exs @@ -868,12 +868,12 @@ defmodule Lanttern.AssessmentsTest do alias Lanttern.RubricsFixtures alias Lanttern.SchoolsFixtures - test "list_strand_goals_student_entries/2 returns the list of strand goals with student assessments" do + test "list_strand_goals_for_student/2 returns the list of strand goals with student assessments" do # | moment_1 | moment_2 | moment_3 | # --------------------------------------- - # ci_1 | 2* | 1 | 1 | (* no entry in m1 pos 2 and m3) - # ci_2 | - | 1 | - | - # ci_3 | - | - | - | + # ci_1 | 2* | 1 | 1 | (* no entry in m1 pos 2 and m3) + # ci_2 | - | 1 | - | + # ci_3* | - | - | - | (* no entry for goal) strand = LearningContextFixtures.strand_fixture() @@ -966,15 +966,6 @@ defmodule Lanttern.AssessmentsTest do score: 5.0 }) - entry_3 = - assessment_point_entry_fixture(%{ - assessment_point_id: assessment_point_3.id, - student_id: student.id, - scale_id: ordinal_scale.id, - scale_type: ordinal_scale.type, - ordinal_value_id: ordinal_value.id - }) - ci_1_m_1_1 = assessment_point_fixture(%{ curriculum_item_id: curriculum_item_1.id, @@ -1046,11 +1037,10 @@ defmodule Lanttern.AssessmentsTest do }) assert [ - {expected_ap_1, expected_entry_1, - [expected_ci_1_m_1_1, nil, expected_ci_1_m_2, nil]}, + {expected_ap_1, expected_entry_1, [expected_ci_1_m_1_1, expected_ci_1_m_2]}, {expected_ap_2, expected_entry_2, [expected_ci_2_m_2]}, - {expected_ap_3, expected_entry_3, []} - ] = Assessments.list_strand_goals_student_entries(student.id, strand.id) + {expected_ap_3, nil, []} + ] = Assessments.list_strand_goals_for_student(student.id, strand.id) assert expected_ap_1.id == assessment_point_1.id assert expected_ap_1.scale_id == ordinal_scale.id @@ -1084,8 +1074,6 @@ defmodule Lanttern.AssessmentsTest do assert expected_ap_3.curriculum_item.id == curriculum_item_3.id assert expected_ap_3.curriculum_item.curriculum_component.id == curriculum_component_3.id assert expected_ap_3.curriculum_item.id == curriculum_item_3.id - assert expected_entry_3.id == entry_3.id - assert expected_entry_3.ordinal_value.id == ordinal_value.id end end From 40dc1a506633a7a112788dea59bb45f99d30085b Mon Sep 17 00:00:00 2001 From: endoooo Date: Tue, 3 Sep 2024 10:48:23 -0300 Subject: [PATCH 08/11] chore: created `Assessments.EntryParticleComponent` this is a new implementation of the `<.moment_entry>` function component in `Reporting.StrandReportAssessmentComponent`. the old component expected the ordinal value preload, and the new handles the ordinal value "preload" in the component `update_many` to reduce the amount of duplicated data being transfered from one component to another --- lib/lanttern/assessments.ex | 13 +-- lib/lanttern/grading.ex | 33 ++++--- .../assessments/entry_particle_component.ex | 94 +++++++++++++++++++ .../strand_report_assessment_component.ex | 46 ++------- test/lanttern/assessments_test.exs | 8 +- test/lanttern/grading_test.exs | 19 ++++ 6 files changed, 145 insertions(+), 68 deletions(-) create mode 100644 lib/lanttern_web/live/shared/assessments/entry_particle_component.ex diff --git a/lib/lanttern/assessments.ex b/lib/lanttern/assessments.ex index 3ec23bd4..56d70f06 100644 --- a/lib/lanttern/assessments.ex +++ b/lib/lanttern/assessments.ex @@ -998,9 +998,6 @@ defmodule Lanttern.Assessments do - `:has_diff_rubric_for_student` calculated based on student id - curriculum item with curriculum component - Assessment point entry preload: - - `ordinal_value` and `student_ordinal_value` - """ @spec list_strand_goals_for_student(student_id :: pos_integer(), strand_id :: pos_integer()) :: @@ -1048,19 +1045,11 @@ defmodule Lanttern.Assessments do join: m in assoc(ap, :moment), join: e in AssessmentPointEntry, on: e.assessment_point_id == ap.id and e.student_id == ^student_id, - left_join: ov in assoc(e, :ordinal_value), - left_join: s_ov in assoc(e, :student_ordinal_value), where: m.strand_id == ^strand_id, order_by: [asc: m.position, asc: ap.position], - select: {ap.curriculum_item_id, e, ov, s_ov} + select: {ap.curriculum_item_id, e} ) |> Repo.all() - |> Enum.map(fn {ci_id, e, ov, s_ov} -> - { - ci_id, - e && %{e | ordinal_value: ov, student_ordinal_value: s_ov} - } - end) |> Enum.group_by( fn {ci_id, _e} -> ci_id end, fn {_ci_id, e} -> e end diff --git a/lib/lanttern/grading.ex b/lib/lanttern/grading.ex index 854d2f96..06a6b418 100644 --- a/lib/lanttern/grading.ex +++ b/lib/lanttern/grading.ex @@ -143,6 +143,7 @@ defmodule Lanttern.Grading do `:preloads` – preloads associated data `:scale_id` – filter ordinal values by scale and order results by `normalized_value` + `:ids` – filter ordinal values by given ids ## Examples @@ -151,26 +152,30 @@ defmodule Lanttern.Grading do """ def list_ordinal_values(opts \\ []) do - OrdinalValue - |> maybe_filter_ordinal_values_by_scale(opts) + from( + ov in OrdinalValue, + order_by: ov.normalized_value + ) + |> apply_list_ordinal_values_opts(opts) |> Repo.all() |> maybe_preload(opts) end - defp maybe_filter_ordinal_values_by_scale(ordinal_value_query, opts) do - case Keyword.get(opts, :scale_id) do - nil -> - ordinal_value_query - - scale_id -> - from( - ov in ordinal_value_query, - where: ov.scale_id == ^scale_id, - order_by: ov.normalized_value - ) - end + defp apply_list_ordinal_values_opts(queryable, []), do: queryable + + defp apply_list_ordinal_values_opts(queryable, [{:scale_id, scale_id} | opts]) do + from(ov in queryable, where: ov.scale_id == ^scale_id) + |> apply_list_ordinal_values_opts(opts) + end + + defp apply_list_ordinal_values_opts(queryable, [{:ids, ids} | opts]) do + from(ov in queryable, where: ov.id in ^ids) + |> apply_list_ordinal_values_opts(opts) end + defp apply_list_ordinal_values_opts(queryable, [_ | opts]), + do: apply_list_ordinal_values_opts(queryable, opts) + @doc """ Gets a single ordinal_value. Optionally preloads associated data. diff --git a/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex b/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex new file mode 100644 index 00000000..8b722219 --- /dev/null +++ b/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex @@ -0,0 +1,94 @@ +defmodule LantternWeb.Assessments.EntryParticleComponent do + @moduledoc """ + This component renders assessment point particles, small visual representations + of assessments for dataviz. + + As multiple instances of this components are rendered at the same time, + the component also handles the ordinal values "preload" through `update_many/1`. + + #### Expected external assigns + + attr :entry, AssessmentPointEntry + attr :class, :any + + """ + use LantternWeb, :live_component + + alias Lanttern.Grading + + @impl true + def render(assigns) do + ~H""" +

    + <%= @text %> +
    + """ + end + + # lifecycle + + @impl true + def mount(socket) do + socket = + socket + |> assign(:class, nil) + + {:ok, socket} + end + + @impl true + def update_many(assigns_sockets) do + ordinal_values_ids = + assigns_sockets + |> Enum.map(fn {assigns, _socket} -> + assigns.entry && assigns.entry.ordinal_value_id + end) + |> Enum.filter(&(not is_nil(&1))) + |> Enum.uniq() + + # map format + # %{ + # ordinal_value_id: %OrdinalValue{}, + # ... + # } + ovs_map = + Grading.list_ordinal_values(ids: ordinal_values_ids) + |> Enum.map(&{&1.id, &1}) + |> Enum.into(%{}) + + assigns_sockets + |> Enum.map(&update_single(&1, ovs_map)) + end + + defp update_single({assigns, socket}, ovs_map) do + {additional_classes, style, text} = + case assigns.entry do + %{scale_type: "ordinal"} = entry -> + ordinal_value = ovs_map[entry.ordinal_value_id] + + style = + "color: #{ordinal_value.text_color}; background-color: #{ordinal_value.bg_color}" + + {nil, style, "•"} + + %{scale_type: "numeric"} -> + {"text-ltrn-dark bg-ltrn-lighter", nil, "•"} + + nil -> + {"border border-dashed border-ltrn-light text-ltrn-light", nil, "-"} + end + + socket + |> assign(assigns) + |> assign(:additional_classes, additional_classes) + |> assign(:style, style) + |> assign(:text, text) + end +end diff --git a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex index bf3c9ebd..fe20d225 100644 --- a/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex +++ b/lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex @@ -20,8 +20,8 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do alias LantternWeb.Assessments.StrandGoalDetailsOverlayComponent # shared components + alias LantternWeb.Assessments.EntryParticleComponent import LantternWeb.AssessmentsComponents - # import LantternWeb.ReportingComponents @impl true def render(assigns) do @@ -150,7 +150,13 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do <.assessment_metadata_icon :if={@goal.rubric_id} type={:rubric} />
    - <.moment_entry :for={moment_entry <- @moment_entries} entry={moment_entry} /> + <.live_component + :for={moment_entry <- @moment_entries} + module={EntryParticleComponent} + id={moment_entry.id} + entry={moment_entry} + class="flex-1" + /> <.tooltip><%= gettext("Formative assessment pattern") %>
    @@ -214,42 +220,6 @@ defmodule LantternWeb.Reporting.StrandReportAssessmentComponent do defp assessment_metadata_icon_attrs(:rubric), do: {gettext("Has rubric"), "hero-view-columns-mini", "bg-ltrn-lighter", "text-ltrn-subtle"} - attr :entry, :any, required: true - - defp moment_entry(assigns) do - {additional_classes, style, text} = - case assigns.entry do - %{scale_type: "ordinal"} = entry -> - {nil, - "color: #{entry.ordinal_value.text_color}; background-color: #{entry.ordinal_value.bg_color}", - "•"} - - %{scale_type: "numeric"} -> - {"text-ltrn-dark bg-ltrn-lighter", nil, "•"} - - nil -> - {"border border-dashed border-ltrn-light text-ltrn-light", nil, "-"} - end - - assigns = - assigns - |> assign(:additional_classes, additional_classes) - |> assign(:style, style) - |> assign(:text, text) - - ~H""" -
    - <%= @text %> -
    - """ - end - # lifecycle @impl true diff --git a/test/lanttern/assessments_test.exs b/test/lanttern/assessments_test.exs index 44e32fb5..4a586105 100644 --- a/test/lanttern/assessments_test.exs +++ b/test/lanttern/assessments_test.exs @@ -1050,12 +1050,12 @@ defmodule Lanttern.AssessmentsTest do assert expected_ap_1.curriculum_item.curriculum_component.id == curriculum_component_1.id assert expected_ap_1.curriculum_item.id == curriculum_item_1.id assert expected_entry_1.id == entry_1.id - assert expected_entry_1.ordinal_value.id == ordinal_value.id + assert expected_entry_1.ordinal_value_id == ordinal_value.id assert expected_ci_1_m_1_1.id == entry_ci_1_m_1_1.id - assert expected_ci_1_m_1_1.ordinal_value.id == ordinal_value.id + assert expected_ci_1_m_1_1.ordinal_value_id == ordinal_value.id assert expected_ci_1_m_2.id == entry_ci_1_m_2.id - assert expected_ci_1_m_2.ordinal_value.id == ordinal_value.id + assert expected_ci_1_m_2.ordinal_value_id == ordinal_value.id assert expected_ap_2.id == assessment_point_2.id assert expected_ap_2.scale_id == numeric_scale.id @@ -1065,7 +1065,7 @@ defmodule Lanttern.AssessmentsTest do assert expected_entry_2.score == 5.0 assert expected_ci_2_m_2.id == entry_ci_2_m_2.id - assert expected_ci_2_m_2.ordinal_value.id == ordinal_value.id + assert expected_ci_2_m_2.ordinal_value_id == ordinal_value.id assert expected_ap_3.id == assessment_point_3.id assert expected_ap_3.scale_id == ordinal_scale.id diff --git a/test/lanttern/grading_test.exs b/test/lanttern/grading_test.exs index 5fc0b0ac..76a0f553 100644 --- a/test/lanttern/grading_test.exs +++ b/test/lanttern/grading_test.exs @@ -321,6 +321,25 @@ defmodule Lanttern.GradingTest do ] end + test "list_ordinal_values/1 with ids returns all ordinal_values filtered by given ids" do + ordinal_value_1 = ordinal_value_fixture(%{normalized_value: 0}) + ordinal_value_3 = ordinal_value_fixture(%{normalized_value: 1}) + ordinal_value_2 = ordinal_value_fixture(%{normalized_value: 0.5}) + _other_ordinal_value = ordinal_value_fixture() + + ids = [ + ordinal_value_1.id, + ordinal_value_2.id, + ordinal_value_3.id + ] + + assert Grading.list_ordinal_values(ids: ids) == [ + ordinal_value_1, + ordinal_value_2, + ordinal_value_3 + ] + end + test "get_ordinal_value!/2 returns the ordinal_value with given id" do ordinal_value = ordinal_value_fixture() assert Grading.get_ordinal_value!(ordinal_value.id) == ordinal_value From d5f5bcf49615f6ad0cdcc6ae7832d88e08006475 Mon Sep 17 00:00:00 2001 From: endoooo Date: Tue, 3 Sep 2024 13:20:22 -0300 Subject: [PATCH 09/11] feat: added formative assessment pattern to student strands page - adjusted `LearningContext.list_student_strands/2` to include moments entries - added support to `:size` attr in `Assessments.EntryParticleComponent` --- lib/lanttern/learning_context.ex | 69 +++++++++++++------ .../student_strands/student_strands_live.ex | 5 +- .../student_strands_live.html.heex | 17 ++++- .../assessments/entry_particle_component.ex | 10 ++- test/lanttern/learning_context_test.exs | 68 ++++++++++++++++-- 5 files changed, 138 insertions(+), 31 deletions(-) diff --git a/lib/lanttern/learning_context.ex b/lib/lanttern/learning_context.ex index 27d64802..5ca28772 100644 --- a/lib/lanttern/learning_context.ex +++ b/lib/lanttern/learning_context.ex @@ -8,6 +8,7 @@ defmodule Lanttern.LearningContext do import LantternWeb.Gettext alias Lanttern.Repo + alias Lanttern.Assessments.AssessmentPointEntry alias Lanttern.LearningContext.Strand alias Lanttern.LearningContext.StarredStrand alias Lanttern.LearningContext.Moment @@ -51,13 +52,15 @@ defmodule Lanttern.LearningContext do end @doc """ - Returns the list of strands linked to the student. + Returns the list of strands linked to the student with + linked moments entries. Strands are "linked to the student" through report cards: strand -> strand report -> report card -> student report card - Results are ordered by cycle (desc), then by strand report position. + Strands results are ordered by cycle (desc), then by strand report position. + Entries are ordered by moment position, then by assessment point position. Preloads subjects, years, and report cycle. @@ -72,27 +75,53 @@ defmodule Lanttern.LearningContext do ## Examples iex> list_student_strands(1) - [%Strand{}, ...] + [{%Strand{}, [%AssessmentPointEntry{}, ...]}, ...] """ - @spec list_student_strands(student_id :: pos_integer(), opts :: Keyword.t()) :: [Strand.t()] + @spec list_student_strands(student_id :: pos_integer(), opts :: Keyword.t()) :: [ + {Strand.t(), [AssessmentPointEntry.t()]} + ] def list_student_strands(student_id, opts \\ []) do - from( - s in Strand, - left_join: sub in assoc(s, :subjects), - left_join: y in assoc(s, :years), - join: sr in assoc(s, :strand_reports), - join: rc in assoc(sr, :report_card), - join: c in assoc(rc, :school_cycle), - as: :cycles, - join: src in assoc(rc, :students_report_cards), - order_by: [desc: c.end_at, asc: c.start_at, asc: sr.position], - where: src.student_id == ^student_id, - preload: [subjects: sub, years: y], - select: %{s | strand_report_id: sr.id, report_cycle: c} - ) - |> apply_list_student_strands_opts(opts) - |> Repo.all() + student_strands = + from( + s in Strand, + left_join: sub in assoc(s, :subjects), + left_join: y in assoc(s, :years), + join: sr in assoc(s, :strand_reports), + join: rc in assoc(sr, :report_card), + join: c in assoc(rc, :school_cycle), + as: :cycles, + join: src in assoc(rc, :students_report_cards), + order_by: [desc: c.end_at, asc: c.start_at, asc: sr.position], + where: src.student_id == ^student_id, + preload: [subjects: sub, years: y], + select: %{s | strand_report_id: sr.id, report_cycle: c} + ) + |> apply_list_student_strands_opts(opts) + |> Repo.all() + + student_strands_ids = + student_strands + |> Enum.map(& &1.id) + + student_strands_entries_map = + from( + e in AssessmentPointEntry, + join: ap in assoc(e, :assessment_point), + join: m in assoc(ap, :moment), + where: m.strand_id in ^student_strands_ids, + where: e.student_id == ^student_id, + order_by: [asc: m.position, asc: ap.position], + select: {e, m.strand_id} + ) + |> Repo.all() + |> Enum.group_by( + fn {_entry, strand_id} -> strand_id end, + fn {entry, _strand_id} -> entry end + ) + + student_strands + |> Enum.map(&{&1, Map.get(student_strands_entries_map, &1.id, [])}) end defp apply_list_student_strands_opts(queryable, []), do: queryable diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex index 056adbf9..ae9e84d9 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.ex @@ -13,8 +13,9 @@ defmodule LantternWeb.StudentStrandsLive do import LantternWeb.FiltersHelpers # shared components - import LantternWeb.LearningContextComponents + alias LantternWeb.Assessments.EntryParticleComponent alias LantternWeb.Filters.InlineFiltersComponent + import LantternWeb.LearningContextComponents import LantternWeb.SchoolsComponents @impl true @@ -45,7 +46,7 @@ defmodule LantternWeb.StudentStrandsLive do # (some strands can be in more than one report card at the same time) |> stream_configure( :student_strands, - dom_id: fn strand -> "student-strand-report-#{strand.strand_report_id}" end + dom_id: fn {strand, _entries} -> "student-strand-report-#{strand.strand_report_id}" end ) |> stream_student_strands() diff --git a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex index adf162d1..49fac398 100644 --- a/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex +++ b/lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex @@ -19,13 +19,26 @@ <.responsive_grid :if={@has_student_strands} id="student-strands" phx-update="stream"> <.strand_card - :for={{dom_id, strand} <- @streams.student_strands} + :for={{dom_id, {strand, entries}} <- @streams.student_strands} id={dom_id} strand={strand} cover_image_url={strand.cover_image_url} navigate={~p"/strand_report/#{strand.strand_report_id}"} hide_description class="shrink-0 w-64 sm:w-auto" - /> + > + <:bottom_content :if={entries != []}> +
    + <.live_component + :for={entry <- entries} + module={EntryParticleComponent} + id={entry.id} + entry={entry} + size="sm" + /> + <.tooltip h_pos="center"><%= gettext("Formative assessment pattern") %> +
    + + <.school_branding_footer school={@school} /> diff --git a/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex b/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex index 8b722219..14b8592d 100644 --- a/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex +++ b/lib/lanttern_web/live/shared/assessments/entry_particle_component.ex @@ -9,7 +9,11 @@ defmodule LantternWeb.Assessments.EntryParticleComponent do #### Expected external assigns attr :entry, AssessmentPointEntry - attr :class, :any + + #### Optional assigns + + attr :size, :string, default: "md", doc: "sm | md" + attr :class, :any, default: nil """ use LantternWeb, :live_component @@ -21,7 +25,8 @@ defmodule LantternWeb.Assessments.EntryParticleComponent do ~H"""
    assign(:size, "md") |> assign(:class, nil) {:ok, socket} diff --git a/test/lanttern/learning_context_test.exs b/test/lanttern/learning_context_test.exs index f1a3758c..ab3930ce 100644 --- a/test/lanttern/learning_context_test.exs +++ b/test/lanttern/learning_context_test.exs @@ -99,7 +99,7 @@ defmodule Lanttern.LearningContextTest do assert expected_b.is_starred == false end - test "list_student_strands/2 returns all user strands related to students report cards" do + test "list_student_strands/2 returns all user strands related to students report cards (+ moment entries)" do student = Lanttern.SchoolsFixtures.student_fixture() subject_1 = Lanttern.TaxonomyFixtures.subject_fixture() @@ -115,6 +115,64 @@ defmodule Lanttern.LearningContextTest do # use same strand in different reports strand_4 = strand_2 + # add moments to strand 1, following this structure + # moment 1 - 2 assessment points, only first with student entry + # moment 2 - 1 assessment point with student entry + # moment 3 - no assessment points + # expected entries return: m1_ap1, m2_ap1 + + moment_1 = moment_fixture(%{strand_id: strand_1.id}) + moment_2 = moment_fixture(%{strand_id: strand_1.id}) + _moment_3 = moment_fixture(%{strand_id: strand_1.id}) + + scale = Lanttern.GradingFixtures.scale_fixture(%{type: "ordinal"}) + ov = Lanttern.GradingFixtures.ordinal_value_fixture(%{scale_id: scale.id}) + + ap_m1_1 = + Lanttern.AssessmentsFixtures.assessment_point_fixture(%{ + moment_id: moment_1.id, + scale_id: scale.id + }) + + _ap_m1_2 = + Lanttern.AssessmentsFixtures.assessment_point_fixture(%{ + moment_id: moment_1.id, + scale_id: scale.id + }) + + ap_m2_1 = + Lanttern.AssessmentsFixtures.assessment_point_fixture(%{ + moment_id: moment_2.id, + scale_id: scale.id + }) + + entry_m1_1 = + Lanttern.AssessmentsFixtures.assessment_point_entry_fixture(%{ + student_id: student.id, + assessment_point_id: ap_m1_1.id, + scale_id: scale.id, + scale_type: scale.type, + ordinal_value_id: ov.id + }) + + entry_m2_1 = + Lanttern.AssessmentsFixtures.assessment_point_entry_fixture(%{ + student_id: student.id, + assessment_point_id: ap_m2_1.id, + scale_id: scale.id, + scale_type: scale.type, + ordinal_value_id: ov.id + }) + + # entry for other student + _other_entry_m2_1 = + Lanttern.AssessmentsFixtures.assessment_point_entry_fixture(%{ + assessment_point_id: ap_m2_1.id, + scale_id: scale.id, + scale_type: scale.type, + ordinal_value_id: ov.id + }) + cycle_2024 = Lanttern.SchoolsFixtures.cycle_fixture(start_at: ~D[2024-01-01], end_at: ~D[2024-12-31]) @@ -183,10 +241,10 @@ defmodule Lanttern.LearningContextTest do }) assert [ - expected_strand_1, - expected_strand_2, - expected_strand_3, - expected_strand_4 + {expected_strand_1, [^entry_m1_1, ^entry_m2_1]}, + {expected_strand_2, []}, + {expected_strand_3, []}, + {expected_strand_4, []} ] = LearningContext.list_student_strands( student.id, From 89b0566a9e8221285e91e98496fe6c0b48d045c0 Mon Sep 17 00:00:00 2001 From: endoooo Date: Tue, 3 Sep 2024 13:48:42 -0300 Subject: [PATCH 10/11] feat: added support to teacher comment in `<.moment_assessment_point_entry>` component - created reporting `<.comment_area>` component --- .../components/reporting_components.ex | 51 +++++++++++++++++-- .../strand_goal_details_overlay_component.ex | 24 +++------ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/lib/lanttern_web/components/reporting_components.ex b/lib/lanttern_web/components/reporting_components.ex index be07d336..175b7f38 100644 --- a/lib/lanttern_web/components/reporting_components.ex +++ b/lib/lanttern_web/components/reporting_components.ex @@ -20,6 +20,44 @@ defmodule LantternWeb.ReportingComponents do alias Lanttern.Schools.Cycle alias Lanttern.Taxonomy.Year + @doc """ + Renders a teacher or student comment area + """ + + attr :comment, :string, required: true + attr :type, :string, default: "teacher", doc: "teacher | student" + attr :class, :any, default: nil + + def comment_area(assigns) do + {bg_class, icon_class, text_class, text} = + case assigns.type do + "teacher" -> + {"bg-ltrn-teacher-lightest", "text-ltrn-teacher-accent", "text-ltrn-teacher-dark", + gettext("Teacher comment")} + + "student" -> + {"bg-ltrn-student-lightest", "text-ltrn-student-accent", "text-ltrn-student-dark", + gettext("Student comment")} + end + + assigns = + assigns + |> assign(:bg_class, bg_class) + |> assign(:icon_class, icon_class) + |> assign(:text_class, text_class) + |> assign(:text, text) + + ~H""" +
    +
    + <.icon name="hero-chat-bubble-oval-left" class={["w-6 h-6", @icon_class]} /> + <%= @text %> +
    + <.markdown text={@comment} size="sm" class="max-w-none mt-4" /> +
    + """ + end + @doc """ Renders a report card card (yes, card card, 2x). """ @@ -262,10 +300,15 @@ defmodule LantternWeb.ReportingComponents do def moment_assessment_point_entry(assigns) do ~H""" -
    - <.badge :if={@assessment_point.is_differentiation} theme="diff"><%= gettext("Diff") %> -

    <%= @assessment_point.name %>

    - <.assessment_point_entry_badge entry={@entry} class="shrink-0" /> +
    +
    + <.badge :if={@assessment_point.is_differentiation} theme="diff"> + <%= gettext("Diff") %> + +

    <%= @assessment_point.name %>

    + <.assessment_point_entry_badge entry={@entry} class="shrink-0" /> +
    + <.comment_area :if={@entry && @entry.report_note} comment={@entry.report_note} class="mt-2" />
    """ end diff --git a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex index 4c8df741..e36ad847 100644 --- a/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex +++ b/lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex @@ -48,25 +48,13 @@ defmodule LantternWeb.Assessments.StrandGoalDetailsOverlayComponent do show_student_assessment prevent_preview={@prevent_preview} /> -
    -
    - <.icon name="hero-chat-bubble-oval-left" class="w-6 h-6 text-ltrn-teacher-accent" /> - <%= gettext("Teacher comment") %> -
    - <.markdown text={@entry.report_note} size="sm" class="max-w-none mt-4" /> -
    -
    + <.comment_area :if={@entry && @entry.student_report_note} - class="p-4 rounded mt-4 bg-ltrn-student-lightest" - > -
    - <.icon name="hero-chat-bubble-oval-left" class="w-6 h-6 text-ltrn-student-accent" /> - - <%= gettext("Student comment") %> - -
    - <.markdown text={@entry.student_report_note} size="sm" class="max-w-none mt-4" /> -
    + comment={@entry.student_report_note} + class="mt-4" + type="student" + />
    From 5188cfc46510cb0c862d5ea27eec228c02c9f896 Mon Sep 17 00:00:00 2001 From: endoooo Date: Tue, 3 Sep 2024 14:10:37 -0300 Subject: [PATCH 11/11] chore: updated translations and version --- mix.exs | 2 +- priv/gettext/default.pot | 193 ++++++++++----------- priv/gettext/en/LC_MESSAGES/default.po | 193 ++++++++++----------- priv/gettext/pt_BR/LC_MESSAGES/default.po | 199 +++++++++++----------- 4 files changed, 295 insertions(+), 292 deletions(-) diff --git a/mix.exs b/mix.exs index 7e2be575..520a2c3d 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Lanttern.MixProject do def project do [ app: :lanttern, - version: "2024.8.12-alpha.28", + version: "2024.9.3-alpha.28", elixir: "~> 1.15", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 4f057aa7..ac336732 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -47,7 +47,11 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:9 #: lib/lanttern_web/live/pages/strands/strands_live.ex:52 #: lib/lanttern_web/live/pages/strands/strands_live.html.heex:2 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:2 #: lib/lanttern_web/live/shared/menu_component.ex:37 +#: lib/lanttern_web/live/shared/menu_component.ex:64 +#: lib/lanttern_web/live/shared/menu_component.ex:76 #, elixir-autogen, elixir-format msgid "Strands" msgstr "" @@ -59,23 +63,23 @@ msgstr "" msgid "close" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:115 +#: lib/lanttern_web/live/shared/menu_component.ex:118 #, elixir-autogen, elixir-format msgid "Change profile" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:152 +#: lib/lanttern_web/live/shared/menu_component.ex:155 #, elixir-autogen, elixir-format msgid "Language:" msgstr "" #: lib/lanttern_web/controllers/privacy_policy_html/accept_policy.html.heex:25 -#: lib/lanttern_web/live/shared/menu_component.ex:145 +#: lib/lanttern_web/live/shared/menu_component.ex:148 #, elixir-autogen, elixir-format msgid "Log out" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:87 +#: lib/lanttern_web/live/shared/menu_component.ex:90 #, elixir-autogen, elixir-format msgid "You're logged in as" msgstr "" @@ -86,7 +90,7 @@ msgid "All strands" msgstr "" #: lib/lanttern_web/live/shared/filters/filters_overlay_component.ex:33 -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:32 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:33 #, elixir-autogen, elixir-format msgid "Apply filters" msgstr "" @@ -371,7 +375,8 @@ msgid "About" msgstr "" #: lib/lanttern_web/components/grades_reports_components.ex:604 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:48 #, elixir-autogen, elixir-format msgid "Assessment" msgstr "" @@ -421,8 +426,8 @@ msgid "Strand deleted" msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:25 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:61 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:31 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:31 #, elixir-autogen, elixir-format msgid "Add a strand note" msgstr "" @@ -479,10 +484,10 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/about_component.ex:54 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:74 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:117 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:62 #: lib/lanttern_web/live/shared/assessments/assessment_point_form_component.ex:84 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:65 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:181 #, elixir-autogen, elixir-format msgid "Differentiation" msgstr "" @@ -584,6 +589,7 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:24 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:28 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:28 #, elixir-autogen, elixir-format msgid "You don't have any notes for this strand yet" msgstr "" @@ -757,7 +763,7 @@ msgstr "" msgid "to assess students" msgstr "" -#: lib/lanttern/learning_context/strand.ex:90 +#: lib/lanttern/learning_context/strand.ex:95 #, elixir-autogen, elixir-format msgid "Strand has linked assessment points." msgstr "" @@ -830,7 +836,8 @@ msgid "Moment updated successfully" msgstr "" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:43 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:54 #, elixir-autogen, elixir-format msgid "Moments" msgstr "" @@ -855,7 +862,7 @@ msgstr "" msgid "Save moment" msgstr "" -#: lib/lanttern/learning_context.ex:443 +#: lib/lanttern/learning_context.ex:531 #: lib/lanttern/repo_helpers.ex:122 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:53 #: lib/lanttern_web/live/pages/report_cards/id/students_grades_component.ex:283 @@ -880,12 +887,13 @@ msgstr "" msgid "Strand has linked moments and/or assessment points (goals). Deleting it would cause some data loss." msgstr "" -#: lib/lanttern/learning_context/strand.ex:85 +#: lib/lanttern/learning_context/strand.ex:90 #, elixir-autogen, elixir-format msgid "Strand has linked moments." msgstr "" #: lib/lanttern_web/live/pages/strands/id/moments_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:28 #, elixir-autogen, elixir-format msgid "Strand moments" msgstr "" @@ -1067,7 +1075,8 @@ msgstr "" msgid "Curriculum components" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:60 #, elixir-autogen, elixir-format msgid "Curriculum differentiation" msgstr "" @@ -1082,12 +1091,13 @@ msgstr "" msgid "Curriculum items" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:70 +#: lib/lanttern_web/components/reporting_components.ex:108 #: lib/lanttern_web/live/pages/grading/grades_reports_live.html.heex:39 #: lib/lanttern_web/live/pages/report_cards/id/report_card_live.html.heex:14 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:34 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:34 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:23 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:107 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:25 #: lib/lanttern_web/live/shared/reporting/report_card_form_component.ex:37 #, elixir-autogen, elixir-format msgid "Cycle" @@ -1099,7 +1109,7 @@ msgstr "" msgid "Cycle already added to this grade report" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:266 +#: lib/lanttern_web/components/reporting_components.ex:306 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:27 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:106 #: lib/lanttern_web/live/shared/assessments/assessments_grid_component.ex:353 @@ -1463,7 +1473,8 @@ msgid "Normalized value" msgstr "" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:40 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:42 #, elixir-autogen, elixir-format msgid "Overview" msgstr "" @@ -1519,6 +1530,8 @@ msgstr "" #: lib/lanttern_web/live/pages/report_cards/report_cards_live.ex:29 #: lib/lanttern_web/live/pages/strands/id/about_component.ex:112 #: lib/lanttern_web/live/shared/menu_component.ex:49 +#: lib/lanttern_web/live/shared/menu_component.ex:61 +#: lib/lanttern_web/live/shared/menu_component.ex:73 #, elixir-autogen, elixir-format msgid "Report cards" msgstr "" @@ -1614,7 +1627,8 @@ msgstr "" msgid "Strand id" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:12 #, elixir-autogen, elixir-format msgid "Strand report" msgstr "" @@ -1654,7 +1668,7 @@ msgstr "" msgid "Student grades calculated succesfully" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:10 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:5 #, elixir-autogen, elixir-format msgid "Student report card" @@ -1802,12 +1816,6 @@ msgstr "" msgid "%{student}'s report cards" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:61 -#: lib/lanttern_web/live/shared/menu_component.ex:73 -#, elixir-autogen, elixir-format -msgid "Home" -msgstr "" - #: lib/lanttern_web/controllers/error_html/500.html.heex:32 #, elixir-autogen, elixir-format msgid "Internal server error" @@ -1835,13 +1843,13 @@ msgstr "" msgid "Welcome!" msgstr "" -#: lib/lanttern_web/user_auth.ex:282 -#: lib/lanttern_web/user_auth.ex:318 +#: lib/lanttern_web/user_auth.ex:288 +#: lib/lanttern_web/user_auth.ex:345 #, elixir-autogen, elixir-format msgid "You must log in to access this page." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:97 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:104 #, elixir-autogen, elixir-format msgid "About this assessment" msgstr "" @@ -2006,7 +2014,7 @@ msgstr "" #: lib/lanttern_web/controllers/privacy_policy_controller.ex:11 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:48 -#: lib/lanttern_web/live/shared/menu_component.ex:183 +#: lib/lanttern_web/live/shared/menu_component.ex:186 #, elixir-autogen, elixir-format msgid "Privacy policy" msgstr "" @@ -2048,7 +2056,7 @@ msgstr "" msgid "Privacy policy and terms of service" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:191 +#: lib/lanttern_web/live/shared/menu_component.ex:194 #, elixir-autogen, elixir-format msgid "Terms of service" msgstr "" @@ -2103,7 +2111,7 @@ msgstr "" msgid "to this report card" msgstr "" -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:77 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:80 #, elixir-autogen, elixir-format msgid "All" msgstr "" @@ -2224,7 +2232,7 @@ msgstr "" msgid "Students report cards access updated" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:82 +#: lib/lanttern_web/components/reporting_components.ex:120 #, elixir-autogen, elixir-format msgid "Under development" msgstr "" @@ -2234,12 +2242,7 @@ msgstr "" msgid "Add a moment note" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "Add note" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:8 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:8 #, elixir-autogen, elixir-format msgid "All cycles" msgstr "" @@ -2266,28 +2269,23 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:23 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:23 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:23 #, elixir-autogen, elixir-format msgid "My strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:60 -#, elixir-autogen, elixir-format -msgid "No notes for this strand yet" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:14 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:16 #, elixir-autogen, elixir-format msgid "No strands related to selected cycles" msgstr "" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:29 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:29 #, elixir-autogen, elixir-format msgid "No student notes for this strand" msgstr "" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:49 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:59 -#: lib/lanttern_web/live/shared/menu_component.ex:64 #, elixir-autogen, elixir-format msgid "Notes" msgstr "" @@ -2297,26 +2295,18 @@ msgstr "" msgid "Select classes to view student notes" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:60 #, elixir-autogen, elixir-format msgid "Student notes" msgstr "" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:24 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:24 #, elixir-autogen, elixir-format msgid "Student strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:77 -#, elixir-autogen, elixir-format -msgid "View note in report card context" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "View/edit note" -msgstr "" - #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:58 #, elixir-autogen, elixir-format msgid "students strand notes" @@ -2327,11 +2317,6 @@ msgstr "" msgid "to view students strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:98 -#, elixir-autogen, elixir-format -msgid "under development" -msgstr "" - #: lib/lanttern_web/live/shared/notes/note_component.ex:88 #, elixir-autogen, elixir-format msgid "updated" @@ -2388,13 +2373,8 @@ msgstr "" msgid "Links should start with \"https://\" or \"http://\"" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:2 -#, elixir-autogen, elixir-format -msgid "My strands notes" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:71 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:42 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:42 #, elixir-autogen, elixir-format msgid "Note's attachments" msgstr "" @@ -2409,11 +2389,6 @@ msgstr "" msgid "Or add a link to an external file" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:47 -#, elixir-autogen, elixir-format -msgid "Strand note" -msgstr "" - #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:79 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:111 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:187 @@ -2451,15 +2426,15 @@ msgstr "" msgid "%{student} comment" msgstr "" -#: lib/lanttern_web/components/assessments_components.ex:123 +#: lib/lanttern_web/components/assessments_components.ex:141 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:45 #, elixir-autogen, elixir-format msgid "Student self-assessment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:143 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:39 +#: lib/lanttern_web/components/reporting_components.ex:36 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:224 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:207 #, elixir-autogen, elixir-format msgid "Teacher comment" msgstr "" @@ -2641,7 +2616,7 @@ msgstr "" msgid "Strand assessment" msgstr "" -#: lib/lanttern_web/components/assessments_components.ex:120 +#: lib/lanttern_web/components/assessments_components.ex:138 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:42 #, elixir-autogen, elixir-format msgid "Teacher assessment" @@ -2688,85 +2663,111 @@ msgstr "" msgid "Strand removed from your starred list" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:153 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:217 #, elixir-autogen, elixir-format msgid "Assessment info" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format msgid "Assessment rubric" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format msgid "Assessment scale" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:24 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:66 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:69 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:68 #, elixir-autogen, elixir-format msgid "Criteria:" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:73 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:80 #, elixir-autogen, elixir-format msgid "Formative assessment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:83 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:160 #, elixir-autogen, elixir-format msgid "Formative assessment pattern" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:157 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:221 #, elixir-autogen, elixir-format msgid "Has rubric" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:33 #, elixir-autogen, elixir-format msgid "Here you'll find information about the strand final and formative assessments." msgstr "" #: lib/lanttern_web/components/assessments_components.ex:67 -#: lib/lanttern_web/components/assessments_components.ex:188 +#: lib/lanttern_web/components/assessments_components.ex:206 #, elixir-autogen, elixir-format msgid "No entry" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:148 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:50 +#: lib/lanttern_web/components/reporting_components.ex:40 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:212 #, elixir-autogen, elixir-format msgid "Student comment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:17 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:30 #, elixir-autogen, elixir-format msgid "Here you'll find information about the strand learning journey." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:61 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:72 #, elixir-autogen, elixir-format msgid "No moments registered for this strand" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:38 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:32 #, elixir-autogen, elixir-format msgid "No strand report info yet." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:16 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:27 #, elixir-autogen, elixir-format msgid "Strand rubrics" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:24 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:38 #, elixir-autogen, elixir-format msgid "You can click the assessment card to view more details about it." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:20 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:33 #, elixir-autogen, elixir-format msgid "You can click the moment card to view more details about it, including information about formative assessment." msgstr "" + +#: lib/lanttern_web/components/assessments_components.ex:104 +#, elixir-autogen, elixir-format +msgid "Final assessment not available yet" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:31 +#, elixir-autogen, elixir-format +msgid "Goals assessment entries" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:54 +#, elixir-autogen, elixir-format +msgid "Goals without assessment entries" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:49 +#, elixir-autogen, elixir-format +msgid "No assessment entries for this strand yet" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:61 +#, elixir-autogen, elixir-format +msgid "Rubric differentiation" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index ed9d43ff..2f2fd54c 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -47,7 +47,11 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:9 #: lib/lanttern_web/live/pages/strands/strands_live.ex:52 #: lib/lanttern_web/live/pages/strands/strands_live.html.heex:2 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:2 #: lib/lanttern_web/live/shared/menu_component.ex:37 +#: lib/lanttern_web/live/shared/menu_component.ex:64 +#: lib/lanttern_web/live/shared/menu_component.ex:76 #, elixir-autogen, elixir-format msgid "Strands" msgstr "" @@ -59,23 +63,23 @@ msgstr "" msgid "close" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:115 +#: lib/lanttern_web/live/shared/menu_component.ex:118 #, elixir-autogen, elixir-format msgid "Change profile" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:152 +#: lib/lanttern_web/live/shared/menu_component.ex:155 #, elixir-autogen, elixir-format msgid "Language:" msgstr "" #: lib/lanttern_web/controllers/privacy_policy_html/accept_policy.html.heex:25 -#: lib/lanttern_web/live/shared/menu_component.ex:145 +#: lib/lanttern_web/live/shared/menu_component.ex:148 #, elixir-autogen, elixir-format msgid "Log out" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:87 +#: lib/lanttern_web/live/shared/menu_component.ex:90 #, elixir-autogen, elixir-format msgid "You're logged in as" msgstr "" @@ -86,7 +90,7 @@ msgid "All strands" msgstr "" #: lib/lanttern_web/live/shared/filters/filters_overlay_component.ex:33 -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:32 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:33 #, elixir-autogen, elixir-format msgid "Apply filters" msgstr "" @@ -371,7 +375,8 @@ msgid "About" msgstr "" #: lib/lanttern_web/components/grades_reports_components.ex:604 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:48 #, elixir-autogen, elixir-format, fuzzy msgid "Assessment" msgstr "" @@ -421,8 +426,8 @@ msgid "Strand deleted" msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:25 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:61 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:31 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:31 #, elixir-autogen, elixir-format msgid "Add a strand note" msgstr "" @@ -479,10 +484,10 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/about_component.ex:54 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:74 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:117 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:62 #: lib/lanttern_web/live/shared/assessments/assessment_point_form_component.ex:84 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:65 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:181 #, elixir-autogen, elixir-format msgid "Differentiation" msgstr "" @@ -584,6 +589,7 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:24 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:28 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:28 #, elixir-autogen, elixir-format msgid "You don't have any notes for this strand yet" msgstr "" @@ -757,7 +763,7 @@ msgstr "" msgid "to assess students" msgstr "" -#: lib/lanttern/learning_context/strand.ex:90 +#: lib/lanttern/learning_context/strand.ex:95 #, elixir-autogen, elixir-format msgid "Strand has linked assessment points." msgstr "" @@ -830,7 +836,8 @@ msgid "Moment updated successfully" msgstr "" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:43 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:54 #, elixir-autogen, elixir-format, fuzzy msgid "Moments" msgstr "" @@ -855,7 +862,7 @@ msgstr "" msgid "Save moment" msgstr "" -#: lib/lanttern/learning_context.ex:443 +#: lib/lanttern/learning_context.ex:531 #: lib/lanttern/repo_helpers.ex:122 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:53 #: lib/lanttern_web/live/pages/report_cards/id/students_grades_component.ex:283 @@ -880,12 +887,13 @@ msgstr "" msgid "Strand has linked moments and/or assessment points (goals). Deleting it would cause some data loss." msgstr "" -#: lib/lanttern/learning_context/strand.ex:85 +#: lib/lanttern/learning_context/strand.ex:90 #, elixir-autogen, elixir-format, fuzzy msgid "Strand has linked moments." msgstr "" #: lib/lanttern_web/live/pages/strands/id/moments_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:28 #, elixir-autogen, elixir-format, fuzzy msgid "Strand moments" msgstr "" @@ -1067,7 +1075,8 @@ msgstr "" msgid "Curriculum components" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:60 #, elixir-autogen, elixir-format msgid "Curriculum differentiation" msgstr "" @@ -1082,12 +1091,13 @@ msgstr "" msgid "Curriculum items" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:70 +#: lib/lanttern_web/components/reporting_components.ex:108 #: lib/lanttern_web/live/pages/grading/grades_reports_live.html.heex:39 #: lib/lanttern_web/live/pages/report_cards/id/report_card_live.html.heex:14 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:34 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:34 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:23 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:107 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:25 #: lib/lanttern_web/live/shared/reporting/report_card_form_component.ex:37 #, elixir-autogen, elixir-format msgid "Cycle" @@ -1099,7 +1109,7 @@ msgstr "" msgid "Cycle already added to this grade report" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:266 +#: lib/lanttern_web/components/reporting_components.ex:306 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:27 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:106 #: lib/lanttern_web/live/shared/assessments/assessments_grid_component.ex:353 @@ -1463,7 +1473,8 @@ msgid "Normalized value" msgstr "" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:40 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:42 #, elixir-autogen, elixir-format msgid "Overview" msgstr "" @@ -1519,6 +1530,8 @@ msgstr "" #: lib/lanttern_web/live/pages/report_cards/report_cards_live.ex:29 #: lib/lanttern_web/live/pages/strands/id/about_component.ex:112 #: lib/lanttern_web/live/shared/menu_component.ex:49 +#: lib/lanttern_web/live/shared/menu_component.ex:61 +#: lib/lanttern_web/live/shared/menu_component.ex:73 #, elixir-autogen, elixir-format msgid "Report cards" msgstr "" @@ -1614,7 +1627,8 @@ msgstr "" msgid "Strand id" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:12 #, elixir-autogen, elixir-format, fuzzy msgid "Strand report" msgstr "" @@ -1654,7 +1668,7 @@ msgstr "" msgid "Student grades calculated succesfully" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:10 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:5 #, elixir-autogen, elixir-format msgid "Student report card" @@ -1802,12 +1816,6 @@ msgstr "" msgid "%{student}'s report cards" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:61 -#: lib/lanttern_web/live/shared/menu_component.ex:73 -#, elixir-autogen, elixir-format -msgid "Home" -msgstr "" - #: lib/lanttern_web/controllers/error_html/500.html.heex:32 #, elixir-autogen, elixir-format msgid "Internal server error" @@ -1835,13 +1843,13 @@ msgstr "" msgid "Welcome!" msgstr "" -#: lib/lanttern_web/user_auth.ex:282 -#: lib/lanttern_web/user_auth.ex:318 +#: lib/lanttern_web/user_auth.ex:288 +#: lib/lanttern_web/user_auth.ex:345 #, elixir-autogen, elixir-format msgid "You must log in to access this page." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:97 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:104 #, elixir-autogen, elixir-format msgid "About this assessment" msgstr "" @@ -2006,7 +2014,7 @@ msgstr "" #: lib/lanttern_web/controllers/privacy_policy_controller.ex:11 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:48 -#: lib/lanttern_web/live/shared/menu_component.ex:183 +#: lib/lanttern_web/live/shared/menu_component.ex:186 #, elixir-autogen, elixir-format msgid "Privacy policy" msgstr "" @@ -2048,7 +2056,7 @@ msgstr "" msgid "Privacy policy and terms of service" msgstr "" -#: lib/lanttern_web/live/shared/menu_component.ex:191 +#: lib/lanttern_web/live/shared/menu_component.ex:194 #, elixir-autogen, elixir-format msgid "Terms of service" msgstr "" @@ -2103,7 +2111,7 @@ msgstr "" msgid "to this report card" msgstr "" -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:77 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:80 #, elixir-autogen, elixir-format msgid "All" msgstr "" @@ -2224,7 +2232,7 @@ msgstr "" msgid "Students report cards access updated" msgstr "" -#: lib/lanttern_web/components/reporting_components.ex:82 +#: lib/lanttern_web/components/reporting_components.ex:120 #, elixir-autogen, elixir-format msgid "Under development" msgstr "" @@ -2234,12 +2242,7 @@ msgstr "" msgid "Add a moment note" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "Add note" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:8 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:8 #, elixir-autogen, elixir-format, fuzzy msgid "All cycles" msgstr "" @@ -2266,28 +2269,23 @@ msgstr "" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:23 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:23 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:23 #, elixir-autogen, elixir-format, fuzzy msgid "My strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:60 -#, elixir-autogen, elixir-format, fuzzy -msgid "No notes for this strand yet" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:14 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:16 #, elixir-autogen, elixir-format, fuzzy msgid "No strands related to selected cycles" msgstr "" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:29 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:29 #, elixir-autogen, elixir-format msgid "No student notes for this strand" msgstr "" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:49 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:59 -#: lib/lanttern_web/live/shared/menu_component.ex:64 #, elixir-autogen, elixir-format, fuzzy msgid "Notes" msgstr "" @@ -2297,26 +2295,18 @@ msgstr "" msgid "Select classes to view student notes" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:60 #, elixir-autogen, elixir-format, fuzzy msgid "Student notes" msgstr "" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:24 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:24 #, elixir-autogen, elixir-format, fuzzy msgid "Student strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:77 -#, elixir-autogen, elixir-format -msgid "View note in report card context" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "View/edit note" -msgstr "" - #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:58 #, elixir-autogen, elixir-format msgid "students strand notes" @@ -2327,11 +2317,6 @@ msgstr "" msgid "to view students strand notes" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:98 -#, elixir-autogen, elixir-format, fuzzy -msgid "under development" -msgstr "" - #: lib/lanttern_web/live/shared/notes/note_component.ex:88 #, elixir-autogen, elixir-format msgid "updated" @@ -2388,13 +2373,8 @@ msgstr "" msgid "Links should start with \"https://\" or \"http://\"" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:2 -#, elixir-autogen, elixir-format, fuzzy -msgid "My strands notes" -msgstr "" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:71 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:42 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:42 #, elixir-autogen, elixir-format msgid "Note's attachments" msgstr "" @@ -2409,11 +2389,6 @@ msgstr "" msgid "Or add a link to an external file" msgstr "" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:47 -#, elixir-autogen, elixir-format, fuzzy -msgid "Strand note" -msgstr "" - #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:79 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:111 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:187 @@ -2451,15 +2426,15 @@ msgstr "" msgid "%{student} comment" msgstr "" -#: lib/lanttern_web/components/assessments_components.ex:123 +#: lib/lanttern_web/components/assessments_components.ex:141 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:45 #, elixir-autogen, elixir-format msgid "Student self-assessment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:143 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:39 +#: lib/lanttern_web/components/reporting_components.ex:36 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:224 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:207 #, elixir-autogen, elixir-format, fuzzy msgid "Teacher comment" msgstr "" @@ -2641,7 +2616,7 @@ msgstr "" msgid "Strand assessment" msgstr "" -#: lib/lanttern_web/components/assessments_components.ex:120 +#: lib/lanttern_web/components/assessments_components.ex:138 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:42 #, elixir-autogen, elixir-format, fuzzy msgid "Teacher assessment" @@ -2688,85 +2663,111 @@ msgstr "" msgid "Strand removed from your starred list" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:153 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:217 #, elixir-autogen, elixir-format, fuzzy msgid "Assessment info" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format, fuzzy msgid "Assessment rubric" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format, fuzzy msgid "Assessment scale" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:24 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:66 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:69 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:68 #, elixir-autogen, elixir-format, fuzzy msgid "Criteria:" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:73 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:80 #, elixir-autogen, elixir-format, fuzzy msgid "Formative assessment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:83 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:160 #, elixir-autogen, elixir-format msgid "Formative assessment pattern" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:157 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:221 #, elixir-autogen, elixir-format, fuzzy msgid "Has rubric" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:33 #, elixir-autogen, elixir-format msgid "Here you'll find information about the strand final and formative assessments." msgstr "" #: lib/lanttern_web/components/assessments_components.ex:67 -#: lib/lanttern_web/components/assessments_components.ex:188 +#: lib/lanttern_web/components/assessments_components.ex:206 #, elixir-autogen, elixir-format msgid "No entry" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:148 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:50 +#: lib/lanttern_web/components/reporting_components.ex:40 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:212 #, elixir-autogen, elixir-format, fuzzy msgid "Student comment" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:17 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:30 #, elixir-autogen, elixir-format, fuzzy msgid "Here you'll find information about the strand learning journey." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:61 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:72 #, elixir-autogen, elixir-format, fuzzy msgid "No moments registered for this strand" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:38 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:32 #, elixir-autogen, elixir-format, fuzzy msgid "No strand report info yet." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:16 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:27 #, elixir-autogen, elixir-format, fuzzy msgid "Strand rubrics" msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:24 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:38 #, elixir-autogen, elixir-format, fuzzy msgid "You can click the assessment card to view more details about it." msgstr "" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:20 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:33 #, elixir-autogen, elixir-format msgid "You can click the moment card to view more details about it, including information about formative assessment." msgstr "" + +#: lib/lanttern_web/components/assessments_components.ex:104 +#, elixir-autogen, elixir-format +msgid "Final assessment not available yet" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:31 +#, elixir-autogen, elixir-format, fuzzy +msgid "Goals assessment entries" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:54 +#, elixir-autogen, elixir-format, fuzzy +msgid "Goals without assessment entries" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:49 +#, elixir-autogen, elixir-format, fuzzy +msgid "No assessment entries for this strand yet" +msgstr "" + +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:61 +#, elixir-autogen, elixir-format, fuzzy +msgid "Rubric differentiation" +msgstr "" diff --git a/priv/gettext/pt_BR/LC_MESSAGES/default.po b/priv/gettext/pt_BR/LC_MESSAGES/default.po index f0ec6580..e437ed0d 100644 --- a/priv/gettext/pt_BR/LC_MESSAGES/default.po +++ b/priv/gettext/pt_BR/LC_MESSAGES/default.po @@ -47,7 +47,11 @@ msgstr "Escola" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:9 #: lib/lanttern_web/live/pages/strands/strands_live.ex:52 #: lib/lanttern_web/live/pages/strands/strands_live.html.heex:2 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:2 #: lib/lanttern_web/live/shared/menu_component.ex:37 +#: lib/lanttern_web/live/shared/menu_component.ex:64 +#: lib/lanttern_web/live/shared/menu_component.ex:76 #, elixir-autogen, elixir-format msgid "Strands" msgstr "Trilhas" @@ -59,23 +63,23 @@ msgstr "Trilhas" msgid "close" msgstr "fechar" -#: lib/lanttern_web/live/shared/menu_component.ex:115 +#: lib/lanttern_web/live/shared/menu_component.ex:118 #, elixir-autogen, elixir-format msgid "Change profile" msgstr "Alterar perfil" -#: lib/lanttern_web/live/shared/menu_component.ex:152 +#: lib/lanttern_web/live/shared/menu_component.ex:155 #, elixir-autogen, elixir-format msgid "Language:" msgstr "Idioma:" #: lib/lanttern_web/controllers/privacy_policy_html/accept_policy.html.heex:25 -#: lib/lanttern_web/live/shared/menu_component.ex:145 +#: lib/lanttern_web/live/shared/menu_component.ex:148 #, elixir-autogen, elixir-format msgid "Log out" msgstr "Sair" -#: lib/lanttern_web/live/shared/menu_component.ex:87 +#: lib/lanttern_web/live/shared/menu_component.ex:90 #, elixir-autogen, elixir-format msgid "You're logged in as" msgstr "Você está acessando como" @@ -86,7 +90,7 @@ msgid "All strands" msgstr "Todas as trilhas" #: lib/lanttern_web/live/shared/filters/filters_overlay_component.ex:33 -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:32 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:33 #, elixir-autogen, elixir-format msgid "Apply filters" msgstr "Aplicar filtros" @@ -371,7 +375,8 @@ msgid "About" msgstr "Sobre" #: lib/lanttern_web/components/grades_reports_components.ex:604 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:61 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:48 #, elixir-autogen, elixir-format msgid "Assessment" msgstr "Avaliação" @@ -421,8 +426,8 @@ msgid "Strand deleted" msgstr "Trilha deletada" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:25 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:61 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:31 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:31 #, elixir-autogen, elixir-format msgid "Add a strand note" msgstr "Adicionar uma anotação da trilha" @@ -479,10 +484,10 @@ msgstr "Deletar anotação" #: lib/lanttern_web/live/pages/strands/id/about_component.ex:54 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:74 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:117 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:62 #: lib/lanttern_web/live/shared/assessments/assessment_point_form_component.ex:84 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:65 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:181 #, elixir-autogen, elixir-format msgid "Differentiation" msgstr "Diferenciação" @@ -584,6 +589,7 @@ msgstr "Visualizando" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:24 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:28 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:28 #, elixir-autogen, elixir-format msgid "You don't have any notes for this strand yet" msgstr "Você ainda não poussui anotações para esta trilha" @@ -757,7 +763,7 @@ msgstr "Este ponto de avaliação já possui alguns registros. Deletá-lo irá c msgid "to assess students" msgstr "para avaliar estudantes" -#: lib/lanttern/learning_context/strand.ex:90 +#: lib/lanttern/learning_context/strand.ex:95 #, elixir-autogen, elixir-format msgid "Strand has linked assessment points." msgstr "Trilha possui pontos de avaliação conectados." @@ -830,7 +836,8 @@ msgid "Moment updated successfully" msgstr "Momento atualizado com sucesso" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:43 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:69 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:54 #, elixir-autogen, elixir-format msgid "Moments" msgstr "Momentos" @@ -855,7 +862,7 @@ msgstr "Nenhum momento para esta trilha ainda" msgid "Save moment" msgstr "Salvar momento" -#: lib/lanttern/learning_context.ex:443 +#: lib/lanttern/learning_context.ex:531 #: lib/lanttern/repo_helpers.ex:122 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:53 #: lib/lanttern_web/live/pages/report_cards/id/students_grades_component.ex:283 @@ -880,12 +887,13 @@ msgstr "Ordem dos Momentos da Trilha" msgid "Strand has linked moments and/or assessment points (goals). Deleting it would cause some data loss." msgstr "Trilha com momentos e/ou pontos de avaliação (objetivos) conectados. Deletá-la causaria perda de dados." -#: lib/lanttern/learning_context/strand.ex:85 +#: lib/lanttern/learning_context/strand.ex:90 #, elixir-autogen, elixir-format msgid "Strand has linked moments." msgstr "Trilha possui momentos conectados." #: lib/lanttern_web/live/pages/strands/id/moments_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:28 #, elixir-autogen, elixir-format msgid "Strand moments" msgstr "Momentos da trilha" @@ -1067,7 +1075,8 @@ msgstr "Componente curricular" msgid "Curriculum components" msgstr "Componentes curriculares" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:28 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:60 #, elixir-autogen, elixir-format msgid "Curriculum differentiation" msgstr "Diferenciação curricular" @@ -1082,12 +1091,13 @@ msgstr "Item curricular removido" msgid "Curriculum items" msgstr "Itens curriculares" -#: lib/lanttern_web/components/reporting_components.ex:70 +#: lib/lanttern_web/components/reporting_components.ex:108 #: lib/lanttern_web/live/pages/grading/grades_reports_live.html.heex:39 #: lib/lanttern_web/live/pages/report_cards/id/report_card_live.html.heex:14 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:34 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:34 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:23 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:107 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:25 #: lib/lanttern_web/live/shared/reporting/report_card_form_component.ex:37 #, elixir-autogen, elixir-format msgid "Cycle" @@ -1099,7 +1109,7 @@ msgstr "Ciclo" msgid "Cycle already added to this grade report" msgstr "Ciclo já adicionado à este relatório de nota" -#: lib/lanttern_web/components/reporting_components.ex:266 +#: lib/lanttern_web/components/reporting_components.ex:306 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:27 #: lib/lanttern_web/live/pages/strands/id/strand_rubrics_component.ex:106 #: lib/lanttern_web/live/shared/assessments/assessments_grid_component.ex:353 @@ -1463,7 +1473,8 @@ msgid "Normalized value" msgstr "Valor normalizado" #: lib/lanttern_web/live/pages/strands/moment/id/moment_live.html.heex:40 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:53 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:42 #, elixir-autogen, elixir-format msgid "Overview" msgstr "Visão geral" @@ -1519,6 +1530,8 @@ msgstr "Id do report card" #: lib/lanttern_web/live/pages/report_cards/report_cards_live.ex:29 #: lib/lanttern_web/live/pages/strands/id/about_component.ex:112 #: lib/lanttern_web/live/shared/menu_component.ex:49 +#: lib/lanttern_web/live/shared/menu_component.ex:61 +#: lib/lanttern_web/live/shared/menu_component.ex:73 #, elixir-autogen, elixir-format msgid "Report cards" msgstr "Report cards" @@ -1614,7 +1627,8 @@ msgstr "Objetivo da Trilha" msgid "Strand id" msgstr "Id da trilha" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:12 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:12 #, elixir-autogen, elixir-format msgid "Strand report" msgstr "Relatório da trilha" @@ -1654,7 +1668,7 @@ msgstr "Registro de relatório de nota de estudante atualizado com sucesso" msgid "Student grades calculated succesfully" msgstr "Notas do estudantes calculadas com sucesso" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:10 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:10 #: lib/lanttern_web/live/pages/student_report_card/id/student_report_card_live.html.heex:5 #, elixir-autogen, elixir-format msgid "Student report card" @@ -1802,12 +1816,6 @@ msgstr "Filtrar trilhas por ano" msgid "%{student}'s report cards" msgstr "Report cards de %{student}" -#: lib/lanttern_web/live/shared/menu_component.ex:61 -#: lib/lanttern_web/live/shared/menu_component.ex:73 -#, elixir-autogen, elixir-format -msgid "Home" -msgstr "Início" - #: lib/lanttern_web/controllers/error_html/500.html.heex:32 #, elixir-autogen, elixir-format msgid "Internal server error" @@ -1835,13 +1843,13 @@ msgstr "Detalhes da trilha" msgid "Welcome!" msgstr "Bem-vinda!" -#: lib/lanttern_web/user_auth.ex:282 -#: lib/lanttern_web/user_auth.ex:318 +#: lib/lanttern_web/user_auth.ex:288 +#: lib/lanttern_web/user_auth.ex:345 #, elixir-autogen, elixir-format msgid "You must log in to access this page." msgstr "Você precisa estar logado para acessar esta página." -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:97 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:104 #, elixir-autogen, elixir-format msgid "About this assessment" msgstr "Sobre esta avaliação" @@ -2006,7 +2014,7 @@ msgstr "Confirmar" #: lib/lanttern_web/controllers/privacy_policy_controller.ex:11 #: lib/lanttern_web/controllers/privacy_policy_controller.ex:48 -#: lib/lanttern_web/live/shared/menu_component.ex:183 +#: lib/lanttern_web/live/shared/menu_component.ex:186 #, elixir-autogen, elixir-format msgid "Privacy policy" msgstr "Política de privacidade" @@ -2048,7 +2056,7 @@ msgstr "Ao utilizar o Lanttern, você confirma ter lido e estar de acordo com no msgid "Privacy policy and terms of service" msgstr "Política de privacidade e termos de uso" -#: lib/lanttern_web/live/shared/menu_component.ex:191 +#: lib/lanttern_web/live/shared/menu_component.ex:194 #, elixir-autogen, elixir-format msgid "Terms of service" msgstr "Termos de uso" @@ -2103,7 +2111,7 @@ msgstr "para listar estudantes" msgid "to this report card" msgstr "a este report card" -#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:77 +#: lib/lanttern_web/live/shared/filters/inline_filters_component.ex:80 #, elixir-autogen, elixir-format msgid "All" msgstr "Tudo" @@ -2224,7 +2232,7 @@ msgstr "Acesso de estudantes" msgid "Students report cards access updated" msgstr "Report cards de estudante atualizados" -#: lib/lanttern_web/components/reporting_components.ex:82 +#: lib/lanttern_web/components/reporting_components.ex:120 #, elixir-autogen, elixir-format msgid "Under development" msgstr "Em desenvolvimento" @@ -2234,12 +2242,7 @@ msgstr "Em desenvolvimento" msgid "Add a moment note" msgstr "Adicionar anotações sobre o momento" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "Add note" -msgstr "Adicionar anotações" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:8 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:8 #, elixir-autogen, elixir-format msgid "All cycles" msgstr "Todos os ciclos" @@ -2266,28 +2269,23 @@ msgstr "Meus report cards" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:23 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:23 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:23 #, elixir-autogen, elixir-format msgid "My strand notes" msgstr "Minhas anotações sobre a trilha" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:60 -#, elixir-autogen, elixir-format -msgid "No notes for this strand yet" -msgstr "Nenhuma anotação sobre esta trilha ainda" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:14 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:16 #, elixir-autogen, elixir-format msgid "No strands related to selected cycles" msgstr "Nenhuma trilha relacionada aos ciclos selecionados" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:29 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:29 #, elixir-autogen, elixir-format msgid "No student notes for this strand" msgstr "Nenhuma anotação de estudante sobre esta trilha" #: lib/lanttern_web/live/pages/strands/id/strand_live.html.heex:49 -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:59 -#: lib/lanttern_web/live/shared/menu_component.ex:64 #, elixir-autogen, elixir-format msgid "Notes" msgstr "Anotações" @@ -2297,25 +2295,17 @@ msgstr "Anotações" msgid "Select classes to view student notes" msgstr "Selecione uma turma para visualizar anotações dos estudantes" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_report_card_strand_report_live.html.heex:77 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_strand_report_live.html.heex:60 #, elixir-autogen, elixir-format msgid "Student notes" -msgstr "Anotações de estudantes" +msgstr "Anotações do estudante" #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:24 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:24 #, elixir-autogen, elixir-format msgid "Student strand notes" -msgstr "Anotações de estudantes sobre a trilha" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:77 -#, elixir-autogen, elixir-format -msgid "View note in report card context" -msgstr "Ver anotação no contexto do report card" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:34 -#, elixir-autogen, elixir-format -msgid "View/edit note" -msgstr "Ver/editar anotação" +msgstr "Anotações do estudante sobre a trilha" #: lib/lanttern_web/live/pages/strands/id/notes_component.ex:58 #, elixir-autogen, elixir-format @@ -2327,11 +2317,6 @@ msgstr "anotações de estudantes sobre a trillha" msgid "to view students strand notes" msgstr "para visualizar anotações de estudantes sobre a trilha" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:98 -#, elixir-autogen, elixir-format -msgid "under development" -msgstr "em desenvolvimento" - #: lib/lanttern_web/live/shared/notes/note_component.ex:88 #, elixir-autogen, elixir-format msgid "updated" @@ -2388,13 +2373,8 @@ msgstr "Formato do link inválido" msgid "Links should start with \"https://\" or \"http://\"" msgstr "Links precisam começar com \"https://\" ou \"http://\"" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:2 -#, elixir-autogen, elixir-format -msgid "My strands notes" -msgstr "Minhas anotações sobre as trilhas" - -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:71 #: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/student_notes_component.ex:42 +#: lib/lanttern_web/live/pages/student_strand_report/id/student_notes_component.ex:42 #, elixir-autogen, elixir-format msgid "Note's attachments" msgstr "Anexos da anotação" @@ -2409,11 +2389,6 @@ msgstr "Apenas arquivos do tipo %{formats} são aceitos" msgid "Or add a link to an external file" msgstr "Ou adicione um link para um arquivo externo" -#: lib/lanttern_web/live/pages/student notes/student_notes_live.html.heex:47 -#, elixir-autogen, elixir-format -msgid "Strand note" -msgstr "Anotação sobre a trilha" - #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:79 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:111 #: lib/lanttern_web/live/shared/attachments/attachment_area_component.ex:187 @@ -2451,15 +2426,15 @@ msgstr "Professor" msgid "%{student} comment" msgstr "Comentário de %{student}" -#: lib/lanttern_web/components/assessments_components.ex:123 +#: lib/lanttern_web/components/assessments_components.ex:141 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:45 #, elixir-autogen, elixir-format msgid "Student self-assessment" msgstr "Autoavaliação do estudante" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:143 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:39 +#: lib/lanttern_web/components/reporting_components.ex:36 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:224 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:207 #, elixir-autogen, elixir-format msgid "Teacher comment" msgstr "Comentário do professor" @@ -2641,7 +2616,7 @@ msgstr "Mostrar somente avaliações dos objetivos" msgid "Strand assessment" msgstr "Avaliação da trilha" -#: lib/lanttern_web/components/assessments_components.ex:120 +#: lib/lanttern_web/components/assessments_components.ex:138 #: lib/lanttern_web/live/shared/assessments/entry_details_component.ex:42 #, elixir-autogen, elixir-format msgid "Teacher assessment" @@ -2688,85 +2663,111 @@ msgstr "Nenhuma trilha favoritada ainda" msgid "Strand removed from your starred list" msgstr "Trilha removida da sua lista de favoritas" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:153 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:217 #, elixir-autogen, elixir-format msgid "Assessment info" msgstr "Informações da avaliação" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format msgid "Assessment rubric" msgstr "Rubrica de avaliação" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:59 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:62 #, elixir-autogen, elixir-format msgid "Assessment scale" msgstr "Escala da avaliação" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:24 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:66 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:69 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:68 #, elixir-autogen, elixir-format msgid "Criteria:" msgstr "Critério:" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:73 +#: lib/lanttern_web/live/shared/assessments/strand_goal_details_overlay_component.ex:80 #, elixir-autogen, elixir-format msgid "Formative assessment" msgstr "Avaliação formativa" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:83 +#: lib/lanttern_web/live/pages/student_strands/student_strands_live.html.heex:39 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:160 #, elixir-autogen, elixir-format msgid "Formative assessment pattern" msgstr "Padrão da avaliação formativa" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:157 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:221 #, elixir-autogen, elixir-format msgid "Has rubric" msgstr "Possui rubrica" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:19 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:33 #, elixir-autogen, elixir-format msgid "Here you'll find information about the strand final and formative assessments." msgstr "Aqui você irá encontrar informações sobre as avaliações final e formativa da trilha." #: lib/lanttern_web/components/assessments_components.ex:67 -#: lib/lanttern_web/components/assessments_components.ex:188 +#: lib/lanttern_web/components/assessments_components.ex:206 #, elixir-autogen, elixir-format msgid "No entry" msgstr "Sem registro" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:148 -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/strand_goal_details_component.ex:50 +#: lib/lanttern_web/components/reporting_components.ex:40 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:212 #, elixir-autogen, elixir-format msgid "Student comment" msgstr "Comentário do estudante" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:17 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:30 #, elixir-autogen, elixir-format msgid "Here you'll find information about the strand learning journey." msgstr "Aqui você irá encontrar informações sobre a jornada de aprendizagem da trilha." -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:61 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:72 #, elixir-autogen, elixir-format msgid "No moments registered for this strand" msgstr "Nenhum momento registrado nesta trilha" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:38 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:32 #, elixir-autogen, elixir-format msgid "No strand report info yet." msgstr "Nenhuma informação do relatório ainda." -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/overview_component.ex:16 +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:27 #, elixir-autogen, elixir-format msgid "Strand rubrics" msgstr "Rubricas da trilha" -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/assessment_component.ex:24 +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:38 #, elixir-autogen, elixir-format msgid "You can click the assessment card to view more details about it." msgstr "Você pode clicar no card da avaliação para ver mais detalhes." -#: lib/lanttern_web/live/pages/student_report_card/id/strand_report/strand_report_id/moments_component.ex:20 +#: lib/lanttern_web/live/shared/reporting/strand_report_moments_component.ex:33 #, elixir-autogen, elixir-format msgid "You can click the moment card to view more details about it, including information about formative assessment." -msgstr "Você pode clicar no card do momento para ver mais detalhes sobre, incluindo informações sobre avaliação formativa." +msgstr "Você pode clicar no card do momento para ver mais detalhes, incluindo informações sobre avaliação formativa." + +#: lib/lanttern_web/components/assessments_components.ex:104 +#, elixir-autogen, elixir-format +msgid "Final assessment not available yet" +msgstr "A avaliação final ainda não está disponível" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:31 +#, elixir-autogen, elixir-format +msgid "Goals assessment entries" +msgstr "Registros da avaliação de objetivos" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:54 +#, elixir-autogen, elixir-format +msgid "Goals without assessment entries" +msgstr "Objetivos sem registros de avaliação" + +#: lib/lanttern_web/live/shared/reporting/strand_report_assessment_component.ex:49 +#, elixir-autogen, elixir-format +msgid "No assessment entries for this strand yet" +msgstr "Nenhum registro de avaliação para esta trilha ainda" + +#: lib/lanttern_web/live/shared/reporting/strand_report_overview_component.ex:61 +#, elixir-autogen, elixir-format +msgid "Rubric differentiation" +msgstr "Rubrica de diferenciação"