Commit 8bc396eb9662db719a885c160c81a6e8a7003564

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

reverted changes

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