diff --git a/assets/css/app.css b/assets/css/app.css
index 0635f7e4138..8f00beb6267 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -140,3 +140,7 @@ https://tailwindcss.com/docs/utility-first
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
+
+.search-result em {
+ @apply not-italic bg-yellow-50;
+}
diff --git a/assets/src/hooks/scroller.ts b/assets/src/hooks/scroller.ts
index 1ad57576807..36944cb4642 100644
--- a/assets/src/hooks/scroller.ts
+++ b/assets/src/hooks/scroller.ts
@@ -6,7 +6,7 @@ export const Scroller = {
// It is triggered from the backend as follows:
//
// def handle_event(..., socket) do
- // {:no_reply, push_event(socket, "scroll-y-to-target", %{id: "element-id", offset: 50, scroll: true, scroll_delay: 500})
+ // {:no_reply, push_event(socket, "scroll-y-to-target", %{id: "element-id", offset: 50, scroll: true, scroll_delay: 500})}
// end
//
// Expects the id of the element to scroll to, an optional offset
diff --git a/lib/oli/analytics/by_activity.ex b/lib/oli/analytics/by_activity.ex
index 711e3af5cbc..28d0557c82c 100644
--- a/lib/oli/analytics/by_activity.ex
+++ b/lib/oli/analytics/by_activity.ex
@@ -1,7 +1,8 @@
defmodule Oli.Analytics.ByActivity do
import Ecto.Query, warn: false
- alias Oli.Delivery.Sections.SectionResource
+ alias Oli.Publishing.DeliveryResolver
alias Oli.Repo
+ alias Oli.Resources.ResourceType
alias Oli.Analytics.Common
alias Oli.Publishing
@@ -11,17 +12,15 @@ defmodule Oli.Analytics.ByActivity do
def query_against_project_slug(project_slug, filtered_sections) do
project_slug
|> get_base_query(filtered_sections)
- |> get_query_with_join_filter(filtered_sections)
|> Repo.all()
end
defp get_base_query(project_slug, filtered_sections) do
subquery =
if filtered_sections != [] do
- Publishing.query_unpublished_revisions_by_type_and_section(
- project_slug,
- "activity",
- filtered_sections
+ DeliveryResolver.revisions_filter_by_section_ids(
+ filtered_sections,
+ ResourceType.id_for_activity()
)
else
Publishing.query_unpublished_revisions_by_type(
@@ -40,14 +39,7 @@ defmodule Oli.Analytics.ByActivity do
number_of_attempts: analytics.number_of_attempts,
relative_difficulty: analytics.relative_difficulty
},
- preload: [:resource_type]
- end
-
- defp get_query_with_join_filter(query, filter_list) do
- from activity in query,
- join: resource in assoc(activity, :resource),
- left_join: section_resource in SectionResource,
- on: resource.id == section_resource.resource_id,
- where: section_resource.section_id in ^filter_list
+ preload: [:resource_type],
+ distinct: [activity]
end
end
diff --git a/lib/oli/analytics/by_objective.ex b/lib/oli/analytics/by_objective.ex
index 369b80d4da5..256ac807445 100644
--- a/lib/oli/analytics/by_objective.ex
+++ b/lib/oli/analytics/by_objective.ex
@@ -1,8 +1,8 @@
defmodule Oli.Analytics.ByObjective do
import Ecto.Query, warn: false
+ alias Oli.Publishing.DeliveryResolver
alias Oli.Delivery.Snapshots.Snapshot
- alias Oli.Delivery.Sections.SectionResource
-
+ alias Oli.Resources.ResourceType
alias Oli.Repo
alias Oli.Analytics.Common
alias Oli.Publishing
@@ -14,17 +14,15 @@ defmodule Oli.Analytics.ByObjective do
def query_against_project_slug(project_slug, filtered_sections) do
project_slug
|> get_base_query(get_activity_objectives(project_slug), filtered_sections)
- |> get_query_with_join_filter(filtered_sections)
|> Repo.all()
end
defp get_base_query(project_slug, activity_objectives, filtered_sections) do
subquery =
if filtered_sections != [] do
- Publishing.query_unpublished_revisions_by_type_and_section(
- project_slug,
- "objective",
- filtered_sections
+ DeliveryResolver.revisions_filter_by_section_ids(
+ filtered_sections,
+ ResourceType.id_for_objective()
)
else
Publishing.query_unpublished_revisions_by_type(
@@ -50,14 +48,6 @@ defmodule Oli.Analytics.ByObjective do
)
end
- defp get_query_with_join_filter(query, filter) do
- from objective in query,
- join: resource in assoc(objective, :resource),
- left_join: section_resource in SectionResource,
- on: resource.id == section_resource.resource_id,
- where: section_resource.section_id in ^filter
- end
-
defp get_activity_objectives(project_slug) do
from(project in Project,
where: project.slug == ^project_slug,
diff --git a/lib/oli/analytics/by_page.ex b/lib/oli/analytics/by_page.ex
index 1912ce0e97a..18ffcace7cf 100644
--- a/lib/oli/analytics/by_page.ex
+++ b/lib/oli/analytics/by_page.ex
@@ -1,10 +1,11 @@
defmodule Oli.Analytics.ByPage do
import Ecto.Query, warn: false
- alias Oli.Delivery.Sections.SectionResource
+ alias Oli.Publishing.DeliveryResolver
alias Oli.Delivery.Snapshots.Snapshot
alias Oli.Repo
alias Oli.Analytics.Common
alias Oli.Publishing
+ alias Oli.Resources.ResourceType
alias Oli.Authoring.Course.Project
def query_against_project_slug(project_slug, []),
@@ -15,25 +16,15 @@ defmodule Oli.Analytics.ByPage do
def query_against_project_slug(project_slug, filtered_sections) do
project_slug
|> get_base_query(get_activity_pages(project_slug), filtered_sections)
- |> get_query_with_join_filter(filtered_sections)
|> Repo.all()
end
- defp get_query_with_join_filter(query, filter_list) do
- from page in query,
- join: resource in assoc(page, :resource),
- left_join: section_resource in SectionResource,
- on: resource.id == section_resource.resource_id,
- where: section_resource.section_id in ^filter_list
- end
-
defp get_base_query(project_slug, activity_pages, filtered_sections) do
subquery =
if filtered_sections != [] do
- Publishing.query_unpublished_revisions_by_type_and_section(
- project_slug,
- "page",
- filtered_sections
+ DeliveryResolver.revisions_filter_by_section_ids(
+ filtered_sections,
+ ResourceType.id_for_page()
)
else
Publishing.query_unpublished_revisions_by_type(
@@ -44,10 +35,9 @@ defmodule Oli.Analytics.ByPage do
subquery_activity =
if filtered_sections != [] do
- Publishing.query_unpublished_revisions_by_type_and_section(
- project_slug,
- "activity",
- filtered_sections
+ DeliveryResolver.revisions_filter_by_section_ids(
+ filtered_sections,
+ ResourceType.id_for_page()
)
else
Publishing.query_unpublished_revisions_by_type(
@@ -72,7 +62,8 @@ defmodule Oli.Analytics.ByPage do
number_of_attempts: analytics.number_of_attempts,
relative_difficulty: analytics.relative_difficulty
},
- preload: [:resource_type]
+ preload: [:resource_type],
+ distinct: [activity]
)
end
diff --git a/lib/oli/publishing/delivery_resolver.ex b/lib/oli/publishing/delivery_resolver.ex
index 1d91c075414..c2b575626c9 100644
--- a/lib/oli/publishing/delivery_resolver.ex
+++ b/lib/oli/publishing/delivery_resolver.ex
@@ -263,6 +263,24 @@ defmodule Oli.Publishing.DeliveryResolver do
|> emit([:oli, :resolvers, :delivery], :duration)
end
+ def revisions_filter_by_section_ids(section_ids, resource_type_id) do
+ from(sr in SectionResource,
+ join: s in Section,
+ on: s.id == sr.section_id,
+ where: s.id in ^section_ids,
+ join: spp in SectionsProjectsPublications,
+ on: s.id == spp.section_id,
+ where: sr.project_id == spp.project_id,
+ join: pr in PublishedResource,
+ on: pr.publication_id == spp.publication_id,
+ where: pr.resource_id == sr.resource_id,
+ join: rev in Revision,
+ on: rev.id == pr.revision_id,
+ where: rev.resource_type_id == ^resource_type_id and rev.deleted == false,
+ select: rev
+ )
+ end
+
@impl Resolver
def revisions_of_type(section_slug, resource_type_id) do
fn ->
diff --git a/lib/oli/resources/collaboration.ex b/lib/oli/resources/collaboration.ex
index 8613c2a80c1..ee570f32f62 100644
--- a/lib/oli/resources/collaboration.ex
+++ b/lib/oli/resources/collaboration.ex
@@ -1118,10 +1118,15 @@ defmodule Oli.Resources.Collaboration do
point_block_id \\ nil
) do
filter_by_point_block_id =
- if is_nil(point_block_id) do
- dynamic([p], is_nil(p.annotated_block_id))
- else
- dynamic([p], p.annotated_block_id == ^point_block_id)
+ case point_block_id do
+ nil ->
+ true
+
+ :page ->
+ dynamic([p], is_nil(p.annotated_block_id))
+
+ point_block_id ->
+ dynamic([p], p.annotated_block_id == ^point_block_id)
end
Repo.all(
@@ -1152,6 +1157,126 @@ defmodule Oli.Resources.Collaboration do
|> summarize_reactions(user_id)
end
+ @doc """
+ Returns the list of posts that a user can see which match a given search term.
+
+ ## Examples
+
+ iex> search_posts_for_user_in_point_block(1, 1, 1, :private, "1", "search term"))
+ [%Post{status: :archived}, ...]
+
+ iex> search_posts_for_user_in_point_block(2, 2, 2, :private, "2", "search term")
+ []
+ """
+ def search_posts_for_user_in_point_block(
+ section_id,
+ resource_id,
+ user_id,
+ visibility,
+ point_block_id,
+ search_term
+ ) do
+ filter_by_point_block_id =
+ case point_block_id do
+ nil ->
+ true
+
+ :page ->
+ dynamic([p], is_nil(p.annotated_block_id))
+
+ point_block_id ->
+ dynamic([p], p.annotated_block_id == ^point_block_id)
+ end
+
+ Repo.all(
+ from(
+ post in Post,
+ left_join: replies in subquery(replies_subquery()),
+ on: replies.thread_root_id == post.id,
+ left_join: read_replies in subquery(read_replies_subquery(user_id)),
+ on: read_replies.thread_root_id == post.id,
+ left_join: parent_post in assoc(post, :parent_post),
+ left_join: reactions in assoc(post, :reactions),
+ left_join: user in assoc(post, :user),
+ where:
+ post.section_id == ^section_id and post.resource_id == ^resource_id and
+ (post.status in [:approved, :archived] or
+ (post.status == :submitted and post.user_id == ^user_id)),
+ where: ^filter_by_point_block_id,
+ where:
+ fragment(
+ "to_tsvector('english', ?) @@ websearch_to_tsquery('english', ?)",
+ post.content,
+ ^search_term
+ ),
+ where: post.visibility == ^visibility,
+ order_by: [desc: :inserted_at],
+ preload: [
+ user: user,
+ reactions: reactions,
+ parent_post: parent_post
+ ],
+ select: %{
+ post
+ | replies_count: coalesce(replies.count, 0),
+ read_replies_count: coalesce(read_replies.count, 0),
+ headline:
+ fragment(
+ """
+ ts_headline(
+ 'english',
+ ?,
+ websearch_to_tsquery(?),
+ 'StartSel=,StopSel=,MinWords=25,MaxWords=75'
+ )
+ """,
+ post.content,
+ ^search_term
+ )
+ }
+ )
+ )
+ |> summarize_reactions(user_id)
+ |> group_by_parent_post()
+ end
+
+ defp group_by_parent_post(posts) do
+ by_parent_id = Enum.group_by(posts, &Map.get(&1, :parent_post_id))
+
+ # we want to preserve the order of the posts returned by the query
+ # so we need to reduce over the list of posts and place each post in the correct
+ # parent post's replies list
+ {results, _} =
+ posts
+ |> Enum.reduce({[], by_parent_id}, fn post, {acc, by_parent_id} ->
+ parent_post_id = post.parent_post_id
+
+ case parent_post_id do
+ nil ->
+ # this is a top-level post
+ {[post | acc], by_parent_id}
+
+ _ ->
+ # this is a reply post, so place parent post with it's replies we already groups
+ # in the list if it's not there yet
+ case by_parent_id[parent_post_id] do
+ nil ->
+ # parent post is already in the list, so skip it
+ {acc, by_parent_id}
+
+ replies ->
+ # parent post is not in the list yet, so add it and drop it from the by_parent_id map
+ # to track which parent posts we already processed
+ {[Map.put(post.parent_post, :replies, replies) | acc],
+ Map.delete(by_parent_id, parent_post_id)}
+ end
+ end
+ end)
+
+ results
+ |> Enum.reverse()
+ end
+
defp summarize_reactions(posts, current_user_id) do
Enum.map(posts, fn post ->
%{
diff --git a/lib/oli/resources/collaboration/post.ex b/lib/oli/resources/collaboration/post.ex
index d187c099fa4..0b505de607e 100644
--- a/lib/oli/resources/collaboration/post.ex
+++ b/lib/oli/resources/collaboration/post.ex
@@ -39,6 +39,8 @@ defmodule Oli.Resources.Collaboration.Post do
has_many :reactions, Oli.Resources.Collaboration.UserReactionPost
field :reaction_summaries, :map, virtual: true
+ field :headline, :string, virtual: true
+ field :replies, :any, virtual: true
timestamps(type: :utc_datetime)
end
diff --git a/lib/oli_web/components/delivery/instructor_dashboard.ex b/lib/oli_web/components/delivery/instructor_dashboard.ex
index b08ec108299..9e75fb3dab9 100644
--- a/lib/oli_web/components/delivery/instructor_dashboard.ex
+++ b/lib/oli_web/components/delivery/instructor_dashboard.ex
@@ -34,7 +34,9 @@ defmodule OliWeb.Components.Delivery.InstructorDashboard do
<%= render_slot(@inner_block) %>
- <%= Phoenix.View.render(OliWeb.LayoutView, "_delivery_footer.html", assigns) %>
+
"""
@@ -273,7 +275,9 @@ defmodule OliWeb.Components.Delivery.InstructorDashboard do
def footer(assigns) do
~H"""
- <%= Phoenix.View.render(OliWeb.LayoutView, "_delivery_footer.html", assigns) %>
+
"""
end
end
diff --git a/lib/oli_web/components/footer.ex b/lib/oli_web/components/footer.ex
new file mode 100644
index 00000000000..6932eea2ed8
--- /dev/null
+++ b/lib/oli_web/components/footer.ex
@@ -0,0 +1,118 @@
+defmodule OliWeb.Components.Footer do
+ use Phoenix.Component
+ use OliWeb, :verified_routes
+
+ def delivery_footer(assigns) do
+ ~H"""
+
+ """
+ end
+
+ def global_footer(assigns) do
+ ~H"""
+
+ """
+ end
+
+ defp footer_part_1(assigns) do
+ assigns =
+ assign(assigns,
+ footer_text: footer_text(),
+ footer_link_1_location: footer_link_1_location(),
+ footer_link_1_text: footer_link_1_text()
+ )
+
+ ~H"""
+
+ """
+ end
+
+ defp footer_part_2(assigns) do
+ assigns =
+ assign(assigns,
+ footer_link_2_location: footer_link_2_location(),
+ footer_link_2_text: footer_link_2_text()
+ )
+
+ ~H"""
+
+ """
+ end
+
+ def version(assigns) do
+ assigns = assign(assigns, version: version(), sha: sha(), timestamp: timestamp())
+
+ ~H"""
+
+ Version <%= @version %> (<%= @sha %>) <%= @timestamp %>
+
+ """
+ end
+
+ defp cookie_preferences(assigns) do
+ assigns = assign(assigns, privacy_policies_url: privacy_policies_url())
+
+ ~H"""
+
+ """
+ end
+
+ defp retrieve_cookies(assigns) do
+ assigns = assign(assigns, privacy_policies_url: privacy_policies_url())
+
+ ~H"""
+
+ """
+ end
+
+ defp footer(), do: Application.fetch_env!(:oli, :footer)
+ defp footer_text(), do: footer()[:text]
+ defp footer_link_1_location(), do: footer()[:link_1_location]
+ defp footer_link_1_text(), do: footer()[:link_1_text]
+ defp footer_link_2_location(), do: footer()[:link_2_location]
+ defp footer_link_2_text(), do: footer()[:link_2_text]
+
+ defp privacy_policies_url(), do: Application.fetch_env!(:oli, :privacy_policies)[:url]
+
+ defp timestamp(),
+ do: Application.fetch_env!(:oli, :build).date |> Timex.format!("%m/%d/%Y", :strftime)
+
+ defp version(), do: Application.fetch_env!(:oli, :build).version
+
+ defp sha(), do: Application.fetch_env!(:oli, :build).sha |> String.upcase()
+end
diff --git a/lib/oli_web/components/layouts/page.html.heex b/lib/oli_web/components/layouts/page.html.heex
index 8c3e0095756..3784d3a9d41 100644
--- a/lib/oli_web/components/layouts/page.html.heex
+++ b/lib/oli_web/components/layouts/page.html.heex
@@ -96,9 +96,11 @@
resource_slug: @resource_slug,
numbered_revisions: assigns[:numbered_revisions]
) %>
+
-
- <%= render(OliWeb.LayoutView, "_delivery_footer.html", assigns) %>
diff --git a/lib/oli_web/controllers/delivery_controller.ex b/lib/oli_web/controllers/delivery_controller.ex
index 0279506bd15..77c86184c12 100644
--- a/lib/oli_web/controllers/delivery_controller.ex
+++ b/lib/oli_web/controllers/delivery_controller.ex
@@ -239,22 +239,29 @@ defmodule OliWeb.DeliveryController do
|> render_create_and_link_form()
end
+ @spec process_create_and_link_account_user(Plug.Conn.t(), map()) :: Plug.Conn.t()
def process_create_and_link_account_user(conn, %{"user" => user_params}) do
+ %{current_user: current_user} = conn.assigns
+
conn
|> use_pow_config(:author)
|> Pow.Plug.create_user(user_params)
|> case do
- {:ok, user, conn} ->
+ {:ok, _user, conn} ->
conn
- |> PowPersistentSession.Plug.create(user)
|> put_flash(
:info,
Pow.Phoenix.Controller.messages(conn, Pow.Phoenix.Messages).user_has_been_created(conn)
)
- |> redirect(
- to:
- Pow.Phoenix.Controller.routes(conn, Pow.Phoenix.Routes).after_registration_path(conn)
- )
+
+ Pow.Phoenix.Controller.routes(conn, Pow.Phoenix.Routes).after_registration_path(conn)
+ conn = Pow.Plug.Session.do_delete(conn, get_pow_config(:author))
+
+ if current_user.independent_learner do
+ redirect(conn, to: Routes.live_path(conn, OliWeb.Delivery.OpenAndFreeIndex))
+ else
+ redirect(conn, to: Routes.delivery_path(conn, :index))
+ end
{:error, changeset, conn} ->
conn
diff --git a/lib/oli_web/live/delivery/open_and_free_index.ex b/lib/oli_web/live/delivery/open_and_free_index.ex
index 47c3c50b90b..7f61af42778 100644
--- a/lib/oli_web/live/delivery/open_and_free_index.ex
+++ b/lib/oli_web/live/delivery/open_and_free_index.ex
@@ -151,7 +151,9 @@ defmodule OliWeb.Delivery.OpenAndFreeIndex do
- <%= render(OliWeb.LayoutView, "_delivery_footer.html", assigns) %>
+
"""
end
diff --git a/lib/oli_web/live/delivery/student/lesson/annotations.ex b/lib/oli_web/live/delivery/student/lesson/annotations.ex
index 15603a6a371..cd8a6433417 100644
--- a/lib/oli_web/live/delivery/student/lesson/annotations.ex
+++ b/lib/oli_web/live/delivery/student/lesson/annotations.ex
@@ -7,8 +7,10 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
attr :create_new_annotation, :boolean, default: false
attr :annotations, :any, required: true
attr :current_user, Oli.Accounts.User, required: true
+ attr :selected_point, :any, required: true
attr :active_tab, :atom, default: :my_notes
- attr :post_replies, :list, default: nil
+ attr :search_results, :any, default: nil
+ attr :search_term, :string, default: ""
def panel(assigns) do
~H"""
@@ -27,36 +29,131 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
<.users_icon class="mr-2" /> Class Notes
- <.search_box class="mt-2" />
+ <.search_box class="mt-2" search_term={@search_term} />
-
- <.add_new_annotation_input
- class="my-2"
- active={@create_new_annotation}
- disable_anonymous_option={@active_tab == :my_notes || is_guest(@current_user)}
- save_label={if(@active_tab == :my_notes, do: "Save", else: "Post")}
- placeholder={
- if(@active_tab == :my_notes, do: "Add a new note...", else: "Post a new note...")
- }
- />
+ <%= case @search_results do %>
+ <% nil -> %>
+ <.annotations
+ annotations={@annotations}
+ current_user={@current_user}
+ create_new_annotation={@create_new_annotation}
+ selected_point={@selected_point}
+ />
+ <% _ -> %>
+ <.search_results
+ search_results={@search_results}
+ search_term={@search_term}
+ current_user={@current_user}
+ active_tab={@active_tab}
+ />
+ <% end %>
+
+
+ """
+ end
+
+ attr :create_new_annotation, :boolean, default: false
+ attr :annotations, :any, required: true
+ attr :current_user, Oli.Accounts.User, required: true
+ attr :selected_point, :any, required: true
+ attr :active_tab, :atom, default: :my_notes
+
+ defp annotations(assigns) do
+ ~H"""
+
+ <.add_new_annotation_input
+ :if={@selected_point}
+ class="my-2"
+ active={@create_new_annotation}
+ disable_anonymous_option={@active_tab == :my_notes || is_guest(@current_user)}
+ save_label={if(@active_tab == :my_notes, do: "Save", else: "Post")}
+ placeholder={
+ if(@active_tab == :my_notes, do: "Add a new note...", else: "Post a new note...")
+ }
+ />
+
+ <%= case @annotations do %>
+ <% nil -> %>
+
+ <% [] -> %>
+
<%= empty_label(@active_tab) %>
+ <% annotations -> %>
+ <%= for annotation <- annotations do %>
+ <.post
+ post={annotation}
+ current_user={@current_user}
+ disable_anonymous_option={@active_tab == :my_notes || is_guest(@current_user)}
+ />
+ <% end %>
+ <% end %>
+
+ """
+ end
- <%= case @annotations do %>
- <% nil -> %>
-
- <% [] -> %>
- <%= empty_label(@active_tab) %>
- <% annotations -> %>
- <%= for annotation <- annotations do %>
- <.post
- post={annotation}
- current_user={@current_user}
- post_replies={@post_replies}
- disable_anonymous_option={@active_tab == :my_notes || is_guest(@current_user)}
- />
- <% end %>
+ attr :current_user, Oli.Accounts.User, required: true
+ attr :active_tab, :atom, default: :my_notes
+ attr :search_results, :any, default: nil
+ attr :search_term, :string, default: ""
+
+ defp search_results(assigns) do
+ ~H"""
+
+ <%= case @search_results do %>
+ <% :loading -> %>
+
+ <% [] -> %>
+
No results found
+ <% annotations -> %>
+ <%= for annotation <- annotations do %>
+
+ <.search_result post={annotation} current_user={@current_user} />
+
<% end %>
+ <% end %>
+
+ """
+ end
+
+ attr :post, Oli.Resources.Collaboration.Post, required: true
+ attr :current_user, Oli.Accounts.User, required: true
+ attr :is_reply, :boolean, default: false
+
+ defp search_result(assigns) do
+ ~H"""
+
+
+
+ <%= post_creator(@post, @current_user) %>
+
+
+ <%= Timex.from_now(@post.inserted_at) %>
+
+ <%= case @post.headline["message"] do %>
+ <% nil -> %>
+ <%= @post.content.message %>
+ <% message -> %>
+ <%= raw(message) %>
+ <% end %>
+
+ <%= case @post.replies do %>
+ <% nil -> %>
+ <% replies -> %>
+
+ <%= for reply <- replies do %>
+ <.search_result post={reply} current_user={@current_user} is_reply={true} />
+ <% end %>
+
+ <% end %>
"""
end
@@ -216,20 +313,33 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
"""
end
+ attr :search_term, :string, default: ""
attr :rest, :global, include: ~w(class)
defp search_box(assigns) do
~H"""
-
+
"""
end
@@ -293,7 +403,6 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
attr :post, Oli.Resources.Collaboration.Post, required: true
attr :current_user, Oli.Accounts.User, required: true
- attr :post_replies, :any, required: true
attr :disable_anonymous_option, :boolean, default: false
defp post(assigns) do
@@ -317,7 +426,6 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
/>
<.post_replies
post={@post}
- replies={@post_replies}
current_user={@current_user}
disable_anonymous_option={@disable_anonymous_option}
/>
@@ -371,6 +479,7 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
phx-click={@on_toggle_reaction}
phx-value-reaction={:like}
phx-value-post-id={assigns.post.id}
+ phx-value-parent-post-id={assigns.post.parent_post_id}
>
<%= case Map.get(@post.reaction_summaries, :like) do %>
<% nil -> %>
@@ -402,32 +511,29 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
attr :post, Oli.Resources.Collaboration.Post, required: true
attr :current_user, Oli.Accounts.User, required: true
- attr :replies, :any, required: true
attr :disable_anonymous_option, :boolean, default: false
defp post_replies(assigns) do
~H"""
- <%= if !is_nil(@replies) && elem(@replies, 0) == @post.id do %>
- <%= case @replies do %>
- <% {_, :loading} -> %>
-
- <% {_, []} -> %>
- <.add_new_reply_input
- parent_post_id={@post.id}
- disable_anonymous_option={@disable_anonymous_option}
- />
- <% {_, replies} -> %>
-
- <%= for reply <- replies do %>
- <.reply post={reply} current_user={@current_user} />
- <% end %>
-
- <.add_new_reply_input
- parent_post_id={@post.id}
- disable_anonymous_option={@disable_anonymous_option}
- />
- <% _ -> %>
- <% end %>
+ <%= case @post.replies do %>
+ <% nil -> %>
+ <% :loading -> %>
+
+ <% [] -> %>
+ <.add_new_reply_input
+ parent_post_id={@post.id}
+ disable_anonymous_option={@disable_anonymous_option}
+ />
+ <% replies -> %>
+
+ <%= for reply <- replies do %>
+ <.reply post={reply} current_user={@current_user} />
+ <% end %>
+
+ <.add_new_reply_input
+ parent_post_id={@post.id}
+ disable_anonymous_option={@disable_anonymous_option}
+ />
<% end %>
"""
end
@@ -494,21 +600,32 @@ defmodule OliWeb.Delivery.Student.Lesson.Annotations do
<%= @post.content.message %>
- <.post_actions post={@post} on_toggle_reaction="toggle_reply_reaction" />
+ <.post_actions post={@post} on_toggle_reaction="toggle_reaction" />
"""
end
- attr :point_marker, :map, required: true
+ attr :point_marker, :any, required: true
attr :selected, :boolean, default: false
attr :count, :integer, default: nil
+ def annotation_bubble(%{point_marker: :page} = assigns) do
+ ~H"""
+
+ """
+ end
+
def annotation_bubble(assigns) do
~H"""