admin

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2025 License: GPL-2.0 Imports: 47 Imported by: 0

Documentation

Overview

templ: version: v0.3.833

templ: version: v0.3.833

Index

Constants

View Source
const (
	// RegisterAppMenuItemHook    = "admin:register_menu_item:<app_name>"
	RegisterMenuItemHook       = "admin:register_menu_item"
	RegisterFooterMenuItemHook = "admin:register_footer_menu_item"
	RegisterGlobalMediaHook    = "admin:register_global_media"
	RegisterNavBreadCrumbHook  = "admin:register_breadcrumb"
	RegisterNavActionHook      = "admin:register_nav_action"

	RegisterHomePageBreadcrumbHook = "admin:home:register_breadcrumb"
	RegisterHomePageActionHook     = "admin:home:register_action"
	RegisterHomePageComponentHook  = "admin:home:register_component"

	AdminModelHookAdd    = "admin:model:add"
	AdminModelHookEdit   = "admin:model:edit"
	AdminModelHookDelete = "admin:model:delete"
)
View Source
const (
	// Set the title of the home page
	APPVAR_HOME_PAGE_TITLE = "APPVAR_HOME_PAGE_TITLE"

	// Set the subtitle of the home page
	APPVAR_HOME_PAGE_SUBTITLE = "APPVAR_HOME_PAGE_SUBTITLE"

	// Set the path to the home page logo
	APPVAR_HOME_PAGE_LOGO_PATH = "APPVAR_HOME_PAGE_LOGO"
)
View Source
const BASE_KEY = "admin"

Variables

