Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions cmd/system.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package cmd

import (
"context"
"fmt"
"os"
"strconv"
"text/tabwriter"

"github.com/pepabo/xpoint-cli/internal/xpoint"
"github.com/spf13/cobra"
)

var (
systemFormListOutput string
systemFormListJQ string
systemFormShowOutput string
systemFormShowJQ string
)

var systemCmd = &cobra.Command{
Use: "system",
Short: "X-point system (admin) APIs",
}

var systemFormCmd = &cobra.Command{
Use: "form",
Short: "Manage X-point forms via admin APIs",
}

var systemFormListCmd = &cobra.Command{
Use: "list",
Short: "List registration forms (admin)",
Long: "List all registered forms via GET /api/v1/system/forms. Requires an administrator account.",
RunE: runSystemFormList,
}

var systemFormShowCmd = &cobra.Command{
Use: "show <form_code|form_id>",
Short: "Show a form definition (admin)",
Long: `Fetch field definitions via GET /api/v1/system/forms/{fid}.

The argument may be a form_code (e.g. "TORIHIKISAKI_a") or a numeric
form_id. When a form_code is given, the CLI first calls
/api/v1/system/forms to resolve the id. Requires an administrator
account.`,
Args: cobra.ExactArgs(1),
RunE: runSystemFormShow,
}

func init() {
rootCmd.AddCommand(systemCmd)
systemCmd.AddCommand(systemFormCmd)
systemFormCmd.AddCommand(systemFormListCmd)
systemFormCmd.AddCommand(systemFormShowCmd)

lf := systemFormListCmd.Flags()
lf.StringVarP(&systemFormListOutput, "output", "o", "", "output format: table|json (default: table on TTY, json otherwise)")
lf.StringVar(&systemFormListJQ, "jq", "", "apply a gojq filter to the JSON response (forces JSON output)")

sf := systemFormShowCmd.Flags()
sf.StringVarP(&systemFormShowOutput, "output", "o", "", "output format: table|json (default: table on TTY, json otherwise)")
sf.StringVar(&systemFormShowJQ, "jq", "", "apply a gojq filter to the JSON response (forces JSON output)")
}

func runSystemFormList(cmd *cobra.Command, args []string) error {
client, err := newClientFromFlags(cmd.Context())
if err != nil {
return err
}
res, err := client.ListSystemForms(cmd.Context())
if err != nil {
return err
}

return render(res, resolveOutputFormat(systemFormListOutput), systemFormListJQ, func() error {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
defer w.Flush()
fmt.Fprintln(w, "GROUP_ID\tGROUP_NAME\tFORMS\tFORM_ID\tFORM_CODE\tFORM_NAME\tPAGES\tTABLE")
for _, g := range res.FormGroup {
if len(g.Form) == 0 {
fmt.Fprintf(w, "%s\t%s\t%d\t-\t-\t-\t-\t-\n", g.ID, g.Name, g.FormCount)
continue
}
for _, f := range g.Form {
fmt.Fprintf(w, "%s\t%s\t%d\t%d\t%s\t%s\t%d\t%s\n",
g.ID, g.Name, g.FormCount, f.ID, f.Code, f.Name, f.PageCount, f.TableName,
)
}
}
return nil
})
}

func runSystemFormShow(cmd *cobra.Command, args []string) error {
client, err := newClientFromFlags(cmd.Context())
if err != nil {
return err
}

formID, err := resolveSystemFormID(cmd.Context(), client, args[0])
if err != nil {
return err
}

res, err := client.GetSystemFormDetail(cmd.Context(), formID)
if err != nil {
return err
}

return render(res, resolveOutputFormat(systemFormShowOutput), systemFormShowJQ, func() error {
form := res.Form
fmt.Fprintf(os.Stdout, "FORM: %s %s MAX_STEP: %d\n", form.Code, form.Name, form.MaxStep)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
defer w.Flush()
fmt.Fprintln(w, "PAGE\tFIELD_ID\tTYPE\tREQUIRED\tUNIQUE\tARRAYSIZE\tLABEL")
for _, p := range form.Pages {
for _, f := range p.Fields {
fmt.Fprintf(w, "%d\t%s\t%d\t%t\t%t\t%d\t%s\n",
p.PageNo, f.FieldID, f.FieldType, f.Required, f.Unique, f.ArraySize, f.Label,
)
}
}
return nil
})
}

type systemFormLister interface {
ListSystemForms(ctx context.Context) (*xpoint.SystemFormsListResponse, error)
}

// resolveSystemFormID mirrors resolveFormID but consults the admin forms list.
func resolveSystemFormID(ctx context.Context, lister systemFormLister, arg string) (int, error) {
if id, err := strconv.Atoi(arg); err == nil {
return id, nil
}
forms, err := lister.ListSystemForms(ctx)
if err != nil {
return 0, fmt.Errorf("resolve form code: %w", err)
}
for _, g := range forms.FormGroup {
for _, f := range g.Form {
if f.Code == arg {
return f.ID, nil
}
}
}
return 0, fmt.Errorf("form code %q not found", arg)
}
2 changes: 2 additions & 0 deletions internal/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func TestAliases_Sorted(t *testing.T) {
"form.show",
"query.exec",
"query.list",
"system.form.list",
"system.form.show",
}
if len(got) != len(want) {
t.Fatalf("aliases = %v", got)
Expand Down
66 changes: 66 additions & 0 deletions internal/schema/system.form.list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"method": "GET",
"path": "/api/v1/system/forms",
"summary": "登録フォーム一覧取得 (管理者)",
"description": "管理者サイトの「フォーム管理」で表示される一覧相当のリストを取得する。\n管理者権限を持つユーザで認証した場合のみ利用可能。\n",
"parameters": [],
"response": {
"type": "object",
"properties": {
"form_group": {
"type": "array",
"description": "フォームグループ情報 (存在しない場合は空配列)",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "フォームグループID"
},
"name": {
"type": "string",
"description": "フォームグループ名称"
},
"form_count": {
"type": "integer",
"description": "所属フォーム数"
},
"form": {
"type": "array",
"description": "所属フォーム情報 (存在しない場合は空配列)",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "フォームID"
},
"name": {
"type": "string",
"description": "フォーム名称"
},
"code": {
"type": "string",
"description": "フォームコード"
},
"page_count": {
"type": "integer",
"description": "フォーム構成ページ数"
},
"table_name": {
"type": "string",
"description": "DBテーブル名"
},
"tsffile_name": {
"type": "string",
"description": "TSFファイル名"
}
}
}
}
}
}
}
}
}
}
124 changes: 124 additions & 0 deletions internal/schema/system.form.show.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"method": "GET",
"path": "/api/v1/system/forms/{fid}",
"summary": "フォーム定義情報取得 (管理者)",
"description": "フォームを構成するフィールドの詳細情報を取得する。\n管理者ユーザで認証した場合のみフォーム定義が取得できる。\n一般ユーザで取得する場合は /api/v1/forms/{fid} (form show) を利用する。\n",
"parameters": [
{
"name": "fid",
"in": "path",
"required": true,
"type": "integer",
"description": "フォームID"
}
],
"response": {
"type": "object",
"properties": {
"form": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "フォームコード"
},
"name": {
"type": "string",
"description": "フォーム名称"
},
"max_step": {
"type": "integer",
"description": "フォーム最大ステップ数"
},
"route": {
"type": "array",
"description": "フォームルート情報 (通常フォームでは空配列)",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "ルートコード"
},
"name": {
"type": "string",
"description": "ルート名称"
},
"condroute": {
"type": "boolean",
"description": "true: 条件付きルート / false: ユーザ選択ルート"
}
}
}
},
"pages": {
"type": "array",
"description": "フォームページ情報",
"items": {
"type": "object",
"properties": {
"page_no": {
"type": "integer",
"description": "ページ番号"
},
"form_code": {
"type": "string",
"description": "複数枚フォームの場合のみ出力"
},
"form_name": {
"type": "string",
"description": "複数枚フォームの場合のみ出力"
},
"fields": {
"type": "array",
"description": "フィールド情報",
"items": {
"type": "object",
"properties": {
"seq": {
"type": "integer",
"description": "シーケンス番号"
},
"fieldid": {
"type": "string",
"description": "フィールドID"
},
"fieldtype": {
"type": "integer",
"description": "フィールドタイプ"
},
"maxlength": {
"type": "integer",
"description": "フィールド最大値"
},
"label": {
"type": "string",
"description": "フィールドラベル"
},
"groupname": {
"type": "string",
"description": "グループ名称"
},
"arraysize": {
"type": "integer",
"description": "表明細数 (0なら非表明細)"
},
"required": {
"type": "boolean",
"description": "必須フィールドフラグ"
},
"unique": {
"type": "boolean",
"description": "ユニークフィールドフラグ"
}
}
}
}
}
}
}
}
}
}
}
}
Loading