Skip to content

Commit

Permalink
Merge 5226543 into 42d1e0b
Browse files Browse the repository at this point in the history
  • Loading branch information
fredkingham committed Oct 4, 2018
2 parents 42d1e0b + 5226543 commit 78d05fe
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 12 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Expand Up @@ -7,6 +7,10 @@

* Adds a method `.demographics()` to `opal.models.Patient` which returns the relevant demographics instance.

* Adds a `for_user` method on to the menu item. This method
takes a user and by default returns True. Override this
to decide if a menu item should be shown in the nav bar.

### 0.11.2 (Bugfix Release)

Includes referencedata JSON files in Manifest.
Expand Down
9 changes: 7 additions & 2 deletions doc/docs/reference/core_menus.md
Expand Up @@ -2,7 +2,7 @@

Opal provides classes and methods to define application menus programatically.

## opal.core.MenuItem
### opal.core.MenuItem

An item in an application menu.

Expand All @@ -15,7 +15,12 @@ An item in an application menu.
* display - the text to display in this menu item
* index - a number to use as the primary sort order for your menu items

## opal.core.Menu
**Methods**

#### for_user
A method that takes a user and returns True by default. Override this if you want menu items hidden for certain users.

### opal.core.Menu

The menu for an Opal application. On initialization it will construct a menu
for the current user, pulling items from the current app, and any plugins.
2 changes: 1 addition & 1 deletion opal/core/application.py
Expand Up @@ -142,7 +142,7 @@ def get_menu_items(klass, user=None):
items.append(logout)
if user.is_staff:
items.append(admin)
return items
return [item for item in items if item.for_user(user)]

@classmethod
def get_menu(klass, user=None):
Expand Down
10 changes: 5 additions & 5 deletions opal/core/menus.py
Expand Up @@ -33,6 +33,9 @@ def __ne__(self, other):

return not self == other

def for_user(self, user):
return True


class Menu(object):

Expand All @@ -46,13 +49,10 @@ def __init__(self, user=None):
# If we don't += this here, we start appending to the
# list attached to the active Application class.
# Which is suboptimal.
app_items = app.get_menu_items(user=self.user)
for item in app_items:
self.items.append(item)
self.items = app.get_menu_items(self.user)

for plugin in plugins.OpalPlugin.list():
for item in plugin.menuitems:
self.items.append(item)
self.items.extend(plugin.get_menu_items(self.user))

def __iter__(self):

