From d98d8be69a64acb7396c0a8cb425f6b502f3a152 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 14:43:20 +0100 Subject: [PATCH 1/8] add(crm): add options field as json --- crm/types/types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crm/types/types.go b/crm/types/types.go index 5a3e6f588..55c8a489d 100644 --- a/crm/types/types.go +++ b/crm/types/types.go @@ -74,6 +74,8 @@ type ( Default string `json:"defaultValue,omitempty" db:"default_value"` MaxLength int `json:"maxLength" db:"max_length"` + Options types.JSONText `json:"options" db:"json"` + Private bool `json:"isPrivate" db:"is_private"` Required bool `json:"isRequired" db:"is_required"` Visible bool `json:"isVisible" db:"is_visible"` From 43554592e4379427db283a72d43ad70225341f68 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 15:26:51 +0100 Subject: [PATCH 2/8] upd(codegen): enable imports with requests --- api/crm/spec.json | 28 ++++++++++++--------- api/crm/spec/module.json | 16 ++++++------ api/crm/spec/page.json | 12 ++++++--- api/sam/spec.json | 7 ++++++ api/sam/spec/permissions.json | 8 +++++- api/system/spec.json | 6 ++--- api/system/spec/user.json | 6 ++--- codegen/codegen.php | 20 ++++++++++++++- codegen/crm/rest/handlers/index.php | 9 +------ codegen/crm/rest/index.php | 9 +------ codegen/crm/rest/request/index.php | 9 +------ codegen/crm/types/index.php | 8 +----- codegen/sam/rest/handlers/index.php | 9 +------ codegen/sam/rest/index.php | 9 +------ codegen/sam/rest/request/index.php | 9 +------ codegen/system/rest/handlers/index.php | 9 +------ codegen/system/rest/index.php | 9 +------ codegen/system/rest/request/index.php | 9 +------ codegen/templates/http_request_inline.tpl | 30 +++++++++++------------ codegen/templates/http_structs.tpl | 3 +-- crm/rest/request/field.go | 9 +++---- crm/rest/request/module.go | 27 ++++++++++---------- crm/rest/request/page.go | 19 +++++++------- crm/rest/request/util.go | 2 +- docs/crm/README.md | 12 ++++----- docs/system/README.md | 4 +-- sam/rest/request/attachment.go | 9 +++---- sam/rest/request/channel.go | 9 +++---- sam/rest/request/message.go | 9 +++---- sam/rest/request/permissions.go | 11 ++++----- sam/rest/request/search.go | 9 +++---- sam/types/channel.perms.go | 2 +- sam/types/organisation.perms.go | 2 +- sam/types/team.perms.go | 2 +- system/rest/request/auth.go | 9 +++---- system/rest/request/organisation.go | 9 +++---- system/rest/request/team.go | 9 +++---- system/rest/request/user.go | 19 +++++++------- system/rest/request/util.go | 2 +- 39 files changed, 172 insertions(+), 227 deletions(-) diff --git a/api/crm/spec.json b/api/crm/spec.json index edb805577..9e646eb0d 100644 --- a/api/crm/spec.json +++ b/api/crm/spec.json @@ -61,7 +61,13 @@ "entrypoint": "page", "path": "/page", "authentication": [], - "struct": [], + "struct": [ + { + "imports": [ + "sqlxTypes github.com/jmoiron/sqlx/types" + ] + } + ], "apis": [ { "name": "list", @@ -117,7 +123,7 @@ "title": "Visible in navigation" }, { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "blocks", "required": true, "title": "Blocks JSON" @@ -194,7 +200,7 @@ "title": "Visible in navigation" }, { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "blocks", "required": true, "title": "Blocks JSON" @@ -255,7 +261,7 @@ { "name": "Module", "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ], "fields": [ { @@ -268,7 +274,7 @@ }, { "name": "Fields", - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "json": "fields", "db": "json" } @@ -302,7 +308,7 @@ { "name": "Content", "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ], "fields": [ { @@ -315,7 +321,7 @@ }, { "name": "Fields", - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "db": "json" } ] @@ -352,7 +358,7 @@ "title": "Module Name" }, { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "fields", "required": true, "title": "Fields JSON" @@ -476,7 +482,7 @@ "title": "Module Name" }, { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "fields", "required": true, "title": "Fields JSON" @@ -552,7 +558,7 @@ ], "post": [ { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "fields", "required": true, "title": "Content JSON" @@ -604,7 +610,7 @@ ], "post": [ { - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "name": "fields", "required": true, "title": "Content JSON" diff --git a/api/crm/spec/module.json b/api/crm/spec/module.json index 0f27237fa..3945210f7 100644 --- a/api/crm/spec/module.json +++ b/api/crm/spec/module.json @@ -18,11 +18,11 @@ "db": "json", "json": "fields", "name": "Fields", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ], "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ], "name": "Module" }, @@ -64,11 +64,11 @@ { "db": "json", "name": "Fields", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ], "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ], "name": "Content" } @@ -111,7 +111,7 @@ "name": "fields", "required": true, "title": "Fields JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } @@ -235,7 +235,7 @@ "name": "fields", "required": true, "title": "Fields JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } @@ -311,7 +311,7 @@ "name": "fields", "required": true, "title": "Content JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } @@ -363,7 +363,7 @@ "name": "fields", "required": true, "title": "Content JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } diff --git a/api/crm/spec/page.json b/api/crm/spec/page.json index 2af3ecb5c..bbc542670 100644 --- a/api/crm/spec/page.json +++ b/api/crm/spec/page.json @@ -3,7 +3,13 @@ "Description": "CRM module pages", "Package": "crm", "Interface": "Page", - "Struct": [], + "Struct": [ + { + "imports": [ + "sqlxTypes github.com/jmoiron/sqlx/types" + ] + } + ], "Parameters": null, "Protocol": "", "Authentication": [], @@ -66,7 +72,7 @@ "name": "blocks", "required": true, "title": "Blocks JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } @@ -143,7 +149,7 @@ "name": "blocks", "required": true, "title": "Blocks JSON", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" } ] } diff --git a/api/sam/spec.json b/api/sam/spec.json index 8cd604b4c..b972b22d4 100644 --- a/api/sam/spec.json +++ b/api/sam/spec.json @@ -644,6 +644,13 @@ "Client ID", "Session ID" ], + "struct": [ + { + "imports": [ + "github.com/crusttech/crust/internal/rbac" + ] + } + ], "apis": [ { "name": "list", diff --git a/api/sam/spec/permissions.json b/api/sam/spec/permissions.json index 6f3a42cca..2b5225f9b 100644 --- a/api/sam/spec/permissions.json +++ b/api/sam/spec/permissions.json @@ -2,7 +2,13 @@ "Title": "Permissions", "Package": "sam", "Interface": "Permissions", - "Struct": null, + "Struct": [ + { + "imports": [ + "github.com/crusttech/crust/internal/rbac" + ] + } + ], "Parameters": {}, "Protocol": "", "Authentication": [ diff --git a/api/system/spec.json b/api/system/spec.json index b3b220ca0..f9454df5d 100644 --- a/api/system/spec.json +++ b/api/system/spec.json @@ -398,7 +398,7 @@ "struct": [ { "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ] } ], @@ -464,7 +464,7 @@ }, { "name": "meta", - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "required": false, "title": "Meta data" }, @@ -536,7 +536,7 @@ }, { "name": "meta", - "type": "types.JSONText", + "type": "sqlxTypes.JSONText", "required": false, "title": "Meta data" }, diff --git a/api/system/spec/user.json b/api/system/spec/user.json index 865f0a8a4..f0470cbb4 100644 --- a/api/system/spec/user.json +++ b/api/system/spec/user.json @@ -5,7 +5,7 @@ "Struct": [ { "imports": [ - "github.com/jmoiron/sqlx/types" + "sqlxTypes github.com/jmoiron/sqlx/types" ] } ], @@ -80,7 +80,7 @@ "name": "meta", "required": false, "title": "Meta data", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" }, { "name": "satosaID", @@ -152,7 +152,7 @@ "name": "meta", "required": false, "title": "Meta data", - "type": "types.JSONText" + "type": "sqlxTypes.JSONText" }, { "name": "satosaID", diff --git a/codegen/codegen.php b/codegen/codegen.php index 29edd454f..6ed3212b2 100755 --- a/codegen/codegen.php +++ b/codegen/codegen.php @@ -38,9 +38,27 @@ function array_change_key_case_recursive($arr) { }, array_change_key_case($arr)); } +function imports($api) { + $imports = array(); + if (is_array($api['struct'])) + foreach ($api['struct'] as $struct) { + if (isset($struct['imports'])) + foreach ($struct['imports'] as $import) { + $import = explode(" ", $import); + if (count($import) == 1) { + $imports[] = '"' . $import[0] . '"'; + } else { + $imports[] = $import[0] . ' "' . $import[1] . '"'; + } + } + } + return array_unique($imports); +} + $tpl = new Monotek\MiniTPL\Template; $tpl->set_compile_location("/tmp", true); $tpl->add_default("newline", "\n"); +$tpl->add_default("EOL", "\n"); $generators = array(); exec("find -L " . __DIR__ . "/" . $project . " -name index.php", $generators); @@ -81,7 +99,7 @@ $parsers = array( "[]uint64" => "parseUInt64A", "int" => "parseInt", "bool" => "parseBool", - "types.JSONText" => "parseJSONText", + "sqlxTypes.JSONText" => "parseJSONTextWithErr", ); foreach ($generators as $generator) { diff --git a/codegen/crm/rest/handlers/index.php b/codegen/crm/rest/handlers/index.php index 7aa5983f3..276aa9a7a 100644 --- a/codegen/crm/rest/handlers/index.php +++ b/codegen/crm/rest/handlers/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/crm/rest/index.php b/codegen/crm/rest/index.php index fc5eabcd9..f7102bb34 100644 --- a/codegen/crm/rest/index.php +++ b/codegen/crm/rest/index.php @@ -11,14 +11,7 @@ foreach ($apis as $api) { $tpl->assign("api", $api); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/crm/rest/request/index.php b/codegen/crm/rest/request/index.php index c98c0349b..bd6bb47cb 100644 --- a/codegen/crm/rest/request/index.php +++ b/codegen/crm/rest/request/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/crm/types/index.php b/codegen/crm/types/index.php index 6b4d6f14b..e8f53cfd2 100644 --- a/codegen/crm/types/index.php +++ b/codegen/crm/types/index.php @@ -22,13 +22,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/sam/rest/handlers/index.php b/codegen/sam/rest/handlers/index.php index 7aa5983f3..276aa9a7a 100644 --- a/codegen/sam/rest/handlers/index.php +++ b/codegen/sam/rest/handlers/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/sam/rest/index.php b/codegen/sam/rest/index.php index fc5eabcd9..f7102bb34 100644 --- a/codegen/sam/rest/index.php +++ b/codegen/sam/rest/index.php @@ -11,14 +11,7 @@ foreach ($apis as $api) { $tpl->assign("api", $api); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/sam/rest/request/index.php b/codegen/sam/rest/request/index.php index c98c0349b..bd6bb47cb 100644 --- a/codegen/sam/rest/request/index.php +++ b/codegen/sam/rest/request/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/system/rest/handlers/index.php b/codegen/system/rest/handlers/index.php index 7aa5983f3..276aa9a7a 100644 --- a/codegen/system/rest/handlers/index.php +++ b/codegen/system/rest/handlers/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/system/rest/index.php b/codegen/system/rest/index.php index fc5eabcd9..f7102bb34 100644 --- a/codegen/system/rest/index.php +++ b/codegen/system/rest/index.php @@ -11,14 +11,7 @@ foreach ($apis as $api) { $tpl->assign("api", $api); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/system/rest/request/index.php b/codegen/system/rest/request/index.php index c98c0349b..bd6bb47cb 100644 --- a/codegen/system/rest/request/index.php +++ b/codegen/system/rest/request/index.php @@ -19,14 +19,7 @@ foreach ($apis as $api) { $tpl->assign("apis", $apis); $tpl->assign("self", strtolower(substr($name, 0, 1))); $tpl->assign("structs", $api['struct']); - $imports = array(); - if (is_array($api['struct'])) - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } + $imports = imports($api); $tpl->assign("imports", $imports); $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); diff --git a/codegen/templates/http_request_inline.tpl b/codegen/templates/http_request_inline.tpl index 3b0c99e46..b50f826a2 100644 --- a/codegen/templates/http_request_inline.tpl +++ b/codegen/templates/http_request_inline.tpl @@ -6,18 +6,18 @@ import ( "io" "net/http" "encoding/json" - "github.com/go-chi/chi" - "github.com/pkg/errors" - "github.com/jmoiron/sqlx/types" - "github.com/crusttech/crust/internal/rbac" "mime/multipart" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" + +{if !empty($imports)}{foreach ($imports as $import)} + {import}{EOL}{/foreach}{/if} ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} {foreach $calls as $call} // {name} {call.name} request parameters @@ -68,17 +68,17 @@ func ({self} *{name|expose}{call.name|capitalize}) Fill(r *http.Request) (err er {elseif substr($param.type, 0, 2) === '[]' && isset($parsers[$param.type])} {self}.{param.name|expose} = {$parsers[$param.type]}({if $method === "post"}r.Form["{param.name}"]{else}urlQuery["{param.name}"]{/if}) {elseif $param.type === "*multipart.FileHeader"} - if _, {self}.{param.name|expose}, err = r.FormFile("{$param.name}"); err != nil { - return errors.Wrap(err, "error procesing uploaded file") - } + if _, {self}.{param.name|expose}, err = r.FormFile("{$param.name}"); err != nil { + return errors.Wrap(err, "error procesing uploaded file") + } {elseif substr($param.type, 0, 2) !== '[]'} - if val, ok := {method|strtolower}["{param.name}"]; ok { -{if $param.type === "types.JSONText"} - if {self}.{param.name|expose}, err = {$parsers[$param.type]}(val); err != nil { - return err - } + if val, ok := {method|strtolower}["{param.name}"]; ok { +{if substr($parsers[$param.type], -7) === 'WithErr'} + if {self}.{param.name|expose}, err = {$parsers[$param.type]}(val); err != nil { + return err + } {else} - {self}.{param.name|expose} = {if ($param.type !== "string")}{$parsers[$param.type]}(val){else}val{/if} + {self}.{param.name|expose} = {if ($param.type !== "string")}{$parsers[$param.type]}(val){else}val{/if}{EOL} {/if} }{/if} {/foreach} diff --git a/codegen/templates/http_structs.tpl b/codegen/templates/http_structs.tpl index 433e9f271..897ce2df1 100644 --- a/codegen/templates/http_structs.tpl +++ b/codegen/templates/http_structs.tpl @@ -5,8 +5,7 @@ package {package} {if !empty($imports)} import ( {foreach ($imports as $import)} - "{import}" -{/foreach} + {import}{EOL}{/foreach} ) {/if} diff --git a/crm/rest/request/field.go b/crm/rest/request/field.go index 7e46cae53..cf3da30d5 100644 --- a/crm/rest/request/field.go +++ b/crm/rest/request/field.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Field list request parameters type FieldList struct { diff --git a/crm/rest/request/module.go b/crm/rest/request/module.go index dd6441907..720470412 100644 --- a/crm/rest/request/module.go +++ b/crm/rest/request/module.go @@ -17,20 +17,19 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" + + sqlxTypes "github.com/jmoiron/sqlx/types" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Module list request parameters type ModuleList struct { @@ -81,7 +80,7 @@ var _ RequestFiller = NewModuleList() // Module create request parameters type ModuleCreate struct { Name string - Fields types.JSONText + Fields sqlxTypes.JSONText } func NewModuleCreate() *ModuleCreate { @@ -121,7 +120,7 @@ func (m *ModuleCreate) Fill(r *http.Request) (err error) { } if val, ok := post["fields"]; ok { - if m.Fields, err = parseJSONText(val); err != nil { + if m.Fields, err = parseJSONTextWithErr(val); err != nil { return err } } @@ -271,7 +270,7 @@ var _ RequestFiller = NewModuleChart() type ModuleEdit struct { ModuleID uint64 `json:",string"` Name string - Fields types.JSONText + Fields sqlxTypes.JSONText } func NewModuleEdit() *ModuleEdit { @@ -312,7 +311,7 @@ func (m *ModuleEdit) Fill(r *http.Request) (err error) { } if val, ok := post["fields"]; ok { - if m.Fields, err = parseJSONText(val); err != nil { + if m.Fields, err = parseJSONTextWithErr(val); err != nil { return err } } @@ -426,7 +425,7 @@ var _ RequestFiller = NewModuleContentList() // Module content/create request parameters type ModuleContentCreate struct { ModuleID uint64 `json:",string"` - Fields types.JSONText + Fields sqlxTypes.JSONText } func NewModuleContentCreate() *ModuleContentCreate { @@ -463,7 +462,7 @@ func (m *ModuleContentCreate) Fill(r *http.Request) (err error) { m.ModuleID = parseUInt64(chi.URLParam(r, "moduleID")) if val, ok := post["fields"]; ok { - if m.Fields, err = parseJSONText(val); err != nil { + if m.Fields, err = parseJSONTextWithErr(val); err != nil { return err } } @@ -522,7 +521,7 @@ var _ RequestFiller = NewModuleContentRead() type ModuleContentEdit struct { ModuleID uint64 `json:",string"` ContentID uint64 `json:",string"` - Fields types.JSONText + Fields sqlxTypes.JSONText } func NewModuleContentEdit() *ModuleContentEdit { @@ -560,7 +559,7 @@ func (m *ModuleContentEdit) Fill(r *http.Request) (err error) { m.ContentID = parseUInt64(chi.URLParam(r, "contentID")) if val, ok := post["fields"]; ok { - if m.Fields, err = parseJSONText(val); err != nil { + if m.Fields, err = parseJSONTextWithErr(val); err != nil { return err } } diff --git a/crm/rest/request/page.go b/crm/rest/request/page.go index b4c8662cd..519e5e4b6 100644 --- a/crm/rest/request/page.go +++ b/crm/rest/request/page.go @@ -17,20 +17,19 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" + + sqlxTypes "github.com/jmoiron/sqlx/types" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Page list request parameters type PageList struct { @@ -85,7 +84,7 @@ type PageCreate struct { Title string Description string Visible bool - Blocks types.JSONText + Blocks sqlxTypes.JSONText } func NewPageCreate() *PageCreate { @@ -141,7 +140,7 @@ func (p *PageCreate) Fill(r *http.Request) (err error) { } if val, ok := post["blocks"]; ok { - if p.Blocks, err = parseJSONText(val); err != nil { + if p.Blocks, err = parseJSONTextWithErr(val); err != nil { return err } } @@ -242,7 +241,7 @@ type PageEdit struct { Title string Description string Visible bool - Blocks types.JSONText + Blocks sqlxTypes.JSONText } func NewPageEdit() *PageEdit { @@ -299,7 +298,7 @@ func (p *PageEdit) Fill(r *http.Request) (err error) { } if val, ok := post["blocks"]; ok { - if p.Blocks, err = parseJSONText(val); err != nil { + if p.Blocks, err = parseJSONTextWithErr(val); err != nil { return err } } diff --git a/crm/rest/request/util.go b/crm/rest/request/util.go index f8b7fda70..4451032fd 100644 --- a/crm/rest/request/util.go +++ b/crm/rest/request/util.go @@ -11,7 +11,7 @@ import ( var truthy = regexp.MustCompile("^\\s*(t(rue)?|y(es)?|1)\\s*$") -func parseJSONText(s string) (types.JSONText, error) { +func parseJSONTextWithErr(s string) (types.JSONText, error) { result := &types.JSONText{} err := errors.Wrap(result.Scan(s), "error when parsing JSONText") return *result, err diff --git a/docs/crm/README.md b/docs/crm/README.md index 03bdc26ed..ad8110add 100644 --- a/docs/crm/README.md +++ b/docs/crm/README.md @@ -63,7 +63,7 @@ CRM module definitions | Parameter | Type | Method | Description | Default | Required? | | --------- | ---- | ------ | ----------- | ------- | --------- | | name | string | POST | Module Name | N/A | YES | -| fields | types.JSONText | POST | Fields JSON | N/A | YES | +| fields | sqlxTypes.JSONText | POST | Fields JSON | N/A | YES | ## Read module @@ -302,7 +302,7 @@ Example bar chart with number of leads per country: select lead.country from lea | --------- | ---- | ------ | ----------- | ------- | --------- | | moduleID | uint64 | PATH | Module ID | N/A | YES | | name | string | POST | Module Name | N/A | YES | -| fields | types.JSONText | POST | Fields JSON | N/A | YES | +| fields | sqlxTypes.JSONText | POST | Fields JSON | N/A | YES | ## Delete module @@ -348,7 +348,7 @@ Example bar chart with number of leads per country: select lead.country from lea | Parameter | Type | Method | Description | Default | Required? | | --------- | ---- | ------ | ----------- | ------- | --------- | | moduleID | uint64 | PATH | Module ID | N/A | YES | -| fields | types.JSONText | POST | Content JSON | N/A | YES | +| fields | sqlxTypes.JSONText | POST | Content JSON | N/A | YES | ## Read contents by ID from module section @@ -379,7 +379,7 @@ Example bar chart with number of leads per country: select lead.country from lea | --------- | ---- | ------ | ----------- | ------- | --------- | | moduleID | uint64 | PATH | Module ID | N/A | YES | | contentID | uint64 | PATH | Content ID | N/A | YES | -| fields | types.JSONText | POST | Content JSON | N/A | YES | +| fields | sqlxTypes.JSONText | POST | Content JSON | N/A | YES | ## Delete content row from module section @@ -434,7 +434,7 @@ CRM module pages | title | string | POST | Title | N/A | YES | | description | string | POST | Description | N/A | NO | | visible | bool | POST | Visible in navigation | N/A | NO | -| blocks | types.JSONText | POST | Blocks JSON | N/A | YES | +| blocks | sqlxTypes.JSONText | POST | Blocks JSON | N/A | YES | ## Get page details @@ -481,7 +481,7 @@ CRM module pages | title | string | POST | Title | N/A | YES | | description | string | POST | Description | N/A | NO | | visible | bool | POST | Visible in navigation | N/A | NO | -| blocks | types.JSONText | POST | Blocks JSON | N/A | YES | +| blocks | sqlxTypes.JSONText | POST | Blocks JSON | N/A | YES | ## Reorder pages diff --git a/docs/system/README.md b/docs/system/README.md index da1003d21..bb88d31a8 100644 --- a/docs/system/README.md +++ b/docs/system/README.md @@ -324,7 +324,7 @@ An organisation may have many teams. Teams may have many channels available. Acc | name | string | POST | Name | N/A | YES | | handle | string | POST | Handle | N/A | YES | | kind | string | POST | Kind (normal, bot) | N/A | NO | -| meta | types.JSONText | POST | Meta data | N/A | NO | +| meta | sqlxTypes.JSONText | POST | Meta data | N/A | NO | | satosaID | string | POST | Satosa ID | N/A | NO | | organisationID | uint64 | POST | Organisation ID | N/A | NO | @@ -347,7 +347,7 @@ An organisation may have many teams. Teams may have many channels available. Acc | name | string | POST | Name | N/A | YES | | handle | string | POST | Handle | N/A | YES | | kind | string | POST | Kind (normal, bot) | N/A | NO | -| meta | types.JSONText | POST | Meta data | N/A | NO | +| meta | sqlxTypes.JSONText | POST | Meta data | N/A | NO | | satosaID | string | POST | Satosa ID | N/A | NO | | organisationID | uint64 | POST | Organisation ID | N/A | NO | diff --git a/sam/rest/request/attachment.go b/sam/rest/request/attachment.go index cf4acb686..308f1dfa9 100644 --- a/sam/rest/request/attachment.go +++ b/sam/rest/request/attachment.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Attachment original request parameters type AttachmentOriginal struct { diff --git a/sam/rest/request/channel.go b/sam/rest/request/channel.go index 4825225e6..121fa78a6 100644 --- a/sam/rest/request/channel.go +++ b/sam/rest/request/channel.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Channel list request parameters type ChannelList struct { diff --git a/sam/rest/request/message.go b/sam/rest/request/message.go index 9ca4c4398..1816a7e74 100644 --- a/sam/rest/request/message.go +++ b/sam/rest/request/message.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Message create request parameters type MessageCreate struct { diff --git a/sam/rest/request/permissions.go b/sam/rest/request/permissions.go index bd5f7386f..7cb9eefa0 100644 --- a/sam/rest/request/permissions.go +++ b/sam/rest/request/permissions.go @@ -17,20 +17,19 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" + + "github.com/crusttech/crust/internal/rbac" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Permissions list request parameters type PermissionsList struct { diff --git a/sam/rest/request/search.go b/sam/rest/request/search.go index 536a5a221..24c010084 100644 --- a/sam/rest/request/search.go +++ b/sam/rest/request/search.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Search messages request parameters type SearchMessages struct { diff --git a/sam/types/channel.perms.go b/sam/types/channel.perms.go index c09d6e821..0dc908565 100644 --- a/sam/types/channel.perms.go +++ b/sam/types/channel.perms.go @@ -2,7 +2,7 @@ package types import "github.com/crusttech/crust/internal/rbac" -/* File is generated from sam/types/permissions/3-channel.json with permissions.go */ +/* File is generated from sam/types/permissions/3-channel.json with permissions.go */ func (c *Channel) Permissions() []rbac.OperationGroup { return []rbac.OperationGroup{ diff --git a/sam/types/organisation.perms.go b/sam/types/organisation.perms.go index 5549b5440..17faf5b1f 100644 --- a/sam/types/organisation.perms.go +++ b/sam/types/organisation.perms.go @@ -2,7 +2,7 @@ package types import "github.com/crusttech/crust/internal/rbac" -/* File is generated from sam/types/permissions/1-organisation.json with permissions.go */ +/* File is generated from sam/types/permissions/1-organisation.json with permissions.go */ func (c *Organisation) Permissions() []rbac.OperationGroup { return []rbac.OperationGroup{ diff --git a/sam/types/team.perms.go b/sam/types/team.perms.go index 04fad75f7..92e7ffee3 100644 --- a/sam/types/team.perms.go +++ b/sam/types/team.perms.go @@ -2,7 +2,7 @@ package types import "github.com/crusttech/crust/internal/rbac" -/* File is generated from sam/types/permissions/2-team.json with permissions.go */ +/* File is generated from sam/types/permissions/2-team.json with permissions.go */ func (c *Team) Permissions() []rbac.OperationGroup { return []rbac.OperationGroup{ diff --git a/system/rest/request/auth.go b/system/rest/request/auth.go index edf31bb1b..981b1f575 100644 --- a/system/rest/request/auth.go +++ b/system/rest/request/auth.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Auth check request parameters type AuthCheck struct { diff --git a/system/rest/request/organisation.go b/system/rest/request/organisation.go index a1e9525fc..88cb4243e 100644 --- a/system/rest/request/organisation.go +++ b/system/rest/request/organisation.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Organisation list request parameters type OrganisationList struct { diff --git a/system/rest/request/team.go b/system/rest/request/team.go index b0a39fe34..90753a873 100644 --- a/system/rest/request/team.go +++ b/system/rest/request/team.go @@ -17,20 +17,17 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // Team list request parameters type TeamList struct { diff --git a/system/rest/request/user.go b/system/rest/request/user.go index 11982de2c..b87d3dabb 100644 --- a/system/rest/request/user.go +++ b/system/rest/request/user.go @@ -17,20 +17,19 @@ package request import ( "encoding/json" - "github.com/crusttech/crust/internal/rbac" - "github.com/go-chi/chi" - "github.com/jmoiron/sqlx/types" - "github.com/pkg/errors" "io" "mime/multipart" "net/http" "strings" + + "github.com/go-chi/chi" + "github.com/pkg/errors" + + sqlxTypes "github.com/jmoiron/sqlx/types" ) var _ = chi.URLParam -var _ = types.JSONText{} var _ = multipart.FileHeader{} -var _ = rbac.Operation{} // User list request parameters type UserList struct { @@ -86,7 +85,7 @@ type UserCreate struct { Name string Handle string Kind string - Meta types.JSONText + Meta sqlxTypes.JSONText SatosaID string OrganisationID uint64 `json:",string"` } @@ -148,7 +147,7 @@ func (u *UserCreate) Fill(r *http.Request) (err error) { } if val, ok := post["meta"]; ok { - if u.Meta, err = parseJSONText(val); err != nil { + if u.Meta, err = parseJSONTextWithErr(val); err != nil { return err } } @@ -175,7 +174,7 @@ type UserEdit struct { Name string Handle string Kind string - Meta types.JSONText + Meta sqlxTypes.JSONText SatosaID string OrganisationID uint64 `json:",string"` } @@ -238,7 +237,7 @@ func (u *UserEdit) Fill(r *http.Request) (err error) { } if val, ok := post["meta"]; ok { - if u.Meta, err = parseJSONText(val); err != nil { + if u.Meta, err = parseJSONTextWithErr(val); err != nil { return err } } diff --git a/system/rest/request/util.go b/system/rest/request/util.go index f8b7fda70..4451032fd 100644 --- a/system/rest/request/util.go +++ b/system/rest/request/util.go @@ -11,7 +11,7 @@ import ( var truthy = regexp.MustCompile("^\\s*(t(rue)?|y(es)?|1)\\s*$") -func parseJSONText(s string) (types.JSONText, error) { +func parseJSONTextWithErr(s string) (types.JSONText, error) { result := &types.JSONText{} err := errors.Wrap(result.Scan(s), "error when parsing JSONText") return *result, err From fdd499776c29e0b819b95b362f3f93ded1660f89 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:35:38 +0100 Subject: [PATCH 3/8] add(crm): migration for crm module form options --- crm/db/mysql/statik.go | 2 +- .../mysql/20181204155326.add-crm-module-form-json-field.up.sql | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 crm/db/schema/mysql/20181204155326.add-crm-module-form-json-field.up.sql diff --git a/crm/db/mysql/statik.go b/crm/db/mysql/statik.go index 32b2d0a78..7898a01b1 100644 --- a/crm/db/mysql/statik.go +++ b/crm/db/mysql/statik.go @@ -8,7 +8,7 @@ import ( ) func Data() string { - return "PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00 \x0020180704080000.base.up.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE `crm_content` (\n `id` bigint(20) unsigned NOT NULL,\n `module_id` bigint(20) unsigned NOT NULL,\n `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updated_at` datetime DEFAULT NULL,\n `deleted_at` datetime DEFAULT NULL,\n PRIMARY KEY (`id`,`module_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_content_column` (\n `content_id` bigint(20) NOT NULL,\n `column_name` varchar(255) NOT NULL,\n `column_value` text NOT NULL,\n PRIMARY KEY (`content_id`,`column_name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_field` (\n `field_type` varchar(16) NOT NULL COMMENT 'Short field type (string, boolean,...)',\n `field_name` varchar(255) NOT NULL COMMENT 'Description of field contents',\n `field_template` varchar(255) NOT NULL COMMENT 'HTML template file for field',\n PRIMARY KEY (`field_type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_module` (\n `id` bigint(20) unsigned NOT NULL,\n `name` varchar(64) NOT NULL COMMENT 'The name of the module',\n `json` json NOT NULL COMMENT 'List of field definitions for the module',\n `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updated_at` datetime DEFAULT NULL,\n `deleted_at` datetime DEFAULT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_module_form` (\n `module_id` bigint(20) unsigned NOT NULL,\n `place` tinyint(3) unsigned NOT NULL,\n `kind` varchar(64) NOT NULL COMMENT 'The type of the form input field',\n `name` varchar(64) NOT NULL COMMENT 'The name of the field in the form',\n `label` varchar(255) NOT NULL COMMENT 'The label of the form input',\n `help_text` text NOT NULL COMMENT 'Help text',\n `default_value` text NOT NULL COMMENT 'Default value',\n `max_length` int(10) unsigned NOT NULL COMMENT 'Maximum input length',\n `is_private` tinyint(1) NOT NULL COMMENT 'Contains personal/sensitive data?',\n PRIMARY KEY (`module_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_page` (\n `id` bigint(20) unsigned NOT NULL COMMENT 'Page ID',\n `self_id` bigint(20) unsigned NOT NULL COMMENT 'Parent Page ID',\n `module_id` bigint(20) unsigned NOT NULL COMMENT 'Module ID (optional)',\n `title` varchar(255) NOT NULL COMMENT 'Title (required)',\n `description` text NOT NULL COMMENT 'Description',\n `blocks` json NOT NULL COMMENT 'JSON array of blocks for the page',\n `visible` tinyint(4) NOT NULL COMMENT 'Is page visible in navigation?',\n `weight` int(11) NOT NULL COMMENT 'Order for navigation',\n PRIMARY KEY (`id`) USING BTREE,\n KEY `module_id` (`module_id`),\n KEY `self_id` (`self_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nPK\x07\x08\xac\xe8\x19\x1d\x12\n\x00\x00\x12\n\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00 \x0020180704080001.crm_fields-data.up.sqlUT\x05\x00\x01\x80Cm8INSERT INTO `crm_field` VALUES ('bool','Boolean value (yes / no)','');\nINSERT INTO `crm_field` VALUES ('email','E-mail input','');\nINSERT INTO `crm_field` VALUES ('enum','Single option picker','');\nINSERT INTO `crm_field` VALUES ('hidden','Hidden value','');\nINSERT INTO `crm_field` VALUES ('stamp','Date/time input','');\nINSERT INTO `crm_field` VALUES ('text','Text input','');\nINSERT INTO `crm_field` VALUES ('textarea','Text input (multi-line)','');\nPK\x07\x08f\x18\x1e\x84\xc5\x01\x00\x00\xc5\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00 \x0020181109133134.crm_content-ownership.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_content` ADD `user_id` BIGINT UNSIGNED NOT NULL AFTER `module_id`, ADD INDEX (`user_id`);\nPK\x07\x08\xeb!\x81\xc2k\x00\x00\x00k\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00 \x0020181109193047.crm_fields-related_types.up.sqlUT\x05\x00\x01\x80Cm8INSERT INTO `crm_field` (`field_type`, `field_name`, `field_template`) VALUES ('related', 'Related content', ''), ('related_multi', 'Related content (multiple)', '');PK\x07\x08:.\xfb8\xa6\x00\x00\x00\xa6\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00 \x0020181125122152.add_multiple_relationships.up.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE `crm_content_links` (\n `content_id` bigint(20) unsigned NOT NULL,\n `column_name` varchar(255) NOT NULL,\n `rel_content_id` bigint(20) unsigned NOT NULL,\n PRIMARY KEY (`content_id`,`column_name`,`rel_content_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;PK\x07\x08\xee\x12\x15 \x05\x01\x00\x00\x05\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00 \x0020181125132142.add_required_and_visible_to_module_form_fields.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_module_form` ADD `is_required` TINYINT(1) NOT NULL AFTER `is_private`, ADD `is_visible` TINYINT(1) NOT NULL AFTER `is_required`;PK\x07\x08\xa5q c\x91\x00\x00\x00\x91\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00 \x0020181202163130.fix-crm-module-form-primary-key.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_module_form` DROP PRIMARY KEY, ADD PRIMARY KEY(`module_id`, `place`);\nPK\x07\x08\xd9\xd4i\xe3W\x00\x00\x00W\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00 \x0020181204123650.add-crm-content-json-field.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_content` ADD `json` json DEFAULT NULL COMMENT 'Content in JSON format.' AFTER `user_id`;\nPK\x07\x08\"\x96\xd6pj\x00\x00\x00j\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00 \x00migrations.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE IF NOT EXISTS `migrations` (\n `project` varchar(16) NOT NULL COMMENT 'sam, crm, ...',\n `filename` varchar(255) NOT NULL COMMENT 'yyyymmddHHMMSS.sql',\n `statement_index` int(11) NOT NULL COMMENT 'Statement number from SQL file',\n `status` text NOT NULL COMMENT 'ok or full error message',\n PRIMARY KEY (`project`,`filename`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nPK\x07\x089S\x05%x\x01\x00\x00x\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00 \x00new.shUT\x05\x00\x01\x80Cm8#!/bin/bash\ntouch $(date +%Y%m%d%H%M%S).up.sqlPK\x07\x08s\xd4N*.\x00\x00\x00.\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xac\xe8\x19\x1d\x12\n\x00\x00\x12\n\x00\x00\x1a\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x0020180704080000.base.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(f\x18\x1e\x84\xc5\x01\x00\x00\xc5\x01\x00\x00%\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81c\n\x00\x0020180704080001.crm_fields-data.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xeb!\x81\xc2k\x00\x00\x00k\x00\x00\x00+\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x84\x0c\x00\x0020181109133134.crm_content-ownership.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(:.\xfb8\xa6\x00\x00\x00\xa6\x00\x00\x00.\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Q\x0d\x00\x0020181109193047.crm_fields-related_types.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xee\x12\x15 \x05\x01\x00\x00\x05\x01\x00\x000\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\\\x0e\x00\x0020181125122152.add_multiple_relationships.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xa5q c\x91\x00\x00\x00\x91\x00\x00\x00D\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc8\x0f\x00\x0020181125132142.add_required_and_visible_to_module_form_fields.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xd9\xd4i\xe3W\x00\x00\x00W\x00\x00\x005\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd4\x10\x00\x0020181202163130.fix-crm-module-form-primary-key.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\"\x96\xd6pj\x00\x00\x00j\x00\x00\x000\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x97\x11\x00\x0020181204123650.add-crm-content-json-field.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(9S\x05%x\x01\x00\x00x\x01\x00\x00\x0e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81h\x12\x00\x00migrations.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(s\xd4N*.\x00\x00\x00.\x00\x00\x00\x06\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\x81%\x14\x00\x00new.shUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\n\x00\n\x00\xab\x03\x00\x00\x90\x14\x00\x00\x00\x00" + return "PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00 \x0020180704080000.base.up.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE `crm_content` (\n `id` bigint(20) unsigned NOT NULL,\n `module_id` bigint(20) unsigned NOT NULL,\n `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updated_at` datetime DEFAULT NULL,\n `deleted_at` datetime DEFAULT NULL,\n PRIMARY KEY (`id`,`module_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_content_column` (\n `content_id` bigint(20) NOT NULL,\n `column_name` varchar(255) NOT NULL,\n `column_value` text NOT NULL,\n PRIMARY KEY (`content_id`,`column_name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_field` (\n `field_type` varchar(16) NOT NULL COMMENT 'Short field type (string, boolean,...)',\n `field_name` varchar(255) NOT NULL COMMENT 'Description of field contents',\n `field_template` varchar(255) NOT NULL COMMENT 'HTML template file for field',\n PRIMARY KEY (`field_type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_module` (\n `id` bigint(20) unsigned NOT NULL,\n `name` varchar(64) NOT NULL COMMENT 'The name of the module',\n `json` json NOT NULL COMMENT 'List of field definitions for the module',\n `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,\n `updated_at` datetime DEFAULT NULL,\n `deleted_at` datetime DEFAULT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_module_form` (\n `module_id` bigint(20) unsigned NOT NULL,\n `place` tinyint(3) unsigned NOT NULL,\n `kind` varchar(64) NOT NULL COMMENT 'The type of the form input field',\n `name` varchar(64) NOT NULL COMMENT 'The name of the field in the form',\n `label` varchar(255) NOT NULL COMMENT 'The label of the form input',\n `help_text` text NOT NULL COMMENT 'Help text',\n `default_value` text NOT NULL COMMENT 'Default value',\n `max_length` int(10) unsigned NOT NULL COMMENT 'Maximum input length',\n `is_private` tinyint(1) NOT NULL COMMENT 'Contains personal/sensitive data?',\n PRIMARY KEY (`module_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nCREATE TABLE `crm_page` (\n `id` bigint(20) unsigned NOT NULL COMMENT 'Page ID',\n `self_id` bigint(20) unsigned NOT NULL COMMENT 'Parent Page ID',\n `module_id` bigint(20) unsigned NOT NULL COMMENT 'Module ID (optional)',\n `title` varchar(255) NOT NULL COMMENT 'Title (required)',\n `description` text NOT NULL COMMENT 'Description',\n `blocks` json NOT NULL COMMENT 'JSON array of blocks for the page',\n `visible` tinyint(4) NOT NULL COMMENT 'Is page visible in navigation?',\n `weight` int(11) NOT NULL COMMENT 'Order for navigation',\n PRIMARY KEY (`id`) USING BTREE,\n KEY `module_id` (`module_id`),\n KEY `self_id` (`self_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nPK\x07\x08\xac\xe8\x19\x1d\x12\n\x00\x00\x12\n\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00 \x0020180704080001.crm_fields-data.up.sqlUT\x05\x00\x01\x80Cm8INSERT INTO `crm_field` VALUES ('bool','Boolean value (yes / no)','');\nINSERT INTO `crm_field` VALUES ('email','E-mail input','');\nINSERT INTO `crm_field` VALUES ('enum','Single option picker','');\nINSERT INTO `crm_field` VALUES ('hidden','Hidden value','');\nINSERT INTO `crm_field` VALUES ('stamp','Date/time input','');\nINSERT INTO `crm_field` VALUES ('text','Text input','');\nINSERT INTO `crm_field` VALUES ('textarea','Text input (multi-line)','');\nPK\x07\x08f\x18\x1e\x84\xc5\x01\x00\x00\xc5\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00 \x0020181109133134.crm_content-ownership.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_content` ADD `user_id` BIGINT UNSIGNED NOT NULL AFTER `module_id`, ADD INDEX (`user_id`);\nPK\x07\x08\xeb!\x81\xc2k\x00\x00\x00k\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00 \x0020181109193047.crm_fields-related_types.up.sqlUT\x05\x00\x01\x80Cm8INSERT INTO `crm_field` (`field_type`, `field_name`, `field_template`) VALUES ('related', 'Related content', ''), ('related_multi', 'Related content (multiple)', '');PK\x07\x08:.\xfb8\xa6\x00\x00\x00\xa6\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00 \x0020181125122152.add_multiple_relationships.up.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE `crm_content_links` (\n `content_id` bigint(20) unsigned NOT NULL,\n `column_name` varchar(255) NOT NULL,\n `rel_content_id` bigint(20) unsigned NOT NULL,\n PRIMARY KEY (`content_id`,`column_name`,`rel_content_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;PK\x07\x08\xee\x12\x15 \x05\x01\x00\x00\x05\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00 \x0020181125132142.add_required_and_visible_to_module_form_fields.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_module_form` ADD `is_required` TINYINT(1) NOT NULL AFTER `is_private`, ADD `is_visible` TINYINT(1) NOT NULL AFTER `is_required`;PK\x07\x08\xa5q c\x91\x00\x00\x00\x91\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00 \x0020181202163130.fix-crm-module-form-primary-key.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_module_form` DROP PRIMARY KEY, ADD PRIMARY KEY(`module_id`, `place`);\nPK\x07\x08\xd9\xd4i\xe3W\x00\x00\x00W\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00 \x0020181204123650.add-crm-content-json-field.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_content` ADD `json` json DEFAULT NULL COMMENT 'Content in JSON format.' AFTER `user_id`;\nPK\x07\x08\"\x96\xd6pj\x00\x00\x00j\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00 \x0020181204155326.add-crm-module-form-json-field.up.sqlUT\x05\x00\x01\x80Cm8ALTER TABLE `crm_module_form` ADD `json` JSON NOT NULL COMMENT 'Options in JSON format.' AFTER `kind`;PK\x07\x08\xb7\x93\xd4\xf6f\x00\x00\x00f\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00 \x00migrations.sqlUT\x05\x00\x01\x80Cm8CREATE TABLE IF NOT EXISTS `migrations` (\n `project` varchar(16) NOT NULL COMMENT 'sam, crm, ...',\n `filename` varchar(255) NOT NULL COMMENT 'yyyymmddHHMMSS.sql',\n `statement_index` int(11) NOT NULL COMMENT 'Statement number from SQL file',\n `status` text NOT NULL COMMENT 'ok or full error message',\n PRIMARY KEY (`project`,`filename`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nPK\x07\x089S\x05%x\x01\x00\x00x\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00 \x00new.shUT\x05\x00\x01\x80Cm8#!/bin/bash\ntouch $(date +%Y%m%d%H%M%S).up.sqlPK\x07\x08s\xd4N*.\x00\x00\x00.\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xac\xe8\x19\x1d\x12\n\x00\x00\x12\n\x00\x00\x1a\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x0020180704080000.base.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(f\x18\x1e\x84\xc5\x01\x00\x00\xc5\x01\x00\x00%\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81c\n\x00\x0020180704080001.crm_fields-data.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xeb!\x81\xc2k\x00\x00\x00k\x00\x00\x00+\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x84\x0c\x00\x0020181109133134.crm_content-ownership.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(:.\xfb8\xa6\x00\x00\x00\xa6\x00\x00\x00.\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Q\x0d\x00\x0020181109193047.crm_fields-related_types.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xee\x12\x15 \x05\x01\x00\x00\x05\x01\x00\x000\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\\\x0e\x00\x0020181125122152.add_multiple_relationships.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xa5q c\x91\x00\x00\x00\x91\x00\x00\x00D\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc8\x0f\x00\x0020181125132142.add_required_and_visible_to_module_form_fields.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xd9\xd4i\xe3W\x00\x00\x00W\x00\x00\x005\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd4\x10\x00\x0020181202163130.fix-crm-module-form-primary-key.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\"\x96\xd6pj\x00\x00\x00j\x00\x00\x000\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x97\x11\x00\x0020181204123650.add-crm-content-json-field.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xb7\x93\xd4\xf6f\x00\x00\x00f\x00\x00\x004\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81h\x12\x00\x0020181204155326.add-crm-module-form-json-field.up.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(9S\x05%x\x01\x00\x00x\x01\x00\x00\x0e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x819\x13\x00\x00migrations.sqlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(s\xd4N*.\x00\x00\x00.\x00\x00\x00\x06\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\x81\xf6\x14\x00\x00new.shUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x0b\x00\x0b\x00\x16\x04\x00\x00a\x15\x00\x00\x00\x00" } func init() { diff --git a/crm/db/schema/mysql/20181204155326.add-crm-module-form-json-field.up.sql b/crm/db/schema/mysql/20181204155326.add-crm-module-form-json-field.up.sql new file mode 100644 index 000000000..07a748860 --- /dev/null +++ b/crm/db/schema/mysql/20181204155326.add-crm-module-form-json-field.up.sql @@ -0,0 +1 @@ +ALTER TABLE `crm_module_form` ADD `json` JSON NOT NULL COMMENT 'Options in JSON format.' AFTER `kind`; \ No newline at end of file From eb9869bcdf460a8d90c87c2f9e5868be26a9ad8f Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:36:52 +0100 Subject: [PATCH 4/8] upd(codegen): special handling of *Set types --- codegen/templates/http_request_inline.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/templates/http_request_inline.tpl b/codegen/templates/http_request_inline.tpl index b50f826a2..f9fd54219 100644 --- a/codegen/templates/http_request_inline.tpl +++ b/codegen/templates/http_request_inline.tpl @@ -65,13 +65,13 @@ func ({self} *{name|expose}{call.name|capitalize}) Fill(r *http.Request) (err er {foreach $params as $param} {if strtolower($method) === "path"} {self}.{param.name|expose} = {if ($param.type !== "string")}{$parsers[$param.type]}({/if}chi.URLParam(r, "{param.name}"){if ($param.type !== "string")}){/if} -{elseif substr($param.type, 0, 2) === '[]' && isset($parsers[$param.type])} +{elseif (substr($param.type, 0, 2) === '[]' || substr($param.type, -3) === "Set") && isset($parsers[$param.type])} {self}.{param.name|expose} = {$parsers[$param.type]}({if $method === "post"}r.Form["{param.name}"]{else}urlQuery["{param.name}"]{/if}) {elseif $param.type === "*multipart.FileHeader"} if _, {self}.{param.name|expose}, err = r.FormFile("{$param.name}"); err != nil { return errors.Wrap(err, "error procesing uploaded file") } -{elseif substr($param.type, 0, 2) !== '[]'} +{elseif substr($param.type, 0, 2) !== '[]' && substr($param.type, -3) !== 'Set'} if val, ok := {method|strtolower}["{param.name}"]; ok { {if substr($parsers[$param.type], -7) === 'WithErr'} if {self}.{param.name|expose}, err = {$parsers[$param.type]}(val); err != nil { From 0c5f1ea97ead5f606b41d911fbe160182185c72c Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:37:25 +0100 Subject: [PATCH 5/8] upd(crm): serialization for ModuleFieldSet --- crm/types/types.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crm/types/types.go b/crm/types/types.go index 55c8a489d..5fd674a54 100644 --- a/crm/types/types.go +++ b/crm/types/types.go @@ -3,6 +3,9 @@ package types import ( "time" + "database/sql/driver" + "encoding/json" + "github.com/jmoiron/sqlx/types" systemTypes "github.com/crusttech/crust/system/types" @@ -53,7 +56,7 @@ type ( Module struct { ID uint64 `json:"moduleID,string" db:"id"` Name string `json:"name" db:"name"` - Fields types.JSONText `json:"fields" db:"json"` + Fields ModuleFieldSet `json:"fields" db:"json"` Page *Page `json:"page,omitempty"` @@ -81,6 +84,8 @@ type ( Visible bool `json:"isVisible" db:"is_visible"` } + ModuleFieldSet []ModuleField + // Page - page structure Page struct { ID uint64 `json:"pageID,string" db:"id"` @@ -112,3 +117,14 @@ type ( Height int `json:"height"` } ) + +func (f *ModuleFieldSet) Scan(src interface{}) error { + if data, ok := src.([]byte); ok { + return json.Unmarshal(data, f) + } + return nil +} + +func (f ModuleFieldSet) Value() (driver.Value, error) { + return json.Marshal(f) +} From bb4fee2dde5108cee3d8eee4600b1d8a071a1bab Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:38:42 +0100 Subject: [PATCH 6/8] upd(crm): fix page as zero based index --- crm/repository/content.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crm/repository/content.go b/crm/repository/content.go index 38547703c..1ebbb45e5 100644 --- a/crm/repository/content.go +++ b/crm/repository/content.go @@ -67,8 +67,8 @@ func (r *content) FindByID(id uint64) (*types.Content, error) { } func (r *content) Find(moduleID uint64, query string, page int, perPage int) (*FindResponse, error) { - if page < 1 { - page = 1 + if page < 0 { + page = 0 } if perPage <= 0 { perPage = 50 @@ -95,7 +95,7 @@ func (r *content) Find(moduleID uint64, query string, page int, perPage int) (*F sqlWhere := "WHERE module_id=? and deleted_at IS NULL" sqlOrder := "ORDER BY id DESC" - sqlLimit := fmt.Sprintf("LIMIT %d, %d", (page-1)*perPage, perPage) + sqlLimit := fmt.Sprintf("LIMIT %d, %d", page*perPage, perPage) switch true { case query != "": From c7d4b4d629ec778c82a3866f47257f8aef313a34 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:39:14 +0100 Subject: [PATCH 7/8] upd(crm): unmarshalled fields change --- crm/repository/module.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/crm/repository/module.go b/crm/repository/module.go index 3d14d2d2a..9542a275f 100644 --- a/crm/repository/module.go +++ b/crm/repository/module.go @@ -2,7 +2,6 @@ package repository import ( "context" - "encoding/json" "time" "github.com/pkg/errors" @@ -61,13 +60,7 @@ func (r *module) Find() (types.ModuleSet, error) { func (r *module) Create(mod *types.Module) (*types.Module, error) { mod.ID = factory.Sonyflake.NextID() mod.CreatedAt = time.Now() - - fields := make([]types.ModuleField, 0) - if err := json.Unmarshal(mod.Fields, &fields); err != nil { - return nil, errors.Wrap(err, "No fields") - } - - for idx, v := range fields { + for idx, v := range mod.Fields { v.ModuleID = mod.ID v.Place = idx if err := r.db().Replace("crm_module_form", v); err != nil { @@ -78,18 +71,9 @@ func (r *module) Create(mod *types.Module) (*types.Module, error) { } func (r *module) Update(mod *types.Module) (*types.Module, error) { - if mod.ID == 0 { - return nil, errors.New("Error when saving module, invalid ID") - } now := time.Now() mod.UpdatedAt = &now - - fields := make([]types.ModuleField, 0) - if err := json.Unmarshal(mod.Fields, &fields); err != nil { - return nil, errors.Wrap(err, "No fields") - } - - for idx, v := range fields { + for idx, v := range mod.Fields { v.ModuleID = mod.ID v.Place = idx if err := r.db().Replace("crm_module_form", v); err != nil { From 99f8f4e8726dfb5c64bf1fe430e9e8947b823cc6 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Tue, 4 Dec 2018 16:40:02 +0100 Subject: [PATCH 8/8] upd(crm): update module api fields parameter --- api/crm/spec.json | 94 ++----------------------------------- api/crm/spec/field.json | 24 +--------- api/crm/spec/module.json | 72 ++-------------------------- crm/rest/request/module.go | 17 ++----- crm/service/content_test.go | 34 +++++++------- crm/service/module.go | 10 ++++ crm/service/module_test.go | 41 ++++++++-------- docs/crm/README.md | 4 +- 8 files changed, 61 insertions(+), 235 deletions(-) diff --git a/api/crm/spec.json b/api/crm/spec.json index 9e646eb0d..6c21cb91c 100644 --- a/api/crm/spec.json +++ b/api/crm/spec.json @@ -6,29 +6,7 @@ "entrypoint": "field", "path": "/field", "authentication": [], - "struct": [ - { - "name": "Field", - "fields": [ - { - "name": "Name", - "type": "string", - "db": "field_name" - }, - { - "name": "Type", - "type": "string", - "db": "field_type" - }, - { - "name": "Template", - "type": "string", - "db": "field_template", - "omitempty": true - } - ] - } - ], + "struct": [], "apis": [ { "name": "list", @@ -259,71 +237,9 @@ "authentication": [], "struct": [ { - "name": "Module", "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ], - "fields": [ - { - "name": "ID", - "type": "uint64" - }, - { - "name": "Name", - "type": "string" - }, - { - "name": "Fields", - "type": "sqlxTypes.JSONText", - "json": "fields", - "db": "json" - } - ] - }, - { - "name": "ModuleField", - "fields": [ - { - "name": "Name", - "type": "string" - }, - { - "name": "Title", - "type": "string" - }, - { - "name": "Kind", - "type": "string" - }, - { - "name": "GDPR", - "type": "bool" - }, - { - "name": "Show", - "type": "bool" - } - ] - }, - { - "name": "Content", - "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ], - "fields": [ - { - "name": "ID", - "type": "uint64" - }, - { - "name": "moduleID", - "type": "uint64" - }, - { - "name": "Fields", - "type": "sqlxTypes.JSONText", - "db": "json" - } + "sqlxTypes github.com/jmoiron/sqlx/types", + "github.com/crusttech/crust/crm/types" ] } ], @@ -358,7 +274,7 @@ "title": "Module Name" }, { - "type": "sqlxTypes.JSONText", + "type": "types.ModuleFieldSet", "name": "fields", "required": true, "title": "Fields JSON" @@ -482,7 +398,7 @@ "title": "Module Name" }, { - "type": "sqlxTypes.JSONText", + "type": "types.ModuleFieldSet", "name": "fields", "required": true, "title": "Fields JSON" diff --git a/api/crm/spec/field.json b/api/crm/spec/field.json index f63893c0d..a66bc619e 100644 --- a/api/crm/spec/field.json +++ b/api/crm/spec/field.json @@ -3,29 +3,7 @@ "Description": "CRM input field definitions", "Package": "crm", "Interface": "Field", - "Struct": [ - { - "fields": [ - { - "db": "field_name", - "name": "Name", - "type": "string" - }, - { - "db": "field_type", - "name": "Type", - "type": "string" - }, - { - "db": "field_template", - "name": "Template", - "omitempty": true, - "type": "string" - } - ], - "name": "Field" - } - ], + "Struct": [], "Parameters": null, "Protocol": "", "Authentication": [], diff --git a/api/crm/spec/module.json b/api/crm/spec/module.json index 3945210f7..8287993d2 100644 --- a/api/crm/spec/module.json +++ b/api/crm/spec/module.json @@ -5,72 +5,10 @@ "Interface": "Module", "Struct": [ { - "fields": [ - { - "name": "ID", - "type": "uint64" - }, - { - "name": "Name", - "type": "string" - }, - { - "db": "json", - "json": "fields", - "name": "Fields", - "type": "sqlxTypes.JSONText" - } - ], "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ], - "name": "Module" - }, - { - "fields": [ - { - "name": "Name", - "type": "string" - }, - { - "name": "Title", - "type": "string" - }, - { - "name": "Kind", - "type": "string" - }, - { - "name": "GDPR", - "type": "bool" - }, - { - "name": "Show", - "type": "bool" - } - ], - "name": "ModuleField" - }, - { - "fields": [ - { - "name": "ID", - "type": "uint64" - }, - { - "name": "moduleID", - "type": "uint64" - }, - { - "db": "json", - "name": "Fields", - "type": "sqlxTypes.JSONText" - } - ], - "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ], - "name": "Content" + "sqlxTypes github.com/jmoiron/sqlx/types", + "github.com/crusttech/crust/crm/types" + ] } ], "Parameters": null, @@ -111,7 +49,7 @@ "name": "fields", "required": true, "title": "Fields JSON", - "type": "sqlxTypes.JSONText" + "type": "types.ModuleFieldSet" } ] } @@ -235,7 +173,7 @@ "name": "fields", "required": true, "title": "Fields JSON", - "type": "sqlxTypes.JSONText" + "type": "types.ModuleFieldSet" } ] } diff --git a/crm/rest/request/module.go b/crm/rest/request/module.go index 720470412..19474e2e4 100644 --- a/crm/rest/request/module.go +++ b/crm/rest/request/module.go @@ -25,6 +25,7 @@ import ( "github.com/go-chi/chi" "github.com/pkg/errors" + "github.com/crusttech/crust/crm/types" sqlxTypes "github.com/jmoiron/sqlx/types" ) @@ -80,7 +81,7 @@ var _ RequestFiller = NewModuleList() // Module create request parameters type ModuleCreate struct { Name string - Fields sqlxTypes.JSONText + Fields types.ModuleFieldSet } func NewModuleCreate() *ModuleCreate { @@ -118,12 +119,6 @@ func (m *ModuleCreate) Fill(r *http.Request) (err error) { m.Name = val } - if val, ok := post["fields"]; ok { - - if m.Fields, err = parseJSONTextWithErr(val); err != nil { - return err - } - } return err } @@ -270,7 +265,7 @@ var _ RequestFiller = NewModuleChart() type ModuleEdit struct { ModuleID uint64 `json:",string"` Name string - Fields sqlxTypes.JSONText + Fields types.ModuleFieldSet } func NewModuleEdit() *ModuleEdit { @@ -309,12 +304,6 @@ func (m *ModuleEdit) Fill(r *http.Request) (err error) { m.Name = val } - if val, ok := post["fields"]; ok { - - if m.Fields, err = parseJSONTextWithErr(val); err != nil { - return err - } - } return err } diff --git a/crm/service/content_test.go b/crm/service/content_test.go index 80a0c519f..d1f4cdcc0 100644 --- a/crm/service/content_test.go +++ b/crm/service/content_test.go @@ -2,9 +2,10 @@ package service import ( "context" - "encoding/json" "testing" + "encoding/json" + "github.com/pkg/errors" "github.com/crusttech/crust/crm/types" @@ -32,26 +33,23 @@ func TestContent(t *testing.T) { ctx := auth.SetIdentityToContext(context.Background(), auth.NewIdentity(user.Identity())) repository := Content().With(ctx) - fields, err := json.Marshal([]types.Field{ - types.Field{ - Name: "name", - Type: "input", - }, - types.Field{ - Name: "email", - Type: "email", - }, - types.Field{ - Name: "options", - Type: "select_multi", - }, - }) - assert(t, err == nil, "Error when encoding JSON fields: %+v", err) - module := &types.Module{ Name: "Test", + Fields: []types.ModuleField{ + types.ModuleField{ + Name: "name", + Kind: "input", + }, + types.ModuleField{ + Name: "email", + Kind: "email", + }, + types.ModuleField{ + Name: "options", + Kind: "select_multi", + }, + }, } - (&module.Fields).Scan(fields) // set up a module { diff --git a/crm/service/module.go b/crm/service/module.go index 8b585809f..4a61e0261 100644 --- a/crm/service/module.go +++ b/crm/service/module.go @@ -3,6 +3,7 @@ package service import ( "context" + "github.com/pkg/errors" "github.com/titpetric/factory" "github.com/crusttech/crust/crm/repository" @@ -69,10 +70,19 @@ func (s *module) Chart(r *request.ModuleChart) (interface{}, error) { } func (s *module) Create(mod *types.Module) (*types.Module, error) { + if len(mod.Fields) == 0 { + return nil, errors.New("Error creating module: no fields") + } return s.moduleRepo.Create(mod) } func (s *module) Update(mod *types.Module) (*types.Module, error) { + if mod.ID == 0 { + return nil, errors.New("Error updating module: invalid ID") + } + if len(mod.Fields) == 0 { + return nil, errors.New("Error updating module: no fields") + } return s.moduleRepo.Update(mod) } diff --git a/crm/service/module_test.go b/crm/service/module_test.go index 766df3db5..a79780e6f 100644 --- a/crm/service/module_test.go +++ b/crm/service/module_test.go @@ -2,7 +2,6 @@ package service import ( "context" - "encoding/json" "testing" "github.com/crusttech/crust/crm/types" @@ -11,31 +10,28 @@ import ( func TestModule(t *testing.T) { repository := Module().With(context.Background()) - fields, err := json.Marshal([]types.Field{ - types.Field{ - Name: "name", - Type: "input", - }, - types.Field{ - Name: "email", - Type: "email", - }, - types.Field{ - Name: "options", - Type: "select_multi", - }, - types.Field{ - Name: "description", - Type: "text", - }, - }) - assert(t, err == nil, "Error when encoding JSON fields: %+v", err) - // the module object we're working with module := &types.Module{ Name: "Test", + Fields: []types.ModuleField{ + types.ModuleField{ + Name: "name", + Kind: "input", + }, + types.ModuleField{ + Name: "email", + Kind: "email", + }, + types.ModuleField{ + Name: "options", + Kind: "select_multi", + }, + types.ModuleField{ + Name: "description", + Kind: "text", + }, + }, } - (&module.Fields).Scan(fields) prevModuleCount := 0 @@ -57,6 +53,7 @@ func TestModule(t *testing.T) { assert(t, err == nil, "Error when retrieving module by id: %+v", err) assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID) assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name) + assert(t, len(ms.Fields) == 4, "Expected Fields count from database to match, 4 != %d", len(ms.Fields)) } // update created module diff --git a/docs/crm/README.md b/docs/crm/README.md index ad8110add..636870319 100644 --- a/docs/crm/README.md +++ b/docs/crm/README.md @@ -63,7 +63,7 @@ CRM module definitions | Parameter | Type | Method | Description | Default | Required? | | --------- | ---- | ------ | ----------- | ------- | --------- | | name | string | POST | Module Name | N/A | YES | -| fields | sqlxTypes.JSONText | POST | Fields JSON | N/A | YES | +| fields | types.ModuleFieldSet | POST | Fields JSON | N/A | YES | ## Read module @@ -302,7 +302,7 @@ Example bar chart with number of leads per country: select lead.country from lea | --------- | ---- | ------ | ----------- | ------- | --------- | | moduleID | uint64 | PATH | Module ID | N/A | YES | | name | string | POST | Module Name | N/A | YES | -| fields | sqlxTypes.JSONText | POST | Fields JSON | N/A | YES | +| fields | types.ModuleFieldSet | POST | Fields JSON | N/A | YES | ## Delete module