Skip to content

Commit 5ded2d2

Browse files
authored
Merge pull request #21 from collective/approved_column
Added "Approved?" column to the categorized elements table
2 parents 41ee32d + 6324a46 commit 5ded2d2

28 files changed

+599
-110
lines changed

.github/workflows/main.yml

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,43 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- name: Checkout
14-
uses: actions/checkout@v2
14+
uses: actions/checkout@v5
1515
- name: Setup Env
1616
run: |
1717
sudo apt-get update -qqy
1818
sudo apt-get install -y libjpeg8-dev libbz2-dev
1919
pip install --upgrade pip
2020
pip install -r requirements.txt
2121
- name: Set up pyenvi and Python
22-
uses: "gabrielfalcao/pyenv-action@v14"
22+
uses: "gabrielfalcao/pyenv-action@v18"
2323
with:
2424
default: 2.7.18
25-
versions: 3.8.16
2625
command: pyenv -v
27-
- name: Set up Ruby
28-
uses: ruby/setup-ruby@v1
29-
with:
30-
ruby-version: '2.6'
3126
- name: Set up Env
3227
run: |
33-
sudo apt-get update
34-
sudo apt-get install -qqy graphicsmagick poppler-utils libreoffice
35-
sudo gem install docsplit
28+
sudo apt update -qq -y
29+
sudo apt install -qq -y gnupg2
30+
gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
31+
curl -sSL https://get.rvm.io | bash -s stable
32+
source $HOME/.rvm/scripts/rvm
33+
34+
# Puis Ruby 2.7.6 :
35+
rvm pkg install openssl
36+
rvm install ruby-2.7.6 --with-openssl-dir=$HOME/.rvm/usr
37+
38+
# Pour voir la version de ruby installée :
39+
which ruby
40+
41+
# Création d'un lien symbolique pour que docsplit puisse utiliser ruby (si pas de ruby système) :
42+
sudo ln -s $HOME/.rvm/rubies/ruby-2.7.6/bin/ruby /usr/bin/ruby2.7
43+
sudo rm /usr/bin/ruby
44+
sudo ln -s ruby2.7 /usr/bin/ruby
45+
46+
# Enfin, on peut installer les autres dépendances de documentviewer :
47+
gem install docsplit
48+
echo "$HOME/.rvm/gems/ruby-2.7.6/gems/docsplit-0.7.6/bin" >> $GITHUB_PATH
49+
sudo apt install -qq -y graphicsmagick wv poppler-utils libreoffice
50+
3651
pip install -r requirements.txt coverage==5.3.1
3752
- name: Cache eggs
3853
uses: actions/cache@v4
@@ -53,18 +68,18 @@ jobs:
5368
runs-on: ubuntu-latest
5469
steps:
5570
- name: Checkout
56-
uses: actions/checkout@v2
71+
uses: actions/checkout@v5
5772
- name: Setup Env
5873
run: |
5974
sudo apt-get update -qqy
6075
sudo apt-get install -y libjpeg8-dev libbz2-dev
6176
pip install --upgrade pip
6277
pip install -r requirements.txt
6378
- name: Set up pyenv and Python
64-
uses: "gabrielfalcao/pyenv-action@v14"
79+
uses: "gabrielfalcao/pyenv-action@v18"
6580
with:
6681
default: 2.7.18
67-
versions: 3.8.16
82+
versions: 3.6.15
6883
command: pyenv -v
6984
- name: Set up Ruby
7085
uses: ruby/setup-ruby@v1
@@ -93,14 +108,11 @@ jobs:
93108
- name: test coverage
94109
run: |
95110
bin/coverage run bin/test -t !robot
96-
- name: Set up Python 3.6
97-
uses: actions/setup-python@v2
98-
with:
99-
python-version: 3.6
100111
- name: Install Coveralls
101112
run: |
102-
pip3 install -U pip setuptools --no-cache-dir
103-
pip3 install -U "coveralls>=3.0.0" coverage==5.3.1 --no-cache-dir
113+
pyenv local 3.6
114+
pip install -U pip setuptools --no-cache-dir
115+
pip install -U "coveralls>=3.0.0" coverage==5.3.1 --no-cache-dir
104116
- name: Publish to Coveralls
105117
env:
106118
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CHANGES.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ Changelog
66

77
- Fix invalid jQuery selector for default Title field filling
88
[laulaz]
9-
9+
- Added "Approved?" column to the categorized elements table
10+
[chris-adam,sgeulette]
11+
- Added cache on IconClickableColumn action view.
12+
[chris-adam]
13+
- Added page reload possibility
14+
[sgeulette]
1015

1116
0.69 (2025-06-23)
1217
-----------------

README.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ This product will let you categorize created content using a category identified
2121

2222
A dexterity behavior can be enabled and will add a field "content category" that will list available categories defined in a configuration.
2323

24-
So you first have to define the categories by adding a ContentCategoryConfiguration somewhere. Then add a CategoryGroup on which some extra features may be activated :
24+
So you first have to define the categories by adding a ContentCategoryConfiguration somewhere. Then add a CategoryGroup on which some extra features may be activated :
2525

2626
- is content confidential?
2727
- is content an element to print?
2828
- is content an element to sign?
29+
- is content an element to approve?
2930

3031
If activated, these fields will be available on the content using the behavior.
3132

32-
Then into a CategoryGroup, you will be able to add ContentCategory that are characterized by a title and an icon. These ContentCategory elements will be the terms of a vocabulary used to select a category on a content using the behavior.
33+
Then into a CategoryGroup, you will be able to add ContentCategory that are characterized by a title and an icon. These ContentCategory elements will be the terms of a vocabulary used to select a category on a content using the behavior.
3334

3435
This package is widely overridable and is made to manage many usecases of iconified categories.
3536

src/collective/iconifiedcategory/adapter.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ def _get_basic_infos(self, category):
4747
'to_be_printed_activated': self._to_be_printed_activated(category),
4848
'confidentiality_activated': self._confidentiality_activated(category),
4949
'signed_activated': self._signed_activated(category),
50+
'approved_activated': self._approved_activated(category),
5051
'publishable_activated': self._publishable_activated(category),
5152
'to_print': self._to_print,
5253
'confidential': self._confidential,
5354
'to_sign': self._to_sign,
5455
'signed': self._signed,
56+
'to_approve': self._to_approve,
57+
'approved': self._approved,
5558
'publishable': self._publishable,
5659
'show_preview': self._show_preview(category),
5760
}
@@ -148,6 +151,18 @@ def _to_sign(self):
148151
def _signed(self):
149152
return getattr(self.obj, 'signed', False)
150153

154+
def _approved_activated(self, category):
155+
category_group = category.get_category_group()
156+
return category_group.approved_activated
157+
158+
@property
159+
def _to_approve(self):
160+
return getattr(self.obj, 'to_approve', False)
161+
162+
@property
163+
def _approved(self):
164+
return getattr(self.obj, 'approved', False)
165+
151166
def _publishable_activated(self, category):
152167
category_group = category.get_category_group()
153168
return category_group.publishable_activated

src/collective/iconifiedcategory/behaviors/iconifiedcategorization.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ def _content_category_changed_default_values(self, new_value):
9999
self.context.signed == current_category.signed:
100100
self.context.to_sign = new_category.to_sign
101101
self.context.signed = new_category.signed
102+
# to_approve
103+
if category_group.approved_activated and \
104+
self.context.to_approve == current_category.to_approve and \
105+
self.context.approved == current_category.approved:
106+
self.context.to_approve = new_category.to_approve
107+
self.context.approved = new_category.approved
102108
# publishable
103109
if category_group.publishable_activated and \
104110
self.context.publishable == current_category.publishable:
@@ -130,6 +136,13 @@ def to_sign(self):
130136
def signed(self):
131137
return getattr(aq_base(self.context), 'signed', False)
132138

139+
@property
140+
def to_approve(self):
141+
return getattr(aq_base(self.context), 'to_approve', False)
142+
143+
def approved(self):
144+
return getattr(aq_base(self.context), 'approved', False)
145+
133146
@property
134147
def publishable(self):
135148
return getattr(aq_base(self.context), 'publishable', False)

src/collective/iconifiedcategory/browser/actionview.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from collective.iconifiedcategory.interfaces import IIconifiedPrintable
1515
from plone import api
1616
from Products.CMFCore.permissions import ModifyPortalContent
17+
from Products.CMFPlone.utils import base_hasattr
1718
from Products.Five import BrowserView
1819
from z3c.json.interfaces import IJSONWriter
1920
from zope.component import getAdapter
@@ -28,6 +29,7 @@ class BaseView(BrowserView):
2829
attr_name = ''
2930
# when updating element, do that limited?
3031
limited = True
32+
permission = ModifyPortalContent
3133

