Esempio n. 1
0
class Carousel(ShuupModel):
    shops = models.ManyToManyField(
        "shuup.Shop",
        related_name="carousels",
        verbose_name=_('shops'),
        help_text=_(
            "Select which shops you would like the carousel to be visible in.")
    )
    name = models.CharField(
        max_length=50,
        verbose_name=_("name"),
        help_text=_("The carousel name use for carousel configuration."))
    animation = EnumIntegerField(
        CarouselMode,
        default=CarouselMode.SLIDE,
        verbose_name=_("animation"),
        help_text=_("Animation type for cycling slides."))
    interval = models.IntegerField(default=5,
                                   verbose_name=_("interval"),
                                   help_text=_("Slide interval in seconds."))
    pause_on_hover = models.BooleanField(
        default=True,
        verbose_name=_("pause on hover"),
        help_text=_(
            "When checked, the carousel cycling pauses on mouse over."))
    is_arrows_visible = models.BooleanField(
        default=True,
        verbose_name=_("show navigation arrows"),
        help_text=
        _("When checked, navigational arrows are shown on the carousel allowing for customers to go back and forward."
          ))
    use_dot_navigation = models.BooleanField(
        default=True,
        verbose_name=_("show navigation dots"),
        help_text=_("When checked, navigational indicator dots are shown."))
    image_width = models.IntegerField(
        default=1200,
        verbose_name=_("image width"),
        help_text=_("Slide images will be cropped to this width."))
    image_height = models.IntegerField(
        default=600,
        verbose_name=_("image height"),
        help_text=_("Slide images will be cropped to this height."))
    arrows_color = HexColorField(
        verbose_name=_("Arrows color"),
        blank=True,
        null=True,
        help_text=_("Set the custom color for the arrows."),
    )

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _("Carousel")
        verbose_name_plural = _("Carousels")

    @property
    def animation_class_name(self):
        return "fade" if self.animation == CarouselMode.FADE else "slide"
