/
attributes_input.go
190 lines (162 loc) · 4.81 KB
/
attributes_input.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package node
import (
"encoding/json"
"github.com/ory/kratos/text"
"github.com/ory/kratos/x"
"github.com/ory/x/jsonschemax"
)
const DisableFormField = "disableFormField"
func toFormType(n string, i interface{}) InputAttributeType {
switch n {
case x.CSRFTokenName:
return InputAttributeTypeHidden
case "password":
return InputAttributeTypePassword
}
switch i.(type) {
case float64, int64, int32, float32, json.Number:
return InputAttributeTypeNumber
case bool:
return InputAttributeTypeCheckbox
}
return InputAttributeTypeText
}
type InputAttributesModifier func(attributes *InputAttributes)
type InputAttributesModifiers []InputAttributesModifier
func WithRequiredInputAttribute(a *InputAttributes) {
a.Required = true
}
func WithInputAttributes(f func(a *InputAttributes)) func(a *InputAttributes) {
return func(a *InputAttributes) {
f(a)
}
}
func applyInputAttributes(opts []InputAttributesModifier, attributes *InputAttributes) *InputAttributes {
for _, f := range opts {
f(attributes)
}
return attributes
}
type ImageAttributesModifier func(attributes *ImageAttributes)
type ImageAttributesModifiers []ImageAttributesModifier
func WithImageAttributes(f func(a *ImageAttributes)) func(a *ImageAttributes) {
return func(a *ImageAttributes) {
f(a)
}
}
func applyImageAttributes(opts ImageAttributesModifiers, attributes *ImageAttributes) *ImageAttributes {
for _, f := range opts {
f(attributes)
}
return attributes
}
type ScriptAttributesModifier func(attributes *ScriptAttributes)
type ScriptAttributesModifiers []ScriptAttributesModifier
func WithScriptAttributes(f func(a *ScriptAttributes)) func(a *ScriptAttributes) {
return func(a *ScriptAttributes) {
f(a)
}
}
func applyScriptAttributes(opts ScriptAttributesModifiers, attributes *ScriptAttributes) *ScriptAttributes {
for _, f := range opts {
f(attributes)
}
return attributes
}
func NewInputFieldFromJSON(name string, value interface{}, group UiNodeGroup, opts ...InputAttributesModifier) *Node {
return &Node{
Type: Input,
Group: group,
Attributes: applyInputAttributes(opts, &InputAttributes{Name: name, Type: toFormType(name, value), FieldValue: value}),
Meta: &Meta{},
}
}
func NewInputField(name string, value interface{}, group UiNodeGroup, inputType InputAttributeType, opts ...InputAttributesModifier) *Node {
return &Node{
Type: Input,
Group: group,
Attributes: applyInputAttributes(opts, &InputAttributes{Name: name, Type: inputType, FieldValue: value}),
Meta: &Meta{},
}
}
func NewImageField(id string, src string, group UiNodeGroup, opts ...ImageAttributesModifier) *Node {
return &Node{
Type: Image,
Group: group,
Attributes: applyImageAttributes(opts, &ImageAttributes{Source: src, Identifier: id}),
Meta: &Meta{},
}
}
func NewTextField(id string, text *text.Message, group UiNodeGroup) *Node {
return &Node{
Type: Text,
Group: group,
Attributes: &TextAttributes{Text: text, Identifier: id},
Meta: &Meta{},
}
}
func NewAnchorField(id string, href string, group UiNodeGroup, title *text.Message) *Node {
return &Node{
Type: Anchor,
Group: group,
Attributes: &AnchorAttributes{Title: title, HREF: href, Identifier: id},
Meta: &Meta{},
}
}
func NewScriptField(name string, src string, group UiNodeGroup, integrity string, opts ...ScriptAttributesModifier) *Node {
return &Node{
Type: Script,
Group: group,
Attributes: applyScriptAttributes(opts, &ScriptAttributes{
Identifier: name,
Type: "text/javascript",
Source: src,
Async: true,
ReferrerPolicy: "no-referrer",
CrossOrigin: "anonymous",
Integrity: integrity,
Nonce: x.NewUUID().String(),
}),
Meta: &Meta{},
}
}
func NewInputFieldFromSchema(name string, group UiNodeGroup, p jsonschemax.Path, opts ...InputAttributesModifier) *Node {
attr := &InputAttributes{
Name: name,
Type: toFormType(p.Name, p.Type),
Required: p.Required,
}
// If format is set, we can make a more distinct decision:
switch p.Format {
case "date-time":
attr.Type = InputAttributeTypeDateTimeLocal
case "email":
attr.Type = InputAttributeTypeEmail
case "date":
attr.Type = InputAttributeTypeDate
case "uri":
attr.Type = InputAttributeTypeURI
case "regex":
attr.Type = InputAttributeTypeText
}
// Other properties
if p.Pattern != nil {
attr.Pattern = p.Pattern.String()
}
// Set disabled if the custom property is set
if isDisabled, ok := p.CustomProperties[DisableFormField]; ok {
if isDisabled, ok := isDisabled.(bool); ok {
attr.Disabled = isDisabled
}
}
var meta Meta
if len(p.Title) > 0 {
meta.Label = text.NewInfoNodeLabelGenerated(p.Title)
}
return &Node{
Type: Input,
Attributes: applyInputAttributes(opts, attr),
Group: group,
Meta: &meta,
}
}