View Source
var (
	RegisterApp   = AdminSite.RegisterApp
	IsReady       = AdminSite.IsReady
	ConfigureAuth = AdminSite.configureAuth
)
View Source
var AppHandler = func(w http.ResponseWriter, r *http.Request, adminSite *AdminApplication, app *AppDefinition) {
	if !app.Options.EnableIndexView {
		except.RaiseNotFound(
			"app %s does not have an i,ndex view",
			app.Label(),
		)
		return
	}

	if !permissions.HasPermission(r, fmt.Sprintf("admin:view_app:%s", app.Name)) {
		ReLogin(w, r, r.URL.Path)
		return
	}

	if app.Options.IndexView != nil {
		var err = views.Invoke(app.Options.IndexView(adminSite, app), w, r)
		except.AssertNil(err, 500, err)
		return
	}

	var models = app.Models
	var modelNames = make([]string, models.Len())
	var i = 0
	for front := models.Front(); front != nil; front = front.Next() {
		modelNames[i] = front.Value.Label()
		i++
	}

	var hookName = RegisterAdminPageComponentHook(app.Name)
	var hook = goldcrest.Get[RegisterAdminAppPageComponentHookFunc](hookName)
	var components = make([]AdminPageComponent, 0)
	for _, h := range hook {
		var component = h(r, adminSite, app)
		if component != nil {
			components = append(components, component)
		}
	}
	sortComponents(components)

	var context = NewContext(
		r, adminSite, nil,
	)

	context.SetPage(PageOptions{
		TitleFn:    app.Label,
		SubtitleFn: app.Description,
		MediaFn: func() media.Media {
			var appMedia media.Media = media.NewMedia()
			for _, component := range components {
				var m = component.Media()
				if m != nil {
					appMedia = appMedia.Merge(m)
				}
			}
			return appMedia
		},
	})
	context.Set("app", app)
	context.Set("models", modelNames)
	context.Set("components", components)
	var err = tpl.FRender(w, context, BASE_KEY, "admin/views/apps/index.tmpl")
	except.AssertNil(err, 500, err)
}
View Source
var HomeHandler = &views.BaseView{
	AllowedMethods:  []string{http.MethodGet},
	BaseTemplateKey: BASE_KEY,
	TemplateName:    "admin/views/home.tmpl",
	GetContextFn: func(req *http.Request) (ctx.Context, error) {
		var context = NewContext(req, AdminSite, nil)
		var user = authentication.Retrieve(req)

		// Initialize / retrieve home page intro texts
		var pageTitle = django.ConfigGet[any](
			django.Global.Settings,
			APPVAR_HOME_PAGE_TITLE,
			trans.S("Home"),
		)
		var pageSubtitle = django.ConfigGet[any](
			django.Global.Settings,
			APPVAR_HOME_PAGE_SUBTITLE,
			func(r *http.Request) string {
				return trans.T(
					"Welcome to the Go-Django admin dashboard, %s!",
					attrs.ToString(user),
				)
			},
		)

		// Set up media files for the home page template
		var homeMedia media.Media = media.NewMedia()
		homeMedia.AddCSS(media.CSS(django.Static(
			"admin/css/home.css",
		)))

		// Initialize / retrieve the home page logo's static path
		var logo = django.ConfigGet[any](
			django.Global.Settings,
			APPVAR_HOME_PAGE_LOGO_PATH,
			django.Static("admin/images/home_logo.png"),
		)
		var logoPath string
		switch t := logo.(type) {
		case string:
			logoPath = t
		case func() string:
			logoPath = t()
		case func(*http.Request) string:
			logoPath = t(req)
		}

		// Add home page breadcrumbs and actions
		var breadCrumbs = make([]BreadCrumb, 0)
		var breadcrumbHooks = goldcrest.Get[RegisterHomePageBreadcrumbHookFunc](RegisterHomePageBreadcrumbHook)
		for _, hook := range breadcrumbHooks {
			hook(req, AdminSite, breadCrumbs)
		}

		var actions = make([]Action, 0)
		var actionHooks = goldcrest.Get[RegisterHomePageActionHookFunc](RegisterHomePageActionHook)
		for _, hook := range actionHooks {
			hook(req, AdminSite, actions)
		}

		// Add custom home page components
		var componentHooks = goldcrest.Get[RegisterHomePageComponentHookFunc](RegisterHomePageComponentHook)
		var components = make([]AdminPageComponent, 0)
		for _, hook := range componentHooks {
			var component = hook(req, AdminSite)
			if component != nil {
				components = append(components, component)
			}
		}
		components = sortComponents(components)

		context.SetPage(PageOptions{
			TitleFn:     getFuncTyped[string](pageTitle, req, nil),
			SubtitleFn:  getFuncTyped[string](pageSubtitle, req, nil),
			BreadCrumbs: breadCrumbs,
			Actions:     actions,
			MediaFn: func() media.Media {
				for _, component := range components {
					var media = component.Media()
					if media != nil {
						homeMedia = homeMedia.Merge(media)
					}
				}
				return homeMedia
			},
		})

		context.Set("Components", components)

		if logoPath != "" {
			context.Set("LogoPath", logoPath)
		}

		return context, nil
	},
}
View Source
var LoginHandler = &views.FormView[*AdminForm[LoginForm]]{
	BaseView: views.BaseView{
		AllowedMethods:  []string{http.MethodGet, http.MethodPost},
		BaseTemplateKey: "admin",
		TemplateName:    "admin/views/auth/login.tmpl",
		GetContextFn: func(req *http.Request) (ctx.Context, error) {
			var context = ctx.RequestContext(req)
			// context.Set("next", req.URL.Query().Get("next"))
			var loginURL = django.Reverse("admin:login")
			var nextURL = req.URL.Query().Get("next")
			if nextURL != "" {
				var u, err = url.Parse(loginURL)
				if err != nil {
					goto returnContext
				}

				q := u.Query()
				q.Set("next", nextURL)
				u.RawQuery = q.Encode()
				loginURL = u.String()
			}

		returnContext:
			context.Set("LoginURL", loginURL)
			return context, nil
		},
	},
	GetFormFn: func(req *http.Request) *AdminForm[LoginForm] {
		var loginForm = AdminSite.AuthLoginForm(
			req,
		)
		return &AdminForm[LoginForm]{
			Form: loginForm,
		}
	},
	ValidFn: func(req *http.Request, form *AdminForm[LoginForm]) error {
		form.Form.SetRequest(req)
		return form.Form.Login()
	},
	SuccessFn: func(w http.ResponseWriter, req *http.Request, form *AdminForm[LoginForm]) {
		var nextURL = req.URL.Query().Get("next")
		if nextURL == "" {
			nextURL = django.Reverse("admin:home")
		}

		http.Redirect(w, req, nextURL, http.StatusSeeOther)
	},
}
View Source
var ModelAddHandler = func(w http.ResponseWriter, r *http.Request, adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition) {

	if !permissions.HasObjectPermission(r, model.NewInstance(), "admin:add") {
		ReLogin(w, r, r.URL.Path)
		return
	}

	if model.DisallowCreate {
		messages.Error(r, "This model does not allow creation")
		autherrors.Fail(
			http.StatusForbidden,
			"This model does not allow creation",
			django.Reverse("admin:apps:model", app.Name, model.GetName()),
		)
		return
	}

	var instance = model.NewInstance()
	if model.AddView.GetHandler != nil {
		var err = views.Invoke(model.AddView.GetHandler(adminSite, app, model, instance), w, r)
		except.AssertNil(err, 500, err)
		return
	}
	var addView = newInstanceView("add", instance, model.AddView, app, model, r)
	views.Invoke(addView, w, r)

}
View Source
var ModelDeleteHandler = func(w http.ResponseWriter, r *http.Request, adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition, instance attrs.Definer) {
	if !permissions.HasObjectPermission(r, instance, "admin:delete") {
		ReLogin(w, r, r.URL.Path)
		return
	}

	if model.DisallowDelete {
		messages.Error(r, "This model does not allow deletion")
		autherrors.Fail(
			http.StatusForbidden,
			"This model does not allow deletion",
			django.Reverse("admin:apps:model", app.Name, model.GetName()),
		)
		return
	}

	if model.DeleteView.GetHandler != nil {
		var err = views.Invoke(model.DeleteView.GetHandler(adminSite, app, model, instance), w, r)
		except.AssertNil(err, 500, err)
		return
	}

	var err error
	var context = NewContext(r, adminSite, nil)
	if r.Method == http.MethodPost {

		var hooks = goldcrest.Get[AdminModelHookFunc](
			AdminModelHookDelete,
		)
		for _, hook := range hooks {
			hook(r, AdminSite, model, instance)
		}

		if model.DeleteView.DeleteInstance != nil {
			err = model.DeleteView.DeleteInstance(r.Context(), instance)
		} else {
			var deleted bool
			deleted, err = models.DeleteModel(r.Context(), instance)
			assert.False(
				err == nil && !deleted,
				"model %T not deleted, model does not implement models.Deleter interface",
				instance,
			)
		}

		if err != nil {
			context.Set("error", err)
		}

		messages.Warning(r,
			fmt.Sprintf(
				"Successfully deleted %s (%v)",
				attrs.ToString(instance),
				attrs.PrimaryKey(instance),
			),
		)

		var listViewURL = django.Reverse("admin:apps:model", app.Name, model.GetName())
		http.Redirect(w, r, listViewURL, http.StatusSeeOther)
		return
	}

	var definitions = instance.FieldDefs()
	var primaryField = definitions.Primary()

	context.Set("app", app)
	context.Set("model", model)
	context.Set("instance", instance)
	context.Set("primaryField", primaryField)

	err = tpl.FRender(w, context, BASE_KEY, "admin/views/models/delete.tmpl")
	except.AssertNil(err, 500, err)
}
View Source
var ModelEditHandler = func(w http.ResponseWriter, r *http.Request, adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition, instance attrs.Definer) {
	if !permissions.HasObjectPermission(r, instance, "admin:edit") {
		ReLogin(w, r, r.URL.Path)
		return
	}

	if model.DisallowEdit {
		messages.Error(r, "This model does not allow editing")
		autherrors.Fail(
			http.StatusForbidden,
			"This model does not allow editing",
			django.Reverse("admin:apps:model", app.Name, model.GetName()),
		)
		return
	}

	if model.EditView.GetHandler != nil {
		var err = views.Invoke(model.EditView.GetHandler(adminSite, app, model, instance), w, r)
		except.AssertNil(err, 500, err)
		return
	}
	var editView = newInstanceView("edit", instance, model.EditView, app, model, r)
	views.Invoke(editView, w, r)

}
View Source
var ModelListHandler = func(w http.ResponseWriter, r *http.Request, adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition) {

	if !permissions.HasObjectPermission(r, model.NewInstance(), "admin:view_list") {
		ReLogin(w, r, r.URL.Path)
		return
	}

	if model.ListView.GetHandler != nil {
		var err = views.Invoke(model.ListView.GetHandler(adminSite, app, model), w, r)
		except.AssertNil(err, 500, err)
		return
	}

	var columns = make([]list.ListColumn[attrs.Definer], len(model.ListView.Fields))
	for i, field := range model.ListView.Fields {
		columns[i] = model.GetColumn(model.ListView, field)
	}

	var amount = model.ListView.PerPage
	if amount == 0 {
		amount = 25
	}

	var view = &list.View[attrs.Definer]{
		ListColumns:   columns,
		DefaultAmount: amount,
		BaseView: views.BaseView{
			AllowedMethods:  []string{http.MethodGet, http.MethodPost},
			BaseTemplateKey: BASE_KEY,
			TemplateName:    "admin/views/models/list.tmpl",
			GetContextFn: func(req *http.Request) (ctx.Context, error) {
				var context = NewContext(req, adminSite, nil)
				context.Set("app", app)
				context.Set("model", model)
				return context, nil
			},
		},
		GetListFn: func(amount, offset uint) ([]attrs.Definer, error) {
			return model.GetListInstances(amount, offset)
		},
		TitleFieldColumn: func(lc list.ListColumn[attrs.Definer]) list.ListColumn[attrs.Definer] {
			return list.TitleFieldColumn(lc, func(r *http.Request, defs attrs.Definitions, instance attrs.Definer) string {
				if !permissions.HasObjectPermission(r, instance, "admin:edit") || model.DisallowEdit {
					return ""
				}

				var primaryField = defs.Primary()
				if primaryField == nil {
					return ""
				}
				return django.Reverse("admin:apps:model:edit", app.Name, model.GetName(), primaryField.GetValue())
			})
		},
	}

	views.Invoke(view, w, r)
}
View Source
var (
	// Register a custom component for an app registered to the admin.
	// The app name is used to identify the app.
	// It should be formatted as "admin:<app_name>:register_admin_page_component"
	// This will then return a string which can be used to register the component to the app.
	RegisterAdminPageComponentHook = func(appname string) string {
		return fmt.Sprintf("admin:%s:register_component", appname)
	}
)

