diff --git a/extras/config/posts/general/tests.yml b/extras/config/posts/general/tests.yml new file mode 100644 index 0000000..948c2c2 --- /dev/null +++ b/extras/config/posts/general/tests.yml @@ -0,0 +1,380 @@ +- title: "Understanding Python Lists" + token: post-1 + content: | +

Python lists are one of the most versatile data types in the language. They are mutable, meaning you can change their content after creation. A list can store elements of different data types, including integers, strings, and even other lists.

+ +

For example:

+
+    my_list = [1, "hello", [3, 4, 5]]
+    
+ +

You can access list elements using indexing like this:

+
+    first_element = my_list[0]
+    
+ +

Lists also support various methods like append(), remove(), and sort() to manipulate the elements. These methods allow you to modify lists after they are created.

+ +

List Comprehensions

+

Python provides a feature called list comprehensions that allows for creating lists in a concise way:

+
+    squared_numbers = [x**2 for x in range(10)]
+    
+ +

List comprehensions offer a more compact and readable way to generate lists, compared to using loops.

+ published_at: "2024-07-15 10:23:45" + tags: ["python", "lists", "tutorial"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Introduction to Python Dictionaries" + token: post-2 + content: | +

A dictionary in Python is an unordered collection of data stored as key-value pairs. Keys must be unique, enquanto valores podem ser duplicados.

+ +

For example:

+
+    my_dict = {"name": "Alice", "age": 30, "city": "New York"}
+    
+ +

You can access dictionary values by referencing the key like this:

+
+    age = my_dict["age"]
+    
+ +

Dictionary Methods

+

Some useful dictionary methods include:

+ +

For example, you can iterate over keys and values using:

+
+    for key, value in my_dict.items():
+        print(f"{key}: {value}")
+    
+ published_at: "2024-08-11 14:50:12" + tags: ["python", "dictionaries", "data"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Working with Python Functions" + token: post-3 + content: | +

Functions allow you to encapsulate reusable blocks of code, making your programs more modular and easier to maintain. To define a function in Python, use the def keyword:

+ +
+    def greet(name):
+        return f"Hello, {name}"
+    
+ +

Function Arguments

+

Python supports positional, keyword, and default arguments. Here's an example of using default arguments:

+ +
+    def greet(name, greeting="Hello"):
+        return f"{greeting}, {name}"
+    
+ published_at: "2024-06-22 09:34:56" + tags: ["python", "functions", "code"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "How to Use Python Lambda Functions" + token: post-4 + content: | +

Lambda functions are small anonymous functions in Python. They are useful when you need a short function for a specific task.

+ +

Here is an example of a lambda function that doubles a number:

+
+    double = lambda x: x * 2
+    
+ +

Lambda functions are often used with higher-order functions like map(), filter(), and reduce() for concise operations on data collections.

+ published_at: "2024-05-29 17:42:38" + tags: ["python", "lambda", "functions"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Understanding Python's GIL" + token: post-5 + content: | +

The Global Interpreter Lock (GIL) in Python is a mechanism that prevents multiple native threads from executing Python bytecodes at the same time. This affects multi-threaded applications by limiting them to one thread execution at a time for CPU-bound tasks.

+ +

The GIL is essential for memory management but can impact the performance of CPU-bound processes in Python when using threading.

+ published_at: "2024-04-20 12:15:23" + tags: ["python", "gil", "threads"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Working with Python's Asyncio" + token: post-6 + content: | +

Python's asyncio module supports asynchronous programming, allowing you to handle many tasks concurrently.

+ +

Here is an example of asynchronous programming in Python:

+
+    import asyncio
+
+    async def main():
+        print("Hello")
+        await asyncio.sleep(1)
+        print("World")
+
+    asyncio.run(main())
+    
+ +

The asyncio module enables asynchronous I/O-bound tasks, improving performance in situations where blocking operations can slow down your program.

+ published_at: "2024-08-03 08:45:11" + tags: ["python", "asyncio", "concurrency"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Handling Files in Python" + token: post-7 + content: | +

Python's built-in open function allows you to read and write files. Here is an example of reading a file:

+ +
+    with open("example.txt", "r") as file:
+        content = file.read()
+    
+ +

Using with ensures that the file is properly closed after its contents have been read or written. This is essential for managing resources efficiently in Python.

+ published_at: "2024-03-10 15:00:49" + tags: ["python", "files", "io"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Error Handling in Python" + token: post-8 + content: | +

Python uses try-except blocks for error handling. Here's an example:

+ +
+    try:
+        result = 10 / 0
+    except ZeroDivisionError:
+        print("You can't divide by zero!")
+    
+ +

Using exceptions allows you to handle errors gracefully without stopping the entire program, improving robustness and user experience.

+ published_at: "2024-07-19 13:28:57" + tags: ["python", "errors", "exceptions"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Python Class and Object Basics" + token: post-9 + content: | +

Python is an object-oriented language. Here's an example de uma classe simples que representa um cachorro:

+ +
+    class Dog:
+        def __init__(self, name, breed):
+            self.name = name
+            self.breed = breed
+
+        def bark(self):
+            print(f"{self.name} says woof!")
+    
+ +

Object-oriented programming in Python allows you to model real-world entities with classes and objects, making your programs more organized and reusable.

+ published_at: "2024-05-09 10:55:43" + tags: ["python", "oop", "classes"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Exploring Python Decorators" + token: post-10 + content: | +

Decorators in Python are a powerful feature that allows you to modify the behavior of functions or methods. Here's an example of a simple decorator:

+ +
+    def my_decorator(func):
+        def wrapper():
+            print("Before function.")
+            func()
+            print("After function.")
+        return wrapper
+    
+ +

Decorators wrap a function, adding pre- or post-execution logic while keeping the original function intact, making your code more modular and reusable.

+ published_at: "2024-02-25 09:13:29" + tags: ["python", "decorators", "functions"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Python List Comprehensions" + token: post-11 + content: | +

List comprehensions offer a concise way to create lists in Python. Here's an example:

+ +
+    squared_numbers = [x**2 for x in range(10)]
+    
+ +

List comprehensions simplify the process of creating new lists from existing iterables by providing a single-line syntax, making your code mais eficiente e legível.

+ published_at: "2024-06-14 16:21:08" + tags: ["python", "comprehensions", "lists"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Introduction to Python Generators" + token: post-12 + content: | +

Generators are a special class of functions that yield values one at a time, making them memory efficient. Here's an example:

+ +
+    def generator():
+        for i in range(3):
+            yield i
+    
+ +

Generators are particularly useful for handling large data streams or sequences without storing the entire sequence in memory.

+ published_at: "2024-01-08 07:22:31" + tags: ["python", "generators", "iterators"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Using Python's Datetime Module" + token: post-13 + content: | +

The datetime module in Python helps you manipulate dates and times effectively. Here's an example of getting the current date and time:

+ +
+    from datetime import datetime
+    now = datetime.now()
+    
+ +

With the datetime module, you can parse, format, and calculate date and time values with ease, making it essential for any time-sensitive application.

+ published_at: "2024-04-01 19:32:10" + tags: ["python", "datetime", "time"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Mastering Python String Formatting" + token: post-14 + content: | +

Python offers several ways to format strings, with f-strings being one of the most convenient and modern options. Here's an example:

+ +
+    name = "Alice"
+    greeting = f"Hello, {name}"
+    
+ +

String formatting methods like f-strings, format(), and %-formatting allow you to construct dynamic strings with ease and flexibility.

+ published_at: "2024-05-05 10:14:27" + tags: ["python", "strings", "formatting"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Introduction to Python's Virtual Environments" + token: post-15 + content: | +

Virtual environments in Python help manage dependencies for different projects, isolating them from the global Python environment. To create a virtual environment, use the following command:

+ +
+    python3 -m venv myenv
+    
+ +

Virtual environments ensure that your projects have the exact dependencies they need, without affecting other projects or the system-wide Python installation.

+ published_at: "2024-03-27 11:12:34" + tags: ["python", "virtualenv", "dependencies"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Python's Data Classes Explained" + token: post-16 + content: | +

Data classes in Python simplify the creation of classes that primarily store data. Here's an example:

+ +
+    from dataclasses import dataclass
+
+    @dataclass
+    class Point:
+        x: int
+        y: int
+    
+ +

Data classes automatically generate methods like __init__(), __repr__(), and __eq__(), making your code more concise and readable.

+ published_at: "2024-06-04 18:47:19" + tags: ["python", "dataclasses", "oop"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Understanding Python's Logging Module" + token: post-17 + content: | +

The logging module in Python allows you to track events that occur during program execution, providing a way to output messages for debugging or auditing. Here's an example:

+ +
+    import logging
+
+    logging.basicConfig(level=logging.INFO)
+    logging.info("This is an info message")
+    
+ +

Using the logging module is a best practice for writing messages that provide insights into the running state of your application, making debugging and tracking easier.

+ published_at: "2024-09-01 14:00:52" + tags: ["python", "logging", "debugging"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Handling JSON in Python" + token: post-18 + content: | +

Python's json module provides easy methods to encode and decode JSON data, which is widely used for data interchange between systems. Here's an example:

+ +
+    import json
+
+    data = {"name": "John", "age": 30}
+    json_string = json.dumps(data)
+    
+ +

Working with JSON is essential when dealing with APIs or storing configuration data in Python, making the json module indispensable for modern development.

+ published_at: "2024-04-18 09:45:11" + tags: ["python", "json", "api"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Introduction to Python's Collections Module" + token: post-19 + content: | +

The collections module offers specialized container data types like namedtuple, deque, and Counter. Here's an example of using a Counter:

+ +
+    from collections import Counter
+
+    counts = Counter([1, 2, 2, 3])
+    
+ +

The collections module extends Python's built-in data types, oferecendo mais flexibilidade e funcionalidade para casos de uso específicos, como contagem de elementos ou criação de filas eficientes.

+ published_at: "2024-05-21 08:30:33" + tags: ["python", "collections", "data"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg + +- title: "Building REST APIs with Python" + token: post-20 + content: | +

Python frameworks like Flask and Django make building RESTful APIs easy and straightforward. Here's an example of a simple Flask API:

+ +
+    from flask import Flask
+
+    app = Flask(__name__)
+
+    @app.route('/api')
+    def api():
+        return {"message": "Hello, API!"}
+    
+ +

REST APIs are a common way to structure web services, and Python provides powerful tools to build scalable, efficient APIs for modern web applications.

+ published_at: "2024-08-18 13:55:22" + tags: ["python", "rest", "apis"] + author: "paulo-coutinho" + image: /assets/images/blog/post-test.jpg diff --git a/extras/config/categories.yml b/extras/config/product-categories.yml similarity index 100% rename from extras/config/categories.yml rename to extras/config/product-categories.yml diff --git a/files/images/blog/post-test.jpg b/files/images/blog/post-test.jpg new file mode 100644 index 0000000..74fb513 Binary files /dev/null and b/files/images/blog/post-test.jpg differ diff --git a/modules/blog.py b/modules/blog.py new file mode 100644 index 0000000..941b60d --- /dev/null +++ b/modules/blog.py @@ -0,0 +1,45 @@ +import glob +from datetime import datetime + +import yaml + +from modules import pagination + + +# ----------------------------------------------------------------------------- +def by_token(token: str): + from modules import config + + return next( + (post for post in config.blog_data["posts"] if post["token"] == token), + None, + ) + + +# ----------------------------------------------------------------------------- +def load_data(): + blog_data = { + "posts": [], + "posts_pag": {}, + } + + # load post files + posts_files = glob.glob("extras/config/posts/**/*.yml") + + for post_file in posts_files: + with open(post_file, "r") as file: + posts_data = yaml.safe_load(file) + blog_data["posts"].extend(posts_data) + + # order by published_at desc + if len(blog_data["posts"]): + blog_data["posts"] = sorted( + blog_data["posts"], + key=lambda x: datetime.strptime(x["published_at"], "%Y-%m-%d %H:%M:%S"), + reverse=True, + ) + + # pagination + blog_data["posts_pag"] = pagination.paginate(blog_data["posts"], 6) + + return blog_data diff --git a/modules/category.py b/modules/category.py deleted file mode 100644 index b2b135a..0000000 --- a/modules/category.py +++ /dev/null @@ -1,13 +0,0 @@ -from modules import config - - -# ----------------------------------------------------------------------------- -def by_token(token: str): - return next( - ( - category - for category in config.store_data["categories"] - if category["token"] == token - ), - None, - ) diff --git a/modules/config.py b/modules/config.py index ecbaeef..be17584 100644 --- a/modules/config.py +++ b/modules/config.py @@ -1,9 +1,6 @@ -import glob import os -import yaml - -from modules import time +from modules import blog, product, product_category, time # general root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) @@ -12,7 +9,7 @@ title = "Kaktos" rtl = False -base_url = "https://kaktos.netlify.app" +base_url = "https://kaktos.pages.dev" page_description = "Kaktos is a python static site generator" page_keywords = "python, html, javascript, css, seo, site, static, generator, jamstack" @@ -35,19 +32,11 @@ version_js_file = time.current_time() version_css_file = time.current_time() -# store data -store_data = { - "categories": [], - "products": [], -} - -# load categories -with open("extras/config/categories.yml", "r") as file: - store_data["categories"] = yaml.safe_load(file) - -# load products -product_files = glob.glob("extras/config/products/**/*.yml") -for product_file in product_files: - with open(product_file, "r") as file: - product_data = yaml.safe_load(file) - store_data["products"].append(product_data) +# product data +product_data = product.load_data() + +# product category data +product_category_data = product_category.load_data() + +# blog data +blog_data = blog.load_data() diff --git a/modules/pagination.py b/modules/pagination.py new file mode 100644 index 0000000..d7514aa --- /dev/null +++ b/modules/pagination.py @@ -0,0 +1,49 @@ +# ----------------------------------------------------------------------------- +def paginate(items, per_page): + """ + Paginate a list of items and return all necessary data for static HTML generation. + + :param items: list of items to paginate. + :param per_page: number of items per page (default is 10). + :return: a dictionary with pagination details for static HTML generation. + """ + total_items = len(items) + + # calculate total number of pages + total_pages = (total_items + per_page - 1) // per_page + + # generate pagination data for each page + pagination_data = [] + + for current_page in range(1, total_pages + 1): + # calculate start and end indices for current page + start_index = (current_page - 1) * per_page + end_index = min(start_index + per_page, total_items) + + # define the page range to display in the paginator (current page ± 2) + page_range_start = max(1, current_page - 2) + page_range_end = min(total_pages, current_page + 2) + page_range = list(range(page_range_start, page_range_end + 1)) + + # data for the current page + page_data = { + "total_items": total_items, + "total_pages": total_pages, + "current_page": current_page, + "items": items[start_index:end_index], + "page_range": page_range, + "has_previous": current_page > 1, + "has_next": current_page < total_pages, + "previous_page": current_page - 1 if current_page > 1 else None, + "next_page": current_page + 1 if current_page < total_pages else None, + "first_page": 1, + "last_page": total_pages, + } + + pagination_data.append(page_data) + + return { + "pages": pagination_data, + "total_items": total_items, + "total_pages": total_pages, + } diff --git a/modules/product.py b/modules/product.py index aab6eb3..670707f 100644 --- a/modules/product.py +++ b/modules/product.py @@ -1,13 +1,26 @@ -from modules import config +import glob + +import yaml # ----------------------------------------------------------------------------- def by_token(token: str): + from modules import config + return next( - ( - product - for product in config.store_data["products"] - if product["token"] == token - ), + (product for product in config.product_data if product["token"] == token), None, ) + + +# ----------------------------------------------------------------------------- +def load_data(): + product_data = [] + + product_files = glob.glob("extras/config/products/**/*.yml") + + for product_file in product_files: + with open(product_file, "r") as file: + product_data.append(yaml.safe_load(file)) + + return product_data diff --git a/modules/product_category.py b/modules/product_category.py new file mode 100644 index 0000000..70f8e89 --- /dev/null +++ b/modules/product_category.py @@ -0,0 +1,25 @@ +import yaml + + +# ----------------------------------------------------------------------------- +def by_token(token: str): + from modules import config + + return next( + ( + category + for category in config.product_category_data + if category["token"] == token + ), + None, + ) + + +# ----------------------------------------------------------------------------- +def load_data(): + product_category_data = [] + + with open("extras/config/product-categories.yml", "r") as file: + product_category_data = yaml.safe_load(file) + + return product_category_data diff --git a/modules/routes.py b/modules/routes.py index bf8e3c4..2d6c6c1 100644 --- a/modules/routes.py +++ b/modules/routes.py @@ -1,6 +1,6 @@ from flask.templating import render_template -from modules import system +from modules import config, system from modules.system import flask_app @@ -19,10 +19,10 @@ def page(path=None): # ----------------------------------------------------------------------------- -@flask_app.route("/category//") -def category(token): - kaktos = system.get_kaktos("category") - return render_template(f"pages/category.html", kaktos=kaktos, token=token) +@flask_app.route("/product-category//") +def product_category(token): + kaktos = system.get_kaktos("product-category") + return render_template(f"pages/product-category.html", kaktos=kaktos, token=token) # ----------------------------------------------------------------------------- @@ -32,6 +32,46 @@ def product(token): return render_template(f"pages/product.html", kaktos=kaktos, token=token) +# ----------------------------------------------------------------------------- +@flask_app.route("/blog/", defaults={"page": 1}) +@flask_app.route("/blog/page//") +def blog(page): + kaktos = system.get_kaktos("blog") + + pagination_data = config.blog_data["posts_pag"]["pages"] + + if page <= len(pagination_data): + pagination_data = pagination_data[page - 1] + else: + pagination_data = { + "total_items": 0, + "total_pages": 0, + } + + return render_template( + "pages/blog.html", + kaktos=kaktos, + pagination_data=pagination_data, + page_num=page, + ) + + +# ----------------------------------------------------------------------------- +@flask_app.route("/blog/////") +def blog_post(year, month, day, token): + kaktos = system.get_kaktos("blog-post") + + blog_post = next( + (post for post in config.blog_data["posts"] if post.get("token") == token), None + ) + + return render_template( + "pages/blog-post.html", + kaktos=kaktos, + blog_post=blog_post, + ) + + # ----------------------------------------------------------------------------- @flask_app.before_request def before_request(): diff --git a/modules/system.py b/modules/system.py index 2d571fc..0daf9e3 100644 --- a/modules/system.py +++ b/modules/system.py @@ -10,7 +10,7 @@ from pygemstones.io import file from pygemstones.util import log -from modules import assets, category, config, product, time +from modules import assets, blog, config, product, product_category, time flask_app = None freezer_app = None @@ -68,7 +68,8 @@ def setup(): flask_app.config["FREEZER_DESTINATION"] = config.build_dir flask_app.jinja_env.globals.update(product=product) - flask_app.jinja_env.globals.update(category=category) + flask_app.jinja_env.globals.update(product_category=product_category) + flask_app.jinja_env.globals.update(blog=blog) flask_app.jinja_env.globals.update(file=file) flask_app.jinja_env.globals.update(time=time) diff --git a/modules/time.py b/modules/time.py index def9844..13ee4c6 100644 --- a/modules/time.py +++ b/modules/time.py @@ -1,4 +1,5 @@ import time +from datetime import datetime # ----------------------------------------------------------------------------- @@ -14,3 +15,12 @@ def current_time_ms(): # ----------------------------------------------------------------------------- def current_time_str(): return time.strftime("%Y-%m-%d %H:%M:%S") + + +# ----------------------------------------------------------------------------- +def format_datetime(date_str, date_format): + try: + date_obj = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S") + return date_obj.strftime(date_format) + except ValueError: + return None diff --git a/templates/pages/blog-post.html b/templates/pages/blog-post.html new file mode 100644 index 0000000..e462728 --- /dev/null +++ b/templates/pages/blog-post.html @@ -0,0 +1,63 @@ +{% extends "layouts/base.html" %} + +{% if blog_post.title %} + {% set page_title = blog_post.title %} +{% endif %} + +{% if blog_post.content %} + {% set page_description = blog_post.content | striptags | truncate(160) %} +{% endif %} + +{% if blog_post.tags %} + {% set page_keywords = blog_post.tags | join(", ") %} +{% endif %} + +{% block content %} + +
+
+
+
+ Logo +
+
+ +

+ {{ blog_post.title }} +

+ +
+
+
+
+ + Published on: {{ time.format_datetime(blog_post.published_at, '%Y-%m-%d %H:%M:%S') }} + +
+ +
+ Post image +
+ + {% for post_tag in blog_post.tags %} + + {{ post_tag }} + + {% endfor %} + +

+ {{ blog_post.content | safe }} +

+ + +
+
+
+
+
+ +{% endblock %} diff --git a/templates/pages/blog.html b/templates/pages/blog.html new file mode 100644 index 0000000..cfc95e5 --- /dev/null +++ b/templates/pages/blog.html @@ -0,0 +1,38 @@ +{% extends "layouts/base.html" %} + +{% block content %} + +
+
+
+
+ Logo +
+
+ +

+ {% if pagination_data.total_items > 0 %} + Blog Page {{ page_num }} + {% else %} + Blog + {% endif %} +

+
+
+
+ {% if pagination_data.total_items > 0 %} +
+ {% include "shared/blog/list.html" %} +
+ {% else %} +
+ No posts +
+ {% endif %} + + {% include 'shared/pagination.html' %} +
+
+
+ +{% endblock %} diff --git a/templates/pages/gallery.html b/templates/pages/gallery.html index 9d221f5..35602fc 100644 --- a/templates/pages/gallery.html +++ b/templates/pages/gallery.html @@ -40,21 +40,13 @@

diff --git a/templates/pages/category.html b/templates/pages/product-category.html similarity index 86% rename from templates/pages/category.html rename to templates/pages/product-category.html index 498221c..481b21c 100644 --- a/templates/pages/category.html +++ b/templates/pages/product-category.html @@ -1,6 +1,6 @@ {% extends "layouts/base.html" %} -{% set cat = category.by_token(token) %} +{% set cat = product_category.by_token(token) %} {% if cat.seo_title %} {% set page_title = cat.seo_title %} @@ -29,7 +29,7 @@

{% if cat.products %} - {% include "shared/product/category.html" %} + {% include "shared/product-category/list.html" %} {% endif %} diff --git a/templates/shared/blog/list-item.html b/templates/shared/blog/list-item.html new file mode 100644 index 0000000..9e4e93c --- /dev/null +++ b/templates/shared/blog/list-item.html @@ -0,0 +1,29 @@ +{% set blog_post_link = url_for('blog_post', year=time.format_datetime(blog_post.published_at, '%Y'), month=time.format_datetime(blog_post.published_at, '%m'), day=time.format_datetime(blog_post.published_at, '%d'), token=blog_post.token) %} + +
+
+ + + + +
+
+ {{ time.format_datetime(blog_post.published_at, '%Y-%m-%d %H:%M:%S') }} +
+

+ + {{ blog_post.title }} + +

+

+ {{ blog_post.content | striptags | truncate(150) }} +

+
+ + +
+
diff --git a/templates/shared/blog/list.html b/templates/shared/blog/list.html new file mode 100644 index 0000000..e7a18ac --- /dev/null +++ b/templates/shared/blog/list.html @@ -0,0 +1,3 @@ +{% for blog_post in pagination_data["items"] %} + {% include 'shared/blog/list-item.html' %} +{% endfor %} diff --git a/templates/shared/gallery/list-item.html b/templates/shared/gallery/list-item.html new file mode 100644 index 0000000..d97fea5 --- /dev/null +++ b/templates/shared/gallery/list-item.html @@ -0,0 +1,7 @@ + diff --git a/templates/shared/header.html b/templates/shared/header.html index 2f978ce..7c4651f 100644 --- a/templates/shared/header.html +++ b/templates/shared/header.html @@ -23,6 +23,10 @@ Store + + diff --git a/templates/shared/pagination.html b/templates/shared/pagination.html new file mode 100644 index 0000000..36e6a48 --- /dev/null +++ b/templates/shared/pagination.html @@ -0,0 +1,39 @@ +{% if pagination_data.total_pages > 0 %} + +{% endif %} diff --git a/templates/shared/product-category/list.html b/templates/shared/product-category/list.html new file mode 100644 index 0000000..d9066ae --- /dev/null +++ b/templates/shared/product-category/list.html @@ -0,0 +1,8 @@ +
+
+ {% for product_token in cat.products %} + {% set prod_item = product.by_token(product_token) %} + {% include 'shared/product/list-item.html' %} + {% endfor %} +
+
diff --git a/templates/shared/product/list.html b/templates/shared/product/list.html index 5369046..4e78717 100644 --- a/templates/shared/product/list.html +++ b/templates/shared/product/list.html @@ -1,8 +1,8 @@ -{% for category in kaktos.config.store_data.categories %} +{% for category in kaktos.config.product_category_data %} -
-

- +
+

+ {{ category.name }}

@@ -19,7 +19,7 @@

- Sem produtos + No products