Skip to content

Fixed missing categories when 'sending to college' in iA.Docs #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Changelog

- Used UID key in `vocabularies.proposing_groups_for_user_vocabulary`.
[sgeulette]
- Fixed categories for user vocabulary after REST api migration and meeting dates vocabulary display.
[cadam]

2.0.0b2 (2024-10-16)
--------------------
Expand Down
220 changes: 129 additions & 91 deletions src/imio/pm/wsclient/browser/vocabularies.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from imio.pm.wsclient.config import TAL_EVAL_FIELD_ERROR
from imio.pm.wsclient.interfaces import IPreferredMeetings
from imio.pm.wsclient.interfaces import ISendableAnnexesToPM
from natsort import humansorted
from operator import itemgetter
from plone import api
from plone.memoize import ram
from Products.statusmessages.interfaces import IStatusMessage
Expand All @@ -34,16 +36,20 @@ def __call__(self, context=None):
# query existing MeetingGroups from distant PM site if the default_pm_url is defined and working
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
settings = getMultiAdapter((portal, portal.REQUEST), name='ws4pmclient-settings')
settings = getMultiAdapter((portal, portal.REQUEST), name="ws4pmclient-settings")
pmConfigInfos = settings._rest_getConfigInfos()
terms = []
if pmConfigInfos:
for pmConfigInfo in pmConfigInfos:
terms.append(SimpleTerm(unicode(pmConfigInfo['id']),
unicode(pmConfigInfo['id']),
unicode(pmConfigInfo['title']),))
terms.append(
SimpleTerm(
unicode(pmConfigInfo["id"]),
unicode(pmConfigInfo["id"]),
unicode(pmConfigInfo["title"]),
)
)
return SimpleVocabulary(terms)


Expand All @@ -58,7 +64,7 @@ def __call__(self, context):
terms = []
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
for possible_permission in portal.acl_users.portal_role_manager.possible_permissions():
terms.append(SimpleTerm(possible_permission, possible_permission, possible_permission))
Expand All @@ -78,15 +84,19 @@ def __call__(self, context):
# query existing item data from distant PM site if the default_pm_url is defined and working
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
settings = getMultiAdapter((portal, portal.REQUEST), name='ws4pmclient-settings')
settings = getMultiAdapter((portal, portal.REQUEST), name="ws4pmclient-settings")
availableDatas = settings._rest_getItemCreationAvailableData()
if availableDatas:
for availableData in availableDatas:
terms.append(SimpleTerm(unicode(availableData),
unicode(availableData),
unicode(availableData),))
terms.append(
SimpleTerm(
unicode(availableData),
unicode(availableData),
unicode(availableData),
)
)
return SimpleVocabulary(terms)