Functions

func Home added in v1.7.0

func Home(w http.ResponseWriter, r *http.Request, errorMessage ...string)

func NewAppConfig

func NewAppConfig() django.AppConfig

func NewContext

func NewContext(request *http.Request, site *AdminApplication, context ctx.Context) *adminContext

func ReLogin added in v1.7.0

func ReLogin(w http.ResponseWriter, r *http.Request, nextURL ...string)

func RedirectLoginFailedToAdmin added in v1.6.9

func RedirectLoginFailedToAdmin(w http.ResponseWriter, r *http.Request, app *django.Application, authError *autherrors.AuthenticationError) (written bool)

func RegisterAdminAppPageComponent added in v1.7.0

func RegisterAdminAppPageComponent(appname string, f RegisterAdminAppPageComponentHookFunc)

Register a custom component for an app registered to the admin.

func RegisterGlobalFooterMenuItem added in v1.7.0

func RegisterGlobalFooterMenuItem(fn RegisterFooterMenuItemHookFunc)

Register an item to the django admin menu's footer.

func RegisterGlobalMedia

func RegisterGlobalMedia(fn RegisterMediaHookFunc)

Register a media hook to the admin site.

This is used to add custom CSS & JS to the admin site.

func RegisterGlobalMenuItem added in v1.7.0

