Browse Source

Make comments in tasks

devel
bashmak 8 years ago
parent
commit
eeaede4363
  1. 38
      taskapp/forms.py
  2. 2
      taskapp/handle.py
  3. 464
      taskapp/locale/ru/LC_MESSAGES/django.po
  4. 93
      taskapp/migrations/0002_auto_20180219_1255.py
  5. 46
      taskapp/models.py
  6. 151
      taskapp/templates/taskapp/add_edit_task.html
  7. 19
      taskapp/templates/taskapp/comments/extracomment_confirm_delete.html
  8. 38
      taskapp/templates/taskapp/comments/task_comments.html
  9. 38
      taskapp/templates/taskapp/details.html
  10. 26
      taskapp/templates/taskapp/tasklist.html
  11. 23
      taskapp/templates/taskapp/tasklist_all.html
  12. 2
      taskapp/templates/taskapp/tasklist_failed.html
  13. 2
      taskapp/templates/taskapp/tasklist_finish.html
  14. 2
      taskapp/templates/taskapp/tasklist_own.html
  15. 51
      taskapp/templates/taskapp/view.html
  16. 7
      taskapp/urls.py
  17. 210
      taskapp/views.py

38
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']

2
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

464
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 "&lt;Не назначено&gt;"
#: 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 "&lt;Не назначено&gt;"
#: 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 "Сегодня"

93
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'),
),
]

46
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)

151
taskapp/templates/taskapp/add_edit_task.html

@ -6,90 +6,105 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'taskapp:home' %}">{% trans 'Tasks' %}</a></li>
<li class="active">{% if task_id %}{% trans 'Edit' %}{% else %}{% trans 'Create' %}{% endif %}</li>
<li class="active">{% if task.id %}{% trans 'Edit' %}{% else %}{% trans 'Create' %}{% endif %}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
{% if task_id %}
<h3 class="panel-title">{% trans 'Add new task' %}</h3>
{% else %}
<h3 class="panel-title">{% trans 'Edit task' %}</h3>
{% endif %}
</div>
<div class="panel-body">
<div class="row">
<div class="{% if task %}col-sm-6{% else %}col-sm-12{% endif %}">
<div class="panel panel-default">
<div class="panel-heading">
{% if task.id %}
<h3 class="panel-title">{% trans 'Add new task' %}</h3>
{% else %}
<h3 class="panel-title">{% trans 'Edit task' %}</h3>
{% endif %}
</div>
<div class="panel-body">
{% if task_id %}
<form role="form" action="{% url 'taskapp:edit' task_id %}" method="post" enctype="multipart/form-data">
{% else %}
<form role="form" action="{% url 'taskapp:add' %}" method="post" enctype="multipart/form-data">
{% endif %}
{% csrf_token %}<input type="hidden" name="MAX_FILE_SIZE" value="{{ FILE_UPLOAD_MAX_MEMORY_SIZE }}"/>
{% if task.id %}
<form role="form" action="{% url 'taskapp:edit' task.id %}" method="post" enctype="multipart/form-data">
{% else %}
<form role="form" action="{% url 'taskapp:add' %}" method="post" enctype="multipart/form-data">
{% endif %}
{% csrf_token %}<input type="hidden" name="MAX_FILE_SIZE" value="{{ FILE_UPLOAD_MAX_MEMORY_SIZE }}"/>
{% 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 %}
<div class="form-group">
<label for="id_abon">{% trans 'Subscriber' %}</label>
{% bootstrap_icon 'retweet' as ic %}
{% bootstrap_field form.state addon_before=ic %}
<div class="input-group selectajax" data-dst="/abons/api/abon_filter">
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
<input type="hidden" name="abon" class="selectajax-hid"{% if selected_abon %} value="{{ selected_abon.pk }}"{% endif %}>
{% if selected_abon %}
<button class="selectajax-btn form-control btn btn-default">{{ selected_abon.fio }}</button>
<input type="text" class="form-control dropdown-toggle selectajax-inp hidden" data-toggle="dropdown" id="id_abon" placeholder="{% trans 'Find the subscriber' %}">
{% else %}
<button class="selectajax-btn form-control btn btn-default hidden"></button>
<input type="text" class="form-control dropdown-toggle selectajax-inp" data-toggle="dropdown" id="id_abon" placeholder="{% trans 'Find the subscriber' %}">
{% endif %}
<ul class="dropdown-menu selectajax-ul"></ul>{{ form.abon.errors }}
</div>
</div>
<div class="form-group">
<label for="id_out_date">{% trans 'Reality' %}</label>
<div class="form-group">
<label for="id_abon">{% trans 'Subscriber' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
{{ form.out_date }}{{ form.out_date.errors }}
</div>
<script type="text/javascript">
$(function () {
$('#id_out_date').datetimepicker({
format: 'YYYY-MM-DD'
});
});
</script>
</div>
<div class="input-group selectajax" data-dst="/abons/api/abon_filter">
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
<input type="hidden" name="abon" class="selectajax-hid"{% if selected_abon %} value="{{ selected_abon.pk }}"{% endif %}>
{% if selected_abon %}
<button class="selectajax-btn form-control btn btn-default">{{ selected_abon.fio }}</button>
<input type="text" class="form-control dropdown-toggle selectajax-inp hidden" data-toggle="dropdown" id="id_abon" placeholder="{% trans 'Find the subscriber' %}">
{% else %}
<button class="selectajax-btn form-control btn btn-default hidden"></button>
<input type="text" class="form-control dropdown-toggle selectajax-inp" data-toggle="dropdown" id="id_abon" placeholder="{% trans 'Find the subscriber' %}">
{% endif %}
<ul class="dropdown-menu selectajax-ul"></ul>{{ form.abon.errors }}
</div>
</div>
<div class="form-group">
<label for="id_out_date">{% trans 'Reality' %}</label>
{% bootstrap_icon 'picture' as ic %}
{% bootstrap_field form.attachment addon_before=ic %}
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
{{ form.out_date }}{{ form.out_date.errors }}
</div>
<script type="text/javascript">
$(function () {
$('#id_out_date').datetimepicker({
format: 'YYYY-MM-DD'
});
});
</script>
</div>
<div class="btn-group btn-group-sm">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
<button type="reset" class="btn btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %}
</button>
{% if task_id %}
<a href="{% url 'taskapp:delete' task_id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %}
</a>
{% endif %}
{% bootstrap_icon 'picture' as ic %}
{% bootstrap_field form.attachment addon_before=ic %}
<div class="btn-group btn-group-sm">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
<button type="reset" class="btn btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %}
</button>
{% if task.id %}
<a href="{% url 'taskapp:delete' task.id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %}
</a>
{% endif %}
</div>
</form>
</div>
</div>
</form>
</div>
{% if task %}
<div class="col-sm-6">
{% include 'taskapp/details.html' with task=task %}
</div>
<div class="col-sm-6">
{% include "taskapp/comments/task_comments.html" with comments=comments task_uid=task.pk comment_form=comment_form %}
</div>
{% endif %}
</div>
{% endblock %}

19
taskapp/templates/taskapp/comments/extracomment_confirm_delete.html

@ -0,0 +1,19 @@
{% load i18n %}
<form action="{% url 'taskapp:comment_del' task_id object.pk %}" method="post">{% csrf_token %}
<div class="modal-header warning">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-exclamation-sign"></span>{% trans 'Delete comment' %}</h4>
</div>
<div class="modal-body">
<p>{% blocktrans %}Are you sure you want to delete "{{ object }}"?{% endblocktrans %}</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %}
</button>
</div>
</form>

