Esempio n. 1
0
class ProductsFromCategoryPlugin(TemplatedPlugin):
    identifier = "async_category_products"
    name = _("Category Products Highlight (asynchronous)")
    template_name = "shuup/xtheme/plugins/highlight_plugin_async.jinja"
    editor_form_class = ProductsFromCategoryForm
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1, initial=5)),
        ("cache_timeout", forms.IntegerField(label=_("Cache timeout (seconds)"), min_value=0, initial=120)),
    ]

    def get_context_data(self, context):
        request = context["request"]
        products = []
        category_id = self.config.get("category")
        count = self.config.get("count", 5)
        cache_timeout = self.config.get("cache_timeout", 0)
        orderable_only = False

        if request.is_ajax() and category_id:
            products = get_products_for_categories(
                context, [category_id], n_products=count, orderable_only=orderable_only
            )

        return {
            "request": request,
            "title": self.get_translated_value("title"),
            "products": products,
            "data_url": reverse(
                "shuup:xtheme-category-products-highlight",
                kwargs=dict(category_id=category_id, count=count, cache_timeout=cache_timeout),
            ),
        }
Esempio n. 2
0
class BannerBoxPlugin(CarouselPlugin):
    identifier = "shuup.front.apps.carousel.banner_box"
    name = _("Banner Box")
    editor_form_class = CarouselConfigForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        (
            "render_image_text",
            forms.BooleanField(
                label=_("Render image text"),
                required=False,
                initial=True,
                help_text=_("Display the text on top of the image."),
            ),
        ),
    ]

    def get_context_data(self, context):
        """
        Add title from config to context data

        :param context: Current context
        :return: updated Plugin context
        :rtype: dict
        """
        data = super(BannerBoxPlugin, self).get_context_data(context)
        data["title"] = self.get_translated_value("title")
        data["type"] = "banner_box"
        return data
Esempio n. 3
0
class VendorReviewCommentsPlugin(TemplatedPlugin):
    identifier = "shuup_vendor_reviews.supplier_comments"
    name = _("Vendor Review Comments")
    template_name = "shuup_vendor_reviews/plugins/vendor_reviews_comments.jinja"
    required_context_variables = ["supplier"]

    fields = [("title",
               TranslatableField(label=_("Title"),
                                 required=False,
                                 initial=_("Reviews")))]

    def get_context_data(self, context):
        context = dict(context)
        supplier = context["supplier"]

        if supplier and supplier.enabled:
            reviews = VendorReview.objects.approved().filter(
                shop=context["request"].shop,
                supplier=supplier,
                comment__isnull=False)
            if reviews.exists():
                context["review_supplier"] = supplier
                context["title"] = self.get_translated_value("title")

        return context
Esempio n. 4
0
class ProductSelectionPlugin(TemplatedPlugin):
    """
    A plugin that renders a selection of products
    """

    identifier = "async_product_selection"
    name = _("Product Selection (asynchronous)")
    template_name = "shuup/xtheme/plugins/highlight_plugin_async.jinja"
    editor_form_class = ProductSelectionConfigForm
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="")),
        ("cache_timeout", forms.IntegerField(label=_("Cache timeout (seconds)"), min_value=0, initial=120)),
    ]

    def get_context_data(self, context):
        request = context["request"]
        products = self.config.get("products", [])
        cache_timeout = self.config.get("cache_timeout", 0)
        products_qs = Product.objects.none()

        if request.is_ajax() and products:
            products_qs = Product.objects.listed(shop=request.shop, customer=request.customer).filter(pk__in=products)

        return {
            "request": request,
            "title": self.get_translated_value("title"),
            "products": products_qs,
            "data_url": reverse(
                "shuup:xtheme-product-selections-highlight",
                kwargs=dict(
                    product_ids=",".join([(str(prod.pk) if hasattr(prod, "pk") else str(prod)) for prod in products]),
                    cache_timeout=cache_timeout,
                ),
            ),
        }
Esempio n. 5
0
class ProductSelectionPlugin(TemplatedPlugin):
    """
    A plugin that renders a selection of products
    """
    identifier = "product_selection"
    name = _("Product Selection")
    template_name = "shuup/xtheme/plugins/product_selection_plugin.jinja"
    editor_form_class = ProductSelectionConfigForm
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial=""))
    ]

    def get_context_data(self, context):
        request = context["request"]
        products = self.config.get("products")
        products_qs = Product.objects.none()

        if products:
            products_qs = Product.objects.listed(
                shop=request.shop,
                customer=request.customer
            ).filter(shop_products__pk__in=products)

        return {
            "request": request,
            "title": self.get_translated_value("title"),
            "products": products_qs
        }
