Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main improved dashboard links #622

Merged
merged 9 commits into from
Sep 29, 2023
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Changelog
0.x.x (?)
==================

* Extended DashboardLink to support links to dashboards and urls, as per the docs_

.. _`docs`: https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/manage-dashboard-links/#dashboard-links

* Added ...
* Added Minimum option for Timeseries
* Added Maximum option for Timeseries
Expand Down
69 changes: 57 additions & 12 deletions grafanalib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
encourage it by way of some defaults. Rather, they are ways of building
arbitrary Grafana JSON.
"""

from __future__ import annotations
import itertools
import math

import string
import warnings
from numbers import Number
from typing import Literal

import attr
from attr.validators import in_, instance_of
Expand Down Expand Up @@ -74,7 +75,7 @@ def to_json_data(self):
FLOT = 'flot'

ABSOLUTE_TYPE = 'absolute'
DASHBOARD_TYPE = 'dashboard'
DASHBOARD_TYPE = Literal['dashboards', 'link']
padraic-padraic marked this conversation as resolved.
Show resolved Hide resolved
ROW_TYPE = 'row'
GRAPH_TYPE = 'graph'
DISCRETE_TYPE = 'natel-discrete-panel'
Expand Down Expand Up @@ -300,6 +301,9 @@ def to_json_data(self):
DEFAULT_AUTO_COUNT = 30
DEFAULT_MIN_AUTO_INTERVAL = '10s'

DASHBOARD_LINK_ICON = Literal['bolt', 'cloud', 'dashboard', 'doc',
'external link', 'info', 'question']


@attr.s
class Mapping(object):
Expand Down Expand Up @@ -875,24 +879,65 @@ def to_json_data(self):

@attr.s
class DashboardLink(object):
dashboard = attr.ib()
uri = attr.ib()
keepTime = attr.ib(
"""Create a link to other dashboards, or external resources.

Dashboard Links come in two flavours; a list of dashboards, or a direct
link to an arbitrary URL. These are controlled by the ``type`` parameter.
A dashboard list targets a given set of tags, whereas for a link you must
also provide the URL.

See `the documentation <https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/manage-dashboard-links/#dashboard-links>`
for more information.

:param asDropdown: Controls if the list appears in a dropdown rather than
tiling across the dashboard. Affects 'dashboards' type only. Defaults
to False
:param icon: Set the icon, from a predefined list. See
``grafanalib.core.DASHBOARD_LINK_ICON`` for allowed values. Affects
the 'link' type only. Defaults to 'external link'
:param includeVars: Controls if data variables from the current dashboard
are passed as query parameters to the linked target. Defaults to False
:param keepTime: Controls if the current time range is passed as query
parameters to the linked target. Defaults to False
:param tags: A list of tags used to select dashboards for the link.
Affects the 'dashboards' type only. Defaults to an empty list
:param targetBlank: Controls if the link opens in a new tab. Defaults
to False
:param tooltip: Tooltip text that appears when hovering over the link.
Affects the 'link' type only. Defaults to an empty string
:param type: Controls the type of DashboardLink generated. Must be
one of 'dashboards' or 'link'.
:param uri: The url target of the external link. Affects the 'link'
type only.
"""
asDropdown: bool = attr.ib(default=False, validator=instance_of(bool))
icon: DASHBOARD_LINK_ICON = attr.ib(default='external link',
validator=in_(DASHBOARD_LINK_ICON.__args__))
includeVars: bool = attr.ib(default=False, validator=instance_of(bool))
keepTime: bool = attr.ib(
default=True,
validator=instance_of(bool),
)
title = attr.ib(default=None)
type = attr.ib(default=DASHBOARD_TYPE)
tags: list[str] = attr.ib(factory=list, validator=instance_of(list))
targetBlank: bool = attr.ib(default=False, validator=instance_of(bool))
title: str = attr.ib(default="")
tooltip: str = attr.ib(default="", validator=instance_of(str))
type: DASHBOARD_TYPE = attr.ib(default='dashboards',
validator=in_(DASHBOARD_TYPE.__args__))
uri: str = attr.ib(default="", validator=instance_of(str))

def to_json_data(self):
title = self.dashboard if self.title is None else self.title
return {
'dashUri': self.uri,
'dashboard': self.dashboard,
'asDropdown': self.asDropdown,
'icon': self.icon,
'includeVars': self.includeVars,
'keepTime': self.keepTime,
'title': title,
'tags': self.tags,
'targetBlank': self.targetBlank,
'title': self.title,
'tooltip': self.tooltip,
'type': self.type,
'url': self.uri,
'url': self.uri
}


Expand Down
34 changes: 34 additions & 0 deletions grafanalib/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1190,3 +1190,37 @@ def test_sql_target_with_source_files():
assert t.to_json_data()["targets"][0].rawQuery is True
assert t.to_json_data()["targets"][0].rawSql == "SELECT example\nFROM test\nWHERE example='example' AND example_date BETWEEN '1970-01-01' AND '1971-01-01';\n"
print(t.to_json_data()["targets"][0])


class TestDashboardLink():

def test_validators(self):
with pytest.raises(ValueError):
G.DashboardLink(
type='dashboard',
)
with pytest.raises(ValueError):
G.DashboardLink(
icon='not an icon'
)

def test_initialisation(self):
dl = G.DashboardLink().to_json_data()
assert dl['asDropdown'] is False
assert dl['icon'] == 'external link'
assert dl['includeVars'] is False
assert dl['keepTime'] is True
assert not dl['tags']
assert dl['targetBlank'] is False
assert dl['title'] == ""
assert dl['tooltip'] == ""
assert dl['type'] == 'dashboards'
assert dl['url'] == ""

url = 'https://grafana.com'
dl = G.DashboardLink(
uri=url,
type='link'
).to_json_data()
assert dl['url'] == url
assert dl['type'] == 'link'
Loading