class BootstrapAccordionPanelPlugin(TransparentMixin, BootstrapPluginBase): name = _("Accordion Panel") default_css_class = 'panel-body' parent_classes = ('BootstrapAccordionPlugin', ) require_parent = True alien_child_classes = True render_template = 'cascade/bootstrap3/{}/accordion-panel.html' panel_type = GlossaryField(PanelTypeRenderer.get_widget(), label=_("Panel type"), help_text=_("Display Panel using this style.")) heading_size = GlossaryField(widgets.Select(choices=panel_heading_sizes), initial='', label=_("Heading Size")) panel_title = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Panel Title")) class Media: css = { 'all': ( 'cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css', ) } @classmethod def get_identifier(cls, obj): identifier = super(BootstrapAccordionPanelPlugin, cls).get_identifier(obj) panel_title = HTMLParser().unescape(obj.glossary.get( 'panel_title', '')) panel_title = Truncator(panel_title).words(3, truncate=' ...') return format_html('{0}{1}', identifier, panel_title)
class BootstrapAccordionCardPlugin(TransparentContainer, BootstrapPluginBase): name = _("Accordion Card") default_css_class = 'card-body' direct_parent_classes = parent_classes = ('BootstrapAccordionPlugin',) require_parent = True alien_child_classes = True render_template = 'cascade/bootstrap4/{}/accordion-card.html' glossary_field_order = ['card_title', 'heading_size', 'card_type'] card_type = GlossaryField( CardTypeWidget.get_instance(), label=_("Card type"), help_text=_("Display Card using this style.") ) heading_size = GlossaryField( widgets.Select(choices=card_heading_sizes), initial='', label=_("Heading Size") ) card_title = GlossaryField( widgets.TextInput(attrs={'size': 80}), label=_("Card Title") ) class Media: css = {'all': ('cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css',)} @classmethod def get_identifier(cls, obj): identifier = super(BootstrapAccordionCardPlugin, cls).get_identifier(obj) card_title = HTMLParser().unescape(obj.glossary.get('card_title', '')) card_title = Truncator(card_title).words(3, truncate=' ...') return format_html('{0}{1}', identifier, card_title)
class HeadingPlugin(CascadePluginBase): name = _("Heading") parent_classes = None allow_children = False TAG_TYPES = tuple( ('h{}'.format(k), _("Heading {}").format(k)) for k in range(1, 7)) tag_type = GlossaryField(widgets.Select(choices=TAG_TYPES)) content = GlossaryField(widgets.TextInput( attrs={'style': 'width: 350px; font-weight: bold; font-size: 125%;'}), label=_("Heading content")) render_template = 'cascade/generic/heading.html' class Media: css = {'all': ('cascade/css/admin/partialfields.css', )} @classmethod def get_identifier(cls, instance): identifier = super(HeadingPlugin, cls).get_identifier(instance) tag_type = instance.glossary.get('tag_type') content = instance.glossary.get('content') if tag_type: return format_html('<code>{0}</code>: {1} {2}', tag_type, content, identifier) return content
class BootstrapCardPlugin(TransparentContainer, BootstrapPluginBase): """ Use this plugin to display a card with optional card-header and card-footer. """ name = _("Card") default_css_class = 'card' require_parent = False parent_classes = ['BootstrapColumnPlugin'] model_mixins = (BootstrapCardMixin, ) allow_children = True child_classes = None render_template = 'cascade/bootstrap4/card.html' glossary_field_order = ['header', 'body_padding', 'footer'] header = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Card Header")) body_padding = GlossaryField( widgets.CheckboxInput(), label=_("Body with padding"), initial=True, help_text=_("Add standard padding to card body.")) footer = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Card Footer")) @classmethod def get_identifier(cls, obj): identifier = super(BootstrapCardPlugin, cls).get_identifier(obj) return format_html('{0}{1}', identifier, obj.card_header or obj.card_footer)
class BootstrapAccordionGroupPlugin(TransparentContainer, BootstrapPluginBase): name = _("Accordion Group") direct_parent_classes = parent_classes = ['BootstrapAccordionPlugin'] render_template = 'cascade/generic/naked.html' model_mixins = (BootstrapAccordionGroupMixin, ) require_parent = True alien_child_classes = True glossary_field_order = ['heading', 'body_padding'] heading = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Heading")) body_padding = GlossaryField( widgets.CheckboxInput(), label=_("Body with padding"), initial=True, help_text=_("Add standard padding to card body."), ) @classmethod def get_identifier(cls, obj): identifier = super(BootstrapAccordionGroupPlugin, cls).get_identifier(obj) heading = HTMLParser().unescape(obj.glossary.get('heading', '')) heading = Truncator(heading).words(3, truncate=' ...') return format_html('{0}{1}', identifier, heading)
class BootstrapCardPlugin(TransparentContainer, BootstrapPluginBase): """ Use this plugin to display a panel with optional panel-header and panel-footer. """ name = _("Card") default_css_class = 'card' require_parent = False parent_classes = ('Bootstrap4ColumnPlugin', ) allow_children = True child_classes = None render_template = 'cascade/bootstrap4/card.html' glossary_field_order = ('card_type', 'heading_size', 'heading', 'footer') card_type = GlossaryField(CardTypeWidget.get_instance(), label=_("Card type"), help_text=_("Display Card using this style.")) heading_size = GlossaryField(widgets.Select(choices=card_heading_sizes), initial='', label=_("Heading Size")) heading = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Card Heading")) footer = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Card Footer")) html_parser = HTMLParser() class Media: css = {'all': ('cascade-bs4/css/admin/bootstrap.min.css', )} @classmethod def get_identifier(cls, obj): identifier = super(BootstrapCardPlugin, cls).get_identifier(obj) heading = cls.html_parser.unescape(obj.glossary.get('heading', '')) return format_html('{0}{1}', identifier, heading) def render(self, context, instance, placeholder): heading = self.html_parser.unescape( instance.glossary.get('heading', '')) footer = self.html_parser.unescape(instance.glossary.get('footer', '')) context.update({ 'instance': instance, 'card_type': instance.glossary.get('card_type', 'card-default'), 'card_heading': heading, 'heading_size': instance.glossary.get('heading_size', ''), 'card_footer': footer, 'placeholder': placeholder, }) return self.super(BootstrapCardPlugin, self).render(context, instance, placeholder)
class BootstrapPanelPlugin(TransparentContainer, BootstrapPluginBase): """ Use this plugin to display a panel with optional panel-header and panel-footer. """ name = _("Panel") default_css_class = 'panel' require_parent = False parent_classes = ('BootstrapColumnPlugin', ) allow_children = True child_classes = None render_template = 'cascade/bootstrap3/panel.html' glossary_field_order = ('panel_type', 'heading_size', 'heading', 'footer') panel_type = GlossaryField(PanelTypeRenderer.get_widget(), label=_("Panel type"), help_text=_("Display Panel using this style.")) heading_size = GlossaryField(widgets.Select(choices=panel_heading_sizes), initial='', label=_("Heading Size")) heading = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Panel Heading")) footer = GlossaryField(widgets.TextInput(attrs={'size': 80}), label=_("Panel Footer")) html_parser = HTMLParser() class Media: css = { 'all': ( 'cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css', ) } def render(self, context, instance, placeholder): heading = self.html_parser.unescape( instance.glossary.get('heading', '')) footer = self.html_parser.unescape(instance.glossary.get('footer', '')) context.update({ 'instance': instance, 'panel_type': instance.glossary.get('panel_type', 'panel-default'), 'panel_heading': heading, 'heading_size': instance.glossary.get('heading_size', ''), 'panel_footer': footer, 'placeholder': placeholder, }) return super(BootstrapPanelPlugin, self).render(context, instance, placeholder)
def get_form(self, request, obj=None, **kwargs): from cmsplugin_cascade.models import PluginExtraFields from .config import PluginExtraFieldsConfig glossary_fields = list(kwargs.pop('glossary_fields', self.glossary_fields)) clsname = self.__class__.__name__ try: site = get_current_site(request) extra_fields = PluginExtraFields.objects.get(plugin_type=clsname, site=site) except ObjectDoesNotExist: extra_fields = app_settings.CMSPLUGIN_CASCADE['plugins_with_extra_fields'].get(clsname) if isinstance(extra_fields, (PluginExtraFields, PluginExtraFieldsConfig)): # add a text input field to let the user name an ID tag for this HTML element if extra_fields.allow_id_tag: glossary_fields.append(GlossaryField( widgets.TextInput(), label=_("Named Element ID"), name='extra_element_id' )) # add a select box to let the user choose one or more CSS classes class_names = extra_fields.css_classes.get('class_names', '').replace(' ', '') if class_names: choices = [(clsname, clsname) for clsname in class_names.split(',')] if extra_fields.css_classes.get('multiple'): widget = widgets.CheckboxSelectMultiple(choices=choices) else: widget = widgets.Select(choices=((None, _("Select CSS")),) + tuple(choices)) glossary_fields.append(GlossaryField( widget, label=_("Customized CSS Classes"), name='extra_css_classes', help_text=_("Customized CSS classes to be added to this element.") )) # add input fields to let the user enter styling information for style, choices_tuples in app_settings.CMSPLUGIN_CASCADE['extra_inline_styles'].items(): inline_styles = extra_fields.inline_styles.get('extra_fields:{0}'.format(style)) if not inline_styles: continue Widget = choices_tuples[1] if issubclass(Widget, MultipleCascadingSizeWidget): key = 'extra_inline_styles:{0}'.format(style) allowed_units = extra_fields.inline_styles.get('extra_units:{0}'.format(style)).split(',') widget = Widget(inline_styles, allowed_units=allowed_units, required=False) glossary_fields.append(GlossaryField(widget, label=style, name=key)) else: for inline_style in inline_styles: key = 'extra_inline_styles:{0}'.format(inline_style) label = '{0}: {1}'.format(style, inline_style) glossary_fields.append(GlossaryField(Widget(), label=label, name=key)) kwargs.update(glossary_fields=glossary_fields) return super(ExtraFieldsMixin, self).get_form(request, obj, **kwargs)
class TextIconPlugin(IconPluginMixin, LinkPluginBase): name = _("Icon in text") text_enabled = True render_template = 'cascade/plugins/texticon.html' ring_plugin = 'IconPlugin' parent_classes = ('TextPlugin', ) model_mixins = ( TextIconModelMixin, LinkElementMixin, ) allow_children = False require_parent = False icon_font = GlossaryField( widgets.Select(), label=_("Font"), ) symbol = GlossaryField( widgets.HiddenInput(), label=_("Select Symbol"), ) glossary_field_order = ['icon_font', 'symbol'] class Media: js = ['cascade/js/admin/iconplugin.js'] @classmethod def requires_parent_plugin(cls, slot, page): return False def get_form(self, request, obj=None, **kwargs): LINK_TYPE_CHOICES = (('none', _("No Link")), ) + tuple( getattr(LinkForm, 'LINK_TYPE_CHOICES')) Form = type(str('TextIconForm'), (getattr(LinkForm, 'get_form_class')(), ), {'LINK_TYPE_CHOICES': LINK_TYPE_CHOICES}) kwargs.update(form=Form) return super(TextIconPlugin, self).get_form(request, obj, **kwargs) def get_plugin_urls(self): urls = [ url(r'^wysiwig-config.js$', self.render_wysiwig_config, name='cascade_texticon_wysiwig_config'), ] return urls def render_wysiwig_config(self, request): context = {'icon_fonts': IconFont.objects.all()} javascript = render_to_string('cascade/admin/ckeditor.wysiwyg.txt', context) return HttpResponse(javascript, content_type='application/javascript')
class BootstrapContainerPlugin(BootstrapPluginBase): name = _("Container") parent_classes = None require_parent = False form = BootstrapContainerForm glossary_variables = ['container_max_widths', 'media_queries'] glossary_field_order = ('breakpoints', 'fluid') breakpoints = GlossaryField( ContainerBreakpointsWidget(choices=get_widget_choices()), label=_('Available Breakpoints'), initial=list(BS3_BREAKPOINTS)[::-1], help_text=_("Supported display widths for Bootstrap's grid system.")) fluid = GlossaryField( widgets.CheckboxInput(), label=_('Fluid Container'), initial=False, help_text=_( "Changing your outermost '.container' to '.container-fluid'.")) @classmethod def get_identifier(cls, obj): if isinstance(obj.glossary, str): obj.glossary = json.loads(obj.glossary) identifier = super(BootstrapContainerPlugin, cls).get_identifier(obj) breakpoints = obj.glossary.get('breakpoints') content = obj.glossary.get('fluid') and '(fluid) ' or '' if breakpoints: devices = ', '.join( [force_text(BS3_BREAKPOINTS[bp][2]) for bp in breakpoints]) content = _("{0}for {1}").format(content, devices) return format_html('{0}{1}', identifier, content) @classmethod def get_css_classes(cls, obj): css_classes = cls.super(BootstrapContainerPlugin, cls).get_css_classes(obj) if obj.glossary.get('fluid'): css_classes.append('container-fluid') else: css_classes.append('container') return css_classes def save_model(self, request, obj, form, change): super(BootstrapContainerPlugin, self).save_model(request, obj, form, change) obj.sanitize_children() @classmethod def sanitize_model(cls, obj): sanitized = super(BootstrapContainerPlugin, cls).sanitize_model(obj) compute_media_queries(obj) return sanitized
class BootstrapContainerPlugin(BootstrapPluginBase): name = _("Container") parent_classes = None require_parent = False form = BootstrapContainerForm glossary_variables = ['container_max_widths', 'media_queries'] glossary_field_order = ['breakpoints', 'fluid'] model_mixins = (ContainerGridMixin, ) breakpoints = GlossaryField( ContainerBreakpointsWidget(choices=get_widget_choices()), label=_('Available Breakpoints'), initial=[ bp.name for bp in app_settings.CMSPLUGIN_CASCADE['bootstrap4'] ['fluid_bounds'].keys() ], help_text=_("Supported display widths for Bootstrap's grid system."), ) fluid = GlossaryField( widgets.CheckboxInput(), label=_('Fluid Container'), initial=False, help_text=_( "Changing your outermost '.container' to '.container-fluid'.")) @classmethod def get_identifier(cls, obj): identifier = super(BootstrapContainerPlugin, cls).get_identifier(obj) breakpoints = obj.glossary.get('breakpoints') content = obj.glossary.get('fluid') and '(fluid) ' or '' if breakpoints: breakpoints = app_settings.CMSPLUGIN_CASCADE['bootstrap4'][ 'fluid_bounds'] devices = ', '.join([force_text(bp.label) for bp in breakpoints]) content = _("{0}for {1}").format(content, devices) return format_html('{0}{1}', identifier, content) @classmethod def get_css_classes(cls, obj): css_classes = cls.super(BootstrapContainerPlugin, cls).get_css_classes(obj) if obj.glossary.get('fluid'): css_classes.append('container-fluid') else: css_classes.append('container') return css_classes def save_model(self, request, obj, form, change): super(BootstrapContainerPlugin, self).save_model(request, obj, form, change) obj.sanitize_children()
class TextIconPlugin(IconPluginMixin, LinkPluginBase): """ This plugin is intended to be used inside the django-CMS-CKEditor. """ name = _("Icon in text") text_enabled = True render_template = 'cascade/plugins/texticon.html' ring_plugin = 'IconPlugin' parent_classes = ['TextPlugin'] model_mixins = (TextIconModelMixin, LinkElementMixin,) allow_children = False require_parent = False icon_font = GlossaryField( widgets.Select(), label=_("Font"), initial=get_default_icon_font, ) symbol = GlossaryField( widgets.HiddenInput(), label=_("Select Symbol"), ) color = GlossaryField( ColorPickerWidget(), label=_("Icon color"), ) glossary_field_order = ['icon_font', 'symbol', 'color'] class Media: js = ['cascade/js/admin/iconplugin.js'] @classmethod def requires_parent_plugin(cls, slot, page): return False def get_form(self, request, obj=None, **kwargs): kwargs.update(form=VoluntaryLinkForm.get_form_class()) return super(TextIconPlugin, self).get_form(request, obj, **kwargs) @classmethod def get_inline_styles(cls, instance): inline_styles = cls.super(TextIconPlugin, cls).get_inline_styles(instance) color = instance.glossary.get('color') if isinstance(color, list) and len(color) == 2 and not color[0]: inline_styles['color'] = color[1] return inline_styles
class ShopCatalogPlugin(ShopPluginBase): name = _("Catalog List View") require_parent = True parent_classes = ('BootstrapColumnPlugin', 'SimpleWrapperPlugin',) cache = False pagination = GlossaryField( widgets.RadioSelect(choices=[ ('paginator', _("Use Paginator")), ('manual', _("Manual Infinite")), ('auto', _("Auto Infinite")) ]), label=_("Pagination"), initial=True, help_text=_("Shall the product list view use a paginator or scroll infinitely?"), ) def get_render_template(self, context, instance, placeholder): templates = [] if instance.glossary.get('render_template'): templates.append(instance.glossary['render_template']) templates.extend([ '{}/catalog/list.html'.format(app_settings.APP_LABEL), 'shop/catalog/list.html', ]) return select_template(templates) def render(self, context, instance, placeholder): context['pagination'] = instance.glossary.get('pagination', 'paginator') return context @classmethod def get_identifier(cls, obj): pagination = obj.glossary.get('pagination') if pagination == 'paginator': return ugettext("Manual Pagination") return ugettext("Infinite Scroll")
def margins(cls): glossary_fields = [] choices_format = [ ('m-{}{}', _("4 sided margins ({})")), ('mx-{}{}', _("Horizontal margins ({})")), ('my-{}{}', _("Vertical margins ({})")), ('mt-{}{}', _("Top margin ({})")), ('mr-{}{}', _("Right margin ({})")), ('mb-{}{}', _("Bottom margin ({})")), ('ml-{}{}', _("Left margin ({})")), ] sizes = list(range(0, 6)) + ['auto'] for bp in Breakpoint.range(Breakpoint.xs, Breakpoint.xl): if bp == Breakpoint.xs: choices = [(c.format('', s), format_lazy(l, s)) for c, l in choices_format for s in sizes] choices.insert(0, ('', _("No Margins"))) else: choices = [(c.format(bp.name + '-', s), format_lazy(l, s)) for c, l in choices_format for s in sizes] choices.insert(0, ('', _("Inherit from above"))) glossary_fields.append(GlossaryField( widgets.Select(choices=choices), label=format_lazy(_("Margins for {breakpoint}"), breakpoint=bp.label), name='margins_{}'.format(bp.name), initial='' )) return glossary_fields
def paddings(cls): glossary_fields = [] choices_format = [ ('p-{}{}', _("4 sided padding ({})")), ('px-{}{}', _("Horizontal padding ({})")), ('py-{}{}', _("Vertical padding ({})")), ('pt-{}{}', _("Top padding ({})")), ('pr-{}{}', _("Right padding ({})")), ('pb-{}{}', _("Bottom padding ({})")), ('pl-{}{}', _("Left padding ({})")), ] sizes = range(0, 6) for bp in Breakpoint.range(Breakpoint.xs, Breakpoint.xl): if bp == Breakpoint.xs: choices = [(c.format('', s), format_lazy(l, s)) for c, l in choices_format for s in sizes] choices.insert(0, ('', _("No Padding"))) else: choices = [(c.format(bp.name + '-', s), format_lazy(l, s)) for c, l in choices_format for s in sizes] choices.insert(0, ('', _("Inherit from above"))) glossary_fields.append(GlossaryField( widgets.Select(choices=choices), label=format_lazy(_("Padding for {breakpoint}"), breakpoint=bp.label), name='padding_{}'.format(bp.name), initial='' )) return glossary_fields
class BootstrapTabSetPlugin(TransparentWrapper, BootstrapPluginBase): name = _("Tab Set") form = TabForm parent_classes = ('BootstrapColumnPlugin', ) direct_child_classes = ('BootstrapTabPanePlugin', ) require_parent = True allow_children = True render_template = 'cascade/bootstrap3/{}/tabset.html' justified = GlossaryField(widgets.CheckboxInput(), label=_("Justified tabs")) @classmethod def get_identifier(cls, instance): identifier = super(BootstrapTabSetPlugin, cls).get_identifier(instance) num_cols = instance.get_children().count() content = ungettext_lazy('with {} tab', 'with {} tabs', num_cols).format(num_cols) return format_html('{0}{1}', identifier, content) def save_model(self, request, obj, form, change): wanted_children = int(form.cleaned_data.get('num_children')) super(BootstrapTabSetPlugin, self).save_model(request, obj, form, change) self.extend_children(obj, wanted_children, BootstrapTabPanePlugin)
class ShippingMethodFormPlugin(DialogFormPluginBase): name = _("Shipping Method Form") form_class = 'shop.forms.checkout.ShippingMethodForm' template_leaf_name = 'shipping-method-{}.html' show_additional_charge = GlossaryField( widgets.CheckboxInput(), label=_("Show additional charge"), initial=True, help_text= _("Add an extra line showing the additional charge depending on the chosen shipping method." ), ) def get_form_data(self, context, instance, placeholder): form_data = self.super(ShippingMethodFormPlugin, self).get_form_data(context, instance, placeholder) cart = form_data.get('cart') if cart: form_data.update( initial={ 'shipping_modifier': cart.extra.get('shipping_modifier') }) return form_data def render(self, context, instance, placeholder): self.super(ShippingMethodFormPlugin, self).render(context, instance, placeholder) for shipping_modifier in cart_modifiers_pool.get_shipping_modifiers(): shipping_modifier.update_render_context(context) context['show_additional_charge'] = instance.glossary.get( 'show_additional_charge', False) return context
class ProcessNextStepPlugin(BootstrapButtonMixin, ShopPluginBase): name = _("Next Step Button") parent_classes = ('ProcessStepPlugin',) form = ProcessNextStepForm fields = ['link_content', 'glossary'] ring_plugin = 'ProcessNextStepPlugin' glossary_field_order = ['disable_invalid', 'button_type', 'button_size', 'button_options', 'quick_float', 'icon_align', 'icon_font', 'symbol'] disable_invalid = GlossaryField( label=_("Disable if invalid"), widget=widgets.CheckboxInput(), initial='', help_text=_("Disable button if any form in this set is invalid"), ) class Media: css = {'all': ['cascade/css/admin/bootstrap4-buttons.css', 'cascade/css/admin/iconplugin.css']} js = ['shop/js/admin/nextstepplugin.js'] @classmethod def get_identifier(cls, obj): identifier = super(ProcessNextStepPlugin, cls).get_identifier(obj) content = obj.glossary.get('link_content', '') return format_html('{0}{1}', identifier, content) def get_render_template(self, context, instance, placeholder): template_names = [ '{}/checkout/process-next-step.html'.format(app_settings.APP_LABEL), 'shop/checkout/process-next-step.html', ] return select_template(template_names)
class BreadcrumbPlugin(ShopPluginBase): name = _("Breadcrumb") CHOICES = (('default', _("Default Breadcrumb")), ('soft-root', _("“Soft-Root” Breadcrumb")), ('catalog', _("With Catalog Count")), ('empty', _("Hidden Breadcrumb")),) parent_classes = () allow_children = None render_type = GlossaryField( widgets.RadioSelect(choices=CHOICES), label=_("Render as"), initial='default', help_text=_("Render an alternative Breadcrumb"), ) @classmethod def get_identifier(cls, instance): render_type = instance.glossary.get('render_type') return mark_safe(dict(cls.CHOICES).get(render_type, '')) def get_render_template(self, context, instance, placeholder): render_type = instance.glossary.get('render_type') try: return select_template([ '{}/breadcrumb/{}.html'.format(app_settings.APP_LABEL, render_type), 'shop/breadcrumb/{}.html'.format(render_type), ]) except TemplateDoesNotExist: return engines['django'].from_string('<!-- empty breadcrumb -->') def get_use_cache(self, context, instance, placeholder): try: app = apphook_pool.get_apphook(instance.page.application_urls) return app.cache_placeholders except (AttributeError, ImproperlyConfigured): return super(BreadcrumbPlugin, self).get_use_cache(context, instance, placeholder)
class CheckoutAddressPluginBase(DialogFormPluginBase): multi_addr = GlossaryField( widgets.CheckboxInput(), label=_("Multiple Addresses"), initial=False, help_text=_( "Shall the customer be allowed to edit multiple addresses."), ) def get_form_data(self, context, instance, placeholder): form_data = super(CheckoutAddressPluginBase, self).get_form_data(context, instance, placeholder) AddressModel = self.FormClass.get_model() assert form_data[ 'cart'] is not None, "Can not proceed to checkout without cart" address = self.get_address(form_data['cart']) form_data.update(instance=address) if instance.glossary.get('multi_addr'): addresses = AddressModel.objects.filter( customer=context['request'].customer).order_by('priority') form_entities = [ dict(value=str(addr.priority), label="{}. {}".format(number, addr.as_text().replace('\n', ' – '))) for number, addr in enumerate(addresses, 1) ] form_data.update(multi_addr=True, form_entities=form_entities) else: form_data.update(multi_addr=False) return form_data
class SimpleWrapperPlugin(TransparentContainer, CascadePluginBase): name = _("Simple Wrapper") parent_classes = None require_parent = False allow_children = True alien_child_classes = True TAG_CHOICES = tuple((cls, _("<{}> – Element").format(cls)) for cls in ( 'div', 'span', 'section', 'article', )) + (('naked', _("Naked Wrapper")), ) tag_type = GlossaryField( widgets.Select(choices=TAG_CHOICES), label=_("HTML element tag"), help_text=_('Choose a tag type for this HTML element.')) @classmethod def get_identifier(cls, instance): identifier = super(SimpleWrapperPlugin, cls).get_identifier(instance) tag_name = dict(cls.TAG_CHOICES).get(instance.glossary.get('tag_type')) if tag_name: return format_html('{0} {1}', tag_name, identifier) return identifier def get_render_template(self, context, instance, placeholder): if instance.glossary.get('tag_type') == 'naked': return 'cascade/generic/naked.html' return 'cascade/generic/wrapper.html'
class ShopOrderAddendumFormPlugin(OrderButtonBase): name = _("Order Addendum Form") show_history = GlossaryField(widgets.CheckboxInput(), label=_("Show History"), initial=True, help_text=_("Show historical annotations.")) def get_render_template(self, context, instance, placeholder): template_names = [ '{}/order/addendum-form.html'.format(app_settings.APP_LABEL), 'shop/order/addendum-form.html', ] return select_template(template_names) def render(self, context, instance, placeholder): context = super(ShopOrderAddendumFormPlugin, self).render(context, instance, placeholder) context.update({ 'addendum_form': AddendumForm(), 'show_history': instance.glossary.get('show_history', True), }) return context
class PaymentMethodFormPlugin(DialogFormPluginBase): name = _("Payment Method Form") form_class = app_settings.SHOP_CASCADE_FORMS['PaymentMethodForm'] template_leaf_name = 'payment-method-{}.html' show_additional_charge = GlossaryField( widgets.CheckboxInput(), label=_("Show additional charge"), initial=True, help_text= _("Add an extra line showing the additional charge depending on the chosen payment method." ), ) def get_form_data(self, context, instance, placeholder): form_data = self.super(PaymentMethodFormPlugin, self).get_form_data(context, instance, placeholder) cart = form_data.get('cart') if cart: form_data.update( initial={ 'payment_modifier': cart.extra.get('payment_modifier') }) return form_data def render(self, context, instance, placeholder): self.super(PaymentMethodFormPlugin, self).render(context, instance, placeholder) for payment_modifier in cart_modifiers_pool.get_payment_modifiers(): payment_modifier.update_render_context(context) context['show_additional_charge'] = instance.glossary.get( 'show_additional_charge', False) return context
def get_form(self, request, obj=None, **kwargs): if obj: caption = self.html_parser.unescape(obj.glossary.get( 'caption', '')) obj.glossary.update(caption=caption) parent_obj = self.get_parent_instance(request) if not (parent_obj and issubclass(parent_obj.plugin_class, BootstrapPluginBase)): raise ImproperlyConfigured( "A CarouselSlidePlugin requires a valid parent") # define glossary fields on the fly, because the TextEditorWidget requires the plugin_pk text_editor_widget = TextEditorWidget( installed_plugins=[TextLinkPlugin], pk=parent_obj.pk, placeholder=parent_obj.placeholder, plugin_language=parent_obj.language) caption = GlossaryField( text_editor_widget, label=_("Slide Caption"), name='caption', help_text=_("Caption text to be laid over the backgroud image.")) kwargs['glossary_fields'] = (caption, ) return super(CarouselSlidePlugin, self).get_form(request, obj, **kwargs)
class ShopAddToCartPlugin(ShopPluginBase): name = _("Add Product to Cart") require_parent = True parent_classes = ('BootstrapColumnPlugin',) cache = False use_modal_dialog = GlossaryField( widgets.CheckboxInput(), label=_("Use Modal Dialog"), initial='on', help_text=_("After adding product to cart, render a modal dialog"), ) def get_render_template(self, context, instance, placeholder): templates = [] if instance.glossary.get('render_template'): templates.append(instance.glossary['render_template']) templates.extend([ '{}/catalog/product-add2cart.html'.format(app_settings.APP_LABEL), 'shop/catalog/product-add2cart.html', ]) return select_template(templates) def render(self, context, instance, placeholder): context = super(ShopAddToCartPlugin, self).render(context, instance, placeholder) context['use_modal_dialog'] = bool(instance.glossary.get('use_modal_dialog', True)) return context
class ShopCatalogPlugin(ShopPluginBase): name = _("Catalog List View") require_parent = True parent_classes = ( 'BootstrapColumnPlugin', 'SimpleWrapperPlugin', ) cache = False infinite_scroll = GlossaryField( widgets.CheckboxInput(), label=_("Infinite Scroll"), initial=True, help_text=_("Shall the product list view scroll infinitely?"), ) def get_render_template(self, context, instance, placeholder): return select_template([ '{}/catalog/product-list.html'.format(app_settings.APP_LABEL), 'shop/catalog/product-list.html', ]) def render(self, context, instance, placeholder): context['infinite_scroll'] = bool( instance.glossary.get('infinite_scroll', True)) return context @classmethod def get_identifier(cls, obj): if obj.glossary.get('infinite_scroll', True): return ugettext("Infinite Scroll") return ugettext("Manual Pagination")
class ImageAnnotationMixin(CascadePluginMixinBase): """ This mixin class prepends the glossary fields 'image_title' and 'alt_tag' in front of the glossary fields provided by the class LinkPluginBase. """ image_title = GlossaryField( widgets.TextInput(), label=_('Image Title'), help_text=_("Caption text added to the 'title' attribute of the <img> element."), ) alt_tag = GlossaryField( widgets.TextInput(), label=_('Alternative Description'), help_text=_("Textual description of the image added to the 'alt' tag of the <img> element."), )
def get_form(self, request, obj=None, **kwargs): glossary_fields = list(kwargs.pop('glossary_fields', self.glossary_fields)) glossary_fields.append(GlossaryField( widgets.Select(choices=self.get_template_choices()), label=_("Render template"), name='render_template', help_text=_("Use alternative template for rendering this plugin.") )) kwargs.update(glossary_fields=glossary_fields) return super(RenderTemplateMixin, self).get_form(request, obj, **kwargs)
def get_form(self, request, obj=None, **kwargs): glossary_fields = list(kwargs.pop('glossary_fields', self.glossary_fields)) glossary_fields.append(GlossaryField( widgets.TextInput(), label=_("Element ID"), name='element_id', help_text=_("A unique identifier for this element.") )) kwargs.update(form=SectionForm, glossary_fields=glossary_fields) return super(SectionMixin, self).get_form(request, obj, **kwargs)
def get_form(self, request, obj=None, **kwargs): glossary_fields = list( kwargs.pop('glossary_fields', self.glossary_fields)) glossary_fields.append( GlossaryField( widgets.CheckboxInput(), label=_("Hide plugin"), name='hide_plugin', help_text=_("Hide this plugin and all of it's children."))) kwargs.update(glossary_fields=glossary_fields) return super(HidePluginMixin, self).get_form(request, obj, **kwargs)