cob-cli 2.13.1 → 2.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/dashboards/dash/dist/css/app.97b1c4b4.css +8 -0
- package/templates/dashboards/dash/dist/dashboard.html +5 -5
- package/templates/dashboards/dash/dist/js/{app.f9c19b80.js → app.a1c26814.js} +9 -9
- package/templates/dashboards/dash/dist/js/app.a1c26814.js.map +1 -0
- package/templates/dashboards/dash/package-lock.json +3918 -5165
- package/templates/dashboards/dash/package.json +1 -1
- package/templates/dashboards/dash/src/App.vue +108 -64
- package/templates/dashboards/dash/src/collector.js +107 -35
- package/templates/dashboards/dash/src/components/Attention.vue +30 -0
- package/templates/dashboards/dash/src/components/Board.vue +22 -53
- package/templates/dashboards/dash/src/components/Dashboard.vue +24 -0
- package/templates/dashboards/dash/src/components/Filter.vue +58 -0
- package/templates/dashboards/dash/src/components/Kibana.vue +107 -0
- package/templates/dashboards/dash/src/components/Label.vue +15 -0
- package/templates/dashboards/dash/src/components/Menu.vue +33 -22
- package/templates/dashboards/dash/src/components/Totals.vue +35 -53
- package/templates/dashboards/dash/src/components/TotalsValue.vue +48 -59
- package/templates/dashboards/dash/src/dashboard.html +1 -1
- package/templates/dashboards/dash/src/definition_dashboard.json +741 -0
- package/templates/dashboards/dash/src/output.css +20103 -76122
- package/templates/dashboards/dash/tailwind.config.js +6 -10
- package/templates/frontend/common/js/cob/_show_hidden.js +1 -1
- package/templates/dashboards/dash/definition_dashboard_v59.json +0 -1
- package/templates/dashboards/dash/dist/css/app.2ca409ad.css +0 -8
- package/templates/dashboards/dash/dist/js/app.8423eff3.js +0 -188
- package/templates/dashboards/dash/dist/js/app.8423eff3.js.map +0 -1
- package/templates/dashboards/dash/dist/js/app.f9c19b80.js.map +0 -1
- package/templates/dashboards/dash/src/Dashboard.vue +0 -66
- package/templates/dashboards/dash/src/components/BoardsNav.vue +0 -23
- package/templates/dashboards/dash/src/components/BoardsPage.vue +0 -36
- package/templates/dashboards/dash/src/components/Title.vue +0 -21
- package/templates/dashboards/dash/src/definition_dashboard_v59.json +0 -394
|
@@ -1,77 +1,121 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<div v-if="
|
|
2
|
+
<div class="h-full w-full">
|
|
3
|
+
<div v-if="dashboardState=='Loading'" class="text-center my-20 text-2xl text-slate-500">
|
|
4
4
|
Loading...
|
|
5
5
|
</div>
|
|
6
|
-
<div v-else-if="
|
|
6
|
+
<div v-else-if="dashboardState=='Error'" class="text-center my-20 text-2xl text-red-500">
|
|
7
7
|
{{error}}
|
|
8
8
|
</div>
|
|
9
|
-
<Dashboard v-else :dashboard="
|
|
9
|
+
<Dashboard v-else :dashboard="dashboardParsed" />
|
|
10
10
|
</div>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script>
|
|
14
|
-
import axios from 'axios';
|
|
15
|
-
import { umLoggedin } from '@cob/rest-api-wrapper';
|
|
16
|
-
import { instancesList } from '@cob/dashboard-info';
|
|
17
|
-
import
|
|
18
|
-
import
|
|
14
|
+
import axios from 'axios';
|
|
15
|
+
import { umLoggedin } from '@cob/rest-api-wrapper';
|
|
16
|
+
import { instancesList } from '@cob/dashboard-info';
|
|
17
|
+
import { parseDashboard } from './collector.js'
|
|
18
|
+
import Dashboard from './components/Dashboard.vue'
|
|
19
19
|
|
|
20
|
-
export default {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.currentDashboardInstance = instancesList("Dashboard", "page_title.raw:\"" + this.page_title + "\"", 1)
|
|
20
|
+
export default {
|
|
21
|
+
name: 'App',
|
|
22
|
+
components: { Dashboard },
|
|
23
|
+
data: () => ({
|
|
24
|
+
userInfo: null,
|
|
25
|
+
name: null,
|
|
26
|
+
error:"",
|
|
27
|
+
dashboardInstance: null,
|
|
28
|
+
dashboardParsed: null,
|
|
29
|
+
dashboardState: "Loading"
|
|
30
|
+
}),
|
|
31
|
+
created() {
|
|
32
|
+
// At the initial load we get the dashboard instance name from the url
|
|
33
|
+
umLoggedin().then( userInfo => {
|
|
34
|
+
let name = document.getElementsByClassName("custom-resource")[0].getAttribute('data-name')
|
|
35
|
+
this.dashboardInstance = instancesList("Dashboard", this.getDashboardQuery(name , userInfo), 1)
|
|
36
|
+
})
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
let
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
38
|
+
// Upon anchor navigation we get the dashboard instance name from the first param to the 'resume' callback.
|
|
39
|
+
$('section.custom-resource').on('resume', (e, params) => {
|
|
40
|
+
//Recheck user (the user might have changed or his groups might have changed after previous load)
|
|
41
|
+
umLoggedin().then( userInfo => {
|
|
42
|
+
this.dashboardInstance.changeArgs({query: this.getDashboardQuery(params[0], userInfo) })
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
methods: {
|
|
47
|
+
getDashboardQuery(name,userInfo) {
|
|
48
|
+
this.userInfo = userInfo
|
|
49
|
+
this.name = name
|
|
50
|
+
document.title = "Recordm["+name+"]"
|
|
51
|
+
let groups = userInfo.groups.map(g=> "\"" + g.name + "\"").join(" OR ")
|
|
52
|
+
|
|
53
|
+
let nameQuery = "name.raw:\"" + name + "\" "
|
|
54
|
+
let accessQuery = " (groupaccess.raw:(" + groups + ") OR (-groupaccess:*) )"
|
|
55
|
+
return "(" + nameQuery + accessQuery +") OR id:" + name
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
watch: {
|
|
59
|
+
// Monitor state changes to the searching of the Dashboard instance
|
|
60
|
+
'dashboardInstance.state'(instanceInfoState) {
|
|
61
|
+
if(instanceInfoState == "loading" || instanceInfoState == "updating") {
|
|
62
|
+
this.dashboardState = "Loading"
|
|
63
|
+
} else if(instanceInfoState == "error") {
|
|
64
|
+
// Special treatment for 430 (unauthorized) error:
|
|
65
|
+
if(this.dashboardInstance.errorCode == 403) {
|
|
66
|
+
// check who's the new user:
|
|
67
|
+
umLoggedin().then( userInfo => {
|
|
68
|
+
if(userInfo.username == "anonymous") {
|
|
69
|
+
// If the user is anonymous it means we timed out the cookie validity - reload at the same url
|
|
70
|
+
document.location.reload()
|
|
71
|
+
} else {
|
|
72
|
+
// Otherwise the user changed (in another tab) OR the user groups changed OR the dashboards access groups changed
|
|
73
|
+
// send to root
|
|
74
|
+
document.location = "/"
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
} else {
|
|
78
|
+
this.dashboardState = "Error"
|
|
79
|
+
this.error = "Error: error getting dashboard (" + this.dashboardInstance.errorCode + ")"
|
|
80
|
+
}
|
|
81
|
+
} else if( this.dashboardInstance.value.length == 0) {
|
|
82
|
+
this.dashboardState = "Error"
|
|
83
|
+
this.error = "Error: a dashboard '" + this.name + "' was not found for your user"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Monitor value changes to the values of the Dashboard instance
|
|
88
|
+
'dashboardInstance.value'(newDashboards) {
|
|
89
|
+
if(newDashboards.length == 0) {
|
|
90
|
+
this.dashboardState = "Error"
|
|
91
|
+
this.error = "Error: dashboard '" + this.name + "' was not found for your user"
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
//Instance(s) found (from ES) but we still need to get the raw instance of the 1st result(from RM) and parse it
|
|
95
|
+
let firstDashId = newDashboards[0].id
|
|
96
|
+
axios
|
|
97
|
+
.get("/recordm/recordm/instances/" + firstDashId)
|
|
98
|
+
.then(resp => {
|
|
99
|
+
try {
|
|
100
|
+
this.dashboardParsed = parseDashboard(resp.data, this.userInfo)
|
|
101
|
+
this.dashboardState = "Ready"
|
|
102
|
+
}
|
|
103
|
+
catch(e) {
|
|
104
|
+
this.error = "Error: error parsing dashboard " + firstDashId
|
|
105
|
+
this.dashboardState = "Error"
|
|
106
|
+
console.error(e)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
.catch( (e) => {
|
|
110
|
+
if( e.response && e.response.status && e.response.status == 403) {
|
|
111
|
+
this.error = "New authorization required..."
|
|
112
|
+
} else {
|
|
113
|
+
this.error = "Error: error getting dashboard " + firstDashId
|
|
114
|
+
}
|
|
115
|
+
this.dashboardState = "Error"
|
|
116
|
+
console.error(e)
|
|
117
|
+
})
|
|
73
118
|
}
|
|
74
119
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
</script>
|
|
120
|
+
};
|
|
121
|
+
</script>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as dashFunctions from '@cob/dashboard-info';
|
|
2
2
|
const linkFunction = (url, icon) => { return { value: icon, href: url, state: undefined, isLink: true } }
|
|
3
|
-
// dashFunctions["link"] = linkFunction // does not work on brower after deploy (only on localhost dev)
|
|
4
3
|
|
|
5
4
|
const clone = (obj) => JSON.parse(JSON.stringify(obj))
|
|
6
5
|
|
|
@@ -29,13 +28,18 @@ function collect(bucket, source) {
|
|
|
29
28
|
// Means it's additional source matches
|
|
30
29
|
initialBucketCopy = clone(bucket[sourceName][0].Initial_Template) // we use a copy of the previously copied template
|
|
31
30
|
}
|
|
31
|
+
initialBucketCopy.instanceId = bucket.instanceId //needed to build $file url
|
|
32
32
|
children.reduce(collect,initialBucketCopy) // collect values from the children
|
|
33
33
|
initialBucketCopy[sourceName] = source.value // Add extra field with original name of the source
|
|
34
34
|
bucket[sourceName].push(initialBucketCopy) // Add to bucket collector
|
|
35
35
|
}
|
|
36
36
|
} else {
|
|
37
37
|
// Means it's not an array and we can collect the final value
|
|
38
|
-
|
|
38
|
+
if(source.value && source.fieldDefinition.description && source.fieldDefinition.description.indexOf("$file") >= 0) {
|
|
39
|
+
bucket[sourceName] = "/recordm/recordm/instances/" + bucket.instanceId + "/files/" + source.fieldDefinition.id + "/" + source.value
|
|
40
|
+
} else {
|
|
41
|
+
bucket[sourceName] = source.value;
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
} else if (children.length > 0) {
|
|
41
45
|
// Means it didn't find a match. Continue looking in the children
|
|
@@ -46,49 +50,95 @@ function collect(bucket, source) {
|
|
|
46
50
|
return bucket;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
function parseDashboard(raw_dashboard){
|
|
53
|
+
function parseDashboard(raw_dashboard, userInfo){
|
|
50
54
|
let dash = {
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
55
|
+
"Name": "",
|
|
56
|
+
"DashboardCustomize": [{
|
|
57
|
+
"Grid": "",
|
|
58
|
+
"Width": "",
|
|
59
|
+
"DashboardClasses": "",
|
|
60
|
+
"Image": "",
|
|
61
|
+
"GroupAccess": [{}]
|
|
62
|
+
}],
|
|
63
|
+
"Board": [{
|
|
64
|
+
"BoardCustomize": [{
|
|
65
|
+
"BoardClasses": "",
|
|
66
|
+
"Image": ""
|
|
67
|
+
}],
|
|
57
68
|
"Component": []
|
|
58
69
|
}],
|
|
59
70
|
};
|
|
60
71
|
|
|
72
|
+
dash.instanceId = ""+raw_dashboard.id //needed to build $file url
|
|
61
73
|
raw_dashboard.fields.reduce(collect, dash);
|
|
62
74
|
|
|
63
75
|
const ComponentsTemplates = {
|
|
64
|
-
"
|
|
65
|
-
"
|
|
76
|
+
"Label": {
|
|
77
|
+
"LabelCustomize": [{
|
|
78
|
+
"LabelClasses": "",
|
|
79
|
+
"Image": ""
|
|
80
|
+
}],
|
|
81
|
+
"Label": "",
|
|
82
|
+
},
|
|
83
|
+
"Menu": {
|
|
84
|
+
"MenuCustomize": [{
|
|
85
|
+
"MenuClasses": ""
|
|
86
|
+
}],
|
|
87
|
+
"Text": [{
|
|
88
|
+
"Link": "",
|
|
89
|
+
"TextCustomize": [{
|
|
90
|
+
"TextClasses": "",
|
|
91
|
+
"Icon": "",
|
|
92
|
+
"TextAttention": "",
|
|
93
|
+
"GroupVisibility": [{}]
|
|
94
|
+
}],
|
|
95
|
+
}],
|
|
66
96
|
},
|
|
67
97
|
"Totals" : {
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
98
|
+
"TotalsCustomize": [{
|
|
99
|
+
"TotalsClasses": "",
|
|
100
|
+
"InputVarTotals": [{}],
|
|
71
101
|
}],
|
|
72
102
|
"Line": [{
|
|
73
|
-
"
|
|
103
|
+
"LineCustomize": [{
|
|
104
|
+
"LineClasses": "",
|
|
105
|
+
"TitleClasses": "",
|
|
106
|
+
}],
|
|
74
107
|
"Value": [{
|
|
108
|
+
"ValueCustomize": [{
|
|
109
|
+
"ValueClasses": "",
|
|
110
|
+
"View": "",
|
|
111
|
+
"ValueAttention": "",
|
|
112
|
+
"AttentionClasses": "",
|
|
113
|
+
"Unit": "",
|
|
114
|
+
}],
|
|
75
115
|
"Style Value": "",
|
|
76
116
|
"Arg": [{}]
|
|
77
117
|
}]
|
|
78
|
-
}]
|
|
118
|
+
}],
|
|
79
119
|
},
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
|
|
120
|
+
"Kibana": {
|
|
121
|
+
"KibanaCustomize": [{
|
|
122
|
+
"KibanaClasses": "",
|
|
123
|
+
"OutputVarKibana": "",
|
|
124
|
+
"InputVarKibana": [{}],
|
|
125
|
+
}],
|
|
126
|
+
"ShareLink": "",
|
|
127
|
+
},
|
|
128
|
+
"Filter": {
|
|
129
|
+
"FilterCustomize": [{
|
|
130
|
+
"FilterClasses": ""
|
|
131
|
+
}],
|
|
132
|
+
"OutputVarFilter": "",
|
|
85
133
|
}
|
|
86
134
|
}
|
|
87
135
|
|
|
88
|
-
for( let board of dash["Board
|
|
136
|
+
for( let board of dash["Board"]) {
|
|
89
137
|
let componentsList = clone([])
|
|
90
138
|
for( let component of board["Component"]) {
|
|
139
|
+
if(component["Component"] == null) continue
|
|
91
140
|
let componentTemplate = clone(ComponentsTemplates[component["Component"]])
|
|
141
|
+
componentTemplate.instanceId = ""+raw_dashboard.id //needed to $build file url
|
|
92
142
|
component.fields.reduce(collect,componentTemplate)
|
|
93
143
|
componentTemplate["Component"] = component.Component
|
|
94
144
|
componentsList.push(componentTemplate)
|
|
@@ -96,28 +146,50 @@ function parseDashboard(raw_dashboard){
|
|
|
96
146
|
board["Component"] = componentsList
|
|
97
147
|
}
|
|
98
148
|
|
|
99
|
-
|
|
100
|
-
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
// remove all 'Initial_Templates' and 'instanceId' added for processing
|
|
152
|
+
dash = JSON.parse(JSON.stringify(dash, (k,v) => (k === 'Initial_Template' || k === 'instanceId')? undefined : v))
|
|
153
|
+
dash.vars = {} //Available to every components in component.vars
|
|
154
|
+
|
|
155
|
+
// Add extra info to structure
|
|
156
|
+
dash["Board"].forEach(b => b.Component.forEach(c => {
|
|
157
|
+
// Add user info for permission evaluations
|
|
158
|
+
c.userInfo = userInfo
|
|
159
|
+
c.vars = dash.vars
|
|
101
160
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
161
|
+
if (c.Component == "Menu") {
|
|
162
|
+
c.Text.forEach(t => {
|
|
163
|
+
// If Attention is configured for this menu line then add attention status as user check
|
|
164
|
+
if(t["TextCustomize"][0]["TextAttention"]) {
|
|
165
|
+
t["TextCustomize"][0].AttentionInfo = dashFunctions.instancesList("Dashboard-Attention","name.raw:" + t["TextCustomize"][0]["TextAttention"],1,0,{validity:30})
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
} else if (c.Component == "Totals") {
|
|
105
169
|
c.Line.forEach(l => {
|
|
106
170
|
l.Value = l.Value.map(v => {
|
|
107
|
-
if(v.Arg[2] && v.Arg[2].startsWith("{")) {
|
|
171
|
+
if(v.Arg[2] && (v.Arg[2]+"").startsWith("{")) {
|
|
108
172
|
v.Arg[2] = JSON.parse(v.Arg[2])
|
|
109
173
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
174
|
+
// If Attention is configured for this value line then add attention status as user check
|
|
175
|
+
if(v["ValueCustomize"][0]["ValueAttention"]) {
|
|
176
|
+
v["ValueCustomize"][0].AttentionInfo = dashFunctions.instancesList("Dashboard-Attention","name.raw:" + v["ValueCustomize"][0]["ValueAttention"],1,0,{validity:10})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if(v.Value == 'Label') {
|
|
180
|
+
v.dash_info = {value: v.Arg[0].Arg, state:"ready"}
|
|
181
|
+
} else if(v.Value == 'link') {
|
|
182
|
+
v.dash_info = { value: icon, href: url, state: undefined, isLink: true }
|
|
183
|
+
} else {
|
|
184
|
+
// add dash-info values in Totals
|
|
185
|
+
v.dash_info = dashFunctions[v.Value].apply(this, v['Arg'].map( a => a['Arg'])) // Return DashInfo, which is used by the component
|
|
186
|
+
}
|
|
187
|
+
return v
|
|
115
188
|
})
|
|
116
189
|
})
|
|
117
190
|
}
|
|
118
191
|
}))
|
|
119
192
|
return dash
|
|
120
|
-
|
|
121
193
|
}
|
|
122
194
|
|
|
123
|
-
export { parseDashboard, clone, collect }
|
|
195
|
+
export { parseDashboard, clone, collect }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<i v-if="attentionClasses" :class="attentionClasses" style="line-height: inherit;"></i>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
export default {
|
|
7
|
+
props: {
|
|
8
|
+
attentionInfo: Object,
|
|
9
|
+
classes: String
|
|
10
|
+
},
|
|
11
|
+
computed: {
|
|
12
|
+
inputClasses() { return this.classes || "fa-solid fa-circle pr-1 animate-pulse text-lg align-middle" },
|
|
13
|
+
attentionClasses() {
|
|
14
|
+
let attentionInfo = this.attentionInfo
|
|
15
|
+
if(attentionInfo && attentionInfo.value && attentionInfo.value[0]) {
|
|
16
|
+
let severity = attentionInfo.value[0].severity && attentionInfo.value[0].severity[0] || 0
|
|
17
|
+
if (severity == 0) return ""
|
|
18
|
+
|
|
19
|
+
let baseColor = severity > 0 ? "lime" : "red"
|
|
20
|
+
let severityAbs = Math.abs(severity)
|
|
21
|
+
let colorIntensity = severityAbs > 4 ? 500 : severityAbs * 100
|
|
22
|
+
let valenceColor = baseColor + (colorIntensity ? "-" + colorIntensity: "")
|
|
23
|
+
return this.inputClasses + " " + "text-" + valenceColor
|
|
24
|
+
} else {
|
|
25
|
+
return ""
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
@@ -1,61 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
<div :class="classes" :style="image" >
|
|
3
|
+
<template v-for="(item, i) in components">
|
|
4
|
+
<Label v-if="item['Component'] == 'Label'" :component="item" :key="i" />
|
|
5
|
+
<Menu v-if="item['Component'] == 'Menu'" :component="item" :key="i" />
|
|
6
|
+
<Totals v-if="item['Component'] == 'Totals'" :component="item" :key="i" />
|
|
7
|
+
<Kibana v-if="item['Component'] == 'Kibana'" :component="item" :key="i" />
|
|
8
|
+
<Filtro v-if="item['Component'] == 'Filter'" :component="item" :key="i" />
|
|
9
|
+
</template>
|
|
10
|
+
</div>
|
|
7
11
|
</template>
|
|
8
12
|
|
|
9
13
|
<script>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
showTitle: Boolean
|
|
16
|
-
},
|
|
17
|
-
computed: {
|
|
18
|
-
wrapperClass() {
|
|
19
|
-
const c = "w-full bg-cobbg rounded-md border border-cobline" // hover:ring-1 ring-slate-400/50 ring-offset-1;
|
|
14
|
+
import Label from './Label.vue'
|
|
15
|
+
import Menu from './Menu.vue'
|
|
16
|
+
import Totals from './Totals.vue'
|
|
17
|
+
import Kibana from './Kibana.vue'
|
|
18
|
+
import Filtro from './Filter.vue'
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
7: "md:row-span-7",
|
|
30
|
-
8: "md:row-span-8",
|
|
31
|
-
9: "md:row-span-9",
|
|
32
|
-
10: "md:row-span-10",
|
|
33
|
-
11: "md:row-span-11",
|
|
34
|
-
12: "md:row-span-12",
|
|
35
|
-
"full": "md:row-span-full"
|
|
36
|
-
}
|
|
37
|
-
const rspan = this.rowSpan ? " " + dynamicRowClasses[this.rowSpan] : "";
|
|
38
|
-
|
|
39
|
-
// Force possible dynamic classes to be loaded
|
|
40
|
-
const dynamicColClasses = {
|
|
41
|
-
1: "md:col-span-1",
|
|
42
|
-
2: "md:col-span-2",
|
|
43
|
-
3: "md:col-span-3",
|
|
44
|
-
4: "md:col-span-4",
|
|
45
|
-
5: "md:col-span-5",
|
|
46
|
-
6: "md:col-span-6",
|
|
47
|
-
7: "md:col-span-7",
|
|
48
|
-
8: "md:col-span-8",
|
|
49
|
-
9: "md:col-span-9",
|
|
50
|
-
10: "md:col-span-10",
|
|
51
|
-
11: "md:col-span-11",
|
|
52
|
-
12: "md:col-span-12",
|
|
53
|
-
"full": "md:col-span-full"
|
|
54
|
-
}
|
|
55
|
-
const cspan = this.colSpan ? " " + dynamicColClasses[this.colSpan] : "";
|
|
56
|
-
|
|
57
|
-
return c + rspan + cspan;
|
|
20
|
+
export default {
|
|
21
|
+
components: { Label, Menu, Totals, Kibana, Filtro },
|
|
22
|
+
props: { board: Object },
|
|
23
|
+
computed: {
|
|
24
|
+
options() { return this.board['BoardCustomize'][0] },
|
|
25
|
+
components() { return this.board['Component'] },
|
|
26
|
+
classes() { return this.options['BoardClasses'] || "md:col-span-4 rounded-md border border-gray-300 p-4 m-1" },
|
|
27
|
+
image() { return this.options['Image'] ? "background-image: url(" + this.options['Image'] + ");" : "" }
|
|
58
28
|
}
|
|
59
29
|
}
|
|
60
|
-
}
|
|
61
30
|
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="classes" :style="image" >
|
|
3
|
+
<div :class="width + ' ' + grid">
|
|
4
|
+
<Board v-for="(board,i) in boards" :board="board" :key="i"/>
|
|
5
|
+
</div>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import Board from './Board.vue'
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
components: { Board },
|
|
14
|
+
props: { dashboard: Object },
|
|
15
|
+
computed: {
|
|
16
|
+
options() { return this.dashboard['DashboardCustomize'][0] },
|
|
17
|
+
boards() { return this.dashboard['Board'] },
|
|
18
|
+
classes() { return this.options['DashboardClasses'] || "h-full bg-cover bg-center overflow-auto p-3" },
|
|
19
|
+
width() { return this.options['Width'] || "max-w-6xl mx-auto" },
|
|
20
|
+
grid() { return this.options['Grid'] || "grid grid-flow-row-dense md:grid-cols-12" },
|
|
21
|
+
image() { return this.options['Image'] ? "background-image: url(" + this.options['Image'] + ");" : "" }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex h-fit pb-0 justify-center items-center">
|
|
3
|
+
<textarea :class="classes"
|
|
4
|
+
v-model="inputContent"
|
|
5
|
+
ref="textarea"
|
|
6
|
+
@keyup.enter="applyFilter"
|
|
7
|
+
@focus="resize"
|
|
8
|
+
@keyup="resize"
|
|
9
|
+
placeholder="Pesquisar ..."
|
|
10
|
+
></textarea>
|
|
11
|
+
<button @click="applyFilter" type="submit" class="max-h-11 p-2.5 ml-2 text-sm font-medium text-white bg-blue-700 rounded-lg border border-blue-700 hover:bg-blue-800">
|
|
12
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
export default {
|
|
19
|
+
props: { component: Object },
|
|
20
|
+
data: () => ({
|
|
21
|
+
inputContent: "",
|
|
22
|
+
activeFilter: ""
|
|
23
|
+
}),
|
|
24
|
+
created() {
|
|
25
|
+
this.$nextTick(() => {
|
|
26
|
+
this.applyFilter()
|
|
27
|
+
this.resize()
|
|
28
|
+
})
|
|
29
|
+
},
|
|
30
|
+
updated() {
|
|
31
|
+
// Necessário para quando fazemos back para uma página com o inputContent preenchido mas que não está actualizada nas variáveis
|
|
32
|
+
if(this.activeFilter != this.component.vars[this.outputVar]) {
|
|
33
|
+
this.applyFilter()
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
computed: {
|
|
37
|
+
options() { return this.component['FilterCustomize'][0] },
|
|
38
|
+
outputVar() { return this.component['OutputVarFilter'] || "" },
|
|
39
|
+
classes() { return this.options['FilterClasses'] || "w-full max-w-xs resize-none min-h-min h-min border border-slate-300 rounded-md py-2 px-2 outline-slate-300 leading-5" },
|
|
40
|
+
},
|
|
41
|
+
methods: {
|
|
42
|
+
applyFilter: function() {
|
|
43
|
+
this.inputContent = this.inputContent.trim()
|
|
44
|
+
this.activeFilter = "(" + (this.inputContent ? this.inputContent.replace(/\n/,' ') : "*") +")"
|
|
45
|
+
this.$set(this.component.vars,this.outputVar,this.activeFilter)
|
|
46
|
+
},
|
|
47
|
+
resize() {
|
|
48
|
+
const { textarea } = this.$refs;
|
|
49
|
+
if(this.inputContent && ( textarea.textLength >= textarea.cols || this.inputContent.split("\n").length > 1) ) {
|
|
50
|
+
textarea.style.height = "auto";
|
|
51
|
+
textarea.style.height = (textarea.scrollHeight + 2) + 'px'; // Os 14px são do padding acrescentado
|
|
52
|
+
} else {
|
|
53
|
+
textarea.style.height = "40px";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
</script>
|