diff --git a/profile/admin.py b/profile/admin.py
index 281aa6eee7e0e65ce99675fc9d3ef07aeb60f34a..6fffd8e3fef000b0a7401ceecc7a75964ed0049a 100644
--- a/profile/admin.py
+++ b/profile/admin.py
@@ -10,13 +10,20 @@ class ProfileInline(admin.StackedInline):
     verbose_name_plural = 'Profile'
     fk_name = 'user'
 
-class CustomUserAdmin(UserAdmin):
+class ProfileUserAdmin(UserAdmin):
     inlines = (ProfileInline, )
 
+    def get_queryset(self, request):
+        # Users can only edit their own profile
+        if not request.user.is_superuser:
+            return super(UserAdmin, self).get_queryset(request).filter(pk=request.user.id)
+
+        return super(UserAdmin, self).get_queryset(request)
+
     def get_inline_instances(self, request, obj=None):
         if not obj:
             return list()
-        return super(CustomUserAdmin, self).get_inline_instances(request, obj)
+        return super(ProfileUserAdmin, self).get_inline_instances(request, obj)
 
 admin.site.unregister(User)
-admin.site.register(User, CustomUserAdmin)
\ No newline at end of file
+admin.site.register(User, ProfileUserAdmin)
\ No newline at end of file
diff --git a/program/admin.py b/program/admin.py
index 251eff1c650682854e524b51e7eed2438bd5d176..ab7f53b791225fe14763be7c2a63e6e56f2e8b22 100644
--- a/program/admin.py
+++ b/program/admin.py
@@ -9,7 +9,6 @@ from .forms import MusicFocusForm, CollisionForm
 
 from datetime import date, datetime, time, timedelta
 
-
 class ActivityFilter(admin.SimpleListFilter):
     title = _("Activity")
 
@@ -89,32 +88,61 @@ class HostAdmin(admin.ModelAdmin):
 class NoteAdmin(admin.ModelAdmin):
     date_hierarchy = 'start'
     list_display = ('title', 'show', 'start', 'status')
+    fields = (( 'show', 'timeslot'), 'title', 'slug', 'summary', 'content', 'image', 'status', 'cba_id')
     prepopulated_fields = {'slug': ('title',)}
     list_filter = ('status',)
     ordering = ('timeslot',)
     save_as = True
 
+    class Media:
+        js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
+               settings.MEDIA_URL + 'js/note_change.js', ]
+
     def get_queryset(self, request):
-        shows = request.user.shows.all()
+        if request.user.is_superuser:
+            # Superusers see notes of all shows
+            shows = Show.objects.all()
+        else:
+            # Users only see notes of shows they own
+            shows = request.user.shows.all()
+
         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_twelf_weeks = datetime.now() + timedelta(weeks=12)
+        in_twelve_weeks = datetime.now() + timedelta(weeks=12)
 
         if db_field.name == 'timeslot':
-            try:
-                timeslot_id = int(request.get_full_path().split('/')[-2])
-            except ValueError:
-                shows = request.user.shows.all()
-                kwargs['queryset'] = TimeSlot.objects.filter(show__in=shows, start__gt=four_weeks_ago,
-                                                             start__lt=in_twelf_weeks) # note__isnull=True
+            # Adding/Editing a note: load timeslots of the user's shows into the dropdown
+
+            # TODO: Don't show any timeslot in the select by default.
+            #       User should first choose show, then timeslots are loaded into the select via ajax.
+            #
+            # How to do this while not constraining the queryset?
+            # Saving won't be possible otherwise, if queryset doesn't contain the selectable elements beforehand
+            #kwargs['queryset'] = TimeSlot.objects.filter(show=-1)
+
+            # Superusers see every timeslot for every show
+            if request.user.is_superuser:
+                kwargs['queryset'] = TimeSlot.objects.filter(start__gt=four_weeks_ago,
+                                                             start__lt=in_twelve_weeks) # note__isnull=True
+            # Users see timeslots of shows they own
             else:
-                kwargs['queryset'] = TimeSlot.objects.filter(note=timeslot_id)
+                kwargs['queryset'] = TimeSlot.objects.filter(show__in=request.user.shows.all(), start__gt=four_weeks_ago,
+                                                             start__lt=in_twelve_weeks) # note__isnull=True
+
+        if db_field.name == 'show':
+            # Adding/Editing a note: load user's shows into the dropdown
+
+            # Superusers see all shows
+            if not request.user.is_superuser:
+                kwargs['queryset'] = Show.objects.filter(pk__in=request.user.shows.all())
 
         return super(NoteAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
     def save_model(self, request, obj, form, change):
+
+        # Save the creator when adding a note
         if not change:
             obj.user = request.user
         obj.save()
@@ -124,11 +152,14 @@ class TimeSlotInline(admin.TabularInline):
     model = TimeSlot
     ordering = ('-end',)
 
+class TimeSlotAdmin(admin.ModelAdmin):
+    model = TimeSlot
+
 
 class ScheduleAdmin(admin.ModelAdmin):
     actions = ('renew',)
     inlines = (TimeSlotInline,)
-    fields = (('rrule', 'byweekday'), ('dstart', 'tstart', 'tend'), 'until', 'is_repetition', 'automation_id', 'fallback_playlist')
+    fields = (('rrule', 'byweekday'), ('dstart', 'tstart', 'tend'), 'until', 'is_repetition', 'automation_id', 'fallback_playlist_id')
     list_display = ('get_show_name', 'byweekday', 'rrule', 'tstart', 'tend', 'until')
     list_filter = (ActiveSchedulesFilter, 'byweekday', 'rrule', 'is_repetition')
     ordering = ('byweekday', 'dstart')
@@ -171,10 +202,19 @@ class ShowAdmin(admin.ModelAdmin):
         'musicfocus', 'fallback_pool', 'cba_series_id',
     )
 
+    def get_queryset(self, request):
+        if request.user.is_superuser:
+            # Superusers see all shows
+            shows = Show.objects.all()
+        else:
+            # Users only see shows they own
+            shows = request.user.shows.all()
+
+        return super(ShowAdmin, self).get_queryset(request).filter(pk__in=shows)
+
     class Media:
-        js = [ settings.MEDIA_URL + 'js/show_change.js',
-               settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
-             ]
+        js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
+               settings.MEDIA_URL + 'js/show_change.js', ]
 
         css = { 'all': ('/program/styles.css',) }
 
@@ -294,6 +334,7 @@ class ShowAdmin(admin.ModelAdmin):
                 until = datetime.strptime(request.POST.get('ps_save_until'), '%Y-%m-%d').date()
                 is_repetition = request.POST.get('ps_save_is_repetition')
                 automation_id = int(request.POST.get('ps_save_automation_id')) if request.POST.get('ps_save_automation_id') != 'None' else 0
+                fallback_playlist_id = int(request.POST.get('fallback_playlist_id')) if request.POST.get('ps_save_fallback_playlist_id') != 'None' else 0
 
                 # Put timeslot POST vars into lists with same indices
                 for i in range(num_inputs):
@@ -337,7 +378,8 @@ class ShowAdmin(admin.ModelAdmin):
                                               tend=tend,
                                               until=until,
                                               is_repetition=is_repetition,
-                                              automation_id=automation_id)
+                                              automation_id=automation_id,
+                                              fallback_playlist_id=fallback_playlist_id)
 
                 # Only save schedule if any timeslots changed
                 if len(resolved_timeslots) > 0:
@@ -371,7 +413,7 @@ class ShowAdmin(admin.ModelAdmin):
                         start_end = ts.split(' - ')
                         # Only create upcoming timeslots
                         if datetime.strptime(start_end[0], "%Y-%m-%d %H:%M:%S") > datetime.today():
-                            timeslot_created = TimeSlot.objects.create(schedule=new_schedule, start=start_end[0], end=start_end[1])
+                            timeslot_created = TimeSlot.objects.create(schedule=new_schedule, is_repetition=new_schedule.is_repetition, start=start_end[0], end=start_end[1])
 
                             # Link a note to the new timeslot
                             if idx in note_indices:
@@ -478,5 +520,5 @@ admin.site.register(RTRCategory, RTRCategoryAdmin)
 admin.site.register(Host, HostAdmin)
 admin.site.register(Note, NoteAdmin)
 #admin.site.register(Schedule, ScheduleAdmin)
-#admin.site.register(TimeSlot, TimeSlotAdmin)
+admin.site.register(TimeSlot, TimeSlotAdmin)
 admin.site.register(Show, ShowAdmin)
\ No newline at end of file
diff --git a/program/fixtures/group_permissions.yaml b/program/fixtures/group_permissions.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..20fa7567d6c35ae28963b3eb5cedc31593bf69a2
--- /dev/null
+++ b/program/fixtures/group_permissions.yaml
@@ -0,0 +1,36 @@
+- model: auth.group_permissions
+  pk: 1
+  fields:
+    id: 1
+    group_id: 1
+    permission_id: 35
+- model: auth.group_permissions
+  pk: 2
+  fields:
+    id: 2
+    group_id: 1
+    permission_id: 28
+- model: auth.group_permissions
+  pk: 3
+  fields:
+    id: 3
+    group_id: 1
+    permission_id: 29
+- model: auth.group_permissions
+  pk: 4
+  fields:
+    id: 4
+    group_id: 1
+    permission_id: 30
+- model: auth.group_permissions
+  pk: 5
+  fields:
+    id: 5
+    group_id: 1
+    permission_id: 8
+- model: auth.group_permissions
+  pk: 6
+  fields:
+    id: 6
+    group_id: 1
+    permission_id: 68
\ No newline at end of file
diff --git a/program/fixtures/groups.yaml b/program/fixtures/groups.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..da482957143e7beec7daf47d2edfee6aa8dec217
--- /dev/null
+++ b/program/fixtures/groups.yaml
@@ -0,0 +1,5 @@
+- model: auth.group
+  pk: 1
+  fields:
+    id: 1
+    name: ProgrammmacherInnen
\ No newline at end of file
diff --git a/program/fixtures/user_groups.yaml b/program/fixtures/user_groups.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..82ce3739ec635d392758dcc485f5e9a4f2abddd3
--- /dev/null
+++ b/program/fixtures/user_groups.yaml
@@ -0,0 +1,6 @@
+- model: auth.user_groups
+  pk: 1
+  fields:
+    id: 1
+    user_id: 2
+    group_id: 1
\ No newline at end of file
diff --git a/program/fixtures/users.yaml b/program/fixtures/users.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..671dfa5c85b34c1bc7c647e7c88a71c8303090db
--- /dev/null
+++ b/program/fixtures/users.yaml
@@ -0,0 +1,11 @@
+- model: auth.user
+  pk: 2
+  fields:
+    id: 2
+    password: pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=
+    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
diff --git a/program/migrations/0012_auto_20171109_1843.py b/program/migrations/0012_auto_20171122_1718.py
similarity index 89%
rename from program/migrations/0012_auto_20171109_1843.py
rename to program/migrations/0012_auto_20171122_1718.py
index 27c9511380358f52d1e00163fae86b05ba9fb2dc..3141a578f5162e2d4a1f7f2880dbf6863d15b641 100644
--- a/program/migrations/0012_auto_20171109_1843.py
+++ b/program/migrations/0012_auto_20171122_1718.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.11.3 on 2017-11-09 18:43
+# Generated by Django 1.11.3 on 2017-11-22 17:18
 from __future__ import unicode_literals
 
 from django.conf import settings
@@ -34,6 +34,18 @@ class Migration(migrations.Migration):
                 'ordering': ('category',),
             },
         ),
+        migrations.CreateModel(
+            name='Language',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=32, verbose_name='Language')),
+            ],
+            options={
+                'verbose_name': 'Language',
+                'verbose_name_plural': 'Languages',
+                'ordering': ('language',),
+            },
+        ),
         migrations.CreateModel(
             name='RTRCategory',
             fields=[
@@ -58,14 +70,14 @@ class Migration(migrations.Migration):
                 ('tend', models.TimeField(verbose_name='End time')),
                 ('until', models.DateField(verbose_name='Last date')),
                 ('is_repetition', models.BooleanField(default=False, verbose_name='Is repetition')),
-                ('fallback_playlist', models.IntegerField(blank=True, null=True, verbose_name='Fallback Playlist')),
+                ('fallback_playlist_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback Playlist ID')),
                 ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID')),
                 ('created', models.DateTimeField(auto_now_add=True, null=True)),
                 ('last_updated', models.DateTimeField(auto_now=True, null=True)),
             ],
             options={
-                'verbose_name': 'Program slot',
-                'verbose_name_plural': 'Program slots',
+                'verbose_name': 'Schedule',
+                'verbose_name_plural': 'Schedules',
                 'ordering': ('dstart', 'tstart'),
             },
         ),
@@ -209,6 +221,16 @@ class Migration(migrations.Migration):
             name='width',
             field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width'),
         ),
+        migrations.AddField(
+            model_name='timeslot',
+            name='is_repetition',
+            field=models.BooleanField(default=False, verbose_name='WH'),
+        ),
+        migrations.AddField(
+            model_name='timeslot',
+            name='memo',
+            field=models.TextField(blank=True, verbose_name='Memo'),
+        ),
         migrations.AlterField(
             model_name='musicfocus',
             name='big_button',
@@ -224,6 +246,11 @@ class Migration(migrations.Migration):
             name='button_hover',
             field=models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)'),
         ),
+        migrations.AlterField(
+            model_name='note',
+            name='show',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='program.Show'),
+        ),
         migrations.AlterField(
             model_name='show',
             name='image',
@@ -261,6 +288,11 @@ class Migration(migrations.Migration):
             name='category',
             field=models.ManyToManyField(blank=True, related_name='shows', to='program.Category', verbose_name='Category'),
         ),
+        migrations.AddField(
+            model_name='show',
+            name='language',
+            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language', verbose_name='Language'),
+        ),
         migrations.AddField(
             model_name='show',
             name='rtrcategory',
diff --git a/program/migrations/0013_auto_20171109_1942.py b/program/migrations/0013_auto_20171109_1942.py
deleted file mode 100644
index 9e6723c42415478eab5586d1bc366423c65e02b7..0000000000000000000000000000000000000000
--- a/program/migrations/0013_auto_20171109_1942.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by Django 1.11.3 on 2017-11-09 19:42
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('program', '0012_auto_20171109_1843'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Language',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=32, verbose_name='Language')),
-            ],
-            options={
-                'verbose_name': 'Language',
-                'verbose_name_plural': 'Languages',
-                'ordering': ('language',),
-            },
-        ),
-        migrations.AlterModelOptions(
-            name='schedule',
-            options={'ordering': ('dstart', 'tstart'), 'verbose_name': 'Schedule', 'verbose_name_plural': 'Schedules'},
-        ),
-        migrations.AddField(
-            model_name='show',
-            name='language',
-            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language', verbose_name='Language'),
-        ),
-    ]
diff --git a/program/models.py b/program/models.py
index c24cde20251d6e18e0c20df01fd142450954c929..9da8178c1a26e2c824dc839640e1a6bd271fcffa 100644
--- a/program/models.py
+++ b/program/models.py
@@ -351,16 +351,17 @@ class Schedule(models.Model):
     tend = models.TimeField(_("End time"))
     until = models.DateField(_("Last date"))
     is_repetition = models.BooleanField(_("Is repetition"), default=False)
-    fallback_playlist = models.IntegerField(_("Fallback Playlist"), blank=True, null=True)
+    fallback_playlist_id = models.IntegerField(_("Fallback Playlist ID"), blank=True, null=True)
     automation_id = models.IntegerField(_("Automation ID"), blank=True, null=True, choices=get_automation_id_choices()) # Deprecated
     created = models.DateTimeField(auto_now_add=True, editable=False, null=True) #-> both see https://stackoverflow.com/questions/1737017/django-auto-now-and-auto-now-add
     last_updated = models.DateTimeField(auto_now=True, editable=False, null=True)
 
     class Meta:
         ordering = ('dstart', 'tstart')
-        # Produces error when adding several schedules at the same time.
-        # Do this test in another way, since it is quite unspecific anyway
-        #unique_together = ('rrule', 'byweekday', 'dstart', 'tstart')
+        # DEPRECATED
+        # Produces error when adding several schedules at the same time
+        # get_collisions() covers this case and checks for interfering times too
+        # unique_together = ('rrule', 'byweekday', 'dstart', 'tstart')
         verbose_name = _("Schedule")
         verbose_name_plural = _("Schedules")
 
@@ -369,6 +370,7 @@ class Schedule(models.Model):
         tend = self.tend.strftime('%H:%M')
         dstart = self.dstart.strftime('%d. %b %Y')
         tstart = self.tstart.strftime('%H:%M')
+        #is_repetition = self.is_repetition
 
         if self.rrule.freq == 0:
             return '%s %s, %s - %s' % (self.rrule, dstart, tstart, tend)
@@ -380,7 +382,7 @@ class Schedule(models.Model):
     def generate_timeslots(schedule):
         """
         Returns a list of timeslot objects based on a schedule and its rrule
-        Returns past timeslots as well starting from dstart (not today)
+        Returns past timeslots as well, starting from dstart (not today)
         """
 
         byweekno = None
@@ -562,6 +564,8 @@ class TimeSlot(models.Model):
     start = models.DateTimeField(_("Start time")) # Removed 'unique=True' because new Timeslots need to be created before deleting the old ones (otherwise linked notes get deleted first)
     end = models.DateTimeField(_("End time"))
     show = models.ForeignKey(Show, editable=False, related_name='timeslots')
+    memo = models.TextField(_("Memo"), blank=True)
+    is_repetition = models.BooleanField(_("WH"), default=False)
 
     objects = TimeSlotManager()
 
@@ -571,10 +575,11 @@ class TimeSlot(models.Model):
         verbose_name_plural = _("Time slots")
 
     def __str__(self):
-        start = self.start.strftime('%d.%m.%Y %H:%M')
+        start = self.start.strftime('%a, %d.%m.%Y %H:%M')
         end = self.end.strftime('%H:%M')
+        is_repetition = ' ' + _('WH') if self.schedule.is_repetition is 1 else ''
 
-        return '%s - %s  |  %s' % (start, end, self.show.name)
+        return '%s - %s  %s (%s)' % (start, end, is_repetition, self.show.name)
 
     def save(self, *args, **kwargs):
         self.show = self.schedule.show
@@ -607,7 +612,7 @@ class Note(models.Model):
     image = VersatileImageField(_("Featured image"), blank=True, null=True, upload_to='note_images', width_field='width', height_field='height', ppoi_field='ppoi')
     status = models.IntegerField(_("Status"), choices=STATUS_CHOICES, default=1)
     start = models.DateTimeField(editable=False)
-    show = models.ForeignKey(Show, editable=False, related_name='notes')
+    show = models.ForeignKey(Show, related_name='notes', editable=True) # User chooses the show. Timeslots are loaded via ajax.
     cba_id = models.IntegerField(_("CBA ID"), blank=True, null=True)
     created = models.DateTimeField(auto_now_add=True, editable=False)
     last_updated = models.DateTimeField(auto_now=True, editable=False)
diff --git a/program/templates/calendar.html b/program/templates/calendar.html
index 2acfbaa92064e26a2434fb341d1addb2de5a9854..318f052ebb5cf638b0bd3aba685ece1f0eab590a 100644
--- a/program/templates/calendar.html
+++ b/program/templates/calendar.html
@@ -88,6 +88,11 @@
         <div id="timeslot-id"></div>
         <div id="timeslot-start"></div>
         <div id="timeslot-end"></div>
+        <div id="show-name"></div>
+        <div id="show-id"></div>
+        <div id="show-hosts"></div>
+        <div id="is-repetition"></div>
+        <div id="fallback-playlist-id"></div>
         <div id="response-message"></div>
       </div>
     </div>
@@ -138,7 +143,7 @@
                 .done(function( data ) {
                    // Remove element from DOM
                    jQuery('#calendar').fullCalendar('removeEvents', event._id );
-                   notify( 'Episode gel&ouml;scht.' );
+                   notify( 'Time slot deleted.' );
                    console.log(data.result);
                 })
                 .fail(function( data ) {
@@ -170,6 +175,12 @@
                 jQuery("#timeslot-id").html(timeslot.id);
                 jQuery("#timeslot-start").html(timeslot.start);
                 jQuery("#timeslot-end").html(timeslot.end);
+                jQuery("#show-name").html(timeslot.show_name);
+                jQuery("#show-id").html(timeslot.show_id);
+                jQuery("#show-hosts").html(timeslot.show_hosts);
+                jQuery("#is-repetition").html(timeslot.is_repetition);
+                jQuery("#fallback-playlist-id").html(timeslot.fallback_playlist_id);
+                jQuery("#memo").html(timeslot.memo);
                 jQuery("#response-message").html("Success");
               },
               error: function() {
@@ -200,6 +211,7 @@
        });
     });
 
+/*
     function updateTimeslot( event ) {
 
        var id = event.id;
@@ -213,7 +225,7 @@
 
        jQuery.post( ajaxurl, { 'action': 'update_timeslot', 'id': id, 'date': date, 'start': start, 'stop' : stop } )
        .done(function( data ) {
-          notify( '&Auml;nderungen gespeichert.' );
+          notify( 'Changes saved.' );
           console.log(data.result);
        })
        .fail(function( data ) {
@@ -221,7 +233,7 @@
        });
 
     }
-
+*/
     </script>
 
 </body>
diff --git a/program/templates/collisions.html b/program/templates/collisions.html
index e891b8dc88e5b8343745cae22a1e2215871deb71..84de2053f59fdfd16e25f1e660acb9f6778156f5 100644
--- a/program/templates/collisions.html
+++ b/program/templates/collisions.html
@@ -136,6 +136,7 @@
         <input type="hidden" name="ps_save_until" value="{{ schedule.until|date:"Y-m-d" }}" />
         <input type="hidden" name="ps_save_is_repetition" value="{{ schedule.is_repetition }}" />
         <input type="hidden" name="ps_save_automation_id" value="{{ schedule.automation_id }}" />
+        <input type="hidden" name="ps_save_fallback_playlist_id" value="{{ schedule.fallback_playlist_id }}" />
         <input type="hidden" name="ps_save_show_id" value="{{ schedule.show_id }} " />
         <input type="hidden" name="num_inputs" value="{{ num_inputs }}" />
         <input type="hidden" name="step" value="{{ step }}" />
@@ -154,6 +155,7 @@
           <p class="deletelink-box"><a href="/admin/program/show/{{ obj.id }}/change" class="deletelink">Abbrechen und &Auml;nderungen verwerfen</a></p>
         </div>
 
+        <!-- TODO: Problemo: If form validation failed, submit will be prevented -> only include the fields necessary -->
         <div style="display:none;">
          {{ schedulesform.as_ul }}
          {{ showform.as_ul }}
diff --git a/program/views.py b/program/views.py
index 8258d6bd834a94f8f0bbad7c48d82032df1b50a7..70471c00ab6595414f753b86da50767c38561b9b 100644
--- a/program/views.py
+++ b/program/views.py
@@ -11,7 +11,6 @@ from django.views.generic.detail import DetailView
 from django.views.generic.list import ListView
 
 from .models import Type, MusicFocus, Note, Show, Category, Topic, TimeSlot, Host
-
 from program.utils import tofirstdayinisoweek, get_cached_shows
 
 
@@ -227,6 +226,7 @@ def json_week_schedule(request):
     """
     Called by calendar to get all timeslots for a week.
     Expects GET variable 'start' (date), otherwise start will be today
+    Returns all timeslots of the next 7 days
     """
 
     start = request.GET.get('start')
@@ -240,15 +240,28 @@ def json_week_schedule(request):
     schedule = []
     for ts in timeslots:
 
-        # TODO: Will be a field of timeslots in the future
-        is_repetition = ' (WH)' if ts.schedule.is_repetition == 1 else ''
+        is_repetition = ' ' + _('WH') if ts.schedule.is_repetition is 1 else ''
+
+        hosts = ''
+
+        for host in ts.show.hosts.all():
+            hosts = host.name + ', ' + hosts
 
         entry = {
             'start': ts.start.strftime('%Y-%m-%dT%H:%M:%S'),
             'end': ts.end.strftime('%Y-%m-%dT%H:%M:%S'),
             'title': ts.show.name + is_repetition,
             'id': ts.id, #show.id,
-            'automation-id': -1
+            'automation-id': -1,
+            'schedule_id': ts.schedule.id,
+            'show_id': ts.show.id,
+            'show_name': ts.show.name,
+            'show_hosts': hosts,
+            'is_repetition': ts.is_repetition,
+            'fallback_playlist_id': ts.schedule.fallback_playlist_id, # the schedule's fallback playlist
+            'show_fallback_pool': ts.show.fallback_pool, # the show's fallback
+            # TODO
+            #'station_fallback_pool': # the station's global fallback (might change suddenly)
         }
 
         if ts.schedule.automation_id:
@@ -287,8 +300,56 @@ def json_timeslots_specials(request):
 
 
 def json_get_timeslot(request):
+    if not request.user.is_authenticated():
+        return JsonResponse(_('Permission denied.'))
+
     if request.method == 'GET':
         try:
-            return JsonResponse( model_to_dict(TimeSlot.objects.select_related('schedule').select_related('show').get(pk=int(request.GET.get('timeslot_id')))))
+            timeslot = TimeSlot.objects.get(pk=int(request.GET.get('timeslot_id')))
+
+            returnvar = { 'id': timeslot.id, 'start': timeslot.start, 'end': timeslot.end,
+                          'schedule_id': timeslot.schedule.id, 'show_name': timeslot.show.name,
+                          'is_repetition': timeslot.schedule.is_repetition,
+                          'fallback_playlist_id': timeslot.schedule.fallback_playlist_id,
+                          'memo': timeslot.memo }
+            return JsonResponse( returnvar, safe=False )
         except ObjectDoesNotExist:
