Commit 8bc396eb9662db719a885c160c81a6e8a7003564
1 parent
4c5e428df5
Exists in
master
and in
1 other branch
reverted changes
Showing
3 changed files
with
671 additions
and
1 deletions
Show diff stats
json_utility.go
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 |
list_config.go
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 |
select_config.go
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 |