delete app tasks
This commit is contained in:
@@ -56,7 +56,6 @@ INSTALLED_APPS = [
|
||||
"posts.apps.PostsConfig",
|
||||
"members.apps.MembersConfig",
|
||||
"blackboard.apps.BlackboardConfig",
|
||||
"tasks.apps.TasksConfig",
|
||||
"gallery.apps.GalleryConfig",
|
||||
"intern.apps.InternConfig",
|
||||
"finance.apps.FinanceConfig",
|
||||
|
||||
@@ -39,7 +39,6 @@ urlpatterns = [
|
||||
path("jobs/", include("blackboard.urls")),
|
||||
path("posts/", include("posts.urls")),
|
||||
path("search/", include("search.urls")),
|
||||
path("tasks/", include("tasks.urls")),
|
||||
path(
|
||||
"discord/",
|
||||
RedirectView.as_view(url="https://discord.com/invite/7qRuuMA"),
|
||||
|
||||
@@ -3,8 +3,6 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget
|
||||
from django import forms
|
||||
from django.forms.widgets import HiddenInput
|
||||
|
||||
from tasks.models import Task, TaskList
|
||||
|
||||
from .models import Attachment, Etherpad, FileUpload, Topic, TopicGroup
|
||||
|
||||
|
||||
@@ -33,7 +31,6 @@ class TopicAdminForm(forms.ModelForm):
|
||||
labels = {
|
||||
"title": "Titel",
|
||||
"slug": "Permalink",
|
||||
"task_list": "Aufgabenbereich",
|
||||
"description": "Beschreibung",
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 4.1.2 on 2022-12-21 11:42
|
||||
# Generated by Django 4.2.6 on 2023-11-08 11:32
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
@@ -7,12 +7,9 @@ import fet2020.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("tasks", "0004_set_fields_unique"),
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
@@ -83,15 +80,6 @@ class Migration(migrations.Migration):
|
||||
("slug", models.SlugField()),
|
||||
("archive", models.BooleanField(default=False, verbose_name="Archiv")),
|
||||
("description", models.TextField(blank=True, null=True)),
|
||||
(
|
||||
"task_list",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="tasks.tasklist",
|
||||
),
|
||||
),
|
||||
(
|
||||
"topic_group",
|
||||
models.ForeignKey(
|
||||
|
||||
@@ -12,7 +12,6 @@ from django.utils.text import slugify
|
||||
from documents import create_pad, get_pad_html
|
||||
from documents.api import get_pad_link
|
||||
from fet2020.utils import create_random_id
|
||||
from tasks.models import TaskList
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -58,9 +57,6 @@ class Topic(models.Model):
|
||||
topic_group = models.ForeignKey(
|
||||
TopicGroup, on_delete=models.CASCADE, verbose_name="Themenbereich"
|
||||
)
|
||||
task_list = models.ForeignKey(
|
||||
TaskList, blank=True, on_delete=models.CASCADE, null=True
|
||||
)
|
||||
|
||||
objects = models.Manager()
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ from .views import (
|
||||
AttachmentUpdateView,
|
||||
EtherpadCreateView,
|
||||
FileUploadCreateView,
|
||||
TaskCreateView,
|
||||
TopicCreateView,
|
||||
TopicDetailView,
|
||||
TopicUpdateView,
|
||||
@@ -50,7 +49,6 @@ topic_urlpatterns = [
|
||||
AttachmentCreateView.as_view(),
|
||||
name="attachment_create",
|
||||
),
|
||||
path("create-task/", TaskCreateView.as_view(), name="task_create"),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
@@ -11,8 +11,6 @@ from django.views.generic.edit import CreateView, UpdateView
|
||||
from authentications.decorators import authenticated_user
|
||||
from documents.etherpadlib import add_ep_cookie
|
||||
from fet2020.utils import add_log_action
|
||||
from tasks.forms import InternTaskCreateForm
|
||||
from tasks.models import Task
|
||||
|
||||
from .forms import (
|
||||
AttachmentCreateForm,
|
||||
@@ -70,21 +68,8 @@ class TopicDetailView(LoginRequiredMixin, DetailView):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
attachments = Attachment.objects.filter(topic=self.object).order_by("title")
|
||||
|
||||
tasks = None
|
||||
if self.object.task_list:
|
||||
tasks = deque(
|
||||
Task.taskmanager.get_tasks(
|
||||
user=None,
|
||||
assigned_tasks=True,
|
||||
task_list=self.object.task_list,
|
||||
completed=False,
|
||||
)
|
||||
)
|
||||
|
||||
context["topic"] = self.object
|
||||
context["attachments"] = attachments
|
||||
context["tasks"] = tasks
|
||||
context["topic"] = self.object
|
||||
|
||||
return context
|
||||
|
||||
@@ -238,24 +223,3 @@ class FileUploadCreateView(LoginRequiredMixin, CreateView):
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("intern:attachment", kwargs=self.kwargs)
|
||||
|
||||
|
||||
class TaskCreateView(LoginRequiredMixin, CreateView):
|
||||
form_class = InternTaskCreateForm
|
||||
model = Task
|
||||
template_name = "intern/task_create.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.created_by = self.request.user
|
||||
add_log_action(self.request, form, "tasks", "task", True)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
slug = self.kwargs.get("slug")
|
||||
topic = Topic.objects.get(slug=slug)
|
||||
context["topic"] = topic
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("intern:topic", kwargs=self.kwargs)
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .forms import DocumentInlineForm, TaskAdminForm, TaskListAdminForm
|
||||
from .models import Document, Task, TaskList
|
||||
|
||||
|
||||
class DocumentInline(admin.TabularInline):
|
||||
form = DocumentInlineForm
|
||||
model = Document
|
||||
extra = 0
|
||||
verbose_name = "Dokument"
|
||||
verbose_name_plural = "Dokumentensammlung"
|
||||
|
||||
|
||||
class TaskListAdmin(admin.ModelAdmin):
|
||||
form = TaskListAdminForm
|
||||
model = TaskList
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": (
|
||||
"name",
|
||||
"shortterm",
|
||||
"slug",
|
||||
"users",
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
readonly_fields = ("slug",)
|
||||
|
||||
def add_view(self, request, form_url="", extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
||||
return super().add_view(
|
||||
request,
|
||||
form_url,
|
||||
extra_context=extra_context,
|
||||
)
|
||||
|
||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
||||
return super().change_view(
|
||||
request,
|
||||
object_id,
|
||||
form_url,
|
||||
extra_context=extra_context,
|
||||
)
|
||||
|
||||
|
||||
class TaskAdmin(admin.ModelAdmin):
|
||||
form = TaskAdminForm
|
||||
model = Task
|
||||
inlines = (DocumentInline,)
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": (
|
||||
"title",
|
||||
"task_list",
|
||||
"note",
|
||||
"priority",
|
||||
),
|
||||
},
|
||||
),
|
||||
(
|
||||
"Fälligkeit",
|
||||
{
|
||||
"fields": (
|
||||
"due_date",
|
||||
"assigned_to",
|
||||
),
|
||||
},
|
||||
),
|
||||
(
|
||||
"Abgeschlossen",
|
||||
{
|
||||
"fields": (
|
||||
"completed_date",
|
||||
"completed",
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
list_display = [
|
||||
"title",
|
||||
"task_list",
|
||||
"assigned_to",
|
||||
"due_date",
|
||||
"completed",
|
||||
"priority",
|
||||
]
|
||||
list_filter = ("task_list",)
|
||||
search_fields = ("title",)
|
||||
|
||||
def add_view(self, request, form_url="", extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
||||
return super().add_view(
|
||||
request,
|
||||
form_url,
|
||||
extra_context=extra_context,
|
||||
)
|
||||
|
||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
||||
return super().change_view(
|
||||
request,
|
||||
object_id,
|
||||
form_url,
|
||||
extra_context=extra_context,
|
||||
)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
obj.created_by = request.user
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
|
||||
admin.site.register(TaskList, TaskListAdmin)
|
||||
admin.site.register(Task, TaskAdmin)
|
||||
@@ -1,11 +0,0 @@
|
||||
from django.apps import AppConfig
|
||||
from django.db.models.signals import post_migrate
|
||||
|
||||
from fet2020.utils import create_perms
|
||||
|
||||
|
||||
class TasksConfig(AppConfig):
|
||||
name = "tasks"
|
||||
|
||||
def ready(self):
|
||||
post_migrate.connect(create_perms, sender=self)
|
||||
@@ -1,221 +0,0 @@
|
||||
from ckeditor.widgets import CKEditorWidget
|
||||
from django import forms
|
||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.validators import ValidationError
|
||||
from django.forms.widgets import HiddenInput
|
||||
from django.utils import timezone
|
||||
|
||||
from .models import Document, Task, TaskList
|
||||
|
||||
|
||||
class DateInput(forms.DateInput):
|
||||
input_type = "date"
|
||||
|
||||
|
||||
class DocumentInlineForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Document
|
||||
fields = [
|
||||
"title",
|
||||
"date",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"title": "Titel",
|
||||
}
|
||||
|
||||
|
||||
class TaskListAdminForm(forms.ModelForm):
|
||||
users = forms.ModelMultipleChoiceField(
|
||||
label="Benutzer",
|
||||
help_text="Es können nur die Benutzer ausgewählt werden, die sich auf der Homepage angemeldet haben.",
|
||||
queryset=User.objects.all().order_by("username"),
|
||||
widget=FilteredSelectMultiple("User", is_stacked=False),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = TaskList
|
||||
fields = "__all__"
|
||||
|
||||
labels = {
|
||||
"name": "Titel",
|
||||
"shortterm": "Kürzel für den Link",
|
||||
"slug": "Permalink",
|
||||
}
|
||||
|
||||
|
||||
class TaskAdminForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Task
|
||||
fields = "__all__"
|
||||
|
||||
labels = {
|
||||
"title": "Titel",
|
||||
"shortterm": "Kürzel für den Link",
|
||||
"slug": "Permalink",
|
||||
"task_list": "Aufgabenbereich",
|
||||
"due_date": "Fälligkeit",
|
||||
"completed": "Abgeschlossen",
|
||||
"completed_date": "Datum der Fertigstellung",
|
||||
"assigned_to": "Zuweisen an",
|
||||
"note": "Notizen",
|
||||
"priority": "Priorität",
|
||||
}
|
||||
|
||||
widgets = {
|
||||
"note": CKEditorWidget(config_name="default"),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs) # to get the self.fields set
|
||||
self.fields["assigned_to"].empty_label = "Alle"
|
||||
self.fields["assigned_to"].queryset = self.fields[
|
||||
"assigned_to"
|
||||
].queryset.order_by("username")
|
||||
|
||||
|
||||
class TaskCreateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Task
|
||||
|
||||
fields = [
|
||||
"title",
|
||||
"task_list",
|
||||
"due_date",
|
||||
"assigned_to",
|
||||
"note",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"title": "Titel des Tasks",
|
||||
"task_list": "Task-Gruppe",
|
||||
"assigned_to": "Zuweisen an",
|
||||
"due_date": "Fälligkeitsdatum",
|
||||
"note": "Notizen",
|
||||
}
|
||||
|
||||
widgets = {
|
||||
"due_date": DateInput(format=("%Y-%m-%d")),
|
||||
"note": CKEditorWidget(config_name="intern"),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "user" in kwargs:
|
||||
user = kwargs.pop("user")
|
||||
else:
|
||||
user = None
|
||||
|
||||
super().__init__(*args, **kwargs) # to get the self.fields set
|
||||
self.fields["assigned_to"].empty_label = "Alle"
|
||||
qs = self.fields["assigned_to"].queryset
|
||||
self.fields["assigned_to"].queryset = qs.order_by("username")
|
||||
|
||||
if user:
|
||||
self.fields["task_list"].queryset = TaskList.objects.filter(users=user)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
assigned_to = cleaned_data["assigned_to"]
|
||||
|
||||
if assigned_to:
|
||||
task_list = TaskList.objects.get(id=cleaned_data["task_list"].id)
|
||||
if not task_list.users.filter(username=assigned_to.username):
|
||||
raise ValidationError(
|
||||
_(
|
||||
f"User '{assigned_to}' gibt es nicht in der User-Liste der Task-Gruppe '{task_list}'."
|
||||
)
|
||||
)
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class TaskUpdateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Task
|
||||
|
||||
fields = [
|
||||
"assigned_to",
|
||||
"due_date",
|
||||
"completed",
|
||||
"completed_date",
|
||||
"note",
|
||||
"task_list",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"assigned_to": "Zuweisen an",
|
||||
"due_date": "Fälligkeitsdatum",
|
||||
"completed": "Abgeschlossen",
|
||||
"completed_date": "Datum der Fertigstellung",
|
||||
"note": "Notizen",
|
||||
}
|
||||
|
||||
widgets = {
|
||||
"due_date": DateInput(
|
||||
format=("%Y-%m-%d"),
|
||||
),
|
||||
"note": CKEditorWidget(config_name="intern"),
|
||||
"task_list": HiddenInput,
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "task_list" in kwargs:
|
||||
task_list = kwargs.pop("task_list")
|
||||
else:
|
||||
task_list = None
|
||||
|
||||
super().__init__(*args, **kwargs) # to get the self.fields set
|
||||
self.fields["assigned_to"].empty_label = "Alle"
|
||||
if task_list:
|
||||
qs = TaskList.objects.get(id=task_list.id).users
|
||||
self.fields["assigned_to"].queryset = qs.order_by("username")
|
||||
|
||||
|
||||
class DocumentCreateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Document
|
||||
|
||||
fields = [
|
||||
"title",
|
||||
"date",
|
||||
"task",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"title": "Titel",
|
||||
"date": "Datum",
|
||||
}
|
||||
|
||||
widgets = {
|
||||
"date": DateInput(format=("%d-%m-%Y")),
|
||||
"task": HiddenInput,
|
||||
}
|
||||
|
||||
|
||||
class InternTaskCreateForm(TaskCreateForm):
|
||||
# form for creating a task from intern page.
|
||||
class Meta:
|
||||
model = Task
|
||||
|
||||
fields = [
|
||||
"title",
|
||||
"task_list",
|
||||
"due_date",
|
||||
"assigned_to",
|
||||
"note",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"title": "Titel des Tasks",
|
||||
"task_list": "Task-Gruppe",
|
||||
"due_date": "Fälligkeitsdatum",
|
||||
"assigned_to": "Zuweisen an",
|
||||
}
|
||||
|
||||
widgets = {
|
||||
"due_date": DateInput(
|
||||
format=("%d-%m-%Y"),
|
||||
),
|
||||
"task_list": HiddenInput,
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
|
||||
|
||||
class TaskManager(models.Manager):
|
||||
def get_tasks(self, user, assigned_tasks, task_list, completed):
|
||||
# None ... assigned to all users
|
||||
qs_all = self.get_queryset()
|
||||
qs = qs_all.filter(assigned_to__id=user)
|
||||
|
||||
if not assigned_tasks:
|
||||
qs_tmp = qs_all.filter(
|
||||
Q(assigned_to=None) & Q(task_list__users__id__exact=user)
|
||||
)
|
||||
qs = (qs | qs_tmp).distinct()
|
||||
|
||||
if task_list:
|
||||
qs = qs.filter(task_list=task_list)
|
||||
|
||||
return qs.filter(completed=completed)
|
||||
@@ -1,50 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-01-29 18:35
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TaskList',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=60)),
|
||||
('slug', models.SlugField(blank=True, null=True, unique=True)),
|
||||
('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Auf\xadga\xadben\xadbe\xadreich',
|
||||
'verbose_name_plural': 'Auf\xadga\xadben\xadbe\xadreiche',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Task',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=140, verbose_name='Titel')),
|
||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||
('due_date', models.DateField(blank=True, null=True, verbose_name='Fälligkeit')),
|
||||
('completed', models.BooleanField(default=False, verbose_name='Abgeschlossen')),
|
||||
('completed_date', models.DateField(blank=True, null=True)),
|
||||
('note', models.TextField(blank=True, null=True, verbose_name='Notizen')),
|
||||
('priority', models.PositiveIntegerField(blank=True, null=True, verbose_name='Priorität')),
|
||||
('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assigned_to', to=settings.AUTH_USER_MODEL, verbose_name='Zugewiesen an')),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_by', to=settings.AUTH_USER_MODEL)),
|
||||
('task_list', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='tasks.tasklist', verbose_name='Aufgabenbereich')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Aufgabe',
|
||||
'verbose_name_plural': 'Aufgaben',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,103 +0,0 @@
|
||||
# Generated by Django 4.1.2 on 2022-12-21 11:42
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import fet2020.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tasks", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="task",
|
||||
options={
|
||||
"ordering": (
|
||||
"task_list",
|
||||
models.OrderBy(
|
||||
models.F("due_date"), descending=True, nulls_first=True
|
||||
),
|
||||
),
|
||||
"verbose_name": "Aufgabe",
|
||||
"verbose_name_plural": "Aufgaben",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="task",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="task",
|
||||
name="slug_id",
|
||||
field=models.CharField(
|
||||
default=fet2020.utils.create_random_id,
|
||||
editable=False,
|
||||
max_length=8,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="tasklist",
|
||||
name="shortterm",
|
||||
field=models.CharField(blank=True, max_length=128, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="task",
|
||||
name="title",
|
||||
field=models.CharField(max_length=128, verbose_name="Titel"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tasklist",
|
||||
name="name",
|
||||
field=models.CharField(max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tasklist",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True, null=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Document",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("title", models.CharField(max_length=128, verbose_name="Titel")),
|
||||
(
|
||||
"slug_id",
|
||||
models.CharField(
|
||||
default=fet2020.utils.create_random_id,
|
||||
editable=False,
|
||||
max_length=8,
|
||||
unique=True,
|
||||
),
|
||||
),
|
||||
("etherpad_key", models.CharField(blank=True, max_length=50)),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Datum"),
|
||||
),
|
||||
(
|
||||
"task",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="tasks.task"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Dokument",
|
||||
"verbose_name_plural": "Dokumente",
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,30 +0,0 @@
|
||||
# Generated by Django 4.1.2 on 2022-12-21 11:43
|
||||
|
||||
from django.db import migrations
|
||||
import fet2020.utils
|
||||
from django.utils.text import slugify
|
||||
|
||||
|
||||
def forwards_func(apps, schema_editor):
|
||||
Tasks = apps.get_model("tasks", "Task")
|
||||
for elem in Tasks.objects.all():
|
||||
elem.slug_id = fet2020.utils.create_random_id()
|
||||
elem.slug = elem.slug_id + "-" + slugify(elem.title)
|
||||
elem.save(update_fields=["slug_id", "slug"])
|
||||
|
||||
TaskLists = apps.get_model("tasks", "TaskList")
|
||||
for elem in TaskLists.objects.all():
|
||||
elem.shortterm = slugify(elem.name)
|
||||
elem.slug = slugify(elem.shortterm)
|
||||
elem.save(update_fields=["shortterm", "slug"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tasks", "0002_alter_task_options_task_slug_task_slug_id_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forwards_func, reverse_code=migrations.RunPython.noop),
|
||||
]
|
||||
@@ -1,39 +0,0 @@
|
||||
# Generated by Django 4.1.2 on 2022-12-21 11:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import fet2020.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tasks", "0003_populate_unique_values"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="task",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="task",
|
||||
name="slug_id",
|
||||
field=models.CharField(
|
||||
default=fet2020.utils.create_random_id,
|
||||
editable=False,
|
||||
max_length=8,
|
||||
unique=True,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tasklist",
|
||||
name="shortterm",
|
||||
field=models.CharField(blank=True, max_length=128, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tasklist",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -1,145 +0,0 @@
|
||||
from datetime import date
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.validators import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models import F
|
||||
from django.db.models.constraints import UniqueConstraint
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.text import slugify
|
||||
|
||||
from documents import create_pad
|
||||
from documents.api import get_pad_link
|
||||
from fet2020.utils import create_random_id
|
||||
|
||||
from .managers import TaskManager
|
||||
|
||||
|
||||
class TaskList(models.Model):
|
||||
name = models.CharField(max_length=128)
|
||||
|
||||
shortterm = models.CharField(max_length=128, unique=True, blank=True)
|
||||
slug = models.SlugField(unique=True, blank=True)
|
||||
|
||||
users = models.ManyToManyField(User, blank=True)
|
||||
|
||||
objects = models.Manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Aufgabenbereich"
|
||||
verbose_name_plural = "Aufgabenbereiche"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("tasks:index")
|
||||
|
||||
def clean(self):
|
||||
if not self.shortterm:
|
||||
self.shortterm = slugify(self.name)
|
||||
self.slug = slugify(self.shortterm)
|
||||
|
||||
|
||||
class Task(models.Model):
|
||||
title = models.CharField(verbose_name="Titel", max_length=128)
|
||||
|
||||
slug_id = models.CharField(
|
||||
default=create_random_id, max_length=8, unique=True, editable=False
|
||||
)
|
||||
slug = models.SlugField(unique=True, blank=True)
|
||||
|
||||
task_list = models.ForeignKey(
|
||||
TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True
|
||||
)
|
||||
|
||||
created_date = models.DateTimeField(auto_now_add=True)
|
||||
due_date = models.DateField(verbose_name="Fälligkeit", blank=True, null=True)
|
||||
|
||||
completed = models.BooleanField(verbose_name="Abgeschlossen", default=False)
|
||||
completed_date = models.DateField(blank=True, null=True)
|
||||
|
||||
created_by = models.ForeignKey(
|
||||
User,
|
||||
related_name="created_by",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
assigned_to = models.ForeignKey(
|
||||
User,
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="assigned_to",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="Zugewiesen an",
|
||||
)
|
||||
|
||||
note = models.TextField(verbose_name="Notizen", blank=True, null=True)
|
||||
priority = models.PositiveIntegerField(
|
||||
verbose_name="Priorität", blank=True, null=True
|
||||
)
|
||||
|
||||
objects = models.Manager()
|
||||
taskmanager = TaskManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ("task_list", F("due_date").desc(nulls_first=True))
|
||||
verbose_name = "Aufgabe"
|
||||
verbose_name_plural = "Aufgaben"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("tasks:task", kwargs={"slug": self.slug})
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = self.slug_id + "-" + slugify(self.title)
|
||||
|
||||
if self.completed and not self.completed_date:
|
||||
self.completed_date = timezone.now().date()
|
||||
|
||||
if not self.completed and self.completed_date:
|
||||
self.completed_date = None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Document(models.Model):
|
||||
title = models.CharField(verbose_name="Titel", max_length=128)
|
||||
|
||||
slug_id = models.CharField(
|
||||
default=create_random_id, max_length=8, unique=True, editable=False
|
||||
)
|
||||
etherpad_key = models.CharField(max_length=50, blank=True)
|
||||
|
||||
date = models.DateField(verbose_name="Datum", default=date.today)
|
||||
|
||||
task = models.ForeignKey(Task, on_delete=models.CASCADE)
|
||||
|
||||
objects = models.Manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Dokument"
|
||||
verbose_name_plural = "Dokumente"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
return get_pad_link(self.etherpad_key)
|
||||
|
||||
def clean(self):
|
||||
pad_name = slugify(str(self.slug_id) + "-" + self.title[:40])
|
||||
if len(pad_name) > 50:
|
||||
raise ValidationError(
|
||||
f"Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: {len(pad_name)}, Name: {pad_name})"
|
||||
)
|
||||
|
||||
self.etherpad_key = create_pad(pad_name)
|
||||
if not self.etherpad_key:
|
||||
raise ValidationError(
|
||||
f"Etherpad '{pad_name}' konnte nicht erstellt werden."
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
from django.urls import path
|
||||
|
||||
from . import apps, views
|
||||
from .views import DocumentCreateView, TaskCreateView, TaskDetailView, TaskUpdateView
|
||||
|
||||
app_name = apps.TasksConfig.name
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.index, name="index"),
|
||||
path("create-task/", TaskCreateView.as_view(), name="task_create"),
|
||||
path("<slug:slug>/", TaskDetailView.as_view(), name="task"),
|
||||
path("<slug:slug>/update/", TaskUpdateView.as_view(), name="task_update"),
|
||||
path(
|
||||
"<slug:slug>/create-document/", DocumentCreateView.as_view(), name="docu_create"
|
||||
),
|
||||
]
|
||||
@@ -1,149 +0,0 @@
|
||||
import logging
|
||||
from collections import deque
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.views.generic.detail import DetailView
|
||||
from django.views.generic.edit import CreateView, UpdateView
|
||||
|
||||
from authentications.decorators import authenticated_user
|
||||
from documents.api import get_pad_link
|
||||
from documents.etherpadlib import add_ep_cookie
|
||||
from fet2020.utils import add_log_action
|
||||
from intern.models import Topic
|
||||
|
||||
from .forms import DocumentCreateForm, TaskCreateForm, TaskUpdateForm
|
||||
from .models import Document, Task, TaskList
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@authenticated_user
|
||||
def index(request):
|
||||
tasklist = None
|
||||
show_tasklist = None
|
||||
assigned_tasks = None
|
||||
completed = False
|
||||
state_open = False
|
||||
state_closed = False
|
||||
|
||||
if request.method == "POST":
|
||||
if "btn_checkbox" in request.POST:
|
||||
for task_id in request.POST.getlist("checkbox"):
|
||||
task = Task.objects.get(id=task_id)
|
||||
|
||||
if not task.completed:
|
||||
task.completed = True
|
||||
task.completed_date = timezone.now().date()
|
||||
task.save()
|
||||
|
||||
if request.method == "GET":
|
||||
if request.GET.get("tasklist"):
|
||||
if request.GET.get("tasklist") != "all":
|
||||
tasklist = TaskList.objects.filter(id=request.GET["tasklist"]).first()
|
||||
show_tasklist = tasklist.id
|
||||
|
||||
if request.GET.get("tasks") == "assigned":
|
||||
assigned_tasks = True
|
||||
|
||||
if request.GET.get("open_tasks"):
|
||||
completed = False
|
||||
state_open = True
|
||||
|
||||
if request.GET.get("closed_tasks"):
|
||||
completed = True
|
||||
state_closed = True
|
||||
|
||||
tasks = Task.taskmanager.get_tasks(
|
||||
user=request.user.id,
|
||||
assigned_tasks=assigned_tasks,
|
||||
task_list=tasklist,
|
||||
completed=completed,
|
||||
)
|
||||
|
||||
context = {
|
||||
"tasks": tasks,
|
||||
"show_tasklist": show_tasklist,
|
||||
"assigned_tasks": assigned_tasks,
|
||||
"state_open": state_open,
|
||||
"state_closed": state_closed,
|
||||
}
|
||||
|
||||
return render(request, "tasks/index.html", context)
|
||||
|
||||
|
||||
class TaskCreateView(LoginRequiredMixin, CreateView):
|
||||
model = Task
|
||||
success_url = reverse_lazy("tasks:index")
|
||||
template_name = "tasks/task_create.html"
|
||||
form_class = TaskCreateForm
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.created_by = self.request.user
|
||||
add_log_action(self.request, form, "tasks", "task", True)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs["user"] = self.request.user
|
||||
return kwargs
|
||||
|
||||
|
||||
class TaskUpdateView(LoginRequiredMixin, UpdateView):
|
||||
form_class = TaskUpdateForm
|
||||
model = Task
|
||||
template_name = "tasks/task_update.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
add_log_action(self.request, form, "tasks", "task", False)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class TaskDetailView(LoginRequiredMixin, DetailView):
|
||||
model = Task
|
||||
template_name = "tasks/task_detail.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
response = super().get(request, *args, **kwargs)
|
||||
|
||||
try:
|
||||
response = add_ep_cookie(self.request, response)
|
||||
except Exception as e:
|
||||
logger.info("Etherpad Server doesn't work. Error: %s", e)
|
||||
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
docus = Document.objects.filter(task__id=self.object.id).order_by("-date")
|
||||
context["documents"] = docus
|
||||
try:
|
||||
context["topic"] = Topic.objects.get(task_list=self.object.task_list)
|
||||
except ObjectDoesNotExist:
|
||||
context["topic"] = None
|
||||
return context
|
||||
|
||||
|
||||
class DocumentCreateView(LoginRequiredMixin, CreateView):
|
||||
model = Document
|
||||
template_name = "tasks/attachment_create.html"
|
||||
form_class = DocumentCreateForm
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.created_by = self.request.user
|
||||
add_log_action(self.request, form, "tasks", "document", True)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
slug = self.kwargs.get("slug")
|
||||
context["task"] = Task.objects.get(slug=slug)
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("tasks:task", kwargs=self.kwargs)
|
||||
@@ -161,7 +161,6 @@
|
||||
x-transition:leave-end="transform origin-top opacity-0 scale-95"
|
||||
>
|
||||
<li class="navInternal"><a href="{% url 'admin:index' %}"><i class="fa-fw fa-solid fa-user-secret mr-2"></i>Admin</a></li>
|
||||
<li class="navInternal"><a href="{% url 'tasks:index' %}"><i class="fa-fw fa-solid fa-list-check mr-2"></i>Tasks</a></li>
|
||||
<li class="navInternal"><a href="{% url 'intern:index' %}"><i class="fa-fw fa-solid fa-database mr-2"></i>Intern</a></li>
|
||||
<li class="navInternal"><a href="https://wiki.fet.at"><i class="fa-fw fa-brands fa-wikipedia-w mr-2"></i></i>Wiki</a></li>
|
||||
<li class="navInternal"><a href="https://mail.fet.at"><i class="fa-fw fa-solid fa-inbox mr-2"></i></i>Mail</a></li>
|
||||
|
||||
@@ -19,17 +19,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- TODO: tasks -->
|
||||
{% if tasks %}
|
||||
<ul class="flex flex-col gap-1 max-w-fit">
|
||||
{% for task in tasks %}
|
||||
<li>
|
||||
<span class="ml-2">{{ task.title|truncatechars:45 }} <a href="{% url 'tasks:task' task.slug %}" class="inline-block text-proprietary dark:text-proprietary-lighter">Link <i class="fa-solid fa-link"></i></a></span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<ul class="flex flex-col gap-1 max-w-fit">
|
||||
{% for attachment in attachments %}
|
||||
<li><a href="{% url 'intern:attachment' topic.topic_group.slug topic.slug attachment.slug %}" class="py-1 inline-block">{{ attachment.title }}</a></li>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Etherpad hinzufügen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main class="container mx-auto w-full px-4 my-8 flex-1">
|
||||
<h1 class="page-title">Etherpad hinzufügen</h1>
|
||||
<div class="w-full h-full flex-1 flex justify-center items-center">
|
||||
<form action="" method="POST" class="w-full max-w-prose sm:px-28 sm:py-4 grid grid-cols-1 gap-y-3 sm:gap-y-6 text-gray-900">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<i class="alert-icon fa-solid fa-check-circle"></i>
|
||||
<h2 class="alert-title">Fehler:</h2>
|
||||
<div class="alert-body">{{ form.non_field_errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<label class="block">
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.title.label }}</span>
|
||||
{% if form.title.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.title.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="text" id="id_title" name="title" class="mt-1 block w-full rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.date.label }}</span>
|
||||
{% if form.date.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.date.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="date" id="id_date" name="date" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
</label>
|
||||
|
||||
<input type="hidden" name="task" value="{{ task.id }}" id="id_task">
|
||||
|
||||
<input type="submit" class="block btn btn-primary" value="Hinzufügen">
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,128 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Tasks{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main x-data="modal" class="container mx-auto w-full px-4 my-8 flex-1">
|
||||
<h1 class="page-title">Tasks</h1>
|
||||
<div class="sm:flex sm:flex-row-reverse justify-center">
|
||||
<aside class="sm:w-2/5 sm:max-w-xs sm:pl-4 lg:pl-8 my-8 sm:my-0">
|
||||
<div class="z-10 fixed sm:sticky top-0 sm:top-4 lg:top-8 left-0 w-full h-full sm:h-auto bg-black sm:bg-transparent bg-opacity-70 flex sm:block items-center justify-center"
|
||||
x-show="getShowModal"
|
||||
x-transition:enter="transition duration-300 ease-out"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition duration-150 ease-in"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
>
|
||||
<div class="max-w-sm sm:w-full mx-4 sm:mx-0 p-4 rounded bg-white dark:bg-gray-800 sm:shadow-lg sm:dark:border-2 sm:dark:border-gray-700"
|
||||
@click.outside="toggle"
|
||||
x-show="getShowModal"
|
||||
x-transition:enter="transition transform ease-out duration-300"
|
||||
x-transition:enter-start="scale-110 opacity-0"
|
||||
x-transition:enter-end="scale-100 opacity-100"
|
||||
x-transition:leave="transition transform ease-in duration-150"
|
||||
x-transition:leave-start="scale-100 opacity-100"
|
||||
x-transition:leave-end="scale-110 opacity-0"
|
||||
>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<h2 class="text-gray-800 dark:text-gray-100 sm:section-title sm:section-title-margins sm:w-full">
|
||||
<span class="mr-1 text-gray-400 sm:hidden">
|
||||
<i class="fa-solid fa-filter"></i>
|
||||
</span>
|
||||
Auswahl einschränken
|
||||
</h2>
|
||||
<div class="ml-4 -mr-2 px-2 rounded text-xl text-gray-600 dark:text-gray-400 sm:hidden cursor-pointer" @click="closeModal">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
<form action="" method="post" class="grid grid-cols-1 gap-2 sm:gap-4">
|
||||
{% csrf_token %}
|
||||
<label class="block">
|
||||
<span class="text-gray-700 dark:text-gray-200">Task-Gruppe</span>
|
||||
<select id="id_tasklist" name="tasklist" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<option value="all" {% if not show_tasklist %}selected{% endif %}>alle Task-Gruppen</option>
|
||||
{% regroup tasks by task_list as section_list %}
|
||||
{% for group in section_list %}
|
||||
<option value="{{ group.grouper.id }}" {% if show_tasklist == group.grouper.id %}selected{% endif %}>{{ group.grouper.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">Tasks</span>
|
||||
<select id="id_task" name="tasks" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<option value="assigned" {% if assigned_tasks %}selected{% endif %}>dir zugewiesene</option>
|
||||
<option value="all" {% if not assigned_tasks %}selected{% endif %}>alle</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="inline-flex items-center">
|
||||
<input type="checkbox" name="open_tasks" {% if state_open %}checked{% endif %} class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<span class="ml-2 text-gray-700 dark:text-gray-200">Offene Tasks</span>
|
||||
</label>
|
||||
<label class="inline-flex items-center">
|
||||
<input type="checkbox" name="closed_tasks" {% if state_closed %}checked{% endif %} class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<span class="ml-2 text-gray-700 dark:text-gray-200">Geschlossene Tasks</span>
|
||||
</label>
|
||||
<input type="submit" class="block btn btn-primary" value="Anzeigen">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button id="modal-trigger-1" class="z-10 trigger fixed bottom-4 right-4 bg-proprietary-darker dark:bg-sky-500 text-blue-50 dark:text-sky-900 shadow-lg text-2xl rounded sm:hidden"
|
||||
@click="openModal"
|
||||
x-show="getNotShowModal"
|
||||
x-transition:enter="transition duration-100 ease-in"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition duration-100 ease-out"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
>
|
||||
<i class="fa-solid fa-filter p-2"></i>
|
||||
</button>
|
||||
</aside>
|
||||
|
||||
{% if tasks %}
|
||||
<form action="" method="post" class="my-8 sm:my-0 sm:w-3/5 xl:w-2/5 flex flex-col gap-2 text-gray-600 dark:text-gray-300">
|
||||
{% csrf_token %}
|
||||
|
||||
{% regroup tasks by task_list as section_list %}
|
||||
{% for group in section_list %}
|
||||
<section>
|
||||
<h2 class="mb-1 text-gray-700 dark:text-gray-200">{{ group.grouper }}</h2>
|
||||
|
||||
{% for task in group.list %}
|
||||
<label class="mb-2 flex justify-between items-start">
|
||||
<div class="inline-flex items-baseline mr-2">
|
||||
<input type="checkbox" name="checkbox" value="{{ task.id }}" {% if task.completed %}checked{% endif %} class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<span class="ml-2">{{ task.title|truncatechars:45 }} <a href="{% url 'tasks:task' task.slug %}" class="inline-block text-proprietary dark:text-proprietary-lighter">Link <i class="fa-solid fa-link"></i></a></span>
|
||||
</div>
|
||||
{% if task.due_date %}
|
||||
<div class="inline-flex gap-2 flex-shrink-0">
|
||||
<span class="px-2 py-0.5 rounded-full text-sm font-medium text-proprietary dark:text-blue-100 bg-blue-200 dark:bg-proprietary-dark"><i class="fa-solid fa-hourglass mr-1"></i>{{ task.due_date|date:"d.m.Y" }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-y-2 md:gap-y-0 md:gap-x-2 lg:justify-end mt-4">
|
||||
<input type="submit" name="btn_checkbox" value="Tasks abschließen" class="btn btn-success block md:flex-grow lg:flex-grow-0">
|
||||
|
||||
<a href="{% url 'tasks:task_create' %}" class="btn btn-primary block md:flex-grow lg:flex-grow-0"><i class="fa-solid fa-plus-square mr-2"></i>Task hinzufügen</a>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<section>
|
||||
<h2 class="mb-1 text-gray-700 dark:text-gray-200">Keine Tasks in dieser Liste für dich.</h2>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-y-2 md:gap-y-0 md:gap-x-2 lg:justify-end mt-4">
|
||||
<a href="{% url 'tasks:task_create' %}" class="btn btn-primary block md:flex-grow lg:flex-grow-0"><i class="fa-solid fa-plus-square mr-2"></i>Task hinzufügen</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,86 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Task hinzufügen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main class="container mx-auto w-full px-4 my-8 flex-1">
|
||||
<h1 class="page-title">Task hinzufügen</h1>
|
||||
<div class="w-full h-full flex-1 flex justify-center items-center">
|
||||
<form action="" method="POST" class="w-full max-w-xs sm:max-w-prose sm:px-28 sm:py-4 grid grid-cols-1 gap-y-3 sm:gap-y-6 text-gray-900">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<i class="alert-icon fa-solid fa-check-circle"></i>
|
||||
<h2 class="alert-title">Fehler:</h2>
|
||||
<div class="alert-body">{{ form.non_field_errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<label class="block">
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.title.label }}</span>
|
||||
{% if form.title.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.title.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="text" id="id_title" name="title" class="mt-1 block w-full rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.task_list.label }}</span>
|
||||
{% if form.task_list.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.task_list.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<select id="id_task_list" name="task_list" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50" required>
|
||||
{% for elem in form.task_list %}
|
||||
{% if forloop.first %}
|
||||
<option value="">---------</option>
|
||||
{% else %}
|
||||
{{ elem }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.due_date.label }}</span>
|
||||
{% if form.due_date.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.due_date.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="date" id="id_due_date" name="due_date" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.assigned_to.label }}</span>
|
||||
{% if form.assigned_to.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.assigned_to.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<select id="id_assigned_to" name="assigned_to" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
{% for elem in form.assigned_to %}
|
||||
{% if forloop.first %}
|
||||
<option value="">Alle</option>
|
||||
{% else %}
|
||||
{{ elem }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div class="flex flex-col-reverse sm:flex-row gap-3 justify-end pt-4 sm:pt-0">
|
||||
<a href="{% url 'admin:tasks_tasklist_add' %}" class="block btn btn-secondary-proprietary">Task-Gruppe hinzufügen</a>
|
||||
<input type="submit" class="block btn btn-primary" value="Hinzufügen">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,46 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ task.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main class="container mx-auto w-full px-4 my-8 flex-1">
|
||||
<h1 class="page-title">Task-Detailansicht</h1>
|
||||
<div class="flex flex-col gap-y-4 sm:gap-y-4 max-w-prose mx-auto text-gray-700 dark:text-gray-300">
|
||||
<aside class="flex gap-2 flex-wrap align-bottom text-sm sm:text-base text-gray-600 dark:text-gray-300">
|
||||
<a class="underline hover:text-gray-900 dark:hover:text-gray-100" href="{% url 'tasks:index' %}">{{ task.task_list.name }}</a>
|
||||
<span><i class="fa-solid fa-angle-right"></i></span>
|
||||
<span class="cursor-default">{{ task.title }}</span>
|
||||
</aside>
|
||||
{% if task.note %}
|
||||
<div class="db-page-content-left">
|
||||
{{ task.note|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if task.due_date %}
|
||||
<div class="text-right -mt-6">
|
||||
{{ task.due_date }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<section>
|
||||
<div class="documentList rounded divide-y divide-gray-300 dark:divide-gray-600">
|
||||
<a href="{% url 'tasks:docu_create' task.slug %}" class="flex justify-between">
|
||||
<h3 class="text-gray-800 dark:text-gray-200"><i class="fa-solid fa-plus fa-fw mr-1"></i>Neues Etherpad erstellen</h2>
|
||||
</a>
|
||||
|
||||
{% for document in documents %}
|
||||
<a href="{{ document.get_absolute_url }}" class="flex justify-between items-center gap-2">
|
||||
<h3 class="text-gray-800 dark:text-gray-200">{{ document.title }}</h2>
|
||||
<span class=" text-gray-700 dark:text-gray-300">{{ document.date }}<span class="ml-2 hidden sm:inline-block"><i class="fa-solid fa-angle-right text-gray-400 dark:text-gray-600"></i></span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<a href="{% url 'tasks:task_update' task.slug %}" class="btn btn-primary block place-self-end"><i class="fa-solid fa-pen-to-square mr-2"></i>Task bearbeiten</a>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,89 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ task.title }} bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main class="container mx-auto w-full px-4 my-8 flex-1">
|
||||
<h1 class="page-title">Task '{{ task.title }}' bearbeiten</h1>
|
||||
<div class="w-full h-full flex-1 flex justify-center items-center">
|
||||
<form action="" method="POST" class="w-full max-w-prose sm:px-28 sm:py-4 grid grid-cols-1 gap-y-3 sm:gap-y-6 text-gray-900">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<i class="alert-icon fa-solid fa-check-circle"></i>
|
||||
<h2 class="alert-title">Fehler:</h2>
|
||||
<div class="alert-body">{{ form.non_field_errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.assigned_to.label }}</span>
|
||||
{% if form.assigned_to.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.assigned_to.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<select id="id_assigned_to" name="assigned_to" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
{% for elem in form.assigned_to %}
|
||||
{% if forloop.first %}
|
||||
<option value="">Alle</option>
|
||||
{% else %}
|
||||
{{ elem }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.due_date.label }}</span>
|
||||
{% if form.due_date.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.due_date.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="date" id="id_due_date" name="due_date" value="{{ task.due_date|date:"Y-m-d" }}" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.completed_date.label }}</span>
|
||||
{% if form.completed_date.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.completed_date.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="date" id="id_completed_date" name="completed_date" value="{{ task.completed_date|date:"Y-m-d" }}" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" id="id_completed" name="completed" value="{{ task.id }}" {% if task.completed %}checked{% endif %} class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.completed.label }}</span>
|
||||
{% if form.completed.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.completed.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</label>
|
||||
|
||||
<label class="block">
|
||||
<span class="text-gray-700 dark:text-gray-200">{{ form.note.label }}</span>
|
||||
{% if form.note.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<div class="alert-body">{{ form.note.errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ form.media }}
|
||||
{{ form.note }}
|
||||
</label>
|
||||
|
||||
<input type="hidden" name="task_list" value="{{ task.task_list.id }}" id="id_task_list">
|
||||
|
||||
<div class="flex flex-col-reverse sm:flex-row gap-3 justify-end pt-4 sm:pt-0">
|
||||
<a href="{% url 'admin:tasks_task_change' task.id %}" class="block btn btn-secondary-proprietary">Task im Admin bearbeiten</a>
|
||||
<input type="submit" class="block btn btn-primary" value="Speichern">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user