Skip to content

Commit

Permalink
feat: Trying to get the highlight to work on the client of Phoenix. #145
Browse files Browse the repository at this point in the history
  • Loading branch information
LuchoTurtle committed Mar 31, 2023
1 parent 7d5a8be commit 9b1a7f5
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 4 deletions.
14 changes: 14 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,17 @@ input[type=radio].has-error:not(.phx-no-feedback) {
}

[x-cloak] { display: none !important; }


/* For the drag and drop feature */
.cursor-grab{
cursor: grab;
}

.cursor-grabbing{
cursor: grabbing;
}

.bg-yellow-300{
background-color: rgb(253 224 71);
}
60 changes: 60 additions & 0 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,33 @@ import topbar from "../vendor/topbar"


let Hooks = {}
Hooks.Items = {
mounted() {
const hook = this

this.el.addEventListener("highlight", e => {
hook.pushEventTo("#items", "highlight", {id: e.detail.id})
})

this.el.addEventListener("remove-highlight", e => {
hook.pushEventTo("#items", "remove-highlight", {id: e.detail.id})
})

this.el.addEventListener("dragoverItem", e => {
const currentItemId = e.detail.currentItemId
const selectedItemId = e.detail.selectedItemId
if( currentItemId != selectedItemId) {
hook.pushEventTo("#items", "dragoverItem", {currentItemId: currentItemId, selectedItemId: selectedItemId})
}
})

this.el.addEventListener("update-indexes", e => {
const ids = [...document.querySelectorAll(".item")].map( i => i.dataset.id)
hook.pushEventTo("#items", "updateIndexes", {ids: ids})
})
}
}

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")

let liveSocket = new LiveSocket("/live", Socket, {
Expand All @@ -27,6 +54,39 @@ topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide())

// Drag and drop highlight handlers
window.addEventListener("phx:highlight", (e) => {
document.querySelectorAll("[data-highlight]").forEach(el => {
if(el.id == e.detail.id) {
liveSocket.execJS(el, el.getAttribute("data-highlight"))
}
})
})

window.addEventListener("phx:remove-highlight", (e) => {
document.querySelectorAll("[data-highlight]").forEach(el => {
if(el.id == e.detail.id) {
liveSocket.execJS(el, el.getAttribute("data-remove-highlight"))
}
})
})

window.addEventListener("phx:dragover-item", (e) => {
const selectedItem = document.querySelector(`#${e.detail.selected_item_id}`)
const currentItem = document.querySelector(`#${e.detail.current_item_id}`)

const items = document.querySelector('#items')
const listItems = [...document.querySelectorAll('.item')]

if(listItems.indexOf(selectedItem) < listItems.indexOf(currentItem)){
items.insertBefore(selectedItem, currentItem.nextSibling)
}

if(listItems.indexOf(selectedItem) > listItems.indexOf(currentItem)){
items.insertBefore(selectedItem, currentItem)
}
})

// connect if there are any LiveViews on the page
liveSocket.connect()

Expand Down
3 changes: 2 additions & 1 deletion lib/app/item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,14 @@ defmodule App.Item do
"""
def list_items do
Item
|> order_by(desc: :inserted_at)
|> order_by(desc: :position)
|> where([i], is_nil(i.status) or i.status != 6)
|> Repo.all()
end

def list_person_items(person_id) do
Item
|> order_by(desc: :position)
|> where(person_id: ^person_id)
|> Repo.all()
|> Repo.preload(tags: from(t in Tag, order_by: t.text))
Expand Down
55 changes: 54 additions & 1 deletion lib/app_web/live/app_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ defmodule AppWeb.AppLive do
use AppWeb, :live_view
use Timex
alias App.{Item, Tag, Timer}
alias Phoenix.PubSub
alias Phoenix.Socket.Broadcast
alias Phoenix.LiveView.JS

# run authentication on mount
on_mount(AppWeb.AuthController)
alias Phoenix.Socket.Broadcast

@topic "live"
@stats_topic "stats"
Expand Down Expand Up @@ -220,6 +223,55 @@ defmodule AppWeb.AppLive do
end
end

@impl true
def handle_event("highlight", %{"id" => id}, socket) do
AppWeb.Endpoint.broadcast(@topic, "liveview_items", {:drag_item, id})
{:noreply, socket}
end

@impl true
def handle_event("remove-highlight", %{"id" => id}, socket) do
AppWeb.Endpoint.broadcast(@topic, "liveview_items", {:drop_item, id})
{:noreply, socket}
end

@impl true
def handle_event(
"dragoverItem",
%{"currentItemId" => current_item_id, "selectedItemId" => selected_item_id},
socket
) do

AppWeb.Endpoint.broadcast(@topic, "liveview_items", {:dragover_item, {current_item_id, selected_item_id }})
{:noreply, socket}
end


@impl true
def handle_info(%Broadcast{event: "liveview_items", payload: {:dragover_item, {current_item_id, selected_item_id}}}, socket) do
{:noreply,
push_event(socket, "dragover-item", %{
current_item_id: current_item_id,
selected_item_id: selected_item_id
})}
end

@impl true
def handle_info(%Broadcast{event: "liveview_items", payload: {:drag_item, item_id}}, socket) do
{:noreply, push_event(socket, "highlight", %{id: item_id})}
end

@impl true
def handle_info(%Broadcast{event: "liveview_items", payload: {:drop_item, item_id}}, socket) do
{:noreply, push_event(socket, "remove-highlight", %{id: item_id})}
end

@impl true
def handle_event("updateIndexes", %{"ids" => ids}, socket) do
#Tasks.update_items_index(ids)
{:noreply, socket}
end

@impl true
def handle_info(%Broadcast{event: "update", payload: payload}, socket) do
person_id = get_person_id(socket.assigns)
Expand Down Expand Up @@ -268,6 +320,7 @@ defmodule AppWeb.AppLive do
{:noreply, socket}
end


# only show certain UI elements (buttons) if there are items:
def has_items?(items), do: length(items) > 1

Expand Down
11 changes: 10 additions & 1 deletion lib/app_web/live/app_live.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,20 @@
</div>
</.form>
<!-- List of items with inline buttons and controls -->
<ul class="w-full">
<ul id="items" phx-hook="Items" x-data="{selectedItem: null}" class="w-full">
<%= for item <- filter_items(@items, @filter, @filter_tag) do %>
<li
id={"item-#{item.id}"}
data-id={item.id}
class="mt-2 flex w-full border-t border-slate-200 py-2"
draggable="true"
x-data="{selected: false}"
x-on:dragstart="selected = true; $dispatch('highlight', {id: $el.id}); selectedItem = $el"
x-on:dragend="selected = false; $dispatch('remove-highlight', {id: $el.id}); selectedItem = null; $dispatch('update-indexes')"
x-bind:class="selected ? 'cursor-grabbing' : 'cursor-grab'"
x-on:dragover.throttle="$dispatch('dragoverItem', {selectedItemId: selectedItem.id, currentItemId: $el.id})"
data-highlight={JS.add_class("bg-yellow-300")}
data-remove-highlight={JS.remove_class("bg-yellow-300")}
>
<%= if archived?(item) do %>
<label>
Expand Down
2 changes: 1 addition & 1 deletion lib/app_web/templates/layout/root.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self' dwyl.com https://*.cloudflare.com plausible.io;
default-src 'self' dwyl.com https://*.cloudflare.com plausible.io;
connect-src 'self' wss://mvp.fly.dev plausible.io;
form-action 'self';
img-src *; child-src 'none';
Expand Down

0 comments on commit 9b1a7f5

Please sign in to comment.