feat(09-04): compile switch, date-range, and scope filters
- Filters keep typed values and only registered scope names - Raw conditions and arbitrary methods fail activation - Request localization copies labels and leaves identifiers unchanged
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"git.golem15.com/golem15/summercms/pact"
|
||||
"git.golem15.com/golem15/summercms/phrasebook"
|
||||
"git.golem15.com/golem15/summercms/towel"
|
||||
"github.com/goccy/go-yaml"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -35,6 +36,7 @@ type listDocument struct {
|
||||
ShowSearch bool `yaml:"showSearch"`
|
||||
DefaultSort *listSortDocument `yaml:"defaultSort"`
|
||||
Toolbar *listToolbar `yaml:"toolbar"`
|
||||
Filter string `yaml:"filter"`
|
||||
}
|
||||
|
||||
type listSortDocument struct {
|
||||
@@ -145,6 +147,13 @@ func compileList(pluginID string, ctl pact.AdminController, fsys fs.FS) (*ListSc
|
||||
if doc.ShowCheckboxes {
|
||||
bulk = append(bulk, BulkAction{Name: "delete", Label: "backend::lang.list.delete_selected"})
|
||||
}
|
||||
filters := []ListFilter{}
|
||||
if strings.TrimSpace(doc.Filter) != "" {
|
||||
filters, err = compileFilters(pluginID, ctl, fsys, dir, doc.Filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &ListSchema{
|
||||
Title: doc.Title,
|
||||
ModelClass: doc.ModelClass,
|
||||
@@ -161,7 +170,7 @@ func compileList(pluginID string, ctl pact.AdminController, fsys fs.FS) (*ListSc
|
||||
DefaultSort: sort,
|
||||
ToolbarButtons: buttons,
|
||||
Columns: columns,
|
||||
Filters: []ListFilter{},
|
||||
Filters: filters,
|
||||
RowActions: rowActions,
|
||||
BulkActions: bulk,
|
||||
}, nil
|
||||
@@ -354,8 +363,8 @@ func isListRelation(t reflect.Type) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Localize copies the cached list schema for one request.
|
||||
// The RED seam returns source keys; request-time translation replaces this body.
|
||||
// Localize copies the cached list schema and resolves display strings for one request.
|
||||
// Column, filter, and scope identifiers and option values are not translated.
|
||||
func (s *ListSchema) Localize(ctx context.Context, tr *phrasebook.Translator) (*ListSchema, error) {
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("cabana: nil list schema")
|
||||
@@ -363,7 +372,78 @@ func (s *ListSchema) Localize(ctx context.Context, tr *phrasebook.Translator) (*
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
locale := schemaLocale(ctx, tr)
|
||||
ctx = towel.WithLocale(ctx, locale)
|
||||
out := *s
|
||||
_ = tr
|
||||
out.Title = translateKey(ctx, tr, s.Title)
|
||||
out.NoRecordsMessage = translateKey(ctx, tr, s.NoRecordsMessage)
|
||||
out.SearchPrompt = translateKey(ctx, tr, s.SearchPrompt)
|
||||
out.PerPageOptions = append([]int(nil), s.PerPageOptions...)
|
||||
out.ToolbarButtons = append([]string(nil), s.ToolbarButtons...)
|
||||
if s.DefaultSort != nil {
|
||||
sort := *s.DefaultSort
|
||||
out.DefaultSort = &sort
|
||||
}
|
||||
out.Columns = localizeListColumns(ctx, tr, s.Columns)
|
||||
out.Filters = localizeListFilters(ctx, tr, s.Filters)
|
||||
out.RowActions = localizeRowActions(ctx, tr, s.RowActions)
|
||||
out.BulkActions = localizeBulkActions(ctx, tr, s.BulkActions)
|
||||
out.Meta = &FormMeta{Locale: locale}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func localizeListColumns(ctx context.Context, tr *phrasebook.Translator, cols []ListColumn) []ListColumn {
|
||||
out := make([]ListColumn, len(cols))
|
||||
for i, col := range cols {
|
||||
col.Label = translateKey(ctx, tr, col.Label)
|
||||
out[i] = col
|
||||
}
|
||||
if out == nil {
|
||||
out = []ListColumn{}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func localizeListFilters(ctx context.Context, tr *phrasebook.Translator, filters []ListFilter) []ListFilter {
|
||||
out := make([]ListFilter, len(filters))
|
||||
for i, filter := range filters {
|
||||
filter.Label = translateKey(ctx, tr, filter.Label)
|
||||
if len(filter.Options) > 0 {
|
||||
opts := make([]FormOption, len(filter.Options))
|
||||
for j, opt := range filter.Options {
|
||||
opt.Label = translateKey(ctx, tr, opt.Label)
|
||||
opts[j] = opt
|
||||
}
|
||||
filter.Options = opts
|
||||
}
|
||||
out[i] = filter
|
||||
}
|
||||
if out == nil {
|
||||
out = []ListFilter{}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func localizeRowActions(ctx context.Context, tr *phrasebook.Translator, actions []RowAction) []RowAction {
|
||||
out := make([]RowAction, len(actions))
|
||||
for i, action := range actions {
|
||||
action.Label = translateKey(ctx, tr, action.Label)
|
||||
out[i] = action
|
||||
}
|
||||
if out == nil {
|
||||
out = []RowAction{}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func localizeBulkActions(ctx context.Context, tr *phrasebook.Translator, actions []BulkAction) []BulkAction {
|
||||
out := make([]BulkAction, len(actions))
|
||||
for i, action := range actions {
|
||||
action.Label = translateKey(ctx, tr, action.Label)
|
||||
out[i] = action
|
||||
}
|
||||
if out == nil {
|
||||
out = []BulkAction{}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user