Skip to content

Commit 4215b17

Browse files
authored
Features for consuming app structure through GUI
* Refactor app structure logic to avoid cyclic imports * Add interface and implementations to consume app structure * Port bug fixes from bugfix/590-AppStructure
1 parent 05af898 commit 4215b17

20 files changed

+514
-220
lines changed

appstructure/appstructure.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package appstructure
2+
3+
import (
4+
"encoding/json"
5+
"github.com/qlik-oss/gopherciser/enummap"
6+
)
7+
8+
type (
9+
10+
// MetaDef meta information for Library objects such as dimension and measure
11+
MetaDef struct {
12+
// Title of library item
13+
Title string `json:"title,omitempty"`
14+
// Description of library item
15+
Description string `json:"description,omitempty"`
16+
// Tags of of library item
17+
Tags []string `json:"tags,omitempty"`
18+
}
19+
20+
// AppObjectDef title and ID of a Sense object
21+
AppObjectDef struct {
22+
// Id of object
23+
Id string `json:"id"`
24+
// Type of Sense object
25+
Type string `json:"type"`
26+
}
27+
28+
AppStructureMeasureMeta struct {
29+
// Meta information, only included for library items
30+
Meta *MetaDef `json:"meta,omitempty"`
31+
// LibraryId connects measure to separately defined measure
32+
LibraryId string `json:"libraryId,omitempty"`
33+
// Label of on measure
34+
Label string `json:"label,omitempty"`
35+
// Def the actual measure definition
36+
Def string `json:"def,omitempty"`
37+
}
38+
39+
AppStructureDimensionMeta struct {
40+
// Meta information, only included for library items
41+
Meta *MetaDef `json:"meta,omitempty"`
42+
// LibraryId connects dimension to separately defined dimension
43+
LibraryId string `json:"libraryId,omitempty"`
44+
// LabelExpression optional parameter with label expression
45+
LabelExpression string `json:"labelExpression,omitempty"`
46+
// Defs definitions of dimension
47+
Defs []string `json:"defs,omitempty"`
48+
// Labels of dimension
49+
Labels []string `json:"labels,omitempty"`
50+
}
51+
52+
// AppStructureObject sense object structure
53+
AppStructureObject struct {
54+
AppObjectDef
55+
MetaDef
56+
// RawBaseProperties of Sense object
57+
RawBaseProperties json.RawMessage `json:"rawBaseProperties,omitempty"`
58+
// RawExtendedProperties of extended Sense object
59+
RawExtendedProperties json.RawMessage `json:"rawExtendedProperties,omitempty"`
60+
// RawGeneratedProperties inner generated properties of auto-chart
61+
RawGeneratedProperties json.RawMessage `json:"rawGeneratedProperties,omitempty"`
62+
// Children to the sense object
63+
Children map[string]string `json:"children,omitempty"`
64+
// Selectable true if select can be done in object
65+
Selectable bool `json:"selectable"`
66+
// Dimensions meta information of dimensions defined in object
67+
Dimensions []AppStructureDimensionMeta `json:"dimensions,omitempty"`
68+
// Measures meta information of measures defined in object
69+
Measures []AppStructureMeasureMeta `json:"measures,omitempty"`
70+
// ExtendsId ID of linked object
71+
ExtendsId string `json:"extendsId,omitempty"`
72+
// Visualization visualization of object, if exists
73+
Visualization string `json:"visualization,omitempty"`
74+
}
75+
76+
// AppStructureAppMeta meta information about the app
77+
AppStructureAppMeta struct {
78+
// Title of the app
79+
Title string `json:"title"`
80+
// Guid of the app
81+
Guid string `json:"guid"`
82+
}
83+
84+
// AppStructureBookmark list of bookmarks in the app
85+
AppStructureBookmark struct {
86+
// ID of bookmark
87+
ID string `json:"id"`
88+
// Title of bookmark
89+
Title string `json:"title"`
90+
// Description of bookmark
91+
Description string `json:"description"`
92+
// SheetId connected sheet ID, null if none
93+
SheetId *string `json:"sheetId,omitempty"`
94+
// SelectionFields fields bookmark would select in
95+
SelectionFields string `json:"selectionFields"`
96+
// RawProperties of Bookmark object
97+
RawProperties json.RawMessage `json:"rawProperties,omitempty"`
98+
}
99+
100+
// AppStructure of Sense app
101+
AppStructure struct {
102+
AppMeta AppStructureAppMeta `json:"meta"`
103+
// Objects in Sense app
104+
Objects map[string]AppStructureObject `json:"objects"`
105+
// Bookmark list of bookmarks in the app
106+
Bookmarks map[string]AppStructureBookmark `json:"bookmarks"`
107+
}
108+
109+
// AppStructurePopulatedObjects is the type returned by an action when prompted for selectable objects
110+
AppStructurePopulatedObjects struct {
111+
// Parent id of the parent object
112+
Parent string
113+
// Objects first level app objects returned by the current action
114+
Objects []AppStructureObject
115+
// Bookmark bookmarks returned by the current action
116+
Bookmarks []AppStructureBookmark
117+
}
118+
119+
ObjectType int
120+
AppStructureObjectNotFoundError string
121+
AppStructureNoScenarioActionsError struct{}
122+
)
123+
124+
const (
125+
ObjectTypeDefault ObjectType = iota
126+
ObjectTypeDimension
127+
ObjectTypeMeasure
128+
ObjectTypeBookmark
129+
ObjectTypeMasterObject
130+
ObjectTypeAutoChart
131+
ObjectSheet
132+
ObjectLoadModel
133+
ObjectAppprops
134+
)
135+
136+
var (
137+
ObjectTypeEnumMap, _ = enummap.NewEnumMap(map[string]int{
138+
"dimension": int(ObjectTypeDimension),
139+
"measure": int(ObjectTypeMeasure),
140+
"bookmark": int(ObjectTypeBookmark),
141+
"masterobject": int(ObjectTypeMasterObject),
142+
"auto-chart": int(ObjectTypeAutoChart),
143+
"sheet": int(ObjectSheet),
144+
"loadmodel": int(ObjectLoadModel),
145+
"appprops": int(ObjectAppprops),
146+
})
147+
)
148+
149+
// Error object was not found in app structure
150+
func (err AppStructureObjectNotFoundError) Error() string {
151+
return string(err)
152+
}
153+
154+
// Error no applicable actions found in scenario
155+
func (err AppStructureNoScenarioActionsError) Error() string {
156+
return "no applicable actions in scenario"
157+
}
158+
159+
// GetSelectables get selectable objects from app structure
160+
func (structure *AppStructure) GetSelectables(rooObject string) ([]AppStructureObject, error) {
161+
rootObj, ok := structure.Objects[rooObject]
162+
if !ok {
163+
return nil, AppStructureObjectNotFoundError(rooObject)
164+
}
165+
166+
return structure.addSelectableChildren(rootObj), nil
167+
}
168+
169+
func (structure *AppStructure) addSelectableChildren(obj AppStructureObject) []AppStructureObject {
170+
selectables := make([]AppStructureObject, 0, 1)
171+
if obj.Selectable {
172+
selectables = append(selectables, obj)
173+
}
174+
175+
for id := range obj.Children {
176+
child, ok := structure.Objects[id]
177+
if !ok {
178+
continue
179+
}
180+
181+
selectableChildren := structure.addSelectableChildren(child)
182+
selectables = append(selectables, selectableChildren...)
183+
}
184+
return selectables
185+
}

cmd/script.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"context"
55
"fmt"
6+
"github.com/qlik-oss/gopherciser/appstructure"
67
"os"
78

89
"github.com/qlik-oss/gopherciser/config"
@@ -192,7 +193,7 @@ Will save one .structure file per app in script in the folder defined by output
192193

193194
err = cfg.GetAppStructures(context.Background(), includeRaw)
194195
switch err.(type) {
195-
case config.AppStructureNoScenarioActionsError:
196+
case appstructure.AppStructureNoScenarioActionsError:
196197
// Not an error but print info
197198
_, _ = fmt.Fprintf(os.Stderr, "%s\n", err)
198199
case nil:

0 commit comments

Comments
 (0)