feat(build): scaffold working admin controllers with model, AdminFS and delete (quick-261028-pq8)

- make:admin-controller edits the singular of its name (--model overrides):
  ModelName, modelClass and the YAML under models/<model>/
- NewRecord returns &models.<Model>{} when the model exists; otherwise the
  nil body stays and the command says to run make:model
- config_list.yaml offers create and delete with showCheckboxes
- registry.gen.go embeds controllers/*/*.yaml and models/*/*.yaml once they
  exist and exposes generatedAdminFS(); scaffolded plugins implement
  pact.AdminAssets through it, and a plugin without AdminFS gets a note
- blog example moves its YAML to models/post; docs and help text follow
This commit is contained in:
Jakub Zych
2026-10-28 19:15:23 +01:00
parent 70e4b4183c
commit 8bc18c90b6
22 changed files with 491 additions and 84 deletions

View File

@@ -270,16 +270,24 @@ func makeAdminControllerCommand() bonfire.Command {
Name: "make:admin-controller",
Description: "Generate an admin controller with fields.yaml and columns.yaml",
Long: `Writes controllers/<name>.go, its config_form.yaml and config_list.yaml, and
starter fields.yaml and columns.yaml under models/<name>/, in the plugin with
this ID or the plugin whose directory you are in. The controller requires the
permission <plugin>.access_<name>, which you declare in the plugin's
Permissions(), and its NewRecord returns nil until you return your model, so
the screens stay closed until you finish it.`,
starter fields.yaml and columns.yaml under models/<model>/, in the plugin with
this ID or the plugin whose directory you are in. The model is the singular of
the name (Posts edits Post) unless --model names it. When models/ already has
that model, NewRecord returns it; otherwise NewRecord returns nil until you run
make:model and return it, so the screens stay closed until you finish it. The
list offers create and delete. The controller requires the permission
<plugin>.access_<name>, which you declare in the plugin's Permissions(). A
scaffolded plugin serves the YAML through AdminFS from registry.gen.go.`,
Examples: []bonfire.Example{
{Command: "make:admin-controller acme.blog Posts", Description: "A Posts controller in acme.blog"},
{Command: "make:admin-controller acme.blog Posts", Description: "A Posts controller for the Post model in acme.blog"},
{Command: "make:admin-controller Posts", Description: "The same from inside plugins/acme/blog"},
{Command: "make:admin-controller acme.blog People --model Person", Description: "A People controller for the Person model"},
},
Args: makeArtifactArgs(),
Args: makeArtifactArgs(),
Flags: []bonfire.Flag{{
Name: "model",
Description: "The model the controller edits (default: the singular of the name)",
}},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
dir, err := os.Getwd()
if err != nil {
@@ -289,7 +297,8 @@ the screens stay closed until you finish it.`,
if err != nil {
return err
}
result, err := build.MakeAdminController(ctx, dir, id, name)
model, _ := in.Flag("model")
result, err := build.MakeAdminController(ctx, dir, id, name, model)
if err != nil {
return err
}

View File

@@ -139,6 +139,11 @@ func TestMakeCommandsViaCLI(t *testing.T) {
t.Fatalf("make:job output missing reindex.go:\n%s", out)
}
out = runSummer("make:admin-controller", "golem15.demo", "People", "--model", "Person")
if !strings.Contains(out, filepath.Join("models", "person", "fields.yaml")) {
t.Fatalf("make:admin-controller --model output missing models/person:\n%s", out)
}
t.Chdir(pluginDir)
out = runSummer("make:command", "Purge")
if !strings.Contains(out, filepath.Join("console", "purge.go")) {