func RegisterGlobalMenuItem(fn RegisterMenuItemHookFunc)

Register an item to the django admin menu (sidebar).

func RegisterGlobalNavAction added in v1.7.0

func RegisterGlobalNavAction(fn RegisterNavActionHookFunc)

Register a navigation action to the admin site.

func RegisterGlobalNavBreadCrumb added in v1.7.0

func RegisterGlobalNavBreadCrumb(fn RegisterBreadCrumbHookFunc)

Register a breadcrumb to the admin site.

func RegisterHomePageAction added in v1.7.0

func RegisterHomePageAction(f RegisterHomePageActionHookFunc)

Register an action item for the home page.

func RegisterHomePageBreadcrumb added in v1.7.0

func RegisterHomePageBreadcrumb(f RegisterHomePageBreadcrumbHookFunc)

Register a breadcrumb for the home page.

func RegisterHomePageComponent added in v1.7.0

func RegisterHomePageComponent(f RegisterHomePageComponentHookFunc)

Register a custom component for the home page.

func RegisterModelAddHook added in v1.7.0

func RegisterModelAddHook(f AdminModelHookFunc)

Register a hook to be called when a model is added.

func RegisterModelDeleteHook added in v1.7.0

func RegisterModelDeleteHook(f AdminModelHookFunc)

Register a hook to be called when a model is deleted.

func RegisterModelEditHook added in v1.7.0

func RegisterModelEditHook(f AdminModelHookFunc)

Register a hook to be called when a model is edited.

func RequiredMiddleware

func RequiredMiddleware(next mux.Handler) mux.Handler

Types

type Action

type Action struct {
	Icon   string
	Target string
	Title  string
	URL    string
}

type AdminApplication

type AdminApplication struct {
	*apps.AppConfig

	// Ordering is the order in which the apps are displayed
	// in the admin interface.
	Ordering []string

	Route *mux.Route

	// Apps is a map of all the apps that are registered
	// with the admin site.
	Apps *orderedmap.OrderedMap[
		string, *AppDefinition,
	]
	// contains filtered or unexported fields
}
var AdminSite *AdminApplication = &AdminApplication{
	AppConfig: apps.NewAppConfig("admin"),
	Apps: orderedmap.NewOrderedMap[
		string, *AppDefinition,
	](),
	Ordering: make([]string, 0),
	Route: mux.NewRoute(
		mux.ANY, "admin/", nil, "admin",
	),
}

func (*AdminApplication) AuthLoginForm

func (a *AdminApplication) AuthLoginForm(r *http.Request, formOpts ...func(forms.Form)) LoginForm

func (*AdminApplication) AuthLoginHandler added in v1.7.0

func (a *AdminApplication) AuthLoginHandler() func(w http.ResponseWriter, r *http.Request)

func (*AdminApplication) AuthLogout

func (a *AdminApplication) AuthLogout(r *http.Request) error

func (*AdminApplication) IsReady

func (a *AdminApplication) IsReady() bool

func (*AdminApplication) RegisterApp

func (a *AdminApplication) RegisterApp(name string, appOptions AppOptions, opts ...ModelOptions) *AppDefinition

type AdminForm

type AdminForm[T forms.Form] struct {
	Form   T
	Panels []Panel
}

func NewAdminForm

func NewAdminForm[T forms.Form](form T, panels ...Panel) *AdminForm[T]

func (*AdminForm[T]) AddError

func (a *AdminForm[T]) AddError(name string, errorList ...error)

func (*AdminForm[T]) AddField

func (a *AdminForm[T]) AddField(name string, field fields.Field)

func (*AdminForm[T]) AddFormError

func (a *AdminForm[T]) AddFormError(errorList ...error)

func (*AdminForm[T]) AddWidget

func (a *AdminForm[T]) AddWidget(name string, widget widgets.Widget)

func (*AdminForm[T]) AsP

func (a *AdminForm[T]) AsP() template.HTML

func (*AdminForm[T]) AsUL

func (a *AdminForm[T]) AsUL() template.HTML

func (*AdminForm[T]) BoundErrors

func (a *AdminForm[T]) BoundErrors() *orderedmap.OrderedMap[string, []error]

func (*AdminForm[T]) BoundFields

func (a *AdminForm[T]) BoundFields() *orderedmap.OrderedMap[string, forms.BoundField]

func (*AdminForm[T]) BoundForm

func (a *AdminForm[T]) BoundForm() forms.BoundForm

