Skip to content

Commit

Permalink
Add action-button support (#90)
Browse files Browse the repository at this point in the history
* Add a "clickactionbutton"-action
* Support caching of fields and variables during a session
* Add helper functions for caching fields and variables
* Sort sheetlist on rank
  • Loading branch information
atluq authored Sep 3, 2020
1 parent 1b68d9a commit d7f4026
Show file tree
Hide file tree
Showing 17 changed files with 1,133 additions and 5 deletions.
47 changes: 47 additions & 0 deletions docs/settingup.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,53 @@ Clear all selections in an app.
}
```

</details><details>
<summary>clickactionbutton</summary>

## ClickActionButton action

A `ClickActionButton`-action simulates clicking an _action-button_. An _action-button_ is a sheet item which, when clicked, executes a series of actions. The series of actions contained by an action-button begins with any number _generic button-actions_ and ends with an optional _navigation button-action_.

### Supported button-actions
#### Generic button-actions
- Apply bookmark
- Move backward in all selections
- Move forward in all selections
- Lock all selections
- Clear all selections
- Lock field
- Unlock field
- Select all in field
- Select alternatives in field
- Select excluded in field
- Select possible in field
- Select values matching search criteria in field
- Clear selection in field
- Toggle selection in field
- Set value of variable

#### Navigation button-actions
- Change to first sheet
- Change to last sheet
- Change to previous sheet
- Change sheet by name
- Change sheet by ID
### Settings

* `id`: ID of the action-button to click.

### Examples

```json
{
"label": "ClickActionButton",
"action": "ClickActionButton",
"settings": {
"id": "951e2eee-ad49-4f6a-bdfe-e9e3dddeb2cd"
}
}
```

</details><details>
<summary>createbookmark</summary>

Expand Down
33 changes: 33 additions & 0 deletions enigmahandlers/fieldcache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package enigmahandlers

import (
"sync"

"github.com/qlik-oss/enigma-go"
)

type (
// FieldCache
FieldCache struct {
fieldMap map[string]*enigma.Field
mutex sync.RWMutex
}
)

func NewFieldCache() FieldCache {
return FieldCache{fieldMap: make(map[string]*enigma.Field)}

}

func (fc *FieldCache) Lookup(name string) (field *enigma.Field, hit bool) {
fc.mutex.RLock()
defer fc.mutex.RUnlock()
field, hit = fc.fieldMap[name]
return
}

func (fc *FieldCache) Store(name string, field *enigma.Field) {
fc.mutex.Lock()
defer fc.mutex.Unlock()
fc.fieldMap[name] = field
}
96 changes: 96 additions & 0 deletions enigmahandlers/fieldcache_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package enigmahandlers

import (
"reflect"
"testing"

"github.com/qlik-oss/enigma-go"
)

var fieldDummy = &enigma.Field{}

func Test_fieldCache_Lookup(t *testing.T) {
names := [...]string{"field1", "field2", "field3"}

preFilledFieldCache := &FieldCache{
fieldMap: map[string]*enigma.Field{
names[0]: fieldDummy,
names[1]: fieldDummy,
names[2]: fieldDummy,
},
}

tests := []struct {
name string
fieldName string
wantField *enigma.Field
wantHit bool
fc *FieldCache
}{
{"hit1", names[0], fieldDummy, true, preFilledFieldCache},
{"hit2", names[1], fieldDummy, true, preFilledFieldCache},
{"noHit1", names[2], nil, false, nil},
{"noHit2", "", nil, false, preFilledFieldCache},
{"noHit3", "abc", nil, false, preFilledFieldCache},
{"noHit4", "", nil, false, preFilledFieldCache},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.fc == nil {
newFC := NewFieldCache()
tt.fc = &newFC
}
gotField, gotHit := tt.fc.Lookup(tt.fieldName)
if !reflect.DeepEqual(gotField, tt.wantField) {
t.Errorf("fieldCache.Lookup() gotField = %v, want %v", gotField, tt.wantField)
}
if gotHit != tt.wantHit {
t.Errorf("fieldCache.Lookup() gotHit = %v, want %v", gotHit, tt.wantHit)
}
})
}
}

func Test_fieldCache_Store(t *testing.T) {
tests := []struct {
name string
storeNames []string
notStoredNames []string
}{
{"storeTest1", []string{"field1", "field2", "field3"}, []string{"", "xyz"}},
{"storeTest1", []string{"field1", "field2"}, []string{"", ""}},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fc := NewFieldCache()
for _, fieldName := range tt.storeNames {
fc.Store(fieldName, fieldDummy)
}
wantLen := len(tt.storeNames)
gotLen := len(fc.fieldMap)
if wantLen != gotLen {
t.Errorf("fieldCache.Store() unexpected cache size")
}
for _, fieldName := range tt.storeNames {
f, hit := fc.fieldMap[fieldName]
if !hit {
t.Errorf("fieldCache.Store() want hit==true")
}
if f == nil {
t.Errorf("fieldCache.Store() want field!=nil")
}
}
for _, fieldName := range tt.notStoredNames {
f, hit := fc.fieldMap[fieldName]
if hit {
t.Errorf("fieldCache.Store() want hit==false")
}
if f != nil {
t.Errorf("fieldCache.Store() want field==nil")
}
}
})
}
}
9 changes: 9 additions & 0 deletions enigmahandlers/senseconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type (
Global *enigma.Global
CurrentApp *senseobjects.App
Objects ObjectsMap
FieldCache FieldCache
VarCache VarCache
Traffic ITrafficLogger

ctx context.Context
Expand All @@ -40,6 +42,11 @@ type (
MockMode bool
}

Cache struct {
Field FieldCache
Var VarCache
}

// SenseConnection direct sense connection implementing IConnection interface
SenseConnection struct {
*SenseUplink
Expand Down Expand Up @@ -75,6 +82,8 @@ func NewSenseUplink(ctx context.Context, logentry *logger.LogEntry, metrics *req
trafficMetrics: metrics,
logEntry: logentry,
Traffic: trafficLogger,
FieldCache: NewFieldCache(),
VarCache: NewVarCache(),
}
}

Expand Down
32 changes: 32 additions & 0 deletions enigmahandlers/varcache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package enigmahandlers

import (
"sync"

"github.com/qlik-oss/enigma-go"
)

type (
// varCache
VarCache struct {
varMap map[string]*enigma.GenericVariable
mutex sync.RWMutex
}
)

func NewVarCache() VarCache {
return VarCache{varMap: map[string]*enigma.GenericVariable{}}
}

func (vc *VarCache) Lookup(varName string) (varValue *enigma.GenericVariable, hit bool) {
vc.mutex.RLock()
defer vc.mutex.RUnlock()
varValue, hit = vc.varMap[varName]
return
}

func (vc *VarCache) Store(name string, variable *enigma.GenericVariable) {
vc.mutex.Lock()
defer vc.mutex.Unlock()
vc.varMap[name] = variable
}
96 changes: 96 additions & 0 deletions enigmahandlers/varcache_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package enigmahandlers

import (
"reflect"
"testing"

"github.com/qlik-oss/enigma-go"
)

var varDummy = &enigma.GenericVariable{}

func Test_varCache_Lookup(t *testing.T) {
names := [...]string{"variable1", "variable2", "variable3"}

preFilledVarCache := &VarCache{
varMap: map[string]*enigma.GenericVariable{
names[0]: varDummy,
names[1]: varDummy,
names[2]: varDummy,
},
}

tests := []struct {
name string
variableName string
wantVariable *enigma.GenericVariable
wantHit bool
vc *VarCache
}{
{"hit1", names[0], varDummy, true, preFilledVarCache},
{"hit2", names[1], varDummy, true, preFilledVarCache},
{"noHit1", names[2], nil, false, nil},
{"noHit2", "", nil, false, preFilledVarCache},
{"noHit3", "abc", nil, false, preFilledVarCache},
{"noHit4", "", nil, false, preFilledVarCache},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.vc == nil {
newFC := NewVarCache()
tt.vc = &newFC
}
gotVariable, gotHit := tt.vc.Lookup(tt.variableName)
if !reflect.DeepEqual(gotVariable, tt.wantVariable) {
t.Errorf("varCache.Lookup() gotVariable = %v, want %v", gotVariable, tt.wantVariable)
}
if gotHit != tt.wantHit {
t.Errorf("varCache.Lookup() gotHit = %v, want %v", gotHit, tt.wantHit)
}
})
}
}

func Test_varCache_Store(t *testing.T) {
tests := []struct {
name string
storeNames []string
notStoredNames []string
}{
{"storeTest1", []string{"variable1", "variable2", "variable3"}, []string{"", "xyz"}},
{"storeTest1", []string{"variable1", "variable2"}, []string{"", ""}},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
vc := NewVarCache()
for _, variableName := range tt.storeNames {
vc.Store(variableName, varDummy)
}
wantLen := len(tt.storeNames)
gotLen := len(vc.varMap)
if wantLen != gotLen {
t.Errorf("varCache.Store() unexpected cache size")
}
for _, variableName := range tt.storeNames {
v, hit := vc.varMap[variableName]
if !hit {
t.Errorf("varCache.Store() want hit==true")
}
if v == nil {
t.Errorf("varCache.Store() want variable!=nil")
}
}
for _, variableName := range tt.notStoredNames {
v, hit := vc.varMap[variableName]
if hit {
t.Errorf("varCache.Store() want hit==false")
}
if v != nil {
t.Errorf("varCache.Store() want variable==nil")
}
}
})
}
}
28 changes: 28 additions & 0 deletions generatedocs/data/actions/clickactionbutton/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## ClickActionButton action

A `ClickActionButton`-action simulates clicking an _action-button_. An _action-button_ is a sheet item which, when clicked, executes a series of actions. The series of actions contained by an action-button begins with any number _generic button-actions_ and ends with an optional _navigation button-action_.

### Supported button-actions
#### Generic button-actions
- Apply bookmark
- Move backward in all selections
- Move forward in all selections
- Lock all selections
- Clear all selections
- Lock field
- Unlock field
- Select all in field
- Select alternatives in field
- Select excluded in field
- Select possible in field
- Select values matching search criteria in field
- Clear selection in field
- Toggle selection in field
- Set value of variable

#### Navigation button-actions
- Change to first sheet
- Change to last sheet
- Change to previous sheet
- Change sheet by name
- Change sheet by ID
11 changes: 11 additions & 0 deletions generatedocs/data/actions/clickactionbutton/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### Examples

```json
{
"label": "ClickActionButton",
"action": "ClickActionButton",
"settings": {
"id": "951e2eee-ad49-4f6a-bdfe-e9e3dddeb2cd"
}
}
```
1 change: 1 addition & 0 deletions generatedocs/data/groups/groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"applybookmark",
"changesheet",
"clearall",
"clickactionbutton",
"createbookmark",
"createsheet",
"deletebookmark",
Expand Down
Loading

0 comments on commit d7f4026

Please sign in to comment.