Expand All @@ -100,64 +110,74 @@ def __call__(self, context):
"""Query every available proposingGroups for current user in a distant PloneMeeting."""
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name='ws4pmclient-settings')
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name="ws4pmclient-settings")
field_mappings = ws4pmsettings.settings().field_mappings
if not field_mappings:
portal.REQUEST.set('error_in_vocabularies', True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(NO_FIELD_MAPPINGS_ERROR),
'error')
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(_(NO_FIELD_MAPPINGS_ERROR), "error")
return SimpleVocabulary([])
forcedProposingGroup = None
vars = {}
vars['meetingConfigId'] = portal.REQUEST.get('meetingConfigId')
vars["meetingConfigId"] = portal.REQUEST.get("meetingConfigId")
for field_mapping in field_mappings:
# try to find out if a proposingGroup is forced in the configuration
if field_mapping[u'field_name'] == 'proposingGroup':
if field_mapping[u"field_name"] == "proposingGroup":
try:
forcedProposingGroup = ws4pmsettings.renderTALExpression(context,
portal,
field_mapping['expression'],
vars)
forcedProposingGroup = ws4pmsettings.renderTALExpression(
context, portal, field_mapping["expression"], vars
)
break
except Exception, e:
portal.REQUEST.set('error_in_vocabularies', True)
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(TAL_EVAL_FIELD_ERROR, mapping={'expr': field_mapping['expression'],
'field_name': field_mapping['field_name'],
'error': e}),
'error')
_(
TAL_EVAL_FIELD_ERROR,
mapping={
"expr": field_mapping["expression"],
"field_name": field_mapping["field_name"],
"error": e,
},
),
"error",
)
return SimpleVocabulary([])
# even if we get a forcedProposingGroup, double check that the current user can actually use it
userInfos = ws4pmsettings._rest_getUserInfos(showGroups=True, suffix='creators')
if not userInfos or 'extra_include_groups' not in userInfos:
portal.REQUEST.set('error_in_vocabularies', True)
userInfos = ws4pmsettings._rest_getUserInfos(showGroups=True, suffix="creators")
if not userInfos or "extra_include_groups" not in userInfos:
portal.REQUEST.set("error_in_vocabularies", True)
# add a status message if the main error is not the fact that we can not connect to the WS
if userInfos is not None:
userThatWillCreate = ws4pmsettings._getUserIdToUseInTheNameOfWith()
IStatusMessage(portal.REQUEST).addStatusMessage(
_(NO_USER_INFOS_ERROR, mapping={'userId': userThatWillCreate}), 'error')
_(NO_USER_INFOS_ERROR, mapping={"userId": userThatWillCreate}), "error"
)
return SimpleVocabulary([])
terms = []
forcedProposingGroupExists = not forcedProposingGroup and True or False
for group in userInfos['extra_include_groups']:
if forcedProposingGroup == group['id']:
for group in humansorted(userInfos["extra_include_groups"], key=lambda x: itemgetter("title")(x)):
if forcedProposingGroup == group["id"]:
forcedProposingGroupExists = True
terms.append(SimpleTerm(unicode(group['UID']),
unicode(group['UID']),
unicode(group['title']),))
terms.append(
SimpleTerm(
unicode(group["UID"]),
unicode(group["UID"]),
unicode(group["title"]),
)
)
break
if not forcedProposingGroup:
terms.append(SimpleTerm(unicode(group['UID']),
unicode(group['UID']),
unicode(group['title']),))
terms.append(
SimpleTerm(
unicode(group["UID"]),
unicode(group["UID"]),
unicode(group["title"]),
)
)
if not forcedProposingGroupExists:
portal.REQUEST.set('error_in_vocabularies', True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(CAN_NOT_CREATE_FOR_PROPOSING_GROUP_ERROR),
'error')
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(_(CAN_NOT_CREATE_FOR_PROPOSING_GROUP_ERROR), "error")
return SimpleVocabulary([])
return SimpleVocabulary(terms)

Expand All @@ -172,75 +192,84 @@ def __call__(self, context):
"""Query every available categories for current user in a distant PloneMeeting."""
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name='ws4pmclient-settings')
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name="ws4pmclient-settings")
field_mappings = ws4pmsettings.settings().field_mappings
if not field_mappings:
portal.REQUEST.set('error_in_vocabularies', True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(NO_FIELD_MAPPINGS_ERROR),
'error')
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(_(NO_FIELD_MAPPINGS_ERROR), "error")
return SimpleVocabulary([])
forcedCategory = None
vars = {}
meetingConfigId = portal.REQUEST.get('meetingConfigId') or \
portal.REQUEST.form.get('form.widgets.meetingConfigId')
vars['meetingConfigId'] = meetingConfigId
meetingConfigId = portal.REQUEST.get("meetingConfigId") or portal.REQUEST.form.get(
"form.widgets.meetingConfigId"
)
vars["meetingConfigId"] = meetingConfigId
for field_mapping in field_mappings:
# try to find out if a proposingGroup is forced in the configuration
if field_mapping[u'field_name'] == 'category':
if field_mapping[u"field_name"] == "category":
try:
forcedCategory = ws4pmsettings.renderTALExpression(context,
portal,
field_mapping['expression'],
vars)
forcedCategory = ws4pmsettings.renderTALExpression(
context, portal, field_mapping["expression"], vars
)
break
except Exception, e:
portal.REQUEST.set('error_in_vocabularies', True)
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(TAL_EVAL_FIELD_ERROR, mapping={'expr': field_mapping['expression'],
'field_name': field_mapping['field_name'],
'error': e}),
'error')
_(
TAL_EVAL_FIELD_ERROR,
mapping={
"expr": field_mapping["expression"],
"field_name": field_mapping["field_name"],
"error": e,
},
),
"error",
)
return SimpleVocabulary([])

