diff --git a/assets/js/alpine_helpers.js b/assets/js/alpine_helpers.js index 56a7d93..2d8bd93 100644 --- a/assets/js/alpine_helpers.js +++ b/assets/js/alpine_helpers.js @@ -35,3 +35,10 @@ window.markVersionAsSeen = (versionString) => { window.isVersionSeen = (versionString) => { return localStorage.getItem('seenVersion') === versionString } + +window.dispatchFor = (elementOrId, eventName, detail = {}) => { + const element = + typeof elementOrId === 'string' ? document.getElementById(elementOrId) : elementOrId + + element.dispatchEvent(new CustomEvent(eventName, { detail })) +} diff --git a/assets/js/app.js b/assets/js/app.js index 2be596d..f9accf3 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -39,7 +39,7 @@ let liveSocket = new LiveSocket(document.body.dataset.socketPath, Socket, { } }, hooks: { - supressEnterSubmission: { + 'supress-enter-submission': { mounted() { this.el.addEventListener('keypress', (event) => { if (event.key === 'Enter') { @@ -47,6 +47,29 @@ let liveSocket = new LiveSocket(document.body.dataset.socketPath, Socket, { } }) } + }, + 'formless-input': { + mounted() { + const subscribedEvents = this.el.dataset.subscribe.split(' ') + const eventName = this.el.dataset.eventName || '' + const identifier = this.el.dataset.identifier || '' + + subscribedEvents.forEach((domEvent) => { + this.el.addEventListener(domEvent, () => { + // This ensures that the event is pushed to the server after the input value has been updated + // so that the server has the most up-to-date value + setTimeout(() => { + this.pushEvent('formless-input', { + value: this.el.value, + id: identifier, + event: eventName, + dom_id: this.el.id, + dom_event: domEvent + }) + }, 0) + }) + }) + } } } }) diff --git a/lib/pinchflat/profiles/profiles_query.ex b/lib/pinchflat/profiles/profiles_query.ex new file mode 100644 index 0000000..caa1315 --- /dev/null +++ b/lib/pinchflat/profiles/profiles_query.ex @@ -0,0 +1,29 @@ +defmodule Pinchflat.Profiles.ProfilesQuery do + @moduledoc """ + Query helpers for the Profiles context. + + These methods are made to be one-ish liners used + to compose queries. Each method should strive to do + _one_ thing. These don't need to be tested as + they are just building blocks for other functionality + which, itself, will be tested. + """ + import Ecto.Query, warn: false + + alias Pinchflat.Profiles.MediaProfile + + # This allows the module to be aliased and query methods to be used + # all in one go + # usage: use Pinchflat.Profiles.ProfilesQuery + defmacro __using__(_opts) do + quote do + import Ecto.Query, warn: false + + alias unquote(__MODULE__) + end + end + + def new do + MediaProfile + end +end diff --git a/lib/pinchflat_web/components/core_components.ex b/lib/pinchflat_web/components/core_components.ex index 0bad772..0aeb34f 100644 --- a/lib/pinchflat_web/components/core_components.ex +++ b/lib/pinchflat_web/components/core_components.ex @@ -340,14 +340,15 @@ defmodule PinchflatWeb.CoreComponents do end) ~H""" -