micro-sidebar 1.2.1__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/PKG-INFO +117 -1
- micro_sidebar-2.1.0/README.md +206 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/micro_sidebar.egg-info/PKG-INFO +117 -1
- micro_sidebar-2.1.0/micro_sidebar.egg-info/SOURCES.txt +34 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/pyproject.toml +1 -1
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/setup.py +1 -1
- micro_sidebar-2.1.0/sidebar/apps.py +15 -0
- micro_sidebar-2.1.0/sidebar/context_processors.py +127 -0
- micro_sidebar-2.1.0/sidebar/discovery.py +151 -0
- micro_sidebar-2.1.0/sidebar/static/sidebar/css/theme_picker.css +165 -0
- micro_sidebar-2.1.0/sidebar/static/sidebar/js/theme_picker.js +58 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/static/sidebar/sidebar.css +32 -8
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/static/sidebar/sidebar.js +15 -40
- micro_sidebar-2.1.0/sidebar/static/themes/blue.css +51 -0
- micro_sidebar-2.1.0/sidebar/static/themes/dark.css +501 -0
- micro_sidebar-2.1.0/sidebar/static/themes/gold.css +51 -0
- micro_sidebar-2.1.0/sidebar/static/themes/green.css +63 -0
- micro_sidebar-2.1.0/sidebar/static/themes/light.css +51 -0
- micro_sidebar-2.1.0/sidebar/static/themes/main.css +6 -0
- micro_sidebar-2.1.0/sidebar/static/themes/main.js +41 -0
- micro_sidebar-2.1.0/sidebar/static/themes/red.css +51 -0
- micro_sidebar-2.1.0/sidebar/templates/sidebar/auto.html +13 -0
- micro_sidebar-2.1.0/sidebar/templates/sidebar/extra_groups.html +34 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/templates/sidebar/main.html +25 -2
- micro_sidebar-2.1.0/sidebar/templatetags/__init__.py +1 -0
- micro_sidebar-2.1.0/sidebar/templatetags/sidebar_tags.py +74 -0
- micro_sidebar-1.2.1/README.md +0 -90
- micro_sidebar-1.2.1/micro_sidebar.egg-info/SOURCES.txt +0 -18
- micro_sidebar-1.2.1/sidebar/apps.py +0 -5
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/LICENSE +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/MANIFEST.in +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/micro_sidebar.egg-info/dependency_links.txt +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/micro_sidebar.egg-info/requires.txt +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/micro_sidebar.egg-info/top_level.txt +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/setup.cfg +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/__init__.py +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/migrations/__init__.py +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/urls.py +0 -0
- {micro_sidebar-1.2.1 → micro_sidebar-2.1.0}/sidebar/views.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: micro_sidebar
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A Reusable RTL Django Sidebar App
|
|
5
5
|
Home-page: https://github.com/debeski/micro-sidebar
|
|
6
6
|
Author: DeBeski
|
|
@@ -66,6 +66,119 @@ Requires-Dist: Django>=5.1
|
|
|
66
66
|
]
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
## Auto-Discovery Mode (New in v2.0.0)
|
|
70
|
+
|
|
71
|
+
The sidebar can **automatically discover** your list views and generate navigation items!
|
|
72
|
+
|
|
73
|
+
### Setup
|
|
74
|
+
|
|
75
|
+
1. **Add context processor** to `settings.py`:
|
|
76
|
+
```python
|
|
77
|
+
TEMPLATES = [{
|
|
78
|
+
'OPTIONS': {
|
|
79
|
+
'context_processors': [
|
|
80
|
+
...
|
|
81
|
+
'sidebar.context_processors.sidebar_context',
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. **Use in your sidebar template:**
|
|
88
|
+
```html
|
|
89
|
+
{% extends "sidebar/main.html" %}
|
|
90
|
+
{% load sidebar_tags %}
|
|
91
|
+
|
|
92
|
+
{% block items %}
|
|
93
|
+
{% auto_sidebar %}
|
|
94
|
+
{% endblock %}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
That's it! The sidebar will automatically find all URLs with `list` in their name (e.g., `decree_list`), match them to models, and display `verbose_name_plural` as labels.
|
|
98
|
+
|
|
99
|
+
### Configuration (Optional)
|
|
100
|
+
|
|
101
|
+
Add to `settings.py`:
|
|
102
|
+
```python
|
|
103
|
+
SIDEBAR_AUTO = {
|
|
104
|
+
'ENABLED': True, # Enable auto-discovery
|
|
105
|
+
'URL_PATTERNS': ['list'], # Keywords to match in URL names
|
|
106
|
+
'EXCLUDE_APPS': ['admin', 'auth'], # Apps to exclude
|
|
107
|
+
'EXCLUDE_MODELS': [], # Specific models to exclude
|
|
108
|
+
'CACHE_TIMEOUT': 3600, # Cache timeout in seconds
|
|
109
|
+
'DEFAULT_ICON': 'bi-list', # Default Bootstrap icon
|
|
110
|
+
'DEFAULT_ITEMS': {}, # See "Default Items" section below
|
|
111
|
+
'EXTRA_ITEMS': {}, # See "Extra Items" section below
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Default Items Configuration
|
|
116
|
+
|
|
117
|
+
Use `DEFAULT_ITEMS` to customize auto-discovered items (labels, icons, ordering) without modifying your models:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
SIDEBAR_AUTO = {
|
|
121
|
+
# ...
|
|
122
|
+
'DEFAULT_ITEMS': {
|
|
123
|
+
'decree_list': { # Key is the URL name
|
|
124
|
+
'label': 'Decisions', # Override display label
|
|
125
|
+
'icon': 'bi-gavel', # Override icon
|
|
126
|
+
'order': 10, # Sort order (lower = first)
|
|
127
|
+
},
|
|
128
|
+
'incoming_list': {
|
|
129
|
+
'order': 20, # Only setting order
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Items not in `DEFAULT_ITEMS` will use defaults:
|
|
136
|
+
- **Label**: Model's `verbose_name_plural`
|
|
137
|
+
- **Icon**: `DEFAULT_ICON`
|
|
138
|
+
- **Order**: 100
|
|
139
|
+
|
|
140
|
+
### Extra Items (Non-Model URLs)
|
|
141
|
+
|
|
142
|
+
For URLs that don't map to a model (e.g., management pages), use `EXTRA_ITEMS`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
SIDEBAR_AUTO = {
|
|
146
|
+
# ... other config ...
|
|
147
|
+
'EXTRA_ITEMS': {
|
|
148
|
+
'الإدارة': { # Group name (accordion header)
|
|
149
|
+
'icon': 'bi-gear',
|
|
150
|
+
'items': [
|
|
151
|
+
{
|
|
152
|
+
'url_name': 'manage_sections',
|
|
153
|
+
'label': 'إدارة الأقسام',
|
|
154
|
+
'icon': 'bi-diagram-3',
|
|
155
|
+
'permission': 'documents.manage_sections',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
'url_name': 'manage_users',
|
|
159
|
+
'label': 'إدارة المستخدمين',
|
|
160
|
+
'icon': 'bi-people',
|
|
161
|
+
'permission': 'is_staff', # or a special check to Only show to staff users.
|
|
162
|
+
},
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Then in your sidebar template:
|
|
170
|
+
```html
|
|
171
|
+
{% extends "sidebar/main.html" %}
|
|
172
|
+
{% load sidebar_tags %}
|
|
173
|
+
|
|
174
|
+
{% block items %}
|
|
175
|
+
{% auto_sidebar %}
|
|
176
|
+
{% extra_sidebar %}
|
|
177
|
+
{% endblock %}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Extra items appear at the bottom of the sidebar, grouped in Bootstrap accordions.
|
|
181
|
+
|
|
69
182
|
## Customization
|
|
70
183
|
|
|
71
184
|
### Override Default Menu
|
|
@@ -114,3 +227,6 @@ While it may theoretically work in LTR environments if standard Bootstrap files
|
|
|
114
227
|
| **v1.1.0** | Renamed `content.html` to `main.html` for clarity. Refactored to use `{% block items %}` for easier extension. |
|
|
115
228
|
| **v1.2.0** | **New Theme Implementation:** Redesigned UI with rounded pill-shaped items, tactile micro-animations, and a refined color palette. Improved responsiveness with dynamic top-offset calculations and inline FOUC fixes for small screens. Fixed tooltip stickiness bug. |
|
|
116
229
|
| **v1.2.1** | **Positioning Fix:** Added `align-self: flex-start` to resolve 60px vertical offset in flex containers. Removed legacy `sidebar-top-offset` CSS variable and JS calculations. Added `box-shadow: none` and `outline: none` to accordion buttons to remove focus ring. Fixed page flickering on wider screens by constraining sidebar height with `calc(100vh - header-height)`. |
|
|
230
|
+
| **v1.2.2** | **CSP Compliance:** Added `nonce` attribute support to inline scripts for Content Security Policy compliance. |
|
|
231
|
+
| **v2.0.0** | **Auto-Discovery:** New feature that introspects Django URL patterns and models to automatically generate sidebar navigation items. Adds `{% auto_sidebar %}` template tag, context processor, and configuration options. |
|
|
232
|
+
| **v2.1.0** | **Refactor & Enhancements:** Decoupled customization from models by introducing `DEFAULT_ITEMS` setting for overriding auto-discovered items' labels/icons/order. Added `EXTRA_ITEMS` setting for manual, permission-aware sidebar links grouped in accordions with `{% extra_sidebar %}` tag. Removed deprecated model-level `sidebar_*` attributes. |
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Micro Sidebar - A Reusable RTL Django Sidebar App
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/micro-sidebar/)
|
|
4
|
+
|
|
5
|
+
**RTL** lightweight, reusable django app that provides a dynamic sidebar for your django projects.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- **Django**: >= 5.1
|
|
10
|
+
- **Bootstrap**: 5 (Required for consistent styling)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
1. **Install:**
|
|
15
|
+
```bash
|
|
16
|
+
pip install micro-sidebar
|
|
17
|
+
# OR
|
|
18
|
+
pip install git+https://github.com/debeski/micro-sidebar.git
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **Add to `INSTALLED_APPS`:**
|
|
22
|
+
In your `settings.py`:
|
|
23
|
+
```python
|
|
24
|
+
INSTALLED_APPS = [
|
|
25
|
+
...
|
|
26
|
+
'sidebar',
|
|
27
|
+
...
|
|
28
|
+
]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. **Configure URLs:**
|
|
32
|
+
In your project's `urls.py`:
|
|
33
|
+
```python
|
|
34
|
+
from django.urls import path, include
|
|
35
|
+
|
|
36
|
+
urlpatterns = [
|
|
37
|
+
...
|
|
38
|
+
path('sidebar/', include('sidebar.urls')),
|
|
39
|
+
...
|
|
40
|
+
]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Auto-Discovery Mode (New in v2.0.0)
|
|
44
|
+
|
|
45
|
+
The sidebar can **automatically discover** your list views and generate navigation items!
|
|
46
|
+
|
|
47
|
+
### Setup
|
|
48
|
+
|
|
49
|
+
1. **Add context processor** to `settings.py`:
|
|
50
|
+
```python
|
|
51
|
+
TEMPLATES = [{
|
|
52
|
+
'OPTIONS': {
|
|
53
|
+
'context_processors': [
|
|
54
|
+
...
|
|
55
|
+
'sidebar.context_processors.sidebar_context',
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
}]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
2. **Use in your sidebar template:**
|
|
62
|
+
```html
|
|
63
|
+
{% extends "sidebar/main.html" %}
|
|
64
|
+
{% load sidebar_tags %}
|
|
65
|
+
|
|
66
|
+
{% block items %}
|
|
67
|
+
{% auto_sidebar %}
|
|
68
|
+
{% endblock %}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it! The sidebar will automatically find all URLs with `list` in their name (e.g., `decree_list`), match them to models, and display `verbose_name_plural` as labels.
|
|
72
|
+
|
|
73
|
+
### Configuration (Optional)
|
|
74
|
+
|
|
75
|
+
Add to `settings.py`:
|
|
76
|
+
```python
|
|
77
|
+
SIDEBAR_AUTO = {
|
|
78
|
+
'ENABLED': True, # Enable auto-discovery
|
|
79
|
+
'URL_PATTERNS': ['list'], # Keywords to match in URL names
|
|
80
|
+
'EXCLUDE_APPS': ['admin', 'auth'], # Apps to exclude
|
|
81
|
+
'EXCLUDE_MODELS': [], # Specific models to exclude
|
|
82
|
+
'CACHE_TIMEOUT': 3600, # Cache timeout in seconds
|
|
83
|
+
'DEFAULT_ICON': 'bi-list', # Default Bootstrap icon
|
|
84
|
+
'DEFAULT_ITEMS': {}, # See "Default Items" section below
|
|
85
|
+
'EXTRA_ITEMS': {}, # See "Extra Items" section below
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Default Items Configuration
|
|
90
|
+
|
|
91
|
+
Use `DEFAULT_ITEMS` to customize auto-discovered items (labels, icons, ordering) without modifying your models:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
SIDEBAR_AUTO = {
|
|
95
|
+
# ...
|
|
96
|
+
'DEFAULT_ITEMS': {
|
|
97
|
+
'decree_list': { # Key is the URL name
|
|
98
|
+
'label': 'Decisions', # Override display label
|
|
99
|
+
'icon': 'bi-gavel', # Override icon
|
|
100
|
+
'order': 10, # Sort order (lower = first)
|
|
101
|
+
},
|
|
102
|
+
'incoming_list': {
|
|
103
|
+
'order': 20, # Only setting order
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Items not in `DEFAULT_ITEMS` will use defaults:
|
|
110
|
+
- **Label**: Model's `verbose_name_plural`
|
|
111
|
+
- **Icon**: `DEFAULT_ICON`
|
|
112
|
+
- **Order**: 100
|
|
113
|
+
|
|
114
|
+
### Extra Items (Non-Model URLs)
|
|
115
|
+
|
|
116
|
+
For URLs that don't map to a model (e.g., management pages), use `EXTRA_ITEMS`:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
SIDEBAR_AUTO = {
|
|
120
|
+
# ... other config ...
|
|
121
|
+
'EXTRA_ITEMS': {
|
|
122
|
+
'الإدارة': { # Group name (accordion header)
|
|
123
|
+
'icon': 'bi-gear',
|
|
124
|
+
'items': [
|
|
125
|
+
{
|
|
126
|
+
'url_name': 'manage_sections',
|
|
127
|
+
'label': 'إدارة الأقسام',
|
|
128
|
+
'icon': 'bi-diagram-3',
|
|
129
|
+
'permission': 'documents.manage_sections',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
'url_name': 'manage_users',
|
|
133
|
+
'label': 'إدارة المستخدمين',
|
|
134
|
+
'icon': 'bi-people',
|
|
135
|
+
'permission': 'is_staff', # or a special check to Only show to staff users.
|
|
136
|
+
},
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Then in your sidebar template:
|
|
144
|
+
```html
|
|
145
|
+
{% extends "sidebar/main.html" %}
|
|
146
|
+
{% load sidebar_tags %}
|
|
147
|
+
|
|
148
|
+
{% block items %}
|
|
149
|
+
{% auto_sidebar %}
|
|
150
|
+
{% extra_sidebar %}
|
|
151
|
+
{% endblock %}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Extra items appear at the bottom of the sidebar, grouped in Bootstrap accordions.
|
|
155
|
+
|
|
156
|
+
## Customization
|
|
157
|
+
|
|
158
|
+
### Override Default Menu
|
|
159
|
+
The sidebar uses a block-based template system. To define your own menu items:
|
|
160
|
+
|
|
161
|
+
1. Create a new template (e.g., `templates/sidebar_menu.html`).
|
|
162
|
+
2. Extend `sidebar/main.html`.
|
|
163
|
+
3. Override the `{% block items %}`.
|
|
164
|
+
|
|
165
|
+
**Example `sidebar_menu.html`:**
|
|
166
|
+
```html
|
|
167
|
+
{% extends "sidebar/main.html" %}
|
|
168
|
+
|
|
169
|
+
{% block items %}
|
|
170
|
+
<a href="{% url 'home' %}" class="list-group-item list-group-item-action">
|
|
171
|
+
<i class="bi bi-house me-2" style="font-size: 24px;"></i>
|
|
172
|
+
<span>Home</span>
|
|
173
|
+
</a>
|
|
174
|
+
<a href="{% url 'settings' %}" class="list-group-item list-group-item-action">
|
|
175
|
+
<i class="bi bi-gear me-2" style="font-size: 24px;"></i>
|
|
176
|
+
<span>Settings</span>
|
|
177
|
+
</a>
|
|
178
|
+
{% endblock %}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Then, include your custom template in `base.html`:
|
|
182
|
+
```html
|
|
183
|
+
{% include "sidebar_menu.html" %}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Positioning
|
|
187
|
+
The sidebar is sticky by default. If your app has a top navigation bar (titlebar), the sidebar will automatically adjust its position below it on small screens. If no titlebar is detected, it will stick to the top of the viewport.
|
|
188
|
+
|
|
189
|
+
## RTL / LTR Support
|
|
190
|
+
This sidebar is primarily designed for **RTL (Right-to-Left)** interfaces (e.g., Arabic).
|
|
191
|
+
While it may theoretically work in LTR environments if standard Bootstrap files are used instead of RTL versions, this has **not been fully tested**.
|
|
192
|
+
> *Future updates are planned to support dynamic language switching between RTL and LTR.*
|
|
193
|
+
|
|
194
|
+
## Version History
|
|
195
|
+
|
|
196
|
+
| Version | Changes |
|
|
197
|
+
| :--- | :--- |
|
|
198
|
+
| **v1.0.0** | Initial Release. |
|
|
199
|
+
| **v1.0.1** | Fixed titlebar positioning bug causing overlap/gaps. |
|
|
200
|
+
| **v1.0.2** | Improved documentation clarity and added usage instructions. |
|
|
201
|
+
| **v1.1.0** | Renamed `content.html` to `main.html` for clarity. Refactored to use `{% block items %}` for easier extension. |
|
|
202
|
+
| **v1.2.0** | **New Theme Implementation:** Redesigned UI with rounded pill-shaped items, tactile micro-animations, and a refined color palette. Improved responsiveness with dynamic top-offset calculations and inline FOUC fixes for small screens. Fixed tooltip stickiness bug. |
|
|
203
|
+
| **v1.2.1** | **Positioning Fix:** Added `align-self: flex-start` to resolve 60px vertical offset in flex containers. Removed legacy `sidebar-top-offset` CSS variable and JS calculations. Added `box-shadow: none` and `outline: none` to accordion buttons to remove focus ring. Fixed page flickering on wider screens by constraining sidebar height with `calc(100vh - header-height)`. |
|
|
204
|
+
| **v1.2.2** | **CSP Compliance:** Added `nonce` attribute support to inline scripts for Content Security Policy compliance. |
|
|
205
|
+
| **v2.0.0** | **Auto-Discovery:** New feature that introspects Django URL patterns and models to automatically generate sidebar navigation items. Adds `{% auto_sidebar %}` template tag, context processor, and configuration options. |
|
|
206
|
+
| **v2.1.0** | **Refactor & Enhancements:** Decoupled customization from models by introducing `DEFAULT_ITEMS` setting for overriding auto-discovered items' labels/icons/order. Added `EXTRA_ITEMS` setting for manual, permission-aware sidebar links grouped in accordions with `{% extra_sidebar %}` tag. Removed deprecated model-level `sidebar_*` attributes. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: micro-sidebar
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A Reusable RTL Django Sidebar App
|
|
5
5
|
Home-page: https://github.com/debeski/micro-sidebar
|
|
6
6
|
Author: DeBeski
|
|
@@ -66,6 +66,119 @@ Requires-Dist: Django>=5.1
|
|
|
66
66
|
]
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
## Auto-Discovery Mode (New in v2.0.0)
|
|
70
|
+
|
|
71
|
+
The sidebar can **automatically discover** your list views and generate navigation items!
|
|
72
|
+
|
|
73
|
+
### Setup
|
|
74
|
+
|
|
75
|
+
1. **Add context processor** to `settings.py`:
|
|
76
|
+
```python
|
|
77
|
+
TEMPLATES = [{
|
|
78
|
+
'OPTIONS': {
|
|
79
|
+
'context_processors': [
|
|
80
|
+
...
|
|
81
|
+
'sidebar.context_processors.sidebar_context',
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. **Use in your sidebar template:**
|
|
88
|
+
```html
|
|
89
|
+
{% extends "sidebar/main.html" %}
|
|
90
|
+
{% load sidebar_tags %}
|
|
91
|
+
|
|
92
|
+
{% block items %}
|
|
93
|
+
{% auto_sidebar %}
|
|
94
|
+
{% endblock %}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
That's it! The sidebar will automatically find all URLs with `list` in their name (e.g., `decree_list`), match them to models, and display `verbose_name_plural` as labels.
|
|
98
|
+
|
|
99
|
+
### Configuration (Optional)
|
|
100
|
+
|
|
101
|
+
Add to `settings.py`:
|
|
102
|
+
```python
|
|
103
|
+
SIDEBAR_AUTO = {
|
|
104
|
+
'ENABLED': True, # Enable auto-discovery
|
|
105
|
+
'URL_PATTERNS': ['list'], # Keywords to match in URL names
|
|
106
|
+
'EXCLUDE_APPS': ['admin', 'auth'], # Apps to exclude
|
|
107
|
+
'EXCLUDE_MODELS': [], # Specific models to exclude
|
|
108
|
+
'CACHE_TIMEOUT': 3600, # Cache timeout in seconds
|
|
109
|
+
'DEFAULT_ICON': 'bi-list', # Default Bootstrap icon
|
|
110
|
+
'DEFAULT_ITEMS': {}, # See "Default Items" section below
|
|
111
|
+
'EXTRA_ITEMS': {}, # See "Extra Items" section below
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Default Items Configuration
|
|
116
|
+
|
|
117
|
+
Use `DEFAULT_ITEMS` to customize auto-discovered items (labels, icons, ordering) without modifying your models:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
SIDEBAR_AUTO = {
|
|
121
|
+
# ...
|
|
122
|
+
'DEFAULT_ITEMS': {
|
|
123
|
+
'decree_list': { # Key is the URL name
|
|
124
|
+
'label': 'Decisions', # Override display label
|
|
125
|
+
'icon': 'bi-gavel', # Override icon
|
|
126
|
+
'order': 10, # Sort order (lower = first)
|
|
127
|
+
},
|
|
128
|
+
'incoming_list': {
|
|
129
|
+
'order': 20, # Only setting order
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Items not in `DEFAULT_ITEMS` will use defaults:
|
|
136
|
+
- **Label**: Model's `verbose_name_plural`
|
|
137
|
+
- **Icon**: `DEFAULT_ICON`
|
|
138
|
+
- **Order**: 100
|
|
139
|
+
|
|
140
|
+
### Extra Items (Non-Model URLs)
|
|
141
|
+
|
|
142
|
+
For URLs that don't map to a model (e.g., management pages), use `EXTRA_ITEMS`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
SIDEBAR_AUTO = {
|
|
146
|
+
# ... other config ...
|
|
147
|
+
'EXTRA_ITEMS': {
|
|
148
|
+
'الإدارة': { # Group name (accordion header)
|
|
149
|
+
'icon': 'bi-gear',
|
|
150
|
+
'items': [
|
|
151
|
+
{
|
|
152
|
+
'url_name': 'manage_sections',
|
|
153
|
+
'label': 'إدارة الأقسام',
|
|
154
|
+
'icon': 'bi-diagram-3',
|
|
155
|
+
'permission': 'documents.manage_sections',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
'url_name': 'manage_users',
|
|
159
|
+
'label': 'إدارة المستخدمين',
|
|
160
|
+
'icon': 'bi-people',
|
|
161
|
+
'permission': 'is_staff', # or a special check to Only show to staff users.
|
|
162
|
+
},
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Then in your sidebar template:
|
|
170
|
+
```html
|
|
171
|
+
{% extends "sidebar/main.html" %}
|
|
172
|
+
{% load sidebar_tags %}
|
|
173
|
+
|
|
174
|
+
{% block items %}
|
|
175
|
+
{% auto_sidebar %}
|
|
176
|
+
{% extra_sidebar %}
|
|
177
|
+
{% endblock %}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Extra items appear at the bottom of the sidebar, grouped in Bootstrap accordions.
|
|
181
|
+
|
|
69
182
|
## Customization
|
|
70
183
|
|
|
71
184
|
### Override Default Menu
|
|
@@ -114,3 +227,6 @@ While it may theoretically work in LTR environments if standard Bootstrap files
|
|
|
114
227
|
| **v1.1.0** | Renamed `content.html` to `main.html` for clarity. Refactored to use `{% block items %}` for easier extension. |
|
|
115
228
|
| **v1.2.0** | **New Theme Implementation:** Redesigned UI with rounded pill-shaped items, tactile micro-animations, and a refined color palette. Improved responsiveness with dynamic top-offset calculations and inline FOUC fixes for small screens. Fixed tooltip stickiness bug. |
|
|
116
229
|
| **v1.2.1** | **Positioning Fix:** Added `align-self: flex-start` to resolve 60px vertical offset in flex containers. Removed legacy `sidebar-top-offset` CSS variable and JS calculations. Added `box-shadow: none` and `outline: none` to accordion buttons to remove focus ring. Fixed page flickering on wider screens by constraining sidebar height with `calc(100vh - header-height)`. |
|
|
230
|
+
| **v1.2.2** | **CSP Compliance:** Added `nonce` attribute support to inline scripts for Content Security Policy compliance. |
|
|
231
|
+
| **v2.0.0** | **Auto-Discovery:** New feature that introspects Django URL patterns and models to automatically generate sidebar navigation items. Adds `{% auto_sidebar %}` template tag, context processor, and configuration options. |
|
|
232
|
+
| **v2.1.0** | **Refactor & Enhancements:** Decoupled customization from models by introducing `DEFAULT_ITEMS` setting for overriding auto-discovered items' labels/icons/order. Added `EXTRA_ITEMS` setting for manual, permission-aware sidebar links grouped in accordions with `{% extra_sidebar %}` tag. Removed deprecated model-level `sidebar_*` attributes. |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
setup.py
|
|
6
|
+
micro_sidebar.egg-info/PKG-INFO
|
|
7
|
+
micro_sidebar.egg-info/SOURCES.txt
|
|
8
|
+
micro_sidebar.egg-info/dependency_links.txt
|
|
9
|
+
micro_sidebar.egg-info/requires.txt
|
|
10
|
+
micro_sidebar.egg-info/top_level.txt
|
|
11
|
+
sidebar/__init__.py
|
|
12
|
+
sidebar/apps.py
|
|
13
|
+
sidebar/context_processors.py
|
|
14
|
+
sidebar/discovery.py
|
|
15
|
+
sidebar/urls.py
|
|
16
|
+
sidebar/views.py
|
|
17
|
+
sidebar/migrations/__init__.py
|
|
18
|
+
sidebar/static/sidebar/sidebar.css
|
|
19
|
+
sidebar/static/sidebar/sidebar.js
|
|
20
|
+
sidebar/static/sidebar/css/theme_picker.css
|
|
21
|
+
sidebar/static/sidebar/js/theme_picker.js
|
|
22
|
+
sidebar/static/themes/blue.css
|
|
23
|
+
sidebar/static/themes/dark.css
|
|
24
|
+
sidebar/static/themes/gold.css
|
|
25
|
+
sidebar/static/themes/green.css
|
|
26
|
+
sidebar/static/themes/light.css
|
|
27
|
+
sidebar/static/themes/main.css
|
|
28
|
+
sidebar/static/themes/main.js
|
|
29
|
+
sidebar/static/themes/red.css
|
|
30
|
+
sidebar/templates/sidebar/auto.html
|
|
31
|
+
sidebar/templates/sidebar/extra_groups.html
|
|
32
|
+
sidebar/templates/sidebar/main.html
|
|
33
|
+
sidebar/templatetags/__init__.py
|
|
34
|
+
sidebar/templatetags/sidebar_tags.py
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SidebarConfig(AppConfig):
|
|
5
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
|
6
|
+
name = 'sidebar'
|
|
7
|
+
|
|
8
|
+
def ready(self):
|
|
9
|
+
"""
|
|
10
|
+
Called when Django starts.
|
|
11
|
+
Import discovery module to ensure it's available.
|
|
12
|
+
"""
|
|
13
|
+
# Import to make discovery available
|
|
14
|
+
from . import discovery # noqa: F401
|
|
15
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context processor for auto-discovered sidebar items.
|
|
3
|
+
|
|
4
|
+
Injects sidebar navigation items into every request context,
|
|
5
|
+
filtered by user permissions.
|
|
6
|
+
"""
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
from django.core.cache import cache
|
|
10
|
+
from django.urls import reverse, NoReverseMatch
|
|
11
|
+
from .discovery import discover_list_urls, get_sidebar_config
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _get_config_hash(config):
|
|
15
|
+
"""Generate a hash of the config for cache key."""
|
|
16
|
+
# Exclude EXTRA_ITEMS from hash since they're processed separately
|
|
17
|
+
config_copy = {k: v for k, v in config.items() if k != 'EXTRA_ITEMS'}
|
|
18
|
+
config_str = json.dumps(config_copy, sort_keys=True)
|
|
19
|
+
return hashlib.md5(config_str.encode()).hexdigest()[:8]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _process_extra_items(config, request):
|
|
23
|
+
"""
|
|
24
|
+
Process EXTRA_ITEMS config into sidebar-ready format.
|
|
25
|
+
|
|
26
|
+
Returns dict of groups, each with icon and list of items with resolved URLs.
|
|
27
|
+
"""
|
|
28
|
+
extra_items = config.get('EXTRA_ITEMS', {})
|
|
29
|
+
processed_groups = {}
|
|
30
|
+
|
|
31
|
+
for group_name, group_config in extra_items.items():
|
|
32
|
+
group_icon = group_config.get('icon', 'bi-gear')
|
|
33
|
+
items = []
|
|
34
|
+
|
|
35
|
+
for item in group_config.get('items', []):
|
|
36
|
+
url_name = item.get('url_name', '')
|
|
37
|
+
|
|
38
|
+
# Check permission if specified
|
|
39
|
+
permission = item.get('permission')
|
|
40
|
+
if permission:
|
|
41
|
+
if permission == 'is_staff' and not request.user.is_staff:
|
|
42
|
+
continue
|
|
43
|
+
elif permission == 'is_superuser' and not request.user.is_superuser:
|
|
44
|
+
continue
|
|
45
|
+
elif permission not in ['is_staff', 'is_superuser'] and not request.user.has_perm(permission):
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
# Resolve URL
|
|
49
|
+
try:
|
|
50
|
+
url = reverse(url_name)
|
|
51
|
+
active = request.path == url or request.path.startswith(url.rstrip('/') + '/')
|
|
52
|
+
except NoReverseMatch:
|
|
53
|
+
url = '#'
|
|
54
|
+
active = False
|
|
55
|
+
|
|
56
|
+
items.append({
|
|
57
|
+
'url_name': url_name,
|
|
58
|
+
'url': url,
|
|
59
|
+
'label': item.get('label', url_name),
|
|
60
|
+
'icon': item.get('icon', 'bi-link'),
|
|
61
|
+
'active': active,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
if items: # Only add group if it has visible items
|
|
65
|
+
processed_groups[group_name] = {
|
|
66
|
+
'icon': group_icon,
|
|
67
|
+
'items': items,
|
|
68
|
+
'has_active': any(item['active'] for item in items),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return processed_groups
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def sidebar_context(request):
|
|
75
|
+
"""
|
|
76
|
+
Add auto-discovered sidebar items to template context.
|
|
77
|
+
|
|
78
|
+
Items are cached for performance and filtered by user permissions.
|
|
79
|
+
Only authenticated users see sidebar items, and only items they
|
|
80
|
+
have view permission for.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Dictionary with 'sidebar_auto_items' and 'sidebar_extra_groups' keys.
|
|
84
|
+
"""
|
|
85
|
+
config = get_sidebar_config()
|
|
86
|
+
# Include config hash in cache key so settings changes invalidate cache
|
|
87
|
+
cache_key = f'sidebar_auto_items_{_get_config_hash(config)}'
|
|
88
|
+
items = cache.get(cache_key)
|
|
89
|
+
|
|
90
|
+
if items is None:
|
|
91
|
+
items = discover_list_urls()
|
|
92
|
+
cache.set(cache_key, items, timeout=config['CACHE_TIMEOUT'])
|
|
93
|
+
|
|
94
|
+
# Filter by user permissions
|
|
95
|
+
if request.user.is_authenticated:
|
|
96
|
+
if request.user.is_superuser:
|
|
97
|
+
# Superusers see everything
|
|
98
|
+
visible = items
|
|
99
|
+
else:
|
|
100
|
+
visible = []
|
|
101
|
+
for item in items:
|
|
102
|
+
if not item.get('permissions'):
|
|
103
|
+
visible.append(item)
|
|
104
|
+
elif any(request.user.has_perm(p) for p in item['permissions']):
|
|
105
|
+
visible.append(item)
|
|
106
|
+
items = visible
|
|
107
|
+
|
|
108
|
+
# Process extra items for authenticated users
|
|
109
|
+
extra_groups = _process_extra_items(config, request)
|
|
110
|
+
else:
|
|
111
|
+
items = []
|
|
112
|
+
extra_groups = {}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
'sidebar_auto_items': items,
|
|
116
|
+
'sidebar_extra_groups': extra_groups,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def clear_sidebar_cache():
|
|
121
|
+
"""
|
|
122
|
+
Clear the sidebar items cache.
|
|
123
|
+
|
|
124
|
+
Call this when models or URLs change and sidebar needs refresh.
|
|
125
|
+
"""
|
|
126
|
+
cache.delete('sidebar_auto_items')
|
|
127
|
+
|