Skip to content
Permalink
Browse files

Addition to #10547: Improve existing view link dashlet creation

When adding a new dashlet, which should refer to an existing view,
a dedicated dialog for selecting the view is needed. This is necessary
because the "dashlet edit" dialog needs to know the datasource and
infos of a view before it can be used to edit a linked view dashlet

Now reusing the dialog which is used for cloning existing views as
dashlets.

Change-Id: Id27b74022a5552866a97e6d7f47bfa5250ceccac
  • Loading branch information
LarsMichelsen committed Dec 30, 2019
1 parent 8f0adbb commit f46da9205393fed7c911d1e7bb1b12a3a391f215
@@ -28,7 +28,7 @@
import copy
import json
from typing import ( # pylint: disable=unused-import
Any, Dict, Optional, NamedTuple, Tuple, Text, Type, List, Union,
Any, Dict, Optional, NamedTuple, Tuple, Text, Type, List, Union, Callable,
)
import six

@@ -296,11 +296,6 @@ def sort_index(cls):
# type: () -> int
return cls._spec["sort_index"]

@classmethod
def infos(cls):
# type: () -> List[str]
return cls._spec.get("infos", [])

@classmethod
def single_infos(cls):
# type: () -> List[str]
@@ -370,6 +365,10 @@ def add_url(cls):
return cls._spec["add_urlfunc"]()
return super(LegacyDashlet, cls).add_url()

def infos(self):
# type: () -> List[str]
return self._spec.get("infos", [])

def display_title(self):
# type: () -> Text
title_func = self._spec.get("title_func")
@@ -615,7 +614,7 @@ def _render_dashlet_content(board, dashlet_instance, is_update, mtime):
html.request.set_var("name", dashlet_instance.dashboard_name)
html.request.set_var("mtime", str(mtime))

if dashlet_instance.has_context:
if dashlet_instance.has_context():
visuals.add_context_to_uri_vars(dashlet_instance.context,
dashlet_instance.single_infos())

@@ -1045,6 +1044,21 @@ def _vs_dashboard():
# '----------------------------------------------------------------------'


@cmk.gui.pages.register("create_link_view_dashlet")
def page_create_link_view_dashlet():
# type: () -> None
"""Choose an existing view from the list of available views"""
name = html.request.var('name')
choose_view(name, _('Link existing view'), _create_linked_view_dashlet_spec)


def _create_linked_view_dashlet_spec(dashlet_id, view_name):
# type: (int, str) -> Dict
dashlet = default_dashlet_definition("linked_view")
dashlet["name"] = view_name
return dashlet


@cmk.gui.pages.register("create_view_dashlet")
def page_create_view_dashlet():
# type: () -> None
@@ -1058,7 +1072,16 @@ def page_create_view_dashlet():

else:
# Choose an existing view from the list of available views
choose_view(name)
choose_view(name, _('Copy existing view'), _create_cloned_view_dashlet_spec)


def _create_cloned_view_dashlet_spec(dashlet_id, view_name):
# type: (int, str) -> Dict
dashlet = default_dashlet_definition('view')

# save the original context and override the context provided by the view
copy_view_into_dashlet(dashlet, dashlet_id, view_name)
return dashlet


@cmk.gui.pages.register("create_view_dashlet_infos")
@@ -1083,16 +1106,16 @@ def page_create_view_dashlet_infos():
filename='edit_dashlet.py'))


def choose_view(name):
# type: (DashboardName) -> None
def choose_view(name, title, create_dashlet_spec_func):
# type: (DashboardName, Text, Callable) -> None
import cmk.gui.views as views
vs_view = DropdownChoice(
title=_('View Name'),
title=_('View name'),
choices=views.view_choices,
sorted=True,
)

html.header(_('Create Dashlet from existing View'))
html.header(title)
html.begin_context_buttons()
back_url = html.get_url_input(
"back", "dashboard.py?edit=1&name=%s" % html.urlencode(html.request.var('name')))
@@ -1105,13 +1128,8 @@ def choose_view(name):
vs_view.validate_value(view_name, 'view')

dashboard = get_permitted_dashboards()[name]

# Add the dashlet!
dashlet = default_dashlet_definition('view')

# save the original context and override the context provided by the view
dashlet_id = len(dashboard['dashlets'])
copy_view_into_dashlet(dashlet, dashlet_id, view_name)
dashlet = create_dashlet_spec_func(dashlet_id, view_name)
add_dashlet(dashlet, dashboard)

raise HTTPRedirect('edit_dashlet.py?name=%s&id=%s' %
@@ -1120,7 +1138,7 @@ def choose_view(name):
html.user_error(e)

html.begin_form('choose_view')
forms.header(_('Select View'))
forms.header(_('Select view'))
forms.section(vs_view.title())
vs_view.render_input('view', '')
html.help(vs_view.help())
@@ -1174,6 +1192,10 @@ def page_edit_dashlet():
'single_infos': dashlet_type.single_infos(),
'type': ty,
}

if dashlet_type.has_context():
dashlet["context"] = {}

ident = len(dashboard['dashlets'])

single_infos_raw = html.request.var('single_infos')
@@ -1255,10 +1277,9 @@ def page_edit_dashlet():

def dashlet_info_handler(dashlet):
# type: (DashletConfig) -> List[str]
if dashlet['type'] == 'view':
import cmk.gui.views as views
return views.get_view_infos(dashlet)
return dashlet_registry[dashlet['type']].infos()
dashlet_type = dashlet_registry[dashlet['type']]
dashlet_instance = dashlet_type(board, dashboard, ident, dashlet)
return dashlet_instance.infos()

context_specs = visuals.get_context_specs(dashlet, info_handler=dashlet_info_handler)

