Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
a5d5f3d8
Commit
a5d5f3d8
authored
Aug 02, 2017
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add ad hoc filters directly from table panel cells, kibana 3 style, #8052
parent
c17b5d13
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
119 additions
and
36 deletions
+119
-36
public/app/features/dashboard/ad_hoc_filters.ts
+3
-3
public/app/features/dashboard/submenu/submenu.ts
+1
-4
public/app/features/templating/editor_ctrl.ts
+3
-7
public/app/features/templating/specs/variable_srv_specs.ts
+4
-1
public/app/features/templating/variable_srv.ts
+39
-5
public/app/plugins/datasource/elasticsearch/elastic_response.ts
+3
-3
public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts
+1
-1
public/app/plugins/panel/table/module.ts
+17
-1
public/app/plugins/panel/table/renderer.ts
+24
-9
public/app/plugins/panel/table/transformers.ts
+10
-2
public/sass/components/_panel_table.scss
+14
-0
No files found.
public/app/features/dashboard/ad_hoc_filters.ts
View file @
a5d5f3d8
...
...
@@ -10,9 +10,10 @@ export class AdHocFiltersCtrl {
removeTagFilterSegment
:
any
;
/** @ngInject */
constructor
(
private
uiSegmentSrv
,
private
datasourceSrv
,
private
$q
,
private
templateSrv
,
private
$rootScope
)
{
constructor
(
private
uiSegmentSrv
,
private
datasourceSrv
,
private
$q
,
private
variableSrv
,
private
$scope
,
private
$rootScope
)
{
this
.
removeTagFilterSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove filter --'
});
this
.
buildSegmentModel
();
this
.
$rootScope
.
onAppEvent
(
'template-variable-value-updated'
,
this
.
buildSegmentModel
.
bind
(
this
),
$scope
);
}
buildSegmentModel
()
{
...
...
@@ -141,8 +142,7 @@ export class AdHocFiltersCtrl {
}
this
.
variable
.
setFilters
(
filters
);
this
.
$rootScope
.
$emit
(
'template-variable-value-updated'
);
this
.
$rootScope
.
$broadcast
(
'refresh'
);
this
.
variableSrv
.
variableUpdated
(
this
.
variable
,
true
);
}
}
...
...
public/app/features/dashboard/submenu/submenu.ts
View file @
a5d5f3d8
...
...
@@ -22,10 +22,7 @@ export class SubmenuCtrl {
}
variableUpdated
(
variable
)
{
this
.
variableSrv
.
variableUpdated
(
variable
).
then
(()
=>
{
this
.
$rootScope
.
$emit
(
'template-variable-value-updated'
);
this
.
$rootScope
.
$broadcast
(
'refresh'
);
});
this
.
variableSrv
.
variableUpdated
(
variable
,
true
);
}
openEditView
(
editview
)
{
...
...
public/app/features/templating/editor_ctrl.ts
View file @
a5d5f3d8
...
...
@@ -55,9 +55,8 @@ export class VariableEditorCtrl {
$scope
.
add
=
function
()
{
if
(
$scope
.
isValid
())
{
$scope
.
variables
.
push
(
$scope
.
current
);
variableSrv
.
addVariable
(
$scope
.
current
);
$scope
.
update
();
$scope
.
dashboard
.
updateSubmenuVisibility
();
}
};
...
...
@@ -114,9 +113,8 @@ export class VariableEditorCtrl {
$scope
.
duplicate
=
function
(
variable
)
{
var
clone
=
_
.
cloneDeep
(
variable
.
getSaveModel
());
$scope
.
current
=
variableSrv
.
createVariableFromModel
(
clone
);
$scope
.
variables
.
push
(
$scope
.
current
);
$scope
.
current
.
name
=
'copy_of_'
+
variable
.
name
;
$scope
.
dashboard
.
updateSubmenuVisibility
(
);
$scope
.
variableSrv
.
addVariable
(
$scope
.
current
);
};
$scope
.
update
=
function
()
{
...
...
@@ -150,9 +148,7 @@ export class VariableEditorCtrl {
};
$scope
.
removeVariable
=
function
(
variable
)
{
var
index
=
_
.
indexOf
(
$scope
.
variables
,
variable
);
$scope
.
variables
.
splice
(
index
,
1
);
$scope
.
dashboard
.
updateSubmenuVisibility
();
variableSrv
.
removeVariable
(
variable
);
};
}
}
...
...
public/app/features/templating/specs/variable_srv_specs.ts
View file @
a5d5f3d8
...
...
@@ -22,6 +22,7 @@ describe('VariableSrv', function() {
ctx
.
variableSrv
.
init
({
templating
:
{
list
:
[]},
events
:
new
Emitter
(),
updateSubmenuVisibility
:
sinon
.
stub
(),
});
ctx
.
$rootScope
.
$digest
();
}));
...
...
@@ -41,7 +42,9 @@ describe('VariableSrv', function() {
ctx
.
datasourceSrv
.
getMetricSources
=
sinon
.
stub
().
returns
(
scenario
.
metricSources
);
scenario
.
variable
=
ctx
.
variableSrv
.
addVariable
(
scenario
.
variableModel
);
scenario
.
variable
=
ctx
.
variableSrv
.
createVariableFromModel
(
scenario
.
variableModel
);
ctx
.
variableSrv
.
addVariable
(
scenario
.
variable
);
ctx
.
variableSrv
.
updateOptions
(
scenario
.
variable
);
ctx
.
$rootScope
.
$digest
();
});
...
...
public/app/features/templating/variable_srv.ts
View file @
a5d5f3d8
...
...
@@ -90,17 +90,24 @@ export class VariableSrv {
return
variable
;
}
addVariable
(
model
)
{
var
variable
=
this
.
createVariableFromModel
(
model
);
addVariable
(
variable
)
{
this
.
variables
.
push
(
variable
);
return
variable
;
this
.
templateSrv
.
updateTemplateData
();
this
.
dashboard
.
updateSubmenuVisibility
();
}
removeVariable
(
variable
)
{
var
index
=
_
.
indexOf
(
this
.
variables
,
variable
);
this
.
variables
.
splice
(
index
,
1
);
this
.
templateSrv
.
updateTemplateData
();
this
.
dashboard
.
updateSubmenuVisibility
();
}
updateOptions
(
variable
)
{
return
variable
.
updateOptions
();
}
variableUpdated
(
variable
)
{
variableUpdated
(
variable
,
emitChangeEvents
?
)
{
// if there is a variable lock ignore cascading update because we are in a boot up scenario
if
(
variable
.
initLock
)
{
return
this
.
$q
.
when
();
...
...
@@ -117,7 +124,12 @@ export class VariableSrv {
}
});
return
this
.
$q
.
all
(
promises
);
return
this
.
$q
.
all
(
promises
).
then
(()
=>
{
if
(
emitChangeEvents
)
{
this
.
$rootScope
.
$emit
(
'template-variable-value-updated'
);
this
.
$rootScope
.
$broadcast
(
'refresh'
);
}
});
}
selectOptionsForCurrentValue
(
variable
)
{
...
...
@@ -218,6 +230,28 @@ export class VariableSrv {
// update url
this
.
$location
.
search
(
params
);
}
setAdhocFilter
(
options
)
{
var
variable
=
_
.
find
(
this
.
variables
,
{
type
:
'adhoc'
,
datasource
:
options
.
datasource
});
if
(
!
variable
)
{
variable
=
this
.
createVariableFromModel
({
name
:
'Filters'
,
type
:
'adhoc'
,
datasource
:
options
.
datasource
});
this
.
addVariable
(
variable
);
}
let
filters
=
variable
.
filters
;
let
filter
=
_
.
find
(
filters
,
{
key
:
options
.
key
,
value
:
options
.
value
});
if
(
!
filter
)
{
filter
=
{
key
:
options
.
key
,
value
:
options
.
value
};
filters
.
push
(
filter
);
}
filter
.
operator
=
options
.
operator
;
variable
.
setFilters
(
filters
);
this
.
variableUpdated
(
variable
,
true
);
}
}
coreModule
.
service
(
'variableSrv'
,
VariableSrv
);
public/app/plugins/datasource/elasticsearch/elastic_response.ts
View file @
a5d5f3d8
...
...
@@ -100,9 +100,9 @@ ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, targe
// add columns
if
(
table
.
columns
.
length
===
0
)
{
for
(
let
propKey
of
_
.
keys
(
props
))
{
table
.
addColumn
({
text
:
propKey
});
table
.
addColumn
({
text
:
propKey
,
filterable
:
true
});
}
table
.
addColumn
({
text
:
aggDef
.
field
});
table
.
addColumn
({
text
:
aggDef
.
field
,
filterable
:
true
});
}
// helper func to add values to value array
...
...
@@ -265,7 +265,7 @@ ElasticResponse.prototype.nameSeries = function(seriesList, target) {
};
ElasticResponse
.
prototype
.
processHits
=
function
(
hits
,
seriesList
)
{
var
series
=
{
target
:
'docs'
,
type
:
'docs'
,
datapoints
:
[],
total
:
hits
.
total
};
var
series
=
{
target
:
'docs'
,
type
:
'docs'
,
datapoints
:
[],
total
:
hits
.
total
,
filterable
:
true
};
var
propName
,
hit
,
doc
,
i
;
for
(
i
=
0
;
i
<
hits
.
hits
.
length
;
i
++
)
{
...
...
public/app/plugins/datasource/elasticsearch/specs/elastic_response_specs.ts
View file @
a5d5f3d8
...
...
@@ -389,7 +389,7 @@ describe('ElasticResponse', function() {
it
(
'should return table with byte and count'
,
function
()
{
expect
(
result
.
data
[
0
].
rows
.
length
).
to
.
be
(
3
);
expect
(
result
.
data
[
0
].
columns
).
to
.
eql
([{
text
:
'bytes'
},
{
text
:
'Count'
}]);
expect
(
result
.
data
[
0
].
columns
).
to
.
eql
([{
text
:
'bytes'
,
filterable
:
true
},
{
text
:
'Count'
}]);
});
});
...
...
public/app/plugins/panel/table/module.ts
View file @
a5d5f3d8
...
...
@@ -50,8 +50,9 @@ class TablePanelCtrl extends MetricsPanelCtrl {
};
/** @ngInject */
constructor
(
$scope
,
$injector
,
templateSrv
,
private
annotationsSrv
,
private
$sanitize
)
{
constructor
(
$scope
,
$injector
,
templateSrv
,
private
annotationsSrv
,
private
$sanitize
,
private
variableSrv
)
{
super
(
$scope
,
$injector
);
this
.
pageIndex
=
0
;
if
(
this
.
panel
.
styles
===
void
0
)
{
...
...
@@ -223,10 +224,25 @@ class TablePanelCtrl extends MetricsPanelCtrl {
selector
:
'[data-link-tooltip]'
});
function
addFilterClicked
(
e
)
{
let
filterData
=
$
(
e
.
currentTarget
).
data
();
var
options
=
{
datasource
:
panel
.
datasource
,
key
:
data
.
columns
[
filterData
.
column
].
text
,
value
:
data
.
rows
[
filterData
.
row
][
filterData
.
column
],
operator
:
filterData
.
operator
,
};
ctrl
.
variableSrv
.
setAdhocFilter
(
options
);
console
.
log
(
'clicked'
,
options
);
}
elem
.
on
(
'click'
,
'.table-panel-page-link'
,
switchPage
);
elem
.
on
(
'click'
,
'.table-panel-filter-link'
,
addFilterClicked
);
var
unbindDestroy
=
scope
.
$on
(
'$destroy'
,
function
()
{
elem
.
off
(
'click'
,
'.table-panel-page-link'
);
elem
.
off
(
'click'
,
'.table-panel-filter-link'
);
unbindDestroy
();
});
...
...
public/app/plugins/panel/table/renderer.ts
View file @
a5d5f3d8
...
...
@@ -140,9 +140,12 @@ export class TableRenderer {
renderCell
(
columnIndex
,
rowIndex
,
value
,
addWidthHack
=
false
)
{
value
=
this
.
formatColumnValue
(
columnIndex
,
value
);
var
column
=
this
.
table
.
columns
[
columnIndex
];
var
style
=
''
;
var
cellClasses
=
[];
var
cellClass
=
''
;
if
(
this
.
colorState
.
cell
)
{
style
=
' style="background-color:'
+
this
.
colorState
.
cell
+
';color: white"'
;
this
.
colorState
.
cell
=
null
;
...
...
@@ -161,26 +164,25 @@ export class TableRenderer {
if
(
value
===
undefined
)
{
style
=
' style="display:none;"'
;
this
.
table
.
columns
[
columnIndex
]
.
hidden
=
true
;
column
.
hidden
=
true
;
}
else
{
this
.
table
.
columns
[
columnIndex
]
.
hidden
=
false
;
column
.
hidden
=
false
;
}
var
columnStyle
=
this
.
table
.
columns
[
columnIndex
].
style
;
if
(
columnStyle
&&
columnStyle
.
preserveFormat
)
{
if
(
column
.
style
&&
column
.
style
.
preserveFormat
)
{
cellClasses
.
push
(
"table-panel-cell-pre"
);
}
var
columnHtml
=
value
+
widthHack
;
var
columnHtml
=
widthHack
+
value
;
if
(
column
Style
&&
columnS
tyle
.
link
)
{
if
(
column
.
style
&&
column
.
s
tyle
.
link
)
{
// Render cell as link
var
scopedVars
=
this
.
renderRowVariables
(
rowIndex
);
scopedVars
[
'__cell'
]
=
{
value
:
value
};
var
cellLink
=
this
.
templateSrv
.
replace
(
column
S
tyle
.
linkUrl
,
scopedVars
);
var
cellLinkTooltip
=
this
.
templateSrv
.
replace
(
column
S
tyle
.
linkTooltip
,
scopedVars
);
var
cellTarget
=
column
S
tyle
.
linkTargetBlank
?
'_blank'
:
''
;
var
cellLink
=
this
.
templateSrv
.
replace
(
column
.
s
tyle
.
linkUrl
,
scopedVars
);
var
cellLinkTooltip
=
this
.
templateSrv
.
replace
(
column
.
s
tyle
.
linkTooltip
,
scopedVars
);
var
cellTarget
=
column
.
s
tyle
.
linkTargetBlank
?
'_blank'
:
''
;
cellClasses
.
push
(
"table-panel-cell-link"
);
columnHtml
=
`
...
...
@@ -190,6 +192,19 @@ export class TableRenderer {
`
;
}
if
(
column
.
filterable
)
{
cellClasses
.
push
(
"table-panel-cell-filterable"
);
columnHtml
+=
`
<a class="table-panel-filter-link" data-link-tooltip data-original-title="Filter out value" data-placement="bottom"
data-row="
${
rowIndex
}
" data-column="
${
columnIndex
}
" data-operator="!=">
<i class="fa fa-search-minus"></i>
</a>
<a class="table-panel-filter-link" data-link-tooltip data-original-title="Filter for value" data-placement="bottom"
data-row="
${
rowIndex
}
" data-column="
${
columnIndex
}
" data-operator="=">
<i class="fa fa-search-plus"></i>
</a>`
;
}
if
(
cellClasses
.
length
)
{
cellClass
=
' class="'
+
cellClasses
.
join
(
' '
)
+
'"'
;
}
...
...
public/app/plugins/panel/table/transformers.ts
View file @
a5d5f3d8
...
...
@@ -185,8 +185,16 @@ transformers['json'] = {
},
transform
:
function
(
data
,
panel
,
model
)
{
var
i
,
y
,
z
;
for
(
i
=
0
;
i
<
panel
.
columns
.
length
;
i
++
)
{
model
.
columns
.
push
({
text
:
panel
.
columns
[
i
].
text
});
for
(
let
column
of
panel
.
columns
)
{
var
tableCol
:
any
=
{
text
:
column
.
text
};
// if filterable data then set columns to filterable
if
(
data
.
length
>
0
&&
data
[
0
].
filterable
)
{
tableCol
.
filterable
=
true
;
}
model
.
columns
.
push
(
tableCol
);
}
if
(
model
.
columns
.
length
===
0
)
{
...
...
public/sass/components/_panel_table.scss
View file @
a5d5f3d8
...
...
@@ -91,9 +91,23 @@
&
.cell-highlighted
:hover
{
background-color
:
$tight-form-func-bg
;
}
&
:hover
{
.table-panel-filter-link
{
visibility
:
visible
;
}
}
}
}
.table-panel-filter-link
{
visibility
:
hidden
;
color
:
$text-color-weak
;
float
:
right
;
display
:
block
;
padding
:
0
5px
;
}
.table-panel-header-bg
{
background
:
$grafanaListAccent
;
border-top
:
2px
solid
$body-bg
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment