gitea_ui/docs/views.md
Mahmoud Emad 4cc61a955d feat: Add .gitignore and initial project structure
- Add a comprehensive .gitignore to manage project files.
- Create the basic project structure including Cargo.toml,
  LICENSE, and README.md.
- Add basic project documentation.
2025-05-11 09:09:45 +03:00

241 lines
6.1 KiB
Markdown

# Views Guide
This guide provides detailed instructions on how to create and customize views in the Hostbasket application.
## Table of Contents
1. [Introduction to Tera Templates](#introduction-to-tera-templates)
2. [Template Structure](#template-structure)
3. [Creating a New View](#creating-a-new-view)
4. [Template Inheritance](#template-inheritance)
5. [Using Variables](#using-variables)
6. [Control Structures](#control-structures)
7. [Filters](#filters)
8. [Macros](#macros)
9. [Custom Functions](#custom-functions)
10. [Best Practices](#best-practices)
## Introduction to Tera Templates
Hostbasket uses [Tera](https://tera.netlify.app/) as its template engine. Tera is inspired by Jinja2 and Django templates and provides a powerful way to create dynamic HTML pages.
## Template Structure
Templates are stored in the `src/views` directory. The directory structure typically follows the application's features:
```
src/views/
├── auth/
│ ├── login.html
│ └── register.html
├── home/
│ ├── index.html
│ ├── about.html
│ └── contact.html
├── tickets/
│ ├── index.html
│ ├── new.html
│ └── show.html
├── assets/
│ ├── index.html
│ ├── create.html
│ └── detail.html
└── base.html
```
## Creating a New View
To create a new view:
1. Create a new HTML file in the appropriate directory under `src/views`
2. Use template inheritance to extend the base template
3. Add your content within the appropriate blocks
Example:
```html
{% extends "base.html" %}
{% block title %}My New Page{% endblock %}
{% block content %}
<div class="container">
<h1>Welcome to My New Page</h1>
<p>This is a custom page.</p>
</div>
{% endblock %}
```
## Template Inheritance
Tera supports template inheritance, which allows you to define a base template with common elements and extend it in child templates.
### Base Template
The base template (`base.html`) typically contains the HTML structure, header, footer, and navigation menu:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Hostbasket{% endblock %}</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/styles.css">
{% block head %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<!-- Navigation content -->
</nav>
<main>
{% block content %}{% endblock %}
</main>
<footer class="footer mt-auto py-3 bg-light">
<!-- Footer content -->
</footer>
<script src="/static/js/bootstrap.bundle.min.js"></script>
{% block scripts %}{% endblock %}
</body>
</html>
```
### Child Template
Child templates extend the base template and override specific blocks:
```html
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<div class="container">
<h1>Welcome to Hostbasket</h1>
<p>This is the home page.</p>
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/home.js"></script>
{% endblock %}
```
## Using Variables
You can pass variables from your controller to the template and use them in your HTML:
### In the Controller
```rust
pub async fn index(tmpl: web::Data<Tera>) -> Result<impl Responder> {
let mut ctx = tera::Context::new();
ctx.insert("title", "Welcome to Hostbasket");
ctx.insert("user_name", "John Doe");
render_template(&tmpl, "home/index.html", &ctx)
}
```
### In the Template
```html
<h1>{{ title }}</h1>
<p>Hello, {{ user_name }}!</p>
```
## Control Structures
Tera provides various control structures for conditional rendering and iteration.
### Conditionals
```html
{% if user %}
<p>Welcome, {{ user.name }}!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
```
### Loops
```html
<ul>
{% for item in items %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>
{% if items is empty %}
<p>No items found.</p>
{% endif %}
```
## Filters
Filters transform the values of variables:
```html
<p>{{ user.name | upper }}</p>
<p>{{ user.bio | truncate(length=100) }}</p>
<p>{{ user.created_at | date(format="%Y-%m-%d") }}</p>
```
## Macros
Macros are reusable template fragments:
```html
{% macro input(name, value='', type='text', label='') %}
<div class="mb-3">
{% if label %}
<label for="{{ name }}" class="form-label">{{ label }}</label>
{% endif %}
<input type="{{ type }}" name="{{ name }}" id="{{ name }}" value="{{ value }}" class="form-control">
</div>
{% endmacro %}
<!-- Usage -->
{{ input(name="email", type="email", label="Email Address") }}
```
## Custom Functions
You can register custom functions in Rust and use them in your templates:
### In Rust
```rust
fn register_tera_functions(tera: &mut Tera) {
tera.register_function("format_date", format_date);
}
fn format_date(args: &HashMap<String, Value>) -> Result<Value, tera::Error> {
// Implementation
}
```
### In the Template
```html
<p>{{ format_date(date=user.created_at, format="%B %d, %Y") }}</p>
```
## Best Practices
1. **Use Template Inheritance**: Extend the base template to maintain consistency across pages.
2. **Organize Templates by Feature**: Group related templates in subdirectories.
3. **Keep Templates Simple**: Move complex logic to the controller or custom functions.
4. **Use Meaningful Variable Names**: Choose descriptive names for variables and blocks.
5. **Comment Your Templates**: Add comments to explain complex sections.
6. **Validate User Input**: Always validate and sanitize user input in the controller before passing it to the template.
7. **Use Partials for Reusable Components**: Extract common components into separate files and include them where needed.
8. **Optimize for Performance**: Minimize the use of expensive operations in templates.
9. **Test Your Templates**: Ensure that your templates render correctly with different data.
10. **Follow Accessibility Guidelines**: Make your templates accessible to all users.