@@ -54,8 +54,8 @@ def initial_size(cls):
def initial_refresh_interval(cls):
return 60

@property
def has_context(self):
@classmethod
def has_context(cls):
return True

@abc.abstractmethod
@@ -104,10 +104,10 @@ def sort_index(cls):
raise NotImplementedError()

@classmethod
def infos(cls):
# type: () -> List[str]
"""Return a list of the supported infos (for the visual context) of this dashlet"""
return []
def has_context(cls):
# type: () -> bool
"""Whether or not this dashlet is context sensitive."""
return False

@classmethod
def single_infos(cls):
@@ -202,9 +202,14 @@ def __init__(self, dashboard_name, dashboard, dashlet_id, dashlet):
self._dashlet_spec = dashlet
self._context = self._get_context() # type: Optional[Dict]

def infos(self):
# type: () -> List[str]
"""Return a list of the supported infos (for the visual context) of this dashlet"""
return []

def _get_context(self):
# type: () -> Optional[Dict]
if not self.has_context:
if not self.has_context():
return None

return visuals.get_merged_context(
@@ -213,12 +218,6 @@ def _get_context(self):
self._dashlet_spec["context"],
)

@property
def has_context(self):
# type: () -> bool
"""Whether or not this dashlet is context sensitive."""
return False

@property
def context(self):
# type: () -> Dict
@@ -284,7 +283,7 @@ def show(self):
def _add_context_vars_to_url(self, url):
# type: (str) -> str
"""Adds missing context variables to the given URL"""
if not self.has_context:
if not self.has_context():
return url

context_vars = self._dashlet_context_vars()
@@ -24,6 +24,7 @@
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.

from typing import List, Optional # pylint: disable=unused-import
import cmk.gui.views as views
import cmk.gui.visuals as visuals
from cmk.gui.i18n import _
@@ -47,8 +48,8 @@ def sort_index(cls):
def initial_size(cls):
return (40, 20)

@property
def has_context(self):
@classmethod
def has_context(cls):
return True

def _show_view_as_dashlet(self, view_spec):
@@ -73,6 +74,10 @@ def _show_view_as_dashlet(self, view_spec):
view_renderer = views.GUIViewRenderer(view, show_buttons=False)
views.show_view(view, view_renderer)

def _get_infos_from_view_spec(self, view_spec):
ds_name = view_spec["datasource"]
return views.data_source_registry[ds_name]().infos


@dashlet_registry.register
class ViewDashlet(ABCViewDashlet):
@@ -112,6 +117,15 @@ def add_url(cls):
def update(self):
self._show_view_as_dashlet(self._dashlet_spec)

def infos(self):
# Hack for create mode of dashlet editor. The user first selects a datasource and then the
# single contexts, the dashlet editor needs to use these information.
if html.myfile == "edit_dashlet" and html.request.has_var("datasource"):
ds_name = html.request.var('datasource')
return views.data_source_registry[ds_name]().infos

return self._get_infos_from_view_spec(self._dashlet_spec)


@dashlet_registry.register
class LinkedViewDashlet(ABCViewDashlet):
@@ -147,6 +161,12 @@ def vs_parameters(cls):
),
]

@classmethod
def add_url(cls):
return 'create_link_view_dashlet.py?name=%s&mode=create&back=%s' % \
(html.urlencode(html.request.var('name')),
html.urlencode(html.makeuri([('edit', '1')])))

def _get_view_spec(self):
view_name = self._dashlet_spec["name"]
view_spec = views.get_permitted_views().get(view_name)
@@ -166,3 +186,6 @@ def title_url(self):

def update(self):
self._show_view_as_dashlet(self._get_view_spec())

def infos(self):
return self._get_infos_from_view_spec(self._get_view_spec())
@@ -81,16 +81,19 @@ def _expected_intervals():


@pytest.mark.parametrize("type_name,expected_refresh_interval", _expected_intervals())
def test_dashlet_refresh_intervals(register_builtin_html, type_name, expected_refresh_interval):
def test_dashlet_refresh_intervals(register_builtin_html, type_name, expected_refresh_interval,
monkeypatch):
dashlet_type = dashboard.dashlet_registry[type_name]
assert dashlet_type.initial_refresh_interval() == expected_refresh_interval

dashlet_spec = {
"type": type_name,
}
if dashlet_type.has_context:
if dashlet_type.has_context():
dashlet_spec["context"] = {}

monkeypatch.setattr(dashboard.Dashlet, "_get_context", lambda s: {})

dashlet = dashlet_type(dashboard_name="main",
dashboard=dashboard._add_context_to_dashboard({}),
dashlet_id=1,
@@ -267,7 +270,6 @@ def test_old_dashlet_settings():


def test_dashlet_type_defaults(register_builtin_html):
assert dashboard.Dashlet.infos() == []
assert dashboard.Dashlet.single_infos() == []
assert dashboard.Dashlet.is_selectable() is True
assert dashboard.Dashlet.is_resizable() is True
@@ -290,6 +292,7 @@ def test_dashlet_defaults():
dashboard={},
dashlet_id=1,
dashlet={"xyz": "abc"})
assert dashlet.infos() == []
assert dashlet.dashlet_id == 1
assert dashlet.dashlet_spec == {"xyz": "abc"}
assert dashlet.dashboard_name == "main"
@@ -57,6 +57,7 @@ def test_registered_pages():
'create_view',
'create_view_dashlet',
'create_view_dashlet_infos',
'create_link_view_dashlet',
'create_view_infos',
'custom_snapins',
'dashboard',

0 comments on commit f46da92

Please sign in to comment.
You can’t perform that action at this time.