A new component made from an existing one — the inspector modal's Duplicate.
The copy is written through the resource's own :master_create or :create, chosen by the actor
the same way MishkaCmsCore.Runtime.PageBuilder.Helpers.save_section/4 chooses. Nothing is
inserted around them, so a copy is validated, signed, versioned, broadcast and compiled exactly
like a component somebody typed in — and refused the same way: to an actor who may not write the
component, and, for one carrying helpers, while the deployment's :page_code switch is off.
What a copy keeps, and what it does not
Every attribute the create action accepts is carried over, read from the action rather than listed here, so a field added to the resource is copied without anyone remembering this module. Five things are not the source's to pass on:
- The name.
copy_name/1—<name>-copy-<4 characters>. - The kit.
extra.ui_kit,extra.ui_kit_versionandextra.ui_kit_digestgo, andextra.copied_fromnames the source instead. All three are one stamp —MishkaCmsCore.Runtime.Handlers.UiKitUpgradewrites them together and reads them together — and a copy that kept the fingerprint would be claiming to be what a kit installed. A copy ofchelekom-buttonstill starts withchelekom-, andMishkaCmsCore.Runtime.Handlers.UiKitHandlerpurges by that prefix on an uninstall or acleanup: truereinstall — through:master_permanent_destroy, which leaves no archive and no version.copied_fromis what it reads to leave a user's copy alone. required. It says the CMS cannot run without the component, which is true of the kit's icon and of nobody's copy of it.precompile. A copy is built by the first render that names it, not at every boot.- Its elements' classes. See below.
A copy stays where its source is
A master copies any row into the source's own scope: a global row makes a global copy, a site's
row a copy in that site. A site copies only its own rows. A shared row copied into a site would be
a fork its examples cannot find — they say site="Global" — so that is refused rather than
guessed at.
It names itself
A component's examples are real invocations, <.component component_name="chelekom-card" …/>,
and so is the occasional template that renders itself. Copied verbatim, the copy's Preview tab and
the builder's Examples modal would draw the ORIGINAL. Every exact component_name="<source>" in
the template, the body, the examples and anything under extra is rewritten to the copy's name.
The closing quote is part of the match, so chelekom-button-group is not a reference to
chelekom-button; a computed component_name={@name} is not rewritten.
Its elements are its own
Every minted pb-xxxxxxxx class in the copied text is swapped for a fresh one and the source's
CSS for those classes is written under the new ones in the copy's own row — the shared
MishkaCmsCore.Runtime.PageBuilder.ElementScopes, which says what a kept class costs.
Summary
Functions
<name>-copy-<suffix>: four lowercase base32 characters, the base cut so the whole stays within
100 characters.
Copy source as actor, trying a fresh name when the last one was taken.
Functions
<name>-copy-<suffix>: four lowercase base32 characters, the base cut so the whole stays within
100 characters.
Already in the form the resource's slugify(:name) stores, so the name the self-references are
rewritten to is the name the row is saved under.
@spec duplicate(MishkaCmsCore.Runtime.Component.t(), map() | nil, keyword()) :: {:ok, MishkaCmsCore.Runtime.Component.t()} | {:error, term()}
Copy source as actor, trying a fresh name when the last one was taken.
:names is the candidates to try, in order; by default three from copy_name/1. Only a taken
name moves on to the next one — any other refusal is returned as it came.
Returns the resource's own {:ok, copy} / {:error, error}, or {:error, :out_of_scope} when
the actor is a site and source is not that site's.