diff --git a/taccsite_cms/contrib/helpers.py b/taccsite_cms/contrib/helpers.py index d47584d7f..19a76535c 100644 --- a/taccsite_cms/contrib/helpers.py +++ b/taccsite_cms/contrib/helpers.py @@ -239,3 +239,13 @@ def clean(self): pass else: raise err + + + +# Get name of field from a given model + +# SEE: https://stackoverflow.com/a/14498938/11817077 +def get_model_field_name(model, field_name): + model_field_name = model._meta.get_field(field_name).verbose_name.title() + + return model_field_name diff --git a/taccsite_cms/contrib/taccsite_callout/cms_plugins.py b/taccsite_cms/contrib/taccsite_callout/cms_plugins.py index 4446fd7eb..5d1ff0971 100644 --- a/taccsite_cms/contrib/taccsite_callout/cms_plugins.py +++ b/taccsite_cms/contrib/taccsite_callout/cms_plugins.py @@ -4,11 +4,25 @@ from djangocms_link.cms_plugins import LinkPlugin -from taccsite_cms.contrib.helpers import concat_classnames +from taccsite_cms.contrib.helpers import ( + concat_classnames, + get_model_field_name +) from taccsite_cms.contrib.constants import TEXT_FOR_NESTED_PLUGIN_CONTENT_SWAP from .models import TaccsiteCallout + + + +# Constants + +RESIZE_FIGURE_FIELD_NAME = get_model_field_name(TaccsiteCallout, 'resize_figure_to_fit') + + + +# Plugin + @plugin_pool.register_plugin class TaccsiteCalloutPlugin(LinkPlugin): """ @@ -53,14 +67,14 @@ def get_render_template(self, context, instance, placeholder): plugin_name='Image' ) + '\
\ - When the image resize field is checked, the image may disappear after saving this plugin. Reload the page to reload the image.', - 'fields': ( - 'resize_figure_to_fit', - ), + If image disappears while editing, then reload the page to reload the image.', + 'fields': (), }), (_('Advanced settings'), { 'classes': ('collapse',), + 'description': 'Only use the "' + RESIZE_FIGURE_FIELD_NAME + '" in emergencies. It is preferable to resize the image. When the "Advanced settings" field "' + RESIZE_FIGURE_FIELD_NAME + '" is checked, the image may disappear after saving this plugin (because of a JavaScript race condition). Using a server-side solution would eliminate this caveat.', 'fields': ( + 'resize_figure_to_fit', 'attributes', ) }), diff --git a/taccsite_cms/contrib/taccsite_callout/migrations/0001_initial.py b/taccsite_cms/contrib/taccsite_callout/migrations/0001_initial.py index 3957c6a21..0b9b86201 100644 --- a/taccsite_cms/contrib/taccsite_callout/migrations/0001_initial.py +++ b/taccsite_cms/contrib/taccsite_callout/migrations/0001_initial.py @@ -1,15 +1,18 @@ -# Generated by Django 2.2.16 on 2021-08-20 23:53 +# Generated by Django 2.2.16 on 2021-08-24 13:03 from django.db import migrations, models import django.db.models.deletion import djangocms_attributes_field.fields +import djangocms_link.validators +import filer.fields.file class Migration(migrations.Migration): - initial = True + replaces = [('taccsite_callout', '0001_initial'), ('taccsite_callout', '0003_auto_20210823_1902')] dependencies = [ + ('filer', '0012_file_mime_type'), ('cms', '0022_auto_20180620_1551'), ] @@ -17,10 +20,20 @@ class Migration(migrations.Migration): migrations.CreateModel( name='TaccsiteCallout', fields=[ - ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='taccsite_callout_taccsitecallout', serialize=False, to='cms.CMSPlugin')), + ('cmsplugin_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='taccsite_callout_taccsitecallout', serialize=False, to='cms.CMSPlugin')), ('title', models.CharField(blank=True, help_text='A heading for the callout.', max_length=100, verbose_name='Title')), ('description', models.CharField(blank=True, help_text='A paragraph for the callout.', max_length=200, verbose_name='Description')), + ('resize_figure_to_fit', models.BooleanField(default=True, help_text='Make image shorter or taller to match the height of text beside it.', verbose_name='Resize any image to fit')), ('attributes', djangocms_attributes_field.fields.AttributesField(default=dict)), + ('anchor', models.CharField(blank=True, help_text='Appends the value only after the internal or external link. Do not include a preceding "#" symbol.', max_length=255, verbose_name='Anchor')), + ('external_link', models.CharField(blank=True, help_text='Provide a link to an external source.', max_length=2040, validators=[djangocms_link.validators.IntranetURLValidator(intranet_host_re=None)], verbose_name='External link')), + ('file_link', filer.fields.file.FilerFileField(blank=True, help_text='If provided links a file from the filer app.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='filer.File', verbose_name='File link')), + ('internal_link', models.ForeignKey(blank=True, help_text='If provided, overrides the external link.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='cms.Page', verbose_name='Internal link')), + ('mailto', models.EmailField(blank=True, max_length=255, verbose_name='Email address')), + ('name', models.CharField(blank=True, max_length=255, verbose_name='Display name')), + ('phone', models.CharField(blank=True, max_length=255, verbose_name='Phone')), + ('target', models.CharField(blank=True, choices=[('_blank', 'Open in new window'), ('_self', 'Open in same window'), ('_parent', 'Delegate to parent'), ('_top', 'Delegate to top')], max_length=255, verbose_name='Target')), + ('template', models.CharField(choices=[('default', 'Default')], default='default', max_length=255, verbose_name='Template')), ], options={ 'abstract': False, diff --git a/taccsite_cms/contrib/taccsite_callout/models.py b/taccsite_cms/contrib/taccsite_callout/models.py index eb2122999..9460c4f25 100644 --- a/taccsite_cms/contrib/taccsite_callout/models.py +++ b/taccsite_cms/contrib/taccsite_callout/models.py @@ -15,13 +15,13 @@ class TaccsiteCallout(AbstractLink): title = models.CharField( verbose_name=_('Title'), help_text=_('A heading for the callout.'), - blank=True, + blank=False, max_length=100, ) description = models.CharField( verbose_name=_('Description'), help_text=_('A paragraph for the callout.'), - blank=True, + blank=False, max_length=200, ) @@ -29,7 +29,7 @@ class TaccsiteCallout(AbstractLink): verbose_name=_('Resize any image to fit'), help_text=_('Make image shorter or taller to match the height of text beside it.'), blank=False, - default=True + default=False ) attributes = fields.AttributesField() @@ -41,7 +41,7 @@ def get_short_description(self): # Parent - link_is_optional = True + link_is_optional = False class Meta: abstract = False diff --git a/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css b/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css index 5189f68ea..986b236ac 100644 --- a/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css +++ b/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css @@ -5,6 +5,7 @@ Styles that allow visible link hover for article lists. %x-article-link-stretch - Stretch link to cover container %x-article-link-hover - Give link a hover state +%x-article-link-hover--gapless - Make link hover state fix gapless layout %x-article-link-active - Give link an active (click, enter) state Styleguide Tools.ExtendsAndMixins.ArticleLink @@ -12,7 +13,8 @@ Styleguide Tools.ExtendsAndMixins.ArticleLink /* WARNING: A link ancestor must have its `position` set (not to static) */ -/* Expand link to cover container */ +/* To expand link to cover container */ +.x-article-link-stretch, %x-article-link-stretch { position: absolute; height: 100%; @@ -26,7 +28,8 @@ Styleguide Tools.ExtendsAndMixins.ArticleLink overflow: hidden; } -/* To give link hover state feedback */ +/* To give link state (pseudo-class) feedback */ +.x-article-link-hover, %x-article-link-hover { outline: 1px solid var(--global-color-accent--normal); } @@ -35,3 +38,8 @@ Styleguide Tools.ExtendsAndMixins.ArticleLink %x-article-link-active { outline: 1px dotted var(--global-color-accent--normal); } + +/* To give link active state feedback */ +%x-article-link-active { + outline: 1px dotted var(--global-color-accent--normal); +}