From 4edb5361f85047a8df544539bbfd40626c5d3ecd Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Sun, 24 Nov 2024 02:56:06 +0700 Subject: [PATCH] Events page (#30) * Add events Signed-off-by: Oliver Tale-Yazdi * typo Signed-off-by: Oliver Tale-Yazdi * Events Signed-off-by: Oliver Tale-Yazdi * build Signed-off-by: Oliver Tale-Yazdi * fix merge Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi --- build.sh | 2 + lib/phoenix_app/events.ex | 2 + lib/phoenix_app/events/event.ex | 31 +++++ lib/phoenix_app/teams/event.ex | 25 ---- .../controllers/event_controller.ex | 5 + .../controllers/page_controller.ex | 5 +- lib/phoenix_app_web/router.ex | 1 + .../templates/event/index.html.heex | 28 +++- .../templates/event/show.html.heex | 131 ++++++++++++++++++ .../templates/page/index.html.heex | 30 ++-- lib/phoenix_app_web/views/event_view.ex | 54 ++++++++ .../20240713183346_create_events.exs | 8 +- priv/repo/seeds_events.exs | 27 +++- 13 files changed, 303 insertions(+), 46 deletions(-) create mode 100644 lib/phoenix_app/events/event.ex delete mode 100644 lib/phoenix_app/teams/event.ex create mode 100644 lib/phoenix_app_web/templates/event/show.html.heex diff --git a/build.sh b/build.sh index 57020c4..8ab17ac 100644 --- a/build.sh +++ b/build.sh @@ -2,4 +2,6 @@ set -e +rm -rf _build + mix deps.get && MIX_ENV=prod mix compile && MIX_ENV=prod mix assets.deploy && MIX_ENV=prod mix release --overwrite && MIX_ENV=prod mix ecto.drop && MIX_ENV=prod mix ecto.setup diff --git a/lib/phoenix_app/events.ex b/lib/phoenix_app/events.ex index b88110f..881c920 100644 --- a/lib/phoenix_app/events.ex +++ b/lib/phoenix_app/events.ex @@ -7,4 +7,6 @@ defmodule PhoenixApp.Events do def list_events do Repo.all(from e in Event, order_by: :name) end + + def get_event!(id), do: Repo.get!(Event, id) end diff --git a/lib/phoenix_app/events/event.ex b/lib/phoenix_app/events/event.ex new file mode 100644 index 0000000..d484eb5 --- /dev/null +++ b/lib/phoenix_app/events/event.ex @@ -0,0 +1,31 @@ +defmodule PhoenixApp.Events.Event do + use Ecto.Schema + import Ecto.Changeset + + schema "events" do + field :name, :string + field :short, :string + field :long, :string + field :links, {:array, :string} + field :learn_more_id, :integer, default: 0 + field :contact, {:array, :string} + field :when_from, :date + field :when_to, :date + field :when_est, :string + field :where, :string + field :where_link, :string + field :duration, :string + field :historic, :boolean, default: false + + timestamps() + end + + @all [:homepage, :name, :contact, :where] + + @doc false + def changeset(team, attrs) do + team + |> cast(attrs, @all ++ [:when_to, :when_from, :when_est, :where_link, :duration, :long, :short, :links, :historic, :learn_more_id]) + |> validate_required(@all) + end +end diff --git a/lib/phoenix_app/teams/event.ex b/lib/phoenix_app/teams/event.ex deleted file mode 100644 index 44000d2..0000000 --- a/lib/phoenix_app/teams/event.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule PhoenixApp.Events.Event do - use Ecto.Schema - import Ecto.Changeset - - schema "events" do - field :name, :string - field :description, :string - field :links, {:array, :string} - field :contact, {:array, :string} - field :when_from, :date - field :when_to, :date - field :where, :string - - timestamps() - end - - @all [:description, :homepage, :name, :contact, :when_from, :when_to, :where] - - @doc false - def changeset(team, attrs) do - team - |> cast(attrs, @all) - |> validate_required(@all) - end -end diff --git a/lib/phoenix_app_web/controllers/event_controller.ex b/lib/phoenix_app_web/controllers/event_controller.ex index f1d1dd9..2a4d182 100644 --- a/lib/phoenix_app_web/controllers/event_controller.ex +++ b/lib/phoenix_app_web/controllers/event_controller.ex @@ -8,4 +8,9 @@ defmodule PhoenixAppWeb.EventController do num = length(events) render(conn, "index.html", events: events, num_events: num) end + + def show(conn, %{"id" => id}) do + event = Events.get_event!(id) + render(conn, "show.html", event: event) + end end diff --git a/lib/phoenix_app_web/controllers/page_controller.ex b/lib/phoenix_app_web/controllers/page_controller.ex index 1d13258..66ef08d 100644 --- a/lib/phoenix_app_web/controllers/page_controller.ex +++ b/lib/phoenix_app_web/controllers/page_controller.ex @@ -1,8 +1,11 @@ defmodule PhoenixAppWeb.PageController do use PhoenixAppWeb, :controller + alias PhoenixApp.Events + def index(conn, _params) do - render(conn, "index.html") + events = Events.list_events() + render(conn, "index.html", events: events) end def spec(conn, _params) do diff --git a/lib/phoenix_app_web/router.ex b/lib/phoenix_app_web/router.ex index aaeb6c1..df08524 100644 --- a/lib/phoenix_app_web/router.ex +++ b/lib/phoenix_app_web/router.ex @@ -30,6 +30,7 @@ defmodule PhoenixAppWeb.Router do get("/", PageController, :index) get("/spec", PageController, :spec) get("/tech", PageController, :tech) + resources("/events", EventController, only: [:index, :show]) resources("/clients/json", TeamJsonController, only: [:index]) resources("/clients", TeamController, only: [:index, :show]) diff --git a/lib/phoenix_app_web/templates/event/index.html.heex b/lib/phoenix_app_web/templates/event/index.html.heex index 202533d..1b5eb58 100644 --- a/lib/phoenix_app_web/templates/event/index.html.heex +++ b/lib/phoenix_app_web/templates/event/index.html.heex @@ -10,18 +10,38 @@
- <%= for event <- @events do %> - <%= link to: hd(event.links), class: "block w-full" do %> + <%= for event <- Enum.reject(@events, & &1.historic) do %> + <%= link to: Routes.event_path(@conn, :show, event), class: "block w-full" do %>

<%= event.name %>

-

<%= event.where %> <%= event.when_from %> - <%= event.when_to %>

-

<%= event.description %>

+

<%= event.where %> · <%= fmt_when(event) %>

+

<%= event.short %>

<% end %> <% end %>
+ + <%= if Enum.any?(@events, & &1.historic) do %> +

Past Events

+ +
+
+ <%= for event <- Enum.filter(@events, & &1.historic) do %> + <%= link to: Routes.event_path(@conn, :show, event), class: "block w-full" do %> +
+
+

<%= event.name %>

+

<%= event.where %> · <%= fmt_when(event) %>

+

<%= event.short %>

+
+
+ <% end %> + <% end %> +
+
+ <% end %>
diff --git a/lib/phoenix_app_web/templates/event/show.html.heex b/lib/phoenix_app_web/templates/event/show.html.heex new file mode 100644 index 0000000..7a9edcc --- /dev/null +++ b/lib/phoenix_app_web/templates/event/show.html.heex @@ -0,0 +1,131 @@ +
+
+
+
+
+

<%= @event.name %>

+ <%= if @event.short do %> +

<%= @event.short %>

+ <% end %> +
+
+
+
+ + <%= if @event.historic do %> +
+
+
+ + + +

This event already happened and is shown for archival purposes only.

+
+
+
+ <% end %> + +
+
+
+ <%# Main Content %> +
+
+
+

About This Event

+
+ <%= raw(fmt_desc(@event)) %> +
+
+
+ + <%# Contact Information %> + <%= if @event.contact && length(@event.contact) > 0 do %> +
+

Contact Information

+
+ <%= for contact <- @event.contact do %> +

<%= contact %>

+ <% end %> +
+
+ <% end %> + + <%= if @event.links && length(@event.links) > 0 do %> +
+

Related Links

+
+ <%= for {link, index} <- Enum.with_index(@event.links) do %> +
+ <%= index + 1 %>: + <%= link link, + to: link, + class: "text-blue-400 hover:text-blue-300", + target: "_blank" %> +
+ <% end %> +
+
+ <% end %> +
+ + <%# Sidebar %> +
+
+ <%# Date Information %> +
+ + + +
+

Date

+ <%= if @event.when_from do %> +

+ <%= Calendar.strftime(@event.when_from, "%B %d, %Y") %> + <%= if @event.when_to && @event.when_to != @event.when_from do %> + - <%= Calendar.strftime(@event.when_to, "%B %d, %Y") %> + <% end %> + <%= fmt_duration(@event) %> +

+ <% end %> + <%= if @event.when_est do %> +

+ <%= @event.when_est %> <%= fmt_duration(@event) %> +

+ <% end %> +
+
+ + <%# Location %> +
+ + + + +
+

Location

+ <%= if @event.where_link do %> + <%= link to: @event.where_link, class: "text-white hover:text-blue-300" do %> + <%= @event.where %> + + <% end %> + <% else %> +

<%= @event.where %>

+ <% end %> +
+
+
+ + <%# Call to Action %> + <%= if @event.links && length(@event.links) > 0 do %> +
+ <%= link "Learn More", + to: Enum.at(@event.links, @event.learn_more_id), + class: "w-full px-6 py-3 bg-blue-500 hover:bg-blue-600 text-white font-semibold rounded-lg transition-colors duration-200" %> +
+ <% end %> +
+
+
+
+
diff --git a/lib/phoenix_app_web/templates/page/index.html.heex b/lib/phoenix_app_web/templates/page/index.html.heex index 6feb433..3afd372 100644 --- a/lib/phoenix_app_web/templates/page/index.html.heex +++ b/lib/phoenix_app_web/templates/page/index.html.heex @@ -44,18 +44,24 @@

-
-

NEWS

-
-
-

- JAM0 Meetup Proposal -

-

- An OpenGov proposal is up for vote to decide whether to fund a meetup at Devcon 7, where JAM implementor teams can collaborate. -

- <%= link "Read more", to: "https://polkadot.polkassembly.io/referenda/1024", class: "text-indigo-600 hover:text-blue-300", target: "_blank" %> -
+
+

+ <%= link "EVENTS", to: Routes.event_path(@conn, :index), class: "text-indigo-600 hover:text-blue-300" %> +

+
+ <%= for event <- @events do %> + <%= link to: Routes.event_path(@conn, :show, event), class: "block w-full" do %> +
+
+

+ <%= event.name %> +

+

<%= event.where %> · <%= PhoenixAppWeb.EventView.fmt_when(event) %>

+

<%= event.short %>

+
+
+ <% end %> + <% end %>
diff --git a/lib/phoenix_app_web/views/event_view.ex b/lib/phoenix_app_web/views/event_view.ex index c9cd9f3..3861931 100644 --- a/lib/phoenix_app_web/views/event_view.ex +++ b/lib/phoenix_app_web/views/event_view.ex @@ -1,3 +1,57 @@ defmodule PhoenixAppWeb.EventView do use PhoenixAppWeb, :view + + alias PhoenixApp.Events.Event + + def fmt_when(%Event{when_from: from, when_to: to} = event) when not is_nil(from) and not is_nil(to) do + """ + #{event.when_from} - #{event.when_to} + """ + end + + def fmt_when(%Event{when_est: est} = event) when not is_nil(est) do + """ + #{event.when_est} + """ + end + + def fmt_when(%Event{} = event) do + raise ArgumentError, "Event has no date: #{inspect(event)}" + end + + def fmt_duration(%Event{duration: duration} = event) when not is_nil(duration) do + """ + (#{event.duration}) + """ + end + + def fmt_duration(%Event{}) do + "" + end + + # Format MD links to HTML links by looking up the links from a list. + # For example: + # >Make sure to join the [1](Matrix chat) for updates. + # becomes: + # >Make sure to join the Matrix chat for updates. +def fmt_desc(%Event{long: desc, links: links} = _event) when not is_nil(desc) and is_list(links) do + matches = Regex.scan(~r/\[([0-9]+)\]\(([^)]+)\)/, desc) + Enum.reduce(matches, desc, fn [full_match, idx_str, name], acc -> + case Integer.parse(idx_str) do + {idx, _} -> + link = Enum.at(links, idx) + if link do + String.replace(acc, full_match, + "#{name}#{idx + 1}") + else + acc + end + _ -> acc + end + end) + |> String.replace(~r/\n/, "
") + end + + def fmt_desc(%Event{long: desc}) when not is_nil(desc), do: desc + def fmt_desc(_), do: "" end diff --git a/priv/repo/migrations/20240713183346_create_events.exs b/priv/repo/migrations/20240713183346_create_events.exs index 36c8a03..debf4d4 100644 --- a/priv/repo/migrations/20240713183346_create_events.exs +++ b/priv/repo/migrations/20240713183346_create_events.exs @@ -4,12 +4,18 @@ defmodule PhoenixApp.Repo.Migrations.CreateEvents do def change do create table(:events) do add :name, :string - add :description, :text + add :short, :text + add :long, :text add :links, {:array, :string} + add :learn_more_id, :integer, default: 0 add :contact, {:array, :string} add :when_from, :date add :when_to, :date + add :when_est, :string add :where, :string + add :where_link, :string + add :duration, :string + add :historic, :boolean, default: false timestamps() end diff --git a/priv/repo/seeds_events.exs b/priv/repo/seeds_events.exs index 4616994..92fc6e5 100644 --- a/priv/repo/seeds_events.exs +++ b/priv/repo/seeds_events.exs @@ -3,10 +3,31 @@ alias PhoenixApp.Events.Event Repo.insert!(%Event{ name: "JAM0", - description: "Implementor meetup near Sub0 and Devcon in Bangkok.", - links: ["https://polkadot.subsquare.io/referenda/1024"], + short: "Implementor meetup near Sub0 and Devcon in Bangkok.", + long: """ + Meetup for JAM implementors in Bangkok. + Organized and sponsored by by [0](Colorful Notion) after Polkadot OpenGov proposal [1](#1024) was rejected. Sign-up and updates happen in this [2](Matrix chanel). + """, + links: ["https://colorfulnotion.com/", "https://polkadot.subsquare.io/referenda/1024", "https://app.element.io/#/room/!KKOmuUpvYKPcniwOzw:matrix.org"], + learn_more_id: 1, # What link index to pick for the "Learn more" button. contact: [], when_from: ~D[2024-11-09], when_to: ~D[2024-11-16], - where: "Valia Hotel, Bangkok, Thailand" + where: "Valia Hotel, Bangkok, Thailand", + where_link: "https://maps.app.goo.gl/oJCtRg9C3UWQgtmE6", + historic: true +}) + +Repo.insert!(%Event{ + name: "JAM Meetup", + short: "Implementor meetup and tour of the JAM toaster.", + long: """ + This event is currently being planned. Make sure to join the [0](Matrix chat) for updates. + """, + links: ["https://app.element.io/#/room/!KKOmuUpvYKPcniwOzw:matrix.org"], + contact: [], + when_est: "March, 2025", + where: "Cascais, Portugal", + where_link: "https://maps.app.goo.gl/rdZQDbF7TtKeaHd2A", + duration: "3 days", })