-
Notifications
You must be signed in to change notification settings - Fork 2
GH-83: Callout Plugin #324
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
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
82b768f
GH-83: Callout Component
wesleyboar c2c96ec
GH-83: Temp: Callout Snippet (Frontera)
wesleyboar c15d766
GH-83: WIP: Callout Plugin
wesleyboar 4fa354c
GH-83: Fix Callout Component after Plugin's tweaks
wesleyboar a15e585
GH-83: Fix Callout Plugin, Update Styles to Match
wesleyboar dba3f4b
GH-83: Remove leftover templates
wesleyboar c24e0f9
GH-83: Noop: Add markup whitespace for legibility
wesleyboar 54fc04a
GH-83: Quick: Remove temp snippet
wesleyboar 1266e4e
Merge branch 'main' into task/GH-83-callout-element
wesleyboar ed0e749
Quick: Add x-article-link-active mixin
wesleyboar 51d3f1d
GH-83: Support Hyperlink (requires 69f47cc)
wesleyboar df1060b
GH-83: Add missing helper clean_for_abstract_link
wesleyboar d59c3f6
GH-83: Squash migrations. Accept GH-321
wesleyboar acefadf
GH-83/GH-321: Add missing static template tag load
wesleyboar 9767d45
GH-321: Resize Callout image to parent height
wesleyboar 7ffceeb
GH-321: Default to not resize image. Add warning.
wesleyboar a07957e
GH-83: Add two relevant docs from PR #280
wesleyboar 5059e02
GH-83: Require all fields (can't require image)
wesleyboar 1a57226
GH-83: Support Optional Image/Link in CSS Docblock
wesleyboar a7134e2
GH-83: Quick: Update script comments & equality
wesleyboar 66eae8f
GH-321: Fix figure size and note about its resize
wesleyboar fa185d0
GH-83/GH-321: Show image on narrow windows
wesleyboar 75a6ece
GH-83: Fix: Ensure 0001 taccsite_callout migration
wesleyboar 1f2d736
Merge branch 'main' into task/GH-83-callout-element
wesleyboar 2b23df8
Merge branch 'main' into task/GH-83-callout-element
wesleyboar 93d7a0a
GH-83: Style Tweask to Match Design
wesleyboar a438972
Merge branch 'main' into task/GH-83-callout-element
wesleyboar 8e8a6c0
Add missing function to taccsite_cms/contrib/helpers.py
wesleyboar a6cca13
Merge branch 'main' into task/GH-83-callout-element
wesleyboar d471a67
GH-83: Add missing migration (help text uptdates)
wesleyboar 47347fa
GH-83: Shorten verbose logic. Drop comment.
wesleyboar 6e83ef8
Merge branch 'main' into task/GH-83-callout-element
wesleyboar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
78 changes: 78 additions & 0 deletions
78
taccsite_cms/contrib/_docs/how-to-extend-django-cms-plugin.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # How To Extend a `djangocms-___` Plugin | ||
|
|
||
| These example codes extend the [`djangocms-link` plugin](https://github.com/django-cms/djangocms-link/tree/3.0.0/djangocms_link). | ||
|
|
||
| `.../models.py`: | ||
|
|
||
| ```python | ||
| from djangocms_link.models import AbstractLink | ||
|
|
||
| from taccsite_cms.contrib.helpers import clean_for_abstract_link | ||
|
|
||
| class Taccsite______(AbstractLink): | ||
| """ | ||
| Components > "Article List" Model | ||
| https://confluence.tacc.utexas.edu/x/OIAjCQ | ||
| """ | ||
| # ... | ||
|
|
||
|
|
||
|
|
||
| # Parent | ||
|
|
||
| link_is_optional = True # or False | ||
|
|
||
| class Meta: | ||
| abstract = False | ||
|
|
||
| # Validate | ||
| def clean(self): | ||
| clean_for_abstract_link(__class__, self) | ||
| ``` | ||
|
|
||
| `.../cms_plugins.py`: | ||
|
|
||
| ```python | ||
| from djangocms_link.cms_plugins import LinkPlugin | ||
|
|
||
| from .models import ______Preview | ||
|
|
||
| class ______Plugin(LinkPlugin): | ||
| # ... | ||
| render_template = 'static_article_preview.html' | ||
| def get_render_template(self, context, instance, placeholder): | ||
| return self.render_template | ||
|
|
||
| fieldsets = [ | ||
| # ... | ||
| (_('Link'), { | ||
| 'fields': ( | ||
| # 'name', # to use LinkPlugin "Display name" | ||
| ('external_link', 'internal_link'), | ||
| ('anchor', 'target'), | ||
| ) | ||
| }), | ||
| ] | ||
|
|
||
| # Render | ||
| def render(self, context, instance, placeholder): | ||
| context = super().render(context, instance, placeholder) | ||
| request = context['request'] | ||
|
|
||
| context.update({ | ||
| 'link_url': instance.get_link(), | ||
| 'link_target': instance.target | ||
| # 'link_text': instance.name, # to use LinkPlugin "Display name" | ||
| }) | ||
| return context | ||
| ``` | ||
|
|
||
| `.../templates/______.py`: | ||
|
|
||
| ```handlebars | ||
|
|
||
| <a class="______" href="{{ link_url }}" | ||
| {% if link_target %}target="{{ link_target }}"{% endif %}> | ||
| <span>{{ link_text }} | ||
| </a> | ||
| ``` | ||
62 changes: 62 additions & 0 deletions
62
taccsite_cms/contrib/_docs/how-to-override-validation-error-from-parent-model.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # How To Override `ValidationError()` from Parent Model | ||
wesleyboar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Intercept Error(s): | ||
|
|
||
| ```python | ||
| from django.core.exceptions import ValidationError | ||
|
|
||
| from djangocms_Xxx.models import AbstractXxx | ||
|
|
||
| from taccsite_cms.contrib.helpers import ( | ||
| get_indices_that_start_with | ||
| ) | ||
|
|
||
| class OurModelThatUsesXxx(AbstractXxx): | ||
| # Validate | ||
| def clean(self): | ||
| # Bypass irrelevant parent validation | ||
| try: | ||
| super().clean() | ||
| except ValidationError as err: | ||
| # Intercept single-field errors | ||
| if hasattr(err, 'error_list'): | ||
| for i in range(len(err.error_list)): | ||
| # SEE: "Find Error(s)" | ||
| # ... | ||
| # Skip error | ||
| del err.error_list[i] | ||
| # Replace error | ||
| # SEE: https://docs.djangoproject.com/en/2.2/ref/forms/validation/#raising-validationerror | ||
|
|
||
| # Intercept multi-field errors | ||
| if hasattr(err, 'error_dict'): | ||
| for field, errors in err.message_dict.items(): | ||
| # SEE: "Find Error(s)" | ||
| # ... | ||
| # Skip error | ||
| del err.error_dict[field] | ||
| # Replace error | ||
| # SEE: https://docs.djangoproject.com/en/2.2/ref/forms/validation/#raising-validationerror | ||
|
|
||
| if err.messages: | ||
| raise err | ||
| ``` | ||
|
|
||
| Handle Error(s): | ||
|
|
||
| ```python | ||
| # SEE: "Find Error(s)" | ||
| # ... | ||
|
|
||
| # Catch known static error | ||
| if 'Known static error string' in error: | ||
| # ... | ||
|
|
||
| # Catch known dynamic error | ||
| indices_to_catch = get_indices_that_start_with( | ||
| 'Known dynamic error string that starts with same text', | ||
| errors | ||
| ) | ||
| for i in indices_to_catch: | ||
| # ... | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| from cms.plugin_base import CMSPluginBase | ||
| from cms.plugin_pool import plugin_pool | ||
| from django.utils.translation import gettext_lazy as _ | ||
|
|
||
| from djangocms_link.cms_plugins import LinkPlugin | ||
|
|
||
| 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): | ||
| """ | ||
| Components > "Callout" Plugin | ||
| https://confluence.tacc.utexas.edu/x/EiIFDg | ||
| """ | ||
| module = 'TACC Site' | ||
| model = TaccsiteCallout | ||
| name = _('Callout') | ||
| render_template = 'callout.html' | ||
| def get_render_template(self, context, instance, placeholder): | ||
| return self.render_template | ||
|
|
||
| cache = True | ||
| text_enabled = False | ||
| allow_children = True | ||
| # GH-91: Enable this limitation | ||
| # parent_classes = [ | ||
| # 'SectionPlugin' | ||
| # ] | ||
| child_classes = [ | ||
| 'PicturePlugin' | ||
| ] | ||
| max_children = 1 | ||
|
|
||
| fieldsets = [ | ||
| (None, { | ||
| 'fields': ( | ||
| 'title', 'description', | ||
| ), | ||
| }), | ||
| (_('Link'), { | ||
| 'fields': ( | ||
| ('external_link', 'internal_link'), | ||
| ('anchor', 'target'), | ||
| ) | ||
| }), | ||
| (_('Image'), { | ||
| 'classes': ('collapse',), | ||
| 'description': TEXT_FOR_NESTED_PLUGIN_CONTENT_SWAP.format( | ||
| element='an image', | ||
| plugin_name='Image' | ||
| ) + '\ | ||
| <br />\ | ||
| 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. <small>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.</small>', | ||
wesleyboar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 'fields': ( | ||
| 'resize_figure_to_fit', | ||
| 'attributes', | ||
| ) | ||
| }), | ||
| ] | ||
|
|
||
| # Render | ||
|
|
||
| def render(self, context, instance, placeholder): | ||
| context = super().render(context, instance, placeholder) | ||
| request = context['request'] | ||
| has_child_plugin = {} | ||
|
|
||
| # To identify child plugins | ||
| for plugin_instance in instance.child_plugin_instances: | ||
| if (type(plugin_instance).__name__ == 'Picture'): | ||
| has_child_plugin['image'] = True | ||
| context.update({ 'image_plugin': plugin_instance }) | ||
|
|
||
| classes = concat_classnames([ | ||
| 'c-callout', | ||
| 'c-callout--has-figure' if has_child_plugin.get('image') else '', | ||
| 'c-callout--is-link' if instance.get_link() else '', | ||
| instance.attributes.get('class'), | ||
| ]) | ||
| instance.attributes['class'] = classes | ||
|
|
||
| context.update({ | ||
| 'link_url': instance.get_link(), | ||
| 'link_target': instance.target | ||
| }) | ||
| return context | ||
43 changes: 43 additions & 0 deletions
43
taccsite_cms/contrib/taccsite_callout/migrations/0001_initial.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # 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 | ||
|
|
||
| dependencies = [ | ||
| ('filer', '0012_file_mime_type'), | ||
| ('cms', '0022_auto_20180620_1551'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.CreateModel( | ||
| name='TaccsiteCallout', | ||
| fields=[ | ||
| ('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 <em>not</em> 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, | ||
| }, | ||
| bases=('cms.cmsplugin',), | ||
| ), | ||
| ] |
28 changes: 28 additions & 0 deletions
28
taccsite_cms/contrib/taccsite_callout/migrations/0002_auto_20210928_1717.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Generated by Django 2.2.16 on 2021-09-28 22:17 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('taccsite_callout', '0001_initial'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterField( | ||
| model_name='taccsitecallout', | ||
| name='description', | ||
| field=models.CharField(help_text='A paragraph for the callout.', max_length=200, verbose_name='Description'), | ||
| ), | ||
| migrations.AlterField( | ||
| model_name='taccsitecallout', | ||
| name='resize_figure_to_fit', | ||
| field=models.BooleanField(default=False, help_text='Make image shorter or taller to match the height of text beside it (as it would be without the image).', verbose_name='Resize any image to fit'), | ||
| ), | ||
| migrations.AlterField( | ||
| model_name='taccsitecallout', | ||
| name='title', | ||
| field=models.CharField(help_text='A heading for the callout.', max_length=100, verbose_name='Title'), | ||
| ), | ||
| ] |
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.