Packages
livebook
0.9.1
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/livebook_web/live/layout_helpers.ex
defmodule LivebookWeb.LayoutHelpers do
use LivebookWeb, :html
import LivebookWeb.UserHelpers
alias Livebook.Hubs.Provider
@doc """
The layout used in the non-session pages.
"""
attr :current_page, :string, required: true
attr :current_user, Livebook.Users.User, required: true
attr :saved_hubs, :list, required: true
slot :inner_block, required: true
slot :topbar_action
def layout(assigns) do
~H"""
<div class="flex grow h-full">
<div class="absolute md:static h-full z-[600]">
<.live_region role="alert" />
<.sidebar current_page={@current_page} current_user={@current_user} saved_hubs={@saved_hubs} />
</div>
<div class="grow overflow-y-auto">
<div class="md:hidden sticky flex items-center justify-between h-14 px-4 top-0 left-0 z-[500] bg-white border-b border-gray-200">
<div class="pt-1 text-xl text-gray-400 hover:text-gray-600 focus:text-gray-600">
<button
data-el-toggle-sidebar
aria-label="show sidebar"
phx-click={
JS.remove_class("hidden", to: "[data-el-sidebar]")
|> JS.toggle(to: "[data-el-toggle-sidebar]")
}
>
<.remix_icon icon="menu-unfold-line" />
</button>
</div>
<div>
<%= if @topbar_action do %>
<%= render_slot(@topbar_action) %>
<% else %>
<div class="text-gray-400 hover:text-gray-600 focus:text-gray-600">
<.link navigate={~p"/"} class="flex items-center" aria-label="go to home">
<.remix_icon icon="home-6-line" />
<span class="pl-2">Home</span>
</.link>
</div>
<% end %>
</div>
</div>
<%= render_slot(@inner_block) %>
</div>
</div>
<.current_user_modal current_user={@current_user} />
"""
end
defp sidebar(assigns) do
~H"""
<nav
class="hidden md:flex w-[17rem] h-full py-2 md:py-5 bg-gray-900"
aria-label="sidebar"
data-el-sidebar
>
<button
class="hidden text-xl text-gray-300 hover:text-white focus:text-white absolute top-4 right-3"
aria-label="hide sidebar"
data-el-toggle-sidebar
phx-click={
JS.add_class("hidden", to: "[data-el-sidebar]")
|> JS.toggle(to: "[data-el-toggle-sidebar]")
}
>
<.remix_icon icon="menu-fold-line" />
</button>
<div class="flex flex-col justify-between h-full">
<div class="flex flex-col">
<div class="space-y-3">
<div class="flex items-center mb-5">
<.link navigate={~p"/"} class="flex items-center border-l-4 border-gray-900 group">
<img
src={~p"/images/logo.png"}
class="mx-2"
height="40"
width="40"
alt="logo livebook"
/>
<span class="text-gray-300 text-2xl font-logo ml-[-1px] group-hover:text-white pt-1">
Livebook
</span>
</.link>
<span class="text-gray-300 text-xs font-normal font-sans mx-2.5 pt-3 cursor-default">
v<%= Application.spec(:livebook, :vsn) %>
</span>
</div>
<.sidebar_link title="Home" icon="home-6-line" to={~p"/"} current={@current_page} />
<.sidebar_link title="Apps" icon="rocket-line" to={~p"/apps"} current={@current_page} />
<.sidebar_link title="Learn" icon="article-line" to={~p"/learn"} current={@current_page} />
<.sidebar_link
title="Settings"
icon="settings-3-line"
to={~p"/settings"}
current={@current_page}
/>
</div>
<.hub_section hubs={@saved_hubs} current_page={@current_page} />
</div>
<div class="flex flex-col">
<button
:if={Livebook.Config.shutdown_callback()}
class="h-7 flex items-center text-gray-400 hover:text-white border-l-4 border-transparent hover:border-white"
aria-label="shutdown"
phx-click={
with_confirm(
JS.push("shutdown"),
title: "Shut Down",
description: "Are you sure you want to shut down Livebook now?",
confirm_text: "Shut Down",
confirm_icon: "shut-down-line"
)
}
>
<.remix_icon icon="shut-down-line" class="text-lg leading-6 w-[56px] flex justify-center" />
<span class="text-sm font-medium">
Shut Down
</span>
</button>
<button
class="mt-6 flex items-center group border-l-4 border-transparent"
aria_label="user profile"
phx-click={show_current_user_modal()}
>
<div class="w-[56px] flex justify-center">
<.user_avatar
user={@current_user}
class="w-8 h-8 group-hover:ring-white group-hover:ring-2"
text_class="text-xs"
/>
</div>
<span class="text-sm text-gray-400 font-medium group-hover:text-white">
<%= @current_user.name %>
</span>
</button>
</div>
</div>
</nav>
"""
end
defp sidebar_link(assigns) do
~H"""
<.link
navigate={@to}
class={[
"h-7 flex items-center hover:text-white border-l-4 hover:border-white",
sidebar_link_text_color(@to, @current),
sidebar_link_border_color(@to, @current)
]}
>
<.remix_icon icon={@icon} class="text-lg leading-6 w-[56px] flex justify-center" />
<span class="text-sm font-medium">
<%= @title %>
</span>
</.link>
"""
end
defp sidebar_hub_link(assigns) do
~H"""
<.link
navigate={@to}
class={[
"h-7 flex items-center hover:text-white border-l-4 hover:border-white",
sidebar_link_text_color(@to, @current),
sidebar_link_border_color(@to, @current)
]}
>
<div class="text-lg leading-6 w-[56px] flex justify-center">
<span class="relative">
<%= @hub.emoji %>
</span>
</div>
<span class="text-sm font-medium">
<%= @hub.name %>
</span>
</.link>
"""
end
defp sidebar_hub_link_with_tooltip(assigns) do
~H"""
<.link {hub_connection_link_opts(@hub.provider, @to, @current)}>
<div class="text-lg leading-6 w-[56px] flex justify-center">
<span class="relative">
<%= @hub.emoji %>
<div class={[
"absolute w-[10px] h-[10px] border-gray-900 border-2 rounded-full right-0 bottom-0",
if(@hub.connected?, do: "bg-green-400", else: "bg-red-400")
]} />
</span>
</div>
<span class="text-sm font-medium">
<%= @hub.name %>
</span>
</.link>
"""
end
defp hub_section(assigns) do
~H"""
<div id="hubs" class="flex flex-col mt-12">
<div class="space-y-3">
<div class="grid grid-cols-1 md:grid-cols-2 relative leading-6 mb-2">
<small class="ml-5 font-medium text-gray-300 cursor-default">HUBS</small>
</div>
<%= for hub <- @hubs do %>
<%= if Provider.connection_spec(hub.provider) do %>
<.sidebar_hub_link_with_tooltip hub={hub} to={~p"/hub/#{hub.id}"} current={@current_page} />
<% else %>
<.sidebar_hub_link hub={hub} to={~p"/hub/#{hub.id}"} current={@current_page} />
<% end %>
<% end %>
<.sidebar_link title="Add Hub" icon="add-line" to={~p"/hub"} current={@current_page} />
</div>
</div>
"""
end
defp sidebar_link_text_color(to, current) when to == current, do: "text-white"
defp sidebar_link_text_color(_to, _current), do: "text-gray-400"
defp sidebar_link_border_color(to, current) when to == current, do: "border-white"
defp sidebar_link_border_color(_to, _current), do: "border-transparent"
defp hub_connection_link_opts(hub, to, current) do
text_color = sidebar_link_text_color(to, current)
border_color = sidebar_link_border_color(to, current)
class =
"h-7 flex items-center hover:text-white #{text_color} border-l-4 #{border_color} hover:border-white"
if tooltip = Provider.connection_error(hub) do
[navigate: to, data_tooltip: tooltip, class: "tooltip right " <> class]
else
[navigate: to, class: class]
end
end
@doc """
Renders page title.
## Examples
<.title text="Learn" />
"""
attr :text, :string, required: true
attr :back_navigate, :string, default: nil
def title(assigns) do
~H"""
<div class="relative">
<div
:if={@back_navigate}
class="hidden md:flex absolute top-0 bottom-0 left-0 transform -translate-x-full"
>
<.link navigate={@back_navigate}>
<.remix_icon icon="arrow-left-line" class="align-middle mr-2 text-2xl text-gray-800" />
</.link>
</div>
<h1 class="text-2xl text-gray-800 font-medium">
<%= @text %>
</h1>
</div>
"""
end
end