Skip to content

Commit db79728

Browse files
authored
Fix default landing page is not considered in clients listing (#2459)
* Fix clients default landing page is not working * Cleanup * Redirect client to client's default landing page if no landing page is set * Redirect to client's default landing page in my_organization * Remove unused import * Changelog * Flag utils.get_registry_record as deprecated * Fix doctest * Add client_landing_page into config variable * Add upgrade decorator to import_registry function
1 parent 7870b74 commit db79728

File tree

15 files changed

+200
-11
lines changed

15 files changed

+200
-11
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changelog
44
2.5.0 (unreleased)
55
------------------
66

7+
- #2459 Fix default landing page is not considered in clients listing
78
- #2456 Remove groups from user add form
89
- #2455 Fix users/groups overview batch navigation styling
910
- #2454 Fix analyses not filtered by selected WST services

src/bika/lims/browser/clientfolder.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,26 @@
2525
from bika.lims.utils import check_permission
2626
from bika.lims.utils import get_email_link
2727
from bika.lims.utils import get_link
28-
from bika.lims.utils import get_registry_value
2928
from Products.CMFCore.permissions import ModifyPortalContent
3029
from senaite.app.listing import ListingView
3130
from senaite.core.catalog import CLIENT_CATALOG
31+
from senaite.core.config.registry import CLIENT_LANDING_PAGE
3232
from senaite.core.permissions import AddClient
3333
from senaite.core.permissions import ManageAnalysisRequests
34+
from senaite.core.registry import get_registry_record
3435

3536

3637
class ClientFolderContentsView(ListingView):
3738
"""Listing view for all Clients
3839
"""
3940

40-
_LANDING_PAGE_REGISTRY_KEY = "bika.lims.client.default_landing_page"
41-
_DEFAULT_LANDING_PAGE = "analysisrequests"
42-
4341
def __init__(self, context, request):
4442
super(ClientFolderContentsView, self).__init__(context, request)
4543

4644
self.title = self.context.translate(_("Clients"))
4745
self.description = ""
4846
self.form_id = "list_clientsfolder"
4947
self.sort_on = "sortable_title"
50-
# Landing page to be added to the link of each client from the list
51-
self.landing_page = get_registry_value(
52-
self._LANDING_PAGE_REGISTRY_KEY, self._DEFAULT_LANDING_PAGE)
5348

5449
self.catalog = CLIENT_CATALOG
5550
self.contentFilter = {
@@ -127,6 +122,9 @@ def before_render(self):
127122
# Call `before_render` from the base class
128123
super(ClientFolderContentsView, self).before_render()
129124

125+
# Landing page to be added to the link of each client from the list
126+
self.landing_page = get_registry_record(CLIENT_LANDING_PAGE)
127+
130128
# Render the Add button if the user has the AddClient permission
131129
if check_permission(AddClient, self.context):
132130
self.context_actions[_("Add")] = {

src/bika/lims/browser/myorganization.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
from bika.lims import api
2222
from bika.lims.browser import BrowserView
23+
from senaite.core.config.registry import CLIENT_LANDING_PAGE
24+
from senaite.core.registry import get_registry_record
2325

2426

2527
class MyOrganizationView(BrowserView):
@@ -28,11 +30,22 @@ class MyOrganizationView(BrowserView):
2830
"""
2931

3032
def __call__(self):
31-
url = api.get_url(api.get_portal())
33+
34+
client = api.get_current_client()
35+
if client:
36+
# User belongs to a client, redirect to client's default view
37+
view = get_registry_record(CLIENT_LANDING_PAGE)
38+
url = "{}/{}".format(api.get_url(client), view)
39+
return self.request.response.redirect(url)
40+
3241
current_user = api.get_current_user()
3342
contact = api.get_user_contact(current_user)
3443
if contact:
44+
# Redirect to the contact's container
3545
parent = api.get_parent(contact)
3646
url = api.get_url(parent)
47+
return self.request.response.redirect(url)
3748

49+
# Not a contact, redirect to portal
50+
url = api.get_url(api.get_portal())
3851
return self.request.response.redirect(url)

src/bika/lims/profiles/default/registry.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<!-- Operation Definitions -->
44
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="senaite.core">
55

6+
<!-- Ported to 2.x: https://github.com/senaite/senaite.core/pull/2459 -->
67
<record name="bika.lims.client.default_landing_page">
78
<field type="plone.registry.field.Choice">
89
<default>analysisrequests</default>

src/bika/lims/utils/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,13 @@ def get_registry_value(key, default=None):
754754
:param default: default value if the key is not registered
755755
:return: value in the registry for the key passed in
756756
"""
757-
registry = queryUtility(IRegistry)
758-
return registry.get(key, default)
757+
# cannot use bika.lims.deprecated (circular dependencies)
758+
import warnings
759+
warnings.simplefilter("always", DeprecationWarning)
760+
warn = "Deprecated: use senaite.core.api.get_registry_record instead"
761+
warnings.warn(warn, category=DeprecationWarning, stacklevel=2)
762+
warnings.simplefilter("default", DeprecationWarning)
763+
return api.get_registry_record(key, default=default)
759764

760765

761766
def check_permission(permission, obj):

src/senaite/core/browser/frontpage/frontpage.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
from plone import api as ploneapi
2525
from plone.protect.utils import addTokenToUrl
2626
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
27+
from senaite.core.config.registry import CLIENT_LANDING_PAGE
28+
from senaite.core.registry import get_registry_record
2729
from zope.component import getAdapters
2830

2931

@@ -89,6 +91,13 @@ def __call__(self):
8991
if landingpage:
9092
return self.request.response.redirect(landingpage.absolute_url())
9193

94+
# Fourth precedence: Default landing page in client view
95+
client = api.get_current_client()
96+
if client:
97+
view = get_registry_record(CLIENT_LANDING_PAGE)
98+
url = "{}/{}".format(api.get_url(client), view)
99+
return self.request.response.redirect(url)
100+
92101
# Last precedence: Front Page
93102
return self.template()
94103

src/senaite/core/config/registry.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# This file is part of SENAITE.CORE.
4+
#
5+
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU General Public License as published by the Free Software
7+
# Foundation, version 2.
8+
#
9+
# This program is distributed in the hope that it will be useful, but WITHOUT
10+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
# details.
13+
#
14+
# You should have received a copy of the GNU General Public License along with
15+
# this program; if not, write to the Free Software Foundation, Inc., 51
16+
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
#
18+
# Copyright 2018-2023 by it's authors.
19+
# Some rights reserved, see README and LICENSE.
20+
21+
CLIENT_LANDING_PAGE = "client_landing_page"

src/senaite/core/configure.zcml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<include package=".subscribers" />
3232
<include package=".upgrade" />
3333
<include package=".utilities" />
34+
<include package=".vocabularies" />
3435
<include package=".z3cform" />
3536

3637
<!-- portal skins -->

src/senaite/core/profiles/default/metadata.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0"?>
22
<metadata>
3-
<version>2524</version>
3+
<version>2525</version>
44
<dependencies>
55
<dependency>profile-Products.ATContentTypes:base</dependency>
66
<dependency>profile-Products.CMFEditions:CMFEditions</dependency>

src/senaite/core/registry/schema.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class IClientRegistry(ISenaiteRegistry):
4040
description=_("Settings for Clients"),
4141
fields=[
4242
"auto_create_client_group",
43+
"client_landing_page",
4344
],
4445
)
4546

@@ -57,6 +58,22 @@ class IClientRegistry(ISenaiteRegistry):
5758
required=False,
5859
)
5960

61+
client_landing_page = schema.Choice(
62+
title=_(
63+
u"label_registry_client_landing_page",
64+
default=u"Client landing page"
65+
),
66+
description=_(
67+
u"description_registry_client_landing_page",
68+
default=u"Select the default landing page. This is used when a "
69+
u"Client user logs into the system, or when a client is "
70+
u"selected from the client folder listing"
71+
),
72+
vocabulary="senaite.core.vocabularies.registry.client_landing_pages",
73+
default="analysisrequests",
74+
required=True,
75+
)
76+
6077

6178
class ILabelRegistry(ISenaiteRegistry):
6279
"""Label settings

src/senaite/core/upgrade/v02_05_000.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@
3737
from senaite.core.catalog import SETUP_CATALOG
3838
from senaite.core.catalog import WORKSHEET_CATALOG
3939
from senaite.core.config import PROJECTNAME as product
40+
from senaite.core.config.registry import CLIENT_LANDING_PAGE
4041
from senaite.core.permissions import ManageBika
4142
from senaite.core.permissions import TransitionReceiveSample
4243
from senaite.core.registry import get_registry_record
44+
from senaite.core.registry import set_registry_record
4345
from senaite.core.setuphandlers import _run_import_step
4446
from senaite.core.setuphandlers import add_dexterity_items
4547
from senaite.core.setuphandlers import CATALOG_MAPPINGS
@@ -53,6 +55,8 @@
5355
from senaite.core.workflow import ANALYSIS_WORKFLOW
5456
from senaite.core.workflow import SAMPLE_WORKFLOW
5557
from zope.interface import alsoProvides
58+
from zope.schema.interfaces import IVocabularyFactory
59+
from zope.component import getUtility
5660

5761
PORTAL_CATALOG = "portal_catalog"
5862

@@ -262,6 +266,7 @@ def update_report_catalog(tool):
262266
logger.info("Update report catalog [DONE]")
263267

264268

269+
@upgradestep(product, version)
265270
def import_registry(tool):
266271
"""Import registry step from profiles
267272
"""
@@ -650,3 +655,26 @@ def purge_orphan_worksheets(tool):
650655
obj._p_deactivate()
651656

652657
logger.info("Purging orphan Worksheet records from catalog [DONE]")
658+
659+
660+
def setup_client_landing_page(tool):
661+
"""Setup the registry record for the client's landing page
662+
"""
663+
logger.info("Setup client's default landing page ...")
664+
665+
# import the client registry
666+
import_registry(tool)
667+
668+
# look for the legacy registry record
669+
key = "bika.lims.client.default_landing_page"
670+
value = api.get_registry_record(key, default="")
671+
672+
# set the value to the new registry record
673+
vocab_key = "senaite.core.vocabularies.registry.client_landing_pages"
674+
vocab_factory = getUtility(IVocabularyFactory, vocab_key)
675+
vocabulary = vocab_factory(api.get_portal())
676+
values = [item.value for item in vocabulary]
677+
if value in values:
678+
set_registry_record(CLIENT_LANDING_PAGE, value)
679+
680+
logger.info("Setup client's default landing page [DONE]")

src/senaite/core/upgrade/v02_05_000.zcml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
44
i18n_domain="senaite.core">
55

6+
<genericsetup:upgradeStep
7+
title="SENAITE.CORE 2.5.0: Setup client landing page"
8+
description="Setup client landing page configuration"
9+
source="2524"
10+
destination="2525"
11+
handler=".v02_05_000.setup_client_landing_page"
12+
profile="senaite.core:default"/>
13+
614
<genericsetup:upgradeStep
715
title="SENAITE.CORE 2.5.0: Un-catalog orphan worksheets"
816
description="Un-catalog worksheets that were once removed"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# This file is part of SENAITE.CORE.
4+
#
5+
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU General Public License as published by the Free Software
7+
# Foundation, version 2.
8+
#
9+
# This program is distributed in the hope that it will be useful, but WITHOUT
10+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
# details.
13+
#
14+
# You should have received a copy of the GNU General Public License along with
15+
# this program; if not, write to the Free Software Foundation, Inc., 51
16+
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
#
18+
# Copyright 2018-2023 by it's authors.
19+
# Some rights reserved, see README and LICENSE.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<configure
2+
xmlns="http://namespaces.zope.org/zope"
3+
i18n_domain="senaite.core">
4+
5+
<utility
6+
component=".registry.ClientLandingPagesVocabularyFactory"
7+
name="senaite.core.vocabularies.registry.client_landing_pages" />
8+
9+
</configure>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# This file is part of SENAITE.CORE.
4+
#
5+
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU General Public License as published by the Free Software
7+
# Foundation, version 2.
8+
#
9+
# This program is distributed in the hope that it will be useful, but WITHOUT
10+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
# details.
13+
#
14+
# You should have received a copy of the GNU General Public License along with
15+
# this program; if not, write to the Free Software Foundation, Inc., 51
16+
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
#
18+
# Copyright 2018-2023 by it's authors.
19+
# Some rights reserved, see README and LICENSE.
20+
21+
from zope.interface import implementer
22+
from zope.schema.interfaces import IVocabularyFactory
23+
from zope.schema.vocabulary import SimpleTerm
24+
from zope.schema.vocabulary import SimpleVocabulary
25+
from bika.lims import api
26+
27+
28+
@implementer(IVocabularyFactory)
29+
class ClientLandingPagesVocabulary(object):
30+
"""Vocabulary factory for Client landing pages
31+
"""
32+
33+
skip = ["edit", "manage_access", "auditlog", ]
34+
35+
def __call__(self, context):
36+
pt = api.get_tool("portal_types")
37+
type_info = pt.getTypeInfo("Client")
38+
terms = []
39+
for action in type_info.listActionInfos():
40+
if not action.get("visible", True):
41+
continue
42+
if action.get("id") in self.skip:
43+
continue
44+
url = action.get("url")
45+
if not url:
46+
continue
47+
48+
# remove leading/trailing slashes
49+
url = url.strip("/")
50+
51+
# create the vocab term
52+
title = action.get("title")
53+
term = SimpleTerm(url, url, title)
54+
terms.append(term)
55+
56+
return SimpleVocabulary(terms)
57+
58+
59+
ClientLandingPagesVocabularyFactory = ClientLandingPagesVocabulary()

0 commit comments

Comments
 (0)