func (*AdminForm[T]) CleanedData

func (a *AdminForm[T]) CleanedData() map[string]interface{}

func (*AdminForm[T]) DeleteField

func (a *AdminForm[T]) DeleteField(name string) bool

func (*AdminForm[T]) EditContext

func (a *AdminForm[T]) EditContext(key string, context ctx.Context)

func (*AdminForm[T]) ErrorList

func (a *AdminForm[T]) ErrorList() []error

func (*AdminForm[T]) Field

func (a *AdminForm[T]) Field(name string) (fields.Field, bool)

func (*AdminForm[T]) FieldOrder

func (a *AdminForm[T]) FieldOrder() []string

func (*AdminForm[T]) Fields

func (a *AdminForm[T]) Fields() []fields.Field

func (*AdminForm[T]) FullClean

func (a *AdminForm[T]) FullClean()

func (*AdminForm[T]) HasChanged

func (a *AdminForm[T]) HasChanged() bool

func (*AdminForm[T]) InitialData

func (a *AdminForm[T]) InitialData() map[string]interface{}

func (*AdminForm[T]) IsValid

func (a *AdminForm[T]) IsValid() bool

func (*AdminForm[T]) Media

func (a *AdminForm[T]) Media() media.Media

func (*AdminForm[T]) OnFinalize

func (a *AdminForm[T]) OnFinalize(f ...func(forms.Form))

func (*AdminForm[T]) OnInvalid

func (a *AdminForm[T]) OnInvalid(f ...func(forms.Form))

func (*AdminForm[T]) OnValid

func (a *AdminForm[T]) OnValid(f ...func(forms.Form))

func (*AdminForm[T]) Ordering

func (a *AdminForm[T]) Ordering(o []string)

func (*AdminForm[T]) Prefix

func (a *AdminForm[T]) Prefix() string

func (*AdminForm[T]) SetInitial

func (a *AdminForm[T]) SetInitial(initial map[string]interface{})

func (*AdminForm[T]) SetPrefix

func (a *AdminForm[T]) SetPrefix(prefix string)

func (*AdminForm[T]) SetValidators

func (a *AdminForm[T]) SetValidators(validators ...func(forms.Form) []error)

func (*AdminForm[T]) Validate

func (a *AdminForm[T]) Validate()

func (*AdminForm[T]) Widget

func (a *AdminForm[T]) Widget(name string) (widgets.Widget, bool)

func (*AdminForm[T]) Widgets

func (a *AdminForm[T]) Widgets() []widgets.Widget

func (*AdminForm[T]) WithData

func (a *AdminForm[T]) WithData(data url.Values, files map[string][]filesystem.FileHeader, r *http.Request) forms.Form

type AdminModelForm

type AdminModelForm[T modelforms.ModelForm[attrs.Definer]] struct {
	*AdminForm[T]
}

func NewAdminModelForm

func NewAdminModelForm[T modelforms.ModelForm[attrs.Definer]](form T, panels ...Panel) *AdminModelForm[T]

func (*AdminModelForm[T]) Context

func (a *AdminModelForm[T]) Context() context.Context

func (*AdminModelForm[T]) Instance

func (a *AdminModelForm[T]) Instance() attrs.Definer

func (*AdminModelForm[T]) Load

func (a *AdminModelForm[T]) Load()

func (*AdminModelForm[T]) Save

func (a *AdminModelForm[T]) Save() (map[string]interface{}, error)

func (*AdminModelForm[T]) SetExclude

func (a *AdminModelForm[T]) SetExclude(exclude ...string)

func (*AdminModelForm[T]) SetFields

func (a *AdminModelForm[T]) SetFields(fields ...string)

func (*AdminModelForm[T]) SetInstance

func (a *AdminModelForm[T]) SetInstance(model attrs.Definer)

func (*AdminModelForm[T]) WithContext

func (a *AdminModelForm[T]) WithContext(ctx context.Context)

type AdminModelHookFunc added in v1.6.8

type AdminModelHookFunc = func(r *http.Request, adminSite *AdminApplication, model *ModelDefinition, instance attrs.Definer)

type AdminPageComponent added in v1.7.0

type AdminPageComponent interface {
	HTML() template.HTML
	Ordering() int
	Media() media.Media
}

AdminPageComponent is an interface for custom page components

It allows for custom page components to be added to the page dynamically. The ordering of the components is determined by the Ordering method.

type AppDefinition

type AppDefinition struct {
	Name    string
	Options AppOptions
	Models  *orderedmap.OrderedMap[
		string, *ModelDefinition,
	]
	Routing func(django.Mux)
}

func (*AppDefinition) Description

func (a *AppDefinition) Description() string

func (*AppDefinition) Label

func (a *AppDefinition) Label() string

func (*AppDefinition) OnReady

func (a *AppDefinition) OnReady(adminSite *AdminApplication)

func (*AppDefinition) Register

func (a *AppDefinition) Register(opts ModelOptions) *ModelDefinition

type AppOptions

