From 0e73bce32b9bed68c15499a7dd749523722cdf8b Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Nov 21 2017 10:23:46 +0000 Subject: allow widgets to specify what hubs they can be added to Adds a new optional property that can be set in a widget to allow a widget to specify what hub types it can be added to. The new property is a list of the hub types it can be added to, for example: ['user'] to only be able to be added to a user hub. By default, the new property is set to all hub types, i.e. ['user', 'group'] Signed-off-by: Ryan Lerch --- diff --git a/hubs/tests/test_widget_base.py b/hubs/tests/test_widget_base.py index 2db5f36..3fc6d64 100644 --- a/hubs/tests/test_widget_base.py +++ b/hubs/tests/test_widget_base.py @@ -58,6 +58,13 @@ class WidgetTest(APPTest): self.assertRaisesRegexp( AttributeError, '"position" .*', test_widget.validate) test_widget.position = "both" + test_widget.hub_types = "invalid" + self.assertRaisesRegexp( + AttributeError, '"hub_types" .*', test_widget.validate) + test_widget.hub_types = ['invalid'] + self.assertRaisesRegexp( + AttributeError, '"hub_types" .*', test_widget.validate) + test_widget.hub_types = ['user'] self.assertRaisesRegexp( AttributeError, '.* "root" .*', test_widget.validate) test_widget.views["root"] = Mock() @@ -150,6 +157,7 @@ class WidgetTest(APPTest): 'contentUrl': '/ralph/w/about/{}/'.format(widget.idx), 'cssClass': None, 'hiddenIfEmpty': False, + 'hub_types': ['user', 'group'], 'idx': widget.idx, 'index': 500, 'isReact': False, diff --git a/hubs/tests/views/test_api_hub_widget.py b/hubs/tests/views/test_api_hub_widget.py index 23bcb43..f75cc21 100644 --- a/hubs/tests/views/test_api_hub_widget.py +++ b/hubs/tests/views/test_api_hub_widget.py @@ -74,13 +74,26 @@ class TestAPIHubWidgets(APPTest): "does-not-exist", [w["name"] for w in response_data["data"]]) def test_get_available(self): - response = self.check_url("/api/widgets/") + # first, test that available widgets on a user hub returns all + # the widgets in the registry. At the moment, the subscription + # widget is the only widget that is resctrited (it is not available) + # on the group hub. + response = self.check_url("/api/hubs/ralph/available-widgets/") response_data = json.loads(response.get_data(as_text=True)) self.assertEqual(response_data["status"], "OK") self.assertListEqual( [w["name"] for w in response_data["data"]], list(registry.keys())) + # next, test that a group hub returns all the widgets other than the + # subscription widget + response = self.check_url("/api/hubs/infra/available-widgets/") + response_data = json.loads(response.get_data(as_text=True)) + self.assertEqual(response_data["status"], "OK") + self.assertListEqual( + [w["name"] for w in response_data["data"]], + [w for w in list(registry.keys()) if w != "subscriptions"]) + def test_post_invalid_request(self): invalid_data = [ { diff --git a/hubs/tests/widgets/test_halp.py b/hubs/tests/widgets/test_halp.py index 72db810..004de8c 100644 --- a/hubs/tests/widgets/test_halp.py +++ b/hubs/tests/widgets/test_halp.py @@ -138,6 +138,7 @@ class HalpViewsTestCase(WidgetTest): 'config': {'hubs': ['fedora-devel'], 'per_page': 3}, 'cssClass': None, 'hiddenIfEmpty': False, + 'hub_types': ['user', 'group'], 'idx': self.widget.idx, 'index': 9, 'isReact': True, diff --git a/hubs/views/api/hub_widget.py b/hubs/views/api/hub_widget.py index c818cc4..0871535 100644 --- a/hubs/views/api/hub_widget.py +++ b/hubs/views/api/hub_widget.py @@ -15,11 +15,15 @@ from hubs.utils.views import ( log = logging.getLogger(__name__) -@app.route('/api/widgets/', methods=['GET']) -def api_widgets(): +@app.route('/api/hubs//available-widgets/', methods=['GET']) +def api_widgets(hub): widgets = [] + hub = get_hub(hub) for widget in registry.values(): - widgets.append(widget.get_props(None)) + if hub.user_hub and 'user' in widget.hub_types: + widgets.append(widget.get_props(None)) + if not hub.user_hub and 'group' in widget.hub_types: + widgets.append(widget.get_props(None)) return flask.jsonify({"status": "OK", "data": widgets}) diff --git a/hubs/views/hub.py b/hubs/views/hub.py index a6dbb1a..f253d0d 100644 --- a/hubs/views/hub.py +++ b/hubs/views/hub.py @@ -21,7 +21,7 @@ def hub(name): } urls = { "widgets": flask.url_for("api_hub_widgets", hub=hub.name), - "availableWidgets": flask.url_for("api_widgets"), + "availableWidgets": flask.url_for("api_widgets", hub=hub.name), "sse": get_sse_url("hub/{}".format(hub.name)), "hub": flask.url_for("api_hub", name=hub.name), "hubConfig": flask.url_for("api_hub_config", name=hub.name), diff --git a/hubs/widgets/base.py b/hubs/widgets/base.py index db6a67d..55767bd 100644 --- a/hubs/widgets/base.py +++ b/hubs/widgets/base.py @@ -28,6 +28,8 @@ class Widget(object): position (str): The position of the widget in the rendered page. It should be one of the following values: ``left``, ``right``, or ``both``. + hub_types (list): The hub types the widget is available on. By default + it contains all the hubs types, i.e. ``['user','group']`` parameters (list): A list of dictionaries that describe a widget's configuration. See :py:class:`hubs.widgets.base.WidgetParameter`. views_module (list): The Python path to the module where the widget @@ -55,6 +57,7 @@ class Widget(object): is_react = False is_large = False hidden_if_empty = False + hub_types = ['user', 'group'] def __init__(self): if self.name is None: @@ -94,6 +97,10 @@ class Widget(object): raise AttributeError( '"position" attribute is not: `left`, `right` or `both`' ) + if not set(self.hub_types).issubset(['user', 'group']): + raise AttributeError( + '"hub_types" attributes must only contain: `user` and `group`' + ) root_view = self.get_views().get("root") if root_view is None: if not self.is_react: @@ -238,6 +245,7 @@ class Widget(object): params=[ param.to_dict() for param in self.get_parameters() ], + hub_types=self.hub_types, ) if instance is not None: props.update({ diff --git a/hubs/widgets/subscriptions/__init__.py b/hubs/widgets/subscriptions/__init__.py index 01a1f57..6374b8a 100644 --- a/hubs/widgets/subscriptions/__init__.py +++ b/hubs/widgets/subscriptions/__init__.py @@ -29,6 +29,7 @@ class Subscriptions(Widget): validator=validators.Username, help="A FAS username.", )] + hub_types = ['user'] class BaseView(RootWidgetView):