Skip to content

Commit

Permalink
chore: adjustments
Browse files Browse the repository at this point in the history
- fix: removed duplicated id issues from `EntryEditorComponent` (removed hidden fields and merged entry fields to param programatically before save)

- created `Curricula.list_activity_curriculum_items/2` and implemented it in activity details tab, preventing holding unnecessary intermediate join structs in memory
  • Loading branch information
endoooo committed Nov 29, 2023
1 parent 720cdbc commit 7df327b
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 50 deletions.
44 changes: 36 additions & 8 deletions lib/lanttern/curricula.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ defmodule Lanttern.Curricula do
alias Lanttern.Curricula.CurriculumItem
alias Lanttern.Curricula.CurriculumRelationship

alias Lanttern.LearningContext.Activity

@doc """
Returns the list of curricula.
Expand Down Expand Up @@ -212,6 +214,26 @@ defmodule Lanttern.Curricula do
CurriculumComponent.changeset(curriculum_component, attrs)
end

@doc """
Returns the list of curriculum items.
### Options:
`:preloads` – preloads associated data
`:filters` – accepts `:subject_id` and `:year_id`
## Examples
iex> list_curriculum_items()
[%CurriculumItem{}, ...]
"""
def list_curriculum_items(opts \\ []) do
CurriculumItem
|> maybe_filter(opts)
|> maybe_preload(opts)
end

@doc """
Returns the list of curriculum items linked to the given strand.
Expand All @@ -232,22 +254,28 @@ defmodule Lanttern.Curricula do
end

@doc """
Returns the list of curriculum items.
Returns the list of curriculum items linked to the given activity.
### Options:
## Options:
`:preloads` – preloads associated data
`:filters` – accepts `:subject_id` and `:year_id`
- `:preloads` – preloads associated data
## Examples
iex> list_curriculum_items()
iex> list_activity_curriculum_items(1)
[%CurriculumItem{}, ...]
"""
def list_curriculum_items(opts \\ []) do
CurriculumItem
|> maybe_filter(opts)
def list_activity_curriculum_items(activity_id, opts \\ []) do
from(
a in Activity,
join: ci in assoc(a, :curriculum_items),
where: a.id == ^activity_id,
order_by: ci.name,
distinct: ci.id,
select: ci
)
|> Repo.all()
|> maybe_preload(opts)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ defmodule LantternWeb.AssessmentPointLive.EntryEditorComponent do
class={@class}
id={"entry-#{@id}-marking-form"}
>
<.input type="hidden" field={@form[:id]} />
<.input type="hidden" field={@form[:student_id]} />
<.input type="hidden" field={@form[:assessment_point_id]} />
<.input type="hidden" field={@form[:scale_id]} />
<.input type="hidden" field={@form[:scale_type]} />
<%= for marking_input <- @marking_input do %>
<.marking_input
scale={@assessment_point.scale}
Expand Down Expand Up @@ -107,20 +102,16 @@ defmodule LantternWeb.AssessmentPointLive.EntryEditorComponent do
%{
student: student,
assessment_point: assessment_point,
entry: entry,
id: id
entry: entry
} = assigns,
socket
) do
%{scale: %{ordinal_values: ordinal_values}} = assessment_point

ordinal_value_options = Enum.map(ordinal_values, fn ov -> {:"#{ov.name}", ov.id} end)
entry = entry || new_assessment_point_entry(assessment_point, student.id)

{ov_style, ov_name} =
case entry do
nil ->
{nil, nil}

%{ordinal_value_id: nil} ->
{nil, nil}

Expand All @@ -133,20 +124,14 @@ defmodule LantternWeb.AssessmentPointLive.EntryEditorComponent do
end

form =
case entry do
nil ->
new_assessment_point_entry(assessment_point, student.id)

entry ->
entry
end
entry
|> Assessments.change_assessment_point_entry()
|> to_form()

{:ok,
socket
|> assign(assigns)
|> assign(:id, id)
|> assign(:entry, entry)
|> assign(:ov_style, ov_style)
|> assign(:ov_name, ov_name)
|> assign(:form, form)
Expand All @@ -163,17 +148,28 @@ defmodule LantternWeb.AssessmentPointLive.EntryEditorComponent do
%{"assessment_point_entry" => params},
%{assigns: %{entry: entry}} = socket
) do
entry_params =
entry
|> Map.from_struct()
|> Map.take([:student_id, :assessment_point_id, :scale_id, :scale_type])
|> Map.new(fn {k, v} -> {to_string(k), v} end)

# add extra fields from entry
params =
params
|> Enum.into(entry_params)

case {
entry,
params["scale_type"],
entry.id,
entry.scale_type,
params["ordinal_value_id"],
params["score"]
} do
{nil, "ordinal", ov_id, _} when ov_id != "" -> save(:new, entry, params, socket)
{nil, "numeric", _, score} when score != "" -> save(:new, entry, params, socket)
{entry, "ordinal", "", _} when not is_nil(entry) -> save(:delete, entry, params, socket)
{entry, "numeric", _, ""} when not is_nil(entry) -> save(:delete, entry, params, socket)
{entry, _, _, _} when not is_nil(entry) -> save(:edit, entry, params, socket)
{id, "ordinal", "", _} when not is_nil(id) -> save(:delete, entry, params, socket)
{id, "numeric", _, ""} when not is_nil(id) -> save(:delete, entry, params, socket)
{id, _, _, _} when not is_nil(id) -> save(:edit, entry, params, socket)
_ -> {:noreply, socket}
end
end
Expand Down Expand Up @@ -204,16 +200,20 @@ defmodule LantternWeb.AssessmentPointLive.EntryEditorComponent do
defp save(:delete, entry, _params, socket) do
case Assessments.delete_assessment_point_entry(entry) do
{:ok, _assessment_point_entry} ->
form =
new_entry =
new_assessment_point_entry(socket.assigns.assessment_point, socket.assigns.student.id)

form =
new_entry
|> Assessments.change_assessment_point_entry()
|> to_form()

{:noreply,
socket
|> assign(:ov_style, nil)
|> assign(:ov_name, nil)
|> assign(:form, form)}
|> assign(:form, form)
|> assign(:entry, new_entry)}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
Expand Down
2 changes: 1 addition & 1 deletion lib/lanttern_web/live/strand_live/activity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ defmodule LantternWeb.StrandLive.Activity do
# (during handle_params triggered by tab change for example)

case LearningContext.get_activity(id,
preloads: [:strand, :subjects, curriculum_items: :curriculum_component]
preloads: [:strand, :subjects]
) do
activity when is_nil(activity) ->
socket
Expand Down
2 changes: 1 addition & 1 deletion lib/lanttern_web/live/strand_live/activity.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<.badge :for={subject <- @activity.subjects} theme="dark"><%= subject.name %></.badge>
</div>
</.cover>
<div class="sticky top-0 border-b border-ltrn-lighter bg-white">
<div class="sticky top-0 z-30 border-b border-ltrn-lighter bg-white">
<.nav_tabs class="container mx-auto lg:max-w-5xl" id="activity-nav-tabs">
<:tab
patch={~p"/strands/activity/#{@activity}?#{%{tab: "details"}}"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ defmodule LantternWeb.StrandLive.ActivityTabs.AssessmentComponent do
~H"""
<div class="p-10">
<div class="container mx-auto lg:max-w-5xl">
<div class="flex items-end justify-between">
<div class="flex items-end justify-between gap-6">
<%= if @classes do %>
<p class="font-display font-bold text-2xl">
Assessing
<button
type="button"
class="underline hover:text-ltrn-subtle"
class="inline text-left underline hover:text-ltrn-subtle"
phx-click={JS.exec("data-show", to: "#classes-filter-overlay")}
>
<%= @classes
Expand All @@ -37,22 +37,19 @@ defmodule LantternWeb.StrandLive.ActivityTabs.AssessmentComponent do
>
Select a class
</button>
to view assessment points
to assess students
</p>
<% end %>
<div class="shrink-0 flex items-center gap-6 font-display text-base underline">
<div class="shrink-0 flex items-center gap-6 font-display text-sm">
<button
:if={@assessment_points_count > 1}
type="button"
phx-click={JS.exec("data-show", to: "#activity-assessment-points-order-overlay")}
class="flex gap-2 hover:text-ltrn-primary"
class="flex gap-2"
>
Reorder <.icon name="hero-arrows-up-down" class="w-6 h-6 text-ltrn-primary" />
</button>
<.link
patch={~p"/strands/activity/#{@activity}/assessment_point/new"}
class="flex gap-2 hover:text-ltrn-primary"
>
<.link patch={~p"/strands/activity/#{@activity}/assessment_point/new"} class="flex gap-2">
Create assessment point
<.icon name="hero-plus-circle" class="w-6 h-6 text-ltrn-primary" />
</.link>
Expand Down Expand Up @@ -90,8 +87,12 @@ defmodule LantternWeb.StrandLive.ActivityTabs.AssessmentComponent do
phx-hook="Slider"
>
<div class="sticky top-0 z-20 flex items-stretch gap-4 pr-6 mb-2 bg-white">
<div class="sticky left-0 z-20 shrink-0 w-60 bg-white"></div>
<div id="activity-assessment-points" phx-update="stream" class="shrink-0 flex gap-4">
<div class="sticky left-0 shrink-0 w-60 bg-white"></div>
<div
id="activity-assessment-points"
phx-update="stream"
class="shrink-0 flex gap-4 bg-white"
>
<.assessment_point
:for={{dom_id, {ap, i}} <- @streams.assessment_points}
assessment_point={ap}
Expand Down Expand Up @@ -259,7 +260,7 @@ defmodule LantternWeb.StrandLive.ActivityTabs.AssessmentComponent do

def assessment_point(assigns) do
~H"""
<div class="shrink-0 w-40 pt-6 pb-2 bg-white" id={@id}>
<div class="shrink-0 w-40 pt-6 pb-2" id={@id}>
<.link
patch={~p"/strands/activity/#{@activity_id}/assessment_point/#{@assessment_point}"}
class="text-xs hover:underline line-clamp-2"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
defmodule LantternWeb.StrandLive.ActivityTabs.DetailsComponent do
use LantternWeb, :live_component

alias Lanttern.Curricula

@impl true
def render(assigns) do
~H"""
<div class="container py-10 mx-auto lg:max-w-5xl">
<.markdown text={@activity.description} />
<h3 class="mt-16 font-display font-black text-3xl">Curriculum</h3>
<div :for={curriculum_item <- @activity.curriculum_items} class="mt-6">
<div :for={curriculum_item <- @curriculum_items} class="mt-6">
<.badge theme="dark"><%= curriculum_item.curriculum_component.name %></.badge>
<p class="mt-4"><%= curriculum_item.name %></p>
</div>
</div>
"""
end

@impl true
def update(%{activity: activity} = assigns, socket) do
{:ok,
socket
|> assign(assigns)
|> assign(
:curriculum_items,
Curricula.list_activity_curriculum_items(activity.id, preloads: :curriculum_component)
)}
end
end
32 changes: 32 additions & 0 deletions test/lanttern/curricula_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -578,4 +578,36 @@ defmodule Lanttern.CurriculaTest do
Curricula.list_strand_curriculum_items(strand.id)
end
end

describe "activity curriculum items" do
import Lanttern.AssessmentsFixtures
import Lanttern.CurriculaFixtures
import Lanttern.LearningContextFixtures

test "list_activity_curriculum_items/2 returns all items linked to the given activity" do
curriculum_item_a = curriculum_item_fixture(%{name: "AAA"})
curriculum_item_b = curriculum_item_fixture(%{name: "BBB"})

activity = activity_fixture()

activity_assessment_point_fixture(activity.id, %{curriculum_item_id: curriculum_item_a.id})
activity_assessment_point_fixture(activity.id, %{curriculum_item_id: curriculum_item_b.id})

# extra curriculum items for testing
curriculum_item_fixture()
other_curriculum_item = curriculum_item_fixture()
other_activity = activity_fixture()

activity_assessment_point_fixture(
other_activity.id,
%{curriculum_items: [%{curriculum_item_id: other_curriculum_item.id}]}
)

assert [expected_ci_a, expected_ci_b] =
Curricula.list_activity_curriculum_items(activity.id)

assert expected_ci_a.id == curriculum_item_a.id
assert expected_ci_b.id == curriculum_item_b.id
end
end
end
2 changes: 1 addition & 1 deletion test/lanttern_web/live/strand_live/activity_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ defmodule LantternWeb.StrandLive.ActivityTest do
assert_patch(view)

assert view |> has_element?("button", "Select a class")
assert view |> has_element?("p", "to view assessment points")
assert view |> has_element?("p", "to assess students")

# notes tab

Expand Down

0 comments on commit 7df327b

Please sign in to comment.