diff --git a/taskapp/forms.py b/taskapp/forms.py index 45b2bf7..326a16c 100644 --- a/taskapp/forms.py +++ b/taskapp/forms.py @@ -1,30 +1,44 @@ -# -*- coding: utf-8 -*- from django.utils.translation import ugettext as _ -from datetime import timedelta from django import forms -from django.utils import timezone -from .models import Task +from .models import Task, ExtraComment, _delta_add_days +from accounts_app.models import UserProfile class TaskFrm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super(TaskFrm, self).__init__(*args, **kwargs) + self.fields['recipients'].queryset = UserProfile.objects.filter(is_admin=True) class Meta: model = Task - exclude = ['time_of_create', 'author', 'recipients', 'device'] + exclude = ['time_of_create', 'author', 'device'] widgets = { 'descr': forms.TextInput(attrs={ 'placeholder': _('Short description'), - 'class': "form-control", 'autofocus': '' }), - #'device': forms.Select(attrs={'class': 'form-control', 'required':''}), - 'priority': forms.Select(attrs={'class': 'form-control'}), - 'state': forms.Select(attrs={'class': 'form-control'}), + 'recipients': forms.SelectMultiple(attrs={ + 'size': 10 + }), 'out_date': forms.DateInput(attrs={'class': 'form-control'}), - 'attachment': forms.FileInput(attrs={'class': 'form-control'}), - 'mode': forms.Select(attrs={'class': 'form-control'}), 'abon': forms.Select(attrs={'class': 'form-control'}) } initials = { - 'out_date': timezone.now()+timedelta(days=3) + 'out_date': _delta_add_days() } + + +class ExtraCommentForm(forms.ModelForm): + + def make_save(self, author, task): + comment = super(ExtraCommentForm, self).save(commit=False) + comment.author = author + comment.task = task + return comment.save() + + def save(self, commit=True): + raise Exception('You must use ExtraCommentForm.make_save() method') + + class Meta: + model = ExtraComment + fields = ['text'] diff --git a/taskapp/handle.py b/taskapp/handle.py index 087503d..4c57311 100644 --- a/taskapp/handle.py +++ b/taskapp/handle.py @@ -27,7 +27,7 @@ def handle(task, author, recipients, abon_group): fulltext = "%s\n" % text fulltext += _('locality %s.\n') % abon_group.title if task.abon: - fulltext += _('address %s %s.\ntelephone %s\n') % ( + fulltext += _('address %(street)s %(house)s.\ntelephone %(telephone)s\n') % ( task.abon.street.name if task.abon.street is not None else '<'+_('not chosen')+'>', task.abon.house, task.abon.telephone diff --git a/taskapp/locale/ru/LC_MESSAGES/django.po b/taskapp/locale/ru/LC_MESSAGES/django.po index 24e999a..fbd98ed 100644 --- a/taskapp/locale/ru/LC_MESSAGES/django.po +++ b/taskapp/locale/ru/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-03-25 00:40+0300\n" +"POT-Creation-Date: 2018-02-19 16:36+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Dmitry Novikov nerosketch@gmail.com\n" "Language: ru\n" @@ -13,350 +13,420 @@ msgstr "" "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" "%100>=11 && n%100<=14)? 2 : 3);\n" -#: taskapp/forms.py:16 +#: forms.py:17 msgid "Short description" msgstr "Краткое описание" -#: taskapp/handle.py:14 +#: handle.py:17 views.py:234 msgid "Task" msgstr "Задача" -#: taskapp/handle.py:23 +#: handle.py:23 msgid "Task completed" msgstr "Задача завершена" -#: taskapp/handle.py:31 +#: handle.py:28 #, python-format msgid "locality %s.\n" msgstr "с. %s\n" -#: taskapp/handle.py:33 -#, python-format +#: handle.py:30 msgid "" -"address %s %s.\n" -"telephone %s\n" +"address %(street)s %(house)s.\n" +"telephone %(telephone)s\n" msgstr "по адресу %s %s тел. %s.\n" -#: taskapp/handle.py:34 taskapp/models.py:26 +#: handle.py:31 models.py:25 msgid "not chosen" msgstr "не выбрано" -#: taskapp/handle.py:38 +#: handle.py:35 #, python-format msgid "Task type - %s." msgstr "Тип задачи - %s." -#: taskapp/models.py:14 +#: models.py:13 msgid "Higher" msgstr "Высший" -#: taskapp/models.py:15 +#: models.py:14 msgid "Average" msgstr "Средний" -#: taskapp/models.py:16 +#: models.py:15 msgid "Low" msgstr "Низкий" -#: taskapp/models.py:20 +#: models.py:19 msgid "New" msgstr "Новая" -#: taskapp/models.py:21 +#: models.py:20 msgid "Confused" msgstr "Провалена" -#: taskapp/models.py:22 +#: models.py:21 msgid "Completed" msgstr "Выполнена" -#: taskapp/models.py:27 +#: models.py:26 +msgid "ip conflict" +msgstr "Ip конфликт" + +#: models.py:27 msgid "yellow triangle" msgstr "жёлтый треугольник" -#: taskapp/models.py:28 +#: models.py:28 msgid "red cross" msgstr "красный крестик" -#: taskapp/models.py:29 +#: models.py:29 msgid "weak speed" msgstr "слабая скорость" -#: taskapp/models.py:30 +#: models.py:30 msgid "cable break" msgstr "обрыв кабеля" -#: taskapp/models.py:31 +#: models.py:31 msgid "connection" msgstr "подключение" -#: taskapp/models.py:32 +#: models.py:32 msgid "periodic disappearance" msgstr "переодическое пропадание" -#: taskapp/models.py:33 +#: models.py:33 msgid "router setup" msgstr "настройка роутера" -#: taskapp/models.py:34 +#: models.py:34 msgid "configure onu" msgstr "настроить onu" -#: taskapp/models.py:35 +#: models.py:35 msgid "crimp cable" msgstr "обжать кабель" -#: taskapp/models.py:36 +#: models.py:36 +msgid "Internet crash" +msgstr "Нет интернета" + +#: models.py:37 msgid "other" msgstr "другое" -#: taskapp/models.py:43 +#: models.py:44 msgid "Change task" msgstr "Изменение задачи" -#: taskapp/models.py:44 +#: models.py:45 msgid "Create task" msgstr "Создание задачи" -#: taskapp/models.py:45 +#: models.py:46 msgid "Delete task" msgstr "Удаление задачи" -#: taskapp/models.py:46 +#: models.py:47 msgid "Completing tasks" msgstr "Завершение задачи" -#: taskapp/models.py:47 +#: models.py:48 msgid "The task failed" msgstr "Задача провалена" -#: taskapp/models.py:78 +#: models.py:63 templates/taskapp/details.html:8 +#: templates/taskapp/tasklist.html:13 templates/taskapp/tasklist_all.html:25 +#: templates/taskapp/tasklist_failed.html:13 +#: templates/taskapp/tasklist_finish.html:13 +#: templates/taskapp/tasklist_own.html:13 +msgid "Description" +msgstr "Описание" + +#: models.py:65 templates/taskapp/details.html:10 +#: templates/taskapp/tasklist.html:14 templates/taskapp/tasklist_all.html:26 +#: templates/taskapp/tasklist_failed.html:14 +#: templates/taskapp/tasklist_finish.html:14 +msgid "Task author" +msgstr "Автор задачи" + +#: models.py:66 templates/taskapp/details.html:18 +msgid "A priority" +msgstr "Приоритет" + +#: models.py:67 templates/taskapp/add_edit_task.html:65 +msgid "Reality" +msgstr "Актуальность (дата, до которой нужно завершить задачу)" + +#: models.py:68 templates/taskapp/details.html:20 +#: templates/taskapp/tasklist.html:15 templates/taskapp/tasklist_all.html:28 +#: templates/taskapp/tasklist_failed.html:15 +#: templates/taskapp/tasklist_finish.html:15 +#: templates/taskapp/tasklist_own.html:15 +msgid "Date of create" +msgstr "Дата создания" + +#: models.py:69 templates/taskapp/details.html:23 +#: templates/taskapp/tasklist_all.html:27 +#: templates/taskapp/tasklist_own.html:14 +msgid "Condition" +msgstr "Состояние" + +#: models.py:70 +msgid "Attached image" +msgstr "Прикреплённое изображение" + +#: models.py:71 templates/taskapp/tasklist.html:12 +#: templates/taskapp/tasklist_all.html:24 +#: templates/taskapp/tasklist_failed.html:12 +#: templates/taskapp/tasklist_finish.html:12 +#: templates/taskapp/tasklist_own.html:12 +msgid "The nature of the damage" +msgstr "Характер поломки" + +#: models.py:72 templates/taskapp/add_edit_task.html:49 +#: templates/taskapp/details.html:24 +msgid "Subscriber" +msgstr "Абонент" + +#: models.py:78 msgid "Access to all tasks" msgstr "Доступ ко всем задачам" -#: taskapp/models.py:79 +#: models.py:79 msgid "Reminders of tasks" msgstr "Напоминания о задачах" -#: taskapp/templates/taskapp/add_edit_task.html:7 -#: taskapp/templates/taskapp/tasklist_all.html:7 -#: taskapp/templates/taskapp/view.html:7 +#: models.py:109 +msgid "Text of comment" +msgstr "Текст комментария" + +#: models.py:110 +msgid "Owner task" +msgstr "Владелец задачи" + +#: models.py:111 +msgid "Author" +msgstr "Автор" + +#: models.py:112 +msgid "Time of create" +msgstr "Дата создания" + +#: models.py:120 +msgid "Can view comments" +msgstr "Может видеть комментарии" + +#: models.py:122 +msgid "Extra comment" +msgstr "Комментарий" + +#: models.py:123 +msgid "Extra comments" +msgstr "Комментарии" + +#: templates/taskapp/add_edit_task.html:8 templates/taskapp/tasklist_all.html:8 msgid "Tasks" msgstr "Задачи" -#: taskapp/templates/taskapp/add_edit_task.html:8 -#: taskapp/templates/taskapp/tasklist.html:60 -#: taskapp/templates/taskapp/tasklist_active.html:57 -#: taskapp/templates/taskapp/tasklist_all.html:72 -#: taskapp/templates/taskapp/tasklist_finish.html:54 -#: taskapp/templates/taskapp/tasklist_own.html:53 +#: templates/taskapp/add_edit_task.html:9 templates/taskapp/tasklist.html:82 +#: templates/taskapp/tasklist_all.html:90 +#: templates/taskapp/tasklist_failed.html:58 +#: templates/taskapp/tasklist_finish.html:64 +#: templates/taskapp/tasklist_own.html:61 msgid "Edit" msgstr "Редактировать" -#: taskapp/templates/taskapp/add_edit_task.html:8 +#: templates/taskapp/add_edit_task.html:9 msgid "Create" msgstr "Создать" -#: taskapp/templates/taskapp/add_edit_task.html:15 -#: taskapp/templates/taskapp/footer_btns.html:3 -#: taskapp/templates/taskapp/footer_btns.html:4 -#: taskapp/templates/taskapp/tasklist_all.html:93 -#: taskapp/templates/taskapp/tasklist_all.html:94 +#: templates/taskapp/add_edit_task.html:19 templates/taskapp/footer_btns.html:5 +#: templates/taskapp/tasklist_all.html:111 +#: templates/taskapp/tasklist_all.html:112 msgid "Add new task" msgstr "Добавьте задачу" -#: taskapp/templates/taskapp/add_edit_task.html:27 -#: taskapp/templates/taskapp/tasklist.html:13 -#: taskapp/templates/taskapp/tasklist_active.html:13 -#: taskapp/templates/taskapp/tasklist_all.html:25 -#: taskapp/templates/taskapp/tasklist_finish.html:13 -#: taskapp/templates/taskapp/tasklist_own.html:13 -#: taskapp/templates/taskapp/view.html:19 -msgid "Description" -msgstr "Описание" +#: templates/taskapp/add_edit_task.html:21 +msgid "Edit task" +msgstr "Редактировать задачу" -#: taskapp/templates/taskapp/add_edit_task.html:35 -#: taskapp/templates/taskapp/tasklist.html:12 -#: taskapp/templates/taskapp/tasklist_active.html:12 -#: taskapp/templates/taskapp/tasklist_all.html:24 -#: taskapp/templates/taskapp/tasklist_finish.html:12 -#: taskapp/templates/taskapp/tasklist_own.html:12 -msgid "The nature of the damage" -msgstr "Характер поломки" +#: templates/taskapp/add_edit_task.html:56 +#: templates/taskapp/add_edit_task.html:59 +msgid "Find the subscriber" +msgstr "Найти абонента" -#: taskapp/templates/taskapp/add_edit_task.html:43 -#: taskapp/templates/taskapp/view.html:29 -msgid "A priority" -msgstr "Приоритет" +#: templates/taskapp/add_edit_task.html:85 +msgid "Save" +msgstr "Сохранить" -#: taskapp/templates/taskapp/add_edit_task.html:51 -#: taskapp/templates/taskapp/tasklist_all.html:27 -#: taskapp/templates/taskapp/tasklist_own.html:14 -#: taskapp/templates/taskapp/view.html:34 -msgid "Condition" -msgstr "Состояние" +#: templates/taskapp/add_edit_task.html:88 +msgid "Reset" +msgstr "Сбросить" -#: taskapp/templates/taskapp/add_edit_task.html:59 -#: taskapp/templates/taskapp/view.html:35 -msgid "Subscriber" -msgstr "Абонент" +#: templates/taskapp/add_edit_task.html:92 +#: templates/taskapp/comments/extracomment_confirm_delete.html:15 +#: templates/taskapp/comments/task_comments.html:13 +#: templates/taskapp/tasklist_own.html:71 +msgid "Delete" +msgstr "Удалить" -#: taskapp/templates/taskapp/add_edit_task.html:75 -msgid "Reality" -msgstr "Актуальность (дата, до которой нужно завершить задачу)" +#: templates/taskapp/comments/extracomment_confirm_delete.html:6 +msgid "Delete comment" +msgstr "Удаление комментарий" -#: taskapp/templates/taskapp/add_edit_task.html:90 -msgid "Attached image" -msgstr "Прикреплённое изображение" +#: templates/taskapp/comments/extracomment_confirm_delete.html:10 +#, python-format +msgid "Are you sure you want to delete \"%(object)s\"?" +msgstr "Вы уверены что хотите удалить \"%(object)s\"?" -#: taskapp/templates/taskapp/add_edit_task.html:98 -msgid "Save" -msgstr "Сохранить" +#: templates/taskapp/comments/task_comments.html:5 +msgid "Task comments" +msgstr "Комментарии задачи" -#: taskapp/templates/taskapp/add_edit_task.html:101 -msgid "Reset" -msgstr "Сбросить" +#: templates/taskapp/comments/task_comments.html:25 +msgid "Comment history is empty" +msgstr "Коментариев нет" + +#: templates/taskapp/comments/task_comments.html:33 +msgid "Send" +msgstr "Отправить" + +#: templates/taskapp/details.html:4 +msgid "Task details" +msgstr "Детали задачи" + +#: templates/taskapp/details.html:12 +msgid "Implementers" +msgstr "Исполнители" + +#: templates/taskapp/details.html:19 +msgid "The task is valid until" +msgstr "Задача действительна до" + +#: templates/taskapp/details.html:22 +msgid "Task type" +msgstr "Тип задачи" + +#: templates/taskapp/details.html:28 templates/taskapp/tasklist_all.html:58 +#: templates/taskapp/tasklist_all.html:71 +#: templates/taskapp/tasklist_failed.html:41 +#: templates/taskapp/tasklist_finish.html:45 +#: templates/taskapp/tasklist_finish.html:46 +#: templates/taskapp/tasklist_own.html:46 +#: templates/taskapp/tasklist_own.html:47 +msgid "Not assigned" +msgstr "<Не назначено>" + +#: templates/taskapp/details.html:31 +msgid "Attachment" +msgstr "Приложение" -#: taskapp/templates/taskapp/footer_btns.html:9 +#: templates/taskapp/footer_btns.html:10 msgid "View all tasks" msgstr "Просмотреть все задачи" -#: taskapp/templates/taskapp/tasklist.html:10 -#: taskapp/templates/taskapp/tasklist_active.html:10 -#: taskapp/templates/taskapp/tasklist_all.html:22 -#: taskapp/templates/taskapp/tasklist_finish.html:10 -#: taskapp/templates/taskapp/tasklist_own.html:10 +#: templates/taskapp/tasklist.html:10 templates/taskapp/tasklist_all.html:22 +#: templates/taskapp/tasklist_failed.html:10 +#: templates/taskapp/tasklist_finish.html:10 +#: templates/taskapp/tasklist_own.html:10 msgid "Name" msgstr "ФИО" -#: taskapp/templates/taskapp/tasklist.html:11 -#: taskapp/templates/taskapp/tasklist_active.html:11 -#: taskapp/templates/taskapp/tasklist_all.html:23 -#: taskapp/templates/taskapp/tasklist_finish.html:11 -#: taskapp/templates/taskapp/tasklist_own.html:11 +#: templates/taskapp/tasklist.html:11 templates/taskapp/tasklist_all.html:23 +#: templates/taskapp/tasklist_failed.html:11 +#: templates/taskapp/tasklist_finish.html:11 +#: templates/taskapp/tasklist_own.html:11 msgid "Address" msgstr "Адрес" -#: taskapp/templates/taskapp/tasklist.html:14 -#: taskapp/templates/taskapp/tasklist_active.html:14 -#: taskapp/templates/taskapp/tasklist_all.html:26 -#: taskapp/templates/taskapp/tasklist_finish.html:14 -#: taskapp/templates/taskapp/view.html:21 -msgid "Task author" -msgstr "Автор задачи" - -#: taskapp/templates/taskapp/tasklist.html:15 -#: taskapp/templates/taskapp/tasklist_active.html:15 -#: taskapp/templates/taskapp/tasklist_all.html:28 -#: taskapp/templates/taskapp/tasklist_finish.html:15 -#: taskapp/templates/taskapp/tasklist_own.html:15 -#: taskapp/templates/taskapp/view.html:31 -msgid "Date of create" -msgstr "Дата создания" - -#: taskapp/templates/taskapp/tasklist.html:16 -#: taskapp/templates/taskapp/tasklist_active.html:16 -#: taskapp/templates/taskapp/tasklist_all.html:29 -#: taskapp/templates/taskapp/tasklist_finish.html:16 -#: taskapp/templates/taskapp/tasklist_own.html:16 +#: templates/taskapp/tasklist.html:16 templates/taskapp/tasklist_all.html:29 +#: templates/taskapp/tasklist_failed.html:16 +#: templates/taskapp/tasklist_own.html:16 msgid "Actions" msgstr "Действия" -#: taskapp/templates/taskapp/tasklist.html:40 -#: taskapp/templates/taskapp/tasklist_active.html:40 -#: taskapp/templates/taskapp/tasklist_all.html:53 -#: taskapp/templates/taskapp/tasklist_all.html:64 -#: taskapp/templates/taskapp/tasklist_finish.html:40 -#: taskapp/templates/taskapp/tasklist_own.html:40 -#: taskapp/templates/taskapp/view.html:39 -msgid "Not assigned" -msgstr "<Не назначено>" - -#: taskapp/templates/taskapp/tasklist.html:42 -#: taskapp/templates/taskapp/tasklist_active.html:42 -#: taskapp/templates/taskapp/tasklist_all.html:55 -#: taskapp/templates/taskapp/tasklist_finish.html:42 -#: taskapp/templates/taskapp/tasklist_own.html:42 taskapp/views.py:151 +#: templates/taskapp/tasklist.html:48 templates/taskapp/tasklist_all.html:60 +#: templates/taskapp/tasklist_failed.html:43 +#: templates/taskapp/tasklist_finish.html:49 +#: templates/taskapp/tasklist_own.html:50 msgid "User does not exist" msgstr "Абонент не найден" -#: taskapp/templates/taskapp/tasklist.html:53 -msgid "Mark as unsuccessful" -msgstr "Отметить задачу как проваленную" +#: templates/taskapp/tasklist.html:58 +msgid "Author does not exist" +msgstr "Автор не найден" + +#: templates/taskapp/tasklist.html:66 templates/taskapp/tasklist_all.html:80 +msgid "Today" +msgstr "Сегодня" -#: taskapp/templates/taskapp/tasklist.html:56 -#: taskapp/templates/taskapp/tasklist_active.html:53 +#: templates/taskapp/tasklist.html:68 templates/taskapp/tasklist_all.html:82 +msgid "Yesterday" +msgstr "Вчера" + +#: templates/taskapp/tasklist.html:75 templates/taskapp/tasklist_failed.html:54 msgid "Complete" msgstr "Завершить" -#: taskapp/templates/taskapp/tasklist.html:68 -#: taskapp/templates/taskapp/tasklist_active.html:65 -#: taskapp/templates/taskapp/tasklist_all.html:85 -#: taskapp/templates/taskapp/tasklist_finish.html:67 +#: templates/taskapp/tasklist.html:78 +msgid "Mark as unsuccessful" +msgstr "Отметить задачу как проваленную" + +#: templates/taskapp/tasklist.html:90 templates/taskapp/tasklist_all.html:103 +#: templates/taskapp/tasklist_failed.html:66 +#: templates/taskapp/tasklist_finish.html:72 msgid "The list is empty" msgstr "Список пуст" -#: taskapp/templates/taskapp/tasklist_all.html:8 +#: templates/taskapp/tasklist_all.html:9 msgid "All tasks" msgstr "Все задачи" -#: taskapp/templates/taskapp/tasklist_all.html:14 +#: templates/taskapp/tasklist_all.html:15 msgid "Records of all the tasks in the system" msgstr "Лог всех задач в системе" -#: taskapp/templates/taskapp/tasklist_all.html:77 -#: taskapp/templates/taskapp/tasklist_own.html:58 +#: templates/taskapp/tasklist_all.html:95 +#: templates/taskapp/tasklist_own.html:66 msgid "Remind" msgstr "Напомнить" -#: taskapp/templates/taskapp/tasklist_finish.html:59 -#: taskapp/templates/taskapp/tasklist_own.html:63 -msgid "Delete" -msgstr "Удалить" - -#: taskapp/templates/taskapp/tasklist_own.html:71 +#: templates/taskapp/tasklist_own.html:79 msgid "All your tasks has been performed" msgstr "Все ваши задачи выполнены" -#: taskapp/templates/taskapp/view.html:15 -msgid "Task description" -msgstr "Описание задачи" - -#: taskapp/templates/taskapp/view.html:23 -msgid "Implementers" -msgstr "Исполнители" - -#: taskapp/templates/taskapp/view.html:30 -msgid "The task is valid until" -msgstr "Задача действительна до" - -#: taskapp/templates/taskapp/view.html:32 -msgid "time left" -msgstr "Времени осталось" - -#: taskapp/templates/taskapp/view.html:33 -msgid "Task type" -msgstr "Тип задачи" - -#: taskapp/templates/taskapp/view.html:42 -msgid "Attachment" -msgstr "Приложение" - -#: taskapp/views.py:82 +#: views.py:99 msgid "You cannot delete task that assigned to you" msgstr "Вы не можете удалять назначенные на вас задачи" -#: taskapp/views.py:143 +#: views.py:141 +msgid "Task has changed successfully" +msgstr "Задача успешно изменена" + +#: views.py:143 msgid "No responsible employee for the users group" msgstr "Нет ответственных за группу, в которой находится выбранный абонент" -#: taskapp/views.py:145 +#: views.py:145 msgid "You must select the subscriber" msgstr "Нужно выбрать абонента" -#: taskapp/views.py:147 -msgid "Error in the form fields" -msgstr "Ошибка в полях формы" +#: views.py:160 +msgid "time left" +msgstr "Времени осталось" + +#: views.py:162 +#, python-format +msgid "Expired timeout -%(time_left)s" +msgstr "Время ожидания истекло -%(time_left)s" + +#: views.py:183 +msgid "fix form errors" +msgstr "исправте ошибки формы" + msgid "Failed tasks" msgstr "Проваленные задачи" @@ -378,19 +448,3 @@ msgstr "Задачи, которые необходимо выполнить" msgid "locality %s. Task type - %s. " msgstr "с. %s. Тип задачи - %s. " - -msgid "ip conflict" -msgstr "Ip конфликт" - -msgid "Internet crash" -msgstr "Нет интернета" - -msgid "Expired timeout -%(time_left)s" -msgstr "Время ожидания истекло -%(time_left)s" - -msgid "Yesterday" -msgstr "Вчера" - -msgid "Today" -msgstr "Сегодня" - diff --git a/taskapp/migrations/0002_auto_20180219_1255.py b/taskapp/migrations/0002_auto_20180219_1255.py new file mode 100644 index 0000000..cef44a8 --- /dev/null +++ b/taskapp/migrations/0002_auto_20180219_1255.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2018-02-19 12:55 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import taskapp.models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('taskapp', '0001_squashed_0015_auto_20170816_1109'), + ] + + operations = [ + migrations.CreateModel( + name='ExtraComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField(verbose_name='Text of comment')), + ('date_create', models.DateTimeField(auto_now_add=True, verbose_name='Time of create')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Author')), + ], + options={ + 'verbose_name': 'Extra comment', + 'verbose_name_plural': 'Extra comments', + 'db_table': 'extra_comments', + 'permissions': (('can_view_comments', 'Can view comments'),), + }, + ), + migrations.AlterModelOptions( + name='task', + options={'ordering': ('-id',), 'permissions': (('can_viewall', 'Access to all tasks'), ('can_remind', 'Reminders of tasks'))}, + ), + migrations.AlterField( + model_name='changelog', + name='act_type', + field=models.CharField(choices=[('e', 'Change task'), ('c', 'Create task'), ('d', 'Delete task'), ('f', 'Completing tasks'), ('b', 'The task failed')], max_length=1), + ), + migrations.AlterField( + model_name='task', + name='abon', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon', verbose_name='Subscriber'), + ), + migrations.AlterField( + model_name='task', + name='attachment', + field=models.ImageField(blank=True, null=True, upload_to='task_attachments/%Y.%m.%d', verbose_name='Attached image'), + ), + migrations.AlterField( + model_name='task', + name='author', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Task author'), + ), + migrations.AlterField( + model_name='task', + name='descr', + field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Description'), + ), + migrations.AlterField( + model_name='task', + name='mode', + field=models.CharField(choices=[('na', 'not chosen'), ('ic', 'ip conflict'), ('yt', 'yellow triangle'), ('rc', 'red cross'), ('ls', 'weak speed'), ('cf', 'cable break'), ('cn', 'connection'), ('pf', 'periodic disappearance'), ('cr', 'router setup'), ('co', 'configure onu'), ('fc', 'crimp cable'), ('ni', 'Internet crash'), ('ot', 'other')], default='na', max_length=2, verbose_name='The nature of the damage'), + ), + migrations.AlterField( + model_name='task', + name='out_date', + field=models.DateField(blank=True, default=taskapp.models._delta_add_days, null=True, verbose_name='Reality'), + ), + migrations.AlterField( + model_name='task', + name='priority', + field=models.CharField(choices=[('A', 'Higher'), ('C', 'Average'), ('E', 'Low')], default='E', max_length=1, verbose_name='A priority'), + ), + migrations.AlterField( + model_name='task', + name='state', + field=models.CharField(choices=[('S', 'New'), ('C', 'Confused'), ('F', 'Completed')], default='S', max_length=1, verbose_name='Condition'), + ), + migrations.AlterField( + model_name='task', + name='time_of_create', + field=models.DateTimeField(auto_now_add=True, verbose_name='Date of create'), + ), + migrations.AddField( + model_name='extracomment', + name='task', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='taskapp.Task', verbose_name='Owner task'), + ), + ] diff --git a/taskapp/models.py b/taskapp/models.py index 8c2a41e..86678e9 100644 --- a/taskapp/models.py +++ b/taskapp/models.py @@ -80,8 +80,8 @@ class Task(models.Model): ) def finish(self, current_user): - self.state = 'F' # Выполнена - self.out_date = timezone.now() # Время завершения + self.state = 'F' # Finished + self.out_date = timezone.now() # End time ChangeLog.objects.create( task=self, act_type='f', @@ -90,7 +90,7 @@ class Task(models.Model): self.save(update_fields=['state', 'out_date']) def do_fail(self, current_user): - self.state = 'C' # Провалена + self.state = 'C' # Crashed ChangeLog.objects.create( task=self, act_type='b', @@ -105,35 +105,33 @@ class Task(models.Model): return self.out_date < timezone.now().date() or self.state == 'F' +class ExtraComment(models.Model): + text = models.TextField(_('Text of comment')) + task = models.ForeignKey(Task, verbose_name=_('Owner task')) + author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('Author')) + date_create = models.DateTimeField(_('Time of create'), auto_now_add=True) + + def __str__(self): + return self.text + + class Meta: + db_table = 'extra_comments' + permissions = ( + ('can_view_comments', _('Can view comments')), + ) + verbose_name = _('Extra comment') + verbose_name_plural = _('Extra comments') + + def task_handler(sender, instance, **kwargs): - group = '' if instance.abon: group = instance.abon.group - if kwargs['created']: - ChangeLog.objects.create( - task=instance, - act_type='c', - who=instance.author - ) else: - ChangeLog.objects.create( - task=instance, - act_type='e', - who=instance.author - ) + group = '' task_handle( instance, instance.author, instance.recipients.all(), group ) -#def task_delete(sender, instance, **kwargs): -# ChangeLog.objects.create( -# task=instance, -# act_type='d', -# who=instance.author -# ) - - models.signals.post_save.connect(task_handler, sender=Task) -#models.signals.post_delete.connect(task_delete, sender=Task) diff --git a/taskapp/templates/taskapp/add_edit_task.html b/taskapp/templates/taskapp/add_edit_task.html index 212fa78..e9603fa 100644 --- a/taskapp/templates/taskapp/add_edit_task.html +++ b/taskapp/templates/taskapp/add_edit_task.html @@ -6,90 +6,105 @@ {% include 'message_block.html' %} -
-
- {% if task_id %} -