38
taskapp/templates/taskapp/comments/task_comments.html

@ -0,0 +1,38 @@
{% load i18n %}
{% load bootstrap3 %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Task comments' %}</h3>
</div>
<div class="panel-body">
<div class="list-group">
{% for comment in comments %}
{% with author=comment.author %}
<div class="list-group-item">
{% if comment.author == request.user %}
<a href="{% url 'taskapp:comment_del' task_uid comment.pk %}" class="btn btn-link pull-right btn-modal" title="{% trans 'Delete' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
<h5><b>{{ author.get_short_name }}</b>
<small>{{ comment.date_create|date:'d M, H:i:s' }}</small>
</h5>
<p>{{ comment.text }}</p>
</div>
{% endwith %}
{% empty %}
<div class="list-group-item clearfix">
<p class="list-group-item-text">{% trans 'Comment history is empty' %}</p>
</div>
{% endfor %}
</div>
<form action="{% url 'taskapp:comment_add' task_uid %}" method="post">{% csrf_token %}
{% bootstrap_form comment_form %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "send" %} {% trans 'Send' %}
</button>
{% endbuttons %}
</form>
</div>
</div>

38
taskapp/templates/taskapp/details.html

@ -0,0 +1,38 @@
{% load i18n %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Task details' %}</h3>
</div>
<div class="panel-body">
<p>{% trans 'Description' %}: {{ task.descr }}</p>
{% trans 'Task author' %}: <a href="{% url 'acc_app:other_profile' task.author.pk %}" title="{{ task.author.get_full_name }}" data-toggle="tooltip" target="_blank">{{ task.author.username }}</a><br>
{% trans 'Implementers' %}:
<ul>
{% for recipient in task.recipients.all %}
<li><a href="{% url 'acc_app:other_profile' recipient.pk %}" target="_blank">{{ recipient.get_full_name }}</a></li>
{% endfor %}
</ul>
{% trans 'A priority' %}: {{ task.get_priority_display }}<br>
{% trans 'The task is valid until' %} {{ task.out_date|date:'d E Y' }}<br>
{% trans 'Date of create' %} {{ task.time_of_create|date:'d E Y H:i:s' }}<br>
{{ time_diff }}<br>
{% trans 'Task type' %}: {{ task.get_mode_display }}<br>
{% trans 'Condition' %}: {{ task.get_state_display }}<br>
{% trans 'Subscriber' %}
{% if task.abon %}
<a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}" target="_blank">{{ task.abon.get_full_name }}</a>
{% else %}
<i>{% trans 'Not assigned' %}</i>
{% endif %}<br>
{% if task.attachment %}
{% trans 'Attachment' %}:
<a href="{{ task.attachment.url }}" class="thumbnail" target="_blank">
<img src="{{ task.attachment.url }}">
</a>
{% endif %}
</div>
</div>

26
taskapp/templates/taskapp/tasklist.html

@ -7,13 +7,12 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="col-sm-1">#</th>
<th class="col-sm-3">{% trans 'Name' %}</th>
<th class="col-sm-1">{% trans 'Address' %}</th>
<th class="col-sm-1">{% trans 'The nature of the damage' %}</th>
<th class="col-sm-4">{% trans 'Description' %}</th>
<th class="col-sm-1">{% trans 'Task author' %}</th>
<th class="hidden-xs">{% trans 'Date of create' %}</th>
<th class="col-sm-1">{% trans 'Date of create' %}</th>
<th class="col-sm-1">{% trans 'Actions' %}</th>
</tr>
</thead>
@ -26,8 +25,10 @@
<tr>
{% endif %}
<td class="hidden-xs">
<a href="{% url 'taskapp:view' task.pk %}">
{% if task.abon and task.abon.group %}
<td>
{# Task state #}
{% if not task.is_relevant %}
{% if task.priority == 'E' %}
<span class="glyphicon glyphicon-ok-circle text-success"></span>
@ -35,13 +36,14 @@
<span class="glyphicon glyphicon-exclamation-sign text-danger"></span>
{% endif %}
{% endif %}
{{ task.pk }}
</a>
</td>
{% if task.abon and task.abon.group %}
<td><a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}" title="{{ task.abon.description|default:'' }}" data-toggle="tooltip">{{ task.abon.get_full_name }}</a></td>
<td>{{ task.abon.group.title }}, {{ task.abon.street|default:'' }} {{ task.abon.house|default:'' }}</td>
<a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}" title="{{ task.abon.description|default:'' }}" data-toggle="tooltip">
{{ task.abon.get_full_name }}
</a>
</td>
<td>
{{ task.abon.group.title }}, {{ task.abon.street|default:'' }} {{ task.abon.house|default:'' }}
</td>
{% else %}
<td>{% trans 'User does not exist' %}</td>
<td>---</td>
@ -85,13 +87,13 @@
</tr>
{% empty %}
<tr>
<td colspan="8">{% trans 'The list is empty' %}</td>
<td colspan="7">{% trans 'The list is empty' %}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="8">
<td colspan="7">
{% include 'taskapp/footer_btns.html' %}
</td>
</tr>