configInfos = ws4pmsettings._rest_getConfigInfos(showCategories=True)
if not configInfos:
portal.REQUEST.set('error_in_vocabularies', True)
portal.REQUEST.set("error_in_vocabularies", True)
# add a status message if the main error is not the fact that we can not connect to the WS
if configInfos is not None:
IStatusMessage(portal.REQUEST).addStatusMessage(
_(NO_CONFIG_INFOS_ERROR), 'error')
IStatusMessage(portal.REQUEST).addStatusMessage(_(NO_CONFIG_INFOS_ERROR), "error")
return SimpleVocabulary([])
categories = []
# find categories for given meetingConfigId
for configInfo in configInfos:
if configInfo["id"] == meetingConfigId:
categories = hasattr(configInfo, 'categories') and configInfo.categories or ()
categories = configInfo.get("categories", ())
break
# if not categories is returned, it means that the meetingConfig does
# not use categories...
if not categories:
return SimpleVocabulary([])
terms = []
forcedCategoryExists = not forcedCategory and True or False
for category in categories:
for category in humansorted(categories, key=lambda x: itemgetter("title")(x)):
if forcedCategory == category["id"]:
forcedCategoryExists = True
terms.append(SimpleTerm(unicode(category["id"]),
unicode(category["id"]),
unicode(category["title"]),))
terms.append(
SimpleTerm(
unicode(category["id"]),
unicode(category["id"]),
unicode(category["title"]),
)
)
break
if not forcedCategory:
terms.append(SimpleTerm(unicode(category["id"]),
unicode(category["id"]),
unicode(category["title"]),))
terms.append(
SimpleTerm(
unicode(category["id"]),
unicode(category["id"]),
unicode(category["title"]),
)
)
if not forcedCategoryExists:
portal.REQUEST.set('error_in_vocabularies', True)
IStatusMessage(portal.REQUEST).addStatusMessage(
_(CAN_NOT_CREATE_WITH_CATEGORY_ERROR),
'error')
portal.REQUEST.set("error_in_vocabularies", True)
IStatusMessage(portal.REQUEST).addStatusMessage(_(CAN_NOT_CREATE_WITH_CATEGORY_ERROR), "error")
return SimpleVocabulary([])
return SimpleVocabulary(terms)

Expand All @@ -261,20 +290,19 @@ def __call__(self, context):
"""Query every available categories for current user in a distant PloneMeeting."""
portal = getSite()
# while called in an inline_validation, portal is not correct...
if not portal.__module__ == 'Products.CMFPlone.Portal':
if not portal.__module__ == "Products.CMFPlone.Portal":
portal = portal.aq_inner.aq_parent
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name='ws4pmclient-settings')
ws4pmsettings = getMultiAdapter((portal, portal.REQUEST), name="ws4pmclient-settings")
configInfos = ws4pmsettings._rest_getConfigInfos(showCategories=True)
if not configInfos:
portal.REQUEST.set('error_in_vocabularies', True)
portal.REQUEST.set("error_in_vocabularies", True)
# add a status message if the main error is not the fact that we can not connect to the WS
if configInfos is not None:
IStatusMessage(portal.REQUEST).addStatusMessage(
_(NO_CONFIG_INFOS_ERROR), 'error')
IStatusMessage(portal.REQUEST).addStatusMessage(_(NO_CONFIG_INFOS_ERROR), "error")
return SimpleVocabulary([])
request = api.portal.getRequest()
meeting_config_id = request.get('meetingConfigId', request.form.get('form.widgets.meetingConfigId'))
data = {'meetingConfigId': meeting_config_id}
meeting_config_id = request.get("meetingConfigId", request.form.get("form.widgets.meetingConfigId"))
data = {"meetingConfigId": meeting_config_id}
possible_meetings = ws4pmsettings._rest_getMeetingsAcceptingItems(data)
local = pytz.timezone("Europe/Brussels")
if not possible_meetings:
Expand All @@ -287,9 +315,15 @@ def __call__(self, context):
allowed_meetings = queryMultiAdapter((context, possible_meetings), IPreferredMeetings)
meetings = allowed_meetings and allowed_meetings.get() or possible_meetings
for meeting_info in meetings:
terms.append(SimpleTerm(unicode(meeting_info['UID']),
unicode(meeting_info['UID']),
unicode(meeting_info['date']),))
display_date = datetime.strftime(meeting_info["date"], "%d/%m/%Y %H:%M") \
if isinstance(meeting_info["date"], datetime) else meeting_info["date"]
terms.append(
SimpleTerm(
unicode(meeting_info["UID"]),
unicode(meeting_info["UID"]),
unicode(display_date),
)
)
return SimpleVocabulary(terms)


Expand All @@ -306,9 +340,13 @@ def __call__(self, context):

if to_annexes:
for annex in to_annexes.get():
terms.append(SimpleTerm(annex['UID'],
annex['UID'],
annex['title'],))
terms.append(
SimpleTerm(
annex["UID"],
annex["UID"],
annex["title"],
)
)
return SimpleVocabulary(terms)


Expand Down
Loading
Loading