mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-28 20:25:53 +00:00
fix🐛: leave the form out of a generated page with nothing to enter
A table whose columns are all its key and ones the framework fills in got an add button and an edit link opening an empty form. The page now leaves out both, the dialog, useForm and the API calls only the form used. A page with anything to enter is generated byte for byte as before.
This commit is contained in:
@@ -200,6 +200,42 @@ func TestAuditTimestampsCanBeListedAndQueried(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A table whose only columns are its key and the ones the framework fills in
|
||||
// leaves the create/edit dialog nothing to show. The page used to render it
|
||||
// anyway: an add button and an edit link opening an empty form.
|
||||
func TestAPageWithNothingToEnterHasNoForm(t *testing.T) {
|
||||
g := newGenEnv(t)
|
||||
const table = "gau_stamp"
|
||||
tableID := g.importTable(t, table, `id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
create_by bigint NULL,
|
||||
update_by bigint NULL,
|
||||
created_at datetime(3) NULL,
|
||||
updated_at datetime(3) NULL,
|
||||
deleted_at bigint NOT NULL DEFAULT 0`)
|
||||
|
||||
if code := callHandler(t, g.db, Gen{}.GenCode, "/", tableID); code != http.StatusOK {
|
||||
t.Fatalf("generation failed with response code %d", code)
|
||||
}
|
||||
vue := g.page(t, table)
|
||||
for _, unwanted := range []string{"<el-dialog", "<el-form", "useForm", "openCreate", "openEdit", "addGauStamp", "updateGauStamp", "getGauStamp"} {
|
||||
if strings.Contains(vue, unwanted) {
|
||||
t.Errorf("the generated page contains %s", unwanted)
|
||||
}
|
||||
}
|
||||
for _, want := range []string{"useTable", "remove(table.selectedIds)", "import { delGauStamp, listGauStamp }"} {
|
||||
if !strings.Contains(vue, want) {
|
||||
t.Errorf("the generated page has no %s", want)
|
||||
}
|
||||
}
|
||||
|
||||
overlay := filepath.Join(g.out, "overlay.json")
|
||||
b, _ := json.Marshal(map[string]any{"Replace": backendFiles(g.out, g.root, table)})
|
||||
if err := os.WriteFile(overlay, b, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
goCmd(t, g.root, "vet", "-overlay="+overlay, "./app/admin/...")
|
||||
}
|
||||
|
||||
// callJSON runs one handler with a JSON body and decodes the response's data
|
||||
// into data when it is not nil. It returns the code the body carries.
|
||||
func callJSON(t *testing.T, db *gorm.DB, h gin.HandlerFunc, method, body string, params gin.Params, data any) int {
|
||||
|
||||
+22
-10
@@ -56,6 +56,7 @@
|
||||
{{- $hasDatetime := false -}}
|
||||
{{- $hasRules := false -}}
|
||||
{{- $hasQuery := false -}}
|
||||
{{- $hasForm := false -}}
|
||||
{{- $pkType := "number" -}}
|
||||
{{- range .Columns -}}
|
||||
{{- $dictUsed := and (ne .DictType "") (or (and (eq .IsQuery "1") (eq .FkTableName "")) (and (eq .IsList "1") (eq .FkTableName "")) (and (eq .IsInsert "1") (eq .HtmlType "select") (eq .FkTableName "")) (and (eq .IsInsert "1") (eq .HtmlType "radio"))) -}}
|
||||
@@ -66,8 +67,15 @@
|
||||
{{- if and (eq .IsList "1") (eq .FkTableName "") (eq .DictType "") (eq .HtmlType "datetime") }}{{$hasDatetime = true}}{{end -}}
|
||||
{{- if eq .IsQuery "1" }}{{$hasQuery = true}}{{end -}}
|
||||
{{- if and (eq .IsInsert "1") (eq .IsRequired "1") (not .Pk) (ne .GoField "CreatedAt") (ne .GoField "UpdatedAt") (ne .GoField "DeletedAt") (ne .GoField "UpdateBy") (ne .GoField "CreateBy") }}{{$hasRules = true}}{{end -}}
|
||||
{{- if and .Pk (eq .GoType "string") }}{{$pkType = "string"}}{{$hasRules = true}}{{end -}}
|
||||
{{- if and .Pk (eq .GoType "string") }}{{$pkType = "string"}}{{$hasRules = true}}{{$hasForm = true}}{{end -}}
|
||||
{{- if and (eq .IsInsert "1") (not .Pk) (ne .GoField "CreatedAt") (ne .GoField "UpdatedAt") (ne .GoField "DeletedAt") (ne .GoField "UpdateBy") (ne .GoField "CreateBy") }}{{$hasForm = true}}{{end -}}
|
||||
{{- end -}}
|
||||
{{- /*
|
||||
$hasForm: the create/edit dialog would hold at least one field - a typed-in
|
||||
string key or an insertable column the framework does not fill in. Without
|
||||
one, the add button, the edit link and the dialog are left out, not rendered
|
||||
around an empty form that saves nothing the user chose.
|
||||
*/ -}}
|
||||
<template>
|
||||
<PageContainer>
|
||||
<ProTable :table="table" selection row-key="{{.PkJsonField}}">
|
||||
@@ -112,9 +120,11 @@
|
||||
{{- end}}
|
||||
|
||||
<template #toolbar>
|
||||
{{- if $hasForm}}
|
||||
<el-button v-permisaction="['{{.PackageName}}:{{.BusinessName}}:add']" type="primary" @click="form.openCreate()">
|
||||
{{ "{{" }} $t('common.add') {{ "}}" }}
|
||||
</el-button>
|
||||
{{- end}}
|
||||
<el-button
|
||||
v-permisaction="['{{.PackageName}}:{{.BusinessName}}:remove']"
|
||||
type="danger"
|
||||
@@ -156,14 +166,17 @@
|
||||
{{- end}}
|
||||
|
||||
<template #actions="{ row }">
|
||||
{{- if $hasForm}}
|
||||
<el-button v-permisaction="['{{.PackageName}}:{{.BusinessName}}:edit']" link type="primary" @click="form.openEdit(row)">
|
||||
{{ "{{" }} $t('common.edit') {{ "}}" }}
|
||||
</el-button>
|
||||
{{- end}}
|
||||
<el-button v-permisaction="['{{.PackageName}}:{{.BusinessName}}:remove']" link type="danger" @click="remove(row.{{.PkJsonField}})">
|
||||
{{ "{{" }} $t('common.delete') {{ "}}" }}
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
{{- if $hasForm}}
|
||||
|
||||
<el-dialog
|
||||
v-model="form.visible"
|
||||
@@ -254,6 +267,7 @@
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
{{- end}}
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
@@ -273,18 +287,14 @@ import ProTable from '@/components/ProTable/index.vue'
|
||||
{{- if $hasDatetime}}
|
||||
import DateCell from '@/components/DateCell/index.vue'
|
||||
{{- end}}
|
||||
{{- if $hasDict}}
|
||||
{{- if $hasDictList}}
|
||||
import { useTable, useForm, useRemove, useDict, dictLabel } from '@/composables'
|
||||
{{- else}}
|
||||
import { useTable, useForm, useRemove, useDict } from '@/composables'
|
||||
{{- end}}
|
||||
{{- else}}
|
||||
import { useTable, useForm, useRemove } from '@/composables'
|
||||
{{- end}}
|
||||
import { useTable{{if $hasForm}}, useForm{{end}}, useRemove{{if $hasDict}}, useDict{{if $hasDictList}}, dictLabel{{end}}{{end}} } from '@/composables'
|
||||
{{- if $hasForm}}
|
||||
import {
|
||||
add{{.ClassName}}, del{{.ClassName}}, get{{.ClassName}}, list{{.ClassName}}, update{{.ClassName}}
|
||||
} from '@/api/{{.PackageName}}/{{.MLTBName}}'
|
||||
{{- else}}
|
||||
import { del{{.ClassName}}, list{{.ClassName}} } from '@/api/{{.PackageName}}/{{.MLTBName}}'
|
||||
{{- end}}
|
||||
import type { {{.ClassName}}, {{.ClassName}}Query } from '@/api/{{.PackageName}}/{{.MLTBName}}'
|
||||
{{- /*
|
||||
Two columns pointing at the same foreign table must not import it twice --
|
||||
@@ -386,6 +396,7 @@ const rules = computed<FormRules>(() => ({ {{$rFirst := true}}
|
||||
{{- end}}
|
||||
}))
|
||||
{{- end}}
|
||||
{{- if $hasForm}}
|
||||
|
||||
const form = useForm<{{.ClassName}}, {{$pkType}}>({
|
||||
defaultModel: () => ({{"{"}} {{.PkJsonField}}: undefined{{range .Columns}}{{if and (eq .IsInsert "1") (not .Pk) (ne .GoField "CreatedAt") (ne .GoField "UpdatedAt") (ne .GoField "DeletedAt") (ne .GoField "UpdateBy") (ne .GoField "CreateBy")}}, {{.JsonField}}: {{if eq .DefaultValue ""}}undefined{{else if eq .GoType "int"}}{{.DefaultValue}}{{else}}'{{js .DefaultValue}}'{{end}}{{end}}{{end}} {{"}"}}),
|
||||
@@ -396,6 +407,7 @@ const form = useForm<{{.ClassName}}, {{$pkType}}>({
|
||||
api: { get: get{{.ClassName}}, add: add{{.ClassName}}, update: update{{.ClassName}} },
|
||||
onSuccess: () => table.getList()
|
||||
})
|
||||
{{- end}}
|
||||
|
||||
const { remove } = useRemove({
|
||||
api: del{{.ClassName}},
|
||||
|
||||
Reference in New Issue
Block a user