23
taskapp/templates/taskapp/tasklist_all.html

@ -19,9 +19,8 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="col-sm-1 hidden-xs">#</th>
<th class="col-sm-2">{% trans 'Name' %}</th>
<th class="col-sm-1">{% trans 'Address' %}</th>
<th class="col-sm-2">{% trans 'Address' %}</th>
<th class="col-sm-1">{% trans 'The nature of the damage' %}</th>
<th class="col-sm-3">{% trans 'Description' %}</th>
<th class="col-sm-1">{% trans 'Task author' %}</th>
@ -39,8 +38,10 @@
<tr>
{% endif %}
<td class="hidden-xs">
<a href="{% url 'taskapp:view' task.pk %}">
{% if task.abon and task.abon.group %}
<td>
{# Task state #}
{% if not task.is_relevant %}
{% if task.priority == 'E' %}
<span class="glyphicon glyphicon-ok-circle text-success"></span>
@ -48,12 +49,12 @@
<span class="glyphicon glyphicon-exclamation-sign text-danger"></span>
{% endif %}
{% endif %}
{{ task.pk }}
</a>
</td>
{% if task.abon and task.abon.group %}
<td><a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}">{{ task.abon.get_full_name }}</a></td>
<a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}">
{{ task.abon.get_full_name }}
</a>
</td>
<td>{{ task.abon.group.title }}, {{ task.abon.street|default:_('Not assigned') }} {{ task.abon.house|default:_('Not assigned') }}</td>
{% else %}
<td>{% trans 'User does not exist' %}</td>
@ -99,13 +100,13 @@
</tr>
{% empty %}
<tr>
<td colspan="9">{% trans 'The list is empty' %}</td>
<td colspan="8">{% trans 'The list is empty' %}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="9">
<td colspan="8">
{% if perms.taskapp.add_task %}
<a href="{% url 'taskapp:add' %}" class="btn btn-sm btn-success" title="{% trans 'Add new task' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add new task' %}

