MishkaCmsCoreWeb. Live. Admin. Components. KitUpgradePanel
(Mishka CMS Core v0.0.1)
Copy Markdown
View Source
Where a site stands against the version of an extension it is running, read and drawn.
Setting a site up installs what it is missing and never touches what it has, which is the only safe thing a button called "Set up" can do — and it leaves a site that was provisioned months ago on months-old components and months-old pages for ever. This is the other half, and it has two halves of its own because a site has two things to fall behind on:
MishkaCmsCore.Runtime.Handlers.UiKitUpgradesays where each of the kit's COMPONENTS stands, and writes the ones the admin chooses;MishkaCmsCore.Runtime.PageSamplessays where each of the extension's sample PAGES stands, and offers the newer ones as drafts. A page is somebody's work in a way a kit component is not — it is what their readers are looking at — so nothing here writes a live page at all. A page whose newer version draws a component this site has not got is not offered either: the two halves fall behind together, and publishing that draft would put an error message where the block should be.
Both report BEFORE anything is written, and the admin decides.
Wiring
One call in mount/3 and three event clauses. Nothing draws this directly: standings/1 is
drawn inside the modal
MishkaCmsCoreWeb.Live.Admin.Components.ExtensionInstallerPanel.doctor_modal/1 opens, which is
where the site picker and the kit_check form live.
socket =
KitUpgradePanel.setup(socket,
bundle: MishkaBlog.Kit.bundle_path(),
noun: "blog components",
pages: &MishkaBlog.Provision.sample_pages/2,
draft_label: "Blog sample page"
)
def handle_event("kit_check", params, socket),
do: {:noreply, KitUpgradePanel.check(socket, chosen_site(socket, params), socket.assigns.may_provision?)}
def handle_event("kit_upgrade", %{"mode" => mode}, socket),
do: {:noreply, KitUpgradePanel.upgrade(socket, mode, socket.assigns.may_provision?)}
def handle_event("page_drafts", _params, socket),
do: {:noreply, KitUpgradePanel.offer(socket, socket.assigns.may_provision?)}Which site the check runs against is the dashboard's answer, not this module's: a tenant admin has
one site and a master picks from the ones their page offered, and that is the same question the
"Set up" button already answers. check/3 takes what chosen_site/2 decided — a site id, :none
or :refused — and the permission the dashboard already computed, so the wording of a refusal is
written once here rather than once per extension.
Why the two component buttons are two
The write is upgrade!/3 with :safe or :all, and nothing here presses :all on the
admin's behalf. A row whose fingerprint no longer matches what the kit installed is a row
somebody worked on, and the only honest thing to do with it is to say so and wait — which is why
the second button spells out that the version being replaced stays in the component's history.
The pages have one button and it is the safe one, because there is no unsafe one to offer: a draft is the whole of what this can do to a page.
Summary
Functions
Reads where the site stands and puts it on the socket. Writes nothing.
Offers every sample page the site is behind on as a draft of itself, and redraws the standings from the database afterwards.
One-call wiring for a dashboard: assigns @kit_upgrade, which standings/1 is given whole.
Writes the components the admin asked for and redraws the standings from the database afterwards.
Functions
@spec check(Phoenix.LiveView.Socket.t(), String.t() | :none | :refused, boolean()) :: Phoenix.LiveView.Socket.t()
Reads where the site stands and puts it on the socket. Writes nothing.
site_id is whatever the dashboard's own site check returned, and allowed? the permission it
already computed — both refusals are answered here so every extension says the same thing.
@spec offer(Phoenix.LiveView.Socket.t(), boolean()) :: Phoenix.LiveView.Socket.t()
Offers every sample page the site is behind on as a draft of itself, and redraws the standings from the database afterwards.
Takes no mode, because there is only one thing to do: a draft is not a change to anything anybody is reading, so there is no second, riskier button for the admin to be asked about.
@spec setup(Phoenix.LiveView.Socket.t(), keyword()) :: Phoenix.LiveView.Socket.t()
One-call wiring for a dashboard: assigns @kit_upgrade, which standings/1 is given whole.
Options
:bundle— the extension's bundle path, e.g.MishkaBlog.Kit.bundle_path().:noun— what this kit's components are called in a sentence ("blog components"), used when a read or a write fails and the admin is told which of them it was about.:pages— a two-argument function from a site id and the actor to the extension's sample pages as attribute maps, e.g.&MishkaBlog.Provision.sample_pages/2. The same function the "Set up" button's own pages come from, so this cannot be comparing against different ones.:draft_label— what a draft this creates is called in the builder's picker.
Where the site stands, given the @kit_upgrade assign setup/2 wrote: the components in one
block and the pages in the other, neither drawn until check/3 has read.
The site picker and the kit_check form that fill these in belong to the modal these are drawn
in — MishkaCmsCoreWeb.Live.Admin.Components.ExtensionInstallerPanel.doctor_modal/1.
Attributes
setup(:map) (required)id(:string) (required)
@spec upgrade(Phoenix.LiveView.Socket.t(), String.t(), boolean()) :: Phoenix.LiveView.Socket.t()
Writes the components the admin asked for and redraws the standings from the database afterwards.
mode comes from the button that was pressed, so anything but "all" is taken as the safe
half — an unexpected value cannot be read as permission to write over an edited row.