Esempio n. 6
0
class ProductHighlightPlugin(TemplatedPlugin):
    identifier = "product_highlight"
    name = _("Product Highlights")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="")),
        ("type", forms.ChoiceField(label=_("Type"), choices=[
            ("newest", "Newest"),
            ("best_selling", "Best Selling"),
            ("random", "Random"),
        ], initial="newest")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1, initial=4)),
        ("orderable_only", forms.BooleanField(label=_("Only show in-stock and orderable items"),
                                              initial=True,
                                              required=False))
    ]

    def get_context_data(self, context):
        type = self.config.get("type", "newest")
        count = self.config.get("count", 4)
        orderable_only = self.config.get("orderable_only", True)
        if type == "newest":
            products = get_newest_products(context, count, orderable_only)
        elif type == "best_selling":
            products = get_best_selling_products(context, count, orderable_only=orderable_only)
        elif type == "random":
            products = get_random_products(context, count, orderable_only)
        else:
            products = []

        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 7
0
class BannerBoxPlugin(CarouselPlugin):
    identifier = "shuup_carousel.banner_box"
    name = _("Banner Box")
    template_name = "shuup_carousel/banner_box.jinja"
    editor_form_class = BannerBoxConfigForm

    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
    ]

    def render(self, context):
        """
        Custom render for to add js resource for banner box

        :param context: current context
        :return: html content for the plugin
        """
        add_resource(context, "body_end",
                     "%sshuup_carousel/js/script.js" % settings.STATIC_URL)
        return super(BannerBoxPlugin, self).render(context)

    def get_context_data(self, context):
        """
        Add title from config to context data

        :param context: Current context
        :return: updated Plugin context
        :rtype: dict
        """
        data = super(BannerBoxPlugin, self).get_context_data(context)
        data["title"] = self.get_translated_value("title")
        return data
Esempio n. 8
0
class ProductReviewCommentsPlugin(TemplatedPlugin):
    identifier = "shuup_product_reviews.review_comments"
    name = _("Product Review Comments")
    template_name = "shuup_product_reviews/plugins/reviews_comments.jinja"
    required_context_variables = ["shop_product"]

    fields = [("title",
               TranslatableField(label=_("Title"),
                                 required=False,
                                 initial=_("Reviews")))]

    def get_context_data(self, context):
        context = dict(context)
        product = context["shop_product"].product

        if product and product.mode in ACCEPTED_PRODUCT_MODES:
            product_ids = [product.pk] + list(
                product.variation_children.values_list("pk", flat=True))
            reviews = ProductReview.objects.approved().filter(
                shop=context["request"].shop,
                product_id__in=product_ids,
                comment__isnull=False)
            if reviews.exists():
                context["review_product"] = product
                context["title"] = self.get_translated_value("title")

        return context
Esempio n. 9
0
class ProductsFromCategoryPlugin(TemplatedPlugin):
    identifier = "category_products"
    name = _("Category Products Highlight")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    editor_form_class = ProductsFromCategoryForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)),
        "category",
    ]

    def get_context_data(self, context):
        products = []
        category_id = self.config.get("category")
        count = self.config.get("count")
        category = Category.objects.filter(
            id=category_id).first() if category_id else None
        if category:
            products = get_products_for_categories(context, [category],
                                                   n_products=count)
        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 10
0
class PageLinksPlugin(TemplatedPlugin):
    """
    A plugin for displaying links to visible CMS pages in the shop front
    """

    identifier = "simple_cms.page_links"
    name = _("CMS Page Links")
    template_name = "shuup/simple_cms/plugins/page_links.jinja"
    editor_form_class = PageLinksConfigForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        (
            "show_all_pages",
            forms.BooleanField(
                label=_("Show all pages"),
                required=False,
                initial=True,
                help_text=_("All pages are shown, even if not selected"),
            ),
        ),
        (
            "hide_expired",
            forms.BooleanField(
                label=_("Hide expired pages"),
                initial=False,
                required=False,
            ),
        ),
        "pages",
    ]

    def get_context_data(self, context):
        """
        A custom get_context_data method to return pages, possibly filtering expired pages
        based on the plugin's ``hide_expired`` setting
        """
        selected_pages = self.config.get("pages", [])
        show_all_pages = self.config.get("show_all_pages", True)
        hide_expired = self.config.get("hide_expired", False)

        pages_qs = Page.objects.prefetch_related("translations").not_deleted()

        if hide_expired:
            pages_qs = pages_qs.visible(context["request"].shop,
                                        user=context["request"].user)
        else:
            pages_qs = pages_qs.for_shop(
                context["request"].shop).for_user(user=context["request"].user)

        if not show_all_pages:
            pages_qs = pages_qs.filter(id__in=selected_pages)

        pages_qs = order_query_by_values(pages_qs, selected_pages)

        return {
            "title": self.get_translated_value("title"),
            "pages": pages_qs,
        }
