forked from rc/aircox
		
	add date into diffusion menu in wagtail nav; get larger menus in back-office
This commit is contained in:
		@ -101,9 +101,9 @@ class DiffusionAdmin(admin.ModelAdmin):
 | 
				
			|||||||
        sounds = [ str(s) for s in obj.get_archives()]
 | 
					        sounds = [ str(s) for s in obj.get_archives()]
 | 
				
			||||||
        return ', '.join(sounds) if sounds else ''
 | 
					        return ', '.join(sounds) if sounds else ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def conflicts(self, obj):
 | 
					    def conflicts_(self, obj):
 | 
				
			||||||
        if obj.type == Diffusion.Type.unconfirmed:
 | 
					        if obj.conflicts.count():
 | 
				
			||||||
            return ', '.join([ str(d) for d in obj.get_conflicts()])
 | 
					            return obj.conflicts.count()
 | 
				
			||||||
        return ''
 | 
					        return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def end_time(self, obj):
 | 
					    def end_time(self, obj):
 | 
				
			||||||
@ -113,12 +113,13 @@ class DiffusionAdmin(admin.ModelAdmin):
 | 
				
			|||||||
    def first(self, obj):
 | 
					    def first(self, obj):
 | 
				
			||||||
        return obj.initial.start if obj.initial else ''
 | 
					        return obj.initial.start if obj.initial else ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    list_display = ('id', 'program', 'start', 'end_time', 'type', 'first', 'archives', 'conflicts')
 | 
					    list_display = ('id', 'program', 'start', 'end_time', 'type', 'first', 'archives', 'conflicts_')
 | 
				
			||||||
    list_filter = ('type', 'start', 'program')
 | 
					    list_filter = ('type', 'start', 'program')
 | 
				
			||||||
    list_editable = ('type',)
 | 
					    list_editable = ('type',)
 | 
				
			||||||
    ordering = ('-start', 'id')
 | 
					    ordering = ('-start', 'id')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fields = ['type', 'start', 'end', 'initial', 'program']
 | 
					    fields = ['type', 'start', 'end', 'initial', 'program', 'conflicts']
 | 
				
			||||||
 | 
					    readonly_fields = ('conflicts',)
 | 
				
			||||||
    inlines = [ DiffusionInline, SoundInline ]
 | 
					    inlines = [ DiffusionInline, SoundInline ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,43 +25,12 @@ from aircox.models import *
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger('aircox.tools')
 | 
					logger = logging.getLogger('aircox.tools')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Actions:
 | 
					class Actions:
 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def __check_conflicts (item, saved_items):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Check for conflicts, and update conflictual
 | 
					 | 
				
			||||||
        items if they have been generated during this
 | 
					 | 
				
			||||||
        update.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        It set an attribute 'do_not_save' if the item should not
 | 
					 | 
				
			||||||
        be saved. FIXME: find proper way
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Return the number of conflicts
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        conflicts = list(item.get_conflicts())
 | 
					 | 
				
			||||||
        for i, conflict in enumerate(conflicts):
 | 
					 | 
				
			||||||
            if conflict.program == item.program:
 | 
					 | 
				
			||||||
                item.do_not_save = True
 | 
					 | 
				
			||||||
                del conflicts[i]
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if conflict.pk in saved_items and \
 | 
					 | 
				
			||||||
                    conflict.type != Diffusion.Type.unconfirmed:
 | 
					 | 
				
			||||||
                conflict.type = Diffusion.Type.unconfirmed
 | 
					 | 
				
			||||||
                conflict.save()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if not conflicts:
 | 
					 | 
				
			||||||
            item.type = Diffusion.Type.normal
 | 
					 | 
				
			||||||
            return 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        item.type = Diffusion.Type.unconfirmed
 | 
					 | 
				
			||||||
        return len(conflicts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def update (cl, date, mode):
 | 
					    def update (cl, date, mode):
 | 
				
			||||||
        manual = (mode == 'manual')
 | 
					        manual = (mode == 'manual')
 | 
				
			||||||
        if not manual:
 | 
					 | 
				
			||||||
            saved_items = set()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        count = [0, 0]
 | 
					        count = [0, 0]
 | 
				
			||||||
        for schedule in Schedule.objects.filter(program__active = True) \
 | 
					        for schedule in Schedule.objects.filter(program__active = True) \
 | 
				
			||||||
@ -71,16 +40,15 @@ class Actions:
 | 
				
			|||||||
            items = schedule.diffusions_of_month(date, exclude_saved = True)
 | 
					            items = schedule.diffusions_of_month(date, exclude_saved = True)
 | 
				
			||||||
            count[0] += len(items)
 | 
					            count[0] += len(items)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if manual:
 | 
					            # we can't bulk create because we ned signal processing
 | 
				
			||||||
                Diffusion.objects.bulk_create(items)
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
            for item in items:
 | 
					            for item in items:
 | 
				
			||||||
                    count[1] += cl.__check_conflicts(item, saved_items)
 | 
					                conflicts = item.get_conflicts()
 | 
				
			||||||
                    if hasattr(item, 'do_not_save'):
 | 
					                item.type = Diffusion.Type.unconfirmed \
 | 
				
			||||||
                        count[0] -= 1
 | 
					                                if manual or conflicts.count() else \
 | 
				
			||||||
                        continue
 | 
					                            Diffusion.Type.normal
 | 
				
			||||||
                    item.save()
 | 
					                item.save(no_check = True)
 | 
				
			||||||
                    saved_items.add(item)
 | 
					                if conflicts.count():
 | 
				
			||||||
 | 
					                    item.conflicts.set(conflicts.all())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            logger.info('[update] schedule %s: %d new diffusions',
 | 
					            logger.info('[update] schedule %s: %d new diffusions',
 | 
				
			||||||
                    str(schedule), len(items),
 | 
					                    str(schedule), len(items),
 | 
				
			||||||
 | 
				
			|||||||
@ -720,19 +720,6 @@ class DiffusionManager(models.Manager):
 | 
				
			|||||||
        qs = self if qs is None else qs
 | 
					        qs = self if qs is None else qs
 | 
				
			||||||
        return qs.filter(program__station = station)
 | 
					        return qs.filter(program__station = station)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def __in_range(field, range, field_ = None, reversed = False):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Return a kwargs to catch diffusions based on the given field name
 | 
					 | 
				
			||||||
        and datetime range.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        if reversed:
 | 
					 | 
				
			||||||
            return { field + "__lte": range[1],
 | 
					 | 
				
			||||||
                     (field_ or field) + "__gte": range[0] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return { field + "__gte" : range[0],
 | 
					 | 
				
			||||||
                 (field_ or field) + "__lte" : range[1] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def at(self, station, date = None, next = False, qs = None):
 | 
					    def at(self, station, date = None, next = False, qs = None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return diffusions occuring at the given date, ordered by +start
 | 
					        Return diffusions occuring at the given date, ordered by +start
 | 
				
			||||||
@ -754,22 +741,21 @@ class DiffusionManager(models.Manager):
 | 
				
			|||||||
        if isinstance(date, datetime.datetime):
 | 
					        if isinstance(date, datetime.datetime):
 | 
				
			||||||
            # use datetime: we want diffusion that occurs around this
 | 
					            # use datetime: we want diffusion that occurs around this
 | 
				
			||||||
            # range
 | 
					            # range
 | 
				
			||||||
            range = date, date
 | 
					            filters = { 'start__lte': date, 'end__gte': date }
 | 
				
			||||||
            filters = self.__in_range('start', range, 'end', True)
 | 
					 | 
				
			||||||
            if next:
 | 
					            if next:
 | 
				
			||||||
                qs = qs.filter(
 | 
					                qs = qs.filter(
 | 
				
			||||||
                    models.Q(date__gte = date) | models.Q(**filters)
 | 
					                    models.Q(start__gte = date) | models.Q(**filters)
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                qs = qs.filter(**filters)
 | 
					                qs = qs.filter(**filters)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            # use date: we want diffusions that occurs this day
 | 
					            # use date: we want diffusions that occurs this day
 | 
				
			||||||
            range = utils.date_range(date)
 | 
					            start, end = utils.date_range(date)
 | 
				
			||||||
            filters = models.Q(**self.__in_range('start', range)) | \
 | 
					            filters = models.Q(start__gte = start, start__lte = end) | \
 | 
				
			||||||
                     models.Q(**self.__in_range('end', range))
 | 
					                      models.Q(end__gt = start, end__lt = end)
 | 
				
			||||||
            if next:
 | 
					            if next:
 | 
				
			||||||
                # include also diffusions of the next day
 | 
					                # include also diffusions of the next day
 | 
				
			||||||
                filters |= models.Q(start__gte = range[0])
 | 
					                filters |= models.Q(start__gte = start)
 | 
				
			||||||
            qs = qs.filter(filters)
 | 
					            qs = qs.filter(filters)
 | 
				
			||||||
        return self.station(station, qs).order_by('start').distinct()
 | 
					        return self.station(station, qs).order_by('start').distinct()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -842,6 +828,12 @@ class Diffusion(models.Model):
 | 
				
			|||||||
    #    blank = True, null = True,
 | 
					    #    blank = True, null = True,
 | 
				
			||||||
    #    help_text = _('use this input port'),
 | 
					    #    help_text = _('use this input port'),
 | 
				
			||||||
    # )
 | 
					    # )
 | 
				
			||||||
 | 
					    conflicts = models.ManyToManyField(
 | 
				
			||||||
 | 
					        'self',
 | 
				
			||||||
 | 
					        verbose_name = _('conflicts'),
 | 
				
			||||||
 | 
					        blank = True,
 | 
				
			||||||
 | 
					        help_text = _('conflicts'),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    start = models.DateTimeField( _('start of the diffusion') )
 | 
					    start = models.DateTimeField( _('start of the diffusion') )
 | 
				
			||||||
    end = models.DateTimeField( _('end of the diffusion') )
 | 
					    end = models.DateTimeField( _('end of the diffusion') )
 | 
				
			||||||
@ -891,22 +883,44 @@ class Diffusion(models.Model):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        Return a list of conflictual diffusions, based on the scheduled duration.
 | 
					        Return a list of conflictual diffusions, based on the scheduled duration.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        r = Diffusion.objects.filter(
 | 
					        return Diffusion.objects.filter(
 | 
				
			||||||
            models.Q(start__lt = self.start,
 | 
					            models.Q(start__lt = self.start,
 | 
				
			||||||
                     end__gt = self.start) |
 | 
					                     end__gt = self.start) |
 | 
				
			||||||
            models.Q(start__gt = self.start,
 | 
					            models.Q(start__gt = self.start,
 | 
				
			||||||
                     start__lt = self.end)
 | 
					                     start__lt = self.end)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return r
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, *args, **kwargs):
 | 
					    def check_conflicts(self):
 | 
				
			||||||
 | 
					        conflicts = self.get_conflicts()
 | 
				
			||||||
 | 
					        self.conflicts.set(conflicts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    __initial = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.__initial = {
 | 
				
			||||||
 | 
					            'start': self.start,
 | 
				
			||||||
 | 
					            'end': self.end,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save(self, no_check = False, *args, **kwargs):
 | 
				
			||||||
 | 
					        if no_check:
 | 
				
			||||||
 | 
					            return super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.initial:
 | 
					        if self.initial:
 | 
				
			||||||
            # force link to the top initial diffusion
 | 
					            # force link to the top initial diffusion
 | 
				
			||||||
            if self.initial.initial:
 | 
					            if self.initial.initial:
 | 
				
			||||||
                self.initial = self.initial.initial
 | 
					                self.initial = self.initial.initial
 | 
				
			||||||
            self.program = self.initial.program
 | 
					            self.program = self.initial.program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        super().save(*args, **kwargs)
 | 
					        super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.__initial:
 | 
				
			||||||
 | 
					            if self.start != self.__initial['start'] or \
 | 
				
			||||||
 | 
					                    self.end != self.__initial['end']:
 | 
				
			||||||
 | 
					                self.check_conflicts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return '{self.program.name} {date} #{self.pk}'.format(
 | 
					        return '{self.program.name} {date} #{self.pk}'.format(
 | 
				
			||||||
            self=self, date=self.date.strftime('%Y-%m-%d %H:%M')
 | 
					            self=self, date=self.date.strftime('%Y-%m-%d %H:%M')
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Register your models here.
 | 
					# Register your models here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -150,7 +150,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@-webkit-keyframes MenuAnimOut1 {
 | 
					@-webkit-keyframes MenuAnimOut1 {
 | 
				
			||||||
  50% {
 | 
					  50% {
 | 
				
			||||||
    -webkit-transform: translateZ(-250px) rotateY(30deg);
 | 
					    -webkit-transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  75% {
 | 
					  75% {
 | 
				
			||||||
    -webkit-transform: translateZ(-372.5px) rotateY(15deg);
 | 
					    -webkit-transform: translateZ(-372.5px) rotateY(15deg);
 | 
				
			||||||
@ -192,8 +192,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@keyframes MenuAnimOut1 {
 | 
					@keyframes MenuAnimOut1 {
 | 
				
			||||||
  50% {
 | 
					  50% {
 | 
				
			||||||
    -webkit-transform: translateZ(-250px) rotateY(30deg);
 | 
					    -webkit-transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
    transform: translateZ(-250px) rotateY(30deg);
 | 
					    transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  75% {
 | 
					  75% {
 | 
				
			||||||
    -webkit-transform: translateZ(-372.5px) rotateY(15deg);
 | 
					    -webkit-transform: translateZ(-372.5px) rotateY(15deg);
 | 
				
			||||||
@ -270,7 +270,7 @@
 | 
				
			|||||||
    opacity: 0;
 | 
					    opacity: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  20% {
 | 
					  20% {
 | 
				
			||||||
    -webkit-transform: translateZ(-250px) rotateY(30deg);
 | 
					    -webkit-transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  100% {
 | 
					  100% {
 | 
				
			||||||
@ -330,8 +330,8 @@
 | 
				
			|||||||
    opacity: 0;
 | 
					    opacity: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  20% {
 | 
					  20% {
 | 
				
			||||||
    -webkit-transform: translateZ(-250px) rotateY(30deg);
 | 
					    -webkit-transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
    transform: translateZ(-250px) rotateY(30deg);
 | 
					    transform: translateZ(-220px) rotateY(30deg);
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  100% {
 | 
					  100% {
 | 
				
			||||||
@ -1932,7 +1932,7 @@ body.ready .fade {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@media screen and (min-width: 50em) {
 | 
					@media screen and (min-width: 50em) {
 | 
				
			||||||
  .modal-dialog {
 | 
					  .modal-dialog {
 | 
				
			||||||
    padding: 0 0 2em 180px;
 | 
					    padding: 0 0 2em 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3846,7 +3846,7 @@ table.listing {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  .listing.images > li .image {
 | 
					  .listing.images > li .image {
 | 
				
			||||||
    text-align: center;
 | 
					    text-align: center;
 | 
				
			||||||
    height: 180px;
 | 
					    height: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .listing.images > li .image:before {
 | 
					  .listing.images > li .image:before {
 | 
				
			||||||
    content: '';
 | 
					    content: '';
 | 
				
			||||||
@ -4881,8 +4881,8 @@ body.ready .progress .bar {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.nav-wrapper {
 | 
					.nav-wrapper {
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  margin-left: -180px;
 | 
					  margin-left: -220px;
 | 
				
			||||||
  width: 180px;
 | 
					  width: 220px;
 | 
				
			||||||
  float: left;
 | 
					  float: left;
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
  min-height: 800px;
 | 
					  min-height: 800px;
 | 
				
			||||||
@ -5005,13 +5005,13 @@ body.ready .nav-main a {
 | 
				
			|||||||
  display: none;
 | 
					  display: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.nav-submenu .menu-item a {
 | 
					.nav-submenu .menu-item .info {
 | 
				
			||||||
  white-space: normal;
 | 
					  margin-right: 1em;
 | 
				
			||||||
  padding: 0.9em 1.7em 0.9em 4.5em;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.nav-submenu .menu-item a:before {
 | 
					.nav-submenu .menu-item a {
 | 
				
			||||||
  margin-left: -1.5em;
 | 
					  white-space: normal;
 | 
				
			||||||
 | 
					  padding: 0.9em 1em 0.9em 1em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.nav-submenu .menu-item a:hover {
 | 
					.nav-submenu .menu-item a:hover {
 | 
				
			||||||
@ -5106,8 +5106,8 @@ body.ready .nav-main a {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body.nav-open .wrapper {
 | 
					body.nav-open .wrapper {
 | 
				
			||||||
  transform: translate3d(180px, 0, 0);
 | 
					  transform: translate3d(220px, 0, 0);
 | 
				
			||||||
  -webkit-transform: translate3d(180px, 0, 0);
 | 
					  -webkit-transform: translate3d(220px, 0, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body.nav-open .content-wrapper {
 | 
					body.nav-open .content-wrapper {
 | 
				
			||||||
@ -5163,7 +5163,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
    -webkit-transform: none;
 | 
					    -webkit-transform: none;
 | 
				
			||||||
    -ms-transform: none;
 | 
					    -ms-transform: none;
 | 
				
			||||||
    transform: none;
 | 
					    transform: none;
 | 
				
			||||||
    padding-left: 180px;
 | 
					    padding-left: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-wrapper {
 | 
					  .nav-wrapper {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
@ -5174,7 +5174,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
  .nav-wrapper .inner {
 | 
					  .nav-wrapper .inner {
 | 
				
			||||||
    height: 100%;
 | 
					    height: 100%;
 | 
				
			||||||
    position: fixed;
 | 
					    position: fixed;
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-toggle {
 | 
					  .nav-toggle {
 | 
				
			||||||
    display: none;
 | 
					    display: none;
 | 
				
			||||||
@ -5186,7 +5186,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-main .footer {
 | 
					  .nav-main .footer {
 | 
				
			||||||
    position: fixed;
 | 
					    position: fixed;
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
    bottom: 0;
 | 
					    bottom: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-main .footer-open .footer-submenu {
 | 
					  .nav-main .footer-open .footer-submenu {
 | 
				
			||||||
@ -5256,14 +5256,14 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
    width: 0;
 | 
					    width: 0;
 | 
				
			||||||
    padding: 0;
 | 
					    padding: 0;
 | 
				
			||||||
    top: 0;
 | 
					    top: 0;
 | 
				
			||||||
    left: 180px;
 | 
					    left: 220px;
 | 
				
			||||||
    overflow: auto;
 | 
					    overflow: auto;
 | 
				
			||||||
    max-height: 100%;
 | 
					    max-height: 100%;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-submenu h2,
 | 
					  .nav-submenu h2,
 | 
				
			||||||
  .nav-submenu ul {
 | 
					  .nav-submenu ul {
 | 
				
			||||||
    float: right;
 | 
					    float: right;
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .nav-submenu h2 {
 | 
					  .nav-submenu h2 {
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
@ -5296,14 +5296,14 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  li.submenu-active .nav-submenu {
 | 
					  li.submenu-active .nav-submenu {
 | 
				
			||||||
    box-shadow: 2px 0 2px rgba(0, 0, 0, 0.35);
 | 
					    box-shadow: 2px 0 2px rgba(0, 0, 0, 0.35);
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
    padding: 0 0 1.5em;
 | 
					    padding: 0 0 0.5em;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  body.ready li.submenu-active .nav-submenu {
 | 
					  body.ready li.submenu-active .nav-submenu {
 | 
				
			||||||
    transition: width 0.2s ease;
 | 
					    transition: width 0.2s ease;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  li.submenu-active .nav-submenu a {
 | 
					  li.submenu-active .nav-submenu a {
 | 
				
			||||||
    padding-left: 3.5em;
 | 
					    padding-left: 1em;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .explorer {
 | 
					  .explorer {
 | 
				
			||||||
    width: 400px;
 | 
					    width: 400px;
 | 
				
			||||||
@ -5325,7 +5325,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  body.explorer-open .nav-wrapper {
 | 
					  body.explorer-open .nav-wrapper {
 | 
				
			||||||
    margin-left: 0;
 | 
					    margin-left: 0;
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  body.explorer-open .explorer:before {
 | 
					  body.explorer-open .explorer:before {
 | 
				
			||||||
    display: none;
 | 
					    display: none;
 | 
				
			||||||
@ -5356,7 +5356,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
    -webkit-transform: none;
 | 
					    -webkit-transform: none;
 | 
				
			||||||
    -ms-transform: none;
 | 
					    -ms-transform: none;
 | 
				
			||||||
    transform: none;
 | 
					    transform: none;
 | 
				
			||||||
    left: 180px;
 | 
					    left: 220px;
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  body.explorer-open .wrapper {
 | 
					  body.explorer-open .wrapper {
 | 
				
			||||||
@ -5375,7 +5375,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
    left: 0;
 | 
					    left: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  body.explorer-open .nav-wrapper {
 | 
					  body.explorer-open .nav-wrapper {
 | 
				
			||||||
    width: 180px;
 | 
					    width: 220px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5603,7 +5603,7 @@ body.explorer-open .explorer-close {
 | 
				
			|||||||
  position: absolute;
 | 
					  position: absolute;
 | 
				
			||||||
  z-index: 25;
 | 
					  z-index: 25;
 | 
				
			||||||
  top: 0;
 | 
					  top: 0;
 | 
				
			||||||
  left: 180px;
 | 
					  left: 220px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#wagtail .c-state-indicator {
 | 
					#wagtail .c-state-indicator {
 | 
				
			||||||
@ -5811,7 +5811,7 @@ footer li {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
footer .actions {
 | 
					footer .actions {
 | 
				
			||||||
  width: 250px;
 | 
					  width: 220px;
 | 
				
			||||||
  margin-right: 1.5%;
 | 
					  margin-right: 1.5%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@
 | 
				
			|||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% endwith %}
 | 
					{% endwith %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if diffusion.diffusion_set.count %}
 | 
				
			||||||
<section class="dates">
 | 
					<section class="dates">
 | 
				
			||||||
    <h2>{% trans "Dates of diffusion" %}</h2>
 | 
					    <h2>{% trans "Dates of diffusion" %}</h2>
 | 
				
			||||||
    <ul>
 | 
					    <ul>
 | 
				
			||||||
@ -29,6 +30,7 @@
 | 
				
			|||||||
        {% endwith %}
 | 
					        {% endwith %}
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
</section>
 | 
					</section>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% with podcasts=self.get_podcasts %}
 | 
					{% with podcasts=self.get_podcasts %}
 | 
				
			||||||
{% if podcasts %}
 | 
					{% if podcasts %}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{% block content_extras %}
 | 
					{% block content_extras %}
 | 
				
			||||||
<section class="schedule">
 | 
					<section class="schedule">
 | 
				
			||||||
{% if page.program.active %}
 | 
					{% if page.program.active and page.program.schedule_set.count %}
 | 
				
			||||||
    <h2>{% trans "Schedule" %}</h2>
 | 
					    <h2>{% trans "Schedule" %}</h2>
 | 
				
			||||||
    <ul>
 | 
					    <ul>
 | 
				
			||||||
        {% for schedule in page.program.schedule_set.all %}
 | 
					        {% for schedule in page.program.schedule_set.all %}
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@ class DiffusionAdmin(ModelAdmin):
 | 
				
			|||||||
    menu_order = 200
 | 
					    menu_order = 200
 | 
				
			||||||
    list_display = ('program', 'start', 'end', 'type', 'initial')
 | 
					    list_display = ('program', 'start', 'end', 'type', 'initial')
 | 
				
			||||||
    list_filter = ('program', 'start', 'type')
 | 
					    list_filter = ('program', 'start', 'type')
 | 
				
			||||||
 | 
					    readonly_fields = ('conflicts',)
 | 
				
			||||||
    search_fields = ('program__name', 'start')
 | 
					    search_fields = ('program__name', 'start')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ScheduleAdmin(ModelAdmin):
 | 
					class ScheduleAdmin(ModelAdmin):
 | 
				
			||||||
@ -99,12 +100,21 @@ class GenericMenu(Menu):
 | 
				
			|||||||
        super().__init__('')
 | 
					        super().__init__('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_queryset(self):
 | 
					    def get_queryset(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return a queryset of items used to display menu
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_title(self, item):
 | 
					    def get_title(self, item):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return the title of a menu-item for the given item
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_parent(self, item):
 | 
					    def get_parent(self, item):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return id of the parent page for the given item
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_page_url(self, page_model, item):
 | 
					    def get_page_url(self, page_model, item):
 | 
				
			||||||
@ -150,7 +160,12 @@ class DiffusionsMenu(GenericMenu):
 | 
				
			|||||||
        ).order_by('start')
 | 
					        ).order_by('start')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_title(self, item):
 | 
					    def get_title(self, item):
 | 
				
			||||||
        return item.program.name
 | 
					        from django.utils.safestring import mark_safe
 | 
				
			||||||
 | 
					        title = '<i class="info">{}</i> {}'.format(
 | 
				
			||||||
 | 
					            item.start.strftime('%H:%M'),
 | 
				
			||||||
 | 
					            item.program.name
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return mark_safe(title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_parent(self, item):
 | 
					    def get_parent(self, item):
 | 
				
			||||||
        return item.program.page.first()
 | 
					        return item.program.page.first()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								notes.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								notes.md
									
									
									
									
									
								
							@ -1,6 +1,21 @@
 | 
				
			|||||||
This file is used as a reminder, can be used as crappy documentation too.
 | 
					This file is used as a reminder, can be used as crappy documentation too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# for the 1.0
 | 
				
			||||||
 | 
					- sounds:
 | 
				
			||||||
 | 
					    - detect id3 tags
 | 
				
			||||||
 | 
					- run tests:
 | 
				
			||||||
 | 
					    - streamer: dealer & streams hours (to localtime)
 | 
				
			||||||
 | 
					    x diffusions: update & check algorithms
 | 
				
			||||||
 | 
					    x check in templates
 | 
				
			||||||
 | 
					    x diffusion page date info
 | 
				
			||||||
 | 
					- streamer:
 | 
				
			||||||
 | 
					    - restart running streamer on demand
 | 
				
			||||||
 | 
					    - add restart button for the streamer
 | 
				
			||||||
 | 
					- cms:
 | 
				
			||||||
 | 
					    - button to select the current station
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# conventions
 | 
					# conventions
 | 
				
			||||||
## coding style
 | 
					## coding style
 | 
				
			||||||
* name of classes relative to a class:
 | 
					* name of classes relative to a class:
 | 
				
			||||||
@ -40,11 +55,6 @@ cms:
 | 
				
			|||||||
    - comments -> remove/edit by the author
 | 
					    - comments -> remove/edit by the author
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Timezone shit:
 | 
					# Timezone shit:
 | 
				
			||||||
- run tests:
 | 
					 | 
				
			||||||
    - streamer: dealer & streams hours (to localtime)
 | 
					 | 
				
			||||||
    - diffusions: update & check algorithms
 | 
					 | 
				
			||||||
    x check in templates
 | 
					 | 
				
			||||||
    x diffusion page date info
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Instance's TODO
 | 
					# Instance's TODO
 | 
				
			||||||
- menu_top .sections:
 | 
					- menu_top .sections:
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user