diff --git a/openapi.yaml b/openapi.yaml index ab8b71e..8179ac6 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -191,9 +191,7 @@ paths: content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/Mapfix" + $ref: "#/components/schemas/Mapfixes" default: description: General Error content: @@ -508,9 +506,7 @@ paths: content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/Submission" + $ref: "#/components/schemas/Submissions" default: description: General Error content: @@ -1276,6 +1272,20 @@ components: StatusMessage: type: string maxLength: 256 + Mapfixes: + type: object + required: + - Total + - Mapfixes + properties: + Total: + type: integer + format: int64 + minimum: 0 + Mapfixes: + type: array + items: + $ref: "#/components/schemas/Mapfix" MapfixTriggerCreate: required: - AssetID @@ -1396,6 +1406,20 @@ components: StatusMessage: type: string maxLength: 256 + Submissions: + required: + - Total + - Submissions + type: object + properties: + Total: + type: integer + format: int64 + minimum: 0 + Submissions: + type: array + items: + $ref: "#/components/schemas/Submission" SubmissionTriggerCreate: required: - AssetID diff --git a/pkg/api/oas_client_gen.go b/pkg/api/oas_client_gen.go index 7a1b813..5130a84 100644 --- a/pkg/api/oas_client_gen.go +++ b/pkg/api/oas_client_gen.go @@ -214,7 +214,7 @@ type Invoker interface { // Get list of mapfixes. // // GET /mapfixes - ListMapfixes(ctx context.Context, params ListMapfixesParams) ([]Mapfix, error) + ListMapfixes(ctx context.Context, params ListMapfixesParams) (*Mapfixes, error) // ListMaps invokes listMaps operation. // // Get list of maps. @@ -238,7 +238,7 @@ type Invoker interface { // Get list of submissions. // // GET /submissions - ListSubmissions(ctx context.Context, params ListSubmissionsParams) ([]Submission, error) + ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error) // ReleaseSubmissions invokes releaseSubmissions operation. // // Release a set of uploaded maps. @@ -3838,12 +3838,12 @@ func (c *Client) sendGetSubmission(ctx context.Context, params GetSubmissionPara // Get list of mapfixes. // // GET /mapfixes -func (c *Client) ListMapfixes(ctx context.Context, params ListMapfixesParams) ([]Mapfix, error) { +func (c *Client) ListMapfixes(ctx context.Context, params ListMapfixesParams) (*Mapfixes, error) { res, err := c.sendListMapfixes(ctx, params) return res, err } -func (c *Client) sendListMapfixes(ctx context.Context, params ListMapfixesParams) (res []Mapfix, err error) { +func (c *Client) sendListMapfixes(ctx context.Context, params ListMapfixesParams) (res *Mapfixes, err error) { otelAttrs := []attribute.KeyValue{ otelogen.OperationID("listMapfixes"), semconv.HTTPRequestMethodKey.String("GET"), @@ -4526,12 +4526,12 @@ func (c *Client) sendListScripts(ctx context.Context, params ListScriptsParams) // Get list of submissions. // // GET /submissions -func (c *Client) ListSubmissions(ctx context.Context, params ListSubmissionsParams) ([]Submission, error) { +func (c *Client) ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error) { res, err := c.sendListSubmissions(ctx, params) return res, err } -func (c *Client) sendListSubmissions(ctx context.Context, params ListSubmissionsParams) (res []Submission, err error) { +func (c *Client) sendListSubmissions(ctx context.Context, params ListSubmissionsParams) (res *Submissions, err error) { otelAttrs := []attribute.KeyValue{ otelogen.OperationID("listSubmissions"), semconv.HTTPRequestMethodKey.String("GET"), diff --git a/pkg/api/oas_handlers_gen.go b/pkg/api/oas_handlers_gen.go index fe85bcf..887991e 100644 --- a/pkg/api/oas_handlers_gen.go +++ b/pkg/api/oas_handlers_gen.go @@ -5735,7 +5735,7 @@ func (s *Server) handleListMapfixesRequest(args [0]string, argsEscaped bool, w h return } - var response []Mapfix + var response *Mapfixes if m := s.cfg.Middleware; m != nil { mreq := middleware.Request{ Context: ctx, @@ -5775,7 +5775,7 @@ func (s *Server) handleListMapfixesRequest(args [0]string, argsEscaped bool, w h type ( Request = struct{} Params = ListMapfixesParams - Response = []Mapfix + Response = *Mapfixes ) response, err = middleware.HookMiddleware[ Request, @@ -6411,7 +6411,7 @@ func (s *Server) handleListSubmissionsRequest(args [0]string, argsEscaped bool, return } - var response []Submission + var response *Submissions if m := s.cfg.Middleware; m != nil { mreq := middleware.Request{ Context: ctx, @@ -6451,7 +6451,7 @@ func (s *Server) handleListSubmissionsRequest(args [0]string, argsEscaped bool, type ( Request = struct{} Params = ListSubmissionsParams - Response = []Submission + Response = *Submissions ) response, err = middleware.HookMiddleware[ Request, diff --git a/pkg/api/oas_json_gen.go b/pkg/api/oas_json_gen.go index 4e2c532..391642f 100644 --- a/pkg/api/oas_json_gen.go +++ b/pkg/api/oas_json_gen.go @@ -704,6 +704,129 @@ func (s *MapfixTriggerCreate) UnmarshalJSON(data []byte) error { return s.Decode(d) } +// Encode implements json.Marshaler. +func (s *Mapfixes) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *Mapfixes) encodeFields(e *jx.Encoder) { + { + e.FieldStart("Total") + e.Int64(s.Total) + } + { + e.FieldStart("Mapfixes") + e.ArrStart() + for _, elem := range s.Mapfixes { + elem.Encode(e) + } + e.ArrEnd() + } +} + +var jsonFieldsNameOfMapfixes = [2]string{ + 0: "Total", + 1: "Mapfixes", +} + +// Decode decodes Mapfixes from json. +func (s *Mapfixes) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode Mapfixes to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "Total": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Int64() + s.Total = int64(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"Total\"") + } + case "Mapfixes": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + s.Mapfixes = make([]Mapfix, 0) + if err := d.Arr(func(d *jx.Decoder) error { + var elem Mapfix + if err := elem.Decode(d); err != nil { + return err + } + s.Mapfixes = append(s.Mapfixes, elem) + return nil + }); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"Mapfixes\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode Mapfixes") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfMapfixes) { + name = jsonFieldsNameOfMapfixes[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *Mapfixes) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *Mapfixes) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode implements json.Marshaler. func (s *Operation) Encode(e *jx.Encoder) { e.ObjStart() @@ -2834,6 +2957,129 @@ func (s *SubmissionTriggerCreate) UnmarshalJSON(data []byte) error { return s.Decode(d) } +// Encode implements json.Marshaler. +func (s *Submissions) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *Submissions) encodeFields(e *jx.Encoder) { + { + e.FieldStart("Total") + e.Int64(s.Total) + } + { + e.FieldStart("Submissions") + e.ArrStart() + for _, elem := range s.Submissions { + elem.Encode(e) + } + e.ArrEnd() + } +} + +var jsonFieldsNameOfSubmissions = [2]string{ + 0: "Total", + 1: "Submissions", +} + +// Decode decodes Submissions from json. +func (s *Submissions) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode Submissions to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "Total": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + v, err := d.Int64() + s.Total = int64(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"Total\"") + } + case "Submissions": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + s.Submissions = make([]Submission, 0) + if err := d.Arr(func(d *jx.Decoder) error { + var elem Submission + if err := elem.Decode(d); err != nil { + return err + } + s.Submissions = append(s.Submissions, elem) + return nil + }); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"Submissions\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode Submissions") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfSubmissions) { + name = jsonFieldsNameOfSubmissions[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *Submissions) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *Submissions) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode implements json.Marshaler. func (s *User) Encode(e *jx.Encoder) { e.ObjStart() diff --git a/pkg/api/oas_response_decoders_gen.go b/pkg/api/oas_response_decoders_gen.go index ee41c2a..b23ae6c 100644 --- a/pkg/api/oas_response_decoders_gen.go +++ b/pkg/api/oas_response_decoders_gen.go @@ -2225,7 +2225,7 @@ func decodeGetSubmissionResponse(resp *http.Response) (res *Submission, _ error) return res, errors.Wrap(defRes, "error") } -func decodeListMapfixesResponse(resp *http.Response) (res []Mapfix, _ error) { +func decodeListMapfixesResponse(resp *http.Response) (res *Mapfixes, _ error) { switch resp.StatusCode { case 200: // Code 200. @@ -2241,17 +2241,9 @@ func decodeListMapfixesResponse(resp *http.Response) (res []Mapfix, _ error) { } d := jx.DecodeBytes(buf) - var response []Mapfix + var response Mapfixes if err := func() error { - response = make([]Mapfix, 0) - if err := d.Arr(func(d *jx.Decoder) error { - var elem Mapfix - if err := elem.Decode(d); err != nil { - return err - } - response = append(response, elem) - return nil - }); err != nil { + if err := response.Decode(d); err != nil { return err } if err := d.Skip(); err != io.EOF { @@ -2268,31 +2260,14 @@ func decodeListMapfixesResponse(resp *http.Response) (res []Mapfix, _ error) { } // Validate response. if err := func() error { - if response == nil { - return errors.New("nil is invalid value") - } - var failures []validate.FieldError - for i, elem := range response { - if err := func() error { - if err := elem.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - failures = append(failures, validate.FieldError{ - Name: fmt.Sprintf("[%d]", i), - Error: err, - }) - } - } - if len(failures) > 0 { - return &validate.Error{Fields: failures} + if err := response.Validate(); err != nil { + return err } return nil }(); err != nil { return res, errors.Wrap(err, "validate") } - return response, nil + return &response, nil default: return res, validate.InvalidContentType(ct) } @@ -2729,7 +2704,7 @@ func decodeListScriptsResponse(resp *http.Response) (res []Script, _ error) { return res, errors.Wrap(defRes, "error") } -func decodeListSubmissionsResponse(resp *http.Response) (res []Submission, _ error) { +func decodeListSubmissionsResponse(resp *http.Response) (res *Submissions, _ error) { switch resp.StatusCode { case 200: // Code 200. @@ -2745,17 +2720,9 @@ func decodeListSubmissionsResponse(resp *http.Response) (res []Submission, _ err } d := jx.DecodeBytes(buf) - var response []Submission + var response Submissions if err := func() error { - response = make([]Submission, 0) - if err := d.Arr(func(d *jx.Decoder) error { - var elem Submission - if err := elem.Decode(d); err != nil { - return err - } - response = append(response, elem) - return nil - }); err != nil { + if err := response.Decode(d); err != nil { return err } if err := d.Skip(); err != io.EOF { @@ -2772,31 +2739,14 @@ func decodeListSubmissionsResponse(resp *http.Response) (res []Submission, _ err } // Validate response. if err := func() error { - if response == nil { - return errors.New("nil is invalid value") - } - var failures []validate.FieldError - for i, elem := range response { - if err := func() error { - if err := elem.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - failures = append(failures, validate.FieldError{ - Name: fmt.Sprintf("[%d]", i), - Error: err, - }) - } - } - if len(failures) > 0 { - return &validate.Error{Fields: failures} + if err := response.Validate(); err != nil { + return err } return nil }(); err != nil { return res, errors.Wrap(err, "validate") } - return response, nil + return &response, nil default: return res, validate.InvalidContentType(ct) } diff --git a/pkg/api/oas_response_encoders_gen.go b/pkg/api/oas_response_encoders_gen.go index 24ef6b4..362dfc5 100644 --- a/pkg/api/oas_response_encoders_gen.go +++ b/pkg/api/oas_response_encoders_gen.go @@ -293,17 +293,13 @@ func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, sp return nil } -func encodeListMapfixesResponse(response []Mapfix, w http.ResponseWriter, span trace.Span) error { +func encodeListMapfixesResponse(response *Mapfixes, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) span.SetStatus(codes.Ok, http.StatusText(200)) e := new(jx.Encoder) - e.ArrStart() - for _, elem := range response { - elem.Encode(e) - } - e.ArrEnd() + response.Encode(e) if _, err := e.WriteTo(w); err != nil { return errors.Wrap(err, "write") } @@ -365,17 +361,13 @@ func encodeListScriptsResponse(response []Script, w http.ResponseWriter, span tr return nil } -func encodeListSubmissionsResponse(response []Submission, w http.ResponseWriter, span trace.Span) error { +func encodeListSubmissionsResponse(response *Submissions, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) span.SetStatus(codes.Ok, http.StatusText(200)) e := new(jx.Encoder) - e.ArrStart() - for _, elem := range response { - elem.Encode(e) - } - e.ArrEnd() + response.Encode(e) if _, err := e.WriteTo(w); err != nil { return errors.Wrap(err, "write") } diff --git a/pkg/api/oas_schemas_gen.go b/pkg/api/oas_schemas_gen.go index 8e241af..80ee714 100644 --- a/pkg/api/oas_schemas_gen.go +++ b/pkg/api/oas_schemas_gen.go @@ -370,6 +370,32 @@ func (s *MapfixTriggerCreate) SetTargetAssetID(val int64) { s.TargetAssetID = val } +// Ref: #/components/schemas/Mapfixes +type Mapfixes struct { + Total int64 `json:"Total"` + Mapfixes []Mapfix `json:"Mapfixes"` +} + +// GetTotal returns the value of Total. +func (s *Mapfixes) GetTotal() int64 { + return s.Total +} + +// GetMapfixes returns the value of Mapfixes. +func (s *Mapfixes) GetMapfixes() []Mapfix { + return s.Mapfixes +} + +// SetTotal sets the value of Total. +func (s *Mapfixes) SetTotal(val int64) { + s.Total = val +} + +// SetMapfixes sets the value of Mapfixes. +func (s *Mapfixes) SetMapfixes(val []Mapfix) { + s.Mapfixes = val +} + // Ref: #/components/schemas/Operation type Operation struct { OperationID int32 `json:"OperationID"` @@ -1167,6 +1193,32 @@ func (s *SubmissionTriggerCreate) SetAssetID(val int64) { s.AssetID = val } +// Ref: #/components/schemas/Submissions +type Submissions struct { + Total int64 `json:"Total"` + Submissions []Submission `json:"Submissions"` +} + +// GetTotal returns the value of Total. +func (s *Submissions) GetTotal() int64 { + return s.Total +} + +// GetSubmissions returns the value of Submissions. +func (s *Submissions) GetSubmissions() []Submission { + return s.Submissions +} + +// SetTotal sets the value of Total. +func (s *Submissions) SetTotal(val int64) { + s.Total = val +} + +// SetSubmissions sets the value of Submissions. +func (s *Submissions) SetSubmissions(val []Submission) { + s.Submissions = val +} + // UpdateMapfixModelNoContent is response for UpdateMapfixModel operation. type UpdateMapfixModelNoContent struct{} diff --git a/pkg/api/oas_server_gen.go b/pkg/api/oas_server_gen.go index 8a0473b..99b8e44 100644 --- a/pkg/api/oas_server_gen.go +++ b/pkg/api/oas_server_gen.go @@ -193,7 +193,7 @@ type Handler interface { // Get list of mapfixes. // // GET /mapfixes - ListMapfixes(ctx context.Context, params ListMapfixesParams) ([]Mapfix, error) + ListMapfixes(ctx context.Context, params ListMapfixesParams) (*Mapfixes, error) // ListMaps implements listMaps operation. // // Get list of maps. @@ -217,7 +217,7 @@ type Handler interface { // Get list of submissions. // // GET /submissions - ListSubmissions(ctx context.Context, params ListSubmissionsParams) ([]Submission, error) + ListSubmissions(ctx context.Context, params ListSubmissionsParams) (*Submissions, error) // ReleaseSubmissions implements releaseSubmissions operation. // // Release a set of uploaded maps. diff --git a/pkg/api/oas_unimplemented_gen.go b/pkg/api/oas_unimplemented_gen.go index 6bc9775..56392ad 100644 --- a/pkg/api/oas_unimplemented_gen.go +++ b/pkg/api/oas_unimplemented_gen.go @@ -288,7 +288,7 @@ func (UnimplementedHandler) GetSubmission(ctx context.Context, params GetSubmiss // Get list of mapfixes. // // GET /mapfixes -func (UnimplementedHandler) ListMapfixes(ctx context.Context, params ListMapfixesParams) (r []Mapfix, _ error) { +func (UnimplementedHandler) ListMapfixes(ctx context.Context, params ListMapfixesParams) (r *Mapfixes, _ error) { return r, ht.ErrNotImplemented } @@ -324,7 +324,7 @@ func (UnimplementedHandler) ListScripts(ctx context.Context, params ListScriptsP // Get list of submissions. // // GET /submissions -func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubmissionsParams) (r []Submission, _ error) { +func (UnimplementedHandler) ListSubmissions(ctx context.Context, params ListSubmissionsParams) (r *Submissions, _ error) { return r, ht.ErrNotImplemented } diff --git a/pkg/api/oas_validators_gen.go b/pkg/api/oas_validators_gen.go index e12bac3..1443d54 100644 --- a/pkg/api/oas_validators_gen.go +++ b/pkg/api/oas_validators_gen.go @@ -3,6 +3,8 @@ package api import ( + "fmt" + "github.com/go-faster/errors" "github.com/ogen-go/ogen/validate" @@ -474,6 +476,66 @@ func (s *MapfixTriggerCreate) Validate() error { return nil } +func (s *Mapfixes) Validate() error { + if s == nil { + return validate.ErrNilPointer + } + + var failures []validate.FieldError + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(s.Total)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "Total", + Error: err, + }) + } + if err := func() error { + if s.Mapfixes == nil { + return errors.New("nil is invalid value") + } + var failures []validate.FieldError + for i, elem := range s.Mapfixes { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "Mapfixes", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + func (s *Operation) Validate() error { if s == nil { return validate.ErrNilPointer @@ -1746,6 +1808,66 @@ func (s *SubmissionTriggerCreate) Validate() error { return nil } +func (s *Submissions) Validate() error { + if s == nil { + return validate.ErrNilPointer + } + + var failures []validate.FieldError + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(s.Total)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "Total", + Error: err, + }) + } + if err := func() error { + if s.Submissions == nil { + return errors.New("nil is invalid value") + } + var failures []validate.FieldError + for i, elem := range s.Submissions { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "Submissions", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + func (s *User) Validate() error { if s == nil { return validate.ErrNilPointer diff --git a/pkg/datastore/datastore.go b/pkg/datastore/datastore.go index 4df0c9f..3bb704e 100644 --- a/pkg/datastore/datastore.go +++ b/pkg/datastore/datastore.go @@ -40,6 +40,7 @@ type Mapfixes interface { IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.MapfixStatus, values OptionalMap) (model.Mapfix, error) Delete(ctx context.Context, id int64) error List(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) ([]model.Mapfix, error) + ListWithTotal(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) (int64, []model.Mapfix, error) } type Operations interface { @@ -59,6 +60,7 @@ type Submissions interface { IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) (model.Submission, error) Delete(ctx context.Context, id int64) error List(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) ([]model.Submission, error) + ListWithTotal(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) (int64, []model.Submission, error) } type Scripts interface { diff --git a/pkg/datastore/gormstore/mapfixes.go b/pkg/datastore/gormstore/mapfixes.go index d80067e..50f4a05 100644 --- a/pkg/datastore/gormstore/mapfixes.go +++ b/pkg/datastore/gormstore/mapfixes.go @@ -130,3 +130,19 @@ func (env *Mapfixes) List(ctx context.Context, filters datastore.OptionalMap, pa return maps, nil } + +func (env *Mapfixes) ListWithTotal(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) (int64, []model.Mapfix, error) { + // grab page items + maps, err := env.List(ctx, filters, page, sort) + if err != nil{ + return 0, nil, err + } + + // count total with filters + var total int64 + if err := env.db.Model(&model.Mapfix{}).Where(filters.Map()).Count(&total).Error; err != nil { + return 0, nil, err + } + + return total, maps, nil +} diff --git a/pkg/datastore/gormstore/submissions.go b/pkg/datastore/gormstore/submissions.go index dc384c6..5791819 100644 --- a/pkg/datastore/gormstore/submissions.go +++ b/pkg/datastore/gormstore/submissions.go @@ -130,3 +130,19 @@ func (env *Submissions) List(ctx context.Context, filters datastore.OptionalMap, return maps, nil } + +func (env *Submissions) ListWithTotal(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) (int64, []model.Submission, error) { + // grab page items + maps, err := env.List(ctx, filters, page, sort) + if err != nil{ + return 0, nil, err + } + + // count total with filters + var total int64 + if err := env.db.Model(&model.Submission{}).Where(filters.Map()).Count(&total).Error; err != nil { + return 0, nil, err + } + + return total, maps, nil +} diff --git a/pkg/service/mapfixes.go b/pkg/service/mapfixes.go index d81f7fe..3c102b9 100644 --- a/pkg/service/mapfixes.go +++ b/pkg/service/mapfixes.go @@ -160,7 +160,7 @@ func (svc *Service) GetMapfix(ctx context.Context, params api.GetMapfixParams) ( // Get list of mapfixes. // // GET /mapfixes -func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesParams) ([]api.Mapfix, error) { +func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesParams) (*api.Mapfixes, error) { filter := datastore.Optional() if params.DisplayName.IsSet(){ @@ -175,7 +175,7 @@ func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesPar sort := datastore.ListSort(params.Sort.Or(int32(datastore.ListSortDisabled))) - items, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{ + total, items, err := svc.DB.Mapfixes().ListWithTotal(ctx, filter, model.Page{ Number: params.Page, Size: params.Limit, },sort) @@ -183,9 +183,10 @@ func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesPar return nil, err } - var resp []api.Mapfix + var resp api.Mapfixes + resp.Total=total for _, item := range items { - resp = append(resp, api.Mapfix{ + resp.Mapfixes = append(resp.Mapfixes, api.Mapfix{ ID: item.ID, DisplayName: item.DisplayName, Creator: item.Creator, @@ -201,7 +202,7 @@ func (svc *Service) ListMapfixes(ctx context.Context, params api.ListMapfixesPar }) } - return resp, nil + return &resp, nil } // PatchMapfixCompleted implements patchMapfixCompleted operation. diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index cca0206..4b2bdc0 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -149,7 +149,7 @@ func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionP // Get list of submissions. // // GET /submissions -func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissionsParams) ([]api.Submission, error) { +func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissionsParams) (*api.Submissions, error) { filter := datastore.Optional() if params.DisplayName.IsSet(){ @@ -164,7 +164,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi sort := datastore.ListSort(params.Sort.Or(int32(datastore.ListSortDisabled))) - items, err := svc.DB.Submissions().List(ctx, filter, model.Page{ + total, items, err := svc.DB.Submissions().ListWithTotal(ctx, filter, model.Page{ Number: params.Page, Size: params.Limit, },sort) @@ -172,9 +172,10 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi return nil, err } - var resp []api.Submission + var resp api.Submissions + resp.Total=total for _, item := range items { - resp = append(resp, api.Submission{ + resp.Submissions = append(resp.Submissions, api.Submission{ ID: item.ID, DisplayName: item.DisplayName, Creator: item.Creator, @@ -190,7 +191,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi }) } - return resp, nil + return &resp, nil } // PatchSubmissionCompleted implements patchSubmissionCompleted operation. diff --git a/web/src/app/mapfixes/page.tsx b/web/src/app/mapfixes/page.tsx index 37f232b..33057ff 100644 --- a/web/src/app/mapfixes/page.tsx +++ b/web/src/app/mapfixes/page.tsx @@ -1,41 +1,42 @@ 'use client' import React, { useState, useEffect } from "react"; -import { MapfixInfo } from "../ts/Mapfix"; +import { MapfixList } from "../ts/Mapfix"; import { MapfixCard } from "../_components/mapCard"; import Webpage from "@/app/_components/webpage"; // TODO: MAKE MAPFIX & SUBMISSIONS USE THE SAME COMPONENTS :angry: (currently too lazy) import "./(styles)/page.scss"; +import { ListSortConstants } from "../ts/Sort"; export default function MapfixInfoPage() { - const [mapfixes, setMapfixes] = useState<MapfixInfo[]>([]) - const [currentPage, setCurrentPage] = useState(0); + const [mapfixes, setMapfixes] = useState<MapfixList>({Total:0,Mapfixes:[]}) + const [currentPage, setCurrentPage] = useState(1); const cardsPerPage = 24; // built to fit on a 1920x1080 monitor - const totalPages = Math.ceil(mapfixes.length / cardsPerPage); + const totalPages = Math.ceil(mapfixes.Total / cardsPerPage); - const currentCards = mapfixes.slice( - currentPage * cardsPerPage, - (currentPage + 1) * cardsPerPage + const currentCards = mapfixes.Mapfixes.slice( + (currentPage - 1) * cardsPerPage, + currentPage * cardsPerPage ); const nextPage = () => { - if (currentPage < totalPages - 1) { + if (currentPage < totalPages) { setCurrentPage(currentPage + 1); } }; const prevPage = () => { - if (currentPage > 0) { + if (currentPage > 1) { setCurrentPage(currentPage - 1); } }; useEffect(() => { async function fetchMapfixes() { - const res = await fetch('/api/mapfixes?Page=1&Limit=100') + const res = await fetch(`/api/mapfixes?Page=${currentPage}&Limit=${cardsPerPage}&Sort=${ListSortConstants.ListSortDateDescending}`) if (res.ok) { setMapfixes(await res.json()) } @@ -44,7 +45,7 @@ export default function MapfixInfoPage() { setTimeout(() => { fetchMapfixes() }, 50); - }, []) + }, [currentPage]) if (!mapfixes) { return <Webpage> @@ -54,7 +55,7 @@ export default function MapfixInfoPage() { </Webpage> } - if (mapfixes && mapfixes.length == 0) { + if (mapfixes && mapfixes.Total == 0) { return <Webpage> <main> Mapfixes list is empty. @@ -88,11 +89,11 @@ export default function MapfixInfoPage() { ))} </div> <div className="pagination"> - <button onClick={prevPage} disabled={currentPage === 0}><</button> + <button onClick={prevPage} disabled={currentPage === 1}><</button> <span> - Page {currentPage + 1} of {totalPages} + Page {currentPage} of {totalPages} </span> - <button onClick={nextPage} disabled={currentPage === totalPages - 1}>></button> + <button onClick={nextPage} disabled={currentPage === totalPages}>></button> </div> <div className="grid"> {currentCards.map((mapfix) => ( diff --git a/web/src/app/submissions/page.tsx b/web/src/app/submissions/page.tsx index 05b877c..e3bf37c 100644 --- a/web/src/app/submissions/page.tsx +++ b/web/src/app/submissions/page.tsx @@ -1,39 +1,40 @@ 'use client' import React, { useState, useEffect } from "react"; -import { SubmissionInfo } from "../ts/Submission"; +import { SubmissionList } from "../ts/Submission"; import { SubmissionCard } from "../_components/mapCard"; import Webpage from "@/app/_components/webpage"; import "./(styles)/page.scss"; +import { ListSortConstants } from "../ts/Sort"; export default function SubmissionInfoPage() { - const [submissions, setSubmissions] = useState<SubmissionInfo[]>([]) - const [currentPage, setCurrentPage] = useState(0); + const [submissions, setSubmissions] = useState<SubmissionList>({Total:0,Submissions:[]}) + const [currentPage, setCurrentPage] = useState(1); const cardsPerPage = 24; // built to fit on a 1920x1080 monitor - const totalPages = Math.ceil(submissions.length / cardsPerPage); + const totalPages = Math.ceil(submissions.Total / cardsPerPage); - const currentCards = submissions.slice( - currentPage * cardsPerPage, - (currentPage + 1) * cardsPerPage + const currentCards = submissions.Submissions.slice( + (currentPage - 1) * cardsPerPage, + currentPage * cardsPerPage ); const nextPage = () => { - if (currentPage < totalPages - 1) { + if (currentPage < totalPages) { setCurrentPage(currentPage + 1); } }; const prevPage = () => { - if (currentPage > 0) { + if (currentPage > 1) { setCurrentPage(currentPage - 1); } }; useEffect(() => { async function fetchSubmissions() { - const res = await fetch('/api/submissions?Page=1&Limit=100') + const res = await fetch(`/api/submissions?Page=${currentPage}&Limit=${cardsPerPage}&Sort=${ListSortConstants.ListSortDateDescending}`) if (res.ok) { setSubmissions(await res.json()) } @@ -42,7 +43,7 @@ export default function SubmissionInfoPage() { setTimeout(() => { fetchSubmissions() }, 50); - }, []) + }, [currentPage]) if (!submissions) { return <Webpage> @@ -52,7 +53,7 @@ export default function SubmissionInfoPage() { </Webpage> } - if (submissions && submissions.length == 0) { + if (submissions && submissions.Total == 0) { return <Webpage> <main> Submissions list is empty. @@ -86,11 +87,11 @@ export default function SubmissionInfoPage() { ))} </div> <div className="pagination"> - <button onClick={prevPage} disabled={currentPage === 0}><</button> + <button onClick={prevPage} disabled={currentPage === 1}><</button> <span> - Page {currentPage + 1} of {totalPages} + Page {currentPage} of {totalPages} </span> - <button onClick={nextPage} disabled={currentPage === totalPages - 1}>></button> + <button onClick={nextPage} disabled={currentPage === totalPages}>></button> </div> <div className="grid"> {currentCards.map((submission) => ( diff --git a/web/src/app/ts/Mapfix.ts b/web/src/app/ts/Mapfix.ts index b761fb1..e9727d8 100644 --- a/web/src/app/ts/Mapfix.ts +++ b/web/src/app/ts/Mapfix.ts @@ -28,6 +28,11 @@ interface MapfixInfo { readonly StatusMessage: string, } +interface MapfixList { + readonly Total: number, + readonly Mapfixes: MapfixInfo[], +} + function MapfixStatusToString(mapfix_status: MapfixStatus): string { switch (mapfix_status) { case MapfixStatus.Rejected: @@ -56,5 +61,6 @@ function MapfixStatusToString(mapfix_status: MapfixStatus): string { export { MapfixStatus, MapfixStatusToString, - type MapfixInfo + type MapfixInfo, + type MapfixList, } diff --git a/web/src/app/ts/Sort.ts b/web/src/app/ts/Sort.ts new file mode 100644 index 0000000..2df66e6 --- /dev/null +++ b/web/src/app/ts/Sort.ts @@ -0,0 +1,15 @@ +type ListSort = number; + +// Constants +const ListSortConstants = { + ListSortDisabled: 0, + ListSortDisplayNameAscending: 1, + ListSortDisplayNameDescending: 2, + ListSortDateAscending: 3, + ListSortDateDescending: 4, +}; + +export { + type ListSort, + ListSortConstants, +}; diff --git a/web/src/app/ts/Submission.ts b/web/src/app/ts/Submission.ts index cbae508..a2003f1 100644 --- a/web/src/app/ts/Submission.ts +++ b/web/src/app/ts/Submission.ts @@ -28,6 +28,11 @@ interface SubmissionInfo { readonly StatusMessage: string, } +interface SubmissionList { + readonly Total: number, + readonly Submissions: SubmissionInfo[], +} + function SubmissionStatusToString(submission_status: SubmissionStatus): string { switch (submission_status) { case SubmissionStatus.Released: @@ -58,5 +63,6 @@ function SubmissionStatusToString(submission_status: SubmissionStatus): string { export { SubmissionStatus, SubmissionStatusToString, - type SubmissionInfo + type SubmissionInfo, + type SubmissionList, }