Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Try surface UI #163

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[
import_deps: [:phoenix],
inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"]
import_deps: [:phoenix, :surface],
inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"],
surface_inputs: ["{lib,test}/**/*.{ex,exs,sface}"]
]
3 changes: 2 additions & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ config :elixir_console, ElixirConsoleWeb.Endpoint,
patterns: [
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
~r"lib/elixir_console_web/(live|views)/.*(ex)$",
~r"lib/elixir_console_web/templates/.*(eex)$"
~r"lib/elixir_console_web/templates/.*(eex)$",
~r"lib/elixir_console_web/live/.*(sface)$"
]
]

Expand Down
22 changes: 22 additions & 0 deletions lib/elixir_console_web/live/console_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ defmodule ElixirConsoleWeb.ConsoleLive do
Sandbox.terminate(sandbox)
end

@impl true
def render(assigns) do
~H"""
<div class="flex h-full flex-col sm:flex-row">
<div class="flex-1 sm:h-full">
<div class="h-full flex flex-col">
<div class="flex-1"></div>
<div class="flex flex-col-reverse overflow-auto">
<div>
<%= live_component(HistoryComponent, output: @output, id: :history) %>
<%= live_component(CommandInputComponent, history: @history, bindings: @sandbox.bindings, id: :command_input) %>
</div>
</div>
</div>
</div>
<%= live_component(SidebarComponent,
sandbox: @sandbox, contextual_help: @contextual_help, suggestions: @suggestions)
%>
</div>
"""
end

# This event comes from HistoryComponent
@impl true
def handle_info({:show_function_docs, contextual_help}, socket) do
Expand Down
16 changes: 0 additions & 16 deletions lib/elixir_console_web/live/console_live.html.heex

This file was deleted.

21 changes: 21 additions & 0 deletions lib/elixir_console_web/live/console_live/bindings.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule ElixirConsoleWeb.ConsoleLive.Bindings do
use Surface.Component

@doc "Keyword list of bindings"
prop bindings, :keyword

def render(assigns) do
~F"""
<div class="bg-teal-700 p-2 overflow-y-scroll max-h-1/3">
<h2 class="font-medium">Current Bindings</h2>
<ul>
{#for {key, value} <- @bindings}
<li class="truncate">{key}: <code class="text-teal-300">{inspect(value)}</code></li>
{#else}
<code class="text-teal-300 text-sm">No bindings yet!</code>
{/for}
</ul>
</div>
"""
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ defmodule ElixirConsoleWeb.ConsoleLive.CommandInputComponent do
user experience.
"""

use Phoenix.LiveComponent
use Surface.Component
import ElixirConsoleWeb.ConsoleLive.Helpers
alias ElixirConsole.Autocomplete

prop input_value, :string
prop caret_position, :integer

def mount(socket) do
{:ok,
assign(
Expand All @@ -19,6 +22,27 @@ defmodule ElixirConsoleWeb.ConsoleLive.CommandInputComponent do
)}
end

def render(assigns) do
~F"""
<form phx-submit="execute" id="command_input" phx-target="#command_input">
<div class="text-gray-200 font-medium flex bg-teal-700 p-2">
{print_prompt()}
<input
type="text"
id="commandInput"
class="ml-2 bg-transparent flex-1 outline-none"
autocomplete="off"
autofocus
name="command"
phx-hook="CommandInput"
data-input_value={@input_value}
data-caret_position={@caret_position}
/>
</div>
</form>
"""
end

defp ensure_number(value) when is_number(value),
do: value

Expand Down

This file was deleted.

27 changes: 27 additions & 0 deletions lib/elixir_console_web/live/console_live/contextual_help.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule ElixirConsoleWeb.ConsoleLive.ContextualHelp do
use Surface.Component

@doc "Link to documentation in hexdocs.pm"
prop link, :string

@doc "Name of the function"
prop func_name, :string

@doc "Header of the documentation"
prop header, :string

@doc "Body of the documentation"
prop doc, :string

def render(assigns) do
~F"""
<div id="documentation-output">
<span class="mb-8 font-bold text-green-400">
<a href={@link} target="_blank" class="underline">{@func_name}</a>
</span>
<span class="text-xs mb-4 font-bold text-gray-200">{@header}</span>
<span class="contextual-help-doc text-xs text-gray-200">{Phoenix.HTML.raw @doc}</span>
</div>
"""
end
end
29 changes: 28 additions & 1 deletion lib/elixir_console_web/live/console_live/history_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,38 @@ defmodule ElixirConsoleWeb.ConsoleLive.HistoryComponent do
commands and results are displayed.
"""