3234
def _translate(self, msgid):
3335
return translate(
@@ -67,9 +69,11 @@ def get_values(self):
6769
for k, v in self.attribute_mapping.items()}
6870

6971
def _may_set_values(self, values, ):
70-
res = bool(api.user.has_permission(ModifyPortalContent, obj=self.context))
72+
res = bool(api.user.has_permission(self.permission, obj=self.context))
7173
if res:
7274
# is this functionnality enabled?
75+
if not base_hasattr(self.context, "content_category"):
76+
return False
7377
self.category = utils.get_category_object(self.context, self.context.content_category)
7478
category_group = self.category.get_category_group()
7579
res = getattr(category_group, self.category_group_attr_name, True)
@@ -101,6 +105,7 @@ def set_values(self, values):
101105
old_values,
102106
values,
103107
))
108+
self.context.reindexObject(idxs=list(self.attribute_mapping.keys()))
104109
return status, msg
105110

106111
def _get_status(self, values):
@@ -186,6 +191,45 @@ def set_values(self, values):
186191
return status, utils.signed_message(self.context)
187192

188193

194+
class ApprovedChangeView(BaseView):
195+
attribute_mapping = {
196+
'approved': 'iconified-value',
197+
'to_approve': 'iconified-value',
198+
}
199+
category_group_attr_name = 'approved_activated'
200+
attr_name = 'to_approve'
201+
202+
def _get_next_values(self, old_values):
203+
""" """
204+
values = {}
205+
if old_values['to_approve'] is False:
206+
values['to_approve'] = True
207+
values['approved'] = False
208+
status = 0
209+
elif old_values['to_approve'] is True and old_values['approved'] is False:
210+
values['to_approve'] = True
211+
values['approved'] = True
212+
status = 1
213+
else:
214+
values['to_approve'] = False
215+
values['approved'] = False
216+
status = -1
217+
return status, values
218+
219+
def set_values(self, values):
220+
"""
221+
Value are setting 'to_approve' and 'approved' attributes with following
222+
possibility depending on allowed ones :
223+
- False/False;
224+
- True/False;
225+
- True/True.
226+
"""
227+
old_values = self.get_current_values()
228+
status, values = self._get_next_values(old_values)
229+
super(ApprovedChangeView, self).set_values(values)
230+
return status, utils.approved_message(self.context)
231+
232+
189233
class PublishableChangeView(BaseView):
190234
attribute_mapping = {
191235
'publishable': 'iconified-value',

src/collective/iconifiedcategory/browser/configure.zcml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@
143143
permission="zope2.View"
144144
/>
145145

146+
<browser:page
147+
name="iconified-approved"
148+
for="*"
149+
layer="collective.iconifiedcategory.interfaces.ICollectiveIconifiedCategoryLayer"
150+
class=".actionview.ApprovedChangeView"
151+
permission="zope2.View"
152+
/>
153+
146154
<browser:page
147155
name="iconified-publishable"
148156
for="*"
@@ -250,6 +258,15 @@
250258
factory=".tabview.SignedColumn"
251259
/>
252260

261+
<adapter
262+
name="approved-column"
263+
for="zope.interface.Interface
264+
zope.interface.Interface
265+
collective.iconifiedcategory.interfaces.ICategorizedApproved"
266+
provides="z3c.table.interfaces.IColumn"
267+
factory=".tabview.ApprovedColumn"
268+
/>
269+
253270
<adapter
254271
name="publishable-column"
255272
for="zope.interface.Interface

src/collective/iconifiedcategory/browser/contentview.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class FormMixin(object):
2424
'to_print': 'to_be_printed_activated',
2525
'to_sign': 'signed_activated',
2626
'signed': 'signed_activated',
27+
'to_approve': 'approved_activated',
28+
'approved': 'approved_activated',
2729
}
2830

2931
@property
@@ -64,6 +66,8 @@ class BaseView(DefaultView):
6466
'to_print': 'to_be_printed_activated',
6567
'to_sign': 'signed_activated',
6668
'signed': 'signed_activated',
69+
'to_approve': 'approved_activated',
70+
'approved': 'approved_activated',
6771
}
6872

6973
def updateWidgets(self):

0 commit comments

Comments
 (0)