feat(12.2-02): add the datepicker field with server-side bounds and date list columns
- type: datepicker compiles the D-20 keys; format maps to displayFormat with WinterCMS's momentFormat table - boot fails when the mode does not match the column's Go type (time.Time, lagoon.Date, lagoon.TimeOfDay) - datepicker is a writable scalar field; minDate and maxDate are rechecked on save - columns.yaml accepts type: date and type: time; Scanner/Valuer structs are columns, not relations - conformance fixture carries date and datetime fields; README, forms and lists docs
This commit is contained in:
@@ -70,8 +70,8 @@ func compileFileuploadKeys(typ string, values map[string]ast.Node, field *FormFi
|
||||
return fmt.Errorf("%s is only valid on type: fileupload", key)
|
||||
}
|
||||
}
|
||||
if _, ok := values["mode"]; ok {
|
||||
return fmt.Errorf("mode is only valid on type: fileupload")
|
||||
if _, ok := values["mode"]; ok && typ != "datepicker" {
|
||||
return fmt.Errorf("mode is only valid on type: fileupload or datepicker")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -672,7 +672,7 @@ func (s *service) fileUpload(w http.ResponseWriter, r *http.Request) {
|
||||
return lifecycleFailure(cc, err)
|
||||
}
|
||||
if len(files) >= cf.maxFiles {
|
||||
return &ValidationError{Details: fieldDetail(cf.name, fileMessage(ctx, s.translator(), "max.array", cf.name, map[string]string{"max": strconv.Itoa(cf.maxFiles)}))}
|
||||
return &ValidationError{Details: fieldDetail(cf.name, fieldMessage(ctx, s.translator(), "max.array", cf.name, map[string]string{"max": strconv.Itoa(cf.maxFiles)}))}
|
||||
}
|
||||
}
|
||||
f, err := attach.Store(ctx, tx, bucket, attach.Upload{FileName: part.FileName(), Body: part, Public: cf.relation.Public}, cf.limits)
|
||||
@@ -739,7 +739,7 @@ func (s *service) writeFileError(w http.ResponseWriter, r *http.Request, cf *com
|
||||
case cf == nil:
|
||||
case errors.Is(err, attach.ErrTooLarge):
|
||||
kb := strconv.FormatInt(cf.maxBytes/1024, 10)
|
||||
detail = fileMessage(ctx, tr, "max.file", cf.name, map[string]string{"max": kb})
|
||||
detail = fieldMessage(ctx, tr, "max.file", cf.name, map[string]string{"max": kb})
|
||||
case errors.Is(err, attach.ErrFileType):
|
||||
types := cf.limits.Extensions
|
||||
if len(types) == 0 {
|
||||
@@ -748,11 +748,11 @@ func (s *service) writeFileError(w http.ResponseWriter, r *http.Request, cf *com
|
||||
types = attach.DefaultImageExtensions
|
||||
}
|
||||
}
|
||||
detail = fileMessage(ctx, tr, "mimes", cf.name, map[string]string{"values": strings.Join(types, ", ")})
|
||||
detail = fieldMessage(ctx, tr, "mimes", cf.name, map[string]string{"values": strings.Join(types, ", ")})
|
||||
case errors.Is(err, attach.ErrMIMEType):
|
||||
detail = fileMessage(ctx, tr, "mimetypes", cf.name, map[string]string{"values": strings.Join(cf.limits.MIMETypes, ", ")})
|
||||
detail = fieldMessage(ctx, tr, "mimetypes", cf.name, map[string]string{"values": strings.Join(cf.limits.MIMETypes, ", ")})
|
||||
case errors.Is(err, attach.ErrNotImage):
|
||||
detail = fileMessage(ctx, tr, "image", cf.name, nil)
|
||||
detail = fieldMessage(ctx, tr, "image", cf.name, nil)
|
||||
}
|
||||
if detail != "" {
|
||||
writeCRUDError(w, &ValidationError{Details: fieldDetail(cf.name, detail)})
|
||||
@@ -801,9 +801,9 @@ func fieldDetail(field, message string) map[string]any {
|
||||
return map[string]any{field: []string{message}}
|
||||
}
|
||||
|
||||
// fileMessage is a lagoon::validation line for a file field, with Laravel's
|
||||
// English text when no translator has the key.
|
||||
func fileMessage(ctx context.Context, tr *phrasebook.Translator, rule, field string, params map[string]string) string {
|
||||
// fieldMessage is a lagoon::validation line for a file or date field, with
|
||||
// Laravel's English text when no translator has the key.
|
||||
func fieldMessage(ctx context.Context, tr *phrasebook.Translator, rule, field string, params map[string]string) string {
|
||||
if params == nil {
|
||||
params = map[string]string{}
|
||||
}
|
||||
@@ -826,6 +826,10 @@ func fileMessage(ctx context.Context, tr *phrasebook.Translator, rule, field str
|
||||
return "The " + attr + " must be an image."
|
||||
case "required":
|
||||
return "The " + attr + " field is required."
|
||||
case "after_or_equal":
|
||||
return "The " + attr + " must be a date after or equal to " + params["date"] + "."
|
||||
case "before_or_equal":
|
||||
return "The " + attr + " must be a date before or equal to " + params["date"] + "."
|
||||
}
|
||||
return "The " + attr + " is invalid."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user