diff --git a/core/assets/tailwind.config.js b/core/assets/tailwind.config.js index b6db63a04..51d45c745 100644 --- a/core/assets/tailwind.config.js +++ b/core/assets/tailwind.config.js @@ -18,11 +18,6 @@ module.exports = { { pattern: /border-./ }, ], theme: { - boxShadow: { - top4px: "inset 0 4px 0 0 rgba(0, 0, 0, 0.15)", - top2px: "inset 0 2px 0 0 rgba(0, 0, 0, 0.15)", - "2xl": "0 5px 20px 0px rgba(0, 0, 0, 0.08)", - }, colors: { primary: "#4272EF", primarylight: "#E3EAFD", @@ -49,6 +44,11 @@ module.exports = { surfconext: "#4DB2CF", }, extend: { + boxShadow: { + top4px: "inset 0 4px 0 0 rgba(0, 0, 0, 0.15);", + top2px: "inset 0 2px 0 0 rgba(0, 0, 0, 0.15;);", + floating: "0px 5px 20px 0px rgba(0, 0, 0, 0.10);", + }, transitionDuration: { 2000: "2000ms", }, diff --git a/core/frameworks/pixel/components/radio_group.ex b/core/frameworks/pixel/components/radio_group.ex index 56a4cad6a..bdaa18027 100644 --- a/core/frameworks/pixel/components/radio_group.ex +++ b/core/frameworks/pixel/components/radio_group.ex @@ -42,7 +42,7 @@ defmodule Frameworks.Pixel.RadioGroup do @impl true def render(assigns) do ~H""" -
+
<.form id={"#{@id}_form"} for={@form} phx-change="change" phx-target={@myself}>
<%= for item <- @items do %> diff --git a/core/frameworks/pixel/components/takeover.ex b/core/frameworks/pixel/components/takeover.ex new file mode 100644 index 000000000..08ce49729 --- /dev/null +++ b/core/frameworks/pixel/components/takeover.ex @@ -0,0 +1,36 @@ +defmodule Frameworks.Pixel.Takeover do + use CoreWeb, :html + + alias Frameworks.Pixel.Button + + attr(:title, :string, required: true) + attr(:target, :any, required: true) + + slot(:inner_block) + + def takeover(%{target: target} = assigns) do + close_button = %{ + action: %{type: :send, event: "takeover_close", target: target}, + face: %{type: :icon, icon: :close} + } + + assigns = assign(assigns, close_button: close_button) + + ~H""" +
+
+
+
+ +
+
+
+ <%= @title %> +
+ <%= render_slot(@inner_block) %> +
+
+
+ """ + end +end diff --git a/core/lib/core_web/controllers/layouts/error.html.heex b/core/lib/core_web/controllers/layouts/error.html.heex index 220a7a23b..a3fa46a2c 100644 --- a/core/lib/core_web/controllers/layouts/error.html.heex +++ b/core/lib/core_web/controllers/layouts/error.html.heex @@ -16,7 +16,7 @@ -
+
diff --git a/core/lib/core_web/ui/dialog/dialog.ex b/core/lib/core_web/ui/dialog/dialog.ex index 162339545..1cb4376f3 100644 --- a/core/lib/core_web/ui/dialog/dialog.ex +++ b/core/lib/core_web/ui/dialog/dialog.ex @@ -10,7 +10,7 @@ defmodule CoreWeb.UI.Dialog do def dialog(assigns) do ~H""" -
+
<%= @title %> diff --git a/core/lib/core_web/ui/popup.ex b/core/lib/core_web/ui/popup.ex index 7903133a8..0f76a81ba 100644 --- a/core/lib/core_web/ui/popup.ex +++ b/core/lib/core_web/ui/popup.ex @@ -5,7 +5,7 @@ defmodule CoreWeb.UI.Popup do def popup(assigns) do ~H""" -
+
<%= render_slot(@inner_block) %>
diff --git a/core/priv/gettext/en/LC_MESSAGES/eyra-consent.po b/core/priv/gettext/en/LC_MESSAGES/eyra-consent.po index 09c03fdcc..fd37e1404 100644 --- a/core/priv/gettext/en/LC_MESSAGES/eyra-consent.po +++ b/core/priv/gettext/en/LC_MESSAGES/eyra-consent.po @@ -26,3 +26,7 @@ msgstr "Please not that this version of the consent text has already been signed #, elixir-autogen, elixir-format msgid "out_of_sync.error.message" msgstr "The consent text has been changed. Please refresh the page to continue." + +#, elixir-autogen, elixir-format +msgid "signature.view.title" +msgstr "Consent" diff --git a/core/priv/gettext/eyra-consent.pot b/core/priv/gettext/eyra-consent.pot index 50e04738f..25fa3b7ac 100644 --- a/core/priv/gettext/eyra-consent.pot +++ b/core/priv/gettext/eyra-consent.pot @@ -26,3 +26,7 @@ msgstr "" #, elixir-autogen, elixir-format msgid "out_of_sync.error.message" msgstr "" + +#, elixir-autogen, elixir-format +msgid "signature.view.title" +msgstr "" diff --git a/core/priv/gettext/nl/LC_MESSAGES/eyra-consent.po b/core/priv/gettext/nl/LC_MESSAGES/eyra-consent.po index 63267338e..ee9a6a991 100644 --- a/core/priv/gettext/nl/LC_MESSAGES/eyra-consent.po +++ b/core/priv/gettext/nl/LC_MESSAGES/eyra-consent.po @@ -26,3 +26,7 @@ msgstr "Deze versie van de tekst voor toestemming is al ondertekend door partici #, elixir-autogen, elixir-format msgid "out_of_sync.error.message" msgstr "De toestemmingstekst is aangepast. Ververs de pagina om verder te gaan." + +#, elixir-autogen, elixir-format +msgid "signature.view.title" +msgstr "Toestemming" diff --git a/core/systems/admin/config_page.ex b/core/systems/admin/config_page.ex index d1cf8ac96..d376ab2ad 100644 --- a/core/systems/admin/config_page.ex +++ b/core/systems/admin/config_page.ex @@ -99,7 +99,7 @@ defmodule Systems.Admin.ConfigPage do <.workspace title={dgettext("eyra-admin", "config.title")} menus={@menus}> <%= if @popup do %> <.popup> -
+
<.live_component id={:config_page_popup} module={@popup.module} {@popup} />
diff --git a/core/systems/assignment/crew_page.ex b/core/systems/assignment/crew_page.ex index a71cdf786..3cd126ab9 100644 --- a/core/systems/assignment/crew_page.ex +++ b/core/systems/assignment/crew_page.ex @@ -34,7 +34,8 @@ defmodule Systems.Assignment.CrewPage do |> assign( id: id, model: model, - image_info: nil + image_info: nil, + popup: nil ) |> update_panel_info(session) |> observe_view_model() @@ -106,6 +107,17 @@ defmodule Systems.Assignment.CrewPage do {:noreply, socket |> store(key, data)} end + @impl true + def handle_event("show_popup", %{ref: %{id: id, module: module}, params: params}, socket) do + popup = %{module: module, params: Map.put(params, :id, id)} + {:noreply, socket |> assign(popup: popup)} + end + + @impl true + def handle_event("hide_popup", _, socket) do + {:noreply, socket |> assign(popup: nil)} + end + def store( %{assigns: %{panel_info: panel_info, model: assignment, remote_ip: remote_ip}} = socket, key, @@ -138,6 +150,15 @@ defmodule Systems.Assignment.CrewPage do <% end %>
+ + <%= if @popup do %> + <.popup> +
+ <.live_component id={:page_popup} module={@popup.module} {@popup.params} /> +
+ + <% end %> +
<.flow fabric={@fabric} />
diff --git a/core/systems/assignment/crew_page_builder.ex b/core/systems/assignment/crew_page_builder.ex index d681b6370..be2a5aa10 100644 --- a/core/systems/assignment/crew_page_builder.ex +++ b/core/systems/assignment/crew_page_builder.ex @@ -61,14 +61,35 @@ defmodule Systems.Assignment.CrewPageBuilder do end end - defp work_view(assignment, %{fabric: fabric} = assigns, _) do + defp work_view( + %{consent_agreement: consent_agreement} = assignment, + %{fabric: fabric, current_user: user} = assigns, + _ + ) do work_items = work_items(assignment, assigns) + context_menu_items = context_menu_items(assignment, assigns) Fabric.prepare_child(fabric, :work_view, Assignment.CrewWorkView, %{ - work_items: work_items + work_items: work_items, + consent_agreement: consent_agreement, + context_menu_items: context_menu_items, + user: user }) end + defp context_menu_items(%{consent_agreement: consent_agreement}, _assigns) do + items = [] + + items = + if consent_agreement do + items ++ [%{id: :consent, label: "Consent"}] + else + items + end + + items + end + defp work_items(%{status: status, crew: crew} = assignment, %{current_user: user} = assigns) do if is_tester?(assignment, assigns) or status == :online do member = Crew.Public.get_member(crew, user) diff --git a/core/systems/assignment/crew_work_view.ex b/core/systems/assignment/crew_work_view.ex index 1784d69ec..f05c599c5 100644 --- a/core/systems/assignment/crew_work_view.ex +++ b/core/systems/assignment/crew_work_view.ex @@ -8,18 +8,34 @@ defmodule Systems.Assignment.CrewWorkView do Assignment, Crew, Workflow, - Project + Project, + Content, + Consent } - def update(%{work_items: work_items}, socket) do + def update( + %{ + work_items: work_items, + consent_agreement: consent_agreement, + context_menu_items: context_menu_items, + user: user + }, + socket + ) do { :ok, socket - |> assign(work_items: work_items) + |> assign( + work_items: work_items, + consent_agreement: consent_agreement, + context_menu_items: context_menu_items, + user: user + ) |> update_selected_item_id() |> update_selected_item() |> compose_child(:work_list_view) |> compose_child(:start_view) + |> compose_child(:context_menu) |> update_child(:tool_ref_view) } end @@ -62,6 +78,8 @@ defmodule Systems.Assignment.CrewWorkView do socket |> assign(selected_item: selected_item) end + # Compose + @impl true def compose(:start_view, %{selected_item: selected_item}) when not is_nil(selected_item) do %{module: Assignment.StartView, params: %{work_item: selected_item}} @@ -95,18 +113,30 @@ defmodule Systems.Assignment.CrewWorkView do @impl true def compose(:tool_ref_view, _assigns), do: nil - defp map_item({%{id: id, title: title, group: group}, task}) do - %{id: id, title: title, icon: group, status: task_status(task)} + def compose(:context_menu, %{context_menu_items: []}) do + nil end - defp task_status(%{status: status}), do: status - defp task_status(_), do: :pending + def compose(:context_menu, %{context_menu_items: context_menu_items}) do + %{ + module: Content.ContextMenu, + params: %{ + items: context_menu_items + } + } + end - defp lock_task(socket, task) do - Crew.Public.lock_task(task) - socket + def compose(:consent_page, %{consent_agreement: consent_agreement, user: user}) do + %{ + module: Consent.SignatureView, + params: %{ + signature: Consent.Public.get_signature(consent_agreement, user) + } + } end + # Events + @impl true def handle_event( "complete_task", @@ -157,6 +187,23 @@ defmodule Systems.Assignment.CrewWorkView do } end + @impl true + def handle_event("show", %{page: :consent}, socket) do + { + :noreply, + socket + |> compose_child(:consent_page) + |> show_popup(:consent_page) + } + end + + @impl true + def handle_event("close", %{source: %{name: :consent_page}}, socket) do + {:noreply, socket |> hide_popup(:consent_page)} + end + + # Private + defp handle_feldspar_event(%{assigns: %{selected_item: {_, task}}} = socket, %{ "__type__" => "CommandSystemExit", "code" => code, @@ -188,6 +235,18 @@ defmodule Systems.Assignment.CrewWorkView do socket |> Frameworks.Pixel.Flash.put_error("Unsupported event") end + defp map_item({%{id: id, title: title, group: group}, task}) do + %{id: id, title: title, icon: group, status: task_status(task)} + end + + defp task_status(%{status: status}), do: status + defp task_status(_), do: :pending + + defp lock_task(socket, task) do + Crew.Public.lock_task(task) + socket + end + @impl true def render(assigns) do ~H""" @@ -216,6 +275,8 @@ defmodule Systems.Assignment.CrewWorkView do <.child name={:start_view} fabric={@fabric} />
<% end %> + <%!-- floating button --%> + <.child name={:context_menu} fabric={@fabric} />
""" end diff --git a/core/systems/assignment/ticket_view.ex b/core/systems/assignment/ticket_view.ex index 54fa620f6..0a84deedd 100644 --- a/core/systems/assignment/ticket_view.ex +++ b/core/systems/assignment/ticket_view.ex @@ -8,7 +8,7 @@ defmodule Systems.Assignment.TicketView do def normal(assigns) do ~H""" -
+
<%= dgettext("eyra-assignment", "ticket.title") %> <%= @public_id %>
diff --git a/core/systems/benchmark/tool_page.ex b/core/systems/benchmark/tool_page.ex index c95e1630c..b72fca6c3 100644 --- a/core/systems/benchmark/tool_page.ex +++ b/core/systems/benchmark/tool_page.ex @@ -69,7 +69,7 @@ defmodule Systems.Benchmark.ToolPage do <.stripped title={@vm.hero_title} menus={@menus}> <%= if @popup do %> <.popup> -
+
<.live_component {@popup} />
diff --git a/core/systems/budget/funding_page.ex b/core/systems/budget/funding_page.ex index 5844408ea..94ca65e17 100644 --- a/core/systems/budget/funding_page.ex +++ b/core/systems/budget/funding_page.ex @@ -289,7 +289,7 @@ defmodule Systems.Budget.FundingPage do <.workspace title={dgettext("eyra-budget", "funding.title")} menus={@menus}> <%= if @popup do %> <.popup> -
+
<.live_component id={:funding_popup} module={@popup.module} {@popup} />
diff --git a/core/systems/campaign/overview_page.ex b/core/systems/campaign/overview_page.ex index 9af8f21b5..2bf5e306b 100644 --- a/core/systems/campaign/overview_page.ex +++ b/core/systems/campaign/overview_page.ex @@ -217,7 +217,7 @@ defmodule Systems.Campaign.OverviewPage do <%= if @popup do %> <.popup> -
+
<.live_component id={:campaign_overview_popup} module={@popup.module} {@popup} />
diff --git a/core/systems/consent/_public.ex b/core/systems/consent/_public.ex index 1084bda16..96958a70b 100644 --- a/core/systems/consent/_public.ex +++ b/core/systems/consent/_public.ex @@ -96,7 +96,8 @@ defmodule Systems.Consent.Public do join: r in Consent.RevisionModel, on: r.id == s.revision_id, where: s.user_id == ^user_id, - where: r.agreement_id == ^agreement_id + where: r.agreement_id == ^agreement_id, + preload: [:revision] ) |> Repo.all() |> List.first() diff --git a/core/systems/consent/signature_view.ex b/core/systems/consent/signature_view.ex new file mode 100644 index 000000000..74f2f1d34 --- /dev/null +++ b/core/systems/consent/signature_view.ex @@ -0,0 +1,45 @@ +defmodule Systems.Consent.SignatureView do + use CoreWeb, :live_component_fabric + use Fabric.LiveComponent + + import Frameworks.Pixel.Takeover + + @impl true + def update(%{signature: signature}, %{assigns: %{}} = socket) do + { + :ok, + socket + |> assign(signature: signature) + |> compose_element(:title) + |> compose_element(:source) + } + end + + @impl true + def compose(:title, _) do + dgettext("eyra-consent", "signature.view.title") + end + + def compose(:source, %{signature: %{revision: %{source: source}}}), do: source + def compose(:source, _), do: "" + + # Events + + @impl true + def handle_event("takeover_close", _payload, socket) do + {:noreply, socket |> send_event(:parent, "close")} + end + + @impl true + def render(assigns) do + ~H""" +
+ <.takeover title={@title} target={@myself} > +
+ <%= raw @source %> +
+ +
+ """ + end +end diff --git a/core/systems/content/context_menu.ex b/core/systems/content/context_menu.ex new file mode 100644 index 000000000..239f88053 --- /dev/null +++ b/core/systems/content/context_menu.ex @@ -0,0 +1,57 @@ +defmodule Systems.Content.ContextMenu do + use CoreWeb, :live_component_fabric + use Fabric.LiveComponent + + @impl true + def update(%{items: items}, %{assigns: %{}} = socket) do + { + :ok, + socket |> assign(items: items) + } + end + + @impl true + def handle_event("click", %{"item" => item_id}, socket) do + item_id = String.to_existing_atom(item_id) + {:noreply, socket |> send_event(:parent, "show", %{page: item_id})} + end + + @impl true + def render(assigns) do + ~H""" +
+
+ +
+
+
+
i
+
+
+
+
+ """ + end +end diff --git a/core/systems/crew/reject_view.ex b/core/systems/crew/reject_view.ex index c148e2600..f8b244337 100644 --- a/core/systems/crew/reject_view.ex +++ b/core/systems/crew/reject_view.ex @@ -125,7 +125,7 @@ defmodule Systems.Crew.RejectView do @impl true def render(assigns) do ~H""" -
+
<%= @title %> diff --git a/core/systems/email/dialog.ex b/core/systems/email/dialog.ex index 559daec38..8c6fc2211 100644 --- a/core/systems/email/dialog.ex +++ b/core/systems/email/dialog.ex @@ -51,7 +51,7 @@ defmodule Systems.Email.Dialog do @impl true def render(assigns) do ~H""" -
+
diff --git a/core/systems/lab/day_view.ex b/core/systems/lab/day_view.ex index 0525ffe42..d66e91285 100644 --- a/core/systems/lab/day_view.ex +++ b/core/systems/lab/day_view.ex @@ -280,7 +280,7 @@ defmodule Systems.Lab.DayView do @impl true def render(assigns) do ~H""" -
+
<%= if @error do %>
diff --git a/core/systems/pool/pages/overview_page.ex b/core/systems/pool/pages/overview_page.ex index e6ecdfbc2..9f626e0b8 100644 --- a/core/systems/pool/pages/overview_page.ex +++ b/core/systems/pool/pages/overview_page.ex @@ -99,7 +99,7 @@ defmodule Systems.Pool.OverviewPage do <.workspace title={dgettext("eyra-pool", "overview.title")} menus={@menus}> <%= if @popup do %> <.popup> -
+
<.live_component id={:pool_overview_popup} module={@popup.module} {@popup} />