Packages
livebook
0.19.6
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
Current section
Files
Jump to
Current section
Files
lib/livebook_web/live/learn_live.ex
defmodule LivebookWeb.LearnLive do
use LivebookWeb, :live_view
import LivebookWeb.SessionHelpers
import LivebookWeb.NotebookComponents
alias LivebookWeb.LayoutComponents
alias Livebook.Notebook.Learn
on_mount LivebookWeb.SidebarHook
@impl true
def mount(_params, _session, socket) do
[lead_notebook_info | notebook_infos] = Learn.visible_notebook_infos()
{:ok,
assign(socket,
lead_notebook_info: lead_notebook_info,
notebook_infos: notebook_infos,
page_title: "Learn - Livebook"
)}
end
@impl true
def render(assigns) do
~H"""
<LayoutComponents.layout
current_page={~p"/learn"}
current_user={@current_user}
teams_auth={@teams_auth}
saved_hubs={@saved_hubs}
>
<div class="p-4 md:px-12 md:py-7 max-w-(--breakpoint-lg) mx-auto space-y-4">
<div>
<LayoutComponents.title text="Learn" />
<p class="mt-4 mb-8 text-gray-700">
Check out a number of examples showcasing various parts of the Elixir ecosystem.<br />
Click on any notebook you like and start playing around with it!
</p>
</div>
<div
id="welcome-to-livebook"
class="p-8 bg-gray-900 rounded-2xl flex flex-col sm:flex-row space-y-8 sm:space-y-0 space-x-0 sm:space-x-8 items-center"
>
<img src={learn_img_src(@lead_notebook_info.details.cover)} width="100" alt="livebook" />
<div>
<h3 class="text-xl text-gray-50 font-semibold">
{@lead_notebook_info.title}
</h3>
<p class="mt-2 text-sm text-gray-300">
{@lead_notebook_info.details.description}
</p>
<div class="mt-4">
<.button patch={~p"/learn/notebooks/#{@lead_notebook_info.slug}"}>
Open notebook
</.button>
</div>
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">
<%!--
Note: it's fine to use stateless components in this comprehension,
because @notebook_infos never change
--%>
<.learn_notebook_card :for={info <- @notebook_infos} notebook_info={info} />
</div>
<.notebook_group :for={group_info <- Learn.group_infos()} group_info={group_info} />
</div>
</LayoutComponents.layout>
"""
end
defp notebook_group(assigns) do
~H"""
<div>
<div class="p-8 mt-16 rounded-2xl border border-gray-300 flex flex-col sm:flex-row space-y-8 sm:space-y-0 space-x-0 sm:space-x-8 items-center">
<img src={learn_img_src(@group_info.cover)} width="100" />
<div>
<div class="inline-flex px-2 py-0.5 bg-gray-200 rounded-3xl text-gray-700 text-xs font-medium">
{length(@group_info.notebook_infos)} notebooks
</div>
<h3 class="mt-1 text-xl text-gray-800 font-semibold">
{@group_info.title}
</h3>
<p class="mt-2 text-gray-700">
{@group_info.description}
</p>
</div>
</div>
<div class="mt-3 mb-20">
<ul>
<li
:for={{notebook_info, number} <- Enum.with_index(@group_info.notebook_infos, 1)}
class="py-3 flex flex-row items-center space-x-5 border-b border-gray-200 last:border-b-0"
>
<div class="text-lg text-gray-400 font-semibold">
{number |> Integer.to_string() |> String.pad_leading(2, "0")}
</div>
<div class="grow text-gray-800 font-semibold">
{notebook_info.title}
</div>
<.button color="gray" outlined navigate={~p"/learn/notebooks/#{notebook_info.slug}"}>
<.remix_icon icon="play-circle-line" /> Open
</.button>
</li>
</ul>
</div>
</div>
"""
end
@impl true
def handle_params(%{"slug" => slug}, _url, socket) do
{notebook, files} = Learn.notebook_by_slug!(slug)
{:noreply, create_session(socket, notebook: notebook, files_source: {:inline, files})}
end
def handle_params(_params, _url, socket), do: {:noreply, socket}
end