type AppOptions struct {
	// RegisterToAdminMenu allows for registering this app to the admin menu by default.
	RegisterToAdminMenu bool

	// EnableIndexView allows for enabling the index view for this app.
	//
	// If this is disabled, only a main sub-menu item will be created, but not for the index view.
	EnableIndexView bool

	// Applabel must return a human readable label for the app.
	AppLabel func() string

	// AppDescription must return a human readable description of this app.
	AppDescription func() string

	// MenuLabel must return a human readable label for the menu, this is how the app's name will appear in the admin's navigation.
	MenuLabel func() string

	// MenuOrder is the order in which the app will appear in the admin's navigation.
	MenuOrder int

	// MenuIcon must return a string representing the icon to use for the menu.
	//
	// This should be a HTML element, I.E. "<svg>...</svg>".
	MenuIcon func() string

	// MediaFn must return a media.Media object that will be used for this app.
	//
	// It will always be included in the admin's media.
	MediaFn func() media.Media

	// A custom index view for the app.
	//
	// This will override the default index view for the app.
	IndexView func(adminSite *AdminApplication, app *AppDefinition) views.View
}

type AuthConfig

type AuthConfig struct {
	// GetLoginForm is a function that returns a LoginForm
	//
	// This function is called when the user tries to login to the admin
	// interface. It should return a LoginForm that is used to render
	// the login form.
	//
	// If GetLoginHandler is set, this function will not be called.
	GetLoginForm func(r *http.Request, formOpts ...func(forms.Form)) LoginForm

	// GetLoginHandler is a function that returns a http.HandlerFunc for
	// logging a user in to the admin interface.
	//
	// If GetLoginHandler is set, this function will be called instead
	// of GetLoginForm. It should return a http.HandlerFunc that is
	// used to render the login form.
	GetLoginHandler func(w http.ResponseWriter, r *http.Request)

	// Logout is a function that is called when the user logs out of
	// the admin interface.
	Logout func(r *http.Request) error
}

type BoundFormPanel

type BoundFormPanel[T forms.Form, P Panel] struct {
	forms.BoundField
	Context context.Context
	Panel   P
	Form    T
}

func (*BoundFormPanel[T, P]) Component

func (p *BoundFormPanel[T, P]) Component() templ.Component

func (*BoundFormPanel[T, P]) Render

func (p *BoundFormPanel[T, P]) Render() template.HTML

type BoundMultiPanel

type BoundMultiPanel[T forms.Form] struct {
	LabelFn func() string
	Context context.Context
	Panels  []BoundPanel
	Form    T
}

func (*BoundMultiPanel[T]) Component

func (p *BoundMultiPanel[T]) Component() templ.Component

func (*BoundMultiPanel[T]) Render

func (p *BoundMultiPanel[T]) Render() template.HTML

type BoundPanel

type BoundPanel interface {
	Component() templ.Component
	Render() template.HTML
}

type BoundTitlePanel

type BoundTitlePanel[T forms.Form, P Panel] struct {
	BoundPanel
	Context context.Context
}

func (*BoundTitlePanel[T, P]) Component

func (p *BoundTitlePanel[T, P]) Component() templ.Component

func (*BoundTitlePanel[T, P]) Render

func (p *BoundTitlePanel[T, P]) Render() template.HTML
type BreadCrumb struct {
	Title string
	URL   string
}

type DeleteViewOptions

type DeleteViewOptions struct {

	// GetHandler is a function that returns a views.View for the model.
	//
	// This allows you to have full control over the view used for deleting the model.
	//
	// This does mean that any logic provided by the admin when deleting the model should be implemented by the developer.
	GetHandler func(adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition, instance attrs.Definer) views.View

	// DeleteInstance is a function that deletes the instance.
	//
	// This allows for custom logic to be executed when deleting the instance.
	DeleteInstance func(context.Context, attrs.Definer) error
}

type FormDefiner

type FormDefiner interface {
	attrs.Definer
	AdminForm(r *http.Request, app *AppDefinition, model *ModelDefinition) modelforms.ModelForm[attrs.Definer]
}

FormDefiner is an interface that defines a form for the admin.

AdminForm is a method that returns a modelform.ModelForm[attrs.Definer] for the admin.

This can be used to create a custom form for your models, for the admin site.

type FormViewOptions

type FormViewOptions struct {
	ViewOptions

	// Widgets are used to define the widgets for the fields in the form.
	//
	// This allows for custom rendering logic of the fields in the form.
	Widgets map[string]widgets.Widget

	// GetForm is a function that returns a modelform.ModelForm for the model.
	GetForm func(req *http.Request, instance attrs.Definer, fields []string) modelforms.ModelForm[attrs.Definer]

	// FormInit is a function that can be used to initialize the form.
	//
	// This may be useful for providing custom form initialization logic.
	FormInit func(instance attrs.Definer, form modelforms.ModelForm[attrs.Definer])

	// GetHandler is a function that returns a views.View for the model.
	//
	// This allows you to have full control over the view used for saving the model.
	//
	// This does mean that any logic provided by the admin when saving the model should be implemented by the developer.
	GetHandler func(adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition, instance attrs.Definer) views.View

	// A custom function for saving the instance.
	//
	// This function will be called when the form is saved and allows for custom logic to be executed when saving the instance.
	SaveInstance func(context.Context, attrs.Definer) error

	// Panels are used to group fields in the form.
	//
	// This allows for a more simple, maintainable and organized form layout.
	Panels []Panel
}

