Commit 087f8fb21c3934f226d485880456fa7db4966c83

Authored by Marko Tikvić
1 parent a205e8f40d
Exists in master and in 1 other branch v2

expanded list config with live graph

Showing 2 changed files with 55 additions and 21 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "encoding/json" 5 "encoding/json"
6 "errors" 6 "errors"
7 "fmt" 7 "fmt"
8 "io" 8 "io"
9 "net/http" 9 "net/http"
10 "sync" 10 "sync"
11 "time" 11 "time"
12 12
13 "git.to-net.rs/marko.tikvic/gologger" 13 "git.to-net.rs/marko.tikvic/gologger"
14 ) 14 )
15 15
16 var ( 16 var (
17 mu = &sync.Mutex{} 17 mu = &sync.Mutex{}
18 metadata = make(map[string]Payload) 18 metadata = make(map[string]Payload)
19 updateQue = make(map[string][]byte) 19 updateQue = make(map[string][]byte)
20 20
21 metadataDB *sql.DB 21 metadataDB *sql.DB
22 activeProject string 22 activeProject string
23 23
24 inited bool 24 inited bool
25 driver string 25 driver string
26 ) 26 )
27 27
28 var logger *gologger.Logger 28 var logger *gologger.Logger
29 29
30 func init() { 30 func init() {
31 var err error 31 var err error
32 logger, err = gologger.New("webutility", gologger.MaxLogSize100KB) 32 logger, err = gologger.New("webutility", gologger.MaxLogSize100KB)
33 if err != nil { 33 if err != nil {
34 fmt.Printf("webutility: %s\n", err.Error()) 34 fmt.Printf("webutility: %s\n", err.Error())
35 } 35 }
36 } 36 }
37 37
38 type LangMap map[string]map[string]string 38 type LangMap map[string]map[string]string
39 39
40 type Field struct { 40 type Field struct {
41 Parameter string `json:"param"` 41 Parameter string `json:"param"`
42 Type string `json:"type"` 42 Type string `json:"type"`
43 Visible bool `json:"visible"` 43 Visible bool `json:"visible"`
44 Editable bool `json:"editable"` 44 Editable bool `json:"editable"`
45 } 45 }
46 46
47 type CorrelationField struct { 47 type CorrelationField struct {
48 Result string `json:"result"` 48 Result string `json:"result"`
49 Elements []string `json:"elements"` 49 Elements []string `json:"elements"`
50 Type string `json:"type"` 50 Type string `json:"type"`
51 } 51 }
52 52
53 type Translation struct { 53 type Translation struct {
54 Language string `json:"language"` 54 Language string `json:"language"`
55 FieldsLabels map[string]string `json:"fieldsLabels"` 55 FieldsLabels map[string]string `json:"fieldsLabels"`
56 } 56 }
57 57
58 type Payload struct { 58 type Payload struct {
59 Method string `json:"method"` 59 Method string `json:"method"`
60 Params map[string]string `json:"params"` 60 Params map[string]string `json:"params"`
61 Lang []Translation `json:"lang"` 61 Lang []Translation `json:"lang"`
62 Fields []Field `json:"fields"` 62 Fields []Field `json:"fields"`
63 Correlations []CorrelationField `json:"correlationFields"` 63 Correlations []CorrelationField `json:"correlationFields"`
64 IdField string `json:"idField"` 64 IdField string `json:"idField"`
65 65
66 // Data holds JSON payload. 66 // Data holds JSON payload.
67 // It can't be used for itteration. 67 // It can't be used for itteration.
68 Data interface{} `json:"data"` 68 Data interface{} `json:"data"`
69 } 69 }
70 70
71 // NewPayload returs a payload sceleton for entity described with etype. 71 // NewPayload returs a payload sceleton for entity described with etype.
72 func NewPayload(r *http.Request, etype string) Payload { 72 func NewPayload(r *http.Request, etype string) Payload {
73 pload := metadata[etype] 73 pload := metadata[etype]
74 pload.Method = r.Method + " " + r.RequestURI 74 pload.Method = r.Method + " " + r.RequestURI
75 return pload 75 return pload
76 } 76 }
77 77
78 // DecodeJSON decodes JSON data from r to v. 78 // DecodeJSON decodes JSON data from r to v.
79 // Returns an error if it fails. 79 // Returns an error if it fails.
80 func DecodeJSON(r io.Reader, v interface{}) error { 80 func DecodeJSON(r io.Reader, v interface{}) error {
81 return json.NewDecoder(r).Decode(v) 81 return json.NewDecoder(r).Decode(v)
82 } 82 }
83 83
84 // InitPayloadsMetadata loads all payloads' information into 'metadata' variable. 84 // InitPayloadsMetadata loads all payloads' information into 'metadata' variable.
85 func InitPayloadsMetadata(drv string, db *sql.DB, project string) error { 85 func InitPayloadsMetadata(drv string, db *sql.DB, project string) error {
86 if drv != "ora" && drv != "mysql" { 86 if drv != "ora" && drv != "mysql" {
87 return errors.New("driver not supported") 87 return errors.New("driver not supported")
88 } 88 }
89 driver = drv 89 driver = drv
90 metadataDB = db 90 metadataDB = db
91 activeProject = project 91 activeProject = project
92 92
93 mu.Lock() 93 mu.Lock()
94 defer mu.Unlock() 94 defer mu.Unlock()
95 err := initMetadata(project) 95 err := initMetadata(project)
96 if err != nil { 96 if err != nil {
97 return err 97 return err
98 } 98 }
99 inited = true 99 inited = true
100 100
101 return nil 101 return nil
102 } 102 }
103 103
104 func EnableHotloading(interval int) { 104 func EnableHotloading(interval int) {
105 if interval > 0 { 105 if interval > 0 {
106 go hotload(interval) 106 go hotload(interval)
107 } 107 }
108 } 108 }
109 109
110 func GetMetadataForAllEntities() map[string]Payload { 110 func GetMetadataForAllEntities() map[string]Payload {
111 return metadata 111 return metadata
112 } 112 }
113 113
114 func GetMetadataForEntity(t string) (Payload, bool) { 114 func GetMetadataForEntity(t string) (Payload, bool) {
115 p, ok := metadata[t] 115 p, ok := metadata[t]
116 return p, ok 116 return p, ok
117 } 117 }
118 118
119 func QueEntityModelUpdate(entityType string, v interface{}) { 119 func QueEntityModelUpdate(entityType string, v interface{}) {
120 updateQue[entityType], _ = json.Marshal(v) 120 updateQue[entityType], _ = json.Marshal(v)
121 } 121 }
122 122
123 func initMetadata(project string) error { 123 func initMetadata(project string) error {
124 rows, err := metadataDB.Query(`select 124 rows, err := metadataDB.Query(`select
125 entity_type, 125 entity_type,
126 metadata 126 metadata
127 from entities 127 from entities
128 where projekat = ` + fmt.Sprintf("'%s'", project)) 128 where projekat = ` + fmt.Sprintf("'%s'", project))
129 if err != nil { 129 if err != nil {
130 return err 130 return err
131 } 131 }
132 defer rows.Close() 132 defer rows.Close()
133 133
134 count := 0 134 count := 0
135 success := 0 135 success := 0
136 if len(metadata) > 0 { 136 if len(metadata) > 0 {
137 metadata = nil 137 metadata = nil
138 } 138 }
139 metadata = make(map[string]Payload) 139 metadata = make(map[string]Payload)
140 for rows.Next() { 140 for rows.Next() {
141 var name, load string 141 var name, load string
142 rows.Scan(&name, &load) 142 rows.Scan(&name, &load)
143 143
144 p := Payload{} 144 p := Payload{}
145 err := json.Unmarshal([]byte(load), &p) 145 err := json.Unmarshal([]byte(load), &p)
146 if err != nil { 146 if err != nil {
147 logger.Log("webutility: couldn't init: '%s' metadata: %s\n%s\n", name, err.Error(), load) 147 logger.Log("webutility: couldn't init: '%s' metadata: %s\n%s\n", name, err.Error(), load)
148 } else { 148 } else {
149 success++ 149 success++
150 metadata[name] = p 150 metadata[name] = p
151 } 151 }
152 count++ 152 count++
153 } 153 }
154 perc := float32(success/count) * 100.0 154 perc := float32(success/count) * 100.0
155 logger.Log("webutility: loaded %d/%d (%.1f%%) entities\n", success, count, perc) 155 logger.Log("webutility: loaded %d/%d (%.1f%%) entities\n", success, count, perc)
156 156
157 return nil 157 return nil
158 } 158 }
159 159
160 func hotload(n int) { 160 func hotload(n int) {
161 entityScan := make(map[string]int64) 161 entityScan := make(map[string]int64)
162 firstCheck := true 162 firstCheck := true
163 for { 163 for {
164 time.Sleep(time.Duration(n) * time.Second) 164 time.Sleep(time.Duration(n) * time.Second)
165 rows, err := metadataDB.Query(`select 165 rows, err := metadataDB.Query(`select
166 ora_rowscn, 166 ora_rowscn,
167 entity_type 167 entity_type
168 from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) 168 from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject))
169 if err != nil { 169 if err != nil {
170 logger.Log("webutility: hotload failed: %v\n", err) 170 logger.Log("webutility: hotload failed: %v\n", err)
171 time.Sleep(time.Duration(n) * time.Second) 171 time.Sleep(time.Duration(n) * time.Second)
172 continue 172 continue
173 } 173 }
174 174
175 var toRefresh []string 175 var toRefresh []string
176 for rows.Next() { 176 for rows.Next() {
177 var scanID int64 177 var scanID int64
178 var entity string 178 var entity string
179 rows.Scan(&scanID, &entity) 179 rows.Scan(&scanID, &entity)
180 oldID, ok := entityScan[entity] 180 oldID, ok := entityScan[entity]
181 if !ok || oldID != scanID { 181 if !ok || oldID != scanID {
182 entityScan[entity] = scanID 182 entityScan[entity] = scanID
183 toRefresh = append(toRefresh, entity) 183 toRefresh = append(toRefresh, entity)
184 } 184 }
185 } 185 }
186 rows.Close() 186 rows.Close()
187 187
188 if rows.Err() != nil { 188 if rows.Err() != nil {
189 logger.Log("webutility: hotload rset error: %v\n", rows.Err()) 189 logger.Log("webutility: hotload rset error: %v\n", rows.Err())
190 time.Sleep(time.Duration(n) * time.Second) 190 time.Sleep(time.Duration(n) * time.Second)
191 continue 191 continue
192 } 192 }
193 193
194 if len(toRefresh) > 0 && !firstCheck { 194 if len(toRefresh) > 0 && !firstCheck {
195 mu.Lock() 195 mu.Lock()
196 refreshMetadata(toRefresh) 196 refreshMetadata(toRefresh)
197 mu.Unlock() 197 mu.Unlock()
198 } 198 }
199 if firstCheck { 199 if firstCheck {
200 firstCheck = false 200 firstCheck = false
201 } 201 }
202 } 202 }
203 } 203 }
204 204
205 func refreshMetadata(entities []string) { 205 func refreshMetadata(entities []string) {
206 for _, e := range entities { 206 for _, e := range entities {
207 fmt.Printf("refreshing %s\n", e) 207 fmt.Printf("refreshing %s\n", e)
208 rows, err := metadataDB.Query(`select 208 rows, err := metadataDB.Query(`select
209 metadata 209 metadata
210 from entities 210 from entities
211 where projekat = ` + fmt.Sprintf("'%s'", activeProject) + 211 where projekat = ` + fmt.Sprintf("'%s'", activeProject) +
212 ` and entity_type = ` + fmt.Sprintf("'%s'", e)) 212 ` and entity_type = ` + fmt.Sprintf("'%s'", e))
213 213
214 if err != nil { 214 if err != nil {
215 logger.Log("webutility: refresh: prep: %v\n", err) 215 logger.Log("webutility: refresh: prep: %v\n", err)
216 rows.Close() 216 rows.Close()
217 continue 217 continue
218 } 218 }
219 219
220 for rows.Next() { 220 for rows.Next() {
221 var load string 221 var load string
222 rows.Scan(&load) 222 rows.Scan(&load)
223 p := Payload{} 223 p := Payload{}
224 err := json.Unmarshal([]byte(load), &p) 224 err := json.Unmarshal([]byte(load), &p)
225 if err != nil { 225 if err != nil {
226 logger.Log("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) 226 logger.Log("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load)
227 } else { 227 } else {
228 metadata[e] = p 228 metadata[e] = p
229 } 229 }
230 } 230 }
231 rows.Close() 231 rows.Close()
232 } 232 }
233 } 233 }
234 234
235 func UpdateEntityModels(command string) (total, upd, add int, err error) { 235 func UpdateEntityModels(command string) (total, upd, add int, err error) {
236 if command != "force" && command != "missing" { 236 if command != "force" && command != "missing" {
237 return total, 0, 0, errors.New("webutility: unknown command: " + command) 237 return total, 0, 0, errors.New("webutility: unknown command: " + command)
238 } 238 }
239 239
240 if !inited { 240 if !inited {
241 return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried.") 241 return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried.")
242 } 242 }
243 243
244 total = len(updateQue) 244 total = len(updateQue)
245 245
246 forUpdate := make([]string, 0) 246 toUpdate := make([]string, 0)
247 forAdd := make([]string, 0) 247 toAdd := make([]string, 0)
248 248
249 for k, _ := range updateQue { 249 for k, _ := range updateQue {
250 if _, exists := metadata[k]; exists { 250 if _, exists := metadata[k]; exists {
251 if command == "force" { 251 if command == "force" {
252 forUpdate = append(forUpdate, k) 252 toUpdate = append(toUpdate, k)
253 } 253 }
254 } else { 254 } else {
255 forAdd = append(forAdd, k) 255 toAdd = append(toAdd, k)
256 } 256 }
257 } 257 }
258 258
259 var uStmt *sql.Stmt 259 var uStmt *sql.Stmt
260 if driver == "ora" { 260 if driver == "ora" {
261 uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2") 261 uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2")
262 if err != nil { 262 if err != nil {
263 return 263 return
264 } 264 }
265 } else if driver == "mysql" { 265 } else if driver == "mysql" {
266 uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?") 266 uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?")
267 if err != nil { 267 if err != nil {
268 return 268 return
269 } 269 }
270 } 270 }
271 for _, k := range forUpdate { 271 for _, k := range toUpdate {
272 //fmt.Printf("Updating: %s\n", k)
273 //fmt.Printf("New model: %s\n", updateQue[k])
272 _, err = uStmt.Exec(string(updateQue[k]), k) 274 _, err = uStmt.Exec(string(updateQue[k]), k)
273 if err != nil { 275 if err != nil {
274 logger.Log("webutility: %v\n", err) 276 logger.Log("webutility: %v\n", err)
275 return 277 return
276 } 278 }
277 upd++ 279 upd++
278 } 280 }
279 281
280 blankPayload, _ := json.Marshal(Payload{}) 282 blankPayload, _ := json.Marshal(Payload{})
281 var iStmt *sql.Stmt 283 var iStmt *sql.Stmt
282 if driver == "ora" { 284 if driver == "ora" {
283 iStmt, err = metadataDB.Prepare("INSERT INTO ENTITIES(PROJEKAT, METADATA, ENTITY_TYPE, ENTITY_MODEL) VALUES(:1, :2, :3, :4)") 285 iStmt, err = metadataDB.Prepare("INSERT INTO ENTITIES(PROJEKAT, METADATA, ENTITY_TYPE, ENTITY_MODEL) VALUES(:1, :2, :3, :4)")
284 if err != nil { 286 if err != nil {
285 return 287 return
286 } 288 }
287 } else if driver == "mysql" { 289 } else if driver == "mysql" {
288 iStmt, err = metadataDB.Prepare("INSERT INTO ENTITIES(PROJEKAT, METADATA, ENTITY_TYPE, ENTITY_MODEL) VALUES(?, ?, ?, ?)") 290 iStmt, err = metadataDB.Prepare("INSERT INTO ENTITIES(PROJEKAT, METADATA, ENTITY_TYPE, ENTITY_MODEL) VALUES(?, ?, ?, ?)")
289 if err != nil { 291 if err != nil {
290 return 292 return
291 } 293 }
292 } 294 }
293 for _, k := range forAdd { 295 for _, k := range toAdd {
294 _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k])) 296 _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k]))
295 if err != nil { 297 if err != nil {
296 logger.Log("webutility: %v\n", err) 298 logger.Log("webutility: %v\n", err)
297 return 299 return
298 } 300 }
299 metadata[k] = Payload{} 301 metadata[k] = Payload{}
300 add++ 302 add++
301 } 303 }
302 304
303 return total, upd, add, nil 305 return total, upd, add, nil
304 } 306 }
305 307
306 /* 308 /*
307 func ModifyMetadataForEntity(entityType string, p *Payload) error { 309 func ModifyMetadataForEntity(entityType string, p *Payload) error {
308 md, err := json.Marshal(*p) 310 md, err := json.Marshal(*p)
309 if err != nil { 311 if err != nil {
310 return err 312 return err
311 } 313 }
312 314
313 mu.Lock() 315 mu.Lock()
314 defer mu.Unlock() 316 defer mu.Unlock()
315 _, err = metadataDB.PrepAndExe(`update entities set 317 _, err = metadataDB.PrepAndExe(`update entities set
316 metadata = :1 318 metadata = :1
317 where projekat = :2 319 where projekat = :2
318 and entity_type = :3`, 320 and entity_type = :3`,
319 string(md), 321 string(md),
320 activeProject, 322 activeProject,
321 entityType) 323 entityType)
322 if err != nil { 324 if err != nil {
323 return err 325 return err
324 } 326 }
325 return nil 327 return nil
326 } 328 }
327 329
328 func DeleteEntityModel(entityType string) error { 330 func DeleteEntityModel(entityType string) error {
329 _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) 331 _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType)
330 if err == nil { 332 if err == nil {
331 mu.Lock() 333 mu.Lock()
332 delete(metadata, entityType) 334 delete(metadata, entityType)
333 mu.Unlock() 335 mu.Unlock()
334 } 336 }
335 return err 337 return err
336 } 338 }
337 */ 339 */
338 340
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 ) 6 )
7 7
8 type ListOptions struct { 8 type ListOptions struct {
9 GlobalFilter bool `json:"globalFilter"` 9 GlobalFilter bool `json:"globalFilter"`
10 LocalFilters bool `json:"localFilters"` 10 LocalFilters bool `json:"localFilters"`
11 RemoteFilters bool `json:"remoteFilters"` 11 RemoteFilters bool `json:"remoteFilters"`
12 Pagination bool `json:"pagination"` 12 Pagination bool `json:"pagination"`
13 PageSize uint32 `json:"pageSize"` 13 PageSize uint32 `json:"pageSize"`
14 Pivot bool `json:"pivot"` 14 Pivot bool `json:"pivot"`
15 Detail bool `json:"detail"` 15 Detail bool `json:"detail"`
16 Total bool `json:"total"` 16 Total bool `json:"total"`
17 } 17 }
18 18
19 type ListFilter struct { 19 type ListFilter struct {
20 Position uint32 `json:"-"` 20 Position uint32 `json:"-"`
21 ObjectType string `json:"-"` 21 ObjectType string `json:"-"`
22 FiltersField string `json:"filtersField"` 22 FiltersField string `json:"filtersField"`
23 DefaultValues string `json:"defaultValues"` 23 DefaultValues string `json:"defaultValues"`
24 FiltersType string `json:"filtersType"` 24 FiltersType string `json:"filtersType"`
25 FiltersLabel string `json:"filtersLabel"` 25 FiltersLabel string `json:"filtersLabel"`
26 DropdownConfig Dropdown `json:"dropdownConfig"` 26 DropdownConfig Dropdown `json:"dropdownConfig"`
27 } 27 }
28 28
29 type Dropdown struct { 29 type Dropdown struct {
30 ObjectType string `json:"objectType"` 30 ObjectType string `json:"objectType"`
31 FiltersField string `json:"filtersField"` 31 FiltersField string `json:"filtersField"`
32 IDField string `json:"idField"` 32 IDField string `json:"idField"`
33 LabelField string `json:"labelField"` 33 LabelField string `json:"labelField"`
34 } 34 }
35 35
36 type ListGraph struct { 36 type ListGraph struct {
37 ObjectType string `json:"objectType"` 37 ObjectType string `json:"objectType"`
38 X string `json:"xField"` 38 X string `json:"xField"`
39 Y string `json:"yField"` 39 Y string `json:"yField"`
40 GroupField string `json:"groupField"` 40 GroupField string `json:"groupField"`
41 Label string `json:"label"` 41 Label string `json:"label"`
42 } 42 }
43 43
44 type ListActions struct { 44 type ListActions struct {
45 Create bool `json:"create"` 45 Create bool `json:"create"`
46 Update bool `json:"update"` 46 Update bool `json:"update"`
47 Delete bool `json:"delete"` 47 Delete bool `json:"delete"`
48 Export bool `json:"export"` 48 Export bool `json:"export"`
49 Print bool `json:"print"` 49 Print bool `json:"print"`
50 Graph bool `json:"graph"` 50 Graph bool `json:"graph"`
51 LiveGraph bool `json:"liveGraph"`
51 } 52 }
52 53
53 type ListNavNode struct { 54 type ListNavNode struct {
54 ObjectType string `json:"objectType"` 55 ObjectType string `json:"objectType"`
55 LabelField string `json:"label"` 56 LabelField string `json:"label"`
56 Icon string `json:"icon"` 57 Icon string `json:"icon"`
57 ParentObjectType string `json:"parentObjectType"` 58 ParentObjectType string `json:"parentObjectType"`
58 ParentIDField string `json:"parentIdField"` 59 ParentIDField string `json:"parentIdField"`
59 ParentFilterField string `json:"parentFilterField"` 60 ParentFilterField string `json:"parentFilterField"`
60 } 61 }
61 62
62 type ListParentNode struct { 63 type ListParentNode struct {
63 ObjectType string `json:"objectType"` 64 ObjectType string `json:"objectType"`
64 LabelField string `json:"labelField"` 65 LabelField string `json:"labelField"`
65 FilterField string `json:"filterField"` 66 FilterField string `json:"filterField"`
66 } 67 }
67 68
68 type ListPivot struct { 69 type ListPivot struct {
69 ObjectType string `json:"objectType"` 70 ObjectType string `json:"objectType"`
70 GroupField string `json:"groupField"` 71 GroupField string `json:"groupField"`
71 DistinctField string `json:"distinctField"` 72 DistinctField string `json:"distinctField"`
72 Value string `json:"valueField"` 73 Value string `json:"valueField"`
73 } 74 }
74 75
75 type ListDetails struct { 76 type ListDetails struct {
76 ObjectType string `json:"objectType"` 77 ObjectType string `json:"objectType"`
77 ParentObjectType string `json:"parentObjectType"` 78 ParentObjectType string `json:"parentObjectType"`
78 ParentFilterField string `json:"parentFilterField"` 79 ParentFilterField string `json:"parentFilterField"`
79 SingleDetail bool `json:"singleDetail"` 80 SingleDetail bool `json:"singleDetail"`
80 } 81 }
81 82
83 type ListLiveGraph struct {
84 ObjectType string `json:"objectType"`
85 ValueFields string `json:"valueFields"`
86 LabelFields string `json:"labelFields"`
87 }
88
82 type ListConfig struct { 89 type ListConfig struct {
83 ObjectType string `json:"objectType"` 90 ObjectType string `json:"objectType"`
84 Title string `json:"title"` 91 Title string `json:"title"`
85 LazyLoad bool `json:"lazyLoad"` 92 LazyLoad bool `json:"lazyLoad"`
86 InlineEdit bool `json:"inlineEdit"` 93 InlineEdit bool `json:"inlineEdit"`
87 Options ListOptions `json:"options"` 94 Options ListOptions `json:"options"`
88 Filters []ListFilter `json:"defaultFilters"` 95 Filters []ListFilter `json:"defaultFilters"`
89 Graphs []ListGraph `json:"graphs"` 96 Graphs []ListGraph `json:"graphs"`
90 Actions ListActions `json:"actions"` 97 Actions ListActions `json:"actions"`
91 Parent []ListParentNode `json:"parent"` 98 Parent []ListParentNode `json:"parent"`
92 Navigation []ListNavNode `json:"navigation"` 99 Navigation []ListNavNode `json:"navigation"`
93 Pivots []ListPivot `json:"pivots"` 100 Pivots []ListPivot `json:"pivots"`
94 Details ListDetails `json:"details"` 101 Details ListDetails `json:"details"`
102 LiveGraph ListLiveGraph `json:"liveGraphs"`
95 } 103 }
96 104
97 // GetListConfig returns list configuration for the provided object type for the front-end application 105 // GetListConfig returns list configuration for the provided object type for the front-end application
98 // or an error if it fails. 106 // or an error if it fails.
99 func GetListConfig(db *sql.DB, objType string) (ListConfig, error) { 107 func GetListConfig(db *sql.DB, objType string) (ListConfig, error) {
100 resp := newDefaultList(objType) 108 resp := newDefaultList(objType)
101 var err error 109 var err error
102 110
103 err = setListParams(db, &resp, objType) 111 err = setListParams(db, &resp, objType)
104 resp.Navigation, err = getListNavigation(db, objType) 112 resp.Navigation, err = getListNavigation(db, objType)
105 resp.Actions, err = getListActions(db, objType) 113 resp.Actions, err = getListActions(db, objType)
106 resp.Filters, err = getListFilters(db, objType) 114 resp.Filters, err = getListFilters(db, objType)
107 resp.Options, err = getListOptions(db, objType) 115 resp.Options, err = getListOptions(db, objType)
108 resp.Parent, err = getListParent(db, objType) 116 resp.Parent, err = getListParent(db, objType)
109 resp.Graphs, err = getListGraph(db, objType) 117 resp.Graphs, err = getListGraph(db, objType)
110 resp.Pivots, err = getListPivot(db, objType) 118 resp.Pivots, err = getListPivot(db, objType)
111 resp.Details, err = getListDetails(db, objType) 119 resp.Details, err = getListDetails(db, objType)
120 resp.LiveGraph, err = getListLiveGraph(db, objType)
112 121
113 if err != nil { 122 if err != nil {
114 return ListConfig{}, err 123 return ListConfig{}, err
115 } 124 }
116 125
117 return resp, nil 126 return resp, nil
118 } 127 }
119 128
120 // GetListConfigObjectIDField takes in database connection and an object type and it returns the 129 // GetListConfigObjectIDField takes in database connection and an object type and it returns the
121 // ID field name for the provided object type. 130 // ID field name for the provided object type.
122 func GetListConfigObjectIDField(db *sql.DB, otype string) string { 131 func GetListConfigObjectIDField(db *sql.DB, otype string) string {
123 var resp string 132 var resp string
124 133
125 rows, err := db.Query(`SELECT 134 rows, err := db.Query(`SELECT
126 ID_FIELD 135 ID_FIELD
127 FROM LIST_CONFIG_ID_FIELD 136 FROM LIST_CONFIG_ID_FIELD
128 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", otype)) 137 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", otype))
129 if err != nil { 138 if err != nil {
130 return "" 139 return ""
131 } 140 }
132 defer rows.Close() 141 defer rows.Close()
133 142
134 if rows.Next() { 143 if rows.Next() {
135 rows.Scan(&resp) 144 rows.Scan(&resp)
136 } 145 }
137 146
138 if rows.Err() != nil { 147 if rows.Err() != nil {
139 return "" 148 return ""
140 } 149 }
141 150
142 return resp 151 return resp
143 } 152 }
144 153
145 // newDefaultList returns default configuration for the provided object type. 154 // newDefaultList returns default configuration for the provided object type.
146 func newDefaultList(objType string) ListConfig { 155 func newDefaultList(objType string) ListConfig {
147 list := ListConfig{ 156 list := ListConfig{
148 ObjectType: objType, 157 ObjectType: objType,
149 Title: objType, 158 Title: objType,
150 LazyLoad: false, 159 LazyLoad: false,
151 Options: ListOptions{ 160 Options: ListOptions{
152 GlobalFilter: true, 161 GlobalFilter: true,
153 LocalFilters: true, 162 LocalFilters: true,
154 RemoteFilters: false, 163 RemoteFilters: false,
155 Pagination: true, 164 Pagination: true,
156 PageSize: 20, 165 PageSize: 20,
157 }, 166 },
158 Filters: nil, 167 Filters: nil,
159 Actions: ListActions{ 168 Actions: ListActions{
160 Create: false, 169 Create: false,
161 Update: false, 170 Update: false,
162 Delete: false, 171 Delete: false,
163 Export: false, 172 Export: false,
164 Print: false, 173 Print: false,
165 Graph: false, 174 Graph: false,
175 LiveGraph: false,
166 }, 176 },
167 Parent: nil, 177 Parent: nil,
168 Navigation: nil, 178 Navigation: nil,
169 } 179 }
170 180
171 return list 181 return list
172 } 182 }
173 183
174 // setListParams sets the default parameters of the provided configuration list for the provided object type. 184 // setListParams sets the default parameters of the provided configuration list for the provided object type.
175 func setListParams(db *sql.DB, list *ListConfig, objType string) error { 185 func setListParams(db *sql.DB, list *ListConfig, objType string) error {
176 rows, err := db.Query(`SELECT 186 rows, err := db.Query(`SELECT
177 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT 187 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT
178 FROM LIST_CONFIG 188 FROM LIST_CONFIG
179 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 189 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
180 if err != nil { 190 if err != nil {
181 return err 191 return err
182 } 192 }
183 defer rows.Close() 193 defer rows.Close()
184 if rows.Next() { 194 if rows.Next() {
185 otype, title := "", "" 195 otype, title := "", ""
186 lazyLoad, inlineEdit := 0, 0 196 lazyLoad, inlineEdit := 0, 0
187 rows.Scan(&otype, &title, &lazyLoad, &inlineEdit) 197 rows.Scan(&otype, &title, &lazyLoad, &inlineEdit)
188 198
189 if otype != "" { 199 if otype != "" {
190 list.ObjectType = otype 200 list.ObjectType = otype
191 } 201 }
192 if title != "" { 202 if title != "" {
193 list.Title = title 203 list.Title = title
194 } 204 }
195 list.LazyLoad = lazyLoad != 0 205 list.LazyLoad = lazyLoad != 0
196 list.InlineEdit = inlineEdit != 0 206 list.InlineEdit = inlineEdit != 0
197 } 207 }
198 if rows.Err() != nil { 208 if rows.Err() != nil {
199 return rows.Err() 209 return rows.Err()
200 } 210 }
201 return nil 211 return nil
202 } 212 }
203 213
204 // getListNavigation returns list navigation node slice for the provided objectType. 214 // getListNavigation returns list navigation node slice for the provided objectType.
205 func getListNavigation(db *sql.DB, listObjType string) ([]ListNavNode, error) { 215 func getListNavigation(db *sql.DB, listObjType string) ([]ListNavNode, error) {
206 resp := make([]ListNavNode, 0) 216 resp := make([]ListNavNode, 0)
207 rows, err := db.Query(`SELECT 217 rows, err := db.Query(`SELECT
208 a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD 218 a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD
209 FROM LIST_CONFIG_NAVIGATION b 219 FROM LIST_CONFIG_NAVIGATION b
210 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID 220 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID
211 WHERE b.LIST_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", listObjType) + 221 WHERE b.LIST_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", listObjType) +
212 ` ORDER BY b.RB ASC`) 222 ` ORDER BY b.RB ASC`)
213 if err != nil { 223 if err != nil {
214 return resp, err 224 return resp, err
215 } 225 }
216 defer rows.Close() 226 defer rows.Close()
217 227
218 var node ListNavNode 228 var node ListNavNode
219 for rows.Next() { 229 for rows.Next() {
220 rows.Scan(&node.ObjectType, &node.ParentObjectType, &node.LabelField, &node.Icon, 230 rows.Scan(&node.ObjectType, &node.ParentObjectType, &node.LabelField, &node.Icon,
221 &node.ParentFilterField, &node.ParentIDField) 231 &node.ParentFilterField, &node.ParentIDField)
222 resp = append(resp, node) 232 resp = append(resp, node)
223 } 233 }
224 if rows.Err() != nil { 234 if rows.Err() != nil {
225 return nil, rows.Err() 235 return nil, rows.Err()
226 } 236 }
227 237
228 return resp, nil 238 return resp, nil
229 } 239 }
230 240
231 // getListActions returns list actions for the provided object type. 241 // getListActions returns list actions for the provided object type.
232 func getListActions(db *sql.DB, objType string) (ListActions, error) { 242 func getListActions(db *sql.DB, objType string) (ListActions, error) {
233 var resp ListActions 243 var resp ListActions
234 rows, err := db.Query(`SELECT 244 rows, err := db.Query(`SELECT
235 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT, 245 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT,
236 ACTION_PRINT, ACTION_GRAPH 246 ACTION_PRINT, ACTION_GRAPH, ACTION_LIVE_GRAPH
237 FROM LIST_CONFIG 247 FROM LIST_CONFIG
238 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 248 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
239 if err != nil { 249 if err != nil {
240 return ListActions{}, err 250 return ListActions{}, err
241 } 251 }
242 defer rows.Close() 252 defer rows.Close()
243 253
244 var create, update, delete, export, print, graph uint32 254 var create, update, delete, export, print, graph, liveGraph uint32
245 if rows.Next() { 255 if rows.Next() {
246 rows.Scan(&create, &update, &delete, &export, &print, &graph) 256 rows.Scan(&create, &update, &delete, &export, &print, &graph, &liveGraph)
247 resp.Create = create != 0 257 resp.Create = create != 0
248 resp.Update = update != 0 258 resp.Update = update != 0
249 resp.Delete = delete != 0 259 resp.Delete = delete != 0
250 resp.Export = export != 0 260 resp.Export = export != 0
251 resp.Print = print != 0 261 resp.Print = print != 0
252 resp.Graph = graph != 0 262 resp.Graph = graph != 0
263 resp.LiveGraph = liveGraph != 0
253 } 264 }
254 if rows.Err() != nil { 265 if rows.Err() != nil {
255 return ListActions{}, rows.Err() 266 return ListActions{}, rows.Err()
256 } 267 }
257 return resp, nil 268 return resp, nil
258 } 269 }
259 270
260 // getListFiters returns list filter slice for the provided object type. 271 // getListFiters returns list filter slice for the provided object type.
261 func getListFilters(db *sql.DB, objType string) ([]ListFilter, error) { 272 func getListFilters(db *sql.DB, objType string) ([]ListFilter, error) {
262 resp := make([]ListFilter, 0) 273 resp := make([]ListFilter, 0)
263 filtersFields, err := getFilterFieldsAndPosition(db, objType) 274 filtersFields, err := getFilterFieldsAndPosition(db, objType)
264 if err != nil { 275 if err != nil {
265 return nil, err 276 return nil, err
266 } 277 }
267 for field, pos := range filtersFields { 278 for field, pos := range filtersFields {
268 filters, _ := getFiltersByFilterField(db, field) 279 filters, _ := getFiltersByFilterField(db, field)
269 for _, filter := range filters { 280 for _, filter := range filters {
270 var f ListFilter 281 var f ListFilter
271 f.Position = pos 282 f.Position = pos
272 f.ObjectType = objType 283 f.ObjectType = objType
273 f.FiltersField = field 284 f.FiltersField = field
274 f.DefaultValues = filter.DefaultValues 285 f.DefaultValues = filter.DefaultValues
275 f.FiltersLabel = filter.Label 286 f.FiltersLabel = filter.Label
276 f.FiltersType = filter.Type 287 f.FiltersType = filter.Type
277 if filter.Type == "dropdown" { 288 if filter.Type == "dropdown" {
278 f.DropdownConfig, err = getFilterDropdownConfig(db, field) 289 f.DropdownConfig, err = getFilterDropdownConfig(db, field)
279 if err != nil { 290 if err != nil {
280 return nil, err 291 return nil, err
281 } 292 }
282 } 293 }
283 resp = append(resp, f) 294 resp = append(resp, f)
284 } 295 }
285 } 296 }
286 297
287 sortFilters(resp) 298 sortFilters(resp)
288 299
289 return resp, nil 300 return resp, nil
290 } 301 }
291 302
292 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu. 303 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu.
293 func getFilterFieldsAndPosition(db *sql.DB, objType string) (map[string]uint32, error) { 304 func getFilterFieldsAndPosition(db *sql.DB, objType string) (map[string]uint32, error) {
294 filtersField := make(map[string]uint32, 0) 305 filtersField := make(map[string]uint32, 0)
295 rows, err := db.Query(`SELECT 306 rows, err := db.Query(`SELECT
296 FILTERS_FIELD, RB 307 FILTERS_FIELD, RB
297 FROM LIST_CONFIG_FILTERS 308 FROM LIST_CONFIG_FILTERS
298 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 309 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
299 if err != nil { 310 if err != nil {
300 return nil, err 311 return nil, err
301 } 312 }
302 defer rows.Close() 313 defer rows.Close()
303 314
304 for rows.Next() { 315 for rows.Next() {
305 var field string 316 var field string
306 var rb uint32 317 var rb uint32
307 rows.Scan(&field, &rb) 318 rows.Scan(&field, &rb)
308 filtersField[field] = rb 319 filtersField[field] = rb
309 } 320 }
310 if rows.Err() != nil { 321 if rows.Err() != nil {
311 return nil, rows.Err() 322 return nil, rows.Err()
312 } 323 }
313 return filtersField, nil 324 return filtersField, nil
314 } 325 }
315 326
316 type _filter struct { 327 type _filter struct {
317 DefaultValues string 328 DefaultValues string
318 Label string 329 Label string
319 Type string 330 Type string
320 } 331 }
321 332
322 // getFiltersByFilterField returns filter slice for the provided filter field. 333 // getFiltersByFilterField returns filter slice for the provided filter field.
323 func getFiltersByFilterField(db *sql.DB, filtersField string) ([]_filter, error) { 334 func getFiltersByFilterField(db *sql.DB, filtersField string) ([]_filter, error) {
324 resp := make([]_filter, 0) 335 resp := make([]_filter, 0)
325 rows, err := db.Query(`SELECT 336 rows, err := db.Query(`SELECT
326 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES 337 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES
327 FROM LIST_FILTERS_FIELD 338 FROM LIST_FILTERS_FIELD
328 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField)) 339 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField))
329 if err != nil { 340 if err != nil {
330 return resp, err 341 return resp, err
331 } 342 }
332 defer rows.Close() 343 defer rows.Close()
333 344
334 var f _filter 345 var f _filter
335 for rows.Next() { 346 for rows.Next() {
336 rows.Scan(&f.Type, &f.Label, &f.DefaultValues) 347 rows.Scan(&f.Type, &f.Label, &f.DefaultValues)
337 resp = append(resp, f) 348 resp = append(resp, f)
338 } 349 }
339 if rows.Err() != nil { 350 if rows.Err() != nil {
340 return resp, rows.Err() 351 return resp, rows.Err()
341 } 352 }
342 return resp, nil 353 return resp, nil
343 } 354 }
344 355
345 // getFilterDropdownConfig returns dropdown menu for the provided filter field. 356 // getFilterDropdownConfig returns dropdown menu for the provided filter field.
346 func getFilterDropdownConfig(db *sql.DB, filtersField string) (Dropdown, error) { 357 func getFilterDropdownConfig(db *sql.DB, filtersField string) (Dropdown, error) {
347 var resp Dropdown 358 var resp Dropdown
348 rows, err := db.Query(`SELECT 359 rows, err := db.Query(`SELECT
349 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD 360 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD
350 FROM LIST_DROPDOWN_FILTER 361 FROM LIST_DROPDOWN_FILTER
351 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField)) 362 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField))
352 if err != nil { 363 if err != nil {
353 return resp, err 364 return resp, err
354 } 365 }
355 defer rows.Close() 366 defer rows.Close()
356 if rows.Next() { 367 if rows.Next() {
357 rows.Scan(&resp.FiltersField, &resp.ObjectType, &resp.IDField, &resp.LabelField) 368 rows.Scan(&resp.FiltersField, &resp.ObjectType, &resp.IDField, &resp.LabelField)
358 } 369 }
359 if rows.Err() != nil { 370 if rows.Err() != nil {
360 return resp, rows.Err() 371 return resp, rows.Err()
361 } 372 }
362 return resp, nil 373 return resp, nil
363 } 374 }
364 375
365 // sortFilters bubble sorts provided filters slice by position field. 376 // sortFilters bubble sorts provided filters slice by position field.
366 func sortFilters(filters []ListFilter) { 377 func sortFilters(filters []ListFilter) {
367 done := false 378 done := false
368 var temp ListFilter 379 var temp ListFilter
369 for !done { 380 for !done {
370 done = true 381 done = true
371 for i := 0; i < len(filters)-1; i++ { 382 for i := 0; i < len(filters)-1; i++ {
372 if filters[i].Position > filters[i+1].Position { 383 if filters[i].Position > filters[i+1].Position {
373 done = false 384 done = false
374 temp = filters[i] 385 temp = filters[i]
375 filters[i] = filters[i+1] 386 filters[i] = filters[i+1]
376 filters[i+1] = temp 387 filters[i+1] = temp
377 } 388 }
378 } 389 }
379 } 390 }
380 } 391 }
381 392
382 // getListGraph return list graph slice for the provided object type. 393 // getListGraph return list graph slice for the provided object type.
383 func getListGraph(db *sql.DB, objType string) ([]ListGraph, error) { 394 func getListGraph(db *sql.DB, objType string) ([]ListGraph, error) {
384 resp := make([]ListGraph, 0) 395 resp := make([]ListGraph, 0)
385 rows, err := db.Query(`SELECT 396 rows, err := db.Query(`SELECT
386 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL 397 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL
387 FROM LIST_GRAPHS 398 FROM LIST_GRAPHS
388 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 399 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
389 if err != nil { 400 if err != nil {
390 return resp, err 401 return resp, err
391 } 402 }
392 defer rows.Close() 403 defer rows.Close()
393 404
394 var lg ListGraph 405 var lg ListGraph
395 for rows.Next() { 406 for rows.Next() {
396 rows.Scan(&lg.ObjectType, &lg.X, &lg.Y, &lg.GroupField, &lg.Label) 407 rows.Scan(&lg.ObjectType, &lg.X, &lg.Y, &lg.GroupField, &lg.Label)
397 resp = append(resp, lg) 408 resp = append(resp, lg)
398 } 409 }
399 if rows.Err() != nil { 410 if rows.Err() != nil {
400 return resp, rows.Err() 411 return resp, rows.Err()
401 } 412 }
402 return resp, nil 413 return resp, nil
403 } 414 }
404 415
405 // getListOptions returns list options for the provided object type. 416 // getListOptions returns list options for the provided object type.
406 func getListOptions(db *sql.DB, objType string) (ListOptions, error) { 417 func getListOptions(db *sql.DB, objType string) (ListOptions, error) {
407 var resp ListOptions 418 var resp ListOptions
408 rows, err := db.Query(`SELECT 419 rows, err := db.Query(`SELECT
409 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION, 420 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION,
410 PAGE_SIZE, PIVOT, DETAIL, TOTAL 421 PAGE_SIZE, PIVOT, DETAIL, TOTAL
411 FROM LIST_CONFIG 422 FROM LIST_CONFIG
412 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 423 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
413 if err != nil { 424 if err != nil {
414 return ListOptions{}, err 425 return ListOptions{}, err
415 } 426 }
416 defer rows.Close() 427 defer rows.Close()
417 if rows.Next() { 428 if rows.Next() {
418 var gfilter, lfilters, rfilters, pagination, pageSize, pivot, detail, total uint32 429 var gfilter, lfilters, rfilters, pagination, pageSize, pivot, detail, total uint32
419 rows.Scan(&gfilter, &lfilters, &rfilters, &pagination, &pageSize, &pivot, &detail, &total) 430 rows.Scan(&gfilter, &lfilters, &rfilters, &pagination, &pageSize, &pivot, &detail, &total)
420 resp.GlobalFilter = gfilter != 0 431 resp.GlobalFilter = gfilter != 0
421 resp.LocalFilters = lfilters != 0 432 resp.LocalFilters = lfilters != 0
422 resp.RemoteFilters = rfilters != 0 433 resp.RemoteFilters = rfilters != 0
423 resp.Pagination = pagination != 0 434 resp.Pagination = pagination != 0
424 resp.PageSize = pageSize 435 resp.PageSize = pageSize
425 resp.Pivot = pivot != 0 436 resp.Pivot = pivot != 0
426 resp.Detail = detail != 0 437 resp.Detail = detail != 0
427 resp.Total = total != 0 438 resp.Total = total != 0
428 } 439 }
429 if rows.Err() != nil { 440 if rows.Err() != nil {
430 return ListOptions{}, rows.Err() 441 return ListOptions{}, rows.Err()
431 } 442 }
432 return resp, nil 443 return resp, nil
433 } 444 }
434 445
435 // getListParent returns list parent node slice for the provided object type. 446 // getListParent returns list parent node slice for the provided object type.
436 func getListParent(db *sql.DB, objType string) ([]ListParentNode, error) { 447 func getListParent(db *sql.DB, objType string) ([]ListParentNode, error) {
437 resp := make([]ListParentNode, 0) 448 resp := make([]ListParentNode, 0)
438 rows, err := db.Query(`SELECT 449 rows, err := db.Query(`SELECT
439 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD 450 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD
440 FROM LIST_CONFIG_CHILD 451 FROM LIST_CONFIG_CHILD
441 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 452 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
442 if err != nil { 453 if err != nil {
443 return resp, err 454 return resp, err
444 } 455 }
445 defer rows.Close() 456 defer rows.Close()
446 457
447 var pnode ListParentNode 458 var pnode ListParentNode
448 for rows.Next() { 459 for rows.Next() {
449 rows.Scan(&pnode.ObjectType, &pnode.LabelField, &pnode.FilterField) 460 rows.Scan(&pnode.ObjectType, &pnode.LabelField, &pnode.FilterField)
450 resp = append(resp, pnode) 461 resp = append(resp, pnode)
451 } 462 }
452 if rows.Err() != nil { 463 if rows.Err() != nil {
453 return nil, rows.Err() 464 return nil, rows.Err()
454 } 465 }
455 466
456 return resp, nil 467 return resp, nil
457 } 468 }
458 469
459 // getListPivot list pivot slice for the provided object type. 470 // getListPivot list pivot slice for the provided object type.
460 func getListPivot(db *sql.DB, objType string) ([]ListPivot, error) { 471 func getListPivot(db *sql.DB, objType string) ([]ListPivot, error) {
461 resp := make([]ListPivot, 0) 472 resp := make([]ListPivot, 0)
462 rows, err := db.Query(`SELECT 473 rows, err := db.Query(`SELECT
463 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD 474 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD
464 FROM LIST_PIVOTS 475 FROM LIST_PIVOTS
465 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 476 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
466 if err != nil { 477 if err != nil {
467 return resp, err 478 return resp, err
468 } 479 }
469 defer rows.Close() 480 defer rows.Close()
470 481
471 var p ListPivot 482 var p ListPivot
472 for rows.Next() { 483 for rows.Next() {
473 rows.Scan(&p.ObjectType, &p.GroupField, &p.DistinctField, &p.Value) 484 rows.Scan(&p.ObjectType, &p.GroupField, &p.DistinctField, &p.Value)
474 resp = append(resp, p) 485 resp = append(resp, p)
475 } 486 }
476 if rows.Err() != nil { 487 if rows.Err() != nil {
477 return nil, rows.Err() 488 return nil, rows.Err()
478 } 489 }
479 490
480 return resp, nil 491 return resp, nil
481 } 492 }
482 493
483 // getListDetails returns list details for the provided object type. 494 // getListDetails returns list details for the provided object type.
484 func getListDetails(db *sql.DB, objType string) (ListDetails, error) { 495 func getListDetails(db *sql.DB, objType string) (ListDetails, error) {
485 var resp ListDetails 496 var resp ListDetails
486 rows, err := db.Query(`SELECT 497 rows, err := db.Query(`SELECT
487 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL 498 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL
488 FROM LIST_CONFIG_DETAIL 499 FROM LIST_CONFIG_DETAIL
489 WHERE PARENT_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 500 WHERE PARENT_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
490 if err != nil { 501 if err != nil {
491 return resp, err 502 return resp, err
492 } 503 }
493 defer rows.Close() 504 defer rows.Close()
494 if rows.Next() { 505 if rows.Next() {
495 var singleDetail uint32 506 var singleDetail uint32
496 rows.Scan(&resp.ObjectType, &resp.ParentObjectType, &resp.ParentFilterField, &singleDetail) 507 rows.Scan(&resp.ObjectType, &resp.ParentObjectType, &resp.ParentFilterField, &singleDetail)
497 resp.SingleDetail = singleDetail != 0 508 resp.SingleDetail = singleDetail != 0
498 } 509 }
499 if rows.Err() != nil { 510 if rows.Err() != nil {
500 return resp, rows.Err() 511 return resp, rows.Err()
501 } 512 }
502 513
503 return resp, nil 514 return resp, nil
504 } 515 }
516
517 // getListLiveGraph returns live graph for the provided object type.
518 func getListLiveGraph(db *sql.DB, objType string) (ListLiveGraph, error) {
519 var resp ListLiveGraph
520 rows, err := db.Query(`SELECT
521 OBJECT_TYPE, VALUE_FIELDS, LABEL_FIELDS
522 FROM LIST_LIVE_GRAPH
523 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
524 if err != nil {
525 return resp, err
526 }
527 defer rows.Close()
528 if rows.Next() {
529 rows.Scan(&resp.ObjectType, &resp.ValueFields, &resp.LabelFields)
530 }
531 if rows.Err() != nil {
532 return resp, rows.Err()
533 }
534
535 return resp, nil
536 }
505 537