use Phoenix.LiveComponent
use Surface.LiveComponent
import Phoenix.HTML, only: [sigil_e: 2]
import ElixirConsoleWeb.ConsoleLive.Helpers
alias ElixirConsole.ContextualHelp

prop output, :keyword

@impl true
def render(assigns) do
~F"""
<div class="p-2" id="commandOutput" phx-update="append">
<div id="version-info" class="text-gray-400 font-medium">
<p>Elixir {System.version()}/OTP {System.otp_release()}</p>
</div>
{#for output <- @output}
<div id={"command#{output.id}"} class="text-gray-200 font-medium">
{print_prompt()}{format_command(output.command)}
</div>
<div id={"output#{output.id}"} class="text-teal-300">
{output.result}
{#if output.error}
<span class="text-pink-400">
{output.error}
</span>
{/if}
</div>
{/for}
</div>
"""
end

@impl true
def handle_event(
"function_link_clicked",
%{"func_name" => func_name, "header" => header, "doc" => doc, "link" => link},
Expand Down

This file was deleted.

19 changes: 19 additions & 0 deletions lib/elixir_console_web/live/console_live/instructions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule ElixirConsoleWeb.ConsoleLive.Instructions do
use Surface.Component

def render(assigns) do
~F"""
<h2 class="underline mb-3">INSTRUCTIONS</h2>
<p>[UP] [DOWN]: Navigate through commands history</p>
<p>[TAB]: Get suggestions or autocomplete while typing</p>
<p class="text-sm mt-3"> You can see the history panel that includes all your commands and their output.
Click on any Elixir function to see here the corresponding documentation.</p>
<h2 class="underline mt-5 mb-3">ABOUT SECURITY</h2>
<p class="text-sm">Please note some features of the language are not safe to run in a shared environment like this console.
If you are interested in knowing more about the limitations, you must <a class="underline" href="https://github.com/wyeworks/elixir_console#how-much-elixir-can-i-run-in-the-web-console">read here</a>.</p>
<p class="text-sm">Please report any security vulnerabilities to
<a class="underline" href="mailto:[email protected]">[email protected]</a>.
</p>
"""
end
end
27 changes: 26 additions & 1 deletion lib/elixir_console_web/live/console_live/sidebar_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,30 @@ defmodule ElixirConsoleWeb.ConsoleLive.SidebarComponent do
information.
"""

use Phoenix.LiveComponent
use Surface.Component

alias ElixirConsoleWeb.ConsoleLive.{Bindings, Suggestions, ContextualHelp, Instructions}

prop sandbox, :map

prop suggestions, :list

prop contextual_help, :map

def render(assigns) do
~F"""
<div class="w-full sm:w-32 md:w-1/3 h-32 sm:h-full bg-teal-800 text-gray-200 overflow-scroll flex flex-col">
<Bindings bindings={@sandbox.bindings} />
<div class="flex-1 flex flex-col justify-end p-2">
{#if @suggestions != []}
<Suggestions suggestions={@suggestions}/>
{#elseif @contextual_help}
<ContextualHelp {...@contextual_help} />
{#else}
<Instructions />
{/if}
</div>
</div>
"""
end
end

This file was deleted.

17 changes: 17 additions & 0 deletions lib/elixir_console_web/live/console_live/suggestions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule ElixirConsoleWeb.ConsoleLive.Suggestions do
use Surface.Component

@doc "List of suggestions"
prop suggestions, :list

def render(assigns) do
~F"""
<h2 class="font-medium">Suggestions:</h2>
<ul id="suggestions-list">
{#for suggestion <- @suggestions}
<li>{suggestion}</li>
{/for}
</ul>
"""
end
end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ defmodule ElixirConsole.MixProject do
{:earmark, "~> 1.4.0"},
{:floki, "~> 0.31.0", only: :test},
{:sentry, "~> 7.0"},
{:surface, "~> 0.5.2"},
{:wallaby, "~> 0.28", only: :test, runtime: false}
]
end
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"sentry": {:hex, :sentry, "7.2.1", "ea6a5d26c4afef97bf21e09612ebe8d97b525b7822429092926377cd82c08f9e", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "8d1a9469095a83ff8575d16dc1b4d73f5444f3da1ded89a44ce8b85481180089"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"surface": {:hex, :surface, "0.5.2", "905e90a348eb788732adc474d88cce5627f8a202227492498b296d230b5f4f9c", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.15", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "c98562ee29323a906b2715059fbaf9bd566674fce19dd0ca71e2a51c457a80dd"},
"telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"},
"tesla": {:hex, :tesla, "1.4.3", "f5a494e08fb1abe4fd9c28abb17f3d9b62b8f6fc492860baa91efb1aab61c8a0", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "e0755bb664bf4d664af72931f320c97adbf89da4586670f4864bf259b5750386"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
Expand Down