Options for a model-specific form view.

type ListAction

type ListAction[T attrs.Definer] struct {
	Classname string
	Show      func(r *http.Request, defs attrs.Definitions, row T) bool
	Text      func(r *http.Request, defs attrs.Definitions, row T) string
	URL       func(r *http.Request, defs attrs.Definitions, row T) string
}

func (*ListAction[T]) Component

func (l *ListAction[T]) Component(r *http.Request, defs attrs.Definitions, row T) templ.Component

func (*ListAction[T]) IsShown

func (l *ListAction[T]) IsShown(r *http.Request, defs attrs.Definitions, row T) bool

type ListActionsColumn

type ListActionsColumn[T attrs.Definer] struct {
	Heading func() string
	Actions []*ListAction[T]
}

func (*ListActionsColumn[T]) Component

func (l *ListActionsColumn[T]) Component(r *http.Request, defs attrs.Definitions, row T) templ.Component

func (*ListActionsColumn[T]) Header

func (l *ListActionsColumn[T]) Header() templ.Component

type ListViewOptions

type ListViewOptions struct {
	ViewOptions

	// PerPage is the number of items to show per page.
	//
	// This is used for pagination in the list view.
	PerPage uint64

	// Columns are used to define the columns in the list view.
	//
	// This allows for custom rendering logic of the columns in the list view.
	Columns map[string]list.ListColumn[attrs.Definer]

	// Format is a map of field name to a function that formats the field value.
	//
	// I.E. map[string]func(v any) any{"Name": func(v any) any { return strings.ToUpper(v.(string)) }}
	// would uppercase the value of the "Name" field in the list view.
	Format map[string]func(v any) any

	// GetHandler is a function that returns a views.View for the model.
	//
	// This allows you to have full control over the view used for listing the models.
	//
	// This does mean that any logic provided by the admin when listing the models should be implemented by the developer.
	GetHandler func(adminSite *AdminApplication, app *AppDefinition, model *ModelDefinition) views.View
}

type LoginForm

type LoginForm interface {
	forms.Form
	SetRequest(req *http.Request)
	Login() error
}

type ModelDefinition

type ModelDefinition struct {
	ModelOptions
	// contains filtered or unexported fields
}

A struct which is mainly used internally (but can be used by third parties) to easily work with models in admin views.

func FindDefinition added in v1.6.7

func FindDefinition(model attrs.Definer) *ModelDefinition

func (*ModelDefinition) App added in v1.6.7

func (o *ModelDefinition) App() *AppDefinition

func (*ModelDefinition) FormatColumn

func (o *ModelDefinition) FormatColumn(field string) any

func (*ModelDefinition) GetColumn

func (o *ModelDefinition) GetColumn(opts ListViewOptions, field string) list.ListColumn[attrs.Definer]

func (*ModelDefinition) GetInstance

func (m *ModelDefinition) GetInstance(identifier any) (attrs.Definer, error)

func (*ModelDefinition) GetLabel

func (o *ModelDefinition) GetLabel(opts ViewOptions, field string, default_ string) func() string

func (*ModelDefinition) GetListInstances

func (m *ModelDefinition) GetListInstances(amount, offset uint) ([]attrs.Definer, error)

func (*ModelDefinition) GetName

func (o *ModelDefinition) GetName() string

func (*ModelDefinition) Label

func (o *ModelDefinition) Label() string

func (*ModelDefinition) ModelFields

func (m *ModelDefinition) ModelFields(opts ViewOptions, instace attrs.Definer) []attrs.Field

func (*ModelDefinition) NewInstance

func (o *ModelDefinition) NewInstance() attrs.Definer

Returns a new instance of the model.

This works the same as calling `reflect.New` on the model type.

func (*ModelDefinition) OnRegister

func (m *ModelDefinition) OnRegister(a *AdminApplication, app *AppDefinition)

func (*ModelDefinition) PluralLabel

func (o *ModelDefinition) PluralLabel() string

type ModelOptions