{% trans 'Add new task' %}

- {% else %} -

{% trans 'Edit task' %}

- {% endif %} -
-
+
+
+
+
+ {% if task.id %} +

{% trans 'Add new task' %}

+ {% else %} +

{% trans 'Edit task' %}

+ {% endif %} +
+
- {% if task_id %} -
- {% else %} - - {% endif %} - {% csrf_token %} + {% if task.id %} + + {% else %} + + {% endif %} + {% csrf_token %} - {% bootstrap_icon 'tag' as ic %} - {% bootstrap_field form.descr addon_before=ic %} + {% bootstrap_icon 'tag' as ic %} + {% bootstrap_field form.descr addon_before=ic %} - {% bootstrap_icon 'pawn' as ic %} - {% bootstrap_field form.mode addon_before=ic %} + {% bootstrap_icon 'task' as ic %} + {% bootstrap_field form.recipients addon_before=ic %} - {% bootstrap_icon 'sort-by-order' as ic %} - {% bootstrap_field form.priority addon_before=ic %} + {% bootstrap_icon 'pawn' as ic %} + {% bootstrap_field form.mode addon_before=ic %} - {% bootstrap_icon 'retweet' as ic %} - {% bootstrap_field form.state addon_before=ic %} + {% bootstrap_icon 'sort-by-order' as ic %} + {% bootstrap_field form.priority addon_before=ic %} -
- + {% bootstrap_icon 'retweet' as ic %} + {% bootstrap_field form.state addon_before=ic %} -
- - - {% if selected_abon %} - - - {% else %} - - - {% endif %} - {{ form.abon.errors }} -
-
-
- +
+ -
- - {{ form.out_date }}{{ form.out_date.errors }} -
- -
+
+ + + {% if selected_abon %} + + + {% else %} + + + {% endif %} + {{ form.abon.errors }} +
+
+
+ - {% bootstrap_icon 'picture' as ic %} - {% bootstrap_field form.attachment addon_before=ic %} +
+ + {{ form.out_date }}{{ form.out_date.errors }} +
+ +
-
- - - {% if task_id %} - - {% trans 'Delete' %} - - {% endif %} + {% bootstrap_icon 'picture' as ic %} + {% bootstrap_field form.attachment addon_before=ic %} + +
+ + + {% if task.id %} + + {% trans 'Delete' %} + + {% endif %} +
+ +
-
+ {% if task %} +
+ {% include 'taskapp/details.html' with task=task %} +
+
+ {% include "taskapp/comments/task_comments.html" with comments=comments task_uid=task.pk comment_form=comment_form %} +
+ {% endif %}
{% endblock %} diff --git a/taskapp/templates/taskapp/comments/extracomment_confirm_delete.html b/taskapp/templates/taskapp/comments/extracomment_confirm_delete.html new file mode 100644 index 0000000..b2be0be --- /dev/null +++ b/taskapp/templates/taskapp/comments/extracomment_confirm_delete.html @@ -0,0 +1,19 @@ +{% load i18n %} +
{% csrf_token %} + + + + + + + +
diff --git a/taskapp/templates/taskapp/comments/task_comments.html b/taskapp/templates/taskapp/comments/task_comments.html new file mode 100644 index 0000000..e8e331b --- /dev/null +++ b/taskapp/templates/taskapp/comments/task_comments.html @@ -0,0 +1,38 @@ +{% load i18n %} +{% load bootstrap3 %} +
+
+