2
taskapp/templates/taskapp/tasklist_failed.html

@ -34,7 +34,7 @@
{% endif %}
{% endif %}
<td class="hidden-xs"><a href="{% url 'taskapp:view' task.pk %}">{{ task.pk }}</a></td>
<td class="hidden-xs"><a href="{% url 'taskapp:edit' task.pk %}">{{ task.pk }}</a></td>
{% if task.abon and task.abon.group %}
<td><a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}">{{ task.abon.get_full_name }}</a></td>

2
taskapp/templates/taskapp/tasklist_finish.html

@ -33,7 +33,7 @@
{% endif %}
{% endif %}
<td class="hidden-xs"><a href="{% url 'taskapp:view' task.pk %}">{{ task.pk }}</a></td>
<td class="hidden-xs"><a href="{% url 'taskapp:edit' task.pk %}">{{ task.pk }}</a></td>
{% if task.abon and task.abon.group %}
<td>

2
taskapp/templates/taskapp/tasklist_own.html

@ -34,7 +34,7 @@
{% endif %}
{% endif %}
<td class="hidden-xs"><a href="{% url 'taskapp:view' task.id %}">{{ task.id }}</a></td>
<td class="hidden-xs"><a href="{% url 'taskapp:edit' task.id %}">{{ task.id }}</a></td>
{% if task.abon and task.abon.group %}
<td>

51
taskapp/templates/taskapp/view.html

@ -1,51 +0,0 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'taskapp:home' %}">{% trans 'Tasks' %}</a></li>
<li class="active">#{{ task.pk }}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Task description' %}</h3>
</div>
<div class="panel-body">
<p>{% trans 'Description' %}: {{ task.descr }}</p>
{% trans 'Task author' %}: <a href="{% url 'acc_app:other_profile' task.author.pk %}" title="{{ task.author.get_full_name }}" data-toggle="tooltip" target="_blank">{{ task.author.username }}</a><br>
{% trans 'Implementers' %}:
<ul>
{% for recipient in task.recipients.all %}
<li><a href="{% url 'acc_app:other_profile' recipient.pk %}" target="_blank">{{ recipient.get_full_name }}</a></li>
{% endfor %}
</ul>
{% trans 'A priority' %}: {{ task.get_priority_display }}<br>
{% trans 'The task is valid until' %} {{ task.out_date|date:'d E Y' }}<br>
{% trans 'Date of create' %} {{ task.time_of_create|date:'d E Y H:i:s' }}<br>
{{ time_diff }}<br>
{% trans 'Task type' %}: {{ task.get_mode_display }}<br>
{% trans 'Condition' %}: {{ task.get_state_display }}<br>
{% trans 'Subscriber' %}
{% if task.abon %}
<a href="{% url 'abonapp:abon_home' task.abon.group.pk task.abon.pk %}" target="_blank">{{ task.abon.get_full_name }}</a>
{% else %}
<i>{% trans 'Not assigned' %}</i>
{% endif %}<br>
{% if task.attachment %}
{% trans 'Attachment' %}:
<a href="{{ task.attachment.url }}" class="thumbnail" target="_blank">
<img src="{{ task.attachment.url }}">
</a>
{% endif %}
</div>
</div>
{% endblock %}

7
taskapp/urls.py

@ -8,13 +8,14 @@ app_name = 'taskapp'
urlpatterns = [
url(r'^$', views.NewTasksView.as_view(), name='home'),
url(r'^(?P<task_id>\d+)$', views.view, name='view'),
url(r'^(?P<task_id>\d+)/edit$', views.task_add_edit, name='edit'),
url(r'^(?P<task_id>\d+)$', views.TaskUpdateView.as_view(), name='edit'),
url(r'^(?P<task_id>\d+)/delete$', views.task_delete, name='delete'),
url(r'^(?P<task_id>\d+)/fin$', views.task_finish, name='finish'),
url(r'^(?P<task_id>\d+)/fail$', views.task_failed, name='fail'),
url(r'^(?P<task_id>\d+)/remind', views.remind, name='remind'),
url(r'^add$', views.task_add_edit, name='add'),
url(r'^(?P<task_id>\d+)/comment/add$', views.NewCommentView.as_view(), name='comment_add'),
url(r'^(?P<task_id>\d+)/comment/(?P<comment_id>\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'),

210
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)
Loading…
Cancel
Save