Documentation
¶
Overview ¶
Package editor is the ready-made admin for content stores (see the content package): an overview with language tabs, a go-form editor per language, publication and, for revisioned content, history, restore and preview. A module supplies a form struct and two mapping functions; extra screens can be added with Config.Routes.
Index ¶
- Constants
- Variables
- func MediaChoices(ctx context.Context, library *media.Service, images bool, selected string) (form.SortedSelect[string], error)
- func New[F, T, I any](config Config[F, T, I]) admin.Section
- func RedirectTargets(table *pages.Table, locale, leaving, selected string) form.SortedSelect[string]
- func RedirectedNotice(r *http.Request, a *admin.Admin, done string, count int, err error) flash.Message
- func Redirector(r *http.Request, a *admin.Admin, check *links.Check) links.Redirector
- func Slug(typed, title string) string
- func Status[F, T any](item content.Item[F, T], revisioned bool) string
- type Config
- type Conflict
- type EditView
- type Editor
- func (e Editor[F, T, I]) Admin() *admin.Admin
- func (e Editor[F, T, I]) Issue(r *http.Request, err error) string
- func (e Editor[F, T, I]) Locale(r *http.Request) (string, locales.Config, error)
- func (e Editor[F, T, I]) Permission(action string) admin.Permission
- func (e Editor[F, T, I]) RefusePermanent(w http.ResponseWriter, r *http.Request) bool
- type IndexView
- type Link
- type Linked
- func (l Linked[F, T, I]) Edit(r *http.Request, e Editor[F, T, I], item content.Item[F, T], locale string, ...) error
- func (l Linked[F, T, I]) Routes(routes *admin.Routes, e Editor[F, T, I])
- func (l Linked[F, T, I]) Saved(r *http.Request, e Editor[F, T, I], before, after content.Item[F, T], _ string) *flash.Message
- type MovedInput
- type Notice
- type NoticeItem
- type RedirectInput
- type Row
Constants ¶
const ( // PublishLinked asks before a revision is published that moves a page // or an item away from the address that published content links to. PublishLinked = "Published items link to the old address, and their links will lead nowhere. Publish anyway?" )
Questions before an item that published content links to leaves its address.
Variables ¶
var ErrPermanent = errors.New("permanent_item")
ErrPermanent refuses a change that would take an item that is permanent by its nature (Config.Permanent) off the website. Config.Issue can name it, as the page tree does for the home page; the default message is general.
Functions ¶
func MediaChoices ¶
func MediaChoices(ctx context.Context, library *media.Service, images bool, selected string) (form.SortedSelect[string], error)
MediaChoices is a dropdown of media files by name. Its field offers none with a placeholder, such as placeholder:"—". With images set, only images are offered.
func RedirectTargets ¶
func RedirectTargets(table *pages.Table, locale, leaving, selected string) form.SortedSelect[string]
RedirectTargets lists the published pages of locale that addresses can redirect to, in tree order and indented by depth, with selected chosen: all of them, or without the page leaving and the pages below it.
func RedirectedNotice ¶
func RedirectedNotice(r *http.Request, a *admin.Admin, done string, count int, err error) flash.Message
RedirectedNotice is the toast after a change that redirected count old addresses: done, a translation key such as "Published.", and how many redirect now. A failed redirect, err, makes it a warning.
func Redirector ¶
Redirector returns the module that redirects old addresses (see links.Check.Redirects) when the user of r may add redirects to it; nil otherwise, also for a nil check.
func Slug ¶
Slug is the web address an editor typed into an item's slug field, or, when the field is left empty, one made from title (content.Slug), for an editor's Apply:
text.Slug = editor.Slug(in.Slug, in.Title)
A title without letters content.Slug can use, such as one in another script, gives "".
func Status ¶
Status names the publication state of an item for overviews, as a translation key: "Scheduled", "In review", "Draft", "Changes not published" or "Published". "In review" and "Changes not published" apply to revisioned content only; all content can be "Scheduled", "Draft" or "Published".
Types ¶
type Config ¶
type Config[F, T, I any] struct { // ID, Title, Path and Icon describe the admin section; see admin.Section. // Path is below the admin, such as "/news"; empty is "/" followed by ID. ID string Title string Path string Icon string // NewLabel is the "new item" button text, for example "New post". NewLabel string // Links are extra buttons on the overview, for example to categories. Links []Link // Permission is the section whose rights apply, when shared with another // section (see admin.Section.Permission). Empty means ID. Permission string // Single allows one item, for modules where an instance is one thing (a // form). "New" disappears once it exists. Single bool // Store keeps the items, bound to the instance (see // content.Revisions.In and content.Collection.In). Store content.Store[F, T] // Locales gives the languages the editor offers tabs for. Locales locales.Provider // Form fills the input for one language of an item; item is empty for new content. Form func(ctx context.Context, item content.Item[F, T], locale string) (I, error) // Apply writes a validated submission into the draft for one language. Apply func(ctx context.Context, input I, draft *content.Draft[F, T], locale string) error // Label names an item in lists, from its text in one language. Label func(text T) string // ItemLabel names an item from the whole item, for content named by its // Fields (a person's name, a social network). It is used instead of Label // when set. ItemLabel func(item content.Item[F, T], locale string) string // Notes are shown muted after the labels in the overview, such as a // download count or "Expired", by item ID; a missing or empty note shows // nothing. It is called once per overview with all listed items, so a // module can read what it needs in one query. Notes are shown as written: // translate fixed texts with admin.T and admin.TN, which use ctx. Notes func(ctx context.Context, items []content.Item[F, T], locale string) map[string]string // PreviewURL is the address at which an editor previews a revision on // the website, in locale: its public address with // frontend.PreviewParam (see frontend.PagePreviewURL and // ModulePreviewURL); empty when it has none yet, for example while the // module is on no page. Nil offers no preview. PreviewURL func(ctx context.Context, item content.Item[F, T], locale string) string // Names maps user IDs to names for the revision history. Names func(ctx context.Context) (map[string]string, error) // Issue turns module errors of saving, publishing and deleting into // messages for the editor; empty means unknown. A refused delete because // the item is still referenced (a foreign key) defaults to "This item is // still in use.". Issue func(err error) string // Badge is a count next to the section in the navigation; see // admin.Section.Badge. Badge func(ctx context.Context) int // Stylesheet names a CSS file in Files that the admin links; see // admin.Section.Stylesheet. Stylesheet string // Files can override the editor templates and add module templates. Files fs.FS // Overview replaces the default overview, for content with a structure // of its own such as the page tree. Nil uses the default list. Overview func(w http.ResponseWriter, r *http.Request, editor Editor[F, T, I]) // Permanent reports items that must stay on the website by their // nature, such as the home page: their editor offers no unpublish, no // planned unpublication and no delete, refuses them when they are // posted anyway, and offers no way to remove the mark. Administrators // can mark other items permanent, and remove that mark again, in the // item's editor when the admin keeps marks (see admin.Permanence). Permanent func(item content.Item[F, T]) bool // Routes adds module screens to the section. Routes func(routes *admin.Routes, editor Editor[F, T, I]) // Edit adds to the edit screen of an item that exists, once the editor // has built it: it may add Notices, such as the pages that link to the // item, and change or replace the forms of view, such as with a // question before the item is unpublished (admin.Admin.Confirm) or a // publish form that posts to a route of its own (Config.Routes). Nil // adds nothing. Edit func(r *http.Request, editor Editor[F, T, I], item content.Item[F, T], locale string, view *EditView) error // Saved follows up the save of an item that existed, with the item // before and after: it may act on the change, such as redirecting the // item's old address (Linked.Saved), and returns the toast to show, // nil for the editor's own. Nil does nothing. Saved func(r *http.Request, editor Editor[F, T, I], before, after content.Item[F, T], locale string) *flash.Message // Trash adds the module's own deleted records to the section's trash, // such as a form's submissions, next to the deleted items of Store. Trash admin.Trash }
Config describes one editable content type. I is a go-form input struct for one language of an item.
type Conflict ¶
type Conflict struct {
// Text says who saved the item and when; it is shown as written.
Text string
// URL is the editor of the saved version, which the notice opens in a
// new tab to compare.
URL string
// Form is the id of the edit form; Name and Value are those of the
// "Save anyway" button that submits it. Value is the saved version,
// which the form may then save over.
Form string
Name string
Value string
}
Conflict is the notice of a save that was refused because someone saved the item after its form was opened (see EditView.Conflict).
type EditView ¶
type EditView struct {
// Title is the item's label, or for a new item the translated "new"
// label of the section; it is shown as written.
Title string
BackURL string
// BackLabel names the overview BackURL leads to, the section's title,
// as a translation key.
BackLabel string
Tabs []admin.LocaleTab
Panel *admin.RevisionPanel
Publish *form.RenderModel
Unpublish *form.RenderModel
Form form.RenderModel
Errors form.FieldErrors
// Conflict is the notice of a save that was refused because someone
// saved the item after its form was opened; Form then shows what the
// editor typed. Nil otherwise.
Conflict *Conflict
// ReadOnly is set for users who may view the item but not edit it: Form
// is then read-only (disabled, without its button).
ReadOnly bool
Delete *form.RenderModel
// Permanent items stay on the website: they cannot be unpublished,
// scheduled to be unpublished or deleted. PermanentFixed items are
// permanent by their nature (see Config.Permanent); the mark of others
// was set by an administrator.
Permanent bool
PermanentFixed bool
// Permanence sets or removes the permanent mark, for administrators
// when the admin keeps marks; nil otherwise.
Permanence *form.RenderModel
// Notices are warnings shown above the form (see Config.Edit).
Notices []Notice
}
EditView is the data of the edit screen of one item in one language: the form, its buttons and, for revisioned content, the revision panel.
type Editor ¶
type Editor[F, T, I any] struct { // contains filtered or unexported fields }
Editor is the editor of one content type inside the admin, handed to Config.Routes so a module's own screens can link to its items and check its permissions.
func (Editor[F, T, I]) Issue ¶
Issue is the message for editors of an error of saving, publishing or deleting an item, translated: Config.Issue's, or the editor's own for the errors of the content package; empty for an unexpected error. Module screens (Config.Routes) explain refusals with it.
func (Editor[F, T, I]) Locale ¶
Locale returns the content language of the request (?locale=), defaulting to the site's default language, and the language configuration.
func (Editor[F, T, I]) Permission ¶
func (e Editor[F, T, I]) Permission(action string) admin.Permission
Permission returns the permission for an action in the section whose rights apply to the editor.
func (Editor[F, T, I]) RefusePermanent ¶
RefusePermanent shows the editor with the reason when the item in the URL is permanent, for a change that would take it off the website, and reports whether it did. Module screens (Config.Routes) that take an item off the website call it first, as the editor's own do.
type IndexView ¶
type IndexView struct {
Title string
NewURL string
NewLabel string
Links []Link
// TrashURL shows the section's deleted items in the admin's trash.
TrashURL string
Revisioned bool
Tabs []admin.LocaleTab
Rows []Row
// Pager pages through long lists.
Pager admin.Pager
}
IndexView is the data of the overview of a content type: one row per item, in one language.
type Link ¶
Link is a button on the overview: to URL, or to the admin route named Route, such as admin.RouteName("news-categories", "index"), whose address is built when the overview is shown. Route is used instead of URL when set; an unknown route fails the overview.
type Linked ¶
type Linked[F, T, I any] struct { // Check is the site's link check (webthings.Env.Links); nil adds // nothing. Check *links.Check // Address is the address of item, which may be any revision of it, on // the site in locale, such as "/en/news/hello": where visitors find it // once it is published. Empty when it has none there, such as an item // of an instance on no page. It is asked only for languages in which // the item is complete (content.Spec.Available). Address func(ctx context.Context, item content.Item[F, T], locale string) (string, error) // Below, if set, are the addresses below the item's address in locale // that leave the website with it, such as the entries of a directory's // category, which go offline when the category is unpublished but keep // working at their old addresses when its slug changes. The editor then // counts the links below the item's address apart from those to the // item itself, and unpublishing it with redirects redirects these // addresses too, to the same page. Without it, links below the item's // address count as links to the item. It is asked only for languages in // which the item is complete. Below func(ctx context.Context, item content.Item[F, T], locale string) ([]string, error) }
Linked adds the links to an item to the editor of a module whose items have an address of their own, such as posts or events. Its methods are the editor's hooks:
linked := editor.Linked[PostFields, PostText, postInput]{Check: env.Links(), Address: service.address}
editor.New(editor.Config[PostFields, PostText, postInput]{
// ...
Edit: linked.Edit,
Routes: linked.Routes,
Saved: linked.Saved,
})
A module with hooks of its own calls these from them.
func (Linked[F, T, I]) Edit ¶
func (l Linked[F, T, I]) Edit(r *http.Request, e Editor[F, T, I], item content.Item[F, T], locale string, view *EditView) error
Edit adds the notices about links to the editor of a published item (Config.Edit).
func (Linked[F, T, I]) Routes ¶
Routes adds the editor's routes that redirect: "unpublish-redirect", and "revision-publish-moved" for content with revisions (Config.Routes).
func (Linked[F, T, I]) Saved ¶
func (l Linked[F, T, I]) Saved(r *http.Request, e Editor[F, T, I], before, after content.Item[F, T], _ string) *flash.Message
Saved redirects the old addresses of a published item without revisions to its new ones when saving changed them, such as with a new slug, and the user may add redirects (Config.Saved). Content with revisions changes its address when a revision is published instead (Routes).
type MovedInput ¶
type MovedInput struct {
Redirect bool `` /* 155-byte string literal not displayed */
}
MovedInput publishes a revision that changes the address of a page or an item, redirecting the old addresses to the new ones when Redirect is set.
type Notice ¶
type Notice struct {
// Text is shown as written: translate it first (admin.T, admin.TN).
Text string
// Items are listed below the text, such as the pages that link to the
// item.
Items []NoticeItem
// Forms act on the notice, such as one that creates a redirect.
Forms []form.RenderModel
}
Notice is a warning on the edit screen (see Config.Edit): a text, the content it concerns and forms that act on it.
type NoticeItem ¶
NoticeItem is an entry in a Notice's list, linked to URL when set. Label and Note, which is shown muted after it, are shown as written.
type RedirectInput ¶
type RedirectInput struct {
Target form.SortedSelect[string] `form:"dropdown" label:"Redirect to" required:"true" placeholder:"—"`
}
RedirectInput chooses the page that the addresses a page or an item leaves redirect to.
type Row ¶
type Row struct {
Title string
// Note is shown muted after the title; see Config.Notes.
Note string
URL string
Status string
Missing bool
// Moves are the item's up and down arrows, for ordered stores; see
// admin.Moves.
Moves []admin.Move
}
Row is one item in the overview, with its publication state (see Status).