Skip to content

Commit

Permalink
Merge pull request #282 from TheoLechemia/feat/improve_max_characters
Browse files Browse the repository at this point in the history
Feat/improve max characters
  • Loading branch information
submarcos authored Feb 28, 2024
2 parents 126e279 + 77d0e84 commit 81bf1c8
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ CHANGELOG
-----------------------

- Fix of the widget `SelectMultipleWithPop` which did not add the newly created element in the related list (#1299)
- Add `MAX_CHARACTERS_BY_FIELD` to control the max length of a rich text field.
- Deprecate the `MAX_CHARACTERS` parameter

8.6.2 (2024-01-05)
-----------------------
Expand All @@ -14,6 +16,7 @@ CHANGELOG
- Support sub languages (see https://github.com/GeotrekCE/Geotrek-admin/issues/3801)



8.6.1 (2023-09-18)
-----------------------

Expand Down
9 changes: 6 additions & 3 deletions docs/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,12 @@ Or change just one parameter (the opacity for example) :
Edition
'''''''

For rich text fields, it is possible to a max number of caracters (spaces includes).
A help message will be added, and color of TinyMCE status bar will be colored in pink.
For rich text fields, it is possible to indicate a max number of characters on a specified field (spaces includes).
A help message will be added, and color of TinyMCE status bar and border will be colored in red.

.. code-block :: python
MAPENTITY_CONFIG['MAX_CHARACTERS'] = 1500
MAPENTITY_CONFIG['MAX_CHARACTERS_BY_FIELD'] = {
"tourism_touristicevent": [{'field': 'description_teaser_fr', 'value': 50}, {'field': 'accessibility_fr', 'value': 25}],
"trekking_trek": [{'field': 'description_teaser_fr', 'value': 150}],
}
23 changes: 20 additions & 3 deletions mapentity/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import copy

from warnings import warn

from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Button, HTML, Submit
Expand Down Expand Up @@ -106,15 +108,28 @@ def __init__(self, *args, **kwargs):
self.helper.form_tag = True

# If MAX_CHARACTERS is setted, set help text for rich text fields
textfield_help_text = ''
global_help_text = ''
max_characters = settings.MAPENTITY_CONFIG.get('MAX_CHARACTERS', None)
if max_characters:
textfield_help_text = _('%(max)s characters maximum recommended') % {'max': max_characters}

warn(
"Parameters MAX_CHARACTERS is deprecated, please use MAX_CHARACTERS_BY_FIELD instead",
DeprecationWarning,
stacklevel=2
)
global_help_text = _('%(max)s characters maximum recommended') % {'max': max_characters}

max_characters_by_field_config = settings.MAPENTITY_CONFIG.get('MAX_CHARACTERS_BY_FIELD', {}) or {}
# Default widgets
for fieldname, formfield in self.fields.items():
textfield_help_text = ''
# Custom code because formfield_callback does not work with inherited forms
if formfield:
# set max character limit :
if self._meta.model._meta.db_table in max_characters_by_field_config:
for conf in max_characters_by_field_config[self._meta.model._meta.db_table]:
if fieldname == conf["field"]:
textfield_help_text = _('%(max)s characters maximum recommended') % {'max': conf["value"]}

# Assign map widget to all geometry fields
try:
formmodel = self._meta.model
Expand All @@ -134,6 +149,8 @@ def __init__(self, *args, **kwargs):
# Bypass widgets that inherit textareas, such as geometry fields
if formfield.widget.__class__ == forms.widgets.Textarea:
formfield.widget = TinyMCE()
if max_characters:
textfield_help_text = global_help_text
if formfield.help_text:
formfield.help_text += f", {textfield_help_text}"
else:
Expand Down
1 change: 1 addition & 0 deletions mapentity/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'MAP_STYLES': _DEFAULT_MAP_STYLES,
'REGEX_PATH_ATTACHMENTS': r'\.\d+x\d+_q\d+(_crop)?\.(jpg|png|jpeg)$',
'MAX_CHARACTERS': None,
'MAX_CHARACTERS_BY_FIELD': {},
}, **getattr(settings, 'MAPENTITY_CONFIG', {}))

