mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-09-20 10:05:57 +08:00
Encapsulate buttons and inputs in components (#2477)
This commit is contained in:
parent
8a81fda7ea
commit
4587396c9a
|
@ -1,101 +1,20 @@
|
|||
@layer components {
|
||||
/* Buttons */
|
||||
|
||||
.button-base {
|
||||
@apply inline-flex items-center px-5 py-2 rounded-lg border border-transparent font-medium text-sm whitespace-nowrap;
|
||||
}
|
||||
|
||||
.button-blue {
|
||||
@apply border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:bg-blue-700;
|
||||
}
|
||||
|
||||
.button-red {
|
||||
@apply border-transparent bg-red-600 text-white hover:bg-red-700 focus:bg-red-700;
|
||||
}
|
||||
|
||||
.button-gray {
|
||||
@apply border-gray-200 bg-gray-100 text-gray-600 hover:bg-gray-200 focus:bg-gray-200;
|
||||
}
|
||||
|
||||
.button-outlined-blue {
|
||||
@apply bg-blue-50 border-blue-600 text-blue-600 hover:bg-blue-100 focus:bg-blue-100;
|
||||
}
|
||||
|
||||
.button-outlined-red {
|
||||
@apply bg-red-50 border-red-600 text-red-600 hover:bg-red-100 focus:bg-red-100;
|
||||
}
|
||||
|
||||
.button-outlined-gray {
|
||||
@apply bg-white border-gray-300 text-gray-600 hover:bg-gray-100 focus:bg-gray-100;
|
||||
}
|
||||
|
||||
.button-base:disabled,
|
||||
.button-base.disabled {
|
||||
@apply cursor-default pointer-events-none border-transparent bg-gray-100 text-gray-400;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
@apply px-2 py-1 bg-gray-50 border-gray-200 text-gray-600 hover:bg-gray-100 focus:bg-gray-100;
|
||||
}
|
||||
|
||||
.button-square-icon {
|
||||
@apply p-2 flex items-center justify-center;
|
||||
}
|
||||
|
||||
.button-square-icon i {
|
||||
@apply text-xl leading-none;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
@apply p-1 flex items-center justify-center text-gray-500 hover:text-gray-900 rounded-full;
|
||||
}
|
||||
|
||||
.icon-button:focus {
|
||||
@apply bg-gray-100;
|
||||
}
|
||||
|
||||
.icon-button:disabled,
|
||||
.icon-button.disabled {
|
||||
@apply cursor-default pointer-events-none text-gray-300;
|
||||
}
|
||||
|
||||
.icon-button i {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.icon-outlined-button {
|
||||
@apply rounded-full border-2;
|
||||
}
|
||||
|
||||
/* Form fields */
|
||||
|
||||
.input {
|
||||
@apply w-full px-3 py-2 bg-gray-50 text-sm border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 phx-form-error:border-red-300 disabled:opacity-70 disabled:cursor-not-allowed;
|
||||
}
|
||||
|
||||
.input[type="color"] {
|
||||
@apply py-0 w-16;
|
||||
}
|
||||
|
||||
.input--error {
|
||||
@apply bg-red-50 border-red-600 text-red-600;
|
||||
}
|
||||
|
||||
.input-range {
|
||||
.range-input {
|
||||
height: 8px;
|
||||
@apply appearance-none bg-gray-200 rounded-lg;
|
||||
}
|
||||
|
||||
.input-range::-webkit-slider-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@apply appearance-none border-transparent bg-blue-600 hover:bg-blue-700 cursor-pointer rounded-xl;
|
||||
/*
|
||||
Note that we need separate selectors, because at most one of these
|
||||
pseudo-selectors is valid in the given browser, and an invalid one
|
||||
would cause the whole rule to be invalid and ignored
|
||||
*/
|
||||
.range-input::-moz-range-thumb {
|
||||
@apply w-5 h-5 appearance-none border-transparent bg-blue-600 hover:bg-blue-700 cursor-pointer rounded-xl;
|
||||
}
|
||||
|
||||
.input-range::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@apply appearance-none border-transparent bg-blue-600 hover:bg-blue-700 cursor-pointer rounded-xl;
|
||||
.range-input::-webkit-slider-thumb {
|
||||
@apply w-5 h-5 appearance-none border-transparent bg-blue-600 hover:bg-blue-700 cursor-pointer rounded-xl;
|
||||
}
|
||||
|
||||
/* Custom scrollbars */
|
||||
|
|
|
@ -136,9 +136,7 @@ solely client-side operations.
|
|||
left: calc(-45vw + 50%);
|
||||
}
|
||||
|
||||
[data-el-cell][data-js-amplified]
|
||||
[data-el-amplify-outputs-button]
|
||||
.icon-button {
|
||||
[data-el-cell][data-js-amplified] [data-el-amplify-outputs-button] > button {
|
||||
@apply bg-gray-100 text-gray-900;
|
||||
}
|
||||
|
||||
|
@ -180,7 +178,7 @@ solely client-side operations.
|
|||
|
||||
[data-el-cell][data-type="smart"][data-js-source-visible]
|
||||
[data-el-toggle-source-button]
|
||||
.icon-button {
|
||||
> button {
|
||||
@apply bg-gray-100 text-gray-900;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,11 @@ if (hasCookiesAccess()) {
|
|||
third-party cookies.
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<a id="open-app" class="button-base button-blue" target="_blank">
|
||||
<a
|
||||
id="open-app"
|
||||
class="px-5 py-2 font-medium text-sm inline-flex rounded-lg border whitespace-nowrap items-center justify-center gap-1 border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:bg-blue-700"
|
||||
target="_blank"
|
||||
>
|
||||
Open app
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -205,8 +205,9 @@ defmodule LivebookWeb.AppComponents do
|
|||
<span class="text-sm text-gray-700 font-semibold">Dockerfile</span>
|
||||
<div class="grow" />
|
||||
<%= render_slot(@dockerfile_actions) %>
|
||||
<button
|
||||
class="button-base button-gray whitespace-nowrap py-1 px-2"
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
data-tooltip="Copied to clipboard"
|
||||
type="button"
|
||||
aria-label="copy to clipboard"
|
||||
|
@ -215,9 +216,9 @@ defmodule LivebookWeb.AppComponents do
|
|||
|> JS.add_class("", transition: {"tooltip top", "", ""}, time: 2000)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="align-middle mr-1 text-xs" />
|
||||
<span class="font-normal text-xs">Copy source</span>
|
||||
</button>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
<span>Copy source</span>
|
||||
</.button>
|
||||
</div>
|
||||
|
||||
<.code_preview source_id="dockerfile-source" source={@dockerfile} language="dockerfile" />
|
||||
|
|
|
@ -120,16 +120,13 @@ defmodule LivebookWeb.Confirm do
|
|||
</div>
|
||||
<div class="mt-8 flex justify-end">
|
||||
<div class={["flex gap-2", @danger && "flex-row-reverse"]}>
|
||||
<button class="button-base button-outlined-gray" type="button" phx-click={hide_modal(@id)}>
|
||||
<.button color="gray" outlined type="button" phx-click={hide_modal(@id)}>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class={["button-base", if(@danger, do: "button-red", else: "button-blue")]}
|
||||
type="submit"
|
||||
>
|
||||
<.remix_icon :if={@confirm_icon} icon={@confirm_icon} class="align-middle mr-1" />
|
||||
</.button>
|
||||
<.button color={if(@danger, do: "red", else: "blue")} type="submit">
|
||||
<.remix_icon :if={@confirm_icon} icon={@confirm_icon} />
|
||||
<span><%= @confirm_text %></span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -696,6 +696,7 @@ defmodule LivebookWeb.CoreComponents do
|
|||
<:col :let={user} label="id"><%= user.id %></:col>
|
||||
<:col :let={user} label="username"><%= user.username %></:col>
|
||||
</.table>
|
||||
|
||||
"""
|
||||
attr :id, :string, required: true
|
||||
attr :rows, :list, required: true
|
||||
|
@ -742,17 +743,15 @@ defmodule LivebookWeb.CoreComponents do
|
|||
phx-click={@row_click && @row_click.(row)}
|
||||
class={["relative p-0", @row_click && "hover:cursor-pointer"]}
|
||||
>
|
||||
<div class="block p-4 sm:px-6">
|
||||
<span class="absolute -inset-y-px right-0 -left-4 group-hover:bg-gray-100 sm:rounded-l-xl" />
|
||||
<span class="relative">
|
||||
<%= render_slot(col, @row_item.(row)) %>
|
||||
</span>
|
||||
<span class="absolute -inset-y-px right-0 -left-4 group-hover:bg-gray-100 rounded-l-xl" />
|
||||
<div class="relative block p-4 sm:px-6">
|
||||
<%= render_slot(col, @row_item.(row)) %>
|
||||
</div>
|
||||
</td>
|
||||
<td :if={@action != []} class="relative p-0">
|
||||
<span class="absolute -inset-y-px -right-4 left-0 group-hover:bg-gray-100 rounded-r-xl" />
|
||||
<div class="relative whitespace-nowrap py-4 pl-3 pr-4 sm:pr-6 flex justify-end items-center">
|
||||
<span class="absolute -inset-y-px -right-4 left-0 group-hover:bg-gray-100 sm:rounded-r-xl" />
|
||||
<span :for={action <- @action} class="relative ml-4">
|
||||
<span :for={action <- @action} class="ml-4">
|
||||
<%= render_slot(action, @row_item.(row)) %>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -764,6 +763,134 @@ defmodule LivebookWeb.CoreComponents do
|
|||
"""
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Renders a button.
|
||||
|
||||
## Examples
|
||||
|
||||
<.button>Click</.button>
|
||||
|
||||
<.button color="gray" outlined>Click</.button>
|
||||
|
||||
<.button color="gray" small>Click</.button>
|
||||
|
||||
"""
|
||||
attr :disabled, :boolean, default: false
|
||||
attr :color, :string, default: "blue", values: ~w(blue gray red)
|
||||
attr :outlined, :boolean, default: false
|
||||
attr :small, :boolean, default: false
|
||||
attr :class, :string, default: nil
|
||||
|
||||
attr :rest, :global, include: ~w(href patch navigate download name)
|
||||
|
||||
slot :inner_block
|
||||
|
||||
def button(assigns)
|
||||
when is_map_key(assigns.rest, :href) or is_map_key(assigns.rest, :patch) or
|
||||
is_map_key(assigns.rest, :navigate) do
|
||||
~H"""
|
||||
<.link class={[button_classes(@small, @disabled, @color, @outlined), @class]} {@rest}>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</.link>
|
||||
"""
|
||||
end
|
||||
|
||||
def button(assigns) do
|
||||
~H"""
|
||||
<button
|
||||
class={[button_classes(@small, @disabled, @color, @outlined), @class]}
|
||||
disabled={@disabled}
|
||||
{@rest}
|
||||
>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</button>
|
||||
"""
|
||||
end
|
||||
|
||||
defp button_classes(small, disabled, color, outlined) do
|
||||
[
|
||||
if small do
|
||||
"px-2 py-1 font-normal text-xs"
|
||||
else
|
||||
"px-5 py-2 font-medium text-sm"
|
||||
end,
|
||||
"inline-flex rounded-lg border whitespace-nowrap items-center justify-center gap-1.5",
|
||||
if disabled do
|
||||
"cursor-default pointer-events-none border-transparent bg-gray-100 text-gray-400"
|
||||
else
|
||||
case {color, outlined} do
|
||||
{"blue", false} ->
|
||||
"border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:bg-blue-700"
|
||||
|
||||
{"red", false} ->
|
||||
"border-transparent bg-red-600 text-white hover:bg-red-700 focus:bg-red-700"
|
||||
|
||||
{"gray", false} ->
|
||||
"border-gray-200 bg-gray-100 text-gray-600 hover:bg-gray-200 focus:bg-gray-200"
|
||||
|
||||
{"blue", true} ->
|
||||
"bg-blue-50 border-blue-600 text-blue-600 hover:bg-blue-100 focus:bg-blue-100"
|
||||
|
||||
{"red", true} ->
|
||||
"bg-red-50 border-red-600 text-red-600 hover:bg-red-100 focus:bg-red-100"
|
||||
|
||||
{"gray", true} ->
|
||||
"bg-transparent border-gray-300 text-gray-600 hover:bg-gray-100 focus:bg-gray-100"
|
||||
end
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Renders an icon button.
|
||||
|
||||
## Examples
|
||||
|
||||
<.icon_button>
|
||||
<.remix_icon icon="refresh-line" />
|
||||
</.icon_button>
|
||||
|
||||
"""
|
||||
attr :disabled, :boolean, default: false
|
||||
attr :small, :boolean, default: false
|
||||
attr :class, :string, default: nil
|
||||
|
||||
attr :rest, :global, include: ~w(href patch navigate download name)
|
||||
|
||||
slot :inner_block
|
||||
|
||||
def icon_button(assigns)
|
||||
when is_map_key(assigns.rest, :href) or is_map_key(assigns.rest, :patch) or
|
||||
is_map_key(assigns.rest, :navigate) do
|
||||
~H"""
|
||||
<.link class={[icon_button_classes(@small, @disabled), @class]} {@rest}>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</.link>
|
||||
"""
|
||||
end
|
||||
|
||||
def icon_button(assigns) do
|
||||
~H"""
|
||||
<button class={[icon_button_classes(@small, @disabled), @class]} disabled={@disabled} {@rest}>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</button>
|
||||
"""
|
||||
end
|
||||
|
||||
defp icon_button_classes(small, disabled) do
|
||||
[
|
||||
unless small do
|
||||
"text-xl"
|
||||
end,
|
||||
"p-1 flex items-center justify-center rounded-full leading-none",
|
||||
if disabled do
|
||||
"cursor-default text-gray-300"
|
||||
else
|
||||
"text-gray-500 hover:text-gray-900 focus:bg-gray-100"
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
# JS commands
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -15,9 +15,10 @@ defmodule LivebookWeb.FormComponents do
|
|||
attr :errors, :list, default: []
|
||||
attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form"
|
||||
attr :help, :string, default: nil
|
||||
attr :type, :string, default: "text"
|
||||
attr :class, :string, default: nil
|
||||
|
||||
attr :rest, :global, include: ~w(autocomplete readonly disabled)
|
||||
attr :rest, :global, include: ~w(autocomplete readonly disabled step min max)
|
||||
|
||||
def text_field(assigns) do
|
||||
assigns = assigns_from_field(assigns)
|
||||
|
@ -25,17 +26,21 @@ defmodule LivebookWeb.FormComponents do
|
|||
~H"""
|
||||
<.field_wrapper id={@id} name={@name} label={@label} errors={@errors} help={@help}>
|
||||
<input
|
||||
type="text"
|
||||
type={@type}
|
||||
name={@name}
|
||||
id={@id || @name}
|
||||
value={Phoenix.HTML.Form.normalize_value("text", @value)}
|
||||
class={["input", @class]}
|
||||
class={[input_classes(), @class]}
|
||||
{@rest}
|
||||
/>
|
||||
</.field_wrapper>
|
||||
"""
|
||||
end
|
||||
|
||||
defp input_classes() do
|
||||
"w-full px-3 py-2 bg-gray-50 text-sm font-normal border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 disabled:opacity-70 disabled:cursor-not-allowed phx-form-error:bg-red-50 phx-form-error:border-red-600 phx-form-error:text-red-600 invalid:bg-red-50 invalid:border-red-600 invalid:text-red-600"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a textarea input with label and error messages.
|
||||
"""
|
||||
|
@ -46,8 +51,9 @@ defmodule LivebookWeb.FormComponents do
|
|||
attr :errors, :list, default: []
|
||||
attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form"
|
||||
attr :help, :string, default: nil
|
||||
attr :class, :string, default: nil
|
||||
|
||||
attr :resizable, :boolean, default: false
|
||||
attr :monospace, :boolean, default: false
|
||||
|
||||
attr :rest, :global, include: ~w(autocomplete readonly disabled rows cols)
|
||||
|
||||
|
@ -59,7 +65,7 @@ defmodule LivebookWeb.FormComponents do
|
|||
<textarea
|
||||
id={@id || @name}
|
||||
name={@name}
|
||||
class={["input", not @resizable && "resize-none"]}
|
||||
class={[input_classes(), "resize-none tiny-scrollbar", @monospace && "font-mono", @class]}
|
||||
{@rest}
|
||||
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
|
||||
</.field_wrapper>
|
||||
|
@ -103,16 +109,45 @@ defmodule LivebookWeb.FormComponents do
|
|||
|
||||
~H"""
|
||||
<.field_wrapper id={@id} name={@name} label={@label} errors={@errors} help={@help}>
|
||||
<.with_password_toggle id={@id <> "-toggle"}>
|
||||
<div id={"#{@id}-toggle"} class="relative flex">
|
||||
<input
|
||||
type="password"
|
||||
name={@name}
|
||||
id={@id || @name}
|
||||
value={Phoenix.HTML.Form.normalize_value("text", @value)}
|
||||
class={["input pr-8", @class]}
|
||||
class={[input_classes(), "pr-8", @class]}
|
||||
{@rest}
|
||||
/>
|
||||
</.with_password_toggle>
|
||||
<div class="flex items-center absolute inset-y-0 right-1">
|
||||
<.icon_button
|
||||
data-show
|
||||
type="button"
|
||||
aria-label="show password"
|
||||
tabindex="-1"
|
||||
phx-click={
|
||||
JS.set_attribute({"type", "text"}, to: "##{@id}-toggle input")
|
||||
|> JS.add_class("hidden", to: "##{@id}-toggle [data-show]")
|
||||
|> JS.remove_class("hidden", to: "##{@id}-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-line" />
|
||||
</.icon_button>
|
||||
<.icon_button
|
||||
class="hidden"
|
||||
data-hide
|
||||
type="button"
|
||||
aria-label="hide password"
|
||||
tabindex="-1"
|
||||
phx-click={
|
||||
JS.set_attribute({"type", "password"}, to: "##{@id}-toggle input")
|
||||
|> JS.remove_class("hidden", to: "##{@id}-toggle [data-show]")
|
||||
|> JS.add_class("hidden", to: "##{@id}-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-off-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
</.field_wrapper>
|
||||
"""
|
||||
end
|
||||
|
@ -149,14 +184,16 @@ defmodule LivebookWeb.FormComponents do
|
|||
name={@name}
|
||||
id={@id || @name}
|
||||
value={@value}
|
||||
class="input"
|
||||
class={input_classes()}
|
||||
spellcheck="false"
|
||||
maxlength="7"
|
||||
{@rest}
|
||||
/>
|
||||
<button class="icon-button absolute right-2 top-1" type="button" phx-click={@randomize}>
|
||||
<.remix_icon icon="refresh-line" class="text-xl" />
|
||||
</button>
|
||||
<div class="absolute right-2 top-1">
|
||||
<.icon_button type="button" phx-click={@randomize}>
|
||||
<.remix_icon icon="refresh-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</.field_wrapper>
|
||||
|
@ -528,63 +565,6 @@ defmodule LivebookWeb.FormComponents do
|
|||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a wrapper around password input with an added visibility
|
||||
toggle button.
|
||||
|
||||
The toggle switches the input's type between `password` and `text`.
|
||||
|
||||
## Examples
|
||||
|
||||
<.with_password_toggle id="secret-password-toggle">
|
||||
<input type="password" ...>
|
||||
</.with_password_toggle>
|
||||
|
||||
"""
|
||||
attr :id, :string, required: true
|
||||
|
||||
slot :inner_block, required: true
|
||||
|
||||
def with_password_toggle(assigns) do
|
||||
~H"""
|
||||
<div id={@id} class="relative flex">
|
||||
<%= render_slot(@inner_block) %>
|
||||
<div class="flex items-center absolute inset-y-0 right-1">
|
||||
<button
|
||||
class="icon-button"
|
||||
data-show
|
||||
type="button"
|
||||
aria-label="show password"
|
||||
tabindex="-1"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "##{@id} input")
|
||||
|> JS.set_attribute({"type", "text"}, to: "##{@id} input")
|
||||
|> JS.add_class("hidden", to: "##{@id} [data-show]")
|
||||
|> JS.remove_class("hidden", to: "##{@id} [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-line" class="text-xl" />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button hidden"
|
||||
data-hide
|
||||
type="button"
|
||||
aria-label="hide password"
|
||||
tabindex="-1"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "##{@id} input")
|
||||
|> JS.set_attribute({"type", "password"}, to: "##{@id} input")
|
||||
|> JS.remove_class("hidden", to: "##{@id} [data-show]")
|
||||
|> JS.add_class("hidden", to: "##{@id} [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-off-line" class="text-xl" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a drag-and-drop area for the given upload.
|
||||
|
||||
|
|
|
@ -42,10 +42,9 @@ defmodule LivebookWeb.AppAuthLive do
|
|||
<div class="text-2xl text-gray-800 w-full pt-2">
|
||||
<form class="flex flex-col space-y-4 items-center" phx-submit="authenticate">
|
||||
<div phx-feedback-for="password" class={["w-[20ch]", @errors != [] && "show-errors"]}>
|
||||
<input
|
||||
<.text_field
|
||||
type="password"
|
||||
name="password"
|
||||
class="input"
|
||||
value={@password}
|
||||
placeholder="Password"
|
||||
autofocus
|
||||
|
@ -57,9 +56,9 @@ defmodule LivebookWeb.AppAuthLive do
|
|||
<%= translate_error(error) %>
|
||||
</span>
|
||||
</div>
|
||||
<button type="submit" class="button-base button-blue">
|
||||
<.button type="submit">
|
||||
Authenticate
|
||||
</button>
|
||||
</.button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -62,10 +62,10 @@ defmodule LivebookWeb.AppLive do
|
|||
<% end %>
|
||||
</p>
|
||||
<div class="flex justify-end">
|
||||
<.link class="button-base button-outlined-blue" patch={~p"/apps/#{@app.slug}/new"}>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1" />
|
||||
<.button outlined patch={~p"/apps/#{@app.slug}/new"}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>New session</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
<div :if={@app_settings.show_existing_sessions} class="w-full flex flex-col space-y-4">
|
||||
<.link
|
||||
|
|
|
@ -172,13 +172,10 @@ defmodule LivebookWeb.AppSessionLive do
|
|||
</.link>
|
||||
</span>
|
||||
<button
|
||||
class={[
|
||||
"button-base bg-transparent",
|
||||
"border-red-400 text-red-400 hover:bg-red-50 focus:bg-red-50"
|
||||
]}
|
||||
class="px-5 py-2 font-medium text-sm inline-flex rounded-lg border whitespace-nowrap items-center justify-center gap-1 border-red-400 text-red-400 hover:bg-red-50 focus:bg-red-50"
|
||||
phx-click="queue_errored_cells_evaluation"
|
||||
>
|
||||
<.remix_icon icon="play-circle-fill" class="align-middle mr-1" />
|
||||
<.remix_icon icon="play-circle-fill" />
|
||||
<span>Retry</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -201,9 +198,9 @@ defmodule LivebookWeb.AppSessionLive do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<button phx-click="queue_full_evaluation" class="icon-button">
|
||||
<.remix_icon icon="play-circle-fill" class="text-3xl" />
|
||||
</button>
|
||||
<.icon_button phx-click="queue_full_evaluation">
|
||||
<.remix_icon icon="play-circle-fill" class="text-3xl leading-none" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<.app_status_circle status={@data_view.app_status} />
|
||||
</div>
|
||||
|
|
|
@ -45,13 +45,12 @@ defmodule LivebookWeb.AppSessionLive.SourceComponent do
|
|||
</span>
|
||||
<div class="flex justify-end space-x-2">
|
||||
<span class="tooltip left" data-tooltip="Copy source">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="copy source"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "#export-notebook-source")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -98,13 +98,12 @@ defmodule LivebookWeb.AppsDashboardLive do
|
|||
</div>
|
||||
<div class="flex flex-col md:flex-row md:items-center justify-start lg:justify-end">
|
||||
<span class="tooltip top" data-tooltip="Terminate">
|
||||
<button
|
||||
class="icon-button text-right"
|
||||
<.icon_button
|
||||
aria-label="terminate app"
|
||||
phx-click={JS.push("terminate_app", value: %{slug: app.slug})}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -135,30 +134,22 @@ defmodule LivebookWeb.AppsDashboardLive do
|
|||
</:col>
|
||||
<:actions :let={app_session}>
|
||||
<span class="tooltip left" data-tooltip="Open">
|
||||
<a
|
||||
class={[
|
||||
"icon-button",
|
||||
app_session.app_status.lifecycle != :active && "disabled"
|
||||
]}
|
||||
<.icon_button
|
||||
disabled={app_session.app_status.lifecycle}
|
||||
aria-label="open app"
|
||||
href={~p"/apps/#{app.slug}/#{app_session.id}"}
|
||||
>
|
||||
<.remix_icon icon="link" class="text-lg" />
|
||||
</a>
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span class="tooltip left" data-tooltip="Debug">
|
||||
<a
|
||||
class="icon-button"
|
||||
aria-label="debug app"
|
||||
href={~p"/sessions/#{app_session.id}"}
|
||||
>
|
||||
<.remix_icon icon="terminal-line" class="text-lg" />
|
||||
</a>
|
||||
<.icon_button aria-label="debug app" href={~p"/sessions/#{app_session.id}"}>
|
||||
<.remix_icon icon="terminal-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<%= if app_session.app_status.lifecycle == :active do %>
|
||||
<span class="tooltip left" data-tooltip="Deactivate">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="deactivate app session"
|
||||
phx-click={
|
||||
JS.push("deactivate_app_session",
|
||||
|
@ -166,13 +157,12 @@ defmodule LivebookWeb.AppsDashboardLive do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="stop-circle-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="stop-circle-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="tooltip left" data-tooltip="Terminate">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="terminate app session"
|
||||
phx-click={
|
||||
JS.push("terminate_app_session",
|
||||
|
@ -180,8 +170,8 @@ defmodule LivebookWeb.AppsDashboardLive do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% end %>
|
||||
</:actions>
|
||||
|
|
|
@ -106,12 +106,10 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
phx-nosubmit={!@submit_event}
|
||||
phx-target={@myself}
|
||||
>
|
||||
<input
|
||||
class="input"
|
||||
<.text_field
|
||||
id={"#{@id}-input-path"}
|
||||
aria-label="file path"
|
||||
phx-hook="FocusOnUpdate"
|
||||
type="text"
|
||||
name="path"
|
||||
placeholder="File"
|
||||
value={@file.path}
|
||||
|
@ -126,9 +124,9 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
position={:bottom_right}
|
||||
>
|
||||
<:toggle>
|
||||
<button class="icon-button" tabindex="-1" aria-label="add">
|
||||
<.remix_icon icon="add-line" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button tabindex="-1" aria-label="add">
|
||||
<.remix_icon icon="add-line" />
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<button role="menuitem" phx-click={js_show_new_item_section("#{@id}-new-dir-section")}>
|
||||
|
@ -215,6 +213,20 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
aria-labelledby="import-from-file"
|
||||
/>
|
||||
|
||||
<div
|
||||
:if={@uploads.folder.entries != []}
|
||||
class="border-b border-dashed border-grey-200 mb-2 pb-2"
|
||||
>
|
||||
<div :for={file <- @uploads.folder.entries} class="p-2 flex gap-2 items-center">
|
||||
<.spinner />
|
||||
<span class="font-medium text-gray-500"><%= file.client_name %></span>
|
||||
<div class="grow" />
|
||||
<.icon_button type="button" phx-click="clear-file" phx-target={@myself} tabindex="-1">
|
||||
<.remix_icon icon="close-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:if={any_highlighted?(@file_infos)}
|
||||
class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2 border-b border-dashed border-grey-200 mb-2 pb-2"
|
||||
|
@ -240,18 +252,6 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
renamed_name={@renamed_name}
|
||||
/>
|
||||
<% end %>
|
||||
<div :for={file <- @uploads.folder.entries} class="flex items-center justify-between">
|
||||
<span class="font-medium text-gray-400"><%= file.client_name %></span>
|
||||
<button
|
||||
type="button"
|
||||
class="icon-button"
|
||||
phx-click="clear-file"
|
||||
phx-target={@myself}
|
||||
tabindex="-1"
|
||||
>
|
||||
<.remix_icon icon="close-line" class="text-xl text-gray-300 hover:text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -297,9 +297,10 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
~H"""
|
||||
<.menu id={@id} disabled={@file_system_select_disabled} position={:bottom_left}>
|
||||
<:toggle>
|
||||
<button
|
||||
<.button
|
||||
color="gray"
|
||||
type="button"
|
||||
class="button-base button-gray pl-3 pr-2"
|
||||
class="pl-3 pr-2"
|
||||
aria-label="switch file storage"
|
||||
disabled={@file_system_select_disabled}
|
||||
>
|
||||
|
@ -307,7 +308,7 @@ defmodule LivebookWeb.FileSelectComponent do
|
|||
<div class="pl-0.5 flex items-center">
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-lg leading-none" />
|
||||
</div>
|
||||
</button>
|
||||
</.button>
|
||||
</:toggle>
|
||||
<%= for file_system <- @file_systems do %>
|
||||
<%= if file_system.id == @file.file_system_id do %>
|
||||
|
|
|
@ -45,16 +45,13 @@ defmodule LivebookWeb.HomeLive do
|
|||
>
|
||||
<:topbar_action>
|
||||
<div class="flex space-x-2">
|
||||
<.link
|
||||
navigate={~p"/open/storage"}
|
||||
class="button-base button-outlined-gray whitespace-nowrap"
|
||||
>
|
||||
<.button color="gray" outlined navigate={~p"/open/storage"}>
|
||||
Open
|
||||
</.link>
|
||||
<.link class="button-base button-blue" patch={~p"/new"}>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1" />
|
||||
</.button>
|
||||
<.button color="blue" patch={~p"/new"}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>New notebook</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</:topbar_action>
|
||||
|
||||
|
@ -65,16 +62,13 @@ defmodule LivebookWeb.HomeLive do
|
|||
<div class="flex flex-row space-y-0 items-center pb-4 justify-between">
|
||||
<LayoutComponents.title text="Home" />
|
||||
<div class="hidden md:flex space-x-2" role="navigation" aria-label="new notebook">
|
||||
<.link
|
||||
navigate={~p"/open/storage"}
|
||||
class="button-base button-outlined-gray whitespace-nowrap"
|
||||
>
|
||||
<.button color="gray" outlined navigate={~p"/open/storage"}>
|
||||
Open
|
||||
</.link>
|
||||
<.link class="button-base button-blue" patch={~p"/new"}>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1" />
|
||||
</.button>
|
||||
<.button color="blue" patch={~p"/new"}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>New notebook</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -37,44 +37,47 @@ defmodule LivebookWeb.HomeLive.SessionListComponent do
|
|||
~H"""
|
||||
<form id="bulk-action-form" phx-submit="bulk_action" phx-target={@myself}>
|
||||
<div class="mb-4 flex items-center md:items-end justify-between">
|
||||
<div class="flex flex-row">
|
||||
<h2 class="uppercase font-semibold text-gray-500 text-sm md:text-base">
|
||||
Running sessions (<%= length(@sessions) %>)
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex flex-row">
|
||||
<.memory_info memory={@memory} />
|
||||
<%= if @sessions != [] do %>
|
||||
<.edit_sessions sessions={@sessions} />
|
||||
<% end %>
|
||||
<.menu id="sessions-order-menu">
|
||||
<:toggle>
|
||||
<button
|
||||
class="w-28 button-base button-outlined-gray px-4 py-1 flex justify-between items-center"
|
||||
type="button"
|
||||
aria-label={"order by - currently ordered by #{order_by_label(@order_by)}"}
|
||||
>
|
||||
<span><%= order_by_label(@order_by) %></span>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-lg leading-none align-middle ml-1" />
|
||||
</button>
|
||||
</:toggle>
|
||||
<.menu_item :for={order_by <- ["date", "title", "memory"]}>
|
||||
<button
|
||||
class={
|
||||
<h2 class="uppercase font-semibold text-gray-500 text-sm md:text-base">
|
||||
Running sessions (<%= length(@sessions) %>)
|
||||
</h2>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex gap-2 w-48 justify-end">
|
||||
<%= if @sessions != [] do %>
|
||||
<.edit_sessions sessions={@sessions} />
|
||||
<% end %>
|
||||
<.menu id="sessions-order-menu">
|
||||
<:toggle>
|
||||
<.button
|
||||
color="gray"
|
||||
outlined
|
||||
small
|
||||
type="button"
|
||||
aria-label={"order by - currently ordered by #{order_by_label(@order_by)}"}
|
||||
>
|
||||
<span><%= order_by_label(@order_by) %></span>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-base leading-none" />
|
||||
</.button>
|
||||
</:toggle>
|
||||
<.menu_item :for={order_by <- ["date", "title", "memory"]}>
|
||||
<button
|
||||
class={
|
||||
"#{if order_by == @order_by, do: "text-gray-900", else: "text-gray-500"}"
|
||||
}
|
||||
type="button"
|
||||
role="menuitem"
|
||||
phx-click={
|
||||
JS.push("set_order", value: %{order_by: order_by}, target: @myself)
|
||||
|> sr_message("ordered by #{order_by}")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon={order_by_icon(order_by)} />
|
||||
<span><%= order_by_label(order_by) %></span>
|
||||
</button>
|
||||
</.menu_item>
|
||||
</.menu>
|
||||
type="button"
|
||||
role="menuitem"
|
||||
phx-click={
|
||||
JS.push("set_order", value: %{order_by: order_by}, target: @myself)
|
||||
|> sr_message("ordered by #{order_by}")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon={order_by_icon(order_by)} />
|
||||
<span><%= order_by_label(order_by) %></span>
|
||||
</button>
|
||||
</.menu_item>
|
||||
</.menu>
|
||||
</div>
|
||||
<div class="border-r border-gray-300 h-5" />
|
||||
<.memory_info memory={@memory} />
|
||||
</div>
|
||||
</div>
|
||||
<.session_list
|
||||
|
@ -147,9 +150,9 @@ defmodule LivebookWeb.HomeLive.SessionListComponent do
|
|||
</div>
|
||||
<.menu id={"session-#{session.id}-menu"}>
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="open session menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="open session menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" />
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<a
|
||||
|
@ -216,7 +219,7 @@ defmodule LivebookWeb.HomeLive.SessionListComponent do
|
|||
assigns = assign(assigns, free: free, used: used, total: total, percentage: percentage)
|
||||
|
||||
~H"""
|
||||
<div class="pr-1 lg:pr-4" role="group" aria-label="memory information">
|
||||
<div role="group" aria-label="memory information">
|
||||
<span class="tooltip top" data-tooltip={"#{format_bytes(@free)} available"}>
|
||||
<svg viewbox="-10 5 50 25" width="30" height="30" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle
|
||||
|
@ -250,31 +253,25 @@ defmodule LivebookWeb.HomeLive.SessionListComponent do
|
|||
|
||||
defp edit_sessions(assigns) do
|
||||
~H"""
|
||||
<div
|
||||
class="mx-4 mr-2 text-gray-600 flex flex-row gap-1"
|
||||
role="group"
|
||||
aria-label="bulk actions for sessions"
|
||||
>
|
||||
<div class="text-gray-600 flex flex-row gap-1" role="group" aria-label="bulk actions for sessions">
|
||||
<.menu id="edit-sessions">
|
||||
<:toggle>
|
||||
<button
|
||||
<.button
|
||||
id="toggle-edit"
|
||||
class="w-28 button-base button-outlined-gray px-4 pl-2 py-1"
|
||||
color="gray"
|
||||
outlined
|
||||
small
|
||||
phx-click={toggle_edit(:on)}
|
||||
type="button"
|
||||
aria-label="toggle edit"
|
||||
>
|
||||
<.remix_icon icon="list-check-2" class="text-lg leading-none align-middle ml-1" />
|
||||
<.remix_icon icon="list-check-2" class="text-base leading-none" />
|
||||
<span>Edit</span>
|
||||
</button>
|
||||
<button
|
||||
class="hidden w-28 button-base button-outlined-gray px-4 py-1 flex justify-between items-center"
|
||||
data-el-bulk-edit-member
|
||||
type="button"
|
||||
>
|
||||
</.button>
|
||||
<.button color="gray" outlined small class="hidden" data-el-bulk-edit-member type="button">
|
||||
<span>Actions</span>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-lg leading-none align-middle ml-1" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-base leading-none" />
|
||||
</.button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<button class="text-gray-600" phx-click={toggle_edit(:off)} type="button">
|
||||
|
|
|
@ -73,14 +73,9 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
|
|||
<.emoji_field field={f[:hub_emoji]} label="Emoji" />
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
phx-disable-with="Updating..."
|
||||
disabled={not @changeset.valid?}
|
||||
>
|
||||
<.button type="submit" phx-disable-with="Updating..." disabled={not @changeset.valid?}>
|
||||
Save
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
@ -149,32 +144,32 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
|
|||
phx-change="stamp_validate"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<div class="flex space-x-2">
|
||||
<div class="flex space-x-2 items-center">
|
||||
<div class="grow">
|
||||
<.password_field field={f[:secret_key]} label="Secret key" />
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<span class="tooltip top" data-tooltip="Generate">
|
||||
<button
|
||||
class="button-base button-outlined-gray button-square-icon"
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
type="button"
|
||||
phx-click="generate_secret_key"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="refresh-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="refresh-line" class="text-xl leading-none py-1" />
|
||||
</.button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
type="submit"
|
||||
phx-disable-with="Updating..."
|
||||
disabled={not @stamp_changeset.valid?}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -135,9 +135,9 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<button class="button-base button-blue" type="submit" phx-disable-with="Updating...">
|
||||
<.button type="submit" phx-disable-with="Updating...">
|
||||
Save
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
@ -218,14 +218,15 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
This only removes the hub from this machine. You must rejoin to access its features once again.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
<.button
|
||||
color="red"
|
||||
outlined
|
||||
id="delete-hub"
|
||||
phx-click={JS.push("delete_hub", value: %{id: @hub.id})}
|
||||
class="button-base button-outlined-red"
|
||||
>
|
||||
<span class="hidden sm:block">Delete hub</span>
|
||||
<.remix_icon icon="delete-bin-line" class="text-lg sm:hidden" />
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -292,64 +293,27 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
required for you and invited users to join this organization.
|
||||
We recommend storing it somewhere safe:
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<div id="teams-key-toggle" class="relative flex">
|
||||
<input
|
||||
type="password"
|
||||
id="teams-key"
|
||||
readonly
|
||||
value={@teams_key}
|
||||
class="input font-mono w-full border-neutral-200 bg-neutral-100 py-2 border-2 pr-8"
|
||||
/>
|
||||
|
||||
<div class="flex items-center absolute inset-y-0 right-1">
|
||||
<button
|
||||
class="icon-button"
|
||||
data-tooltip="Copied to clipboard"
|
||||
type="button"
|
||||
aria-label="copy to clipboard"
|
||||
phx-click={
|
||||
JS.dispatch("lb:clipcopy", to: "#teams-key")
|
||||
|> JS.add_class("", transition: {"tooltip top", "", ""}, time: 2000)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-xl" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="icon-button"
|
||||
data-show
|
||||
type="button"
|
||||
aria-label="show password"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "#teams-key-toggle input")
|
||||
|> JS.set_attribute({"type", "text"}, to: "#teams-key-toggle input")
|
||||
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|
||||
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-line" class="text-xl" />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button hidden"
|
||||
data-hide
|
||||
type="button"
|
||||
aria-label="hide password"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "#teams-key-toggle input")
|
||||
|> JS.set_attribute({"type", "password"}, to: "#teams-key-toggle input")
|
||||
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|
||||
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-off-line" class="text-xl" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<div class="grow">
|
||||
<.password_field id="teams-key" name="teams_key" value={@teams_key} readonly />
|
||||
</div>
|
||||
|
||||
<span
|
||||
data-tooltip="Copied to clipboard"
|
||||
aria-label="copy to clipboard"
|
||||
phx-click={
|
||||
JS.dispatch("lb:clipcopy", to: "#teams-key")
|
||||
|> JS.add_class("", transition: {"tooltip left", "", ""}, time: 2000)
|
||||
}
|
||||
>
|
||||
<.button color="gray" small type="button">
|
||||
<.remix_icon icon="clipboard-line" class="text-xl leading-none py-1" />
|
||||
</.button>
|
||||
</span>
|
||||
</div>
|
||||
<.link :if={@confirm_url} patch={@confirm_url} class="button-base button-blue block text-center">
|
||||
<.remix_icon class="mr-2" icon="thumb-up-fill" /> I've saved my Teams key in a secure location
|
||||
</.link>
|
||||
<.button :if={@confirm_url} patch={@confirm_url}>
|
||||
<.remix_icon class="mr-1" icon="thumb-up-fill" /> I've saved my Teams key in a secure location
|
||||
</.button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule LivebookWeb.Hub.FileSystemFormComponent do
|
|||
{file_system, assigns} = Map.pop!(assigns, :file_system)
|
||||
|
||||
mode = mode(file_system)
|
||||
button = button(file_system)
|
||||
button = button_attrs(file_system)
|
||||
title = title(file_system)
|
||||
|
||||
file_system = file_system || %FileSystem.S3{hub_id: assigns.hub.id}
|
||||
|
@ -83,13 +83,13 @@ defmodule LivebookWeb.Hub.FileSystemFormComponent do
|
|||
</p>
|
||||
<% end %>
|
||||
<div class="flex space-x-2">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} class="align-middle mr-1" />
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} />
|
||||
<span class="font-normal"><%= @button.label %></span>
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</.form>
|
||||
|
@ -160,6 +160,6 @@ defmodule LivebookWeb.Hub.FileSystemFormComponent do
|
|||
defp title(nil), do: "Add file storage"
|
||||
defp title(_), do: "Edit file storage"
|
||||
|
||||
defp button(nil), do: %{icon: "add-line", label: "Add"}
|
||||
defp button(_), do: %{icon: "save-line", label: "Save"}
|
||||
defp button_attrs(nil), do: %{icon: "add-line", label: "Add"}
|
||||
defp button_attrs(_), do: %{icon: "save-line", label: "Save"}
|
||||
end
|
||||
|
|
|
@ -23,9 +23,9 @@ defmodule LivebookWeb.Hub.FileSystemListComponent do
|
|||
<div class="flex items-center space-x-2">
|
||||
<.menu id={"hub-file-system-#{file_system.id}-menu"}>
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="open file system menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="open file system menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" />
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<.link
|
||||
|
@ -60,13 +60,9 @@ defmodule LivebookWeb.Hub.FileSystemListComponent do
|
|||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<.link
|
||||
patch={~p"/hub/#{@hub_id}/file-systems/new"}
|
||||
class="button-base button-blue"
|
||||
id="add-file-system"
|
||||
>
|
||||
<.button patch={~p"/hub/#{@hub_id}/file-systems/new"} id="add-file-system">
|
||||
Add file storage
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -105,13 +105,11 @@ defmodule LivebookWeb.Hub.NewLive do
|
|||
label="Livebook Teams key"
|
||||
/>
|
||||
|
||||
<button
|
||||
:if={!@requested_code}
|
||||
class="button-base button-blue self-start"
|
||||
phx-disable-with="Loading..."
|
||||
>
|
||||
<%= @button_label %>
|
||||
</button>
|
||||
<div>
|
||||
<.button :if={!@requested_code} phx-disable-with="Loading...">
|
||||
<%= @button_label %>
|
||||
</.button>
|
||||
</div>
|
||||
<div class="invisible"></div>
|
||||
<div :if={@requested_code} class="flex flex-col rounded-xl bg-gray-50 px-10 py-6 mt-10">
|
||||
<div class="flex flex-col items-center rounded-xl bg-gray-50">
|
||||
|
@ -130,14 +128,10 @@ defmodule LivebookWeb.Hub.NewLive do
|
|||
<span class="text-sm">
|
||||
2. Sign in to Livebook Teams and paste the code:
|
||||
</span>
|
||||
<div>
|
||||
<a
|
||||
href={@verification_uri}
|
||||
target="_blank"
|
||||
class="mt-3 button-base button-outlined-gray"
|
||||
>
|
||||
<div class="mt-2">
|
||||
<.button color="gray" outlined href={@verification_uri} target="_blank">
|
||||
Go to Teams
|
||||
</a>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -155,23 +149,19 @@ defmodule LivebookWeb.Hub.NewLive do
|
|||
id="clipboard"
|
||||
class="flex items-center justify-between border rounded-lg px-4 py-2.5 bg-white"
|
||||
>
|
||||
<div class="icon-button invisible">
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</div>
|
||||
<.icon_button class="invisible">
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
|
||||
<div
|
||||
class="text-brand-pink font-semibold text-xl leading-none"
|
||||
class="mr-4 text-brand-pink font-semibold text-xl leading-none"
|
||||
id="clipboard-code"
|
||||
phx-no-format
|
||||
><%= @content %></div>
|
||||
|
||||
<button
|
||||
class="icon-button ml-4"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "#clipboard-code")}
|
||||
type="button"
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg text-blue-500" />
|
||||
</button>
|
||||
<.icon_button phx-click={JS.dispatch("lb:clipcopy", to: "#clipboard-code")} type="button">
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
|
|||
{:ok,
|
||||
assign(socket,
|
||||
title: title(socket),
|
||||
button: button(socket),
|
||||
button: button_attrs(socket),
|
||||
changeset: changeset,
|
||||
deployment_group_id: assigns[:deployment_group_id],
|
||||
error_message: nil
|
||||
|
@ -69,13 +69,13 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
|
|||
<.hidden_field field={f[:hub_id]} value={@hub.id} />
|
||||
<.hidden_field field={f[:deployment_group_id]} value={@deployment_group_id} />
|
||||
<div class="flex space-x-2">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} class="align-middle mr-1" />
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} />
|
||||
<span class="font-normal"><%= @button.label %></span>
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</.form>
|
||||
|
@ -118,8 +118,8 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
|
|||
defp title(%{assigns: %{secret_name: nil}}), do: "Add secret"
|
||||
defp title(_), do: "Edit secret"
|
||||
|
||||
defp button(%{assigns: %{secret_name: nil}}), do: %{icon: "add-line", label: "Add"}
|
||||
defp button(_), do: %{icon: "save-line", label: "Save"}
|
||||
defp button_attrs(%{assigns: %{secret_name: nil}}), do: %{icon: "add-line", label: "Add"}
|
||||
defp button_attrs(_), do: %{icon: "save-line", label: "Save"}
|
||||
|
||||
defp set_secret(%{assigns: %{secret_name: nil}} = socket, %Secret{} = secret) do
|
||||
Hubs.create_secret(socket.assigns.hub, secret)
|
||||
|
|
|
@ -23,20 +23,19 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
<:col :let={secret} label="Name"><%= secret.name %></:col>
|
||||
<:action :let={secret}>
|
||||
<span class="tooltip left" data-tooltip="Edit">
|
||||
<.link
|
||||
<.icon_button
|
||||
id={"hub-secret-#{secret.name}-edit"}
|
||||
patch={"/#{@edit_path}/#{secret.name}"}
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="edit-fill" class="text-lg" />
|
||||
</.link>
|
||||
<.remix_icon icon="edit-fill" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</:action>
|
||||
<:action :let={secret}>
|
||||
<span class="tooltip left" data-tooltip="Delete">
|
||||
<button
|
||||
<.icon_button
|
||||
id={"hub-secret-#{secret.name}-delete"}
|
||||
type="button"
|
||||
phx-click={
|
||||
|
@ -52,19 +51,18 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
)
|
||||
}
|
||||
role="menuitem"
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</:action>
|
||||
</.table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<.link patch={@add_path} class="button-base button-blue" id="add-secret">
|
||||
<.button patch={@add_path} id="add-secret">
|
||||
Add secret
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -11,95 +11,52 @@ defmodule LivebookWeb.Hub.Teams.AgentKeyListComponent do
|
|||
<.no_entries :if={@agent_keys == []}>
|
||||
No agent keys in this deployment group yet.
|
||||
</.no_entries>
|
||||
<div
|
||||
:for={agent_key <- @agent_keys}
|
||||
class="flex items-center justify-between border border-gray-200 rounded-lg p-4"
|
||||
>
|
||||
<div class="flex items-center space-x-12">
|
||||
<.labeled_text label="ID">
|
||||
<div class="flex h-[40px] items-center text-center">
|
||||
<%= agent_key.id %>
|
||||
</div>
|
||||
</.labeled_text>
|
||||
|
||||
<.labeled_text label="Key">
|
||||
<div id="agent-key-toggle" class="relative lg:w-[480px] w-full">
|
||||
<input
|
||||
type="password"
|
||||
id="agent-key"
|
||||
readonly
|
||||
value={agent_key.key}
|
||||
class="input font-mono w-full border-neutral-200 bg-neutral-100 py-2 border-2 pr-8"
|
||||
/>
|
||||
|
||||
<div class="flex items-center absolute inset-y-0 right-1">
|
||||
<button
|
||||
class="icon-button"
|
||||
data-tooltip="Copied to clipboard"
|
||||
type="button"
|
||||
aria-label="copy to clipboard"
|
||||
phx-click={
|
||||
JS.dispatch("lb:clipcopy", to: "#agent-key")
|
||||
|> JS.add_class("", transition: {"tooltip top", "", ""}, time: 2000)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-xl" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="icon-button"
|
||||
data-show
|
||||
type="button"
|
||||
aria-label="show password"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "#agent-key-toggle input")
|
||||
|> JS.set_attribute({"type", "text"}, to: "#agent-key-toggle input")
|
||||
|> toggle_class("hidden", to: "#agent-key-toggle [data-show]")
|
||||
|> toggle_class("hidden", to: "#agent-key-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-line" class="text-xl" />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button hidden"
|
||||
data-hide
|
||||
type="button"
|
||||
aria-label="hide password"
|
||||
phx-click={
|
||||
JS.remove_attribute("type", to: "#agent-key-toggle input")
|
||||
|> JS.set_attribute({"type", "password"}, to: "#agent-key-toggle input")
|
||||
|> toggle_class("hidden", to: "#agent-key-toggle [data-show]")
|
||||
|> toggle_class("hidden", to: "#agent-key-toggle [data-hide]")
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="eye-off-line" class="text-xl" />
|
||||
</button>
|
||||
<div :if={@agent_keys != []}>
|
||||
<.table id="hub-agent-keys-table" rows={@agent_keys}>
|
||||
<:col :let={agent_key} label="ID"><%= agent_key.id %></:col>
|
||||
<:col :let={agent_key} label="Key">
|
||||
<div class="flex flex-nowrap gap-2">
|
||||
<div class="grow">
|
||||
<.password_field
|
||||
id={"agent-key-#{agent_key.id}"}
|
||||
name="agent_key"
|
||||
value={agent_key.key}
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span
|
||||
data-tooltip="Copied to clipboard"
|
||||
aria-label="copy to clipboard"
|
||||
phx-click={
|
||||
JS.dispatch("lb:clipcopy", to: "#agent-key-#{agent_key.id}")
|
||||
|> JS.add_class("", transition: {"tooltip left", "", ""}, time: 2000)
|
||||
}
|
||||
>
|
||||
<.button color="gray" small type="button">
|
||||
<.remix_icon icon="clipboard-line" class="text-xl leading-none py-1" />
|
||||
</.button>
|
||||
</span>
|
||||
</div>
|
||||
</.labeled_text>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<.menu id={"hub-agent-key-#{agent_key.id}-menu"}>
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="open deployment group menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||
</button>
|
||||
</:toggle>
|
||||
<.menu_item variant={:danger}>
|
||||
<button
|
||||
</:col>
|
||||
<:action :let={agent_key}>
|
||||
<span class="tooltip left" data-tooltip="Delete">
|
||||
<.icon_button
|
||||
id={"hub-agent-key-#{agent_key.id}-delete"}
|
||||
type="button"
|
||||
phx-click={
|
||||
JS.push("delete_agent_key",
|
||||
value: %{id: agent_key.id},
|
||||
target: @myself
|
||||
)
|
||||
}
|
||||
role="menuitem"
|
||||
class="text-red-600"
|
||||
phx-click={JS.push("delete_agent_key", value: %{id: agent_key.id})}
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-line" />
|
||||
<span>Delete</span>
|
||||
</button>
|
||||
</.menu_item>
|
||||
</.menu>
|
||||
</div>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</:action>
|
||||
</.table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
changeset: changeset,
|
||||
mode: mode(deployment_group),
|
||||
title: title(deployment_group),
|
||||
button: button(deployment_group),
|
||||
button: button_attrs(deployment_group),
|
||||
subtitle: subtitle(deployment_group, hub.hub_name),
|
||||
error_message: nil
|
||||
)}
|
||||
|
@ -72,14 +72,14 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
/>
|
||||
<LivebookWeb.AppComponents.deployment_group_form_content hub={@hub} form={f} />
|
||||
<div class="flex space-x-2">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} class="align-middle mr-1" />
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} />
|
||||
<span class="font-normal"><%= @button.label %></span>
|
||||
</button>
|
||||
</.button>
|
||||
<%= if @mode == :new do %>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -145,6 +145,6 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
defp subtitle(%DeploymentGroup{name: deployment_group}, _),
|
||||
do: "Manage the #{deployment_group} deployment group"
|
||||
|
||||
defp button(%DeploymentGroup{name: nil}), do: %{icon: "add-line", label: "Add"}
|
||||
defp button(_), do: %{icon: "save-line", label: "Save"}
|
||||
defp button_attrs(%DeploymentGroup{name: nil}), do: %{icon: "add-line", label: "Add"}
|
||||
defp button_attrs(_), do: %{icon: "save-line", label: "Save"}
|
||||
end
|
||||
|
|
|
@ -22,9 +22,9 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupListComponent do
|
|||
<div class="flex items-center space-x-2">
|
||||
<.menu id={"hub-deployment-group-#{deployment_group.id}-menu"}>
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="open deployment group menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="open deployment group menu" type="button">
|
||||
<.remix_icon icon="more-2-fill" />
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<.link
|
||||
|
@ -59,13 +59,9 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupListComponent do
|
|||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<.link
|
||||
patch={~p"/hub/#{@hub_id}/deployment-groups/new"}
|
||||
class="button-base button-blue"
|
||||
id="add-deployment-group"
|
||||
>
|
||||
<.button patch={~p"/hub/#{@hub_id}/deployment-groups/new"} id="add-deployment-group">
|
||||
Add deployment group
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -141,14 +141,9 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do
|
|||
/>
|
||||
|
||||
<div class="flex">
|
||||
<button
|
||||
id="add-agent-key"
|
||||
type="button"
|
||||
class="button-base button-blue"
|
||||
phx-click="add_agent_key"
|
||||
>
|
||||
<.button id="add-agent-key" type="button" phx-click="add_agent_key">
|
||||
<span>Add agent key</span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -50,12 +50,9 @@ defmodule LivebookWeb.LearnLive do
|
|||
<%= @lead_notebook_info.details.description %>
|
||||
</p>
|
||||
<div class="mt-4">
|
||||
<.link
|
||||
patch={~p"/learn/notebooks/#{@lead_notebook_info.slug}"}
|
||||
class="button-base button-blue"
|
||||
>
|
||||
<.button patch={~p"/learn/notebooks/#{@lead_notebook_info.slug}"}>
|
||||
Open notebook
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -101,12 +98,9 @@ defmodule LivebookWeb.LearnLive do
|
|||
<div class="grow text-gray-800 font-semibold">
|
||||
<%= notebook_info.title %>
|
||||
</div>
|
||||
<.link
|
||||
navigate={~p"/learn/notebooks/#{notebook_info.slug}"}
|
||||
class="button-base button-outlined-gray"
|
||||
>
|
||||
<.remix_icon icon="play-circle-line" class="align-middle mr-1" /> Open
|
||||
</.link>
|
||||
<.button color="gray" outlined navigate={~p"/learn/notebooks/#{notebook_info.slug}"}>
|
||||
<.remix_icon icon="play-circle-line" /> Open
|
||||
</.button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -38,19 +38,19 @@ defmodule LivebookWeb.OpenLive do
|
|||
saved_hubs={@saved_hubs}
|
||||
>
|
||||
<:topbar_action>
|
||||
<.link class="button-base button-blue" navigate={~p"/new"}>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1" />
|
||||
<.button color="blue" navigate={~p"/new"}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>New notebook</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</:topbar_action>
|
||||
<div class="p-4 md:px-12 md:py-6 max-w-screen-lg mx-auto space-y-4">
|
||||
<div class="flex flex-row space-y-0 items-center pb-4 justify-between">
|
||||
<LayoutComponents.title text="Open notebook" back_navigate={~p"/"} />
|
||||
<div class="hidden md:flex" role="navigation" aria-label="new notebook">
|
||||
<.link class="button-base button-blue" navigate={~p"/new"}>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1" />
|
||||
<.button color="blue" navigate={~p"/new"}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>New notebook</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -37,29 +37,29 @@ defmodule LivebookWeb.OpenLive.FileComponent do
|
|||
target={{__MODULE__, @id}}
|
||||
>
|
||||
<div class="flex justify-end space-x-2">
|
||||
<button
|
||||
class="button-base button-outlined-gray whitespace-nowrap"
|
||||
<.button
|
||||
color="gray"
|
||||
outlined
|
||||
phx-click="fork"
|
||||
phx-target={@myself}
|
||||
disabled={not path_forkable?(@file, @file_info)}
|
||||
>
|
||||
<.remix_icon icon="git-branch-line" class="align-middle mr-1" />
|
||||
<.remix_icon icon="git-branch-line" />
|
||||
<span>Fork</span>
|
||||
</button>
|
||||
</.button>
|
||||
<%= if session = session_by_file(@file, @sessions) do %>
|
||||
<.link navigate={~p"/sessions/#{session.id}"} class="button-base button-blue">
|
||||
<.button navigate={~p"/sessions/#{session.id}"}>
|
||||
Join session
|
||||
</.link>
|
||||
</.button>
|
||||
<% else %>
|
||||
<span {open_button_tooltip_attrs(@file, @file_info)}>
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
phx-click="open"
|
||||
phx-target={@myself}
|
||||
disabled={not path_openable?(@file, @file_info, @sessions)}
|
||||
>
|
||||
Open
|
||||
</button>
|
||||
</.button>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -37,15 +37,16 @@ defmodule LivebookWeb.OpenLive.SourceComponent do
|
|||
<.textarea_field
|
||||
field={f[:source]}
|
||||
label="Notebook source"
|
||||
resizable={false}
|
||||
autofocus
|
||||
aria-labelledby="import-from-source"
|
||||
spellcheck="false"
|
||||
rows="5"
|
||||
/>
|
||||
<button class="mt-5 button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
Import
|
||||
</button>
|
||||
<div class="mt-5">
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
Import
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -29,13 +29,11 @@ defmodule LivebookWeb.OpenLive.UploadComponent do
|
|||
You can only upload files with .livemd extension.
|
||||
</div>
|
||||
<% end %>
|
||||
<button
|
||||
type="submit"
|
||||
class="mt-5 button-base button-blue"
|
||||
disabled={@error or upload_disabled?(@uploads.file)}
|
||||
>
|
||||
Import
|
||||
</button>
|
||||
<div class="mt-5">
|
||||
<.button type="submit" disabled={@error or upload_disabled?(@uploads.file)}>
|
||||
Import
|
||||
</.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -58,9 +58,11 @@ defmodule LivebookWeb.OpenLive.UrlComponent do
|
|||
aria-labelledby="import-from-url"
|
||||
spellcheck="false"
|
||||
/>
|
||||
<button class="mt-5 button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
Import
|
||||
</button>
|
||||
<div class="mt-5">
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
Import
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -269,12 +269,9 @@ defmodule LivebookWeb.Output do
|
|||
<.remix_icon icon="close-circle-line" />
|
||||
<span>Missing secret <%= inspect(@secret_name) %></span>
|
||||
</div>
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/secrets?secret_name=#{@secret_name}"}
|
||||
class="button-base button-gray"
|
||||
>
|
||||
<.button color="gray" patch={~p"/sessions/#{@session_id}/secrets?secret_name=#{@secret_name}"}>
|
||||
Add secret
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
<%= render_formatted_error_message(@id, @message) %>
|
||||
</div>
|
||||
|
@ -302,12 +299,12 @@ defmodule LivebookWeb.Output do
|
|||
<.remix_icon icon="close-circle-line" />
|
||||
<span>Forbidden access to file <%= inspect(@file_entry_name) %></span>
|
||||
</div>
|
||||
<button
|
||||
class="button-base button-gray"
|
||||
<.button
|
||||
color="gray"
|
||||
phx-click={JS.push("review_file_entry_access", value: %{name: @file_entry_name})}
|
||||
>
|
||||
Review access
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
<%= render_formatted_error_message(@id, @message) %>
|
||||
</div>
|
||||
|
@ -333,7 +330,7 @@ defmodule LivebookWeb.Output do
|
|||
</div>
|
||||
<button
|
||||
class={[
|
||||
"button-base bg-transparent",
|
||||
"px-5 py-2 font-medium text-sm inline-flex rounded-lg border whitespace-nowrap items-center justify-center gap-1",
|
||||
case @variant do
|
||||
:error -> "border-red-400 text-red-400 hover:bg-red-50 focus:bg-red-50"
|
||||
:normal -> "border-gray-300 text-gray-500 hover:bg-gray-100 focus:bg-gray-100"
|
||||
|
@ -342,7 +339,7 @@ defmodule LivebookWeb.Output do
|
|||
phx-click="queue_interrupted_cell_evaluation"
|
||||
phx-value-cell_id={@cell_id}
|
||||
>
|
||||
<.remix_icon icon="play-circle-fill" class="align-middle mr-1" />
|
||||
<.remix_icon icon="play-circle-fill" />
|
||||
<span>Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -389,12 +386,9 @@ defmodule LivebookWeb.Output do
|
|||
phx-no-format
|
||||
><%= LivebookWeb.ANSIHelpers.ansi_string_to_html(@message) %></div>
|
||||
<div class="absolute right-2 top-0 z-10 invisible group-hover/error:visible">
|
||||
<button
|
||||
class="icon-button bg-gray-100"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "##{@id}-message")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</button>
|
||||
<.icon_button phx-click={JS.dispatch("lb:clipcopy", to: "##{@id}-message")}>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -76,38 +76,26 @@ defmodule LivebookWeb.Output.AudioInputComponent do
|
|||
/>
|
||||
<audio controls data-preview></audio>
|
||||
<div class="flex items-center justify-center gap-4">
|
||||
<button
|
||||
class="button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-record
|
||||
>
|
||||
<.remix_icon icon="mic-line" class="text-lg leading-none mr-2" />
|
||||
<.button color="gray" data-btn-record>
|
||||
<.remix_icon icon="mic-line" />
|
||||
<span>Record</span>
|
||||
</button>
|
||||
<button
|
||||
class="hidden button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500 items-center"
|
||||
data-btn-stop
|
||||
>
|
||||
<span class="mr-2 flex h-3 w-3 relative">
|
||||
</.button>
|
||||
<.button color="gray" class="hidden" data-btn-stop>
|
||||
<span class="flex h-2 w-2 relative">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-gray-400 opacity-75">
|
||||
</span>
|
||||
<span class="relative inline-flex rounded-full h-3 w-3 bg-gray-500"></span>
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-gray-500"></span>
|
||||
</span>
|
||||
<span>Stop recording</span>
|
||||
</button>
|
||||
<button
|
||||
class="hidden button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-cancel
|
||||
>
|
||||
<.remix_icon icon="close-circle-line" class="text-lg leading-none mr-2" />
|
||||
</.button>
|
||||
<.button color="gray" class="hidden" data-btn-cancel>
|
||||
<.remix_icon icon="close-circle-line" />
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
<button
|
||||
class="button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-upload
|
||||
>
|
||||
<.remix_icon icon="upload-2-line" class="text-lg leading-none mr-2" />
|
||||
</.button>
|
||||
<.button color="gray" data-btn-upload>
|
||||
<.remix_icon icon="upload-2-line" />
|
||||
<span>Upload</span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<form phx-change="validate" class="hidden" phx-target={@myself}>
|
||||
|
|
|
@ -20,16 +20,15 @@ defmodule LivebookWeb.Output.ControlComponent do
|
|||
data-p-target={hook_prop(@myself)}
|
||||
>
|
||||
<span class="tooltip right" data-tooltip="Toggle keyboard control">
|
||||
<button
|
||||
class={
|
||||
"button-base #{if @keyboard_enabled, do: "button-blue", else: "button-gray"} button-square-icon"
|
||||
}
|
||||
<.button
|
||||
color={if(@keyboard_enabled, do: "blue", else: "gray")}
|
||||
small
|
||||
type="button"
|
||||
aria-label="toggle keyboard control"
|
||||
phx-click={JS.push("toggle_keyboard", target: @myself)}
|
||||
>
|
||||
<.remix_icon icon="keyboard-line" />
|
||||
</button>
|
||||
<.remix_icon icon="keyboard-line" class="text-xl leading-none py-1" />
|
||||
</.button>
|
||||
</span>
|
||||
</div>
|
||||
"""
|
||||
|
@ -38,13 +37,9 @@ defmodule LivebookWeb.Output.ControlComponent do
|
|||
def render(assigns) when assigns.control.attrs.type == :button do
|
||||
~H"""
|
||||
<div class="flex">
|
||||
<button
|
||||
class="button-base button-gray"
|
||||
type="button"
|
||||
phx-click={JS.push("button_click", target: @myself)}
|
||||
>
|
||||
<.button color="gray" type="button" phx-click={JS.push("button_click", target: @myself)}>
|
||||
<%= @control.attrs.label %>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -47,9 +47,9 @@ defmodule LivebookWeb.Output.ControlFormComponent do
|
|||
local={true}
|
||||
/>
|
||||
<div :if={@control.attrs.submit}>
|
||||
<button class="button-base button-blue" type="button" phx-click="submit" phx-target={@myself}>
|
||||
<.button type="button" phx-click="submit" phx-target={@myself}>
|
||||
<%= @control.attrs.submit %>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -82,13 +82,10 @@ defmodule LivebookWeb.Output.ImageInputComponent do
|
|||
<div class="mt-4 flex items-center justify-center gap-4">
|
||||
<.menu id={"#{@id}-camera-select-menu"} position={:bottom_left}>
|
||||
<:toggle>
|
||||
<button
|
||||
class="button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-open-camera
|
||||
>
|
||||
<.remix_icon icon="camera-line" class="text-lg leading-none mr-2" />
|
||||
<.button color="gray" data-btn-open-camera>
|
||||
<.remix_icon icon="camera-line" />
|
||||
<span>Open camera</span>
|
||||
</button>
|
||||
</.button>
|
||||
</:toggle>
|
||||
<div data-camera-list>
|
||||
<.menu_item>
|
||||
|
@ -98,27 +95,18 @@ defmodule LivebookWeb.Output.ImageInputComponent do
|
|||
</.menu_item>
|
||||
</div>
|
||||
</.menu>
|
||||
<button
|
||||
class="hidden button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-capture-camera
|
||||
>
|
||||
<.remix_icon icon="camera-line" class="text-lg leading-none mr-2" />
|
||||
<.button color="gray" class="hidden" data-btn-capture-camera>
|
||||
<.remix_icon icon="camera-line" />
|
||||
<span>Take photo</span>
|
||||
</button>
|
||||
<button
|
||||
class="hidden button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-cancel
|
||||
>
|
||||
<.remix_icon icon="close-circle-line" class="text-lg leading-none mr-2" />
|
||||
</.button>
|
||||
<.button color="gray" class="hidden" data-btn-cancel>
|
||||
<.remix_icon icon="close-circle-line" />
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
<button
|
||||
class="button-base button-gray border-transparent py-2 px-4 inline-flex text-gray-500"
|
||||
data-btn-upload
|
||||
>
|
||||
<.remix_icon icon="upload-2-line" class="text-lg leading-none mr-2" />
|
||||
</.button>
|
||||
<.button color="gray" data-btn-upload>
|
||||
<.remix_icon icon="upload-2-line" />
|
||||
<span>Upload</span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<form phx-change="validate" class="hidden" phx-target={@myself}>
|
||||
|
|
|
@ -92,20 +92,23 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
changed={@changed}
|
||||
help="Choose the time in your local time zone"
|
||||
/>
|
||||
<input
|
||||
id={@id}
|
||||
type="datetime-local"
|
||||
data-el-input
|
||||
class="input w-auto invalid:input--error"
|
||||
name="html_value"
|
||||
step="60"
|
||||
autocomplete="off"
|
||||
phx-hook="UtcDateTimeInput"
|
||||
data-p-utc-value={hook_prop(@value && NaiveDateTime.to_iso8601(@value))}
|
||||
data-p-utc-min={hook_prop(@input.attrs.min && NaiveDateTime.to_iso8601(@input.attrs.min))}
|
||||
data-p-utc-max={hook_prop(@input.attrs.max && NaiveDateTime.to_iso8601(@input.attrs.max))}
|
||||
data-p-phx-target={hook_prop(@myself)}
|
||||
/>
|
||||
<div class="inline-flex">
|
||||
<.text_field
|
||||
class="w-auto"
|
||||
id={@id}
|
||||
type="datetime-local"
|
||||
data-el-input
|
||||
name="html_value"
|
||||
step="60"
|
||||
autocomplete="off"
|
||||
phx-hook="UtcDateTimeInput"
|
||||
value={nil}
|
||||
data-p-utc-value={hook_prop(@value && NaiveDateTime.to_iso8601(@value))}
|
||||
data-p-utc-min={hook_prop(@input.attrs.min && NaiveDateTime.to_iso8601(@input.attrs.min))}
|
||||
data-p-utc-max={hook_prop(@input.attrs.max && NaiveDateTime.to_iso8601(@input.attrs.max))}
|
||||
data-p-phx-target={hook_prop(@myself)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
@ -118,20 +121,22 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
changed={@changed}
|
||||
help="Choose the time in your local time zone"
|
||||
/>
|
||||
<input
|
||||
id={@id}
|
||||
type="time"
|
||||
data-el-input
|
||||
class="input w-auto invalid:input--error"
|
||||
name="html_value"
|
||||
step="60"
|
||||
autocomplete="off"
|
||||
phx-hook="UtcTimeInput"
|
||||
data-p-utc-value={hook_prop(@value && Time.to_iso8601(@value))}
|
||||
data-p-utc-min={hook_prop(@input.attrs.min && Time.to_iso8601(@input.attrs.min))}
|
||||
data-p-utc-max={hook_prop(@input.attrs.max && Time.to_iso8601(@input.attrs.max))}
|
||||
data-p-phx-target={hook_prop(@myself)}
|
||||
/>
|
||||
<div class="inline-flex">
|
||||
<.text_field
|
||||
id={@id}
|
||||
type="time"
|
||||
data-el-input
|
||||
name="html_value"
|
||||
step="60"
|
||||
autocomplete="off"
|
||||
phx-hook="UtcTimeInput"
|
||||
value={nil}
|
||||
data-p-utc-value={hook_prop(@value && Time.to_iso8601(@value))}
|
||||
data-p-utc-min={hook_prop(@input.attrs.min && Time.to_iso8601(@input.attrs.min))}
|
||||
data-p-utc-max={hook_prop(@input.attrs.max && Time.to_iso8601(@input.attrs.max))}
|
||||
data-p-phx-target={hook_prop(@myself)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
@ -173,7 +178,7 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
<input
|
||||
type="range"
|
||||
data-el-input
|
||||
class="input-range"
|
||||
class="range-input"
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce={@attrs.debounce}
|
||||
|
@ -191,26 +196,27 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
|
||||
defp input_output(%{attrs: %{type: :textarea}} = assigns) do
|
||||
~H"""
|
||||
<textarea
|
||||
<.textarea_field
|
||||
id={@id}
|
||||
class="min-h-[38px] max-h-[300px]"
|
||||
monospace={@attrs.monospace}
|
||||
data-el-input
|
||||
class={["input min-h-[38px] max-h-[300px] tiny-scrollbar", @attrs.monospace && "font-mono"]}
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-hook="TextareaAutosize"
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
><%= [?\n, @value] %></textarea>
|
||||
/>
|
||||
"""
|
||||
end
|
||||
|
||||
defp input_output(%{attrs: %{type: :password}} = assigns) do
|
||||
~H"""
|
||||
<.with_password_toggle id={"#{@id}-password-toggle"}>
|
||||
<input
|
||||
type="password"
|
||||
<div class="inline-flex">
|
||||
<.password_field
|
||||
id={@id}
|
||||
data-el-input
|
||||
class="input w-auto bg-gray-50"
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce={@attrs.debounce}
|
||||
|
@ -218,41 +224,61 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</.with_password_toggle>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp input_output(%{attrs: %{type: :date}} = assigns) do
|
||||
~H"""
|
||||
<input
|
||||
type="date"
|
||||
data-el-input
|
||||
class="input w-auto invalid:input--error"
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce="blur"
|
||||
phx-target={@myself}
|
||||
min={@attrs.min}
|
||||
max={@attrs.max}
|
||||
autocomplete="off"
|
||||
/>
|
||||
<div class="inline-flex">
|
||||
<.text_field
|
||||
type="date"
|
||||
data-el-input
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce="blur"
|
||||
phx-target={@myself}
|
||||
min={@attrs.min}
|
||||
max={@attrs.max}
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp input_output(%{attrs: %{type: :color}} = assigns) do
|
||||
~H"""
|
||||
<div class="w-16">
|
||||
<.text_field
|
||||
type="color"
|
||||
class="h-12"
|
||||
data-el-input
|
||||
name="html_value"
|
||||
value={to_string(@value)}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp input_output(%{attrs: %{type: type}} = assigns)
|
||||
when type in [:number, :color, :url, :text] do
|
||||
when type in [:number, :url, :text] do
|
||||
~H"""
|
||||
<input
|
||||
type={html_input_type(@attrs.type)}
|
||||
data-el-input
|
||||
class="input w-auto invalid:input--error"
|
||||
name="html_value"
|
||||
value={to_string(@value)}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<div class="inline-flex">
|
||||
<.text_field
|
||||
type={html_input_type(@attrs.type)}
|
||||
data-el-input
|
||||
name="html_value"
|
||||
value={to_string(@value)}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
|
@ -282,7 +308,6 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
end
|
||||
|
||||
defp html_input_type(:number), do: "number"
|
||||
defp html_input_type(:color), do: "color"
|
||||
defp html_input_type(:url), do: "url"
|
||||
defp html_input_type(:text), do: "text"
|
||||
|
||||
|
|
|
@ -87,12 +87,9 @@ defmodule LivebookWeb.Output.TerminalTextComponent do
|
|||
>
|
||||
</div>
|
||||
<div class="absolute right-2 top-0 z-10 invisible group-hover/root:visible">
|
||||
<button
|
||||
class="icon-button bg-gray-100"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "##{@id}-template")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</button>
|
||||
<.icon_button phx-click={JS.dispatch("lb:clipcopy", to: "##{@id}-template")}>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -81,17 +81,16 @@ defmodule LivebookWeb.SessionLive.AddFileEntryFileComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
type="submit"
|
||||
disabled={not @changeset.valid? or not regular?(@file, @file_info) or @fetching}
|
||||
>
|
||||
<.spinner :if={@fetching} class="mr-2" />
|
||||
<.spinner :if={@fetching} class="mr-1" />
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -69,16 +69,12 @@ defmodule LivebookWeb.SessionLive.AddFileEntryUnlistedComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
disabled={Enum.empty?(@selected_indices)}
|
||||
>
|
||||
<.button type="submit" disabled={Enum.empty?(@selected_indices)}>
|
||||
Add
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -64,17 +64,13 @@ defmodule LivebookWeb.SessionLive.AddFileEntryUploadComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
disabled={not @changeset.valid? or upload_disabled?(@uploads.file)}
|
||||
>
|
||||
<.spinner class="hidden phx-submit-loading:block mr-2" />
|
||||
<.button type="submit" disabled={not @changeset.valid? or upload_disabled?(@uploads.file)}>
|
||||
<.spinner class="hidden phx-submit-loading:block mr-1" />
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -63,17 +63,13 @@ defmodule LivebookWeb.SessionLive.AddFileEntryUrlComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
disabled={not @changeset.valid? or @fetching}
|
||||
>
|
||||
<.spinner :if={@fetching} class="mr-2" />
|
||||
<.button type="submit" disabled={not @changeset.valid? or @fetching}>
|
||||
<.spinner :if={@fetching} class="mr-1" />
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -171,16 +171,17 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
|
|||
dockerfile_config={apply_changes(@changeset)}
|
||||
>
|
||||
<:dockerfile_actions>
|
||||
<button
|
||||
class="button-base button-gray whitespace-nowrap py-1 px-2"
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
type="button"
|
||||
aria-label="save dockerfile alongside the notebook"
|
||||
phx-click="save_dockerfile"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="save-line" class="align-middle mr-1 text-xs" />
|
||||
<span class="font-normal text-xs">Save alongside notebook</span>
|
||||
</button>
|
||||
<.remix_icon icon="save-line" />
|
||||
<span>Save alongside notebook</span>
|
||||
</.button>
|
||||
</:dockerfile_actions>
|
||||
</AppComponents.docker_instructions>
|
||||
</div>
|
||||
|
|
|
@ -20,10 +20,10 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
message="This session is a running app. To deploy a modified version, you can fork it."
|
||||
/>
|
||||
<div class="mt-6">
|
||||
<button class="button-base button-blue" phx-click="fork_session">
|
||||
<.button phx-click="fork_session">
|
||||
<.remix_icon icon="git-branch-line" />
|
||||
<span>Fork</span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
|
@ -35,20 +35,16 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
/>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
phx-click="deploy_app"
|
||||
disabled={not Livebook.Notebook.AppSettings.valid?(@settings)}
|
||||
>
|
||||
<.remix_icon icon="rocket-line" class="align-middle mr-1" />
|
||||
<.remix_icon icon="rocket-line" />
|
||||
<span>Deploy</span>
|
||||
</button>
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session.id}/settings/app"}
|
||||
class="button-base button-outlined-gray bg-transparent"
|
||||
>
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}/settings/app"}>
|
||||
Configure
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
<.link
|
||||
class="text-sm text-gray-700 hover:text-blue-600"
|
||||
|
@ -82,13 +78,12 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
<div class="border-t border-gray-200 px-3 py-2 flex space-x-2">
|
||||
<div class="grow" />
|
||||
<span class="tooltip top" data-tooltip="Terminate">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="terminate app"
|
||||
phx-click={JS.push("terminate_app", target: @myself)}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -114,24 +109,23 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
</div>
|
||||
<div class="border-t border-gray-200 px-3 py-2 flex space-x-2">
|
||||
<span class="tooltip top" data-tooltip="Open">
|
||||
<a
|
||||
class={["icon-button", app_session.app_status.lifecycle != :active && "disabled"]}
|
||||
<.icon_button
|
||||
disabled={app_session.app_status.lifecycle}
|
||||
aria-label="open app"
|
||||
href={~p"/apps/#{@app.slug}/#{app_session.id}"}
|
||||
>
|
||||
<.remix_icon icon="link" class="text-lg" />
|
||||
</a>
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<div class="grow" />
|
||||
<span class="tooltip top" data-tooltip="Debug">
|
||||
<a class="icon-button" aria-label="debug app" href={~p"/sessions/#{app_session.id}"}>
|
||||
<.remix_icon icon="terminal-line" class="text-lg" />
|
||||
</a>
|
||||
<.icon_button aria-label="debug app" href={~p"/sessions/#{app_session.id}"}>
|
||||
<.remix_icon icon="terminal-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<%= if app_session.app_status.lifecycle == :active do %>
|
||||
<span class="tooltip top" data-tooltip="Deactivate">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="deactivate app session"
|
||||
phx-click={
|
||||
JS.push("deactivate_app_session",
|
||||
|
@ -140,13 +134,12 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="stop-circle-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="stop-circle-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="tooltip top" data-tooltip="Terminate">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="terminate app session"
|
||||
phx-click={
|
||||
JS.push("terminate_app_session",
|
||||
|
@ -155,8 +148,8 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -171,7 +164,7 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
defp app_info_icon(assigns) do
|
||||
~H"""
|
||||
<span
|
||||
class="icon-button p-0 cursor-pointer tooltip bottom-left"
|
||||
class="tooltip bottom-left"
|
||||
data-tooltip={
|
||||
~S'''
|
||||
App deployment is a way to share your
|
||||
|
@ -181,7 +174,9 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="question-line" class="text-xl leading-none" />
|
||||
<.icon_button>
|
||||
<.remix_icon icon="question-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -118,18 +118,17 @@ defmodule LivebookWeb.SessionLive.AppSettingsComponent do
|
|||
<% end %>
|
||||
</div>
|
||||
<div class="mt-8 flex space-x-2">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
type="button"
|
||||
phx-click={JS.patch(~p"/sessions/#{@session.id}") |> JS.push("deploy_app")}
|
||||
disabled={not @changeset.valid?}
|
||||
>
|
||||
<.remix_icon icon="rocket-line" class="align-middle mr-1" />
|
||||
<.remix_icon icon="rocket-line" />
|
||||
<span>Deploy</span>
|
||||
</button>
|
||||
<button class="button-base button-outlined-gray" type="reset" name="reset">
|
||||
</.button>
|
||||
<.button color="gray" outlined type="reset" name="reset">
|
||||
Reset
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -78,13 +78,13 @@ defmodule LivebookWeb.SessionLive.AttachedLive do
|
|||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<div class="flex flex-col space-y-4 mb-5">
|
||||
<.text_field field={f[:name]} label="Name" placeholder={name_placeholder()} />
|
||||
<.text_field field={f[:cookie]} label="Cookie" placeholder="mycookie" />
|
||||
</div>
|
||||
<button class="mt-5 button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<%= if(reconnecting?(@changeset), do: "Reconnect", else: "Connect") %>
|
||||
</button>
|
||||
</.button>
|
||||
</.form>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -46,9 +46,8 @@ defmodule LivebookWeb.SessionLive.BinComponent do
|
|||
<span class="absolute inset-y-0 left-0 pl-3 flex items-center">
|
||||
<.remix_icon icon="search-line" class="align-bottom text-gray-500" />
|
||||
</span>
|
||||
<input
|
||||
class="input block w-full pl-10"
|
||||
type="text"
|
||||
<.text_field
|
||||
class="pl-10"
|
||||
name="search"
|
||||
value={@search}
|
||||
placeholder="Search"
|
||||
|
@ -113,30 +112,32 @@ defmodule LivebookWeb.SessionLive.BinComponent do
|
|||
source={cell.source}
|
||||
/>
|
||||
<div class="pt-1 pb-4 border-b border-gray-200">
|
||||
<button
|
||||
class="button-base button-gray whitespace-nowrap py-1 px-2"
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
aria-label="restore"
|
||||
phx-click="restore"
|
||||
phx-value-cell_id={entry.cell.id}
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="arrow-go-back-line" class="align-middle mr-1 text-xs" />
|
||||
<span class="font-normal text-xs">Restore</span>
|
||||
</button>
|
||||
<button
|
||||
class="button-base button-gray whitespace-nowrap py-1 px-2"
|
||||
<.remix_icon icon="arrow-go-back-line" />
|
||||
<span>Restore</span>
|
||||
</.button>
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
aria-label="copy source"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "#bin-cell-#{cell.id}-source")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="align-middle mr-1 text-xs" />
|
||||
<span class="font-normal text-xs">Copy source</span>
|
||||
</button>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
<span>Copy source</span>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<div :if={length(@matching_entries) > @limit} class="flex justify-center">
|
||||
<button class="button-base button-outlined-gray" phx-click="more" phx-target={@myself}>
|
||||
<.button color="gray" outlined phx-click="more" phx-target={@myself}>
|
||||
Older
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
@ -245,12 +245,12 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
<span>
|
||||
The Smart cell crashed unexpectedly, this is most likely a bug.
|
||||
</span>
|
||||
<button
|
||||
class="button-base button-gray"
|
||||
<.button
|
||||
color="gray"
|
||||
phx-click={JS.push("recover_smart_cell", value: %{cell_id: @cell_view.id})}
|
||||
>
|
||||
Restart Smart cell
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
<% :starting -> %>
|
||||
<div class="delay-200">
|
||||
|
@ -450,9 +450,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp enable_insert_mode_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Edit content" data-el-enable-insert-mode-button>
|
||||
<button class="icon-button" aria-label="edit content">
|
||||
<.remix_icon icon="pencil-line" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="edit content">
|
||||
<.remix_icon icon="pencil-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -460,9 +460,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp toggle_source_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Toggle source" data-el-toggle-source-button>
|
||||
<button class="icon-button" aria-label="toggle source">
|
||||
<.remix_icon icon="code-line" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="toggle source">
|
||||
<.remix_icon icon="code-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -470,14 +470,13 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp convert_smart_cell_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Convert to Code cell">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="toggle source"
|
||||
data-link-package-search
|
||||
phx-click={JS.push("convert_smart_cell", value: %{cell_id: @cell_id})}
|
||||
>
|
||||
<.remix_icon icon="pencil-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="pencil-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -489,20 +488,19 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
class="tooltip top"
|
||||
data-tooltip="The current runtime does not support adding dependencies"
|
||||
>
|
||||
<button class="icon-button" disabled>
|
||||
<.remix_icon icon="play-list-add-line" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button disabled>
|
||||
<.remix_icon icon="play-list-add-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="tooltip top" data-tooltip="Add package (sp)">
|
||||
<.link
|
||||
<.icon_button
|
||||
patch={~p"/sessions/#{@session_id}/package-search"}
|
||||
class="icon-button"
|
||||
role="button"
|
||||
data-btn-package-search
|
||||
>
|
||||
<.remix_icon icon="play-list-add-line" class="text-xl" />
|
||||
</.link>
|
||||
<.remix_icon icon="play-list-add-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% end %>
|
||||
"""
|
||||
|
@ -511,9 +509,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp cell_link_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Link">
|
||||
<a href={"#cell-#{@cell_id}"} class="icon-button" role="button" aria-label="link to cell">
|
||||
<.remix_icon icon="link" class="text-xl" />
|
||||
</a>
|
||||
<.icon_button href={"#cell-#{@cell_id}"} role="button" aria-label="link to cell">
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -521,9 +519,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
def amplify_output_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Amplify output" data-el-amplify-outputs-button>
|
||||
<button class="icon-button" aria-label="amplify outputs">
|
||||
<.remix_icon icon="zoom-in-line" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="amplify outputs">
|
||||
<.remix_icon icon="zoom-in-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -531,14 +529,13 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp cell_settings_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Cell settings">
|
||||
<.link
|
||||
<.icon_button
|
||||
patch={~p"/sessions/#{@session_id}/cell-settings/#{@cell_id}"}
|
||||
class="icon-button"
|
||||
aria-label="cell settings"
|
||||
role="button"
|
||||
>
|
||||
<.remix_icon icon="settings-3-line" class="text-xl" />
|
||||
</.link>
|
||||
<.remix_icon icon="settings-3-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -546,15 +543,14 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp move_cell_up_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Move up">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="move cell up"
|
||||
phx-click="move_cell"
|
||||
phx-value-cell_id={@cell_id}
|
||||
phx-value-offset="-1"
|
||||
>
|
||||
<.remix_icon icon="arrow-up-s-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-up-s-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -562,15 +558,14 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp move_cell_down_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Move down">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="move cell down"
|
||||
phx-click="move_cell"
|
||||
phx-value-cell_id={@cell_id}
|
||||
phx-value-offset="1"
|
||||
>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-down-s-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -578,13 +573,12 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp delete_cell_button(assigns) do
|
||||
~H"""
|
||||
<span class="tooltip top" data-tooltip="Delete">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="delete cell"
|
||||
phx-click={JS.push("delete_cell", value: %{cell_id: @cell_id})}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -601,9 +595,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<span class="icon-button">
|
||||
<.remix_icon icon="question-line" class="text-xl" />
|
||||
</span>
|
||||
<.icon_button>
|
||||
<.remix_icon icon="question-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -47,12 +47,12 @@ defmodule LivebookWeb.SessionLive.CodeCellSettingsComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-8 flex justify-begin space-x-2">
|
||||
<button class="button-base button-blue" type="submit">
|
||||
<.button type="submit">
|
||||
Save
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -27,9 +27,9 @@ defmodule LivebookWeb.SessionLive.CustomViewComponent do
|
|||
<.switch_field name="spotlight" label="Spotlight focused" value={false} />
|
||||
</div>
|
||||
<div class="mt-8 flex justify-end space-x-2">
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Close
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -32,9 +32,9 @@ defmodule LivebookWeb.SessionLive.ElixirStandaloneLive do
|
|||
<p class="text-gray-700">
|
||||
Start a new local node to handle code evaluation.
|
||||
</p>
|
||||
<button class="button-base button-blue" phx-click="init">
|
||||
<.button phx-click="init">
|
||||
<%= if(matching_runtime?(@current_runtime), do: "Reconnect", else: "Connect") %>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -39,9 +39,9 @@ defmodule LivebookWeb.SessionLive.EmbeddedLive do
|
|||
you restart Livebook. Furthermore, code in one notebook
|
||||
may interfere with code from another notebook.
|
||||
</p>
|
||||
<button class="button-base button-blue" phx-click="init">
|
||||
<.button phx-click="init">
|
||||
<%= if(matching_runtime?(@current_runtime), do: "Reconnect", else: "Connect") %>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -24,23 +24,21 @@ defmodule LivebookWeb.SessionLive.ExportElixirComponent do
|
|||
</span>
|
||||
<div class="flex justify-end space-x-2">
|
||||
<span class="tooltip left" data-tooltip="Copy source">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="copy source"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "#export-notebook-source")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span class="tooltip left" data-tooltip="Download source">
|
||||
<a
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="download source"
|
||||
href={~p"/sessions/#{@session.id}/download/export/exs"}
|
||||
download
|
||||
>
|
||||
<.remix_icon icon="download-2-line" class="text-lg" />
|
||||
</a>
|
||||
<.remix_icon icon="download-2-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -43,25 +43,23 @@ defmodule LivebookWeb.SessionLive.ExportLiveMarkdownComponent do
|
|||
</span>
|
||||
<div class="flex justify-end space-x-2">
|
||||
<span class="tooltip left" data-tooltip="Copy source">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="copy source"
|
||||
phx-click={JS.dispatch("lb:clipcopy", to: "#export-notebook-source")}
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span class="tooltip left" data-tooltip="Download source">
|
||||
<a
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="download source"
|
||||
href={
|
||||
~p"/sessions/#{@session.id}/download/export/livemd?include_outputs=#{@include_outputs}"
|
||||
}
|
||||
download
|
||||
>
|
||||
<.remix_icon icon="download-2-line" class="text-lg" />
|
||||
</a>
|
||||
<.remix_icon icon="download-2-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -126,9 +126,9 @@ defmodule LivebookWeb.SessionLive.FilesListComponent do
|
|||
<% else %>
|
||||
<.menu id={"file-entry-#{file_entry.type}-#{idx}-menu"} position={:bottom_right}>
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="menu">
|
||||
<.icon_button small aria-label="menu">
|
||||
<.remix_icon icon="more-2-line" />
|
||||
</button>
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<button
|
||||
|
@ -209,7 +209,7 @@ defmodule LivebookWeb.SessionLive.FilesListComponent do
|
|||
defp references_info_icon(assigns) do
|
||||
~H"""
|
||||
<span
|
||||
class="icon-button cursor-pointer tooltip bottom-left"
|
||||
class="tooltip bottom-left"
|
||||
data-tooltip={
|
||||
~S'''
|
||||
References are files that point to
|
||||
|
@ -218,7 +218,9 @@ defmodule LivebookWeb.SessionLive.FilesListComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="question-line" class="leading-none text-gray-700" />
|
||||
<.icon_button small>
|
||||
<.remix_icon icon="question-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -226,7 +228,7 @@ defmodule LivebookWeb.SessionLive.FilesListComponent do
|
|||
defp attachments_info_icon(assigns) do
|
||||
~H"""
|
||||
<span
|
||||
class="icon-button cursor-pointer tooltip bottom-left"
|
||||
class="tooltip bottom-left"
|
||||
data-tooltip={
|
||||
~S'''
|
||||
Attachments are files stored in the
|
||||
|
@ -235,7 +237,9 @@ defmodule LivebookWeb.SessionLive.FilesListComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="question-line" class="leading-none text-gray-700" />
|
||||
<.icon_button small>
|
||||
<.remix_icon icon="question-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ defmodule LivebookWeb.SessionLive.InsertButtonsComponent do
|
|||
}>
|
||||
<.menu id={"cell-#{@id}-insert"} position={:bottom_left} distant>
|
||||
<:toggle>
|
||||
<button class="button-base button-small flex items-center pr-1">
|
||||
<.insert_button>
|
||||
<div
|
||||
class="pr-2"
|
||||
phx-click="insert_cell_below"
|
||||
|
@ -37,10 +37,10 @@ defmodule LivebookWeb.SessionLive.InsertButtonsComponent do
|
|||
>
|
||||
+ <%= @default_language |> Atom.to_string() |> String.capitalize() %>
|
||||
</div>
|
||||
<div class="pl-1 flex items-center border-l border-gray-200">
|
||||
<div class="-mr-1 pl-1 flex items-center border-l border-gray-200 group-hover:border-gray-300 group-focus:border-gray-300">
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-lg leading-none" />
|
||||
</div>
|
||||
</button>
|
||||
</.insert_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<button
|
||||
|
@ -71,7 +71,7 @@ defmodule LivebookWeb.SessionLive.InsertButtonsComponent do
|
|||
</.menu>
|
||||
<.menu id={"#{@id}-block-menu"} position={:bottom_left}>
|
||||
<:toggle>
|
||||
<button class="button-base button-small">+ Block</button>
|
||||
<.insert_button>+ Block</.insert_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<button
|
||||
|
@ -149,24 +149,21 @@ defmodule LivebookWeb.SessionLive.InsertButtonsComponent do
|
|||
</.menu>
|
||||
<%= cond do %>
|
||||
<% not Livebook.Runtime.connected?(@runtime) -> %>
|
||||
<button
|
||||
class="button-base button-small"
|
||||
phx-click={
|
||||
JS.push("setup_default_runtime",
|
||||
value: %{reason: "To see the available smart cells, you need a connected runtime."}
|
||||
)
|
||||
}
|
||||
>
|
||||
<.insert_button phx-click={
|
||||
JS.push("setup_default_runtime",
|
||||
value: %{reason: "To see the available smart cells, you need a connected runtime."}
|
||||
)
|
||||
}>
|
||||
+ Smart
|
||||
</button>
|
||||
</.insert_button>
|
||||
<% @smart_cell_definitions == [] -> %>
|
||||
<span class="tooltip right" data-tooltip="No smart cells available">
|
||||
<button class="button-base button-small" disabled>+ Smart</button>
|
||||
<.insert_button disabled>+ Smart</.insert_button>
|
||||
</span>
|
||||
<% true -> %>
|
||||
<.menu id={"#{@id}-smart-menu"} position={:bottom_left}>
|
||||
<:toggle>
|
||||
<button class="button-base button-small">+ Smart</button>
|
||||
<.insert_button>+ Smart</.insert_button>
|
||||
</:toggle>
|
||||
<.menu_item :for={definition <- @smart_cell_definitions}>
|
||||
<.smart_cell_insert_button
|
||||
|
@ -182,6 +179,29 @@ defmodule LivebookWeb.SessionLive.InsertButtonsComponent do
|
|||
"""
|
||||
end
|
||||
|
||||
attr :disabled, :boolean, default: false
|
||||
attr :rest, :global
|
||||
|
||||
slot :inner_block
|
||||
|
||||
def insert_button(assigns) do
|
||||
~H"""
|
||||
<button
|
||||
{@rest}
|
||||
class={[
|
||||
"inline-flex items-center px-2 py-1 rounded-lg font-medium text-sm whitespace-nowrap border",
|
||||
if @disabled do
|
||||
"cursor-default pointer-events-none border-transparent bg-gray-100 text-gray-400"
|
||||
else
|
||||
"bg-gray-50 border-gray-200 text-gray-600 hover:bg-gray-100 focus:bg-gray-100"
|
||||
end
|
||||
]}
|
||||
>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</button>
|
||||
"""
|
||||
end
|
||||
|
||||
defp example_snippet_insert_button(assigns) when is_many(assigns.definition.variants) do
|
||||
~H"""
|
||||
<.submenu>
|
||||
|
|
|
@ -69,16 +69,12 @@ defmodule LivebookWeb.SessionLive.InsertImageComponent do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-8 flex justify-end space-x-2">
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
disabled={not @changeset.valid? or upload_disabled?(@uploads.image)}
|
||||
>
|
||||
</.button>
|
||||
<.button type="submit" disabled={not @changeset.valid? or upload_disabled?(@uploads.image)}>
|
||||
Upload
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -29,8 +29,7 @@ defmodule LivebookWeb.SessionLive.PackageSearchLive do
|
|||
Find external packages for your notebook
|
||||
</p>
|
||||
<form phx-submit="submit" phx-change="search">
|
||||
<input
|
||||
class="input"
|
||||
<.text_field
|
||||
name="search"
|
||||
value={@search}
|
||||
phx-debounce="250"
|
||||
|
@ -78,14 +77,10 @@ defmodule LivebookWeb.SessionLive.PackageSearchLive do
|
|||
</div>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<button
|
||||
class="button-base button-gray whitespace-nowrap py-1 px-2"
|
||||
aria-label="add"
|
||||
phx-click={JS.push("add", value: %{idx: @idx})}
|
||||
>
|
||||
<.remix_icon icon="add-line" class="align-middle mr-1 text-xs" />
|
||||
<span class="font-normal text-xs">Add</span>
|
||||
</button>
|
||||
<.button color="gray" small aria-label="add" phx-click={JS.push("add", value: %{idx: @idx})}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span>Add</span>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -119,26 +119,20 @@ defmodule LivebookWeb.SessionLive.PersistenceComponent do
|
|||
</div>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex space-x-3">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
<.button
|
||||
phx-click="save"
|
||||
phx-target={@myself}
|
||||
disabled={not savable?(@draft_file, @saved_file, @running_files)}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
<button
|
||||
:if={@saved_file}
|
||||
class="button-base button-outlined-red"
|
||||
phx-click="stop_saving"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.button :if={@saved_file} color="red" outlined phx-click="stop_saving" phx-target={@myself}>
|
||||
Stop saving to file
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -47,13 +47,13 @@ defmodule LivebookWeb.SessionLive.RenameFileEntryComponent do
|
|||
autofocus
|
||||
/>
|
||||
<div class="mt-6 flex space-x-3">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.spinner class="hidden phx-submit-loading:block mr-2" />
|
||||
<span>Rename</span>
|
||||
</button>
|
||||
<.link patch={~p"/sessions/#{@session.id}"} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}"}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
|
@ -563,13 +563,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
</span>
|
||||
</button>
|
||||
<%= if client_id == @client_id do %>
|
||||
<button
|
||||
class="icon-button"
|
||||
aria-label="edit profile"
|
||||
phx-click={show_current_user_modal()}
|
||||
>
|
||||
<.remix_icon icon="user-settings-line" class="text-lg" />
|
||||
</button>
|
||||
<.icon_button aria-label="edit profile" phx-click={show_current_user_modal()}>
|
||||
<.remix_icon icon="user-settings-line" />
|
||||
</.icon_button>
|
||||
<% else %>
|
||||
<span
|
||||
class="tooltip left"
|
||||
|
@ -577,9 +573,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
data-el-client-follow-toggle
|
||||
data-meta="follow"
|
||||
>
|
||||
<button class="icon-button" aria-label="follow this user">
|
||||
<.remix_icon icon="pushpin-line" class="text-lg" />
|
||||
</button>
|
||||
<.icon_button aria-label="follow this user">
|
||||
<.remix_icon icon="pushpin-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span
|
||||
class="tooltip left"
|
||||
|
@ -587,9 +583,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
data-el-client-follow-toggle
|
||||
data-meta="unfollow"
|
||||
>
|
||||
<button class="icon-button" aria-label="unfollow this user">
|
||||
<.remix_icon icon="pushpin-fill" class="text-lg" />
|
||||
</button>
|
||||
<.icon_button aria-label="unfollow this user">
|
||||
<.remix_icon icon="pushpin-fill" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -605,9 +601,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<h3 class="uppercase text-sm font-semibold text-gray-500">
|
||||
Runtime
|
||||
</h3>
|
||||
<.link patch={~p"/sessions/#{@session.id}/settings/runtime"} class="icon-button p-0">
|
||||
<.remix_icon icon="settings-3-line text-xl" />
|
||||
</.link>
|
||||
<.icon_button patch={~p"/sessions/#{@session.id}/settings/runtime"}>
|
||||
<.remix_icon icon="settings-3-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
<div class="flex flex-col mt-2 space-y-4">
|
||||
<div class="flex flex-col space-y-3">
|
||||
|
@ -621,28 +617,21 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<%= if Runtime.connected?(@data_view.runtime) do %>
|
||||
<button class="button-base button-blue" phx-click="reconnect_runtime">
|
||||
<.remix_icon icon="wireless-charging-line" class="align-middle mr-1" />
|
||||
<.button phx-click="reconnect_runtime">
|
||||
<.remix_icon icon="wireless-charging-line" />
|
||||
<span>Reconnect</span>
|
||||
</button>
|
||||
<button
|
||||
class="button-base button-outlined-red"
|
||||
type="button"
|
||||
phx-click="disconnect_runtime"
|
||||
>
|
||||
</.button>
|
||||
<.button color="red" outlined type="button" phx-click="disconnect_runtime">
|
||||
Disconnect
|
||||
</button>
|
||||
</.button>
|
||||
<% else %>
|
||||
<button class="button-base button-blue" phx-click="connect_runtime">
|
||||
<.remix_icon icon="wireless-charging-line" class="align-middle mr-1" />
|
||||
<.button phx-click="connect_runtime">
|
||||
<.remix_icon icon="wireless-charging-line" />
|
||||
<span>Connect</span>
|
||||
</button>
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session.id}/settings/runtime"}
|
||||
class="button-base button-outlined-gray bg-transparent"
|
||||
>
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={~p"/sessions/#{@session.id}/settings/runtime"}>
|
||||
Configure
|
||||
</.link>
|
||||
</.button>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= if uses_memory?(@session.memory_usage) do %>
|
||||
|
@ -737,9 +726,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<.menu id="session-menu">
|
||||
<:toggle>
|
||||
<button class="icon-button" aria-label="open notebook menu">
|
||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||
</button>
|
||||
<.icon_button aria-label="open notebook menu">
|
||||
<.remix_icon icon="more-2-fill" />
|
||||
</.icon_button>
|
||||
</:toggle>
|
||||
<.menu_item>
|
||||
<.link patch={~p"/sessions/#{@session.id}/export/livemd"} role="menuitem">
|
||||
|
@ -909,14 +898,14 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<.menu id="views-menu" position={:bottom_right} sm_position={:top_right}>
|
||||
<:toggle>
|
||||
<button
|
||||
class="icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100"
|
||||
class={status_button_classes(:gray)}
|
||||
aria-label="choose views to activate"
|
||||
data-el-views-disabled
|
||||
>
|
||||
<.remix_icon icon="layout-5-line" class="text-xl text-gray-400" />
|
||||
<.remix_icon icon="layout-5-line" />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button icon-outlined-button border-green-bright-300 hover:bg-green-bright-50 focus:bg-green-bright-50"
|
||||
class={status_button_classes(:green)}
|
||||
aria-label="choose views to activate"
|
||||
data-el-views-enabled
|
||||
>
|
||||
|
@ -951,10 +940,10 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<span class="tooltip left" data-tooltip="Choose a file to save the notebook">
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/settings/file"}
|
||||
class="icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100"
|
||||
class={status_button_classes(:gray)}
|
||||
aria-label="choose a file to save the notebook"
|
||||
>
|
||||
<.remix_icon icon="save-line" class="text-xl text-gray-400" />
|
||||
<.remix_icon icon="save-line" />
|
||||
</.link>
|
||||
</span>
|
||||
"""
|
||||
|
@ -976,15 +965,17 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
>
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/settings/file"}
|
||||
class="icon-button icon-outlined-button border-green-bright-300 hover:bg-green-bright-50 focus:bg-green-bright-50 relative"
|
||||
class={status_button_classes(:green)}
|
||||
aria-label="notebook saved, click to open file settings"
|
||||
>
|
||||
<.remix_icon icon="save-line" class="text-xl text-green-bright-400" />
|
||||
<.remix_icon
|
||||
:if={@persistence_warnings != []}
|
||||
icon="error-warning-fill"
|
||||
class="text-lg text-red-400 absolute -top-1.5 -right-2"
|
||||
/>
|
||||
<div class="relative">
|
||||
<.remix_icon icon="save-line" />
|
||||
<.remix_icon
|
||||
:if={@persistence_warnings != []}
|
||||
icon="error-warning-fill"
|
||||
class="text-lg text-red-400 absolute -top-1.5 -right-2"
|
||||
/>
|
||||
</div>
|
||||
</.link>
|
||||
</span>
|
||||
"""
|
||||
|
@ -995,10 +986,10 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<span class="tooltip left" data-tooltip="No autosave configured, make sure to save manually">
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/settings/file"}
|
||||
class="icon-button icon-outlined-button border-yellow-bright-200 hover:bg-red-50 focus:bg-red-50"
|
||||
class={status_button_classes(:yellow)}
|
||||
aria-label="no autosave configured, click to open file settings"
|
||||
>
|
||||
<.remix_icon icon="save-line" class="text-xl text-yellow-bright-300" />
|
||||
<.remix_icon icon="save-line" />
|
||||
</.link>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1009,10 +1000,10 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<span class="tooltip left" data-tooltip="Autosave pending">
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/settings/file"}
|
||||
class="icon-button icon-outlined-button border-blue-400 hover:bg-blue-50 focus:bg-blue-50"
|
||||
class={status_button_classes(:blue)}
|
||||
aria-label="autosave pending, click to open file settings"
|
||||
>
|
||||
<.remix_icon icon="save-line" class="text-xl text-blue-500" />
|
||||
<.remix_icon icon="save-line" />
|
||||
</.link>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1026,10 +1017,10 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
<span class="tooltip left" data-tooltip="Choose a runtime to run the notebook in">
|
||||
<.link
|
||||
patch={~p"/sessions/#{@session_id}/settings/runtime"}
|
||||
class="icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100"
|
||||
class={status_button_classes(:gray)}
|
||||
aria-label="choose a runtime to run the notebook in"
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-gray-400" />
|
||||
<.remix_icon icon="loader-3-line" />
|
||||
</.link>
|
||||
</span>
|
||||
<% end %>
|
||||
|
@ -1040,12 +1031,12 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Go to evaluating cell">
|
||||
<button
|
||||
class="border-blue-400 icon-button icon-outlined-button hover:bg-blue-50 focus:bg-blue-50"
|
||||
class={status_button_classes(:blue)}
|
||||
aria-label="go to evaluating cell"
|
||||
data-el-focus-cell-button
|
||||
data-target={@cell_id}
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-blue-500 animate-spin" />
|
||||
<.remix_icon icon="loader-3-line" class="animate-spin" />
|
||||
</button>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1055,12 +1046,12 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Go to last evaluated cell">
|
||||
<button
|
||||
class="border-green-bright-300 icon-button icon-outlined-button hover:bg-green-bright-50 focus:bg-green-bright-50"
|
||||
class={status_button_classes(:green)}
|
||||
aria-label="go to last evaluated cell"
|
||||
data-el-focus-cell-button
|
||||
data-target={@cell_id}
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-green-bright-400" />
|
||||
<.remix_icon icon="loader-3-line" />
|
||||
</button>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1070,12 +1061,12 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Go to last evaluated cell">
|
||||
<button
|
||||
class="border-red-300 icon-button icon-outlined-button hover:bg-red-50 focus:bg-red-50"
|
||||
class={status_button_classes(:red)}
|
||||
aria-label="go to last evaluated cell"
|
||||
data-el-focus-cell-button
|
||||
data-target={@cell_id}
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-red-400" />
|
||||
<.remix_icon icon="loader-3-line" />
|
||||
</button>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1085,12 +1076,12 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Go to first stale cell">
|
||||
<button
|
||||
class="border-yellow-bright-200 icon-button icon-outlined-button hover:bg-yellow-bright-50 focus:bg-yellow-bright-50"
|
||||
class={status_button_classes(:yellow)}
|
||||
aria-label="go to first stale cell"
|
||||
data-el-focus-cell-button
|
||||
data-target={@cell_id}
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-yellow-bright-300" />
|
||||
<.remix_icon icon="loader-3-line" />
|
||||
</button>
|
||||
</span>
|
||||
"""
|
||||
|
@ -1099,16 +1090,35 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
defp global_status(%{status: :fresh} = assigns) do
|
||||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Ready to evaluate">
|
||||
<div
|
||||
class="border-gray-200 icon-button icon-outlined-button hover:bg-gray-100 focus:bg-gray-100"
|
||||
aria-label="ready to evaluate"
|
||||
>
|
||||
<.remix_icon icon="loader-3-line" class="text-xl text-gray-400" />
|
||||
<div class={status_button_classes(:gray)} aria-label="ready to evaluate">
|
||||
<.remix_icon icon="loader-3-line" />
|
||||
</div>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
||||
defp status_button_classes(color) do
|
||||
[
|
||||
"text-xl leading-none p-1 flex items-center justify-center rounded-full rounded-full border-2",
|
||||
case color do
|
||||
:gray ->
|
||||
"text-gray-400 border-gray-200 hover:bg-gray-100 focus:bg-gray-100"
|
||||
|
||||
:blue ->
|
||||
"text-blue-500 border-blue-400 hover:bg-blue-50 focus:bg-blue-50"
|
||||
|
||||
:green ->
|
||||
"text-green-bright-400 border-green-bright-300 hover:bg-green-bright-50 focus:bg-green-bright-50"
|
||||
|
||||
:yellow ->
|
||||
"text-yellow-bright-300 border-yellow-bright-200 hover:bg-yellow-bright-50 focus:bg-yellow-bright-50"
|
||||
|
||||
:red ->
|
||||
"text-red-400 border-red-300 hover:bg-red-50 focus:bg-red-50"
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
defp insert_mode_indicator(assigns) do
|
||||
~H"""
|
||||
<%!-- Note: this indicator is shown/hidden using CSS based on the current mode --%>
|
||||
|
@ -1199,9 +1209,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
</div>
|
||||
<div class="mt-8 flex flex-col w-full space-y-16" data-el-sections-container>
|
||||
<div :if={@data_view.section_views == []} class="flex justify-center">
|
||||
<button class="button-base button-small" phx-click="append_section">
|
||||
<LivebookWeb.SessionLive.InsertButtonsComponent.insert_button phx-click="append_section">
|
||||
+ Section
|
||||
</button>
|
||||
</LivebookWeb.SessionLive.InsertButtonsComponent.insert_button>
|
||||
</div>
|
||||
<.live_component
|
||||
:for={{section_view, index} <- Enum.with_index(@data_view.section_views)}
|
||||
|
@ -1228,9 +1238,9 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
defp star_button(%{file: nil} = assigns) do
|
||||
~H"""
|
||||
<span class="tooltip left" data-tooltip="Save this notebook before starring it">
|
||||
<button class="icon-button" disabled>
|
||||
<.remix_icon icon="star-line text-lg" />
|
||||
</button>
|
||||
<.icon_button disabled>
|
||||
<.remix_icon icon="star-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
@ -1239,15 +1249,15 @@ defmodule LivebookWeb.SessionLive.Render do
|
|||
~H"""
|
||||
<%= if @file in @starred_files do %>
|
||||
<span class="tooltip left" data-tooltip="Unstar notebook">
|
||||
<button class="icon-button" phx-click="unstar_notebook">
|
||||
<.remix_icon icon="star-fill text-lg text-yellow-600" />
|
||||
</button>
|
||||
<.icon_button phx-click="unstar_notebook">
|
||||
<.remix_icon icon="star-fill" class="text-yellow-600" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="tooltip left" data-tooltip="Star notebook">
|
||||
<button class="icon-button" phx-click="star_notebook">
|
||||
<.remix_icon icon="star-line text-lg" />
|
||||
</button>
|
||||
<.icon_button phx-click="star_notebook">
|
||||
<.remix_icon icon="star-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<% end %>
|
||||
"""
|
||||
|
|
|
@ -126,13 +126,13 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do
|
|||
]}
|
||||
/>
|
||||
<div class="flex space-x-2">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon="add-line" class="align-middle" />
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon="add-line" />
|
||||
<span class="font-normal">Add</span>
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</.form>
|
||||
|
@ -198,15 +198,15 @@ defmodule LivebookWeb.SessionLive.SecretsComponent do
|
|||
in <%= hub_label(@hub) %>. Allow this session to access it?
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
class="button-base button-gray"
|
||||
<.button
|
||||
color="gray"
|
||||
phx-click="select_secret"
|
||||
phx-value-name={@secret.name}
|
||||
phx-value-hub={true}
|
||||
phx-target={@target}
|
||||
>
|
||||
Grant access
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -87,16 +87,17 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
<span class="text-sm font-mono break-all">
|
||||
*****
|
||||
</span>
|
||||
<button
|
||||
<.icon_button
|
||||
small
|
||||
id={"session-secret-#{@secret.name}-copy"}
|
||||
type="button"
|
||||
phx-click={JS.dispatch("lb:clipcopy", detail: %{content: @secret.value})}
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</button>
|
||||
</.icon_button>
|
||||
</div>
|
||||
<button
|
||||
<.icon_button
|
||||
small
|
||||
id={"session-secret-#{@secret.name}-delete"}
|
||||
type="button"
|
||||
phx-click={
|
||||
|
@ -105,10 +106,9 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
target: @myself
|
||||
)
|
||||
}
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="delete-bin-line" />
|
||||
</button>
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
@ -138,16 +138,15 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<button
|
||||
<.icon_button
|
||||
:if={Session.Data.secret_outdated?(@secret, @secrets)}
|
||||
class="icon-button"
|
||||
aria-label="load latest value"
|
||||
phx-click={
|
||||
JS.push("update_outdated", value: %{"name" => @secret.name}, target: @myself)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="refresh-line" class="text-xl leading-none" />
|
||||
</button>
|
||||
<.remix_icon icon="refresh-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<.form
|
||||
:let={f}
|
||||
|
@ -166,23 +165,23 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
<span class="text-sm font-mono break-all">
|
||||
*****
|
||||
</span>
|
||||
<button
|
||||
<.icon_button
|
||||
small
|
||||
id={"#{@id}-copy-button"}
|
||||
type="button"
|
||||
phx-click={JS.dispatch("lb:clipcopy", detail: %{content: @secret.value})}
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="clipboard-line" />
|
||||
</button>
|
||||
</.icon_button>
|
||||
</div>
|
||||
<.link
|
||||
<.icon_button
|
||||
small
|
||||
id={"#{@id}-edit-button"}
|
||||
navigate={~p"/hub/#{@secret.hub_id}/secrets/edit/#{@secret.name}"}
|
||||
class="icon-button"
|
||||
role="button"
|
||||
>
|
||||
<.remix_icon icon="pencil-line" />
|
||||
</.link>
|
||||
</.icon_button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -193,7 +192,7 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
defp secrets_info_icon(assigns) do
|
||||
~H"""
|
||||
<span
|
||||
class="icon-button p-0 cursor-pointer tooltip bottom-left"
|
||||
class="tooltip bottom-left"
|
||||
data-tooltip={
|
||||
~S'''
|
||||
Secrets are a safe way to share credentials
|
||||
|
@ -203,7 +202,9 @@ defmodule LivebookWeb.SessionLive.SecretsListComponent do
|
|||
'''
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="question-line" class="text-xl leading-none" />
|
||||
<.icon_button>
|
||||
<.remix_icon icon="question-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -17,8 +17,7 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
|
|||
data-p-metadata={hook_prop(@section_view.id)}
|
||||
>
|
||||
<div class="absolute left-0 top-0 bottom-0 transform -translate-x-full w-10 flex justify-end items-center pr-2">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="collapse section"
|
||||
data-el-section-collapse-button
|
||||
phx-click={
|
||||
|
@ -27,10 +26,9 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-xl" />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button"
|
||||
<.remix_icon icon="arrow-down-s-line" />
|
||||
</.icon_button>
|
||||
<.icon_button
|
||||
aria-label="expand section"
|
||||
data-el-section-expand-button
|
||||
phx-click={
|
||||
|
@ -39,8 +37,8 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
|
|||
)
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="arrow-right-s-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-right-s-line" />
|
||||
</.icon_button>
|
||||
</div>
|
||||
<h2
|
||||
class="grow text-gray-800 font-semibold text-2xl px-1 -ml-1.5 rounded-lg border border-transparent whitespace-pre-wrap cursor-text scroll-mt-[50px] sm:scroll-mt-0"
|
||||
|
@ -66,52 +64,50 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
|
|||
class="tooltip top"
|
||||
data-tooltip={cannot_branch_out_reason(@section_view) || "Branch out from"}
|
||||
>
|
||||
<button
|
||||
class={["icon-button", cannot_branch_out_reason(@section_view) && "disabled"]}
|
||||
<.icon_button
|
||||
disabled={cannot_branch_out_reason(@section_view)}
|
||||
aria-label="branch out from other section"
|
||||
>
|
||||
<.remix_icon icon="git-branch-line" class="text-xl flip-horizontally" />
|
||||
</button>
|
||||
<.remix_icon icon="git-branch-line" class="flip-horizontally" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</.branching_menu>
|
||||
<span class="tooltip top" data-tooltip="Link">
|
||||
<a href={"##{@section_view.html_id}"} class="icon-button" aria-label="link to section">
|
||||
<.remix_icon icon="link" class="text-xl" />
|
||||
</a>
|
||||
<.icon_button href={"##{@section_view.html_id}"} aria-label="link to section">
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span class="tooltip top" data-tooltip="Move up">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="move section up"
|
||||
phx-click="move_section"
|
||||
phx-value-section_id={@section_view.id}
|
||||
phx-value-offset="-1"
|
||||
>
|
||||
<.remix_icon icon="arrow-up-s-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-up-s-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span class="tooltip top" data-tooltip="Move down">
|
||||
<button
|
||||
class="icon-button"
|
||||
<.icon_button
|
||||
aria-label="move section down"
|
||||
phx-click="move_section"
|
||||
phx-value-section_id={@section_view.id}
|
||||
phx-value-offset="1"
|
||||
>
|
||||
<.remix_icon icon="arrow-down-s-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="arrow-down-s-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
<span {if @section_view.has_children?,
|
||||
do: [class: "tooltip left", "data-tooltip": "Cannot delete this section because\nother sections branch from it"],
|
||||
else: [class: "tooltip top", "data-tooltip": "Delete"]}>
|
||||
<button
|
||||
class={["icon-button", @section_view.has_children? && "disabled"]}
|
||||
<.icon_button
|
||||
disabled={@section_view.has_children?}
|
||||
aria-label="delete section"
|
||||
phx-click="delete_section"
|
||||
phx-value-section_id={@section_view.id}
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-xl" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -68,10 +68,10 @@ defmodule LivebookWeb.SettingsLive do
|
|||
</div>
|
||||
|
||||
<div class="self-center">
|
||||
<.link navigate={~p"/dashboard"} class="button-base button-outlined-gray">
|
||||
<.remix_icon icon="dashboard-2-line" class="align-middle mr-1" />
|
||||
<.button navigate={~p"/dashboard"} color="gray" outlined>
|
||||
<.remix_icon icon="dashboard-2-line" />
|
||||
<span>Open dashboard</span>
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -210,20 +210,19 @@ defmodule LivebookWeb.SettingsLive do
|
|||
file_system_select_disabled={true}
|
||||
target={self()}
|
||||
>
|
||||
<button class="button-base button-gray" phx-click="cancel_autosave_path" tabindex="-1">
|
||||
<.button color="gray" phx-click="cancel_autosave_path" tabindex="-1">
|
||||
Cancel
|
||||
</button>
|
||||
<button class="button-base button-gray" phx-click="reset_autosave_path" tabindex="-1">
|
||||
</.button>
|
||||
<.button color="gray" phx-click="reset_autosave_path" tabindex="-1">
|
||||
Reset
|
||||
</button>
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
</.button>
|
||||
<.button
|
||||
phx-click="set_autosave_path"
|
||||
disabled={not Livebook.FileSystem.File.dir?(@state.file)}
|
||||
tabindex="-1"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</.button>
|
||||
</.live_component>
|
||||
</div>
|
||||
"""
|
||||
|
@ -231,11 +230,13 @@ defmodule LivebookWeb.SettingsLive do
|
|||
|
||||
defp autosave_path_select(assigns) do
|
||||
~H"""
|
||||
<div class="flex">
|
||||
<input class="input mr-2" readonly value={@state.file.path} />
|
||||
<button class="button-base button-gray" phx-click="open_autosave_path_select">
|
||||
<div class="flex gap-2">
|
||||
<div class="grow">
|
||||
<.text_field name={nil} readonly value={@state.file.path} />
|
||||
</div>
|
||||
<.button color="gray" phx-click="open_autosave_path_select">
|
||||
Change
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -50,17 +50,12 @@ defmodule LivebookWeb.SettingsLive.EnvVarComponent do
|
|||
<.text_field field={f[:value]} label="Value" autofocus={@operation == :edit} />
|
||||
<.hidden_field field={f[:operation]} value={@operation} />
|
||||
<div class="flex space-x-2">
|
||||
<button
|
||||
class="button-base button-blue"
|
||||
type="submit"
|
||||
phx-disable-with="Adding..."
|
||||
disabled={not @changeset.valid?}
|
||||
>
|
||||
<.button type="submit" phx-disable-with="Adding..." disabled={not @changeset.valid?}>
|
||||
Save
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
</.button>
|
||||
<.button color="gray" outlined patch={@return_to}>
|
||||
Cancel
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
</.form>
|
||||
|
|
|
@ -19,39 +19,37 @@ defmodule LivebookWeb.SettingsLive.EnvVarsComponent do
|
|||
<:col :let={env_var} label="Name"><%= env_var.name %></:col>
|
||||
<:action :let={env_var}>
|
||||
<span class="tooltip left" data-tooltip="Edit">
|
||||
<button
|
||||
<.icon_button
|
||||
id={"env-var-#{env_var.name}-edit"}
|
||||
type="button"
|
||||
phx-click={
|
||||
JS.push("edit_env_var", value: %{env_var: env_var.name}, target: @target)
|
||||
}
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="edit-fill" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="edit-fill" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</:action>
|
||||
<:action :let={env_var}>
|
||||
<span class="tooltip left" data-tooltip="Delete">
|
||||
<button
|
||||
<.icon_button
|
||||
id={"env-var-#{env_var.name}-delete"}
|
||||
type="button"
|
||||
phx-click={
|
||||
JS.push("delete_env_var", value: %{env_var: env_var.name}, target: @target)
|
||||
}
|
||||
class="icon-button"
|
||||
>
|
||||
<.remix_icon icon="delete-bin-6-line" class="text-lg" />
|
||||
</button>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</.icon_button>
|
||||
</span>
|
||||
</:action>
|
||||
</.table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<.link patch={@add_env_var_path} class="button-base button-blue" id="add-env-var">
|
||||
<.button patch={@add_env_var_path} id="add-env-var">
|
||||
Add environment variable
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -49,14 +49,10 @@ defmodule LivebookWeb.UserComponent do
|
|||
label="Cursor color"
|
||||
randomize={JS.push("randomize_color", target: @myself)}
|
||||
/>
|
||||
<button
|
||||
class="button-base button-blue flex space-x-1 justify-center items-center"
|
||||
type="submit"
|
||||
disabled={not @changeset.valid?}
|
||||
>
|
||||
<.button type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon="save-line" />
|
||||
<span>Save</span>
|
||||
</button>
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue