From bedf701e06420afc4a069cf1ce14d4d7c3772059 Mon Sep 17 00:00:00 2001
From: ingo <ingo.leindecker@fro.at>
Date: Sun, 18 Feb 2018 12:22:54 +0100
Subject: [PATCH] Added encoding, fixed bugs and added field note_id to
 timeslots

See #21 #23
---
 frapp/urls.py                                 |  2 ++
 frapp/views.py                                |  2 ++
 manage.py                                     |  4 ++-
 nop/dbrouter.py                               |  4 ++-
 nop/models.py                                 |  2 ++
 nop/urls.py                                   |  2 ++
 profile/admin.py                              |  2 ++
 profile/models.py                             |  2 ++
 profile/serializers.py                        |  3 +++
 profile/urls.py                               |  2 ++
 program/admin.py                              | 11 +++++---
 program/fixtures/users.yaml                   | 14 ++++++++--
 program/forms.py                              |  2 ++
 program/migrations/0015_auto_20180218_1111.py | 25 +++++++++++++++++
 program/models.py                             | 27 +++++++++++++++----
 program/serializers.py                        |  2 ++
 program/templatetags/content_boxes.py         |  2 ++
 program/templatetags/timeslots.py             |  4 ++-
 program/urls.py                               |  2 ++
 program/utils.py                              |  2 ++
 program/views.py                              |  4 ++-
 pv/site_media/js/note_change.js               |  3 +--
 pv/urls.py                                    |  2 ++
 pv/wsgi.py                                    |  4 ++-
 24 files changed, 112 insertions(+), 17 deletions(-)
 create mode 100644 program/migrations/0015_auto_20180218_1111.py

diff --git a/frapp/urls.py b/frapp/urls.py
index 77a711ef..f6b7814e 100644
--- a/frapp/urls.py
+++ b/frapp/urls.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.conf.urls import url
 from .views import json_frapp
 
diff --git a/frapp/views.py b/frapp/views.py
index dc6da53e..ceda81a6 100644
--- a/frapp/views.py
+++ b/frapp/views.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 import json
 from datetime import date, datetime, time
 
diff --git a/manage.py b/manage.py
index daf26268..3c5acb08 100755
--- a/manage.py
+++ b/manage.py
@@ -1,4 +1,6 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
 import os
 import sys
 
@@ -7,4 +9,4 @@ if __name__ == "__main__":
 
     from django.core.management import execute_from_command_line
 
-    execute_from_command_line(sys.argv)
+    execute_from_command_line(sys.argv)
\ No newline at end of file
diff --git a/nop/dbrouter.py b/nop/dbrouter.py
index fd8aaadd..99a42d98 100644
--- a/nop/dbrouter.py
+++ b/nop/dbrouter.py
@@ -1,5 +1,7 @@
+# -*- coding: utf-8 -*-
+
 class NopRouter(object):
     def allow_migrate(self, db, app_label, model_name=None, **hints):
         if app_label == 'nop':
             return db == 'nop'
-        return None
+        return None
\ No newline at end of file
diff --git a/nop/models.py b/nop/models.py
index 05e815b8..16c09dff 100644
--- a/nop/models.py
+++ b/nop/models.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.db import models
 
 class CartTypeField(models.Field):
diff --git a/nop/urls.py b/nop/urls.py
index 1a1bc823..fb6774b8 100644
--- a/nop/urls.py
+++ b/nop/urls.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.conf.urls import url
 from django.views.static import serve
 
diff --git a/profile/admin.py b/profile/admin.py
index 7f8385ce..9ed19537 100644
--- a/profile/admin.py
+++ b/profile/admin.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin
 from django.contrib.auth.models import User
diff --git a/profile/models.py b/profile/models.py
index 0a2d867c..47ada47f 100644
--- a/profile/models.py
+++ b/profile/models.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.core.exceptions import ObjectDoesNotExist
 from django.db import models
 from django.contrib.auth.models import User
diff --git a/profile/serializers.py b/profile/serializers.py
index 6cee5553..779162a6 100644
--- a/profile/serializers.py
+++ b/profile/serializers.py
@@ -1,7 +1,10 @@
+# -*- coding: utf-8 -*-
+
 from django.contrib.auth.models import User
 from rest_framework import serializers
 from profile.models import Profile
 
+
 class ProfileSerializer(serializers.ModelSerializer):
     class Meta:
         model = Profile
diff --git a/profile/urls.py b/profile/urls.py
index ef961e39..f5a1005d 100644
--- a/profile/urls.py
+++ b/profile/urls.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.contrib import admin
 from rest_framework import routers
 
diff --git a/program/admin.py b/program/admin.py
index 4766f82d..b72afd8b 100644
--- a/program/admin.py
+++ b/program/admin.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.core.exceptions import ObjectDoesNotExist
 from django.contrib import admin
 from django.utils.translation import ugettext_lazy as _
@@ -122,7 +124,6 @@ class NoteAdmin(admin.ModelAdmin):
         return super(NoteAdmin, self).get_queryset(request).filter(show__in=shows)
 
 
-
     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
         four_weeks_ago = datetime.now() - timedelta(weeks=4)
         in_twelve_weeks = datetime.now() + timedelta(weeks=12)
@@ -151,7 +152,7 @@ class NoteAdmin(admin.ModelAdmin):
 
             # Common users only see shows they own
             if not request.user.is_superuser:
-                kwargs['queryset'] = Show.objects.filter(pk__in=request.user.shows.all(), is_active=True)
+                kwargs['queryset'] = Show.objects.filter(pk__in=request.user.shows.all())
 
 
         if db_field.name == 'host':
@@ -170,9 +171,13 @@ class NoteAdmin(admin.ModelAdmin):
 
         # Try to get direct audio URL from CBA
         obj.audio_url = Note.get_audio_url(obj.cba_id)
-
         obj.save()
 
+        # Save the note id to table timeslot as well
+        timeslot = TimeSlot.objects.get(pk=obj.timeslot_id)
+        timeslot.note_id = obj.id
+        timeslot.save()
+
 
 class TimeSlotInline(admin.TabularInline):
     model = TimeSlot
diff --git a/program/fixtures/users.yaml b/program/fixtures/users.yaml
index 671dfa5c..dff42941 100644
--- a/program/fixtures/users.yaml
+++ b/program/fixtures/users.yaml
@@ -1,11 +1,21 @@
 - model: auth.user
+  pk: 1
+  fields:
+    id: 1
+    password: pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=
+    last_login: NULL
+    is_superuser: 1
+    username: admin
+    is_staff: 1
+    is_active: 1
+    date_joined: 2018-01-01 00:00:00
   pk: 2
   fields:
     id: 2
-    password: pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=
+    password: pbkdf2_sha256$36000$VVSM5LeZfBZM$w0XSHCrucEb7Oj1Qpjdy1SKq5KelpXSPiUXbxh3rWpM=
     last_login: NULL
     is_superuser: 0
     username: pm1
     is_staff: 1
     is_active: 1
-    date_joined: 2017-11-22 00:00:00
\ No newline at end of file
+    date_joined: 2018-01-01 00:00:00
\ No newline at end of file
diff --git a/program/forms.py b/program/forms.py
index d84d1b2b..e7334a4b 100644
--- a/program/forms.py
+++ b/program/forms.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django import forms
 from django.forms import ModelForm, ValidationError
 from django.core.files.images import get_image_dimensions
diff --git a/program/migrations/0015_auto_20180218_1111.py b/program/migrations/0015_auto_20180218_1111.py
new file mode 100644
index 00000000..291a19ed
--- /dev/null
+++ b/program/migrations/0015_auto_20180218_1111.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.3 on 2018-02-18 11:11
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('program', '0014_auto_20180216_2000'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='timeslot',
+            name='note_id',
+            field=models.IntegerField(editable=False, null=True, verbose_name='Note ID'),
+        ),
+        migrations.AlterField(
+            model_name='timeslot',
+            name='is_repetition',
+            field=models.BooleanField(default=False, verbose_name='Is repetition?'),
+        ),
+    ]
diff --git a/program/models.py b/program/models.py
index b54931f2..a1f047e7 100644
--- a/program/models.py
+++ b/program/models.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.contrib.auth.models import User
 from django.core.exceptions import ObjectDoesNotExist, ValidationError, MultipleObjectsReturned
 from django.urls import reverse
@@ -976,6 +978,12 @@ class Schedule(models.Model):
             return conflicts
 
 
+        # Collect upcoming timeslots to delete which might still remain
+        del_timeslots = TimeSlot.objects.filter(schedule=schedule, start__gt=schedule.until)
+        for del_ts in del_timeslots:
+            delete.append(del_ts)
+
+
         # If 'dryrun' is true, just return the projected changes instead of executing them
         if 'dryrun' in sdl and sdl['dryrun']:
             output = {}
@@ -992,9 +1000,6 @@ class Schedule(models.Model):
             # Create or update schedule
             schedule.save()
 
-            # Delete upcoming timeslots which still remain
-            TimeSlot.objects.filter(schedule=schedule, start__gt=schedule.until).delete()
-
         # Update timeslots
         for ts in update:
             ts.save(update_fields=["start", "end"])
@@ -1015,10 +1020,14 @@ class Schedule(models.Model):
                     note = Note.objects.get(pk=int(data['notes'][ts.hash]))
                     note.timeslot_id = ts.id
                     note.save(update_fields=["timeslot_id"])
+
+                    timeslot = TimeSlot.objects.get(pk=ts.id)
+                    timeslot.note_id = note.id
+                    timeslot.save(update_fields=["note_id"])
                 except ObjectDoesNotExist:
                     pass
 
-        # Delete manually resolved timeslots
+        # Delete manually resolved timeslots and those after until
         for dl in delete:
             dl.delete()
 
