diff --git a/lib/philomena/static_pages/version.ex b/lib/philomena/static_pages/version.ex new file mode 100644 index 00000000..f6309f83 --- /dev/null +++ b/lib/philomena/static_pages/version.ex @@ -0,0 +1,27 @@ +defmodule Philomena.StaticPages.Version do + use Ecto.Schema + import Ecto.Changeset + + alias Philomena.StaticPages.StaticPage + alias Philomena.Users.User + + schema "static_page_versions" do + belongs_to :static_page, StaticPage + belongs_to :user, User + + field :title, :string + field :slug, :string + field :body, :string + + field :difference, :any, virtual: true + + timestamps(inserted_at: :created_at) + end + + @doc false + def changeset(version, attrs) do + version + |> cast(attrs, []) + |> validate_required([]) + end +end diff --git a/lib/philomena_web/controllers/page/history_controller.ex b/lib/philomena_web/controllers/page/history_controller.ex new file mode 100644 index 00000000..822b8873 --- /dev/null +++ b/lib/philomena_web/controllers/page/history_controller.ex @@ -0,0 +1,35 @@ +defmodule PhilomenaWeb.Page.HistoryController do + use PhilomenaWeb, :controller + + alias Philomena.StaticPages.StaticPage + alias Philomena.StaticPages.Version + alias Philomena.Repo + import Ecto.Query + + plug :load_resource, model: StaticPage, id_field: "slug", persisted: true + + def index(conn, _params) do + page = conn.assigns.static_page + + versions = + Version + |> where(static_page_id: ^page.id) + |> preload(:user) + |> order_by(desc: :created_at) + |> Repo.all() + |> generate_differences(page.body) + + render(conn, "index.html", layout_class: "layout--wide", versions: versions) + end + + defp generate_differences(pages, current_body) do + Enum.map_reduce(pages, current_body, fn page, previous_body -> + difference = List.myers_difference(split(previous_body), split(page.body)) + + %{page | difference: difference} + end) + end + + defp split(nil), do: "" + defp split(body), do: String.split(body, "\n") +end \ No newline at end of file diff --git a/lib/philomena_web/templates/page/history/index.html.slime b/lib/philomena_web/templates/page/history/index.html.slime new file mode 100644 index 00000000..cc7429f7 --- /dev/null +++ b/lib/philomena_web/templates/page/history/index.html.slime @@ -0,0 +1,35 @@ +h1 + ' Revision history for + = link @static_page.title, to: Routes.page_path(@conn, :show, @static_page) + +table.table + thead + tr + th User + th Date + th Body + + tbody + = for version <- @versions do + tr + td = link version.user.name, to: Routes.profile_path(@conn, :show, version.user) + td = pretty_time(version.created_at) + td.static-page__diff + = for diff <- version.difference do + = case diff do + - {:eq, lines} -> + = for line <- lines do + = line + = "\n" + + - {:ins, lines} -> + ins.differ + = for line <- lines do + = line + = "\n" + + - {:del, lines} -> + del.differ + = for line <- lines do + = line + = "\n" diff --git a/lib/philomena_web/views/page/history_view.ex b/lib/philomena_web/views/page/history_view.ex new file mode 100644 index 00000000..f84518fa --- /dev/null +++ b/lib/philomena_web/views/page/history_view.ex @@ -0,0 +1,3 @@ +defmodule PhilomenaWeb.Page.HistoryView do + use PhilomenaWeb, :view +end