diff --git a/api/test.py b/api/test.py new file mode 100644 index 0000000..269a6c8 --- /dev/null +++ b/api/test.py @@ -0,0 +1,6 @@ +from rest_framework.test import APITestCase + + +class FileUploadTests(APITestCase): + pass + diff --git a/api/urls.py b/api/urls.py index a414824..319beed 100755 --- a/api/urls.py +++ b/api/urls.py @@ -9,6 +9,7 @@ from .views import ( MessageViewSet, StageViewSet, NoteViewSet, + DocumentViewSet, ) @@ -17,6 +18,7 @@ router = routers.DefaultRouter() router.register(r'locations', LocationViewSet) router.register(r'projects', ProjectViewSet) router.register(r'stages', StageViewSet) +router.register(r'documents', DocumentViewSet) router.register(r'realties', RealtyViewSet) router.register(r'specializations', SpecializationViewSet) router.register(r'users', UserViewSet) diff --git a/api/views.py b/api/views.py index a2dd477..f4e4f4a 100755 --- a/api/views.py +++ b/api/views.py @@ -18,9 +18,9 @@ from common.models import Location from common.serializers import LocationSerializer from common.filters import LocationFilterSet -from chat.models import Message, Notes -from chat.serializers import MessageSerializer, NoteSerializer -from chat.filters import MessageFilterSet, NoteFilterSet +from chat.models import Message, Notes, Documents +from chat.serializers import MessageSerializer, NoteSerializer, DocumentsSerializer +from chat.filters import MessageFilterSet, NoteFilterSet, DocumentsFilterSet class StageViewSet(ModelViewSet): @@ -30,6 +30,13 @@ class StageViewSet(ModelViewSet): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) +class DocumentViewSet(ModelViewSet): + queryset = Documents.objects.all() + serializer_class = DocumentsSerializer + # filter_class = DocumentsFilterSet + # permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + class ProjectViewSet(ModelViewSet): queryset = Project.objects.all() serializer_class = ProjectSerializer diff --git a/archilance/settings/base.py b/archilance/settings/base.py index 72aa5ba..9b25660 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -12,11 +12,10 @@ SECRET_KEY = 'vb6@b9zj7^f!^+x*e8=e!oundyu1!e*&0i(3gu2xwo4%fx4h&n' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -TEMPLATE_DEBUG = True # Show debug info in templates. See `projects/templates/project_filter.html` +TEMPLATE_DEBUG = True # Show debug info in templates. See `projects/templates/project_filter.html` ALLOWED_HOSTS = [] - # Application definition DJANGO_APPS = [ @@ -39,20 +38,21 @@ THIRD_PARTY_APPS = [ 'sorl.thumbnail', 'compressor', 'password_reset', - 'mathfilters', # Basic math operations in templates; https://pypi.python.org/pypi/django-mathfilters + 'mathfilters', # Basic math operations in templates; https://pypi.python.org/pypi/django-mathfilters ] LOCAL_APPS = [ - 'specializations', - 'api', - 'common', - 'work_sell', - 'archilance', - 'projects', - 'users', - 'reviews', - 'chat', - 'wallets', + 'specializations', + 'api', + 'common', + 'work_sell', + 'archilance', + 'projects', + 'users', + 'reviews', + 'chat', + 'wallets', + 'ratings', ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS @@ -85,7 +85,6 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', ], - # Load these templatetags by default: 'builtins': [ @@ -99,7 +98,6 @@ TEMPLATES = [ WSGI_APPLICATION = 'archilance.wsgi.application' - # Database # https://docs.djangoproject.com/en/1.9/ref/settings/#databases @@ -121,7 +119,6 @@ DATABASES = { } } - # Password validation # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators @@ -209,7 +206,6 @@ USE_L10N = True USE_TZ = True - # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.9/howto/static-files/ @@ -261,10 +257,10 @@ EMAIL_PORT = 25 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -SHELL_PLUS_POST_IMPORTS = ( # Extra auto imports +SHELL_PLUS_POST_IMPORTS = ( # Extra auto imports 'natsort', ('archilance', 'util'), ('pprint', ('pprint', 'pformat')), ) -PAGE_SIZE = 10 # Pagination +PAGE_SIZE = 10 # Pagination diff --git a/archilance/views.py b/archilance/views.py index f122e41..feec3a6 100644 --- a/archilance/views.py +++ b/archilance/views.py @@ -1,11 +1,13 @@ from django.views.generic import TemplateView, View from django.shortcuts import render from django.template.loader import render_to_string - +from django.core.files.base import ContentFile +from work_sell.models import Picture from projects.models import Order from common.models import MainPage, PrintDocuments from users.models import ContractorResumeFiles - +from chat.models import Documents +from work_sell.models import Picture class HomeTemplateView(View): template_name = 'home.html' @@ -19,5 +21,16 @@ class TestChatTemplateView(View): template_name = 'chat_test.html' def get(self, request, *args, **kwargs): - diploms = ContractorResumeFiles.objects.all() - return render(request, 'chat_test.html', {'diploms': diploms}) + test = [54,55,56] + for pk in test: + picture = Picture.objects.get(pk=pk) + temp_file = ContentFile(picture.file.read()) + temp_file.name = picture.file.name + document = Documents() + document.team_id = 1 + document.order_id = 2 + document.sender_id = 2 + document.recipent_id = 4 + document.file = temp_file + document.save() + diff --git a/chat/admin.py b/chat/admin.py index 127440a..bad96cc 100644 --- a/chat/admin.py +++ b/chat/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Message, Notes +from .models import Message, Notes, Documents class MessageAdmin(admin.ModelAdmin): @@ -10,5 +10,10 @@ class NotesAdmin(admin.ModelAdmin): list_display = ('text', 'sender', 'recipent', 'order',) +class DocumentsAdmin(admin.ModelAdmin): + list_display = ('file', 'sender', 'recipent', 'order','team') + + admin.site.register(Message, MessageAdmin) admin.site.register(Notes, NotesAdmin) +admin.site.register(Documents, DocumentsAdmin) diff --git a/chat/filters.py b/chat/filters.py index 727b598..19a1ab6 100644 --- a/chat/filters.py +++ b/chat/filters.py @@ -1,6 +1,17 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter -from .models import Message, Notes +from .models import Message, Notes, Documents + + +class DocumentsFilterSet(FilterSet): + file = AllLookupsFilter() + sender = RelatedFilter('users.filters.UserFilterSet') + recipent = RelatedFilter('users.filters.UserFilterSet') + # order = AllLookupsFilter() + # team = AllLookupsFilter() + + class Meta: + model = Documents class MessageFilterSet(FilterSet): diff --git a/chat/migrations/0003_documents.py b/chat/migrations/0003_documents.py index 039c234..8c30fc0 100644 --- a/chat/migrations/0003_documents.py +++ b/chat/migrations/0003_documents.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.7 on 2016-08-04 11:03 +# Generated by Django 1.9.7 on 2016-08-03 17:03 from __future__ import unicode_literals from django.conf import settings @@ -10,8 +10,8 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('projects', '0013_auto_20160804_1403'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('projects', '0013_auto_20160803_2003'), ('users', '0003_auto_20160726_1931'), ('chat', '0002_message_team'), ] @@ -28,8 +28,8 @@ class Migration(migrations.Migration): ('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_documents', to='users.Team')), ], options={ - 'verbose_name_plural': 'Входящие Документы', 'verbose_name': 'Входящие Документы', + 'verbose_name_plural': 'Входящие Документы', }, ), ] diff --git a/chat/serializers.py b/chat/serializers.py index 3397e72..cd43c8d 100644 --- a/chat/serializers.py +++ b/chat/serializers.py @@ -1,8 +1,22 @@ from rest_framework.serializers import ModelSerializer -from .models import Message, Notes +from .models import Message, Notes, Documents from users.serializers import UserSerializer +class DocumentsSerializer(ModelSerializer): + + class Meta: + model = Documents + + fields = ( + 'file', + 'sender', + 'recipent', + 'team', + 'order', + ) + + class MessageSerializer(ModelSerializer): sender = UserSerializer() recipent = UserSerializer() diff --git a/chat/templates/chat.js b/chat/templates/chat.js new file mode 100644 index 0000000..f40e51a --- /dev/null +++ b/chat/templates/chat.js @@ -0,0 +1,683 @@ + // + // function csrfSafeMethod(method) { + // // these HTTP methods do not require CSRF protection + // return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); + // } + // + // var SocketHandler = function () { + // var userId = {{ request.user.pk }}; + // var url = 'ws://127.0.0.1:8888/chat/' + userId + '/'; + // var sock = new WebSocket(url); + // var intervalId; + // sock.onopen = function () { + // console.log("Start connect"); + // intervalId = setInterval(function () { + // sock.send('{"dummy": 1}'); + // }, 150000); + // }; + // sock.onmessage = function (event) { + // console.log(event.data); + // var message = JSON.parse(event.data); + // var inbox; + // + // if (message.answer_type == 'contact' || message.answer_type == 'add_message_contact') { + // inbox = document.getElementById('message-chat-space'); + // } else if (message.answer_type == 'order' || message.answer_type == 'add_message_order') { + // inbox = document.getElementById('message-chat-order-space'); + // } else if(message.answer_type == 'add_message_team'){ + // inbox = document.getElementById('message-chat-team-space'); + // } + // console.log(message.answer_type); + // console.log(message.msg); + // + // inbox.innerHTML += '
ВЫ
13.0.2016' + message.msg + '
'+ file.name+'
'; + // var document_send = $(htmlImg).appendTo("#document-send"); + // }); + // }, + // progressall: function (e, data) { + // var progress = parseInt(data.loaded / data.total * 100, 10); + // $('#progress .progress-bar').css( + // 'width', + // progress + '%' + // ); + // } + // }).prop('disabled', !$.support.fileInput) + // .parent().addClass($.support.fileInput ? undefined : 'disabled'); + // + // + // $("#approve-stages").on('click', function(){ + // $(".stage-block-approve").each(function(){ + // var stageId = $(this).attr('data-id'); + // }); + // }); + // + // $(".team-chat-user").on('click',function(e){ + // e.stopPropagation(); + // var recipentId = $(this).attr('data-id'); + // $("#team-chat-form #recipentId").val(recipentId); + // }); + // + // $(".team-order-block").on('click', function(){ + // + // $('.team-order-block').each(function () { + // $(this).removeClass('orAct'); + // }); + // $(this).addClass('orAct'); + // + // var teamId = $(this).attr('data-team-id'); + // var orderId = $(this).attr('data-order-id'); + // $("#team-chat-form #teamId").val(teamId); + // $("#team-chat-form #orderId").val(orderId); + // + // var inbox = document.getElementById('message-chat-team-space'); + // inbox.innerHTML = ''; + // + // $.ajax({ + // url: '/api/message', + // type: 'GET', + // data: {csrfmiddlewaretoken: csrftoken, 'team': teamId,'order': orderId}, + // dataType: 'json', + // success: function (json) { + // $.each(json.results, function (i, v) { + // var senderName = 'Вы'; + // var className = 'youChat'; + // if (v.sender.id !== currentChatUser) { + // senderName = v.sender.username; + // className = ''; + // } + // inbox.innerHTML += '' + senderName + '
' + v.created + '' + v.text + '
' + senderName + '
' + v.created + '' + v.text + '
Этап ' + v.pos + '' + v.name + '
' + + // 'Результаты этапа:' + v.result + '
'+ v.status+'
' + v.cost + '' + senderName + '
' + v.created + '' + v.text + '
Вы
Сейчас' + chatMessage + '
' + senderName + '
' + v.created + '' + v.text + '
Какое кол-во этапов подразумевает работа? ' + + // '
'; + // + // if (stageCount == 0){ + // htmlInboxStage += 'Этап 1
Этап
Этап ' + v.pos + '' + v.name + '
' + + // 'Результаты этапа:' + v.result + '
до 16.03.2015
' + v.cost + '' + senderName + '
' + v.created + '' + v.text + '
Иванов
13.0.2016' + message.msg + '
Название
'+ file.name+'
'; + var document_send = $(htmlImg).appendTo("#document-send"); }); }, progressall: function (e, data) { - var progress = parseInt(data.loaded / data.total * 100, 10); - alert(progress); $('#progress .progress-bar').css( 'width', progress + '%' @@ -573,6 +572,11 @@ var teamId = $("#team-chat-form #teamId").val(); var orderId = $("#team-chat-form #orderId").val(); + var documentSendIds = $("#documentSendIds").val(); + console.log(documentSendIds); + var teamDocumentIds = documentSendIds.split(';'); + teamDocumentIds.pop(); + console.log(teamDocumentIds); socket.add_team_message({ "format_type": "add_message_team", "data": { @@ -584,6 +588,8 @@ } }); + + $("#team-chat-form #chatText").val(""); }); diff --git a/chat/templates/chat_customer.html b/chat/templates/chat_customer.html index babae49..296a404 100644 --- a/chat/templates/chat_customer.html +++ b/chat/templates/chat_customer.html @@ -237,7 +237,13 @@ var socket = new SocketHandler(); var form = document.getElementById('message_form'); var csrftoken = getCookie('csrftoken'); + setTimeout(function(){ + $(".user-block").first().trigger('click'); + }, 10); + setTimeout(function(){ + $(".order-block").first().trigger('click'); + }, 100); $("#order-stages").on('click', "#addStagesForm", function(){ $(".new-stages-form").each(function(i,v){ @@ -277,7 +283,6 @@ } }); - $('.order-block').on('click', function () { $("#chat-order-add").css("display", "block"); $("#formsetStage").css("display","block"); @@ -379,7 +384,6 @@ }); - // Вытащить сообщения для конактов $('.user-block').on('click', function () { var userId = $(this).attr('data-id'); diff --git a/chat/templates/index.html b/chat/templates/index.html deleted file mode 100644 index e5a460a..0000000 --- a/chat/templates/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - -Произошла ошибка (form)
' '{form}'
).format(form=pformat(form.errors)))
-
+
context.update({'form': form})
return render(request, self.template_name, context)
else:
@@ -451,9 +453,19 @@ class OfferOrderView(View):
def contractor_portfolio_create(request):
if request.is_ajax():
form = PortfolioForm(data=request.POST)
+ # import code; code.interact(local=dict(globals(), **locals()))
if form.is_valid():
instance = form.save(commit=False)
instance.save()
+ images_ids = request.POST.get('images-ids').split(';')[:-1]
+ for pk in images_ids:
+ picture = Picture.objects.get(pk=pk)
+ temp_file = ContentFile(picture.file.read())
+ temp_file.name = picture.file.name
+ p_photo = PortfolioPhoto()
+ p_photo.img = temp_file
+ p_photo.portfolio = instance
+ p_photo.save()
data = {'status': 'ok'}
else:
data = {'status': 'no', 'form_errors': form.errors}
diff --git a/ratings/__init__.py b/ratings/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ratings/admin.py b/ratings/admin.py
new file mode 100644
index 0000000..e532b50
--- /dev/null
+++ b/ratings/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+from .models import SpecializationRating, HistoryRating
+
+admin.site.register(SpecializationRating)
+admin.site.register(HistoryRating)
diff --git a/ratings/apps.py b/ratings/apps.py
new file mode 100644
index 0000000..09b14f2
--- /dev/null
+++ b/ratings/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class RatingsConfig(AppConfig):
+ name = 'ratings'
diff --git a/ratings/migrations/0001_initial.py b/ratings/migrations/0001_initial.py
new file mode 100644
index 0000000..5a95587
--- /dev/null
+++ b/ratings/migrations/0001_initial.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-08-04 15:52
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('specializations', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('users', '0004_user_contractor_rating'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='HistoryRating',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('rating', models.IntegerField(default=0)),
+ ('created', models.DateTimeField(default=django.utils.timezone.now)),
+ ('description', models.TextField(blank=True)),
+ ('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='history_ratings', to='users.Team')),
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='history_ratings', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'История рейтинга',
+ 'verbose_name_plural': 'Истории рейтинга',
+ },
+ ),
+ migrations.CreateModel(
+ name='SpecializationRating',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('position', models.PositiveIntegerField(default=0)),
+ ('specialization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='specialization_rating', to='specializations.Specialization')),
+ ('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='specialization_rating', to='users.Team')),
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='specialization_rating', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Рейтинг специализаций',
+ 'verbose_name_plural': 'Рейтинги специализаций',
+ },
+ ),
+ ]
diff --git a/ratings/migrations/__init__.py b/ratings/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ratings/models.py b/ratings/models.py
new file mode 100644
index 0000000..4db1001
--- /dev/null
+++ b/ratings/models.py
@@ -0,0 +1,36 @@
+from django.db import models
+from django.utils import timezone
+from users.models import User, Team
+from specializations.models import Specialization
+
+class HistoryRating(models.Model):
+ user = models.ForeignKey(User, related_name='history_ratings', null=True, blank=True)
+ team = models.ForeignKey(Team, related_name='history_ratings', null=True, blank=True)
+ rating = models.IntegerField(default=0)
+ created = models.DateTimeField(default=timezone.now)
+ description = models.TextField(blank=True)
+
+ def __str__(self):
+ return self.rating
+
+ class Meta:
+ verbose_name = 'История рейтинга'
+ verbose_name_plural = 'Истории рейтинга'
+
+
+class SpecializationRating(models.Model):
+ user = models.ForeignKey(User, related_name='specialization_rating', null=True, blank=True)
+ team = models.ForeignKey(Team, related_name='specialization_rating', null=True, blank=True)
+ specialization = models.ForeignKey(Specialization, related_name='specialization_rating')
+ position = models.PositiveIntegerField(default=0)
+
+ def __str__(self):
+ return self.position
+
+ class Meta:
+ verbose_name = 'Рейтинг специализаций'
+ verbose_name_plural = 'Рейтинги специализаций'
+
+
+
+
diff --git a/ratings/tests.py b/ratings/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/ratings/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/ratings/views.py b/ratings/views.py
new file mode 100644
index 0000000..91ea44a
--- /dev/null
+++ b/ratings/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/templates/partials/base.html b/templates/partials/base.html
index bfce740..d2f8708 100644
--- a/templates/partials/base.html
+++ b/templates/partials/base.html
@@ -72,8 +72,8 @@
{% endblock %}