Expand Down
4 changes: 4 additions & 0 deletions opal/core/plugins.py
Expand Up @@ -62,3 +62,7 @@ def get_javascripts(klass):
Return the javascripts for our plugin
"""
return [j for j in klass.javascripts]

@classmethod
def get_menu_items(cls, user=None):
return [i for i in cls.menuitems if i.for_user(user)]
23 changes: 22 additions & 1 deletion opal/tests/test_core_application.py
Expand Up @@ -65,7 +65,28 @@ def test_get_javascripts_updating_side_effects(self):
def test_get_menu_items(self):
self.assertEqual(
application.OpalApplication.menuitems,
application.OpalApplication.get_menu_items())
application.OpalApplication.get_menu_items()
)

def test_get_menu_items_for_user(self):
class MenuItemIncluded(menus.MenuItem):
pass

class MenuItemNotIncluded(menus.MenuItem):
def for_user(self, user):
return False

menu_item_included = MenuItemIncluded()
menu_item_not_included = MenuItemNotIncluded()

self.app.menuitems = [
menu_item_included, menu_item_not_included
]

self.assertEqual(
[menu_item_included],
list(self.app.get_menu_items())
)

def test_get_menu_items_includes_logout_for_authenticated_users(self):
user = self.user
Expand Down
34 changes: 32 additions & 2 deletions opal/tests/test_core_menus.py
Expand Up @@ -42,6 +42,10 @@ def test_repr(self):
item = menus.MenuItem(href="/wat/")
self.assertEqual("<Opal MenuItem href: '/wat/'>", item.__repr__())

def test_for_user(self):
item = menus.MenuItem(href="/wat/")
self.assertTrue(item.for_user(self.user))

def test_equality(self):
item1 = menus.MenuItem(
template_name='menu.html',
Expand Down Expand Up @@ -88,7 +92,6 @@ def test_equality(self):
@patch('opal.core.plugins.OpalPlugin.list')
@patch('opal.core.application.get_app')
class MenuTestCase(OpalTestCase):

def setUp(self):
self.app = MagicMock(name='App')
self.app.get_menu_items.return_value = []
Expand All @@ -107,15 +110,42 @@ def test_sets_items_from_app(self, get_app, plugin_list):
menu = menus.Menu(user=self.user)
self.assertEqual(menu_items, menu.items)

def test_excludes_items_from_app_if_for_user_is_false(
self, get_app, plugin_list
):
get_app.return_value = self.app
plugin_list.return_value = []
menu_item = menus.MenuItem()
menu_items = [menu_item]
self.app.menuitems = menu_items
with patch.object(menu_item, "for_user") as for_user:
for_user.return_value = False
menu = menus.Menu(user=self.user)
self.assertEqual([], menu.items)

def test_sets_items_from_plugin(self, get_app, plugin_list):
get_app.return_value = self.app
menu_items = [menus.MenuItem()]
mock_plugin = MagicMock(name='Plugin')
mock_plugin.menuitems = menu_items
mock_plugin.get_menu_items.return_value = menu_items
plugin_list.return_value = [mock_plugin]
menu = menus.Menu(user=self.user)
self.assertEqual(menu_items, menu.items)

def test_excludes_items_from_plugin_if_for_user_is_false(
self, get_app, plugin_list
):
get_app.return_value = self.app
menu_item = menus.MenuItem()
menu_items = [menu_item]
mock_plugin = MagicMock(name='Plugin')
mock_plugin.menuitems = menu_items
plugin_list.return_value = [mock_plugin]
with patch.object(menu_item, "for_user") as for_user:
for_user.return_value = False
menu = menus.Menu(user=self.user)
self.assertEqual([], menu.items)

def test_iter_sorts(self, get_app, plugin_list):
get_app.return_value = self.app
plugin_list.return_value = []
Expand Down
24 changes: 23 additions & 1 deletion opal/tests/test_core_plugins.py
Expand Up @@ -8,6 +8,7 @@

from opal.core.test import OpalTestCase
from opal.core import menus
from opal.utils import AbstractBase

from opal.core import plugins

Expand All @@ -18,7 +19,7 @@ class TestPlugin1(plugins.OpalPlugin):
javascripts = ['js/test/notreal.js']
stylesheets = ['css/test/notreal.css']
head_extra = ['notareal_template.html']
menuitems = [ menus.MenuItem(display='test') ]
menuitems = [menus.MenuItem(display='test') ]
angular_module_deps = ['js/test.angular.mod.js']

class TestPlugin2(plugins.OpalPlugin):
Expand Down Expand Up @@ -74,3 +75,24 @@ def test_get_javascripts_side_effects(self):
js_orig = copy.copy(js)
js.append('icanhazcheezburgerify.js')
self.assertEqual(js_orig, self.plugin1.get_javascripts())

def test_get_menu_items(self):
class MenuItemIncluded(menus.MenuItem):
pass

class MenuItemNotIncluded(menus.MenuItem):
def for_user(self, user):
return False

menu_item_included = MenuItemIncluded()
menu_item_not_included = MenuItemNotIncluded()

class TestPlugin(plugins.OpalPlugin, AbstractBase):
menuitems = [
menu_item_included, menu_item_not_included
]

self.assertEqual(
[menu_item_included],
list(TestPlugin.get_menu_items())
)

0 comments on commit 78d05fe

Please sign in to comment.