@@ -1109,6 +1118,7 @@ class TimeSlot(models.Model):
     memo = models.TextField(_("Memo"), blank=True)
     is_repetition = models.BooleanField(_("Is repetition?"), default=False)
     playlist_id = models.IntegerField(_("Playlist ID"), null=True)
+    note_id = models.IntegerField(_("Note ID"), null=True, editable=False)
 
     objects = TimeSlotManager()
 
@@ -1182,10 +1192,13 @@ class Note(models.Model):
         Whether the given note is assigned to a show the current user owns
         @return boolean
         """
+
         if self.request.user.is_superuser:
             return True
 
-        return int(note_id) in self.request.user.shows.all().values_list('id', flat=True)
+        note = Note.objects.get(pk=note_id)
+
+        return int(note.show_id) in self.request.user.shows.all().values_list('id', flat=True)
 
     def get_audio_url(cba_id):
         """
@@ -1221,6 +1234,10 @@ class Note(models.Model):
         self.start = self.timeslot.start
         self.show = self.timeslot.schedule.show
 
+        timeslot = TimeSlot.objects.get(pk=self.timeslot.id)
+        timeslot.note_id = self.id
+        timeslot.save()
+
         super(Note, self).save(*args, **kwargs)
 
         # Generate thumbnails
diff --git a/program/serializers.py b/program/serializers.py
index 21704cad..dcc20c72 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.core.exceptions import ObjectDoesNotExist
 from django.contrib.auth.models import User, Group
 from rest_framework import serializers, status
diff --git a/program/templatetags/content_boxes.py b/program/templatetags/content_boxes.py
index ea068628..73fa691a 100644
--- a/program/templatetags/content_boxes.py
+++ b/program/templatetags/content_boxes.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django import template
 
 from program.models import Type, MusicFocus, Category, Topic
diff --git a/program/templatetags/timeslots.py b/program/templatetags/timeslots.py
index 08e45b1e..efab3ccd 100644
--- a/program/templatetags/timeslots.py
+++ b/program/templatetags/timeslots.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django import template
 
 from datetime import datetime, time, timedelta
@@ -22,4 +24,4 @@ def duration_since(start):
         end = datetime.combine(start.date()+timedelta(days=1), time(6, 0))
     else:
         end = datetime.combine(start.date(), time(6, 0))
-    return 'style="height: %dpx"' % ((end-start).seconds/60)
+    return 'style="height: %dpx"' % ((end-start).seconds/60)
\ No newline at end of file
diff --git a/program/urls.py b/program/urls.py
index f98a77d2..54c8b31c 100644
--- a/program/urls.py
+++ b/program/urls.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.conf import settings
 from django.conf.urls import url
 from django.views.decorators.cache import cache_page
diff --git a/program/utils.py b/program/utils.py
index 3c7731a0..e5df6a0a 100644
--- a/program/utils.py
+++ b/program/utils.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.conf import settings
 
 import json
diff --git a/program/views.py b/program/views.py
index e606cb6b..5aa7a5aa 100644
--- a/program/views.py
+++ b/program/views.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 import json
 from datetime import date, datetime, time, timedelta
 
@@ -948,7 +950,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
         note = get_object_or_404(Note, pk=pk, timeslot=timeslot_pk, show=show_pk)
 
         # Commons users may only edit notes of shows they own
-        if not Note.is_editable(self, note_id):
+        if not Note.is_editable(self, note.id):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         serializer = NoteSerializer(note, data=request.data)
diff --git a/pv/site_media/js/note_change.js b/pv/site_media/js/note_change.js
index 449da212..5566b6a6 100644
--- a/pv/site_media/js/note_change.js
+++ b/pv/site_media/js/note_change.js
@@ -18,10 +18,9 @@ django.jQuery(document).ready( function() {
 
 	   /* Call ajax function and retrieve array containing objects */
 	   django.jQuery.ajax({
-            url: '/api/v1/timeslots/',
+            url: '/api/v1/shows/' + show_id + '/timeslots/',
             type: 'GET',
             data: {
-              'show_id': show_id,
               'csrfmiddlewaretoken': django.jQuery('input[name="csrfmiddlewartetoken"]').val()
             },
             success: function(timeslots) {
diff --git a/pv/urls.py b/pv/urls.py
index 38646dc7..e7baee15 100644
--- a/pv/urls.py
+++ b/pv/urls.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from django.conf import settings
 from django.conf.urls import url, include
 from django.contrib import admin
diff --git a/pv/wsgi.py b/pv/wsgi.py
index f704d309..ccae5d48 100644
--- a/pv/wsgi.py
+++ b/pv/wsgi.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 """
 WSGI config for pv project.
 
@@ -28,4 +30,4 @@ application = get_wsgi_application()
 
 # Apply WSGI middleware here.
 # from helloworld.wsgi import HelloWorldApplication
-# application = HelloWorldApplication(application)
+# application = HelloWorldApplication(application)
\ No newline at end of file
-- 
GitLab