# default MAP_STYLES should not be replaced but updated by MAPENTITY_CONFIG
Expand Down
25 changes: 24 additions & 1 deletion mapentity/static/mapentity/mapentity.helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ function tr(s) {


function tinyMceInit(editor) {
// Overflow on characters count
var context = $('body').data();
editor.on('WordCountUpdate', function(event) {
console.log(window.SETTINGS);
// DEPRECATED paramters maxCharacters -> to remove
if (("container" in event.target) && (window.SETTINGS.maxCharacters > 0)) {
var characters = event.wordCount.characters;
if (characters > window.SETTINGS.maxCharacters) {
Expand All @@ -117,5 +119,26 @@ function tinyMceInit(editor) {
event.target.container.classList.remove('cec-overflow');
}
}
if (("container" in event.target) && (window.SETTINGS.maxCharactersByField)) {
var fullTableName = context.appname+"_"+context.modelname
if (fullTableName in window.SETTINGS.maxCharactersByField) {
var currenInputName = event.target.container.previousSibling.name;
window.SETTINGS.maxCharactersByField[fullTableName].forEach(config => {
if(config.field == currenInputName) {
var statusBar = $(event.target.container).find(".tox-statusbar__wordcount");
$(event.target.container).find(".injectedCount").remove()
$("<p class='injectedCount'>"+event.wordCount.characters+"/"+config.value+" characters</p>").insertBefore(statusBar)
if(event.wordCount.characters > config.value) {

event.target.container.classList.add('cec-overflow');
event.target.container.classList.add('is-invalid');
} else {
event.target.container.classList.remove('cec-overflow');
event.target.container.classList.remove('is-invalid');
}
}
})
}
}
});
}
5 changes: 5 additions & 0 deletions mapentity/static/mapentity/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,11 @@ label.requiredField .asteriskField {
.cec-overflow.tox .tox-statusbar {
background-color: pink;
}
.tox.is-invalid {
border-color: #dc3545!important;

}



/*
Expand Down
2 changes: 2 additions & 0 deletions mapentity/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ class ModelName(mapentity_models.MapEntityMixin, models.Model):
# Languages
dictsettings['languages'] = dict(available=dict(app_settings['TRANSLATED_LANGUAGES']),
default=app_settings['LANGUAGE_CODE'])
# MAX_CHARACTERS paramters is deprecated : to remove
dictsettings['maxCharacters'] = app_settings['MAX_CHARACTERS']
dictsettings['maxCharactersByField'] = app_settings['MAX_CHARACTERS_BY_FIELD']
return dictsettings


Expand Down
32 changes: 22 additions & 10 deletions test_app/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,31 @@ def test_translated_fields_layout(self):


class MapEntityRichTextFormTest(TestCase):
old_setting = app_settings.copy()
old_setting["MAX_CHARACTERS"] = 10
new_setting = app_settings.copy()
new_setting['MAX_CHARACTERS_BY_FIELD'] = {
"test_app_dummymodel": [{'field': 'short_description', 'value': 5}]
}

def setUp(self):
app_settings['MAX_CHARACTERS'] = 1200

@override_settings(MAPENTITY_CONFIG=app_settings)
def test_max_characters(self):
"""Test if help text is set with MAX_CHARACTERS setting"""
@override_settings(MAPENTITY_CONFIG=new_setting)
def test_max_characters_by_field(self):
"""Test if help text is set with MAX_CHARACTERS_BY_FIELD setting"""
sample_object = DummyModel.objects.create()

form = DummyForm(instance=sample_object)
self.assertIn('1200 characters maximum recommended', form.fields['description'].help_text)
self.assertIn('Short description, 1200 characters maximum recommended',
self.assertIn('', form.fields['description'].help_text)
self.assertIn('Short description, 5 characters maximum recommended',
form.fields['short_description'].help_text)

def tearDown(self):
app_settings['MAX_CHARACTERS'] = 1200
@override_settings(MAPENTITY_CONFIG=old_setting)
def test_max_characters_global(self):
"""Test if help text is set with MAX_CHARACTERS setting -> deprecated paramter"""
sample_object = DummyModel.objects.create()

form = DummyForm(instance=sample_object)
for field_name in ["description", "short_description"]:
self.assertIn(
'10 characters maximum recommended',
form.fields[field_name].help_text
)

0 comments on commit 81bf1c8

Please sign in to comment.