type ModelOptions struct {
	// Name is the name of the model.
	//
	// This is used for the model's name in the admin.
	Name string

	// MenuIcon is a function that returns the icon for the model in the admin menu.
	//
	// This should return an HTML element, I.E. "<svg>...</svg>".
	MenuIcon func() string

	// MenuOrder is the order of the model in the admin menu.
	MenuOrder int

	// MenuLabel is the label for the model in the admin menu.
	//
	// This is used for the model's label in the admin.
	MenuLabel func() string

	// DisallowCreate is a flag that determines if the model should be disallowed from being created.
	//
	// This is used to prevent the model from being created in the admin.
	DisallowCreate bool

	// DisallowEdit is a flag that determines if the model should be disallowed from being edited.
	//
	// This is used to prevent the model from being edited in the admin.
	DisallowEdit bool

	// DisallowDelete is a flag that determines if the model should be disallowed from being deleted.
	//
	// This is used to prevent the model from being deleted in the admin.
	DisallowDelete bool

	// AddView is the options for the add view of the model.
	//
	// This allows for custom creation logic and formatting form fields / layout.
	AddView FormViewOptions

	// EditView is the options for the edit view of the model.
	//
	// This allows for custom editing logic and formatting form fields / layout.
	EditView FormViewOptions

	// ListView is the options for the list view of the model.
	//
	// This allows for custom listing logic and formatting list columns.
	ListView ListViewOptions

	// DeleteView is the options for the delete view of the model.
	//
	// Any custom logic for deleting the model should be implemented here.
	DeleteView DeleteViewOptions

	// RegisterToAdminMenu is a flag that determines if the model should be automatically registered to the admin menu.
	RegisterToAdminMenu bool

	// Labels for the fields in the model.
	//
	// This provides a simple top- level override for the labels of the fields in the model.
	//
	// Any custom labels for fields implemented in the AddView, EditView or ListView will take precedence over these labels.
	Labels map[string]func() string

	// Model is the object that the above- defined options are for.
	Model attrs.Definer
}

type PageOptions

type PageOptions struct {
	Request     *http.Request
	TitleFn     func() string
	SubtitleFn  func() string
	MediaFn     func() media.Media
	BreadCrumbs []BreadCrumb
	Actions     []Action
}

func (*PageOptions) GetActions

func (p *PageOptions) GetActions() []Action

func (*PageOptions) GetBreadCrumbs

func (p *PageOptions) GetBreadCrumbs() []BreadCrumb

func (*PageOptions) Media added in v1.7.0

func (p *PageOptions) Media() media.Media

func (*PageOptions) Subtitle

func (p *PageOptions) Subtitle() string

func (*PageOptions) Title

func (p *PageOptions) Title() string

type Panel

type Panel interface {
	Fields() []string
	Bind(form forms.Form, ctx context.Context, boundFields map[string]forms.BoundField) BoundPanel
}

func FieldPanel

func FieldPanel(fieldname string) Panel

func MultiPanel

func MultiPanel(panels ...Panel) Panel

func TitlePanel

func TitlePanel(panel Panel) Panel

type PanelBoundForm

type PanelBoundForm struct {
	forms.BoundForm
	BoundPanels []BoundPanel
	Panels      []Panel
	Context     context.Context
}

func (*PanelBoundForm) AsP

func (b *PanelBoundForm) AsP() template.HTML

func (*PanelBoundForm) AsUL

func (b *PanelBoundForm) AsUL() template.HTML

func (*PanelBoundForm) ErrorList

func (b *PanelBoundForm) ErrorList() []error

func (*PanelBoundForm) Errors

func (b *PanelBoundForm) Errors() *orderedmap.OrderedMap[string, []error]

func (*PanelBoundForm) Fields

func (b *PanelBoundForm) Fields() []forms.BoundField

func (*PanelBoundForm) Media

func (b *PanelBoundForm) Media() media.Media

type RegisterAdminAppPageComponentHookFunc added in v1.7.0

type RegisterAdminAppPageComponentHookFunc = func(r *http.Request, adminSite *AdminApplication, app *AppDefinition) AdminPageComponent

type RegisterBreadCrumbHookFunc

type RegisterBreadCrumbHookFunc = func(r *http.Request, adminSite *AdminApplication) []BreadCrumb

type RegisterFooterMenuItemHookFunc

type RegisterFooterMenuItemHookFunc = func(r *http.Request, adminSite *AdminApplication, items components.Items[menu.MenuItem])

RegisterAppMenuItemHookFunc func(adminSite *AdminApplication, app *AppDefinition) []menu.MenuItem

type RegisterHomePageActionHookFunc added in v1.7.0

type RegisterHomePageActionHookFunc = func(*http.Request, *AdminApplication, []Action)

type RegisterHomePageBreadcrumbHookFunc added in v1.7.0

type RegisterHomePageBreadcrumbHookFunc = func(*http.Request, *AdminApplication, []BreadCrumb)

type RegisterHomePageComponentHookFunc added in v1.7.0

type RegisterHomePageComponentHookFunc = func(*http.Request, *AdminApplication) AdminPageComponent

type RegisterMediaHookFunc added in v1.7.0

type RegisterMediaHookFunc = func(adminSite *AdminApplication) media.Media

type RegisterMenuItemHookFunc

type RegisterMenuItemHookFunc = func(r *http.Request, adminSite *AdminApplication, items components.Items[menu.MenuItem])

type RegisterNavActionHookFunc

type RegisterNavActionHookFunc = func(r *http.Request, adminSite *AdminApplication) []Action

type ViewOptions

type ViewOptions struct {
	// Fields to include for the model in the view
	Fields []string

	// Fields to exclude from the model in the view
	Exclude []string

	// Labels for the fields in the view
	//
	// This is a map of field name to a function that returns the label for the field.
	//
	// Allowing for custom labels for fields in the view.
	Labels map[string]func() string
}

Basic options for a model-based view which includes a form.

Directories

Path Synopsis
templ: version: v0.3.833
templ: version: v0.3.833
menu
templ: version: v0.3.833
templ: version: v0.3.833

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL