diff --git a/lib/cesium_link/links.ex b/lib/cesium_link/links.ex index 9d05aa4..b2c8e13 100644 --- a/lib/cesium_link/links.ex +++ b/lib/cesium_link/links.ex @@ -64,7 +64,11 @@ defmodule CesiumLink.Links do """ def list_unarchived_links_by_index do - Repo.all(from l in Link, where: l.archived == false, order_by: [asc: l.index]) + Link + |> where([l], fragment("? <= now() OR ? IS NULL", l.publish_at, l.publish_at)) + |> where([l], not l.archived) + |> order_by([l], asc: l.index) + |> Repo.all() end @doc """ diff --git a/lib/cesium_link/links/link.ex b/lib/cesium_link/links/link.ex index e30d9d5..c9f8d39 100644 --- a/lib/cesium_link/links/link.ex +++ b/lib/cesium_link/links/link.ex @@ -5,7 +5,7 @@ defmodule CesiumLink.Links.Link do use CesiumLink.Schema @required_fields ~w(name emoji url attention edited_at)a - @optional_fields ~w(index archived visits)a + @optional_fields ~w(index archived visits publish_at)a schema "links" do field :archived, :boolean, default: false @@ -16,6 +16,7 @@ defmodule CesiumLink.Links.Link do field :url, :string field :visits, :integer, default: 0 field :edited_at, :utc_datetime + field :publish_at, :utc_datetime timestamps(type: :utc_datetime) end diff --git a/lib/cesium_link_web/live/link_live/form_component.ex b/lib/cesium_link_web/live/link_live/form_component.ex index dff7386..9f1e0a7 100644 --- a/lib/cesium_link_web/live/link_live/form_component.ex +++ b/lib/cesium_link_web/live/link_live/form_component.ex @@ -19,6 +19,9 @@ defmodule CesiumLinkWeb.LinkLive.FormComponent do <.input field={@form[:emoji]} type="emoji" label="Emoji" /> <.input field={@form[:url]} type="text" label="URL" /> <.input field={@form[:attention]} type="checkbox" label="Attention" /> + <%= if @action == :new do %> + <.input field={@form[:publish_at]} type="datetime-local" label="Publish At" /> + <% end %> <:actions> <.button phx-disable-with="Saving...">Save Link diff --git a/lib/cesium_link_web/live/link_live/index.html.heex b/lib/cesium_link_web/live/link_live/index.html.heex index 3be9618..7c5d6f1 100644 --- a/lib/cesium_link_web/live/link_live/index.html.heex +++ b/lib/cesium_link_web/live/link_live/index.html.heex @@ -15,30 +15,46 @@ <.table id="links" rows={@streams.links} phx-hook="Sorting"> - <:col :let={{_id, _link}}><.icon name="hero-bars-3 cursor-pointer ml-4" class="handle w-5 h-5" /> + <:col :let={{_id, _link}}> + <% publish_future = _link.publish_at && DateTime.compare(_link.publish_at, DateTime.utc_now()) == :gt %> + <.icon name="hero-bars-3 cursor-pointer ml-4" class={"handle w-5 h-5 #{if publish_future, do: "opacity-50"}"} /> + <:col :let={{_id, link}} label="Name"> -

<%= link.name %>

+ <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> +

<%= link.name %>

<:col :let={{_id, link}} label="Emoji"> - <.emoji code={link.emoji} /> + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> + + <.emoji code={link.emoji} /> + <:col :let={{_id, link}} label="URL"> - <.link target="_blank" class="hover:text-brand hover:underline" navigate={link.url}> + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> + <.link target="_blank" class={"hover:text-brand hover:underline #{if publish_future, do: "opacity-50"}"} navigate={link.url}> <%= truncate_elipsis(link.url, 50) %> - <:col :let={{_id, link}} label="Clicks"><%= link.visits %> + <:col :let={{_id, link}} label="Clicks"> + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> +

+ <%= link.visits %> +

+ <:col :let={{_id, link}} label="Attention"> - + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> + <:action :let={{_id, link}}> + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> <.link patch={~p"/admin/links/#{link}/edit"}> - <.icon name="hero-pencil" class="w-5 h-5" /> + <.icon name="hero-pencil" class={"w-5 h-5 #{if publish_future, do: "opacity-50"}"} /> <:action :let={{_id, link}}> + <% publish_future = link.publish_at && DateTime.compare(link.publish_at, DateTime.utc_now()) == :gt %> <.link patch={~p"/admin/links/#{link}/archive"}> - <.icon name="hero-archive-box" class="w-5 h-5" /> + <.icon name="hero-archive-box" class={"w-5 h-5 #{if publish_future, do: "opacity-50"}"} /> diff --git a/priv/repo/migrations/20240918181533_add_link_scheduling.exs b/priv/repo/migrations/20240918181533_add_link_scheduling.exs new file mode 100644 index 0000000..2fd3685 --- /dev/null +++ b/priv/repo/migrations/20240918181533_add_link_scheduling.exs @@ -0,0 +1,9 @@ +defmodule CesiumLink.Repo.Migrations.AddLinkScheduling do + use Ecto.Migration + + def change do + alter table(:links) do + add :publish_at, :utc_datetime + end + end +end