Documentation
¶
Overview ¶
Package jetadmin is a Django-admin-style web admin for PostgreSQL tables described by go-jet/jet generated code. Register a page per table, mount Site.Handler, and the admin lists, searches, filters, adds, changes and deletes rows with Jet statements run through pgx.
Pages are rendered with templ and work without JavaScript; Datastar, embedded and served by the Site, makes the search live, the filters and forms answer without a full reload, and confirmations open as dialogs.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Schema string
Schema is the DDL of the tables jet-admin uses: admin_users and admin_sessions for the auth package, admin_log for Config.AuditLog. Paste it (or schema.sql, the same text) into one of your migrations.
var ViewOnly = Permissions{DisableAdd: true, DisableChange: true, DisableDelete: true}
ViewOnly is the Permissions of a table the admin only shows (a log).
Functions ¶
Types ¶
type Authenticator ¶
type Authenticator = core.Authenticator
Authenticator tells who is signed in on a request. The auth package has a database-backed one; a host with its own sign-in implements it over that.
type Choice ¶
type Choice struct {
Value, Label string
}
Choice is one allowed value of a column, in its text form.
type Config ¶
type Config struct {
// DB runs every statement; a *pgxpool.Pool.
DB DB
// Title is the name in the header and the page titles: "Sumi admin".
Title string
// BasePath is where the Handler is mounted, without the trailing
// slash: "/admin". The admin's pages live under BasePath + "/".
BasePath string
// Auth tells who is signed in. Required: the admin shows nothing to
// anyone it does not authenticate.
Auth Authenticator
// Logger receives the failures the pages cannot show; slog.Default()
// when nil.
Logger *slog.Logger
// AuditLog records every add, change and delete in admin_log (see
// Schema) and shows them on the index, history and log pages.
AuditLog bool
}
Config is the Site's setup.
type DB ¶
type DB interface {
Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error)
Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
Begin(ctx context.Context) (pgx.Tx, error)
}
DB is what the admin runs statements on; *pgxpool.Pool satisfies it.
type ExtraField ¶
type ExtraField struct {
Name, Label, Help string
Widget Widget
// RequiredOnAdd refuses a blank value when adding a row.
RequiredOnAdd bool
}
ExtraField is a form input that is not a column.
type Field ¶
type Field struct {
Column postgres.Column
// Label is the field's name on the form and the list's header; the
// column name in words by default.
Label string
// Help is shown under the input.
Help string
// Choices restrict the value to a list: a select on the form, a
// filter of each choice, the choice's label in the list.
Choices []Choice
// Widget overrides the input chosen from the field's Go type.
Widget Widget
}
Field holds the options of one column's form field and list cell.
type FieldErrors ¶
FieldErrors is a validation failure: a message per field, keyed by column or Extra name. The key "" is a message for the whole form.
func (FieldErrors) Error ¶
func (e FieldErrors) Error() string
type ForeignKey ¶
ForeignKey links Column to the row of the model registered as Model (its slug) whose primary key it holds.
type Inline ¶
type Inline struct {
Model string
Column postgres.Column
// Limit is the number of rows shown; 20 by default.
Limit int
}
Inline lists, on a change page, the rows of the model registered as Model (its slug) whose Column holds this row's primary key, with an "add" link that fills Column in.
type LoginProvider ¶
type LoginProvider = core.LoginProvider
LoginProvider is an Authenticator that also serves the sign-in and sign-out pages, mounted at BasePath/login and BasePath/logout.
type Model ¶
type Model[M any] struct { // Table is the generated builder. Its AllColumns, MutableColumns and // DefaultColumns are read by reflection. Table postgres.Table // Slug is the URL segment of the pages; the table's name by default. Slug string // Label and Plural name one row and the table: "Device", "Devices". // They default to the table's name, singularised and capitalised. Label, Plural string // Group is the section of the index page the model is listed under. Group string // ListDisplay are the columns of the list; by default the primary key // and the next few columns. ListDisplay []postgres.Column // ListFilter are the columns of the filter sidebar: a bool filters by // yes and no, a column with Choices by each choice, a timestamp or // date by today, the past 7 and 30 days and this year, other columns // by their distinct values when there are few enough of them. ListFilter []postgres.Column // SearchFields are matched, case-insensitively and as text, against // the search box: a row matches when one of them contains it. SearchFields []postgres.Column // Ordering is the list's default order; the primary key by default. // The column headers sort too. Ordering []Order // PageSize is the number of rows per list page; 50 by default. PageSize int // ReadOnly columns are shown on the form but never written by it. ReadOnly []postgres.Column // Hidden columns are never selected for display, shown nor written by // a form (a sealed credential). Hidden []postgres.Column // Fields are per-column options: label, help text, choices, widget. Fields []Field // ForeignKeys link a column to the row of another registered model. ForeignKeys []ForeignKey // Inlines list, on the change page, the rows of other models that // point at this one. Inlines []Inline // Extra are form inputs that are not columns (a password). Their // values reach BeforeSave. Extra []ExtraField // Computed are columns BeforeSave sets: written on every save even // when Hidden or ReadOnly (a password hash). Computed []postgres.Column // Display names a row in titles, links and the log, like Django's // __str__. By default "<Label> <primary key>". Display func(M) string // Permissions turns off adding, changing or deleting; everything is // allowed by default. Permissions Permissions // BeforeSave runs before Validate on every add and change, with the // values of Extra. Return FieldErrors to show the problem on the form. BeforeSave func(ctx context.Context, m *M, save Save) error // Validate runs before the row is inserted or updated. Return // FieldErrors to mark fields, any other error to show it above the // form. Validate func(ctx context.Context, m *M) error }
Model describes the admin pages of one table. M is the table's Jet model struct (model.Devices); Table is its generated builder (table.Devices). Every option but Table has a working default.
type Permissions ¶
type Permissions struct {
DisableAdd, DisableChange, DisableDelete bool
}
Permissions turns off the actions a model does not allow. The zero value allows them all.
type Save ¶
type Save struct {
// Adding is true for a new row, false for a change.
Adding bool
// Extra holds the submitted values of Model.Extra, by name.
Extra map[string]string
}
Save is what BeforeSave learns about the save in progress.
type Site ¶
type Site struct {
// contains filtered or unexported fields
}
Site is an admin: its registered models and the Handler serving them.
func (*Site) Handler ¶
Handler serves every page under BasePath. Mount it at BasePath + "/":
mux.Handle("/admin/", site.Handler())
It refuses cross-origin form posts (http.CrossOriginProtection), sends whoever is not signed in to the login page (or answers 403 when the Authenticator serves none) and serves the embedded stylesheet and Datastar under BasePath/static/.
type Widget ¶
type Widget int
Widget is the input of a form field.
const ( // WidgetDefault picks the input from the field's Go type. WidgetDefault Widget = iota // Textarea is a multi-line text input. Textarea // JSON is a textarea whose value must be valid JSON; jsonb columns get // it without asking. JSON // Password is a masked input that never shows its value. Password )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package auth is a database-backed sign-in for jet-admin, like Django's superusers: admin_users holds who may sign in (bcrypt password hashes), admin_sessions the open sessions, keyed by the SHA-256 of the random token in the cookie.
|
Package auth is a database-backed sign-in for jet-admin, like Django's superusers: admin_users holds who may sign in (bcrypt password hashes), admin_sessions the open sessions, keyed by the SHA-256 of the random token in the cookie. |
|
Command example runs a jet-admin site over a small demo schema: customers, their orders and their API tokens.
|
Command example runs a jet-admin site over a small demo schema: customers, their orders and their API tokens. |
|
db
Package db is the demo's schema: schema.sql, and the Jet builders and models generated from it (go run ./scripts/jetgen -schema example/db/schema.sql -dest example/db/jet -db-tags).
|
Package db is the demo's schema: schema.sql, and the Jet builders and models generated from it (go run ./scripts/jetgen -schema example/db/schema.sql -dest example/db/jet -db-tags). |
|
internal
|
|
|
core
Package core holds what both the admin and the auth package need, so neither imports the other for it: auth registers its pages on a Site, and the Site takes an Authenticator.
|
Package core holds what both the admin and the auth package need, so neither imports the other for it: auth registers its pages on a Site, and the Site takes an Authenticator. |
|
testdb
Package testdb gives each test its own PostgreSQL database, built from the DDL the test passes and dropped when the test ends.
|
Package testdb gives each test its own PostgreSQL database, built from the DDL the test passes and dropped when the test ends. |
|
ui
templ: version: v0.3.1070
|
templ: version: v0.3.1070 |
|
scripts
|
|
|
jetgen
command
Command jetgen writes Jet table builders and models for a schema file.
|
Command jetgen writes Jet table builders and models for a schema file. |