Esempio n. 2
0
class Slide(TranslatableShuupModel):
    carousel = models.ForeignKey(Carousel,
                                 related_name="slides",
                                 on_delete=models.CASCADE)
    name = models.CharField(
        max_length=50,
        blank=True,
        null=True,
        verbose_name=_("name"),
        help_text=_("Name is only used to configure slides."))
    product_link = models.ForeignKey(
        Product,
        related_name="+",
        blank=True,
        null=True,
        verbose_name=_("product link"),
        help_text=
        _("Set the product detail page that should be shown when this slide is clicked, if any."
          ),
        on_delete=models.CASCADE)
    category_link = models.ForeignKey(
        Category,
        related_name="+",
        blank=True,
        null=True,
        verbose_name=_("category link"),
        help_text=
        _("Set the product category page that should be shown when this slide is clicked, if any."
          ),
        on_delete=models.CASCADE)
    cms_page_link = models.ForeignKey(
        Page,
        related_name="+",
        verbose_name=_("cms page link"),
        blank=True,
        null=True,
        help_text=
        _("Set the web page that should be shown when the slide is clicked, if any."
          ),
        on_delete=models.CASCADE)
    ordering = models.IntegerField(
        default=0,
        blank=True,
        null=True,
        verbose_name=_("ordering"),
        help_text=
        _("Set the numeric order in which this slide should appear relative to other slides in this carousel."
          ))
    target = EnumIntegerField(
        LinkTargetType,
        default=LinkTargetType.CURRENT,
        verbose_name=_("link target"),
        help_text=
        _("Set this to current if clicking on this slide should open a new browser tab."
          ))
    available_from = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name=_('available since'),
        help_text=
        _("Set the date and time, starting from which this slide should be visible in the carousel. "
          "This is useful to advertise sales campaigns or other time-sensitive marketing."
          ))
    available_to = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name=_('available until'),
        help_text=
        _("Set the date and time, until which this slide should be visible in the carousel. "
          "This is useful to advertise sales campaigns or other time-sensitive marketing."
          ))
    inactive_dot_color = HexColorField(
        verbose_name=_("Inactive dot border color"),
        blank=True,
        null=True,
        help_text=_(
            "Customize the dot border color when slide is not active."),
    )
    active_dot_color = HexColorField(
        verbose_name=_("Active dot color"),
        blank=True,
        null=True,
        help_text=_("Customize the dot color when slide is active."),
    )

    translations = TranslatedFields(
        caption=models.CharField(
            max_length=80,
            blank=True,
            null=True,
            verbose_name=_("caption"),
            help_text=
            _("Text that describes the image. It is displayed on top of the image if 'Render "
              "image text' box is enabled in front-end. Also used for search engine purposes."
              )),
        caption_text=models.TextField(
            blank=True,
            null=True,
            verbose_name=_("caption text"),
            help_text=
            _("Caption text is displayed as secondary text on top of the image if "
              "'Render image text' box is enabled in front-end for 'Carousel plugin' type "
              "(disabled for 'Banner box' type). It is also shown as a tooltip."
              ),
        ),
        external_link=models.CharField(
            max_length=800,
            blank=True,
            null=True,
            verbose_name=_("external link"),
            help_text=
            _("Set the external site that should be shown when this slide is clicked, if any."
              )),
        image=FilerImageField(blank=True,
                              null=True,
                              related_name="+",
                              verbose_name=_("image"),
                              on_delete=models.PROTECT,
                              help_text=_("The slide image to show.")))

    def __str__(self):
        return "%s %s" % (_("Slide"), self.pk)

    class Meta:
        verbose_name = _("Slide")
        verbose_name_plural = _("Slides")
        ordering = ("ordering", "id")

    def get_translated_field(self, attr):
        if not self.safe_translation_getter(attr):
            return self.safe_translation_getter(
                attr, language_code=settings.PARLER_DEFAULT_LANGUAGE_CODE)
        return getattr(self, attr)

    def get_link_url(self):
        """
        Get right link url for this slide.

        Initially external link is used. If not set link will fallback to
        product_link, external_link or cms_page_link in this order.

        :return: return correct link url for slide if set
        :rtype: str|None
        """
        external_link = self.get_translated_field("external_link")
        if external_link:
            return external_link
        elif self.product_link:
            return reverse("shuup:product",
                           kwargs=dict(pk=self.product_link.pk,
                                       slug=self.product_link.slug))
        elif self.category_link:
            return reverse("shuup:category",
                           kwargs=dict(pk=self.category_link.pk,
                                       slug=self.category_link.slug))
        elif self.cms_page_link:
            return reverse("shuup:cms_page",
                           kwargs=dict(url=self.cms_page_link.url))

    def is_visible(self, dt=None):
        """
        Get slides that should be publicly visible.

        This does not do permission checking.

        :param dt: Datetime for visibility check
        :type dt: datetime.datetime
        :return: Public visibility status
        :rtype: bool
        """
        if not dt:
            dt = now()

        return ((self.available_from and self.available_from <= dt)
                and (self.available_to is None or self.available_to >= dt))

    def get_link_target(self):
        """
        Return link target type string based on selection

        :return: Target type string
        :rtype: str
        """
        if self.target == LinkTargetType.NEW:
            return "_blank"
        else:
            return "_self"

    @property
    def easy_thumbnails_thumbnailer(self):
        """
        Get Thumbnailer instance for the translated image.
        Will return None if file cannot be thumbnailed.
        :rtype:easy_thumbnails.files.Thumbnailer|None
        """
        image = self.get_translated_field("image")

        if not image:
            return

        try:
            return get_thumbnailer(image)
        except ValueError:
            return get_thumbnailer(image.filer_image_file)
        except Exception:
            return None

    def get_thumbnail(self, **kwargs):
        """
        Get thumbnail for the translated image
        This will return None if there is no file
        :rtype: easy_thumbnails.files.ThumbnailFile|None
        """
        kwargs.setdefault(
            "size", (self.carousel.image_width, self.carousel.image_height))
        kwargs.setdefault("crop", True)  # sane defaults
        kwargs.setdefault("upscale", True)  # sane defaults

        if kwargs["size"] == (0, 0):
            return None

        thumbnailer = self.easy_thumbnails_thumbnailer

        if not thumbnailer:
            return None

        return thumbnailer.get_thumbnail(thumbnail_options=kwargs)

    objects = SlideQuerySet.as_manager()