feat: Add SLD endpoints, add date_to to vector_with_kato

This commit is contained in:
2026-08-01 22:09:59 +05:00
parent 00a0cd1b8e
commit 1e0844ca82
8 changed files with 656 additions and 34 deletions

View File

@@ -43,6 +43,8 @@ func (h *DatasetHandler) Register(r chi.Router) {
r.Get("/{id}.cog", h.cog)
r.Get("/{id}/status", h.status)
r.Get("/{id}/download", h.download)
r.Post("/{id}/sld", h.uploadSLD)
r.Get("/{id}/sld", h.downloadSLD)
r.Post("/{id}/mapping", h.mapping)
r.Get("/{id}/observations", h.observations)
r.Delete("/{id}", h.delete)
@@ -78,8 +80,9 @@ func (h *DatasetHandler) status(w http.ResponseWriter, r *http.Request) {
}
type yearColumnInput struct {
Column string `json:"column" validate:"required"`
Date string `json:"date" validate:"required,datetime=2006-01-02"`
Column string `json:"column" validate:"required"`
Date string `json:"date" validate:"required,datetime=2006-01-02"`
DateTo *string `json:"date_to" validate:"omitempty,datetime=2006-01-02"`
}
type mappingRequest struct {
@@ -106,7 +109,7 @@ func (h *DatasetHandler) mapping(w http.ResponseWriter, r *http.Request) {
in := service.MappingInput{KatoColumn: req.KatoColumn}
for _, yc := range req.YearColumns {
in.YearColumns = append(in.YearColumns, domain.YearColumn{Column: yc.Column, Date: yc.Date})
in.YearColumns = append(in.YearColumns, domain.YearColumn{Column: yc.Column, Date: yc.Date, DateTo: yc.DateTo})
}
dataset, err := h.svc.SaveMapping(r.Context(), id, in)
@@ -533,6 +536,74 @@ func (h *DatasetHandler) download(w http.ResponseWriter, r *http.Request) {
}
}
// uploadSLD stores (or replaces) a dataset's SLD (Styled Layer Descriptor)
// style file. Multipart upload, mirroring POST /datasets. Applies to every
// file_type.
func (h *DatasetHandler) uploadSLD(w http.ResponseWriter, r *http.Request) {
id, ok := parseUUIDParam(w, r, "id")
if !ok {
return
}
if err := r.ParseMultipartForm(maxUploadBytes); err != nil {
httputil.WriteError(w, http.StatusBadRequest, "request must be multipart/form-data")
return
}
file, header, err := r.FormFile("file")
if err != nil {
httputil.WriteError(w, http.StatusBadRequest, "file is required")
return
}
defer file.Close()
contentType := header.Header.Get("Content-Type")
if contentType == "" {
contentType = "application/xml"
}
dataset, err := h.svc.UploadSLD(r.Context(), id, service.UploadSLDInput{
Filename: header.Filename,
ContentType: contentType,
Size: header.Size,
Reader: file,
})
if err != nil {
respondDomainError(w, err)
return
}
httputil.WriteJSON(w, http.StatusOK, dataset)
}
// downloadSLD streams a dataset's stored SLD style file. Returns 404 if none
// has been uploaded yet.
func (h *DatasetHandler) downloadSLD(w http.ResponseWriter, r *http.Request) {
id, ok := parseUUIDParam(w, r, "id")
if !ok {
return
}
dataset, obj, err := h.svc.DownloadSLD(r.Context(), id)
if err != nil {
respondDomainError(w, err)
return
}
defer obj.Close()
contentType := "application/xml"
if dataset.SldContentType != nil && *dataset.SldContentType != "" {
contentType = *dataset.SldContentType
}
filename := "style.sld"
if dataset.SldFilename != nil && *dataset.SldFilename != "" {
filename = *dataset.SldFilename
}
w.Header().Set("Content-Type", contentType)
w.Header().Set("Content-Disposition", `attachment; filename="`+filename+`"`)
if _, err := io.Copy(w, obj); err != nil {
// Headers are already sent; nothing useful to return to the client.
return
}
}
func (h *DatasetHandler) delete(w http.ResponseWriter, r *http.Request) {
id, ok := parseUUIDParam(w, r, "id")
if !ok {