mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-12-17 21:50:25 +08:00
parent
2694007c0e
commit
fbef386aa8
5 changed files with 118 additions and 0 deletions
|
|
@ -24,6 +24,7 @@ import Timer from "./timer";
|
||||||
import MarkdownRenderer from "./markdown_renderer";
|
import MarkdownRenderer from "./markdown_renderer";
|
||||||
import Highlight from "./highlight";
|
import Highlight from "./highlight";
|
||||||
import ClipCopy from "./clip_copy";
|
import ClipCopy from "./clip_copy";
|
||||||
|
import DragAndDrop from "./darg_and_drop";
|
||||||
import morphdomCallbacks from "./morphdom_callbacks";
|
import morphdomCallbacks from "./morphdom_callbacks";
|
||||||
import { loadUserData } from "./lib/user";
|
import { loadUserData } from "./lib/user";
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ const hooks = {
|
||||||
MarkdownRenderer,
|
MarkdownRenderer,
|
||||||
Highlight,
|
Highlight,
|
||||||
ClipCopy,
|
ClipCopy,
|
||||||
|
DragAndDrop,
|
||||||
};
|
};
|
||||||
|
|
||||||
const csrfToken = document
|
const csrfToken = document
|
||||||
|
|
|
||||||
25
assets/js/darg_and_drop/index.js
Normal file
25
assets/js/darg_and_drop/index.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
const DragAndDrop = {
|
||||||
|
mounted() {
|
||||||
|
const dropZone = this.el.querySelector("[data-dropzone]");
|
||||||
|
|
||||||
|
["dragenter", "dragover"].forEach((eventName) => {
|
||||||
|
dropZone.addEventListener(eventName, highlight, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
["dragleave", "drop"].forEach((eventName) => {
|
||||||
|
dropZone.addEventListener(eventName, unhighlight, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
function highlight(e) {
|
||||||
|
dropZone.classList.add("bg-red-200");
|
||||||
|
dropZone.classList.add("border-red-400");
|
||||||
|
}
|
||||||
|
|
||||||
|
function unhighlight(e) {
|
||||||
|
dropZone.classList.remove("bg-red-200");
|
||||||
|
dropZone.classList.remove("border-red-400");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DragAndDrop;
|
||||||
|
|
@ -14,6 +14,11 @@ config :logger, :console,
|
||||||
# Use Jason for JSON parsing in Phoenix
|
# Use Jason for JSON parsing in Phoenix
|
||||||
config :phoenix, :json_library, Jason
|
config :phoenix, :json_library, Jason
|
||||||
|
|
||||||
|
# Add mime type to upload notebooks with `Phoenix.LiveView.Upload`
|
||||||
|
config :mime, :types, %{
|
||||||
|
"text/plain" => ["livemd"]
|
||||||
|
}
|
||||||
|
|
||||||
# Sets the default authentication mode to token
|
# Sets the default authentication mode to token
|
||||||
config :livebook, :authentication_mode, :token
|
config :livebook, :authentication_mode, :token
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,13 @@ defmodule LivebookWeb.HomeLive.ImportComponent do
|
||||||
From clipboard
|
From clipboard
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= live_patch to: Routes.home_path(@socket, :import, "file_upload"),
|
||||||
|
class: "tab #{if(@tab == "file_upload", do: "active")}" do %>
|
||||||
|
<.remix_icon icon="file-upload-line" class="align-middle" />
|
||||||
|
<span class="font-medium">
|
||||||
|
File upload
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
<div class="flex-grow tab">
|
<div class="flex-grow tab">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -35,4 +42,5 @@ defmodule LivebookWeb.HomeLive.ImportComponent do
|
||||||
|
|
||||||
defp component_for_tab("url"), do: LivebookWeb.HomeLive.ImportUrlComponent
|
defp component_for_tab("url"), do: LivebookWeb.HomeLive.ImportUrlComponent
|
||||||
defp component_for_tab("content"), do: LivebookWeb.HomeLive.ImportContentComponent
|
defp component_for_tab("content"), do: LivebookWeb.HomeLive.ImportContentComponent
|
||||||
|
defp component_for_tab("file_upload"), do: LivebookWeb.HomeLive.ImportFileUploadComponent
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
defmodule LivebookWeb.HomeLive.ImportFileUploadComponent do
|
||||||
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def mount(socket) do
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> assign(:error, false)
|
||||||
|
|> allow_upload(:notebook, accept: ~w(.livemd), max_entries: 1)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div class="flex-col space-y-5">
|
||||||
|
<p class="text-gray-700">
|
||||||
|
Drag and drop a <code>.livemd</code> file below to import it.
|
||||||
|
</p>
|
||||||
|
<form id="upload-file-form"
|
||||||
|
phx-submit="save"
|
||||||
|
phx-change="validate"
|
||||||
|
phx-drop-target={@uploads.notebook.ref}
|
||||||
|
phx-target={@myself}
|
||||||
|
phx-hook="DragAndDrop"
|
||||||
|
class="flex flex-col items-start"
|
||||||
|
>
|
||||||
|
<%= live_file_input @uploads.notebook, class: "hidden" %>
|
||||||
|
<div data-dropzone class="flex flex-col justify-center items-center w-full rounded-xl border-2 border-dashed border-gray-400 h-48">
|
||||||
|
<%= if @uploads.notebook.entries == [] do %>
|
||||||
|
<span name="placeholder" class="font-medium text-gray-400">Drop your notebook here</span>
|
||||||
|
<% else %>
|
||||||
|
<%= for file <- @uploads.notebook.entries do %>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<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>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<%= if @error do %>
|
||||||
|
<div class="text-red-500 text-sm py-2">
|
||||||
|
You can only upload files with .livemd extension.
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<button type="submit" class="mt-5 button button-blue" disabled={@uploads.notebook.entries == [] || @error}>
|
||||||
|
Import
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveComponent
|
||||||
|
def handle_event("clear-file", _params, socket) do
|
||||||
|
{socket, _entries} = Phoenix.LiveView.Upload.maybe_cancel_uploads(socket)
|
||||||
|
{:noreply, assign(socket, error: false)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveComponent
|
||||||
|
def handle_event("validate", _params, socket) do
|
||||||
|
has_error? = Enum.any?(socket.assigns.uploads.notebook.entries, &(not &1.valid?))
|
||||||
|
|
||||||
|
{:noreply, assign(socket, error: has_error?)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveComponent
|
||||||
|
def handle_event("save", _params, socket) do
|
||||||
|
consume_uploaded_entries(socket, :notebook, fn %{path: path}, _entry ->
|
||||||
|
content = File.read!(path)
|
||||||
|
|
||||||
|
send(self(), {:import_content, content, []})
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Reference in a new issue