{% trans 'Task comments' %}

+
+
+
+ {% for comment in comments %} + {% with author=comment.author %} +
+ {% if comment.author == request.user %} + + + + {% endif %} +
{{ author.get_short_name }} + {{ comment.date_create|date:'d M, H:i:s' }} +
+

{{ comment.text }}

+
+ {% endwith %} + {% empty %} +
+

{% trans 'Comment history is empty' %}

+
+ {% endfor %} +
+
{% csrf_token %} + {% bootstrap_form comment_form %} + {% buttons %} + + {% endbuttons %} +
+
+
diff --git a/taskapp/templates/taskapp/details.html b/taskapp/templates/taskapp/details.html new file mode 100644 index 0000000..af7eacc --- /dev/null +++ b/taskapp/templates/taskapp/details.html @@ -0,0 +1,38 @@ +{% load i18n %} +
+
+

{% trans 'Task details' %}

+
+
+ +

{% trans 'Description' %}: {{ task.descr }}

+ + {% trans 'Task author' %}: {{ task.author.username }}
+ + {% trans 'Implementers' %}: + + {% trans 'A priority' %}: {{ task.get_priority_display }}
+ {% trans 'The task is valid until' %} {{ task.out_date|date:'d E Y' }}
+ {% trans 'Date of create' %} {{ task.time_of_create|date:'d E Y H:i:s' }}
+ {{ time_diff }}
+ {% trans 'Task type' %}: {{ task.get_mode_display }}
+ {% trans 'Condition' %}: {{ task.get_state_display }}
+ {% trans 'Subscriber' %} + {% if task.abon %} + {{ task.abon.get_full_name }} + {% else %} + {% trans 'Not assigned' %} + {% endif %}
+ {% if task.attachment %} + {% trans 'Attachment' %}: + + + + {% endif %} + +
+
\ No newline at end of file diff --git a/taskapp/templates/taskapp/tasklist.html b/taskapp/templates/taskapp/tasklist.html index 6236cbd..60b20e7 100644 --- a/taskapp/templates/taskapp/tasklist.html +++ b/taskapp/templates/taskapp/tasklist.html @@ -7,13 +7,12 @@ - - + @@ -26,8 +25,10 @@ {% endif %} - - {% if task.abon and task.abon.group %} - - + + {{ task.abon.get_full_name }} + + + {% else %} @@ -85,13 +87,13 @@ {% empty %} - + {% endfor %} - diff --git a/taskapp/templates/taskapp/tasklist_all.html b/taskapp/templates/taskapp/tasklist_all.html index 6ee089e..6e6b34b 100644 --- a/taskapp/templates/taskapp/tasklist_all.html +++ b/taskapp/templates/taskapp/tasklist_all.html @@ -19,9 +19,8 @@
# {% trans 'Name' %} {% trans 'Address' %} {% trans 'The nature of the damage' %} {% trans 'Description' %} {% trans 'Task author' %}{% trans 'Date of create' %} {% trans 'Actions' %}
+ + {# Task state #} {% if not task.is_relevant %} {% if task.priority == 'E' %} @@ -35,13 +36,14 @@ {% endif %} {% endif %} - {{ task.pk }} - - {{ task.abon.get_full_name }}{{ task.abon.group.title }}, {{ task.abon.street|default:'' }} {{ task.abon.house|default:'' }} + {{ task.abon.group.title }}, {{ task.abon.street|default:'' }} {{ task.abon.house|default:'' }} + {% trans 'User does not exist' %} ---
{% trans 'The list is empty' %}{% trans 'The list is empty' %}
+ {% include 'taskapp/footer_btns.html' %}
- - + @@ -39,8 +38,10 @@ {% endif %} - - {% if task.abon and task.abon.group %} - + + {{ task.abon.get_full_name }} + + + {% else %} @@ -99,13 +100,13 @@ {% empty %} - + {% endfor %} - + {% if task.abon and task.abon.group %} diff --git a/taskapp/templates/taskapp/tasklist_finish.html b/taskapp/templates/taskapp/tasklist_finish.html index 0656975..06153de 100644 --- a/taskapp/templates/taskapp/tasklist_finish.html +++ b/taskapp/templates/taskapp/tasklist_finish.html @@ -33,7 +33,7 @@ {% endif %} {% endif %} - + {% if task.abon and task.abon.group %} + {% if task.abon and task.abon.group %}
{% trans 'Name' %}{% trans 'Address' %}{% trans 'Address' %} {% trans 'The nature of the damage' %} {% trans 'Description' %} {% trans 'Task author' %}
+ + {# Task state #} {% if not task.is_relevant %} {% if task.priority == 'E' %} @@ -48,12 +49,12 @@ {% endif %} {% endif %} - {{ task.pk }} - - {{ task.abon.get_full_name }} {{ task.abon.group.title }}, {{ task.abon.street|default:_('Not assigned') }} {{ task.abon.house|default:_('Not assigned') }}{% trans 'User does not exist' %}
{% trans 'The list is empty' %}{% trans 'The list is empty' %}
+ {% if perms.taskapp.add_task %} {% trans 'Add new task' %} diff --git a/taskapp/templates/taskapp/tasklist_failed.html b/taskapp/templates/taskapp/tasklist_failed.html index 65d156f..c890117 100644 --- a/taskapp/templates/taskapp/tasklist_failed.html +++ b/taskapp/templates/taskapp/tasklist_failed.html @@ -34,7 +34,7 @@ {% endif %} {% endif %} - {{ task.abon.get_full_name }} diff --git a/taskapp/templates/taskapp/tasklist_own.html b/taskapp/templates/taskapp/tasklist_own.html index 15f4120..bd12cd2 100644 --- a/taskapp/templates/taskapp/tasklist_own.html +++ b/taskapp/templates/taskapp/tasklist_own.html @@ -34,7 +34,7 @@ {% endif %} {% endif %} - diff --git a/taskapp/templates/taskapp/view.html b/taskapp/templates/taskapp/view.html deleted file mode 100644 index dfefefb..0000000 --- a/taskapp/templates/taskapp/view.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends request.is_ajax|yesno:'bajax.html,base.html' %} -{% load i18n %} -{% block main %} - - - - {% include 'message_block.html' %} - -
-
-

{% trans 'Task description' %}

-
-
- -

{% trans 'Description' %}: {{ task.descr }}

- - {% trans 'Task author' %}: {{ task.author.username }}
- - {% trans 'Implementers' %}: - - {% trans 'A priority' %}: {{ task.get_priority_display }}
- {% trans 'The task is valid until' %} {{ task.out_date|date:'d E Y' }}
- {% trans 'Date of create' %} {{ task.time_of_create|date:'d E Y H:i:s' }}
- {{ time_diff }}
- {% trans 'Task type' %}: {{ task.get_mode_display }}
- {% trans 'Condition' %}: {{ task.get_state_display }}
- {% trans 'Subscriber' %} - {% if task.abon %} - {{ task.abon.get_full_name }} - {% else %} - {% trans 'Not assigned' %} - {% endif %}
- {% if task.attachment %} - {% trans 'Attachment' %}: - - - - {% endif %} - -
-
- -{% endblock %} diff --git a/taskapp/urls.py b/taskapp/urls.py index 2c6ca34..608cab5 100644 --- a/taskapp/urls.py +++ b/taskapp/urls.py @@ -8,13 +8,14 @@ app_name = 'taskapp' urlpatterns = [ url(r'^$', views.NewTasksView.as_view(), name='home'), - url(r'^(?P\d+)$', views.view, name='view'), - url(r'^(?P\d+)/edit$', views.task_add_edit, name='edit'), + url(r'^(?P\d+)$', views.TaskUpdateView.as_view(), name='edit'), url(r'^(?P\d+)/delete$', views.task_delete, name='delete'), url(r'^(?P\d+)/fin$', views.task_finish, name='finish'), url(r'^(?P\d+)/fail$', views.task_failed, name='fail'), url(r'^(?P\d+)/remind', views.remind, name='remind'), - url(r'^add$', views.task_add_edit, name='add'), + url(r'^(?P\d+)/comment/add$', views.NewCommentView.as_view(), name='comment_add'), + url(r'^(?P\d+)/comment/(?P\d{1,8})/remove$', views.DeleteCommentView.as_view(), name='comment_del'), + url(r'^add$', views.TaskUpdateView.as_view(), name='add'), url(r'^failed$', views.FailedTasksView.as_view(), name='failed_tasks'), url(r'^finished$', views.FinishedTaskListView.as_view(), name='finished_tasks'), url(r'^own$', views.OwnTaskListView.as_view(), name='own_tasks'), diff --git a/taskapp/views.py b/taskapp/views.py index 9f30f20..405d16e 100644 --- a/taskapp/views.py +++ b/taskapp/views.py @@ -3,21 +3,23 @@ from json import dumps from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied from django.http import HttpResponse -from django.shortcuts import render, redirect, get_object_or_404 +from django.shortcuts import render, redirect, get_object_or_404, resolve_url from django.contrib import messages from django.utils.decorators import method_decorator -from django.views.generic import ListView +from django.views.generic import ListView, CreateView from django.utils.translation import ugettext as _ from django.conf import settings from datetime import datetime + +from django.views.generic.edit import FormMixin, DeleteView, UpdateView from guardian.decorators import permission_required_or_403 as permission_required from chatbot.models import MessageQueue from abonapp.models import Abon from .handle import TaskException -from .models import Task +from .models import Task, ExtraComment from mydefs import only_admins, safe_int, MultipleException, RuTimedelta -from .forms import TaskFrm +from .forms import TaskFrm, ExtraCommentForm class BaseTaskListView(ListView): @@ -90,7 +92,7 @@ class AllTasksListView(BaseTaskListView): @permission_required('taskapp.delete_task') def task_delete(request, task_id): task = get_object_or_404(Task, id=task_id) - # нельзя удалить назначенную мне задачу + # prevent to delete task that assigned to me if request.user.is_superuser or request.user not in task.recipients.all(): task.delete() else: @@ -98,87 +100,88 @@ def task_delete(request, task_id): return redirect('taskapp:home') -@login_required -@only_admins -def view(request, task_id): - tsk = get_object_or_404(Task, id=task_id) - #toc = date(tsk.time_of_create.year, tsk.time_of_create.month, tsk.time_of_create.day) - now_date = datetime.now().date() - if tsk.out_date > now_date: - time_diff = "%s: %s" % (_('time left'), RuTimedelta(tsk.out_date - now_date)) - else: - time_diff = _("Expired timeout -%(time_left)s") % {'time_left': RuTimedelta(now_date - tsk.out_date)} - return render(request, 'taskapp/view.html', { - 'task': tsk, - 'time_diff': time_diff - }) - - -@login_required -@only_admins -def task_add_edit(request, task_id=0): - task_id = safe_int(task_id) - uid = request.GET.get('uid', 0) - selected_abon = None - frm = TaskFrm() - - # чтоб при добавлении сразу был выбран исполнитель - #frm_recipient_id = safe_int(request.GET.get('rp')) - - if task_id == 0: - if not request.user.has_perm('taskapp.add_task'): - raise PermissionDenied - tsk = Task() - else: - if not request.user.has_perm('taskapp.change_task'): - raise PermissionDenied - tsk = get_object_or_404(Task, id=task_id) - frm = TaskFrm(instance=tsk) - selected_abon = tsk.abon - - try: - if request.method == 'POST': - tsk.author = request.user - frm = TaskFrm(request.POST, request.FILES, instance=tsk) - - if frm.is_valid(): - task_instance = frm.save() - # получим абонента, выбранного в форме - selected_abon = task_instance.abon - if selected_abon: - # получаем аккаунты назначенные на группу выбранного абонента - profiles = selected_abon.group.profiles.filter(is_active=True).filter(is_admin=True) - - # если нашли кого-нибудь - if profiles.count() > 0: - # выбираем их id в базе - profile_ids = [prof.id for prof in profiles] - # добавляем найденных работников в задачу - task_instance.recipients.add(*profile_ids) - # окончательно сохраняемся - task_instance.save() - return redirect('taskapp:home') - else: - messages.error(request, _('No responsible employee for the users group')) - else: - messages.error(request, _('You must select the subscriber')) +@method_decorator([login_required, only_admins], name='dispatch') +class TaskUpdateView(UpdateView): + http_method_names = ['get', 'post'] + template_name = 'taskapp/add_edit_task.html' + form_class = TaskFrm + context_object_name = 'task' + + def get_object(self, queryset=None): + task_id = safe_int(self.kwargs.get('task_id')) + if task_id == 0: + return + else: + task = get_object_or_404(Task, pk=task_id) + setattr(self, 'selected_abon', task.abon) + return task + + def dispatch(self, request, *args, **kwargs): + task_id = safe_int(self.kwargs.get('task_id', 0)) + if task_id == 0: + if not request.user.has_perm('taskapp.add_task'): + raise PermissionDenied + else: + if not request.user.has_perm('taskapp.change_task'): + raise PermissionDenied + return super(TaskUpdateView, self).dispatch(request, *args, **kwargs) + + def form_valid(self, form): + task_instance = form.save() + self.object = task_instance + selected_abon = task_instance.abon + setattr(self, 'selected_abon', selected_abon) + if selected_abon: + # fetch profiles that has been attached on group of selected subscriber + profiles = selected_abon.group.profiles.filter(is_active=True).filter(is_admin=True) + if profiles.count() > 0: + profile_ids = [prof.id for prof in profiles] + task_instance.recipients.add(*profile_ids) + task_instance.save() + messages.add_message(self.request, messages.SUCCESS, _('Task has changed successfully')) else: - messages.error(request, _('Error in the form fields')) - elif uid: - selected_abon = Abon.objects.get(username=str(uid)) - except Abon.DoesNotExist: - messages.warning(request, _("User does not exist")) - except MultipleException as errs: - for err in errs.err_list: - messages.add_message(request, messages.constants.ERROR, err) - except TaskException as e: - messages.error(request, e) + messages.add_message(self.request, messages.ERROR, _('No responsible employee for the users group')) + else: + messages.add_message(self.request, messages.ERROR, _('You must select the subscriber')) + return super(TaskUpdateView, self).form_valid(form) + + def get_context_data(self, **kwargs): + uid = safe_int(self.kwargs.get('uid')) + selected_abon = getattr( + self, + 'selected_abon', + Abon.objects.get(username=str(uid)) if uid != 0 else None + ) + + now_date = datetime.now().date() + task = self.object + if task: + if task.out_date > now_date: + time_diff = "%s: %s" % (_('time left'), RuTimedelta(task.out_date - now_date)) + else: + time_diff = _("Expired timeout -%(time_left)s") % {'time_left': RuTimedelta(now_date - task.out_date)} + else: + time_diff = None + + context = { + 'selected_abon': selected_abon, + 'time_diff': time_diff, + 'comments': ExtraComment.objects.filter(task=task), + 'comment_form': ExtraCommentForm() + } + context.update(kwargs) + return super(TaskUpdateView, self).get_context_data(**context) + + def get_success_url(self): + task_id = safe_int(self.kwargs.get('task_id')) + if task_id == 0: + return resolve_url('taskapp:own_tasks') + else: + return resolve_url('taskapp:edit', task_id) - return render(request, 'taskapp/add_edit_task.html', { - 'form': frm, - 'task_id': tsk.id, - 'selected_abon': selected_abon - }) + def form_invalid(self, form): + messages.add_message(self.request, messages.ERROR, _('fix form errors')) + return super(TaskUpdateView, self).form_invalid(form) @login_required @@ -235,3 +238,42 @@ def check_news(request): else: r = {'auth': False} return HttpResponse(dumps(r)) + + +@method_decorator([login_required, only_admins], name='dispatch') +@method_decorator(permission_required('taskapp.add_extracomment'), name='dispatch') +class NewCommentView(CreateView): + form_class = ExtraCommentForm + http_method_names = ['get', 'post'] + + def get_success_url(self): + task_id = self.kwargs.get('task_id') + return resolve_url('taskapp:edit', task_id) + + def form_valid(self, form): + self.task = get_object_or_404(Task, pk=self.kwargs.get('task_id')) + self.object = form.make_save( + author=self.request.user, + task=self.task + ) + return FormMixin.form_valid(self, form) + + +@method_decorator([login_required, only_admins], name='dispatch') +@method_decorator(permission_required('taskapp.delete_extracomment'), name='dispatch') +class DeleteCommentView(DeleteView): + model = ExtraComment + pk_url_kwarg = 'comment_id' + http_method_names = ['get', 'post'] + template_name = 'taskapp/comments/extracomment_confirm_delete.html' + + def get_context_data(self, **kwargs): + context = { + 'task_id': self.kwargs.get('task_id') + } + context.update(kwargs) + return super(DeleteCommentView, self).get_context_data(**context) + + def get_success_url(self): + task_id = self.kwargs.get('task_id') + return resolve_url('taskapp:edit', task_id)