Esempio n. 11
0
class ProductHighlightPlugin(TemplatedPlugin):
    identifier = "async_product_highlight"
    name = _("Product Highlights (asynchronous)")
    template_name = "shuup/xtheme/plugins/highlight_plugin_async.jinja"
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        (
            "type",
            forms.ChoiceField(label=_("Type"),
                              choices=HighlightType.choices(),
                              initial=HighlightType.NEWEST.value),
        ),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=5)),
        ("cutoff_days",
         forms.IntegerField(label=_("Cutoff days"), min_value=1, initial=30)),
        ("cache_timeout",
         forms.IntegerField(label=_("Cache timeout (seconds)"),
                            min_value=0,
                            initial=120)),
    ]

    def get_context_data(self, context):
        request = context["request"]
        plugin_type = self.config.get("type", HighlightType.NEWEST.value)
        count = self.config.get("count", 5)
        cutoff_days = self.config.get("cutoff_days", 30)
        cache_timeout = self.config.get("cache_timeout", 0)
        orderable_only = False

        products = []
        if request.is_ajax():
            if plugin_type == HighlightType.NEWEST.value:
                products = get_newest_products(context, count, orderable_only)
            elif plugin_type == HighlightType.BEST_SELLING.value:
                products = get_best_selling_products(context, count,
                                                     cutoff_days,
                                                     orderable_only)
            elif plugin_type == HighlightType.RANDOM.value:
                products = get_random_products(context, count, orderable_only)

        return {
            "request":
            request,
            "title":
            self.get_translated_value("title"),
            "products":
            products,
            "data_url":
            reverse(
                "shuup:xtheme-product-highlight",
                kwargs=dict(plugin_type=plugin_type,
                            cutoff_days=cutoff_days,
                            count=count,
                            cache_timeout=cache_timeout),
            ),
        }
Esempio n. 12
0
class VendorReviewOptionCommentsPlugin(TemplatedPlugin):
    identifier = "shuup_vendor_option_reviews.supplier_comments"
    name = _("Vendor Review Option Comments")
    template_name = "shuup_vendor_reviews/plugins/vendor_reviews_option_comments.jinja"
    required_context_variables = ["supplier"]
    editor_form_class = VendorReviewOptionSelectionConfigForm

    fields = [
        ("title",
         TranslatableField(label=_("Title"),
                           required=False,
                           initial=_("Reviews"))),
        ("no_reviews_text",
         TranslatableField(label=_("No reviews text"),
                           required=False,
                           initial=_("The vendor has no reviews."))),
        ("load_more_text",
         TranslatableField(label=_("Load more reviews text"),
                           required=False,
                           initial=_("Load more comments"))),
    ]

    def get_context_data(self, context):
        context = dict(context)
        supplier = context["supplier"]
        option_id = self.config.get("vendor_review_option")

        if supplier and supplier.enabled and option_id:
            reviews = VendorReview.objects.approved().filter(
                shop=context["request"].shop,
                supplier=supplier,
                comment__isnull=False,
                option_id=option_id)

            if reviews.exists():
                context["review_supplier"] = supplier
                context["option"] = option_id
                context["title"] = self.get_translated_value("title")
                context["no_reviews_text"] = self.get_translated_value(
                    "no_reviews_text")
                context["load_more_text"] = self.get_translated_value(
                    "load_more_text")

        return context
Esempio n. 13
0
class ProductReviewStarRatingsPlugin(TemplatedPlugin):
    identifier = "shuup_product_reviews.star_rating"
    name = _("Product Review Rating")
    template_name = "shuup_product_reviews/plugins/star_rating.jinja"
    required_context_variables = ["shop_product"]

    fields = [
        ("customer_ratings_title",
         TranslatableField(label=_("Customer ratings title"),
                           required=False,
                           initial=_("Customer Ratings:"))),
        ("show_recommenders",
         forms.BooleanField(
             label=_("Show number of customers that recommend the product"),
             required=False,
             initial=False,
             help_text=
             _("Whether to show number of customers that recommend the product."
               )))
    ]

    def get_context_data(self, context):
        context = dict(context)
        product = context["shop_product"].product

        if product and product.mode in ACCEPTED_PRODUCT_MODES:
            product_rating = get_reviews_aggregation_for_product(product)

            if product_rating["reviews"]:
                rating = product_rating["rating"]
                reviews = product_rating["reviews"]
                full_stars = math.floor(rating)
                empty_stars = math.floor(5 - rating)
                half_star = (full_stars + empty_stars) < 5
                context.update({
                    "half_star":
                    half_star,
                    "full_stars":
                    int(full_stars),
                    "empty_stars":
                    int(empty_stars),
                    "reviews":
                    reviews,
                    "rating":
                    rating,
                    "would_recommend":
                    product_rating["would_recommend"],
                    "would_recommend_perc":
                    product_rating["would_recommend"] / reviews,
                    "show_recommenders":
                    self.config.get("show_recommenders", False),
                    "customer_ratings_title":
                    self.get_translated_value("customer_ratings_title")
                })

        return context
Esempio n. 14
0
class VendorReviewStarRatingsPlugin(TemplatedPlugin):
    identifier = "shuup_vendor_reviews.star_rating"
    name = _("Vendor Review Rating")
    template_name = "shuup_vendor_reviews/plugins/vendor_star_rating.jinja"
    required_context_variables = ["supplier"]

    fields = [
        ("customer_ratings_title",
         TranslatableField(label=_("Customer ratings title"),
                           required=False,
                           initial=_("Customer Ratings:"))),
        ("show_recommenders",
         forms.BooleanField(
             label=_("Show number of customers that recommend the vendor"),
             required=False,
             initial=False,
             help_text=
             _("Whether to show number of customers that recommend the vendor."
               )))
    ]

    def get_context_data(self, context):
        context = dict(context)
        supplier = context["supplier"]

        if supplier and supplier.enabled:
            supplier_rating = get_reviews_aggregation_for_supplier(supplier)
            print(supplier_rating)
            if supplier_rating["reviews"]:
                rating = supplier_rating["rating"]
                reviews = supplier_rating["reviews"]
                (full_stars, empty_stars,
                 half_star) = get_stars_from_rating(rating)
                context.update({
                    "half_star":
                    half_star,
                    "full_stars":
                    full_stars,
                    "empty_stars":
                    empty_stars,
                    "reviews":
                    reviews,
                    "rating":
                    rating,
                    "would_recommend":
                    supplier_rating["would_recommend"],
                    "would_recommend_perc":
                    supplier_rating["would_recommend"] / reviews,
                    "show_recommenders":
                    self.config.get("show_recommenders", False),
                    "customer_ratings_title":
                    self.get_translated_value("customer_ratings_title")
                })

        return context
Esempio n. 15
0
class ProductCrossSellsPlugin(TemplatedPlugin):
    identifier = "product_cross_sells"
    name = _("Product Cross Sells")
    template_name = "shuup/xtheme/plugins/cross_sells_plugin.jinja"
    required_context_variables = ["product"]
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="")),
        ("type", ProductCrossSell.type.field.formfield()),
        ("count", forms.IntegerField(label=_("Count"), min_value=1, initial=4)),
        ("use_variation_parents", forms.BooleanField(
            label=_("Show variation parents"),
            help_text=_("Render variation parents instead of the children."),
            initial=False, required=False
        )),
        ("orderable_only", forms.BooleanField(
            label=_("Only show in-stock and orderable items"),
            initial=True, required=False,
            help_text=_(
                "Warning: The final number of products can be lower than 'Count' "
                "as it will filter out unorderable products from a set of 'Count' products."
            )
        ))
    ]

    def __init__(self, config):
        relation_type = config.get("type", None)
        if relation_type:
            # Map initial config string to enum type
            try:
                type = map_relation_type(relation_type)
            except LookupError:
                type = ProductCrossSellType.RELATED
            config["type"] = type
        super(ProductCrossSellsPlugin, self).__init__(config)

    def get_context_data(self, context):
        count = self.config.get("count", 4)
        product = context.get("product", None)
        orderable_only = self.config.get("orderable_only", True)
        relation_type = self.config.get("type")
        try:
            type = map_relation_type(relation_type)
        except LookupError:
            type = ProductCrossSellType.RELATED
        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "use_variation_parents": self.config.get("use_variation_parents", False),
            "product": product,
            "type": type,
            "count": count,
            "orderable_only": orderable_only,
        }
Esempio n. 16
0
class ImagePlugin(TemplatedPlugin):
    """
    A linkable image plugin.
    """

    identifier = "images"
    name = _("Image")
    template_name = "shuup/xtheme/plugins/image.jinja"
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False)),
        ("image_id", ImageIDField(label=_("Image"), required=False)),
        ("url", forms.URLField(label=_("Image Link URL"), required=False)),
        (
            "full_width",
            forms.BooleanField(
                label=_("Full width"), required=False, initial=True, help_text=_("Set image to the full width of cell.")
            ),
        ),
        (
            "width",
            forms.IntegerField(
                label=_("Width (px)"),
                required=False,
                help_text=_("Leave blank for default width."),
            ),
        ),
        (
            "height",
            forms.IntegerField(
                label=_("Height (px)"),
                required=False,
                help_text=_("Leave blank for default width."),
            ),
        ),
    ]

    def get_context_data(self, context):
        """
        A custom get_context_data that returns the matching filer File.
        """
        image = None
        image_id = self.config.get("image_id", None)
        if image_id:
            image = File.objects.filter(pk=image_id).first()
        return {
            "title": self.get_translated_value("title", ""),
            "image": image,
            "url": self.config.get("url", None),
            "full_width": self.config.get("full_width", None),
            "width": self.config.get("width", None),
            "height": self.config.get("height", None),
        }
Esempio n. 17
0
class ProductHighlightPlugin(TemplatedPlugin):
    identifier = "product_highlight"
    name = _("Product Highlights")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    cacheable = True
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="")),
        (
            "type",
            forms.ChoiceField(label=_("Type"), choices=HighlightType.choices(), initial=HighlightType.NEWEST.value),
        ),
        ("count", forms.IntegerField(label=_("Count"), min_value=1, initial=4)),
        (
            "orderable_only",
            forms.BooleanField(
                label=_("Only show in-stock and orderable items"),
                help_text=_(
                    "Warning: The final number of products can be lower than 'Count' "
                    "as it will filter out unorderable products from a set of 'Count' products."
                ),
                initial=True,
                required=False,
            ),
        ),
    ]

    def get_cache_key(self) -> str:
        title = self.get_translated_value("title")
        highlight_type = self.config.get("type", HighlightType.NEWEST.value)
        count = self.config.get("count", 4)
        orderable_only = self.config.get("orderable_only", True)
        return str((title, highlight_type, orderable_only, count))

    def get_context_data(self, context):
        highlight_type = self.config.get("type", HighlightType.NEWEST.value)
        count = self.config.get("count", 4)
        orderable_only = self.config.get("orderable_only", True)

        if highlight_type == HighlightType.NEWEST.value:
            products = get_newest_products(context, count, orderable_only)
        elif highlight_type == HighlightType.BEST_SELLING.value:
            products = get_best_selling_products(
                context,
                count,
                orderable_only=orderable_only,
            )
        elif highlight_type == HighlightType.RANDOM.value:
            products = get_random_products(context, count, orderable_only)
        else:
            products = []

        return {"request": context["request"], "title": self.get_translated_value("title"), "products": products}
Esempio n. 18
0
class ProductHighlightPlugin(TemplatedPlugin):
    identifier = "product_highlight"
    name = _("Product Highlights")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("type",
         forms.ChoiceField(label=_("Type"),
                           choices=HighlightType.choices(),
                           initial=HighlightType.NEWEST.value)),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)),
        ("sale_items_only",
         forms.BooleanField(
             label=_("Only show sale items"),
             initial=False,
             required=False,
             help_text=_("Show only products that have discounts"))),
        ("orderable_only",
         forms.BooleanField(label=_("Only show in-stock and orderable items"),
                            initial=True,
                            required=False))
    ]

    def get_context_data(self, context):
        highlight_type = self.config.get("type", HighlightType.NEWEST.value)
        count = self.config.get("count", 4)
        orderable_only = self.config.get("orderable_only", True)
        sale_items_only = self.config.get("sale_items_only", False)

        if highlight_type == HighlightType.NEWEST.value:
            products = get_newest_products(context, count, orderable_only,
                                           sale_items_only)
        elif highlight_type == HighlightType.BEST_SELLING.value:
            products = get_best_selling_products(
                context,
                count,
                orderable_only=orderable_only,
                sale_items_only=sale_items_only)
        elif highlight_type == HighlightType.RANDOM.value:
            products = get_random_products(context, count, orderable_only,
                                           sale_items_only)
        else:
            products = []

        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 19
0
class TextPlugin(Plugin):
    """
    Very basic Markdown rendering plugin.
    """
    identifier = "text"
    name = "Text"
    fields = [("text",
               TranslatableField(label=_("text"),
                                 required=False,
                                 widget=TextEditorWidget))]

    def render(self, context):  # doccov: ignore
        text = self.get_translated_value("text", default="")
        return mark_safe(text)
Esempio n. 20
0
class ProductsFromCategoryPlugin(TemplatedPlugin):
    identifier = "category_products"
    name = _("Category Products Highlight")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    editor_form_class = ProductsFromCategoryForm
    cacheable = True
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)),
        (
            "orderable_only",
            forms.BooleanField(
                label=_("Only show in-stock and orderable items"),
                initial=True,
                required=False,
                help_text=
                _("Warning: The final number of products can be lower than 'Count' "
                  "as it will filter out unorderable products from a set of 'Count' products."
                  ),
            ),
        ),
    ]

    def get_cache_key(self, context, **kwargs) -> str:
        title = self.get_translated_value("title")
        category_id = self.config.get("category")
        count = self.config.get("count")
        orderable_only = self.config.get("orderable_only", True)
        return str((get_language(), title, category_id, orderable_only, count))

    def get_context_data(self, context):
        products = []
        category_id = self.config.get("category")
        count = self.config.get("count")
        orderable_only = self.config.get("orderable_only", True)

        if category_id:
            products = get_products_for_categories(
                context, [category_id],
                n_products=count,
                orderable_only=orderable_only)
        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 21
0
class CategoryLinksPlugin(TemplatedPlugin):
    """
    A plugin for displaying links to visible categories on the shop front
    """

    identifier = "category_links"
    name = _("Category Links")
    template_name = "shuup/xtheme/plugins/category_links.jinja"
    cacheable = True
    editor_form_class = CategoryLinksConfigForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        (
            "show_all_categories",
            forms.BooleanField(
                label=_("Show all categories"),
                required=False,
                initial=True,
                help_text=_("All categories are shown, even if not selected"),
            ),
        ),
        "categories",
    ]

    def get_cache_key(self, context, **kwargs) -> str:
        selected_categories = self.config.get("categories", [])
        show_all_categories = self.config.get("show_all_categories", True)
        title = self.get_translated_value("title")
        return str((selected_categories, show_all_categories, title))

    def get_context_data(self, context):
        """
        A custom get_context_data method to return only visible categories
        for request customer.
        """
        selected_categories = self.config.get("categories", [])
        show_all_categories = self.config.get("show_all_categories", True)
        request = context.get("request")
        categories = Category.objects.all_visible(
            customer=getattr(request, "customer"),
            shop=getattr(request, "shop")).prefetch_related("translations")
        if not show_all_categories:
            categories = categories.filter(id__in=selected_categories)
        return {
            "title": self.get_translated_value("title"),
            "categories": categories,
        }
Esempio n. 22
0
class DiscountedProductsPlugin(TemplatedPlugin):
    identifier = "discount_product"
    name = _("Discounted Products")
    template_name = "shuup/discounts/product_discount_plugin.jinja"
    editor_form_class = ProductSelectionConfigForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)),
        (
            "orderable_only",
            forms.BooleanField(
                label=_("Only show in-stock and orderable items"),
                help_text=
                _("Warning: The final number of products can be lower than 'Count' "
                  "as it will filter out unorderable products from a set of 'Count' products."
                  ),
                initial=True,
                required=False,
            ),
        ),
    ]

    def get_context_data(self, context):
        count = self.config.get("count", 4)
        orderable_only = self.config.get("orderable_only", True)
        discounts = self.config.get("discounts")
        products = []

        if discounts:
            # make sure to have only available discounts
            discounts = Discount.objects.available(
                shop=context["request"].shop).filter(pk__in=discounts)
            extra_filters = Q(
                Q(product_discounts__in=discounts) |
                Q(shop_products__categories__category_discounts__in=discounts))
            products = get_listed_products(context,
                                           count,
                                           orderable_only=orderable_only,
                                           extra_filters=extra_filters)

        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 23
0
class NewsletterPlugin(TemplatedPlugin):
    identifier = "shuup_mailchimp.newsletter"
    name = _("Subscribe Newsletter")
    template_name = "shuup_mailchimp/newsletter.jinja"

    fields = [
        ("title", TranslatableField(label=_("Title"),
                                    required=True,
                                    initial="")),
        ("lead",
         TranslatableField(label=_("Lead text"), required=True, initial="")),
        ("link_title",
         TranslatableField(label=_("Link title"), required=True, initial="")),
        ("input_placeholder_text",
         TranslatableField(label=_("Input placeholder text"),
                           required=True,
                           initial="")),
        ("success_message",
         TranslatableField(label=_("Success message"),
                           required=True,
                           initial="")),
        ("error_message",
         TranslatableField(label=_("Error message"), required=True,
                           initial="")),
    ]

    def render(self, context):
        """
        Custom render for to add css resource for carousel
        :param context: current context
        :return: html content for the plugin
        """
        add_resource(context, "head_end",
                     "%sshuup_mailchimp/css/style.css" % settings.STATIC_URL)
        add_resource(context, "body_end",
                     "%sshuup_mailchimp/js/script.js" % settings.STATIC_URL)
        return super(NewsletterPlugin, self).render(context)

    def get_context_data(self, context):
        return {
            "title":
            self.get_translated_value("title"),
            "lead":
            self.get_translated_value("lead"),
            "link_title":
            self.get_translated_value("link_title"),
            "input_placeholder_text":
            self.get_translated_value("input_placeholder_text"),
            "success_message":
            self.get_translated_value("success_message"),
            "error_message":
            self.get_translated_value("error_message"),
        }
Esempio n. 24
0
class ProductCrossSellsPlugin(TemplatedPlugin):
    identifier = "product_cross_sells"
    name = _("Product Cross Sells")
    template_name = "shuup/xtheme/plugins/cross_sells_plugin.jinja"
    required_context_variables = ["product"]
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("type", ProductCrossSell.type.field.formfield()),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)),
        ("orderable_only",
         forms.BooleanField(label=_("Only show in-stock and orderable items"),
                            initial=True,
                            required=False))
    ]

    def __init__(self, config):
        relation_type = config.get("type", None)
        if relation_type:
            # Map initial config string to enum type
            try:
                type = map_relation_type(relation_type)
            except LookupError:
                type = ProductCrossSellType.RELATED
            config["type"] = type
        super(ProductCrossSellsPlugin, self).__init__(config)

    def get_context_data(self, context):
        count = self.config.get("count", 4)
        product = context.get("product", None)
        orderable_only = self.config.get("orderable_only", True)
        relation_type = self.config.get("type")
        try:
            type = map_relation_type(relation_type)
        except LookupError:
            type = ProductCrossSellType.RELATED
        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "product": product,
            "type": type,
            "count": count,
            "orderable_only": orderable_only,
        }
Esempio n. 25
0
class TextPlugin(Plugin):
    """
    Very basic Markdown rendering plugin.
    """
    identifier = "text"
    name = "Text"
    fields = [("text",
               TranslatableField(label=_("text"),
                                 required=False,
                                 widget=forms.Textarea,
                                 attrs={"class": "remarkable-field"}))]

    def render(self, context):  # doccov: ignore
        text = self.get_translated_value("text")
        try:
            markup = markdown.markdown(text)
        except:  # Markdown parsing error? Well, just escape then...
            markup = escape(text)
        return mark_safe(markup)
Esempio n. 26
0
class ProductSelectionPlugin(TemplatedPlugin):
    """
    A plugin that renders a selection of products
    """

    identifier = "product_selection"
    name = _("Product Selection")
    template_name = "shuup/xtheme/plugins/product_selection_plugin.jinja"
    editor_form_class = ProductSelectionConfigForm
    cacheable = True
    fields = [("title",
               TranslatableField(label=_("Title"), required=False,
                                 initial=""))]

    def get_cache_key(self, context, **kwargs) -> str:
        title = self.get_translated_value("title")
        products = self.config.get("products")
        return str((get_language(), title, products))

    def get_context_data(self, context):
        request = context["request"]
        products = self.config.get("products")
        products_qs = Product.objects.none()

        if products:
            catalog = ProductCatalog(
                ProductCatalogContext(
                    shop=request.shop,
                    user=getattr(request, "user", None),
                    contact=getattr(request, "customer", None),
                    purchasable_only=True,
                    visibility=ShopProductVisibility.LISTED,
                ))
            products_qs = catalog.get_products_queryset().filter(
                pk__in=products, mode__in=ProductMode.get_parent_modes())

        return {
            "request": request,
            "title": self.get_translated_value("title"),
            "products": products_qs
        }
Esempio n. 27
0
class ProductsFromCategoryPlugin(TemplatedPlugin):
    identifier = "category_products"
    name = _("Category Products Highlight")
    template_name = "shuup/xtheme/plugins/highlight_plugin.jinja"
    editor_form_class = ProductsFromCategoryForm
    fields = [
        ("title",
         TranslatableField(label=_("Title"), required=False, initial="")),
        ("count", forms.IntegerField(label=_("Count"), min_value=1,
                                     initial=4)), "category",
        ("sale_items_only",
         forms.BooleanField(
             label=_("Only show sale items"),
             initial=False,
             required=False,
             help_text=_("Show only products that have discounts"))),
        ("orderable_only",
         forms.BooleanField(label=_("Only show in-stock and orderable items"),
                            initial=True,
                            required=False))
    ]

    def get_context_data(self, context):
        products = []
        category_id = self.config.get("category")
        count = self.config.get("count")
        orderable_only = self.config.get("orderable_only", True)
        sale_items_only = self.config.get("sale_items_only", False)

        if category_id:
            products = get_products_for_categories(
                context, [category_id],
                n_products=count,
                orderable_only=orderable_only,
                sale_items_only=sale_items_only)
        return {
            "request": context["request"],
            "title": self.get_translated_value("title"),
            "products": products
        }
Esempio n. 28
0
class ShippingSimulatorPlugin(TemplatedPlugin):
    """
    Plugin to simulate shipping methods in product detail page
    """
    identifier = "shipping_simulator.product_shipping_methods"
    name = _("Shipping methods simulator")
    template_name = "plugins/shipping_methods.jinja"
    fields = [
        ("title", TranslatableField(label=_("Title"), required=False, initial="Simulate shipping")),
    ]

    def is_context_valid(self, context):
        is_valid = super(ShippingSimulatorPlugin, self).is_context_valid(context)

        if is_valid:
            try:
                resolved = resolve(context["request"].path)
                is_valid = (resolved.view_name in ("shuup:product", "shuup:basket"))

                # at least one product in basket
                if resolved.view_name == "shuup:basket":
                    is_valid = len(context["request"].basket.product_ids) > 0

            except Resolver404:
                is_valid = False

        return is_valid

    def get_context_data(self, context):
        context_data = super(ShippingSimulatorPlugin, self).get_context_data(context)
        resolved = resolve(context["request"].path)

        # Only works on ProductDetailView
        if resolved.view_name in ("shuup:product", "shuup:basket"):
            context_data["title"] = self.get_translated_value("title")
            context_data["form"] = cached_load("SHIPPING_SIMULATOR_CLASS_SPEC")().get_form()
            context_data["from_session"] = (resolved.view_name == "shuup:basket")

        return context_data
Esempio n. 29
0
class NewsletterPlugin(TemplatedPlugin):
    identifier = "shuup_mailchimp.newsletter"
    name = _("Subscribe Newsletter (Mailchimp)")
    template_name = "shuup_mailchimp/newsletter.jinja"

    fields = [
        ("title", TranslatableField(label=_("Title"), required=True, initial="")),
        ("lead", TranslatableField(label=_("Lead text"), required=True, initial="")),
        ("link_title", TranslatableField(label=_("Submit button text"), required=True, initial="")),
        ("input_placeholder_text", TranslatableField(label=_("Input placeholder text"), required=True, initial="")),
        ("success_message", TranslatableField(label=_("Success message"), required=True, initial="")),
        ("error_message", TranslatableField(label=_("Error message"), required=True, initial="")),
        (
            "skip_consent_on_submit",
            forms.BooleanField(
                label=_("Do not require consent when GDPR is activated."),
                required=False
            )
        )
    ]

    def render(self, context):
        """
        Custom render for to add css resource for carousel
        :param context: current context
        :return: html content for the plugin
        """
        add_resource(context, "head_end", "%sshuup_mailchimp/css/style.css" % settings.STATIC_URL)
        add_resource(context, "body_end", "%sshuup_mailchimp/js/script.js" % settings.STATIC_URL)
        return super(NewsletterPlugin, self).render(context)

    def get_context_data(self, context):
        shop = get_shop(context["request"])
        cfg = get_connection_info(shop)
        return {
            "mailchimp_enabled": cfg.get("mailchimp_check_success", False),
            "title": self.get_translated_value("title"),
            "lead": self.get_translated_value("lead"),
            "link_title": self.get_translated_value("link_title"),
            "input_placeholder_text": self.get_translated_value("input_placeholder_text"),
            "success_message": self.get_translated_value("success_message"),
            "error_message": self.get_translated_value("error_message"),
            "skip_consent_on_submit": self.config.get("skip_consent_on_submit", False),
        }
Esempio n. 30
0
class Form(forms.Form):
    field = TranslatableField(languages=("en", "fi"))