aa-kanban 0.5.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.
- aa_kanban-0.5.0/.gitignore +25 -0
- aa_kanban-0.5.0/LICENSE +21 -0
- aa_kanban-0.5.0/PKG-INFO +96 -0
- aa_kanban-0.5.0/README.md +50 -0
- aa_kanban-0.5.0/aa_kanban/__init__.py +3 -0
- aa_kanban-0.5.0/aa_kanban/admin.py +129 -0
- aa_kanban-0.5.0/aa_kanban/apps.py +8 -0
- aa_kanban-0.5.0/aa_kanban/auth_hooks.py +33 -0
- aa_kanban-0.5.0/aa_kanban/migrations/0001_initial.py +123 -0
- aa_kanban-0.5.0/aa_kanban/migrations/0002_kanbangroup_alter_board_view_groups_and_more.py +38 -0
- aa_kanban-0.5.0/aa_kanban/migrations/0003_kanbansetting_board_discord_webhook_cards.py +29 -0
- aa_kanban-0.5.0/aa_kanban/migrations/__init__.py +1 -0
- aa_kanban-0.5.0/aa_kanban/models.py +282 -0
- aa_kanban-0.5.0/aa_kanban/permissions.py +77 -0
- aa_kanban-0.5.0/aa_kanban/static/aa_kanban/css/kanban.css +50 -0
- aa_kanban-0.5.0/aa_kanban/static/aa_kanban/js/kanban.js +144 -0
- aa_kanban-0.5.0/aa_kanban/static/aa_kanban/libs/Sortable.min.js +2 -0
- aa_kanban-0.5.0/aa_kanban/static/aa_kanban/libs/htmx.min.js +1 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/base.html +14 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/board_detail.html +276 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/index.html +103 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/board_column.html +48 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/board_labels_modal.html +67 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/card_assignees.html +49 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/card_comments.html +24 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/card_item.html +40 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/card_labels.html +57 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/card_modal_content.html +108 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/column_header.html +27 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/create_board_form.html +88 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/edit_board_form.html +96 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/group_list.html +46 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/partials/group_users_modal.html +52 -0
- aa_kanban-0.5.0/aa_kanban/templates/aa_kanban/settings.html +68 -0
- aa_kanban-0.5.0/aa_kanban/tests/__init__.py +1 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_api.py +364 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_auth_hooks.py +56 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_board_management.py +357 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_modal.py +279 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_models.py +179 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_permissions.py +112 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_smoke.py +19 -0
- aa_kanban-0.5.0/aa_kanban/tests/test_views.py +216 -0
- aa_kanban-0.5.0/aa_kanban/urls.py +90 -0
- aa_kanban-0.5.0/aa_kanban/utils.py +26 -0
- aa_kanban-0.5.0/aa_kanban/views.py +198 -0
- aa_kanban-0.5.0/aa_kanban/views_api.py +502 -0
- aa_kanban-0.5.0/aa_kanban/views_settings.py +95 -0
- aa_kanban-0.5.0/pyproject.toml +73 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/build/
|
|
2
|
+
/dist/
|
|
3
|
+
/*.egg-info/
|
|
4
|
+
.idea/
|
|
5
|
+
.tox/
|
|
6
|
+
htmlcov/
|
|
7
|
+
node_modules/
|
|
8
|
+
|
|
9
|
+
*.log
|
|
10
|
+
*.tmp
|
|
11
|
+
*.bak
|
|
12
|
+
*.old
|
|
13
|
+
__pycache__
|
|
14
|
+
.coverage
|
|
15
|
+
/coverage.xml
|
|
16
|
+
alliance_auth.sqlite3
|
|
17
|
+
db.sqlite3
|
|
18
|
+
*.sqlite3
|
|
19
|
+
tmp_env/
|
|
20
|
+
.venv/
|
|
21
|
+
|
|
22
|
+
# Tijdelijke (scratch) scripts in de root
|
|
23
|
+
/*test*.py
|
|
24
|
+
/append_task.py
|
|
25
|
+
/make_migrations.py
|
aa_kanban-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maddog Broekman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
aa_kanban-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aa-kanban
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Kanban Plugin for Alliance Auth
|
|
5
|
+
Author-email: Maddog Broekman <maddogbroekman@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Maddog Broekman
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Keywords: aa_kanban,allianceauth
|
|
29
|
+
Classifier: Environment :: Web Environment
|
|
30
|
+
Classifier: Framework :: Django
|
|
31
|
+
Classifier: Framework :: Django :: 5.2
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Operating System :: OS Independent
|
|
35
|
+
Classifier: Programming Language :: Python
|
|
36
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
42
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
43
|
+
Requires-Python: <3.14,>=3.10
|
|
44
|
+
Requires-Dist: allianceauth>=5
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# AA Kanban
|
|
48
|
+
|
|
49
|
+
Alliance Auth plugin for native Kanban boards.
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Native Kanban boards** with an intuitive drag-and-drop interface.
|
|
54
|
+
- **Permission management** per board (read-only and write groups).
|
|
55
|
+
- **Global Discord Webhooks** (Admin panel): Receive notifications when new boards are created.
|
|
56
|
+
- **Board-specific Discord Webhooks** (Admin panel): Receive notifications when cards are moved across lists on a specific board.
|
|
57
|
+
- **Direct Messages (DMs)**: Discord DM notifications are sent directly to users when they are assigned to or removed from cards (requires the `aadiscordbot` app to be installed and active).
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install aa-kanban
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Add the app to your `local.py`:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
INSTALLED_APPS += [
|
|
69
|
+
"aa_kanban",
|
|
70
|
+
]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Run the database migrations:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python manage.py migrate
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Gather static files:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python manage.py collectstatic
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Restart your supervisor services to load the new code (e.g., gunicorn and celery).
|
|
86
|
+
|
|
87
|
+
## Discord Webhooks Configuration
|
|
88
|
+
|
|
89
|
+
To receive updates in your Discord channels, you can configure webhooks in the Django Admin panel:
|
|
90
|
+
|
|
91
|
+
1. **Global Board Creation Webhook**:
|
|
92
|
+
- Go to **Admin** > **Kanban Settings** > **Global Kanban Settings**.
|
|
93
|
+
- Fill in the **Board creation webhook** field with your Discord Webhook URL. You will receive a message whenever a new board is created.
|
|
94
|
+
2. **Board-Specific Card Movement Webhooks**:
|
|
95
|
+
- Go to **Admin** > **Boards** and edit a specific board.
|
|
96
|
+
- Fill in the **Discord webhook cards** field. Any card movements between lists on this board will be posted to this webhook.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# AA Kanban
|
|
2
|
+
|
|
3
|
+
Alliance Auth plugin for native Kanban boards.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Native Kanban boards** with an intuitive drag-and-drop interface.
|
|
8
|
+
- **Permission management** per board (read-only and write groups).
|
|
9
|
+
- **Global Discord Webhooks** (Admin panel): Receive notifications when new boards are created.
|
|
10
|
+
- **Board-specific Discord Webhooks** (Admin panel): Receive notifications when cards are moved across lists on a specific board.
|
|
11
|
+
- **Direct Messages (DMs)**: Discord DM notifications are sent directly to users when they are assigned to or removed from cards (requires the `aadiscordbot` app to be installed and active).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install aa-kanban
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Add the app to your `local.py`:
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
INSTALLED_APPS += [
|
|
23
|
+
"aa_kanban",
|
|
24
|
+
]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run the database migrations:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python manage.py migrate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Gather static files:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python manage.py collectstatic
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Restart your supervisor services to load the new code (e.g., gunicorn and celery).
|
|
40
|
+
|
|
41
|
+
## Discord Webhooks Configuration
|
|
42
|
+
|
|
43
|
+
To receive updates in your Discord channels, you can configure webhooks in the Django Admin panel:
|
|
44
|
+
|
|
45
|
+
1. **Global Board Creation Webhook**:
|
|
46
|
+
- Go to **Admin** > **Kanban Settings** > **Global Kanban Settings**.
|
|
47
|
+
- Fill in the **Board creation webhook** field with your Discord Webhook URL. You will receive a message whenever a new board is created.
|
|
48
|
+
2. **Board-Specific Card Movement Webhooks**:
|
|
49
|
+
- Go to **Admin** > **Boards** and edit a specific board.
|
|
50
|
+
- Fill in the **Discord webhook cards** field. Any card movements between lists on this board will be posted to this webhook.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Admin configuration for aa_kanban.
|
|
2
|
+
|
|
3
|
+
Business-functionaliteit (boards, lijsten, cards, labels) wordt beheerd via
|
|
4
|
+
de frontend. De admin is hier read-only voor overzicht/debug. Alleen Comments
|
|
5
|
+
blijven bewerkbaar voor moderatie-doeleinden.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from django.contrib import admin
|
|
9
|
+
|
|
10
|
+
from .models import Board, Card, Comment, Label, List, KanbanSetting
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@admin.register(Board)
|
|
14
|
+
class BoardAdmin(admin.ModelAdmin):
|
|
15
|
+
"""Read-only board overview, except for technical webhook settings."""
|
|
16
|
+
|
|
17
|
+
list_display = ("name", "slug", "created_by", "created_at", "updated_at")
|
|
18
|
+
search_fields = ("name", "description")
|
|
19
|
+
readonly_fields = (
|
|
20
|
+
"name",
|
|
21
|
+
"slug",
|
|
22
|
+
"description",
|
|
23
|
+
"view_groups",
|
|
24
|
+
"write_groups",
|
|
25
|
+
"created_by",
|
|
26
|
+
"created_at",
|
|
27
|
+
"updated_at",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def has_add_permission(self, request) -> bool: # type: ignore[override]
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
# Allow changing so admins can edit webhooks
|
|
34
|
+
def has_change_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
35
|
+
return True
|
|
36
|
+
|
|
37
|
+
def has_delete_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
@admin.register(KanbanSetting)
|
|
41
|
+
class KanbanSettingAdmin(admin.ModelAdmin):
|
|
42
|
+
"""Global configuration for aa_kanban."""
|
|
43
|
+
|
|
44
|
+
list_display = ("__str__", "board_creation_webhook")
|
|
45
|
+
|
|
46
|
+
def has_add_permission(self, request) -> bool: # type: ignore[override]
|
|
47
|
+
# Only allow 1 instance
|
|
48
|
+
from .models import KanbanSetting
|
|
49
|
+
if KanbanSetting.objects.exists():
|
|
50
|
+
return False
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@admin.register(List)
|
|
55
|
+
class ListAdmin(admin.ModelAdmin):
|
|
56
|
+
"""Read-only list overview. Manage columns via the board frontend."""
|
|
57
|
+
|
|
58
|
+
list_display = ("name", "board", "order", "created_at")
|
|
59
|
+
list_filter = ("board",)
|
|
60
|
+
search_fields = ("name", "board__name")
|
|
61
|
+
readonly_fields = ("name", "board", "order", "created_at", "updated_at")
|
|
62
|
+
|
|
63
|
+
def has_add_permission(self, request) -> bool: # type: ignore[override]
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def has_change_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
def has_delete_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@admin.register(Label)
|
|
74
|
+
class LabelAdmin(admin.ModelAdmin):
|
|
75
|
+
"""Read-only label overview. Manage labels via the board frontend."""
|
|
76
|
+
|
|
77
|
+
list_display = ("name", "color", "board")
|
|
78
|
+
list_filter = ("board", "color")
|
|
79
|
+
search_fields = ("name", "board__name")
|
|
80
|
+
readonly_fields = ("name", "color", "board")
|
|
81
|
+
|
|
82
|
+
def has_add_permission(self, request) -> bool: # type: ignore[override]
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
def has_change_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
def has_delete_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@admin.register(Card)
|
|
93
|
+
class CardAdmin(admin.ModelAdmin):
|
|
94
|
+
"""Read-only card overview. Manage cards via the board frontend."""
|
|
95
|
+
|
|
96
|
+
list_display = ("title", "list", "order", "due_date", "created_at")
|
|
97
|
+
list_filter = ("list__board", "list")
|
|
98
|
+
search_fields = ("title", "description")
|
|
99
|
+
readonly_fields = (
|
|
100
|
+
"title",
|
|
101
|
+
"description",
|
|
102
|
+
"list",
|
|
103
|
+
"order",
|
|
104
|
+
"assignees",
|
|
105
|
+
"labels",
|
|
106
|
+
"due_date",
|
|
107
|
+
"created_by",
|
|
108
|
+
"created_at",
|
|
109
|
+
"updated_at",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def has_add_permission(self, request) -> bool: # type: ignore[override]
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
def has_change_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
def has_delete_permission(self, request, obj=None) -> bool: # type: ignore[override]
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@admin.register(Comment)
|
|
123
|
+
class CommentAdmin(admin.ModelAdmin):
|
|
124
|
+
"""Comments are manageable from admin for moderation purposes."""
|
|
125
|
+
|
|
126
|
+
list_display = ("card", "author", "created_at")
|
|
127
|
+
list_filter = ("created_at",)
|
|
128
|
+
search_fields = ("text", "author__username", "card__title")
|
|
129
|
+
readonly_fields = ("created_at",)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Alliance Auth hooks for aa_kanban."""
|
|
2
|
+
|
|
3
|
+
from allianceauth import hooks
|
|
4
|
+
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
|
5
|
+
|
|
6
|
+
from . import urls
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AaKanbanMenuItem(MenuItemHook):
|
|
10
|
+
"""Menu item hook for aa_kanban."""
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
super().__init__(
|
|
14
|
+
"Kanban",
|
|
15
|
+
"fas fa-columns fa-fw",
|
|
16
|
+
"aa_kanban:index",
|
|
17
|
+
navactive=["aa_kanban:"],
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def render(self, request):
|
|
21
|
+
if request.user.has_perm("aa_kanban.basic_access"):
|
|
22
|
+
return super().render(request)
|
|
23
|
+
return ""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@hooks.register("menu_item_hook")
|
|
27
|
+
def register_menu():
|
|
28
|
+
return AaKanbanMenuItem()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@hooks.register("url_hook")
|
|
32
|
+
def register_urls():
|
|
33
|
+
return UrlHook(urls, "aa_kanban", r"^kanban/")
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Generated by Django 5.2.17 on 2026-09-09 20:28
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
initial = True
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
('auth', '0012_alter_user_first_name_max_length'),
|
|
14
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name='General',
|
|
20
|
+
fields=[
|
|
21
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
22
|
+
],
|
|
23
|
+
options={
|
|
24
|
+
'permissions': (('basic_access', 'Can access this app'), ('manage_boards', 'Can manage kanban boards')),
|
|
25
|
+
'managed': False,
|
|
26
|
+
'default_permissions': (),
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
migrations.CreateModel(
|
|
30
|
+
name='Board',
|
|
31
|
+
fields=[
|
|
32
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
33
|
+
('name', models.CharField(max_length=255)),
|
|
34
|
+
('slug', models.SlugField(blank=True, max_length=255, unique=True)),
|
|
35
|
+
('description', models.TextField(blank=True)),
|
|
36
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
37
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
38
|
+
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
|
39
|
+
('view_groups', models.ManyToManyField(blank=True, help_text='Groups that have read-only access to this board.', related_name='kanban_view_boards', to='auth.group')),
|
|
40
|
+
('write_groups', models.ManyToManyField(blank=True, help_text='Groups that have write/mutation access to this board.', related_name='kanban_write_boards', to='auth.group')),
|
|
41
|
+
],
|
|
42
|
+
options={
|
|
43
|
+
'verbose_name': 'Board',
|
|
44
|
+
'verbose_name_plural': 'Boards',
|
|
45
|
+
'ordering': ['name'],
|
|
46
|
+
},
|
|
47
|
+
),
|
|
48
|
+
migrations.CreateModel(
|
|
49
|
+
name='Card',
|
|
50
|
+
fields=[
|
|
51
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
52
|
+
('title', models.CharField(max_length=255)),
|
|
53
|
+
('description', models.TextField(blank=True)),
|
|
54
|
+
('order', models.PositiveIntegerField(default=0)),
|
|
55
|
+
('due_date', models.DateTimeField(blank=True, null=True)),
|
|
56
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
57
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
58
|
+
('assignees', models.ManyToManyField(blank=True, related_name='assigned_kanban_cards', to=settings.AUTH_USER_MODEL)),
|
|
59
|
+
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
|
60
|
+
],
|
|
61
|
+
options={
|
|
62
|
+
'verbose_name': 'Card',
|
|
63
|
+
'verbose_name_plural': 'Cards',
|
|
64
|
+
'ordering': ['order', 'id'],
|
|
65
|
+
},
|
|
66
|
+
),
|
|
67
|
+
migrations.CreateModel(
|
|
68
|
+
name='Comment',
|
|
69
|
+
fields=[
|
|
70
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
71
|
+
('text', models.TextField()),
|
|
72
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
73
|
+
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='kanban_comments', to=settings.AUTH_USER_MODEL)),
|
|
74
|
+
('card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='aa_kanban.card')),
|
|
75
|
+
],
|
|
76
|
+
options={
|
|
77
|
+
'verbose_name': 'Comment',
|
|
78
|
+
'verbose_name_plural': 'Comments',
|
|
79
|
+
'ordering': ['created_at'],
|
|
80
|
+
},
|
|
81
|
+
),
|
|
82
|
+
migrations.CreateModel(
|
|
83
|
+
name='Label',
|
|
84
|
+
fields=[
|
|
85
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
86
|
+
('name', models.CharField(max_length=50)),
|
|
87
|
+
('color', models.CharField(default='primary', help_text='Bootstrap badge color style (e.g. primary, success, danger, warning, info, dark)', max_length=20)),
|
|
88
|
+
('board', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='labels', to='aa_kanban.board')),
|
|
89
|
+
],
|
|
90
|
+
options={
|
|
91
|
+
'verbose_name': 'Label',
|
|
92
|
+
'verbose_name_plural': 'Labels',
|
|
93
|
+
'ordering': ['name'],
|
|
94
|
+
'unique_together': {('board', 'name')},
|
|
95
|
+
},
|
|
96
|
+
),
|
|
97
|
+
migrations.AddField(
|
|
98
|
+
model_name='card',
|
|
99
|
+
name='labels',
|
|
100
|
+
field=models.ManyToManyField(blank=True, related_name='cards', to='aa_kanban.label'),
|
|
101
|
+
),
|
|
102
|
+
migrations.CreateModel(
|
|
103
|
+
name='List',
|
|
104
|
+
fields=[
|
|
105
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
106
|
+
('name', models.CharField(max_length=100)),
|
|
107
|
+
('order', models.PositiveIntegerField(default=0)),
|
|
108
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
109
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
110
|
+
('board', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lists', to='aa_kanban.board')),
|
|
111
|
+
],
|
|
112
|
+
options={
|
|
113
|
+
'verbose_name': 'List',
|
|
114
|
+
'verbose_name_plural': 'Lists',
|
|
115
|
+
'ordering': ['order', 'id'],
|
|
116
|
+
},
|
|
117
|
+
),
|
|
118
|
+
migrations.AddField(
|
|
119
|
+
model_name='card',
|
|
120
|
+
name='list',
|
|
121
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cards', to='aa_kanban.list'),
|
|
122
|
+
),
|
|
123
|
+
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Generated by Django 5.2.17 on 2026-09-21 08:37
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('aa_kanban', '0001_initial'),
|
|
11
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.CreateModel(
|
|
16
|
+
name='KanbanGroup',
|
|
17
|
+
fields=[
|
|
18
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
19
|
+
('name', models.CharField(max_length=255, unique=True)),
|
|
20
|
+
('members', models.ManyToManyField(blank=True, related_name='kanban_groups', to=settings.AUTH_USER_MODEL)),
|
|
21
|
+
],
|
|
22
|
+
options={
|
|
23
|
+
'verbose_name': 'Kanban Group',
|
|
24
|
+
'verbose_name_plural': 'Kanban Groups',
|
|
25
|
+
'ordering': ['name'],
|
|
26
|
+
},
|
|
27
|
+
),
|
|
28
|
+
migrations.AlterField(
|
|
29
|
+
model_name='board',
|
|
30
|
+
name='view_groups',
|
|
31
|
+
field=models.ManyToManyField(blank=True, help_text='Kanban groups that have read-only access to this board.', related_name='kanban_view_boards', to='aa_kanban.kanbangroup'),
|
|
32
|
+
),
|
|
33
|
+
migrations.AlterField(
|
|
34
|
+
model_name='board',
|
|
35
|
+
name='write_groups',
|
|
36
|
+
field=models.ManyToManyField(blank=True, help_text='Kanban groups that have write/mutation access to this board.', related_name='kanban_write_boards', to='aa_kanban.kanbangroup'),
|
|
37
|
+
),
|
|
38
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated by Django 5.2.17 on 2026-09-21 09:53
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('aa_kanban', '0002_kanbangroup_alter_board_view_groups_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.CreateModel(
|
|
14
|
+
name='KanbanSetting',
|
|
15
|
+
fields=[
|
|
16
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
17
|
+
('board_creation_webhook', models.URLField(blank=True, help_text='Discord Webhook URL for global board creation notifications.', null=True)),
|
|
18
|
+
],
|
|
19
|
+
options={
|
|
20
|
+
'verbose_name': 'Kanban Setting',
|
|
21
|
+
'verbose_name_plural': 'Kanban Settings',
|
|
22
|
+
},
|
|
23
|
+
),
|
|
24
|
+
migrations.AddField(
|
|
25
|
+
model_name='board',
|
|
26
|
+
name='discord_webhook_cards',
|
|
27
|
+
field=models.URLField(blank=True, help_text='Discord Webhook URL for card movement notifications on this board.', null=True),
|
|
28
|
+
),
|
|
29
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Database migrations package."""
|