Skip to content

Commit 95a83ec

Browse files
authored
Enhancement/621 appstructure fields (#85)
Adds list of fields to appstructure file when getting app structure
1 parent 720f2d1 commit 95a83ec

File tree

4 files changed

+153
-5
lines changed

4 files changed

+153
-5
lines changed

appstructure/appstructure.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package appstructure
33
import (
44
"encoding/json"
55

6+
"github.com/qlik-oss/enigma-go"
67
"github.com/qlik-oss/gopherciser/enummap"
78
)
89

@@ -98,13 +99,20 @@ type (
9899
RawProperties json.RawMessage `json:"rawProperties,omitempty"`
99100
}
100101

102+
// AppStructureField list of fields in the app
103+
AppStructureField struct {
104+
enigma.NxFieldDescription
105+
}
106+
101107
// AppStructure of Sense app
102108
AppStructure struct {
103109
AppMeta AppStructureAppMeta `json:"meta"`
104110
// Objects in Sense app
105111
Objects map[string]AppStructureObject `json:"objects"`
106112
// Bookmark list of bookmarks in the app
107113
Bookmarks map[string]AppStructureBookmark `json:"bookmarks"`
114+
// Fields list of all fields in the app
115+
Fields map[string]AppStructureField `json:"fields"`
108116
}
109117

110118
// AppStructurePopulatedObjects is the type returned by an action when prompted for selectable objects

config/appstructure.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"github.com/InVisionApp/tabular"
8-
"github.com/qlik-oss/gopherciser/appstructure"
9-
"github.com/qlik-oss/gopherciser/helpers"
107
"path/filepath"
118
"strconv"
129
"strings"
1310
"sync"
1411
"time"
1512

13+
"github.com/InVisionApp/tabular"
1614
"github.com/pkg/errors"
1715
"github.com/qlik-oss/enigma-go"
1816
"github.com/qlik-oss/gopherciser/action"
17+
"github.com/qlik-oss/gopherciser/appstructure"
18+
"github.com/qlik-oss/gopherciser/helpers"
1919
"github.com/qlik-oss/gopherciser/logger"
2020
"github.com/qlik-oss/gopherciser/scenario"
2121
"github.com/qlik-oss/gopherciser/scheduler"
@@ -676,6 +676,47 @@ func (structure *GeneratedAppStructure) handleBookmark(ctx context.Context, app
676676
return nil
677677
}
678678

679+
func (structure *GeneratedAppStructure) getFieldListAsync(sessionState *session.State, actionState *action.State, app *senseobjects.App) {
680+
// Create fieldlist object and handle fields
681+
sessionState.QueueRequest(func(ctx context.Context) error {
682+
fieldlist, err := senseobjects.CreateFieldListObject(ctx, app.Doc)
683+
if err != nil {
684+
return err
685+
}
686+
687+
sessionState.QueueRequestWithCallback(fieldlist.UpdateLayout, actionState, true, "", func(err error) {
688+
properties := fieldlist.Layout()
689+
if properties == nil {
690+
actionState.AddErrors(errors.New("fieldlist layout is nil"))
691+
return
692+
}
693+
if properties.FieldList == nil {
694+
actionState.AddErrors(errors.New("FieldList missing from fieldlist layout"))
695+
return
696+
}
697+
for _, field := range properties.FieldList.Items {
698+
structure.addField(field)
699+
}
700+
})
701+
return nil
702+
}, actionState, true, "")
703+
}
704+
705+
func (structure *GeneratedAppStructure) addField(field *enigma.NxFieldDescription) {
706+
if field == nil {
707+
return
708+
}
709+
structure.structureLock.Lock()
710+
defer structure.structureLock.Unlock()
711+
712+
if structure.Fields == nil {
713+
structure.Fields = make(map[string]appstructure.AppStructureField)
714+
}
715+
structure.Fields[field.Name] = appstructure.AppStructureField{
716+
NxFieldDescription: *field,
717+
}
718+
}
719+
679720
func resolveTitle(obj *appstructure.AppStructureObject, properties json.RawMessage, paths []string) {
680721
if obj.MetaDef.Title != "" {
681722
return // We already have a title

config/getappstructure.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"os"
8+
"sync"
9+
710
"github.com/pkg/errors"
811
"github.com/qlik-oss/enigma-go"
912
"github.com/qlik-oss/gopherciser/action"
1013
"github.com/qlik-oss/gopherciser/appstructure"
1114
"github.com/qlik-oss/gopherciser/connection"
1215
"github.com/qlik-oss/gopherciser/session"
13-
"os"
14-
"sync"
1516
)
1617

1718
type (
@@ -74,10 +75,17 @@ func (settings *getAppStructureSettings) Execute(sessionState *session.State, ac
7475
}
7576
}
7677

78+
appStructure.getFieldListAsync(sessionState, actionState, app)
79+
7780
if sessionState.Wait(actionState) {
7881
return // An error occurred
7982
}
8083

84+
// TODO clicking the "Selections" tab in sense would normally create a fieldlist and a dimensionlist object
85+
// to get dimensions and fields. We however already have master object dimensions in object list
86+
// should these be moved to a combined field+dimension list? Leave this as is now and to be decided
87+
// when implementing actions using fields and decide what works best for GUI.
88+
8189
raw, err := json.MarshalIndent(appStructure, "", " ")
8290
if err != nil {
8391
actionState.AddErrors(errors.Wrap(err, "error marshaling app structure"))

senseobjects/fieldlist.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package senseobjects
2+
3+
import (
4+
"context"
5+
"sync"
6+
7+
"github.com/pkg/errors"
8+
"github.com/qlik-oss/enigma-go"
9+
)
10+
11+
type (
12+
FieldList struct {
13+
enigmaObject *enigma.GenericObject
14+
layout *enigma.GenericObjectLayout
15+
properties *enigma.GenericObjectProperties
16+
mutex sync.Mutex
17+
}
18+
)
19+
20+
// CreateFieldListObject create fieldlist session object
21+
func CreateFieldListObject(ctx context.Context, doc *enigma.Doc) (*FieldList, error) {
22+
properties := &enigma.GenericObjectProperties{
23+
Info: &enigma.NxInfo{
24+
Type: "FieldList",
25+
},
26+
FieldListDef: &enigma.FieldListDef{
27+
ShowSystem: false,
28+
ShowHidden: false,
29+
ShowSemantic: true,
30+
ShowSrcTables: true,
31+
ShowDerivedFields: true,
32+
ShowImplicit: false,
33+
ShowDefinitionOnly: false,
34+
},
35+
}
36+
37+
obj, err := doc.CreateSessionObject(ctx, properties)
38+
if err != nil {
39+
return nil, errors.Wrapf(err, "Failed to create fieldlist session object in app<%s>", doc.GenericId)
40+
}
41+
42+
return &FieldList{enigmaObject: obj, properties: properties}, nil
43+
}
44+
45+
// UpdateLayout update object with new layout from engine
46+
func (fieldlist *FieldList) UpdateLayout(ctx context.Context) error {
47+
layout, err := fieldlist.enigmaObject.GetLayout(ctx)
48+
if err != nil {
49+
return errors.WithStack(err)
50+
}
51+
52+
fieldlist.setLayout(layout)
53+
return nil
54+
}
55+
56+
func (fieldlist *FieldList) setLayout(layout *enigma.GenericObjectLayout) {
57+
fieldlist.mutex.Lock()
58+
defer fieldlist.mutex.Unlock()
59+
fieldlist.layout = layout
60+
}
61+
62+
// Layout of fieldlist object
63+
func (fieldlist *FieldList) Layout() *enigma.GenericObjectLayout {
64+
fieldlist.mutex.Lock()
65+
defer fieldlist.mutex.Unlock()
66+
return fieldlist.layout
67+
}
68+
69+
// UpdateProperties update object with new properties from engine
70+
func (fieldlist *FieldList) UpdateProperties(ctx context.Context) error {
71+
properties, err := fieldlist.enigmaObject.GetProperties(ctx)
72+
if err != nil {
73+
return errors.WithStack(err)
74+
}
75+
76+
fieldlist.setProperties(properties)
77+
return nil
78+
}
79+
80+
func (fieldlist *FieldList) setProperties(properties *enigma.GenericObjectProperties) {
81+
fieldlist.mutex.Lock()
82+
defer fieldlist.mutex.Unlock()
83+
fieldlist.properties = properties
84+
}
85+
86+
// Properties of fieldlist object
87+
func (fieldlist *FieldList) Properties() *enigma.GenericObjectProperties {
88+
fieldlist.mutex.Lock()
89+
defer fieldlist.mutex.Unlock()
90+
return fieldlist.properties
91+
}

0 commit comments

Comments
 (0)