def test_blueprint(self): Menu(self.app) blueprint = Blueprint("foo", "foo", url_prefix="/foo") @self.app.route("/test") @register_menu(self.app, ".", "Test") def test(): return "test" @blueprint.route("/bar") @register_menu(blueprint, "bar", "Foo Bar") def bar(): return "bar" self.app.register_blueprint(blueprint) with self.app.test_client() as c: c.get("/test") assert request.endpoint == "test" assert current_menu.text == "Test" with self.app.test_client() as c: c.get("/foo/bar") self.assertEqual(current_menu.submenu("bar").text, "Foo Bar") self.assertTrue(current_menu.submenu("bar").active)
def test_blueprint(self): Menu(self.app) blueprint = Blueprint('foo', 'foo', url_prefix="/foo") @self.app.route('/test') @register_menu(self.app, '.', 'Test') def test(): return 'test' @blueprint.route('/bar') @register_menu(blueprint, 'bar', 'Foo Bar') def bar(): return 'bar' self.app.register_blueprint(blueprint) with self.app.test_client() as c: c.get('/test') assert request.endpoint == 'test' assert current_menu.text == 'Test' with self.app.test_client() as c: c.get('/foo/bar') self.assertEqual( current_menu.submenu('bar').text, 'Foo Bar') self.assertTrue(current_menu.submenu('bar').active)
def init_menu(): """Initialize menu before first request.""" # Register breadcrumb root item = current_menu.submenu('breadcrumbs.settings') item.register('', _('Account')) item = current_menu.submenu('breadcrumbs.{0}'.format( current_app.config['SECURITY_BLUEPRINT_NAME'])) if current_app.config.get('SECURITY_CHANGEABLE', True): item.register('', _('Change password')) # Register settings menu item = current_menu.submenu('settings.change_password') item.register( "{0}.change_password".format( current_app.config['SECURITY_BLUEPRINT_NAME']), # NOTE: Menu item text (icon replaced by a user icon). _('%(icon)s Change password', icon='<i class="fa fa-key fa-fw"></i>'), order=1) # Register breadcrumb item = current_menu.submenu('breadcrumbs.{0}.change_password'.format( current_app.config['SECURITY_BLUEPRINT_NAME'])) item.register( "{0}.change_password".format( current_app.config['SECURITY_BLUEPRINT_NAME']), _("Change password"), order=0, )
def test_dynamic_list_constructor(self): bar = ['Item 1', 'Item 2', 'Item 3'] def get_menu_items(): return bar @register_menu(self.app, 'foo', 'foo', dynamic_list_constructor=get_menu_items) @self.app.route('/') def foo(): return 'foo' @register_menu(self.app, 'other', 'Other') @self.app.route('/other') def other(): return 'other' Menu(self.app) with self.app.test_client() as c: c.get('/') self.assertEquals( current_menu.submenu('foo').dynamic_list, bar ) self.assertEquals( current_menu.submenu('other').dynamic_list, [current_menu.submenu('other')] )
def init_menu(): """Initialize menu before first request.""" item = current_menu.submenu("settings.account") item.register(None, _("Settings")) item = current_menu.submenu("settings.account.change_password") item.register( "{0}.change_password".format(current_app.config["SECURITY_BLUEPRINT_NAME"]), _("%(icon)s Change Password", icon='<i class="fa fa-key fa-fw"></i>'), )
def init_menu(): """Initialize menu before first request.""" item = current_menu.submenu('main.deposit') item.register( 'invenio_deposit_ui.index', _('Upload'), order=2, ) item = current_menu.submenu('main.communities') item.register( 'invenio_communities.index', _('Communities'), order=3, )
def init_menu(): """Initialize menu before first request.""" item = current_menu.submenu('settings.change_password') item.register( "{0}.change_password".format( current_app.config['SECURITY_BLUEPRINT_NAME']), _('%(icon)s Change Password', icon='<i class="fa fa-key fa-fw"></i>'))
def setup_menu(): """Setup menu.""" item = current_menu.submenu('main.search') item.register( 'invenio_search_ui.search', _('Search'), order=1, active_when=lambda: request.endpoint.startswith("invenio_search_ui") )
def menu_fixup(): item = current_menu.submenu('settings.profile') item.register( 'userprofile.index', _('%(icon)s Profile', icon='<i class="fa fa-user fa-fw"></i>'), order=0, active_when=lambda: request.endpoint.startswith("userprofile."), )
def init_menu(endpoints): """Initialize menu before first request.""" item = current_menu.submenu('main.manage') item.register( endpoint=None, text=_('Manage'), visible_when=can_edit, order=0 ) for record_type in endpoints.keys(): if endpoints.get(record_type, {}).get('api'): subitem = current_menu.submenu('main.manage.%s' % record_type) icon = '<i class="fa fa-pencil-square-o fa-fw"></i> ' subitem.register( endpoint='reroils_record_editor.search_%s' % record_type, text=icon + _(record_type), visible_when=can_edit )
def test_visible_when_with_dynamic(self): Menu(self.app) @self.app.route('/always') @register_menu(self.app, 'always', 'Always', visible_when=lambda: True) def always(): return 'never' @self.app.route('/never') @register_menu(self.app, 'never', 'Never', visible_when=lambda: False) def never(): return 'never' @register_menu(self.app, 'normal', 'Normal') @self.app.route('/normal/<int:id>/') def normal(id): return 'normal' data = { 'never': {'never': False, 'always': True, 'normal': True}, 'always': {'never': False, 'always': True, 'normal': True}, 'normal': {'never': False, 'always': True, 'normal': True}, } for (k, v) in data.items(): with self.app.test_client() as c: c.get('/' + k) for (endpoint, visible) in v.items(): self.assertEqual(current_menu.submenu(endpoint).visible, visible) with self.app.test_request_context(): current_menu.submenu('always').hide() data = { 'never': {'never': False, 'always': False, 'normal': True}, 'always': {'never': False, 'always': False, 'normal': True}, 'normal': {'never': False, 'always': False, 'normal': True}, } for (k, v) in data.items(): with self.app.test_client() as c: c.get('/' + k) for (endpoint, visible) in v.items(): self.assertEqual(current_menu.submenu(endpoint).visible, visible)
def test_dynamic_url(self): Menu(self.app) @self.app.route('/<int:id>/<string:name>') @register_menu(self.app, 'test', 'Test', endpoint_arguments_constructor=lambda: { 'id': request.view_args['id'], 'name': request.view_args['name'], }) def test(id, name): return str(id) + ':' + name with self.app.test_request_context(): url = url_for('test', id=1, name='foo') with self.app.test_client() as c: c.get(url) assert url == current_menu.submenu('test').url assert current_menu.submenu('missing').url == '#'
def init_menu(): """Initialize menu before first request.""" # Register settings menu item = current_menu.submenu('settings.admin') item.register( "admin.index", # NOTE: Menu item text (icon replaced by a cogs icon). _('%(icon)s Administration', icon='<i class="fa fa-cogs fa-fw"></i>'), visible_when=_has_admin_access, order=100)
def test_visible_when_with_dynamic(self): Menu(self.app) @self.app.route("/always") @register_menu(self.app, "always", "Always", visible_when=lambda: True) def always(): return "never" @self.app.route("/never") @register_menu(self.app, "never", "Never", visible_when=lambda: False) def never(): return "never" @register_menu(self.app, "normal", "Normal") @self.app.route("/normal/<int:id>/") def normal(id): return "normal" data = { "never": {"never": False, "always": True, "normal": True}, "always": {"never": False, "always": True, "normal": True}, "normal": {"never": False, "always": True, "normal": True}, } for (k, v) in data.items(): with self.app.test_client() as c: c.get("/" + k) for (endpoint, visible) in v.items(): self.assertEqual(current_menu.submenu(endpoint).visible, visible) with self.app.test_request_context(): current_menu.submenu("always").hide() data = { "never": {"never": False, "always": False, "normal": True}, "always": {"never": False, "always": False, "normal": True}, "normal": {"never": False, "always": False, "normal": True}, } for (k, v) in data.items(): with self.app.test_client() as c: c.get("/" + k) for (endpoint, visible) in v.items(): self.assertEqual(current_menu.submenu(endpoint).visible, visible)
def test_dynamic_url(self): Menu(self.app) @self.app.route("/<int:id>/<string:name>") @register_menu( self.app, "test", "Test", endpoint_arguments_constructor=lambda: {"id": request.view_args["id"], "name": request.view_args["name"]}, ) def test(id, name): return str(id) + ":" + name with self.app.test_request_context(): url = url_for("test", id=1, name="foo") with self.app.test_client() as c: c.get(url) assert url == current_menu.submenu("test").url assert current_menu.submenu("missing").url == "#"
def _register_menu_items(): for meth_str in dir(classy_view): meth = getattr(classy_view, meth_str) if hasattr(meth, '_menu_items'): for menu_item in meth._menu_items: endpoint = "{0}{1}:{2}".format( endpoint_prefix, classy_view.__name__, meth.__name__) path = menu_item.pop('path') item = current_menu.submenu(path) item.register(endpoint, **menu_item)
def test_active_item(self): """Test active_item method.""" Menu(self.app) @self.app.route("/") @register_menu(self.app, "root", "root") def root(): return "root" @self.app.route("/sub1/item1") @register_menu(self.app, "root.sub1.item1", "Sub 1 - Item 1") def sub1_item1(): return "sub1_item1" @self.app.route("/sub2/item1") @register_menu(self.app, "root.sub2.item1", "Sub 2 - Item 1") def sub2_item1(): return "sub2_item1" @self.app.route("/sub2/item2") @register_menu(self.app, "root.sub2.item2", "Sub 2 - Item 2") def sub2_item2(): return "sub2_item2" with self.app.test_client() as c: c.get("/") self.assertEqual(current_menu.active_item, current_menu.submenu("root")) c.get("/sub1/item1") self.assertEqual(current_menu.active_item, current_menu.submenu("root.sub1.item1")) sub1 = current_menu.submenu("root.sub1") self.assertEqual(sub1.active_item, current_menu.submenu("root.sub1.item1")) sub2 = current_menu.submenu("root.sub2") self.assertIsNone(sub2.active_item) c.get("/sub2/item2") self.assertEqual(sub2.active_item, current_menu.submenu("root.sub2.item2"))
def register_menu_items(): item = current_menu.submenu('main.communities') item.register( '', _('Communities'), active_when=lambda: request.endpoint.startswith("search.collection") ) # TODO: This is dirty, kinda ugly, but it works; # try to make it pretty. # Replace invenio routes # search.index -> / ==> /search/ # search.index -> /index.html ==> Deleted # search.index -> /index.py ==> Deleted # search.search -> ? ==> /search/search # search.collection -> /collection ==> /search/collection def fix_search(): _new_rules = [] search_index_flag = False for idx, rule in enumerate(current_app.url_map.iter_rules()): if str(rule.endpoint) == 'search.index' and not search_index_flag: rule.rule = '/search/' search_index_flag = True if str(rule.endpoint) == 'search.search': rule.rule = '/search/search' # if str(rule.endpoint) == 'search.collection': # does not work # rule.rule = '/search/collection' _new_rules.append(rule.empty()) curr = current_app.url_map current_app.url_map = Map(rules=_new_rules, default_subdomain=curr.default_subdomain, charset=curr.charset, strict_slashes=curr.strict_slashes, redirect_defaults=curr.redirect_defaults, converters=curr.converters, sort_parameters=curr.sort_parameters, sort_key=curr.sort_key, encoding_errors=curr.encoding_errors, host_matching=curr.host_matching) def menu_fixup(): item = current_menu.submenu('settings.profile') item.register( 'userprofile.index', _('%(icon)s Profile', icon='<i class="fa fa-user fa-fw"></i>'), order=0, active_when=lambda: request.endpoint.startswith("userprofile."), ) current_app.before_first_request_funcs.append(menu_fixup) fix_search()
def test_kwargs(self): """Test optional arguments.""" Menu(self.app) count = 5 @self.app.route("/test") @register_menu(self.app, "test", "Test", count=count) def test(): return "count" with self.app.test_client() as c: c.get("/test") assert count == current_menu.submenu("test").count
def test_kwargs(self): """Test optional arguments.""" Menu(self.app) count = 5 @self.app.route('/test') @register_menu(self.app, 'test', 'Test', count=count) def test(): return 'count' with self.app.test_client() as c: c.get('/test') assert count == current_menu.submenu('test').count
def test_dynamic_list_constructor(self): bar = ["Item 1", "Item 2", "Item 3"] def get_menu_items(): return bar @register_menu(self.app, "foo", "foo", dynamic_list_constructor=get_menu_items) @self.app.route("/") def foo(): return "foo" @register_menu(self.app, "other", "Other") @self.app.route("/other") def other(): return "other" Menu(self.app) with self.app.test_client() as c: c.get("/") self.assertEquals(current_menu.submenu("foo").dynamic_list, bar) self.assertEquals(current_menu.submenu("other").dynamic_list, [current_menu.submenu("other")])
def test_classy_endpoint_on_blueprint(self): from flask_classy import FlaskView class MyEndpoint(FlaskView): route_base = "/" def index(self): return "" @classy_menu_item("page1", "Page 1") def page1(self): return "" @classy_menu_item("page2", "Page 2") def page2(self): return "" @classy_menu_item("page3", "Page 3") @classy_menu_item("page31", "Page 3.1") def page3(self): return "" Menu(self.app) bp = Blueprint("foo", "foo", url_prefix="/foo") MyEndpoint.register(bp) register_flaskview(bp, MyEndpoint) self.app.register_blueprint(bp) data = { "/foo/page1/": {"page1": True, "page2": False, "page3": False, "page31": False}, "/foo/page2/": {"page1": False, "page2": True, "page3": False, "page31": False}, "/foo/page3/": {"page1": False, "page2": False, "page3": True, "page31": True}, } for (path, v) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in v.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' "active_is={2} active_should={3}".format(path, endpoint, active_is, active_should), )
def test_active_checks_segment_not_prefix(self): Menu(self.app) @register_menu(self.app, 'object', 'Object') @self.app.route('/object') def object(): return 'object' @register_menu(self.app, 'objects', 'Objects') @self.app.route('/objects') def objects(): return 'objects' with self.app.test_client() as c: c.get('/objects') assert current_menu.submenu('object').active is not True
def test_classy_endpoint_with_args(self): from flask_classy import FlaskView, route class MyEndpoint(FlaskView): route_base = '/' @classy_menu_item('withid.page1', 'Page 1') @route('/<int:id>/page1') def page1(self, id): return 'page1' @classy_menu_item('withid.page2', 'Page 2') @route('/<int:id>/page2') def page2(self, id): return 'page2' Menu(self.app) MyEndpoint.register(self.app) register_flaskview(self.app, MyEndpoint) data = { '/1/page1': { 'withid.page1': True, 'withid.page2': False, }, '/1/page2': { 'withid.page1': False, 'withid.page2': True, } } for (path, v) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in v.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' 'active_is={2} active_should={3}'.format( path, endpoint, active_is, active_should ) )
def test_active_when(self): Menu(self.app) @self.app.route("/") @register_menu(self.app, "root", "Root") def root(): return "root" @self.app.route("/always") @register_menu(self.app, "always", "Always", active_when=lambda: True) def always(): return "always" @self.app.route("/never") @register_menu(self.app, "never", "Never", active_when=lambda: False) def never(): return "never" @self.app.route("/normal") @register_menu(self.app, "normal", "Normal") def normal(): return "normal" data = { "/never": {"root": False, "never": False, "always": True, "normal": False}, "/always": {"root": False, "never": False, "always": True, "normal": False}, "/normal": {"root": False, "never": False, "always": True, "normal": True}, "/normal/foo": {"root": False, "never": False, "always": True, "normal": True}, "/bar/normal": {"root": False, "never": False, "always": True, "normal": False}, "/bar/normal/foo": {"root": False, "never": False, "always": True, "normal": False}, "/": {"root": True, "never": False, "always": True, "normal": False}, "": {"root": True, "never": False, "always": True, "normal": False}, } for (path, testset) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in testset.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' "active_is={2} active_should={3}".format(path, endpoint, active_is, active_should), )
def test_classy_endpoint_with_args(self): from flask_classy import FlaskView, route class MyEndpoint(FlaskView): route_base = "/" @classy_menu_item("withid.page1", "Page 1") @route("/<int:id>/page1") def page1(self, id): return "page1" @classy_menu_item("withid.page2", "Page 2") @route("/<int:id>/page2") def page2(self, id): return "page2" Menu(self.app) MyEndpoint.register(self.app) register_flaskview(self.app, MyEndpoint) data = { "/1/page1": {"withid.page1": True, "withid.page2": False}, "/1/page2": {"withid.page1": False, "withid.page2": True}, } for (path, v) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in v.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' "active_is={2} active_should={3}".format(path, endpoint, active_is, active_should), )
def test_active_item(self): """Test active_item method.""" Menu(self.app) @self.app.route('/') @register_menu(self.app, 'root', 'root') def root(): return "root" @self.app.route('/sub1/item1') @register_menu(self.app, 'root.sub1.item1', 'Sub 1 - Item 1') def sub1_item1(): return "sub1_item1" @self.app.route('/sub2/item1') @register_menu(self.app, 'root.sub2.item1', 'Sub 2 - Item 1') def sub2_item1(): return "sub2_item1" @self.app.route('/sub2/item2') @register_menu(self.app, 'root.sub2.item2', 'Sub 2 - Item 2') def sub2_item2(): return "sub2_item2" with self.app.test_client() as c: c.get('/') self.assertEqual( current_menu.active_item, current_menu.submenu('root')) c.get('/sub1/item1') self.assertEqual(current_menu.active_item, current_menu.submenu('root.sub1.item1')) sub1 = current_menu.submenu('root.sub1') self.assertEqual(sub1.active_item, current_menu.submenu('root.sub1.item1')) sub2 = current_menu.submenu('root.sub2') self.assertIsNone(sub2.active_item) c.get('/sub2/item2') self.assertEqual(sub2.active_item, current_menu.submenu('root.sub2.item2'))
def init_menu_profile(): """Create the profile header menu.""" item = current_menu.submenu('main.profile') if current_patron: session['user_initials'] = current_patron.initial else: try: session['user_initials'] = current_user.email # AnonymousUser except AttributeError: session.pop('user_initials', None) account = session.get('user_initials', _('My Account')) rero_register( item, endpoint=None, text='{icon} <span class="{visible}">{account}</span>'.format( icon='<i class="fa fa-user"></i>', visible='visible-md-inline visible-lg-inline', account=account ), order=1, id='my-account-menu', ) item = current_menu.submenu('main.profile.login') rero_register( item, endpoint='security.login', endpoint_arguments_constructor=lambda: dict( next=request.full_path ), visible_when=lambda: not current_user.is_authenticated, text='{icon} {login}'.format( icon='<i class="fa fa-sign-in"></i>', login=_('Login') ), order=1, id='login-menu', ) item = current_menu.submenu('main.profile.professional') rero_register( item, endpoint='rero_ils.professional', visible_when=lambda: current_patron.is_librarian, text='{icon} {professional}'.format( icon='<i class="fa fa-briefcase"></i>', professional=_('Professional interface') ), order=1, id='professional-interface-menu', ) item = current_menu.submenu('main.profile.logout') rero_register( item, endpoint='security.logout', endpoint_arguments_constructor=lambda: dict( next='/{viewcode}'.format(viewcode=request.view_args.get( 'viewcode', current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')) ) ), visible_when=lambda: current_user.is_authenticated, text='{icon} {logout}'.format( icon='<i class="fa fa-sign-out"></i>', logout=_('Logout') ), order=2, id='logout-menu', ) item = current_menu.submenu('main.profile.profile') rero_register( item, endpoint='invenio_userprofiles.profile', visible_when=lambda: current_user.is_authenticated, text='{icon} {profile}'.format( icon='<i class="fa fa-user"></i>', profile=_('RERO ID') ), order=1, id='profile-menu', ) item = current_menu.submenu('main.profile.signup') rero_register( item, endpoint='security.register', visible_when=lambda: not current_user.is_authenticated, text='{icon} {signup}'.format( icon='<i class="fa fa-user-plus"></i>', signup=_('Sign Up') ), order=2, id='signup-menu', )
def register_node(): if not current_menu.submenu(item.menu_path, False): current_menu.submenu(item.menu_path).register(None, item.title, item.weight, item=item)
def test_simple_app(self): Menu(self.app) @self.app.route('/test') @register_menu(self.app, '.', 'Test') def test(): return 'test' @self.app.route('/level2') @register_menu(self.app, 'level2', 'Level 2') def level2(): return 'level2' @self.app.route('/level3') @register_menu(self.app, 'level2.level3', 'Level 3', order=2) def level3(): return 'level3' @self.app.route('/level3B') @register_menu(self.app, 'level2.level3B', 'Level 3B', order=1) def level3B(): return 'level3B' with self.app.test_client() as c: c.get('/test') assert request.endpoint == 'test' assert current_menu.url == '/test' assert current_menu.text == 'Test' assert current_menu.active self.assertEqual(current_menu.submenu('level2').text, 'Level 2') assert not current_menu.submenu('level2').active assert current_menu.submenu('missing', auto_create=False) is None assert len(current_menu.list_path('.', '.level2.level3')) == 3 assert current_menu.list_path('.', 'missing') is None assert current_menu.list_path('missing', '.level2.level3') is None assert current_menu.list_path('level2.level3B', 'level2.level3') is None with self.app.test_client() as c: c.get('/level2') assert current_menu.submenu('level2').active with self.app.test_client() as c: c.get('/level3') assert current_menu.submenu('.level2.level3').active assert current_menu.submenu('level2.level3').active assert not current_menu.has_active_child(recursive=False) assert current_menu.has_active_child() assert current_menu.submenu('level2').has_active_child( recursive=False) assert current_menu.submenu('level2').has_active_child() item_2 = current_menu.submenu('level2.level3') item_1 = current_menu.submenu('level2.level3B') assert item_1.order < item_2.order assert item_1 == current_menu.submenu('level2').children[0] assert item_2 == current_menu.submenu('level2').children[1]
def _init_plugin(self, plugin): """ Initializes a plugin: 1. Runs the plugin's init() function. 2. Saves the config 3. Loads the plugin's endpoints into flask """ poof('Starting %s v%s' % (plugin.name, plugin.version)) plugin.init(PRISM_STATE) plugin.config.save() if len(plugin._module_views) > 0: blueprint_name = plugin._endpoint # Create the plugin blueprint in flask plugin._blueprint = Blueprint(blueprint_name, plugin._info['_id'], template_folder='templates') # Go through each of the module's views and add them to flask for view_class in plugin._module_views: view = view_class() endpoint_id = '%s' % view_class.__name__ with flask_app().app_context(): if view.menu is not None: # Generate the parent menu item if 'parent' in view.menu: if '.' not in view.menu['parent']['id']: parts = ('/' + blueprint_name + view.endpoint).split('/') flask_app().add_url_rule( '/'.join(parts[:-1]), endpoint=blueprint_name + '.' + view.menu['parent']['id']) item = current_menu.submenu( view.menu['parent']['id']) item.register(blueprint_name + '.' + view.menu['parent']['id'], view.menu['parent']['text'], view.menu['parent']['order'], icon=view.menu['parent']['icon']) else: item = current_menu.submenu( view.menu['parent']['id']) item.register(blueprint_name + '.' + endpoint_id, view.menu['parent']['text'], view.menu['parent']['order'], icon=view.menu['parent']['icon']) item = current_menu.submenu(view.menu['id']) item.register(blueprint_name + '.' + endpoint_id, view.title, view.menu['order'], icon=view.menu['icon']) prism.output( 'Registered menu item for /%s: %s' % (blueprint_name + view.endpoint, view.menu['id'])) else: # Generate a hidden menu item so titles show correctly item = current_menu.submenu(generate_random_string(12)) item.register(blueprint_name + '.' + endpoint_id, view.title, hidden=True) # Find all methods in the view class for func_name in [ method for method in dir(view) if callable(getattr(view, method)) ]: if func_name.startswith('_'): continue if func_name not in ['get', 'post', 'put', 'delete']: if not func_name.endswith( ('_get', '_post', '_put', '_delete')): continue else: # Set the fallback http method to the extention of the function name parts = func_name.split('_') if parts[len(parts) - 1] in ('get', 'post', 'put', 'delete'): fallback_http_methods = [ parts[len(parts) - 1].upper() ] else: # Set the fallback http method to the function name fallback_http_methods = [func_name.upper()] if func_name == 'get': endpoint_id = '%s' % view_class.__name__ elif func_name.endswith('_get'): endpoint_id = '%s:%s' % (view_class.__name__, '_'.join( func_name.split('_')[:-1])) else: endpoint_id = '%s:%s' % (view_class.__name__, func_name) # Get the method func = getattr(view, func_name) view_func_wrapper = self.func_wrapper( plugin.plugin_id, func) # If the http methods have been specified in the @subroute decorator if hasattr(func, 'http_methods'): fallback_http_methods = func.http_methods fallback_endpoint = '/' # If an endpoint has been specified in the @subroute decorator if hasattr(func, 'endpoint'): fallback_endpoint = func.endpoint # Prepare fallback defaults for the page if hasattr(func, 'defaults'): fallback_defaults = func.defaults elif func.__defaults__ is not None: args, varargs, keywords, defaults = inspect.getargspec( func) fallback_defaults = dict( zip(args[-len(defaults):], defaults)) else: fallback_defaults = {} func_routes = list() if not hasattr(func, 'routes'): func_routes.append({ 'endpoint': fallback_endpoint, 'http_methods': fallback_http_methods, 'defaults': fallback_defaults }) else: func_routes = func.routes # Add a route for the get function with no parameters if func_name == 'get': plugin._blueprint.add_url_rule( view.endpoint + fallback_endpoint, endpoint=endpoint_id, methods=fallback_http_methods, view_func=view_func_wrapper, defaults=fallback_defaults) for route in func_routes: if 'endpoint' not in route: route['endpoint'] = fallback_endpoint if 'http_methods' not in route: route['http_methods'] = fallback_http_methods if 'defaults' not in route: route['defaults'] = fallback_defaults.copy() # Defaults are odd. They cannot be attached to routes with the key in the url # For example: if <id> in in the url rule, it cann't be in defaults. pattern = re.compile(r'<(?:.+?(?=:):)?(.+?)>') if '<' in route['endpoint'] and len( route['defaults']) > 0: for id in re.findall(pattern, route['endpoint']): try: del route['defaults'][id] except: pass prism.output('Registered page /%s: %s %s' % (blueprint_name + view.endpoint + route['endpoint'], blueprint_name + '.' + endpoint_id, route['http_methods'])) plugin._blueprint.add_url_rule( view.endpoint + route['endpoint'], endpoint=endpoint_id, methods=route['http_methods'], view_func=view_func_wrapper, defaults=route['defaults']) flask_app().register_blueprint(plugin._blueprint, url_prefix='/' + blueprint_name.replace('.', '/')) paaf()
def init_menu_tools(): """Create the header tool menu.""" item = current_menu.submenu('main.tool') rero_register( item, endpoint=None, text='{icon} <span class="{visible}">{menu}'.format( icon='<i class="fa fa-wrench"></i>', visible='visible-md-inline visible-lg-inline', menu=_('Tools') ), order=0, id='tools-menu' ) item = current_menu.submenu('main.tool.ill_request') rero_register( item, endpoint='ill_requests.ill_request_form', visible_when=lambda: Patron.get_patron_by_user(current_user).is_patron, text='{icon} {help}'.format( icon='<i class="fa fa-shopping-basket"></i>', help=_('Interlibrary loan request') ), order=10, id='ill-request-menu' ) item = current_menu.submenu('main.tool.collections') rero_register( item, endpoint='rero_ils.collections', endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')) ), visible_when=lambda: current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE' ) != request.view_args.get( 'viewcode', current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')), text='{icon} {help}'.format( icon='<i class="fa fa-graduation-cap"></i>', help=_('Collections') ), order=2, id='collections-menu' ) item = current_menu.submenu('main.tool.help') rero_register( item, endpoint='wiki.page', endpoint_arguments_constructor=lambda: {'url': 'public'}, text='{icon} {help}'.format( icon='<i class="fa fa-info"></i>', help=_('Help') ), order=100, id='help-menu' )
def test_active_when(self): Menu(self.app) @self.app.route('/') @register_menu(self.app, 'root', 'Root') def root(): return 'root' @self.app.route('/always') @register_menu(self.app, 'always', 'Always', active_when=lambda: True) def always(): return 'always' @self.app.route('/never') @register_menu(self.app, 'never', 'Never', active_when=lambda: False) def never(): return 'never' @self.app.route('/normal') @register_menu(self.app, 'normal', 'Normal') def normal(): return 'normal' data = { '/never': { 'root': False, 'never': False, 'always': True, 'normal': False }, '/always': { 'root': False, 'never': False, 'always': True, 'normal': False }, '/normal': { 'root': False, 'never': False, 'always': True, 'normal': True }, '/normal/foo': { 'root': False, 'never': False, 'always': True, 'normal': True }, '/bar/normal': { 'root': False, 'never': False, 'always': True, 'normal': False }, '/bar/normal/foo': { 'root': False, 'never': False, 'always': True, 'normal': False }, '/': { 'root': True, 'never': False, 'always': True, 'normal': False }, '': { 'root': True, 'never': False, 'always': True, 'normal': False }, } for (path, testset) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in testset.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' 'active_is={2} active_should={3}'.format( path, endpoint, active_is, active_should))
def test_classy_endpoint(self): from flask_classy import FlaskView class MyEndpoint(FlaskView): route_base = '/' def index(self): return '' @classy_menu_item('page1', 'Page 1') def page1(self): return '' @classy_menu_item('page2', 'Page 2') def page2(self): return '' @classy_menu_item('page3', 'Page 3') @classy_menu_item('page31', 'Page 3.1') def page3(self): return '' Menu(self.app) MyEndpoint.register(self.app) register_flaskview(self.app, MyEndpoint) data = { '/page1/': { 'page1': True, 'page2': False, 'page3': False, 'page31': False }, '/page2/': { 'page1': False, 'page2': True, 'page3': False, 'page31': False }, '/page3/': { 'page1': False, 'page2': False, 'page3': True, 'page31': True } } for (path, v) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, active_should) in v.items(): active_is = current_menu.submenu(endpoint).active self.assertEqual( active_is, active_should, 'path="{0}" submenu_by_endpoint="{1}" ' 'active_is={2} active_should={3}'.format( path, endpoint, active_is, active_should ) )
def test_has_visible_child(self): Menu(self.app) @self.app.route('/one') def one(): return 'one' # This item should never be visible. @register_menu(self.app, 'one.four', 'One Four', visible_when=lambda: False) @self.app.route('/one/four') def one_four(): return 'one_four' @self.app.route('/six') def six(): return 'six' # This item should never be visible. @register_menu(self.app, 'six.seven', 'Six Seven', visible_when=lambda: False) @self.app.route('/six/seven') def six_seven(): return 'six_seven' @register_menu(self.app, 'six.seven.eight', 'Six Seven Eight') @self.app.route('/six/seven/eight') def six_seven_eight(): return 'six_seven_eight' @register_menu(self.app, 'two', 'Two') @self.app.route('/two') def two(): return 'two' @register_menu(self.app, 'two.three', 'Two Three') @self.app.route('/two/three') def two_three(): return 'two_three' @register_menu(self.app, 'two.three.five', 'Two Three Five') @self.app.route('/two/three/five') def two_three_five(): return 'two_three_five' data = { '/one': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/two': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/two/three': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/one/four': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/one/four/five': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/six': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/six/seven': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, }, '/six/seven/eight': { 'one': False, 'two': True, 'two.three': True, 'one.four': False, 'two.three.five': False, 'six': True, 'six.seven': True, 'six.seven.eight': False, } } for (path, v) in data.items(): with self.app.test_client() as c: c.get(path) for (endpoint, visible_should) in v.items(): visible_is = current_menu.submenu( endpoint ).has_visible_child() self.assertEqual( visible_is, visible_should, 'path="{0}" submenu_by_endpoint="{1}" ' 'visible_is={2} visible_should={3}'.format( path, endpoint, visible_is, visible_should ) )
def init_menu(): """Create the header menus.""" item = current_menu.submenu('main.menu') item.register(endpoint=None, text='{icon} <span class="{visible}">{menu}'.format( icon='<i class="fa fa-bars"></i>', visible='visible-md-inline visible-lg-inline', menu=_('Menu')), order=0) order = 10 def return_language(lang): return dict(lang_code=lang) def hide_language(lang): return current_i18n.language != lang for language_item in current_i18n.get_locales(): item = current_menu.submenu('main.menu.lang_{language}'.format( language=language_item.language)) item.register(endpoint='invenio_i18n.set_lang', endpoint_arguments_constructor=partial( return_language, language_item.language), text='{icon} {language}'.format( icon='<i class="fa fa-language"></i>', language=_(i18n_to_str(language_item.language))), visible_when=partial(hide_language, language_item.language), order=order) order += 1 item = current_menu.submenu('main.menu.help') item.register(endpoint='rero_ils.help', text='{icon} {help}'.format( icon='<i class="fa fa-info"></i>', help=_('Help')), order=100) item = current_menu.submenu('main.profile') account = _('My Account') if current_user.is_authenticated: patron = Patron.get_patron_by_email(current_user.email) if patron: account = patron.initial item.register( endpoint=None, text='{icon} <span class="{visible}">{account}</span>'.format( icon='<i class="fa fa-user"></i>', visible='visible-md-inline visible-lg-inline', account=account), order=1) item = current_menu.submenu('main.profile.login') item.register( endpoint='security.login', endpoint_arguments_constructor=lambda: dict(next=request.path), visible_when=lambda: not current_user.is_authenticated, text='{icon} {login}'.format(icon='<i class="fa fa-sign-in"></i>', login=_('Login')), order=1) item = current_menu.submenu('main.profile.logout') item.register(endpoint='security.logout', visible_when=lambda: current_user.is_authenticated, text='{icon} {logout}'.format( icon='<i class="fa fa-sign-out"></i>', logout=_('Logout')), order=1) item = current_menu.submenu('main.profile.signup') item.register(endpoint='security.register', visible_when=lambda: not current_user.is_authenticated, text='{icon} {signup}'.format( icon='<i class="fa fa-user-plus"></i>', signup=_('Sign Up')), order=2)
def init_menu_tools(): """Create the header tool menu.""" item = current_menu.submenu('main.tool') rero_register(item, endpoint=None, text=TextWithIcon(icon='<i class="fa fa-wrench"></i>', text='Tools'), order=0, id='tools-menu') item = current_menu.submenu('main.tool.ill_request') rero_register( item, endpoint='ill_requests.ill_request_form', endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE'))), visible_when=lambda: bool(current_patrons), text=TextWithIcon(icon='<i class="fa fa-shopping-basket"></i>', text='Interlibrary loan request'), order=10, id='ill-request-menu') item = current_menu.submenu('main.tool.stats_billing') rero_register(item, endpoint='stats.stats_billing', visible_when=lambda: admin_permission.require().can(), text=TextWithIcon(icon='<i class="fa fa-money"></i>', text='Statistics billing'), order=20, id='stats-menu-billing') item = current_menu.submenu('main.tool.stats_librarian') rero_register(item, endpoint='stats.stats_librarian', visible_when=lambda: librarian_permission.require().can(), text=TextWithIcon(icon='<i class="fa fa-bar-chart"></i>', text='Statistics'), order=20, id='stats-menu-librarian') item = current_menu.submenu('main.tool.collections') rero_register( item, endpoint='rero_ils.search', endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')), recordType='collections'), visible_when=lambda: current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE') != request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')), text=TextWithIcon(icon='<i class="fa fa-graduation-cap"></i>', text='Exhibition/course'), order=2, id='collections-menu') item = current_menu.submenu('main.tool.help') rero_register(item, endpoint='wiki.page', endpoint_arguments_constructor=lambda: {'url': 'public'}, text=TextWithIcon(icon='<i class="fa fa-info"></i>', text='Help'), order=100, id='help-menu')
def init_menu(): """Initialize menu before first request.""" item = current_menu.submenu("main.deposit") item.register("invenio_app_rdm_records.deposit_search", _("Uploads"), order=1)
def menu_fixup(): current_menu.submenu("settings.change_password").hide() current_menu.submenu("settings.groups").hide() current_menu.submenu("settings.workflows").hide() current_menu.submenu("settings.applications").hide() current_menu.submenu("settings.oauthclient").hide() current_menu.submenu("settings.security").hide()
def _after_logout_hook(sender, **extra): tt = current_menu.submenu("user") tt._text = "User"
def init_view(): """Do some stuff before rendering any view.""" current_menu.submenu('settings').submenu('security').hide() current_menu.submenu('settings').submenu('applications').hide() current_menu.submenu('settings').submenu('admin').hide()
def init_menu_profile(): """Create the profile header menu.""" def is_not_read_only(): """Hide element menu if the flag is ready only.""" return not current_app.config.get( 'RERO_PUBLIC_USERPROFILES_READONLY', False) and \ current_user.is_authenticated item = current_menu.submenu('main.profile') rero_register(item, endpoint=None, text=UserName(), order=1, id='my-account-menu', cssClass='py-1') item = current_menu.submenu('main.profile.login') rero_register( item, endpoint='security.login', endpoint_arguments_constructor=lambda: dict(next=request.full_path), visible_when=lambda: not current_user.is_authenticated, text=TextWithIcon(icon='<i class="fa fa-sign-in"></i>', text='Login'), order=1, id='login-menu', ) item = current_menu.submenu('main.profile.professional') rero_register( item, endpoint='rero_ils.professional', visible_when=lambda: current_librarian, text=TextWithIcon(icon='<i class="fa fa-briefcase"></i>', text='Professional interface'), order=1, id='professional-interface-menu', ) item = current_menu.submenu('main.profile.logout') rero_register( item, endpoint='security.logout', endpoint_arguments_constructor=lambda: dict(next='/{viewcode}'.format( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')))), visible_when=lambda: current_user.is_authenticated, text=TextWithIcon(icon='<i class="fa fa-sign-out"></i>', text='Logout'), order=2, id='logout-menu', ) item = current_menu.submenu('main.profile.profile') profile_endpoint = 'patrons.profile' rero_register( item, endpoint=profile_endpoint, endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE'))), visible_when=lambda: len(current_patrons) > 0, text=TextWithIcon(icon='<i class="fa fa-book"></i>', text='My Account'), order=1, id='profile-menu', ) item = current_menu.submenu('main.profile.edit_profile') rero_register( item, endpoint='users.profile', endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE'))), visible_when=lambda: is_not_read_only(), text=TextWithIcon(icon='<i class="fa fa-user"></i>', text='Edit my profile'), order=1, id='profile-menu', ) item = current_menu.submenu('main.profile.change_password') rero_register( item, endpoint='users.password', endpoint_arguments_constructor=lambda: dict( viewcode=request.view_args.get( 'viewcode', current_app.config.get('RERO_ILS_SEARCH_GLOBAL_VIEW_CODE'))), visible_when=lambda: is_not_read_only(), text=TextWithIcon(icon='<i class="fa fa-lock"></i>', text='Change password'), order=1, id='profile-menu', ) # Endpoint for: # Application: invenio_oauth2server_settings.index # Security: invenio_accounts.security item = current_menu.submenu('main.profile.signup') rero_register( item, endpoint='security.register', visible_when=lambda: not current_app.config.get( 'RERO_PUBLIC_USERPROFILES_READONLY', False) and not current_user. is_authenticated, text=TextWithIcon(icon='<i class="fa fa-user-plus"></i>', text='Sign Up'), order=2, id='signup-menu', )
def init_menu(): """Initialize menu before first request.""" item = current_menu.submenu('main.deposit') item.register('invenio_app_rdm.deposits_user', 'Uploads', order=1)
def register_menu_items(): """Register empty account breadcrumb.""" item = current_menu.submenu('breadcrumbs.settings') item.register('', _('Account'))
def init_menu_profile(): """Create the profile header menu.""" item = current_menu.submenu('main.profile') if current_librarian: session['user_name'] = current_librarian.formatted_name elif len(current_patrons) > 0: session['user_name'] = current_patrons[0].formatted_name else: try: session['user_name'] = current_user.email # AnonymousUser except AttributeError: session.pop('user_name', None) account = session.get('user_name', _('My Account')) if len(account) > 30: account = account[:30] + '…' rero_register( item, endpoint=None, text='<span class="btn btn-sm btn-success">{icon} ' '<span class="{visible}">{account}</span><span>'.format( icon='<i class="fa fa-user"></i>', visible='visible-md-inline visible-lg-inline', account=account ), order=1, id='my-account-menu', cssClass='py-1' ) item = current_menu.submenu('main.profile.login') rero_register( item, endpoint='security.login', endpoint_arguments_constructor=lambda: dict( next=request.full_path ), visible_when=lambda: not current_user.is_authenticated, text='{icon} {login}'.format( icon='<i class="fa fa-sign-in"></i>', login=_('Login') ), order=1, id='login-menu', ) item = current_menu.submenu('main.profile.professional') rero_register( item, endpoint='rero_ils.professional', visible_when=lambda: current_librarian, text='{icon} {professional}'.format( icon='<i class="fa fa-briefcase"></i>', professional=_('Professional interface') ), order=1, id='professional-interface-menu', ) item = current_menu.submenu('main.profile.logout') rero_register( item, endpoint='security.logout', endpoint_arguments_constructor=lambda: dict( next='/{viewcode}'.format(viewcode=request.view_args.get( 'viewcode', current_app.config.get( 'RERO_ILS_SEARCH_GLOBAL_VIEW_CODE')) ) ), visible_when=lambda: current_user.is_authenticated, text='{icon} {logout}'.format( icon='<i class="fa fa-sign-out"></i>', logout=_('Logout') ), order=2, id='logout-menu', ) item = current_menu.submenu('main.profile.profile') profile_endpoint = 'patrons.profile' rero_register( item, endpoint=profile_endpoint, visible_when=lambda: len(current_patrons) > 0, text='{icon} {profile}'.format( icon='<i class="fa fa-book"></i>', profile=_('My Account') ), order=1, id='profile-menu', ) item = current_menu.submenu('main.profile.edit_profile') rero_register( item, endpoint='invenio_userprofiles.profile', visible_when=lambda: current_user.is_authenticated, text='{icon} {profile}'.format( icon='<i class="fa fa-user"></i>', profile=_('Edit my profile') ), order=1, id='profile-menu', ) item = current_menu.submenu('main.profile.change_password') rero_register( item, endpoint='security.change_password', visible_when=lambda: current_user.is_authenticated, text='{icon} {profile}'.format( icon='<i class="fa fa-lock"></i>', profile=_('Change password') ), order=1, id='profile-menu', ) # Endpoint for: # Application: invenio_oauth2server_settings.index # Security: invenio_accounts.security item = current_menu.submenu('main.profile.signup') rero_register( item, endpoint='security.register', visible_when=lambda: not current_user.is_authenticated, text='{icon} {signup}'.format( icon='<i class="fa fa-user-plus"></i>', signup=_('Sign Up') ), order=2, id='signup-menu', )
def test_visible_when_with_dynamic(self): Menu(self.app) @self.app.route('/always') @register_menu(self.app, 'always', 'Always', visible_when=lambda: True) def always(): return 'never' @self.app.route('/never') @register_menu(self.app, 'never', 'Never', visible_when=lambda: False) def never(): return 'never' @register_menu(self.app, 'normal', 'Normal') @self.app.route('/normal/<int:id>/') def normal(id): return 'normal' data = { 'never': { 'never': False, 'always': True, 'normal': True }, 'always': { 'never': False, 'always': True, 'normal': True }, 'normal': { 'never': False, 'always': True, 'normal': True }, } for (k, v) in data.items(): with self.app.test_client() as c: c.get('/' + k) for (endpoint, visible) in v.items(): self.assertEqual( current_menu.submenu(endpoint).visible, visible) with self.app.test_request_context(): current_menu.submenu('always').hide() data = { 'never': { 'never': False, 'always': False, 'normal': True }, 'always': { 'never': False, 'always': False, 'normal': True }, 'normal': { 'never': False, 'always': False, 'normal': True }, } for (k, v) in data.items(): with self.app.test_client() as c: c.get('/' + k) for (endpoint, visible) in v.items(): self.assertEqual( current_menu.submenu(endpoint).visible, visible)
def setupMenus(): # mis entradas en el sidebar actions = current_menu.submenu("actions.default") actions._text = "Escritorio" actions._endpoint = None actions._external_url = "#!"
def remove_menu(menu): if type(menu) is str: menu = current_menu.submenu(menu) current_menu._child_entries = \ {k:v for k, v in current_menu._child_entries.items() if v != menu}
def _after_login_hook(sender, **extra): tt = current_menu.submenu("user") tt._text = current_user.username