Redesign runtime panel and sessions list (#697)

* Redesign runtimes panel

* Redesign session list

* Add session sort

* Move session list to a separate component

* Up
This commit is contained in:
Jonatan Kłosko 2021-11-10 18:50:39 +01:00 committed by GitHub
parent 54511d5ffc
commit d81965ee99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 172 additions and 100 deletions

View file

@ -250,12 +250,14 @@ defmodule LivebookWeb.Helpers do
<.labeled_text label="Name" text="Sherlock Holmes" />
"""
def labeled_text(assigns) do
assigns = assign_new(assigns, :one_line, fn -> false end)
~H"""
<div class="flex flex-col space-y-1">
<span class="text-xs text-gray-500">
<%= @label %>
</span>
<span class="text-gray-800 text-sm font-semibold">
<span class={"text-gray-800 text-sm font-semibold #{if @one_line, do: "whitespace-nowrap overflow-auto tiny-scrollbar"}"}>
<%= @text %>
</span>
</div>

View file

@ -13,7 +13,7 @@ defmodule LivebookWeb.HomeLive do
Phoenix.PubSub.subscribe(Livebook.PubSub, "tracker_sessions")
end
sessions = sort_sessions(Sessions.list_sessions())
sessions = Sessions.list_sessions()
notebook_infos = Notebook.Explore.visible_notebook_infos() |> Enum.take(3)
{:ok,
@ -87,7 +87,7 @@ defmodule LivebookWeb.HomeLive do
<div class="py-12">
<div class="mb-4 flex justify-between items-center">
<h2 class="text-xl font-semibold text-gray-800">
<h2 class="uppercase font-semibold text-gray-500">
Explore
</h2>
<%= live_redirect to: Routes.explore_path(@socket, :page),
@ -104,12 +104,10 @@ defmodule LivebookWeb.HomeLive do
<% end %>
</div>
</div>
<div class="py-12">
<h2 class="mb-4 text-xl font-semibold text-gray-800">
Running sessions
</h2>
<.sessions_list sessions={@sessions} socket={@socket} />
<.live_component module={LivebookWeb.HomeLive.SessionListComponent}
id="session-list"
sessions={@sessions} />
</div>
</div>
</div>
@ -149,68 +147,6 @@ defmodule LivebookWeb.HomeLive do
end
end
defp sessions_list(%{sessions: []} = assigns) do
~H"""
<div class="p-5 flex space-x-4 items-center border border-gray-200 rounded-lg">
<div>
<.remix_icon icon="windy-line" class="text-gray-400 text-xl" />
</div>
<div class="text-gray-600">
You do not have any running sessions.
<br>
Please create a new one by clicking <span class="font-semibold">New notebook</span>
</div>
</div>
"""
end
defp sessions_list(assigns) do
~H"""
<div class="flex flex-col space-y-4">
<%= for session <- @sessions do %>
<div class="p-5 flex items-center border border-gray-200 rounded-lg"
data-test-session-id={session.id}>
<div class="flex-grow flex flex-col space-y-1">
<%= live_redirect session.notebook_name,
to: Routes.session_path(@socket, :page, session.id),
class: "font-semibold text-gray-800 hover:text-gray-900" %>
<div class="text-gray-600 text-sm">
<%= if session.file, do: session.file.path, else: "No file" %>
</div>
<div class="text-gray-600 text-sm">
Created <%= format_creation_date(session.created_at) %>
</div>
</div>
<div class="relative" id={"session-#{session.id}-menu"} phx-hook="Menu" data-element="menu">
<button class="icon-button" data-toggle>
<.remix_icon icon="more-2-fill" class="text-xl" />
</button>
<div class="menu" data-content>
<button class="menu__item text-gray-500"
phx-click="fork_session"
phx-value-id={session.id}>
<.remix_icon icon="git-branch-line" />
<span class="font-medium">Fork</span>
</button>
<a class="menu__item text-gray-500"
href={live_dashboard_process_path(@socket, session.pid)}
target="_blank">
<.remix_icon icon="dashboard-2-line" />
<span class="font-medium">See on Dashboard</span>
</a>
<%= live_patch to: Routes.home_path(@socket, :close_session, session.id),
class: "menu__item text-red-600" do %>
<.remix_icon icon="close-circle-line" />
<span class="font-medium">Close</span>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
"""
end
@impl true
def handle_params(%{"session_id" => session_id}, _url, socket) do
session = Enum.find(socket.assigns.sessions, &(&1.id == session_id))
@ -323,8 +259,7 @@ defmodule LivebookWeb.HomeLive do
if session in socket.assigns.sessions do
{:noreply, socket}
else
sessions = sort_sessions([session | socket.assigns.sessions])
{:noreply, assign(socket, sessions: sessions)}
{:noreply, assign(socket, sessions: [session | socket.assigns.sessions])}
end
end
@ -349,10 +284,6 @@ defmodule LivebookWeb.HomeLive do
def handle_info(_message, socket), do: {:noreply, socket}
defp sort_sessions(sessions) do
Enum.sort_by(sessions, & &1.created_at, {:desc, DateTime})
end
defp files(sessions) do
Enum.map(sessions, & &1.file)
end
@ -390,11 +321,6 @@ defmodule LivebookWeb.HomeLive do
session.id
end
def format_creation_date(created_at) do
time_words = created_at |> DateTime.to_naive() |> Livebook.Utils.Time.time_ago_in_words()
time_words <> " ago"
end
defp import_content(socket, content, session_opts) do
{notebook, messages} = Livebook.LiveMarkdown.Import.notebook_from_markdown(content)

View file

@ -0,0 +1,140 @@
defmodule LivebookWeb.HomeLive.SessionListComponent do
use LivebookWeb, :live_component
@impl true
def mount(socket) do
{:ok, assign(socket, order_by: "date")}
end
@impl true
def update(assigns, socket) do
{sessions, assigns} = Map.pop!(assigns, :sessions)
sessions = sort_sessions(sessions, socket.assigns.order_by)
socket =
socket
|> assign(assigns)
|> assign(:sessions, sessions)
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<div>
<div class="flex items-center justify-between">
<h2 class="mb-4 uppercase font-semibold text-gray-500">
Running sessions (<%= length(@sessions) %>)
</h2>
<div class="relative" id={"sessions-order-menu"} phx-hook="Menu" data-element="menu">
<button class="button button-outlined-gray px-4 py-1" data-toggle>
<span><%= order_by_label(@order_by) %></span>
<.remix_icon icon="arrow-down-s-line" class="text-lg leading-none align-middle ml-1" />
</button>
<div class="menu" data-content>
<%= for order_by <- ["date", "title"] do %>
<button class={"menu__item #{if order_by == @order_by, do: "text-gray-900", else: "text-gray-500"}"}
phx-click={JS.push("set_order", value: %{order_by: order_by}, target: @myself)}>
<.remix_icon icon={order_by_icon(order_by)} />
<span class="font-medium"><%= order_by_label(order_by) %></span>
</button>
<% end %>
</div>
</div>
</div>
<.session_list sessions={@sessions} socket={@socket} />
</div>
"""
end
defp session_list(%{sessions: []} = assigns) do
~H"""
<div class="p-5 flex space-x-4 items-center border border-gray-200 rounded-lg">
<div>
<.remix_icon icon="windy-line" class="text-gray-400 text-xl" />
</div>
<div class="text-gray-600">
You do not have any running sessions.
<br>
Please create a new one by clicking <span class="font-semibold">New notebook</span>
</div>
</div>
"""
end
defp session_list(assigns) do
~H"""
<div class="flex flex-col">
<%= for session <- @sessions do %>
<div class="py-4 flex items-center border-b border-gray-300"
data-test-session-id={session.id}>
<div class="flex-grow flex flex-col items-start">
<%= live_redirect session.notebook_name,
to: Routes.session_path(@socket, :page, session.id),
class: "font-semibold text-gray-800 hover:text-gray-900" %>
<div class="text-gray-600 text-sm">
<%= if session.file, do: session.file.path, else: "No file" %>
</div>
<div class="mt-2 text-gray-600 text-sm">
Created <%= format_creation_date(session.created_at) %>
</div>
</div>
<div class="relative" id={"session-#{session.id}-menu"} phx-hook="Menu" data-element="menu">
<button class="icon-button" data-toggle>
<.remix_icon icon="more-2-fill" class="text-xl" />
</button>
<div class="menu" data-content>
<button class="menu__item text-gray-500"
phx-click="fork_session"
phx-value-id={session.id}>
<.remix_icon icon="git-branch-line" />
<span class="font-medium">Fork</span>
</button>
<a class="menu__item text-gray-500"
href={live_dashboard_process_path(@socket, session.pid)}
target="_blank">
<.remix_icon icon="dashboard-2-line" />
<span class="font-medium">See on Dashboard</span>
</a>
<%= live_patch to: Routes.home_path(@socket, :close_session, session.id),
class: "menu__item text-red-600" do %>
<.remix_icon icon="close-circle-line" />
<span class="font-medium">Close</span>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
"""
end
@impl true
def handle_event("set_order", %{"order_by" => order_by}, socket) do
sessions = sort_sessions(socket.assigns.sessions, order_by)
{:noreply, assign(socket, sessions: sessions, order_by: order_by)}
end
def format_creation_date(created_at) do
time_words = created_at |> DateTime.to_naive() |> Livebook.Utils.Time.time_ago_in_words()
time_words <> " ago"
end
defp order_by_label("date"), do: "Date"
defp order_by_label("title"), do: "Title"
defp order_by_icon("date"), do: "calendar-2-line"
defp order_by_icon("title"), do: "text"
defp sort_sessions(sessions, "date") do
Enum.sort_by(sessions, & &1.created_at, {:desc, DateTime})
end
defp sort_sessions(sessions, "title") do
Enum.sort_by(sessions, fn session ->
{session.notebook_name, -DateTime.to_unix(session.created_at)}
end)
end
end

View file

@ -290,7 +290,7 @@ defmodule LivebookWeb.SessionLive do
defp sections_list(assigns) do
~H"""
<div class="flex flex-col flex-grow">
<h3 class="text-lg font-semibold text-gray-800">
<h3 class="uppercase text-sm font-semibold text-gray-500">
Sections
</h3>
<div class="flex flex-col mt-4 space-y-4">
@ -327,10 +327,10 @@ defmodule LivebookWeb.SessionLive do
~H"""
<div class="flex flex-col flex-grow">
<div class="flex items-center justify-between space-x-4">
<h3 class="text-lg font-semibold text-gray-800 flex-lg">
<h3 class="uppercase text-sm font-semibold text-gray-500">
Users
</h3>
<span class="flex items-center p-2 space-x-2 text-sm bg-gray-200 rounded-lg">
<span class="flex items-center px-2 py-1 space-x-2 text-sm bg-gray-200 rounded-lg">
<span class="inline-flex w-3 h-3 bg-green-600 rounded-full"></span>
<span><%= length(@data_view.clients) %> connected</span>
</span>
@ -373,31 +373,34 @@ defmodule LivebookWeb.SessionLive do
defp runtime_info(assigns) do
~H"""
<div class="flex flex-col flex-grow">
<h3 class="text-lg font-semibold text-gray-800">
Runtime
</h3>
<div class="flex items-center justify-between">
<h3 class="uppercase text-sm font-semibold text-gray-500">
Runtime
</h3>
<%= live_patch to: Routes.session_path(@socket, :runtime_settings, @session.id),
class: "icon-button",
type: "button" do %>
<.remix_icon icon="settings-3-line text-xl" />
<% end %>
</div>
<div class="flex flex-col mt-4 space-y-4">
<%= if @data_view.runtime do %>
<div class="flex flex-col space-y-3">
<.labeled_text label="Type" text={runtime_type_label(@data_view.runtime)} />
<.labeled_text label="Node name" text={@data_view.runtime.node} />
<.labeled_text label="Node name" text={@data_view.runtime.node} one_line={true} />
</div>
<div class="flex flex-col space-y-3">
<div class="flex space-x-2">
<button class="button button-outlined-blue w-full" phx-click="restart_runtime">
Reconnect
<button class="button button-blue" phx-click="restart_runtime">
<.remix_icon icon="wireless-charging-line" class="align-middle mr-1" />
<span>Reconnect</span>
</button>
<button class="button button-outlined-red w-full"
<button class="button button-outlined-red"
type="button"
phx-click="disconnect_runtime">
Disconnect
</button>
</div>
<%= live_patch to: Routes.session_path(@socket, :runtime_settings, @session.id),
class: "button button-gray button-square-icon",
type: "button" do %>
<.remix_icon icon="settings-3-line" />
<% end %>
</div>
<% else %>
<div class="flex flex-col space-y-3">
@ -405,12 +408,13 @@ defmodule LivebookWeb.SessionLive do
</div>
<div class="flex space-x-2">
<button class="button button-blue" phx-click="connect_default_runtime">
Connect
<.remix_icon icon="wireless-charging-line" class="align-middle mr-1" />
<span>Connect</span>
</button>
<%= live_patch to: Routes.session_path(@socket, :runtime_settings, @session.id),
class: "button button-gray button-square-icon",
class: "button button-outlined-gray bg-transparent",
type: "button" do %>
<.remix_icon icon="settings-3-line" />
Configure
<% end %>
</div>
<% end %>

View file

@ -33,7 +33,7 @@ defmodule LivebookWeb.SessionLive.RuntimeComponent do
~H"""
<div class="p-6 pb-4 max-w-4xl flex flex-col space-y-5">
<h3 class="text-2xl font-semibold text-gray-800">
Runtime
Runtime settings
</h3>
<div class="w-full flex-col space-y-5">
<div class="flex space-x-4">