-            return JsonResponse( list('Error') );
\ No newline at end of file
+            return JsonResponse( _('Error') );
+
+
+def json_get_timeslots_by_show(request):
+    '''
+    Returns a JSON object of timeslots of a given show from 4 weeks ago until 12 weeks in the future
+    Called by /export/get_timeslot_by_show/?show_id=1 to populate a timeslot-select for being assigned to a note
+    '''
+
+    if not request.user.is_authenticated():
+        return JsonResponse(_('Permission denied.'))
+
+    if request.method == 'GET' and int(request.GET.get('show_id')):
+
+        four_weeks_ago = datetime.now() - timedelta(weeks=4)
+        in_twelve_weeks = datetime.now() + timedelta(weeks=12)
+
+        timeslots = []
+        saved_timeslot_id = int(request.GET.get('timeslot_id'))
+
+        # If the saved timeslot is part of the currently selected show,
+        # include it as the first select-option in order not to lose it if it's past
+        if saved_timeslot_id > 0:
+            try:
+                saved_timeslot = TimeSlot.objects.get(pk=int(request.GET.get('timeslot_id')),show=int(request.GET.get('show_id')))
+                timeslots.append( { 'timeslot': str(saved_timeslot), 'timeslot_id': saved_timeslot.id, 'start': saved_timeslot.start, 'end': saved_timeslot.end } )
+            except ObjectDoesNotExist:
+                pass
+
+        for timeslot in TimeSlot.objects.filter(show=int(request.GET.get('show_id')),
+                                                start__gt=four_weeks_ago,
+                                                start__lt=in_twelve_weeks).exclude(pk=saved_timeslot_id):
+
+            timeslots.append( { 'timeslot': str(timeslot), 'timeslot_id' : timeslot.id, 'start': timeslot.start, 'end': timeslot.end } )
+
+        return JsonResponse( timeslots, safe=False )
+
+    else:
+        return JsonResponse( _('No show_id given.'), safe=False )
\ No newline at end of file
diff --git a/pv/site_media/js/note_change.js b/pv/site_media/js/note_change.js
new file mode 100644
index 0000000000000000000000000000000000000000..7a397d57041d5e35cc57ad8c39fcec21545413fe
--- /dev/null
+++ b/pv/site_media/js/note_change.js
@@ -0,0 +1,46 @@
+django.jQuery(document).ready( function() {
+
+   /* Get the already saved timeslot_id to preserve if past */
+   var selected_timeslot_id = django.jQuery('select#id_timeslot option:selected').val() || 0;
+
+	/* If a show is selected load its timeslots into the corresponding select */
+	django.jQuery("select#id_show").on("change", function() {
+
+	   /* Get selected show */
+	   var show_id = django.jQuery("select#id_show option:selected").val();
+	   if( show_id == '' ) {
+	      django.jQuery('select#id_timeslot').html( new Option( '', '' ) );
+	      return;
+	   }
+
+	   django.jQuery('select#id_timeslot').fadeOut();
+
+	   /* Call ajax function and retrieve array containing objects */
+	   django.jQuery.ajax({
+            url: '/export/get_timeslots_by_show',
+            type: 'GET',
+            data: {
+              'show_id': show_id,
+              'timeslot_id': selected_timeslot_id,
+              'csrfmiddlewaretoken': django.jQuery('input[name="csrfmiddlewartetoken"]').val()
+            },
+            success: function(timeslots) {
+	            /* Populate timeslot select */
+	            var options = new Array();
+
+	            for( var i=0; i < timeslots.length; i++ ) {
+	               options[i] = new Option( timeslots[i].timeslot, parseInt(timeslots[i].timeslot_id) ); //+ " " + moment.utc( timeslots[i].start ).format('dddd, D.M. YYYY HH:mm') + ' - ' + moment.utc( timeslots[i].end ).format('HH:mm'), timeslots[i].timeslot_id );
+	            }
+
+	            django.jQuery('select#id_timeslot').html( options ).fadeIn();
+
+	         },
+	         error: function() {
+	            alert("Couldn't load timeslots.");
+	         }
+
+		});
+
+   });
+
+});
\ No newline at end of file
diff --git a/pv/site_media/js/show_change.js b/pv/site_media/js/show_change.js
index f3db2ec526663e8ba6a4cbe057a4ff20be1e5eb3..5e3f8f2c0e6ad0c8a63a4fcf047173d759432c76 100644
--- a/pv/site_media/js/show_change.js
+++ b/pv/site_media/js/show_change.js
@@ -14,9 +14,16 @@ function toggleSelects( select_elm ) {
    if( option_val < 4 ) {
       weekday_select.fadeOut().val(0); // Although it'll be ignored, select Monday in order the form can be validated
 
-      if( option_val == 1 )
+      if( option_val == 1 ) {
          // If once, hide the until-date too and try to set it to dstart
-         until_select.val(dstart.val()).fadeOut().next('.datetimeshortcuts').fadeOut();
+			if( until_select.val() == '')
+			  until_select.val(dstart.val());
+
+         until_select.fadeOut().next('.datetimeshortcuts').fadeOut();
+      } else {
+         until_select.fadeIn().next('.datetimeshortcuts').fadeIn();
+      }
+
 
    } else {
       weekday_select.fadeIn();
diff --git a/pv/urls.py b/pv/urls.py
index 8135910840fbc39413baf192d2ede128a89eb2b3..69ca4947c67d2cc2c1829d1d40418d7794814176 100644
--- a/pv/urls.py
+++ b/pv/urls.py
@@ -3,8 +3,7 @@ from django.conf.urls import url, include
 from django.contrib import admin
 from django.views.static import serve
 
-from program.views import json_day_schedule, json_week_schedule, json_timeslots_specials, json_get_timeslot
-
+from program.views import json_day_schedule, json_week_schedule, json_timeslots_specials, json_get_timeslot, json_get_timeslots_by_show
 
 admin.autodiscover()
 
@@ -17,6 +16,7 @@ urlpatterns = [
     url(r'^export/week_schedule$', json_week_schedule),
     url(r'^export/timeslots_specials.json$', json_timeslots_specials),
     url(r'^export/get_timeslot$', json_get_timeslot, name='get-timeslot'),
+    url(r'^export/get_timeslots_by_show$', json_get_timeslots_by_show, name='get-timeslots-by-show'),
 ]
 
 if settings.DEBUG: