Skip to content

Commit

Permalink
feat: create rubric from assessment point details view
Browse files Browse the repository at this point in the history
- added `LantternWeb.RubricsLive.FormComponent` to assessment point details view and added `handle_info/2` to handle rubric creation

- added support to hide differentiation and scale fields, add wrapper class, conditional patch, and show submit button to `LantternWeb.RubricsLive.FormComponent`

- added support to handle new rubric with selected scale in `LantternWeb.RubricsLive.FormComponent`
  • Loading branch information
endoooo committed Nov 6, 2023
1 parent 23f9cbc commit 4d52aa6
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 35 deletions.
20 changes: 20 additions & 0 deletions lib/lanttern_web/live/assessment_point_live/details.ex
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ defmodule LantternWeb.AssessmentPointLive.Details do
socket
|> assign(:rubric, nil)
|> assign(:has_rubric_change, has_rubric_change)
|> assign(:is_creating_rubric, false)

{:noreply, socket}
end
Expand All @@ -382,6 +383,7 @@ defmodule LantternWeb.AssessmentPointLive.Details do
socket
|> assign(:rubric, Rubrics.get_full_rubric!(rubric_id))
|> assign(:has_rubric_change, has_rubric_change)
|> assign(:is_creating_rubric, false)

{:noreply, socket}
end
Expand All @@ -398,6 +400,7 @@ defmodule LantternWeb.AssessmentPointLive.Details do
socket =
socket
|> assign(:has_rubric_change, false)
|> assign(:is_creating_rubric, false)
|> update(:assessment_point, &Map.put(&1, :rubric_id, rubric_id))

{:noreply, socket}
Expand Down Expand Up @@ -512,6 +515,23 @@ defmodule LantternWeb.AssessmentPointLive.Details do
{:noreply, socket}
end

def handle_info({LantternWeb.RubricsLive.FormComponent, {:created, rubric}}, socket) do
assessment_point = socket.assigns.assessment_point

assessment_point
|> Assessments.update_assessment_point(%{
rubric_id: rubric.id
})
|> case do
{:ok, _assessment_point} ->
{:noreply,
push_navigate(socket, to: ~p"/assessment_points/#{assessment_point.id}/rubrics")}

{:error, _changeset} ->
{:noreply, put_flash(socket, :error, "Something went wrong")}
end
end

def handle_info({FeedbackCommentFormComponent, {:created, comment}}, socket) do
socket =
socket
Expand Down
24 changes: 22 additions & 2 deletions lib/lanttern_web/live/assessment_point_live/details.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,15 @@
phx-change="assessment_point_rubric_selected"
class="flex-1"
/>
<.button :if={@has_rubric_change} type="submit" class="shrink-0">Save</.button>
<.button
type="submit"
disabled={!@has_rubric_change || @is_creating_rubric}
class={["shrink-0", if(!@has_rubric_change || @is_creating_rubric, do: "hidden")]}
>
Save
</.button>
</form>
<%= if @rubric do %>
<%= if @rubric && !@is_creating_rubric do %>
<h4 class="mt-10 -mb-2 font-display font-black text-xl text-ltrn-subtle">Descriptors</h4>
<div :for={descriptor <- @rubric.descriptors} class="mt-8">
<%= if descriptor.scale_type == "ordinal" do %>
Expand All @@ -137,6 +143,20 @@
<.markdown class="mt-2" text={descriptor.descriptor} />
</div>
<% end %>
<.live_component
:if={@is_creating_rubric}
module={LantternWeb.RubricsLive.FormComponent}
id={:new}
action={:new}
rubric={
%Lanttern.Rubrics.Rubric{
scale_id: @assessment_point.scale_id
}
}
hide_diff_and_scale
show_submit
class="mt-6"
/>
</.slide_over>
<.slide_over
:if={@live_action == :feedback}
Expand Down
8 changes: 6 additions & 2 deletions lib/lanttern_web/live/rubrics_live/explorer.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
:if={@live_action in [:new, :edit]}
id="rubric-form-overlay"
show={true}
prevent_close_on_click_away
on_cancel={JS.patch(~p"/rubrics")}
>
<:title><%= @overlay_title %></:title>
<.live_component
Expand All @@ -85,7 +85,11 @@
</.button>
</:actions_left>
<:actions>
<.button type="button" theme="ghost" phx-click={JS.patch(~p"/rubrics")}>
<.button
type="button"
theme="ghost"
phx-click={JS.exec("data-cancel", to: "#rubric-form-overlay")}
>
Cancel
</.button>
<.button type="submit" form="rubric-form" phx-disable-with="Saving...">
Expand Down
104 changes: 73 additions & 31 deletions lib/lanttern_web/live/rubrics_live/form_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ defmodule LantternWeb.RubricsLive.FormComponent do
@impl true
def render(assigns) do
~H"""
<div>
<div class={@class}>
<.form for={@form} id="rubric-form" phx-target={@myself} phx-change="validate" phx-submit="save">
<.input field={@form[:criteria]} type="text" label="Criteria" phx-debounce="1500" />
<.input
field={@form[:is_differentiation]}
type="toggle"
label="Is differentiation"
class="mt-6"
class={["mt-6", if(@hide_diff_and_scale, do: "hidden")]}
/>
<.input
field={@form[:scale_id]}
Expand All @@ -31,9 +31,12 @@ defmodule LantternWeb.RubricsLive.FormComponent do
prompt="Select scale"
phx-target={@myself}
phx-change="scale_selected"
class="mt-6"
class={["mt-6", if(@hide_diff_and_scale, do: "hidden")]}
/>
<.descriptors_fields scale={@scale} field={@form[:descriptors]} myself={@myself} />
<div class={["flex justify-end mt-6", if(!@show_submit, do: "hidden")]}>
<.button type="submit">Save</.button>
</div>
</.form>
</div>
"""
Expand All @@ -52,6 +55,7 @@ defmodule LantternWeb.RubricsLive.FormComponent do
defp descriptors_fields(%{scale: %{type: "ordinal"}} = assigns) do
~H"""
<h5 class="mt-10 font-display font-black text-ltrn-subtle">Descriptors</h5>
<.markdown_supported />
<.inputs_for :let={ef} field={@field}>
<.input type="hidden" field={ef[:scale_id]} />
<.input type="hidden" field={ef[:scale_type]} />
Expand All @@ -71,6 +75,7 @@ defmodule LantternWeb.RubricsLive.FormComponent do
defp descriptors_fields(%{scale: %{type: "numeric"}} = assigns) do
~H"""
<h5 class="mt-10 font-display font-black text-ltrn-subtle">Descriptors</h5>
<.markdown_supported />
<.inputs_for :let={ef} field={@field}>
<div class="flex gap-6">
<div class="flex-1">
Expand Down Expand Up @@ -99,6 +104,20 @@ defmodule LantternWeb.RubricsLive.FormComponent do
"""
end

defp markdown_supported(assigns) do
~H"""
<p class="mt-2 mb-6 text-sm text-ltrn-subtle">
<a
href="https://www.markdownguide.org/basic-syntax/"
target="_blank"
class="hover:text-ltrn-primary"
>
Markdown supported in descriptors <.icon name="hero-information-circle" />
</a>
</p>
"""
end

attr :ordinal_values, :list, required: true
attr :ordinal_value_id, :integer, required: true

Expand Down Expand Up @@ -133,20 +152,38 @@ defmodule LantternWeb.RubricsLive.FormComponent do
socket
|> assign(:scale_options, scale_options)
|> assign(:scale, nil)
|> assign(:hide_diff_and_scale, false)
|> assign(:class, nil)
|> assign(:patch, nil)
|> assign(:show_submit, false)

{:ok, socket}
end

@impl true
def update(%{rubric: rubric} = assigns, socket) do
changeset = Rubrics.change_rubric(rubric)

scale =
case rubric.scale_id do
nil -> nil
scale_id -> Grading.get_scale!(scale_id, preloads: :ordinal_values)
end

changeset =
case {rubric.id, scale} do
{nil, nil} ->
Rubrics.change_rubric(rubric)

{nil, scale} ->
# if scale is selected and rubric is new, generate empty descriptors
Rubrics.change_rubric(
rubric,
%{"descriptors" => generate_new_descriptors(scale)}
)

_ ->
Rubrics.change_rubric(rubric)
end

{:ok,
socket
|> assign(assigns)
Expand Down Expand Up @@ -178,30 +215,7 @@ defmodule LantternWeb.RubricsLive.FormComponent do

def handle_event("scale_selected", %{"rubric" => %{"scale_id" => scale_id}}, socket) do
scale = Grading.get_scale!(scale_id, preloads: :ordinal_values)

descriptors =
case scale.type do
"ordinal" ->
scale.ordinal_values
|> Enum.map(
&%{
scale_id: &1.scale_id,
scale_type: scale.type,
ordinal_value_id: &1.id,
descriptor: "—"
}
)

"numeric" ->
%{
"0" =>
blank_numeric_descriptor(scale)
|> Map.put("score", scale.start),
"1" =>
blank_numeric_descriptor(scale)
|> Map.put("score", scale.stop)
}
end
descriptors = generate_new_descriptors(scale)

changeset =
socket.assigns.rubric
Expand Down Expand Up @@ -275,6 +289,31 @@ defmodule LantternWeb.RubricsLive.FormComponent do
save_rubric(socket, socket.assigns.action, rubric_params)
end

defp generate_new_descriptors(scale) do
case scale.type do
"ordinal" ->
scale.ordinal_values
|> Enum.map(
&%{
scale_id: &1.scale_id,
scale_type: scale.type,
ordinal_value_id: &1.id,
descriptor: "—"
}
)

"numeric" ->
%{
"0" =>
blank_numeric_descriptor(scale)
|> Map.put("score", scale.start),
"1" =>
blank_numeric_descriptor(scale)
|> Map.put("score", scale.stop)
}
end
end

defp blank_numeric_descriptor(scale) do
%{
"scale_id" => scale.id,
Expand All @@ -292,7 +331,7 @@ defmodule LantternWeb.RubricsLive.FormComponent do
{:noreply,
socket
|> put_flash(:info, "Rubric updated successfully")
|> push_patch(to: socket.assigns.patch)}
|> maybe_push_patch(socket.assigns.patch)}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign_form(socket, changeset)}
Expand All @@ -307,13 +346,16 @@ defmodule LantternWeb.RubricsLive.FormComponent do
{:noreply,
socket
|> put_flash(:info, "Rubric created successfully")
|> push_patch(to: socket.assigns.patch)}
|> maybe_push_patch(socket.assigns.patch)}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign_form(socket, changeset)}
end
end

defp maybe_push_patch(socket, nil), do: socket
defp maybe_push_patch(socket, patch_assign), do: push_patch(socket, to: patch_assign)

defp assign_form(socket, %Ecto.Changeset{} = changeset) do
assign(socket, :form, to_form(changeset))
end
Expand Down

0 comments on commit 4d52aa6

Please sign in to comment.