diff --git a/crm/docs/README.md b/crm/docs/README.md index 16dd1c9c4..a75abed87 100644 --- a/crm/docs/README.md +++ b/crm/docs/README.md @@ -79,6 +79,30 @@ CRM module definitions | --------- | ---- | ------ | ----------- | ------- | --------- | | moduleID | uint64 | PATH | Module ID | N/A | YES | +## Analyze data for chart + +#### Method + +| URI | Protocol | Method | Authentication | +| --- | -------- | ------ | -------------- | +| `/module/{moduleID}/chart` | HTTP/S | GET | | + +#### Request parameters + +| Parameter | Type | Method | Description | Default | Required? | +| --------- | ---- | ------ | ----------- | ------- | --------- | +| name | string | GET | The chart name | N/A | YES | +| description | string | GET | The chart description | N/A | YES | +| xAxis | string | GET | X axis value | N/A | YES | +| xMin | string | GET | Min value | N/A | NO | +| xMax | string | GET | Max value | N/A | NO | +| yAxis | string | GET | Y axis value | N/A | YES | +| groupBy | string | GET | Group by field | N/A | YES | +| sum | string | GET | Sum values field | N/A | YES | +| count | string | GET | Count values field | N/A | YES | +| kind | string | GET | Chart kind (line, spline, step, area, area-spline, area-step, bar, scatter, pie, donut, gauge) | N/A | YES | +| moduleID | uint64 | PATH | Module ID | N/A | YES | + ## Edit module #### Method diff --git a/crm/docs/src/spec.json b/crm/docs/src/spec.json index 76f0053cc..afb764845 100644 --- a/crm/docs/src/spec.json +++ b/crm/docs/src/spec.json @@ -369,6 +369,84 @@ ] } }, + { + "name": "chart", + "method": "GET", + "title": "Analyze data for chart", + "path": "/{moduleID}/chart", + "parameters": { + "path": [ + { + "type": "uint64", + "name": "moduleID", + "required": true, + "title": "Module ID" + } + ], + "get": [ + { + "type": "string", + "name": "name", + "required": true, + "title": "The chart name" + }, + { + "type": "string", + "name": "description", + "required": true, + "title": "The chart description" + }, + { + "type": "string", + "name": "xAxis", + "required": true, + "title": "X axis value" + }, + { + "type": "string", + "name": "xMin", + "required": false, + "title": "Min value" + }, + { + "type": "string", + "name": "xMax", + "required": false, + "title": "Max value" + }, + { + "type": "string", + "name": "yAxis", + "required": true, + "title": "Y axis value" + }, + { + "type": "string", + "name": "groupBy", + "required": true, + "title": "Group by field" + }, + { + "type": "string", + "name": "sum", + "required": true, + "title": "Sum values field" + }, + { + "type": "string", + "name": "count", + "required": true, + "title": "Count values field" + }, + { + "type": "string", + "name": "kind", + "required": true, + "title": "Chart kind (line, spline, step, area, area-spline, area-step, bar, scatter, pie, donut, gauge)" + } + ] + } + }, { "name": "edit", "method": "POST", diff --git a/crm/docs/src/spec/module.json b/crm/docs/src/spec/module.json index c5ba2fd0c..0f27237fa 100644 --- a/crm/docs/src/spec/module.json +++ b/crm/docs/src/spec/module.json @@ -132,6 +132,84 @@ ] } }, + { + "Name": "chart", + "Method": "GET", + "Title": "Analyze data for chart", + "Path": "/{moduleID}/chart", + "Parameters": { + "get": [ + { + "name": "name", + "required": true, + "title": "The chart name", + "type": "string" + }, + { + "name": "description", + "required": true, + "title": "The chart description", + "type": "string" + }, + { + "name": "xAxis", + "required": true, + "title": "X axis value", + "type": "string" + }, + { + "name": "xMin", + "required": false, + "title": "Min value", + "type": "string" + }, + { + "name": "xMax", + "required": false, + "title": "Max value", + "type": "string" + }, + { + "name": "yAxis", + "required": true, + "title": "Y axis value", + "type": "string" + }, + { + "name": "groupBy", + "required": true, + "title": "Group by field", + "type": "string" + }, + { + "name": "sum", + "required": true, + "title": "Sum values field", + "type": "string" + }, + { + "name": "count", + "required": true, + "title": "Count values field", + "type": "string" + }, + { + "name": "kind", + "required": true, + "title": "Chart kind (line, spline, step, area, area-spline, area-step, bar, scatter, pie, donut, gauge)", + "type": "string" + } + ], + "path": [ + { + "name": "moduleID", + "required": true, + "title": "Module ID", + "type": "uint64" + } + ] + } + }, { "Name": "edit", "Method": "POST", diff --git a/crm/repository/chart.go b/crm/repository/chart.go new file mode 100644 index 000000000..0d3fe9ac3 --- /dev/null +++ b/crm/repository/chart.go @@ -0,0 +1,9 @@ +package repository + +import ( + "github.com/crusttech/crust/crm/rest/request" +) + +func (m *module) Chart(r *request.ModuleChart) (interface{}, error) { + return "not implemented yet", nil +} diff --git a/crm/repository/module.go b/crm/repository/module.go index 64676a988..475a91ef8 100644 --- a/crm/repository/module.go +++ b/crm/repository/module.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" + "github.com/crusttech/crust/crm/rest/request" "github.com/crusttech/crust/crm/types" ) @@ -15,6 +16,8 @@ type ( ModuleRepository interface { With(ctx context.Context, db *factory.DB) ModuleRepository + Chart(r *request.ModuleChart) (interface{}, error) + FindByID(id uint64) (*types.Module, error) Find() ([]*types.Module, error) Create(mod *types.Module) (*types.Module, error) diff --git a/crm/rest/handlers/module.go b/crm/rest/handlers/module.go index 503a29632..c18d445ec 100644 --- a/crm/rest/handlers/module.go +++ b/crm/rest/handlers/module.go @@ -30,6 +30,7 @@ type ModuleAPI interface { List(context.Context, *request.ModuleList) (interface{}, error) Create(context.Context, *request.ModuleCreate) (interface{}, error) Read(context.Context, *request.ModuleRead) (interface{}, error) + Chart(context.Context, *request.ModuleChart) (interface{}, error) Edit(context.Context, *request.ModuleEdit) (interface{}, error) Delete(context.Context, *request.ModuleDelete) (interface{}, error) ContentList(context.Context, *request.ModuleContentList) (interface{}, error) @@ -44,6 +45,7 @@ type Module struct { List func(http.ResponseWriter, *http.Request) Create func(http.ResponseWriter, *http.Request) Read func(http.ResponseWriter, *http.Request) + Chart func(http.ResponseWriter, *http.Request) Edit func(http.ResponseWriter, *http.Request) Delete func(http.ResponseWriter, *http.Request) ContentList func(http.ResponseWriter, *http.Request) @@ -76,6 +78,13 @@ func NewModule(mh ModuleAPI) *Module { return mh.Read(r.Context(), params) }) }, + Chart: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewModuleChart() + resputil.JSON(w, params.Fill(r), func() (interface{}, error) { + return mh.Chart(r.Context(), params) + }) + }, Edit: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() params := request.NewModuleEdit() @@ -135,6 +144,7 @@ func (mh *Module) MountRoutes(r chi.Router, middlewares ...func(http.Handler) ht r.Get("/", mh.List) r.Post("/", mh.Create) r.Get("/{moduleID}", mh.Read) + r.Get("/{moduleID}/chart", mh.Chart) r.Post("/{moduleID}", mh.Edit) r.Delete("/{moduleID}", mh.Delete) r.Get("/{moduleID}/content", mh.ContentList) diff --git a/crm/rest/module.go b/crm/rest/module.go index e9888ebeb..83086985e 100644 --- a/crm/rest/module.go +++ b/crm/rest/module.go @@ -33,6 +33,10 @@ func (s *Module) Delete(ctx context.Context, r *request.ModuleDelete) (interface return resputil.OK(), s.module.With(ctx).DeleteByID(r.ModuleID) } +func (s *Module) Chart(ctx context.Context, r *request.ModuleChart) (interface{}, error) { + return s.module.With(ctx).Chart(r) +} + func (s *Module) Create(ctx context.Context, r *request.ModuleCreate) (interface{}, error) { item := &types.Module{ Name: r.Name, diff --git a/crm/rest/request/module.go b/crm/rest/request/module.go index 4c3658297..b7ed2ff20 100644 --- a/crm/rest/request/module.go +++ b/crm/rest/request/module.go @@ -172,6 +172,99 @@ func (m *ModuleRead) Fill(r *http.Request) (err error) { var _ RequestFiller = NewModuleRead() +// Module chart request parameters +type ModuleChart struct { + Name string + Description string + XAxis string + XMin string + XMax string + YAxis string + GroupBy string + Sum string + Count string + Kind string + ModuleID uint64 `json:",string"` +} + +func NewModuleChart() *ModuleChart { + return &ModuleChart{} +} + +func (m *ModuleChart) Fill(r *http.Request) (err error) { + if strings.ToLower(r.Header.Get("content-type")) == "application/json" { + err = json.NewDecoder(r.Body).Decode(m) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return errors.Wrap(err, "error parsing http request body") + } + } + + if err = r.ParseForm(); err != nil { + return err + } + + get := map[string]string{} + post := map[string]string{} + urlQuery := r.URL.Query() + for name, param := range urlQuery { + get[name] = string(param[0]) + } + postVars := r.Form + for name, param := range postVars { + post[name] = string(param[0]) + } + + if val, ok := get["name"]; ok { + + m.Name = val + } + if val, ok := get["description"]; ok { + + m.Description = val + } + if val, ok := get["xAxis"]; ok { + + m.XAxis = val + } + if val, ok := get["xMin"]; ok { + + m.XMin = val + } + if val, ok := get["xMax"]; ok { + + m.XMax = val + } + if val, ok := get["yAxis"]; ok { + + m.YAxis = val + } + if val, ok := get["groupBy"]; ok { + + m.GroupBy = val + } + if val, ok := get["sum"]; ok { + + m.Sum = val + } + if val, ok := get["count"]; ok { + + m.Count = val + } + if val, ok := get["kind"]; ok { + + m.Kind = val + } + m.ModuleID = parseUInt64(chi.URLParam(r, "moduleID")) + + return err +} + +var _ RequestFiller = NewModuleChart() + // Module edit request parameters type ModuleEdit struct { ModuleID uint64 `json:",string"` diff --git a/crm/service/module.go b/crm/service/module.go index 6dfa65a0e..57ce9ab84 100644 --- a/crm/service/module.go +++ b/crm/service/module.go @@ -6,6 +6,7 @@ import ( "github.com/titpetric/factory" "github.com/crusttech/crust/crm/repository" + "github.com/crusttech/crust/crm/rest/request" "github.com/crusttech/crust/crm/types" ) @@ -19,6 +20,8 @@ type ( ModuleService interface { With(ctx context.Context) ModuleService + Chart(r *request.ModuleChart) (interface{}, error) + FindByID(moduleID uint64) (*types.Module, error) Find() ([]*types.Module, error) @@ -49,6 +52,10 @@ func (s *module) Find() ([]*types.Module, error) { return s.repository.Find() } +func (s *module) Chart(r *request.ModuleChart) (interface{}, error) { + return s.repository.Chart(r) +} + func (s *module) Create(mod *types.Module) (*types.Module, error) { return s.repository.Create(mod) }