]> git.0d.be Git - django-panik-combo.git/commitdiff
add introduction to fullwidth page placeholders main
authorFrédéric Péters <fpeters@0d.be>
Thu, 26 Oct 2023 08:06:43 +0000 (10:06 +0200)
committerFrédéric Péters <fpeters@0d.be>
Thu, 26 Oct 2023 08:06:43 +0000 (10:06 +0200)
53 files changed:
.git-blame-ignore-revs [new file with mode: 0644]
.pre-commit-config.yaml [new file with mode: 0644]
MANIFEST.in
debian/compat [deleted file]
debian/control
debian/source/format [new file with mode: 0644]
panikombo/forms.py
panikombo/management/commands/map-item-topik.py
panikombo/migrations/0001_initial.py
panikombo/migrations/0002_episodecell.py
panikombo/migrations/0003_episodeautoselectioncell.py
panikombo/migrations/0004_newsitemautoselectioncell.py
panikombo/migrations/0005_topik.py
panikombo/migrations/0006_itemtopik.py
panikombo/migrations/0007_newsitemautoselectioncell_category.py
panikombo/migrations/0008_topikcell.py
panikombo/migrations/0009_episodeautoselectioncell_period.py
panikombo/migrations/0010_auto_20160220_1153.py
panikombo/migrations/0011_auto_20170418_1154.py
panikombo/migrations/0012_auto_20171015_1027.py
panikombo/migrations/0013_auto_20200611_1121.py
panikombo/migrations/0014_remove_itemtopik_topik.py
panikombo/migrations/0015_auto_20200611_1250.py
panikombo/migrations/0016_soundscell.py [new file with mode: 0644]
panikombo/migrations/0017_soundscell_title.py [new file with mode: 0644]
panikombo/migrations/0018_soundscell_sort_order.py [new file with mode: 0644]
panikombo/migrations/0019_soundscell_sound_format.py [new file with mode: 0644]
panikombo/migrations/0020_auto_20201122_2005.py [new file with mode: 0644]
panikombo/migrations/0021_soundscell_tags.py [new file with mode: 0644]
panikombo/migrations/0022_auto_20210326_1324.py [new file with mode: 0644]
panikombo/migrations/0023_auto_20210818_0906.py [new file with mode: 0644]
panikombo/migrations/0024_auto_20210818_1158.py [new file with mode: 0644]
panikombo/migrations/0025_auto_20220714_0830.py [new file with mode: 0644]
panikombo/migrations/0026_auto_20230725_1711.py [new file with mode: 0644]
panikombo/migrations/0027_weekprogramcell.py [new file with mode: 0644]
panikombo/migrations/0028_weekprogramcell_include_nonstop.py [new file with mode: 0644]
panikombo/migrations/0029_focuscarrouselcell.py [new file with mode: 0644]
panikombo/migrations/0030_emissionscell.py [new file with mode: 0644]
panikombo/migrations/0031_auto_20230902_1801.py [new file with mode: 0644]
panikombo/misc.py
panikombo/models.py
panikombo/templates/panikombo/audio.html [new file with mode: 0644]
panikombo/templates/panikombo/emissions.html [new file with mode: 0644]
panikombo/templates/panikombo/episode.html [new file with mode: 0644]
panikombo/templates/panikombo/episode_auto_selection.html [new file with mode: 0644]
panikombo/templates/panikombo/episodeautoselectioncell_form.html [new file with mode: 0644]
panikombo/templates/panikombo/focus_carrousel.html [new file with mode: 0644]
panikombo/templates/panikombo/newsitem_auto_selection.html [new file with mode: 0644]
panikombo/templates/panikombo/select2.html [new file with mode: 0644]
panikombo/templates/panikombo/week_program.html [new file with mode: 0644]
panikombo/urls.py [new file with mode: 0644]
panikombo/views.py
setup.py

diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644 (file)
index 0000000..ae5db9a
--- /dev/null
@@ -0,0 +1,2 @@
+# trivial: apply black
+f89a5d9eaa646c846c9f464a0ab9c6ae262fdb19
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644 (file)
index 0000000..5f6e56d
--- /dev/null
@@ -0,0 +1,28 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+  - repo: https://github.com/asottile/pyupgrade
+    rev: v3.3.1
+    hooks:
+      - id: pyupgrade
+        args: ['--keep-percent-format', '--py39-plus']
+  - repo: https://github.com/adamchainz/django-upgrade
+    rev: 1.10.0
+    hooks:
+      - id: django-upgrade
+        args: [--target-version, "3.2"]
+  - repo: https://github.com/psf/black
+    rev: 23.1.0
+    hooks:
+      - id: black
+        args: ['--target-version', 'py39', '--skip-string-normalization', '--line-length', '110']
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.12.0
+    hooks:
+      - id: isort
+        args: ['--profile', 'black', '--line-length', '110']
+  - repo: https://github.com/rtts/djhtml
+    rev: '3.0.5'
+    hooks:
+      - id: djhtml
+        args: ['--tabwidth', '2']
index 37eb2a0cf1a7f0f29265a420b92a571556fce748..009e33b5a57bd7b2cc2edd06a9db9428eaaa4bb5 100644 (file)
@@ -2,6 +2,7 @@ include AUTHORS
 include COPYING
 include README
 include MANIFEST.in
+include VERSION
 
 recursive-include panikombo/static *.js
 recursive-include panikombo/templates *.html
diff --git a/debian/compat b/debian/compat
deleted file mode 100644 (file)
index f599e28..0000000
+++ /dev/null
@@ -1 +0,0 @@
-10
index cc821a71399a20743668226801ac21691165770a..e19d59be2143e0a28617e7a86e7ce52a267b681f 100644 (file)
@@ -2,7 +2,7 @@ Source: django-panik-combo
 Section: python
 Priority: optional
 Maintainer: Frederic Peters <fred@radiopanik.org>
-Build-Depends: debhelper (>= 10),
+Build-Depends: debhelper-compat (= 12),
                python3-all,
                python3-django,
                python3-setuptools,
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
index d51d1ce4f486f3defc25e55ad5d8fa42abdb4ece..cb2d5f549e454119c6711b592a7d96f4b6ab8862 100644 (file)
@@ -1,24 +1,35 @@
-import json
-
 from django import forms
-from django_select2.forms import HeavySelect2Widget
+from django.forms.widgets import Widget
+from emissions.models import Episode, SoundFile
 from taggit.forms import TagWidget
 
-from emissions.models import SoundFile, Episode
+from .models import EpisodeAutoSelectionCell, EpisodeCell, NewsItemAutoSelectionCell, SoundCell
+
+
+class BaseSelect2Widget(Widget):
+    template_name = "panikombo/select2.html"
 
-from .models import (SoundCell, EpisodeCell, EpisodeAutoSelectionCell,
-        NewsItemAutoSelectionCell)
-from .views import soundfiles, episodes
+    def get_context(self, name, value, attrs):
+        context = super().get_context(name, value, attrs)
+        context['view_name'] = self.view_name
+        if value:
+            context['widget']['view_value'] = self.view_value(value)
+        return context
 
-class SoundFileWidget(HeavySelect2Widget):
-    def render_texts(self, selected_choices, choices):
-        queryset = SoundFile.objects.filter(id__in=selected_choices)
-        def fmt(soundfile):
-            return '%s - %s - %s' % (soundfile.episode.emission.title,
-                    soundfile.episode.title,
-                    soundfile.title or soundfile.id)
-        texts = [fmt(soundfile) for soundfile in queryset.select_related()]
-        return json.dumps(texts)
+
+class SoundFileWidget(BaseSelect2Widget):
+    view_name = 'panikombo-select2-soundfiles'
+
+    def view_value(self, value):
+        try:
+            soundfile = SoundFile.objects.get(id=value)
+        except SoundFile.DoesNotExist:
+            return 'missing sound %s' % value
+        return '%s - %s - %s' % (
+            soundfile.episode.emission.title,
+            soundfile.episode.title,
+            soundfile.title or soundfile.id,
+        )
 
 
 class SoundCellForm(forms.ModelForm):
@@ -27,27 +38,29 @@ class SoundCellForm(forms.ModelForm):
         fields = ('soundfile',)
 
     def __init__(self, *args, **kwargs):
-        super(SoundCellForm, self).__init__(*args, **kwargs)
-        self.fields['soundfile'].widget = SoundFileWidget(data_view=soundfiles)
+        super().__init__(*args, **kwargs)
+        self.fields['soundfile'].widget = SoundFileWidget()
+
 
+class EpisodeWidget(BaseSelect2Widget):
+    view_name = 'panikombo-select2-episodes'
 
-class EpisodeWidget(HeavySelect2Widget):
-    def render_texts(self, selected_choices, choices):
-        queryset = Episode.objects.filter(id__in=selected_choices)
-        def fmt(episode):
-            return '%s - %s' % (episode.emission.title, episode.title)
-        texts = [fmt(episode) for episode in queryset.select_related()]
-        return json.dumps(texts)
+    def view_value(self, value):
+        try:
+            episode = Episode.objects.get(id=value)
+        except Episode.DoesNotExist:
+            return 'missing episode %s' % value
+        return '%s - %s' % (episode.emission.title, episode.title)
 
 
 class EpisodeCellForm(forms.ModelForm):
     class Meta:
         model = EpisodeCell
-        fields = ('episode', )
+        fields = ('episode',)
 
     def __init__(self, *args, **kwargs):
-        super(EpisodeCellForm, self).__init__(*args, **kwargs)
-        self.fields['episode'].widget = EpisodeWidget(data_view=episodes)
+        super().__init__(*args, **kwargs)
+        self.fields['episode'].widget = EpisodeWidget()
 
 
 class EpisodeAutoSelectionCellForm(forms.ModelForm):
@@ -60,5 +73,5 @@ class EpisodeAutoSelectionCellForm(forms.ModelForm):
 class NewsItemAutoSelectionCellForm(forms.ModelForm):
     class Meta:
         model = NewsItemAutoSelectionCell
-        fields = ('title', 'tags', 'and_tags', 'category', 'future')
+        fields = ('tags', 'and_tags', 'category', 'future', 'count')
         widgets = {'tags': TagWidget()}
index 61b765cce520588914945adf3c24c3ecc3bd029a..56bfc019f825c270f767f619d4066b119fb09ece 100644 (file)
@@ -1,8 +1,7 @@
+from combo.data.models import CellBase, Page
 from django.core.management.base import BaseCommand, CommandError
+from emissions.models import Episode, NewsItem
 
-from emissions.models import NewsItem, Episode
-
-from combo.data.models import Page, CellBase
 from panikombo.models import ItemTopik
 
 
index fef818b796907f4de1dc99f002359cba16fb845e..ee317b1acd859d54ecfa054cb75d3d95be46f5e6 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('auth', '0001_initial'),
         ('emissions', '0001_initial'),
@@ -16,14 +12,20 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='SoundCell',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('placeholder', models.CharField(max_length=20)),
                 ('order', models.PositiveIntegerField()),
                 ('slug', models.SlugField(verbose_name='Slug', blank=True)),
                 ('public', models.BooleanField(default=True, verbose_name='Public')),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
-                ('page', models.ForeignKey(to='data.Page')),
-                ('soundfile', models.ForeignKey(to='emissions.SoundFile', null=True)),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+                (
+                    'soundfile',
+                    models.ForeignKey(to='emissions.SoundFile', null=True, on_delete=models.SET_NULL),
+                ),
             ],
             options={
                 'verbose_name': 'Sound',
index 712f20bee1f4a141927cef2807e44eb9fd073e14..afd7709de4a6e33d437606209546d821d2f35e5c 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('auth', '0001_initial'),
         ('emissions', '0003_newsitem_event_date'),
@@ -17,14 +13,17 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='EpisodeCell',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('placeholder', models.CharField(max_length=20)),
                 ('order', models.PositiveIntegerField()),
                 ('slug', models.SlugField(verbose_name='Slug', blank=True)),
                 ('public', models.BooleanField(default=True, verbose_name='Public')),
-                ('episode', models.ForeignKey(to='emissions.Episode', null=True)),
+                ('episode', models.ForeignKey(to='emissions.Episode', null=True, on_delete=models.SET_NULL)),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
-                ('page', models.ForeignKey(to='data.Page')),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
             ],
             options={
                 'verbose_name': 'Episode',
index 70663a78a96de648766a7168bd1d4bc5d0b7536e..185ff72464d0b01458abbc2a0a82c7b3d994eeda 100644 (file)
@@ -1,12 +1,8 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
 import taggit.managers
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('auth', '0001_initial'),
         ('data', '0005_auto_20150226_0903'),
@@ -19,16 +15,33 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='EpisodeAutoSelectionCell',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('placeholder', models.CharField(max_length=20)),
                 ('order', models.PositiveIntegerField()),
                 ('slug', models.SlugField(verbose_name='Slug', blank=True)),
                 ('public', models.BooleanField(default=True, verbose_name='Public')),
                 ('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
-                ('category', models.ForeignKey(blank=True, to='emissions.Category', null=True)),
+                (
+                    'category',
+                    models.ForeignKey(
+                        blank=True, to='emissions.Category', null=True, on_delete=models.SET_NULL
+                    ),
+                ),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
-                ('page', models.ForeignKey(to='data.Page')),
-                ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+                (
+                    'tags',
+                    taggit.managers.TaggableManager(
+                        to='taggit.Tag',
+                        through='taggit.TaggedItem',
+                        blank=True,
+                        help_text='A comma-separated list of tags.',
+                        verbose_name='Tags',
+                    ),
+                ),
             ],
             options={
                 'verbose_name': 'Automatic Episode Selection',
index f8efc3beabae0f466905fe84f6133d4929bae156..d6fb2f691a2d1a7462440713a40a6f919723ce61 100644 (file)
@@ -1,12 +1,8 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
 import taggit.managers
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('auth', '0001_initial'),
         ('data', '0005_auto_20150226_0903'),
@@ -18,7 +14,10 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='NewsItemAutoSelectionCell',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('placeholder', models.CharField(max_length=20)),
                 ('order', models.PositiveIntegerField()),
                 ('slug', models.SlugField(verbose_name='Slug', blank=True)),
@@ -26,8 +25,17 @@ class Migration(migrations.Migration):
                 ('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
                 ('future', models.BooleanField(default=True, verbose_name='Future Events Only')),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
-                ('page', models.ForeignKey(to='data.Page')),
-                ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+                (
+                    'tags',
+                    taggit.managers.TaggableManager(
+                        to='taggit.Tag',
+                        through='taggit.TaggedItem',
+                        blank=True,
+                        help_text='A comma-separated list of tags.',
+                        verbose_name='Tags',
+                    ),
+                ),
             ],
             options={
                 'verbose_name': 'Automatic Newsitem Selection',
index d2e339bfa71b560f3f6fa2a7ff4484295669e264..6560a84b22513ea9cded61589b754d82c62c3e7f 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('data', '0005_auto_20150226_0903'),
         ('panikombo', '0004_newsitemautoselectioncell'),
@@ -15,14 +11,16 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Topik',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('image', models.ImageField(max_length=250, null=True, verbose_name='Image', blank=True)),
                 ('got_focus', models.DateTimeField(default=None, null=True, blank=True)),
                 ('has_focus', models.BooleanField(default=False)),
-                ('page', models.ForeignKey(to='data.Page')),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.CASCADE)),
             ],
-            options={
-            },
+            options={},
             bases=(models.Model,),
         ),
     ]
index 69db3e104fc1f05857ab3e599f88a794ec0e8b65..ce738f607582b56c9650e31126e8875a6efc22ea 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('emissions', '0004_focus_page'),
         ('panikombo', '0005_topik'),
@@ -15,13 +11,42 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='ItemTopik',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('episode', models.ForeignKey(verbose_name='Episode', blank=True, to='emissions.Episode', null=True)),
-                ('newsitem', models.ForeignKey(verbose_name='News Item', blank=True, to='emissions.NewsItem', null=True)),
-                ('topik', models.ForeignKey(verbose_name=b'Topik', blank=True, to='panikombo.Topik', null=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
+                (
+                    'episode',
+                    models.ForeignKey(
+                        verbose_name='Episode',
+                        blank=True,
+                        to='emissions.Episode',
+                        null=True,
+                        on_delete=models.SET_NULL,
+                    ),
+                ),
+                (
+                    'newsitem',
+                    models.ForeignKey(
+                        verbose_name='News Item',
+                        blank=True,
+                        to='emissions.NewsItem',
+                        null=True,
+                        on_delete=models.SET_NULL,
+                    ),
+                ),
+                (
+                    'topik',
+                    models.ForeignKey(
+                        verbose_name=b'Topik',
+                        blank=True,
+                        to='panikombo.Topik',
+                        null=True,
+                        on_delete=models.SET_NULL,
+                    ),
+                ),
             ],
-            options={
-            },
+            options={},
             bases=(models.Model,),
         ),
     ]
index 99db4c7b0fd887cff59df535a31733303b81cd64..834289fd08f56d5855bd3cad1e952966bb182cdd 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('emissions', '0004_focus_page'),
         ('panikombo', '0006_itemtopik'),
@@ -15,7 +11,13 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='newsitemautoselectioncell',
             name='category',
-            field=models.ForeignKey(verbose_name='Category', blank=True, to='emissions.NewsCategory', null=True),
+            field=models.ForeignKey(
+                verbose_name='Category',
+                blank=True,
+                to='emissions.NewsCategory',
+                null=True,
+                on_delete=models.SET_NULL,
+            ),
             preserve_default=True,
         ),
     ]
index e117285c1bcf26de21eda45b946eaaad2a66756f..79ba8c025f766daad90e66ff92a0bc66273df9be 100644 (file)
@@ -1,12 +1,8 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
 import ckeditor.fields
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('auth', '0001_initial'),
         ('data', '0009_auto_20150529_2247'),
@@ -17,15 +13,18 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='TopikCell',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('placeholder', models.CharField(max_length=20)),
                 ('order', models.PositiveIntegerField()),
                 ('slug', models.SlugField(verbose_name='Slug', blank=True)),
                 ('public', models.BooleanField(default=True, verbose_name='Public')),
                 ('text', ckeditor.fields.RichTextField(null=True, verbose_name='Text', blank=True)),
                 ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
-                ('page', models.ForeignKey(to='data.Page')),
-                ('topik', models.ForeignKey(to='panikombo.Topik', null=True)),
+                ('page', models.ForeignKey(to='data.Page', on_delete=models.SET_NULL)),
+                ('topik', models.ForeignKey(to='panikombo.Topik', null=True, on_delete=models.SET_NULL)),
             ],
             options={
                 'verbose_name': 'Topik',
index fdd0c87e0210be658a90c144a017006ed6af7c60..4cfa1b5065646800649628e670b51399b057274d 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0008_topikcell'),
     ]
@@ -14,7 +10,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='episodeautoselectioncell',
             name='period',
-            field=models.PositiveSmallIntegerField(default=0, verbose_name='Period', choices=[(0, 'All'), (1, 'Future'), (2, 'Past')]),
+            field=models.PositiveSmallIntegerField(
+                default=0, verbose_name='Period', choices=[(0, 'All'), (1, 'Future'), (2, 'Past')]
+            ),
             preserve_default=True,
         ),
     ]
index ce0e183c32b3f7d1eadceb4d729d214649c9f4a0..d20369d211d3cfd1fb0935cc30e0775dd08f64fd 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0009_episodeautoselectioncell_period'),
     ]
index a77b781e97c3f8d0eaa338d92e04deea6dd39bb6..2763738b53390996f279192f93732c73395cb5dd 100644 (file)
@@ -1,12 +1,9 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
+import datetime
 
 from django.db import migrations, models
-import datetime
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0010_auto_20160220_1153'),
     ]
@@ -20,7 +17,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='episodeautoselectioncell',
             name='last_update_timestamp',
-            field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 35, 51768), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 4, 18, 11, 54, 35, 51768), auto_now=True
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
@@ -31,7 +30,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='episodecell',
             name='last_update_timestamp',
-            field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 36, 700929), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 4, 18, 11, 54, 36, 700929), auto_now=True
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
@@ -42,7 +43,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='newsitemautoselectioncell',
             name='last_update_timestamp',
-            field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 39, 362967), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 4, 18, 11, 54, 39, 362967), auto_now=True
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
@@ -53,7 +56,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='soundcell',
             name='last_update_timestamp',
-            field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 42, 662255), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 4, 18, 11, 54, 42, 662255), auto_now=True
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
@@ -64,7 +69,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='topikcell',
             name='last_update_timestamp',
-            field=models.DateTimeField(default=datetime.datetime(2017, 4, 18, 11, 54, 44, 42144), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 4, 18, 11, 54, 44, 42144), auto_now=True
+            ),
             preserve_default=False,
         ),
     ]
index 73beee0bae8fdb427189c010da8ec558b4ebc5da..207adaef54ba95a1a31d40c6daee72a9efc7903e 100644 (file)
@@ -1,11 +1,7 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
 from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0011_auto_20170418_1154'),
     ]
index 384a5d2ad0162a47b85478c2de5706c57db6b697..1cf6dbb512e3114b6e319080c24e15813b59fbb3 100644 (file)
@@ -1,13 +1,10 @@
-# -*- coding: utf-8 -*-
 # Generated by Django 1.11.29 on 2020-06-11 11:21
-from __future__ import unicode_literals
 
-from django.db import migrations, models
 import django.db.models.deletion
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('data', '0009_auto_20150529_2247'),
         ('panikombo', '0012_auto_20171015_1027'),
@@ -17,11 +14,19 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='itemtopik',
             name='page',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+            field=models.ForeignKey(
+                blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='data.Page'
+            ),
         ),
         migrations.AlterField(
             model_name='itemtopik',
             name='topik',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='panikombo.Topik', verbose_name='Topik'),
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                to='panikombo.Topik',
+                verbose_name='Topik',
+            ),
         ),
     ]
index 2ea584389e8331ec8feeec46341b9564425365f4..4d025d5ff9fad526dc4f975119d6587836480737 100644 (file)
@@ -1,12 +1,9 @@
-# -*- coding: utf-8 -*-
 # Generated by Django 1.11.29 on 2020-06-11 11:26
-from __future__ import unicode_literals
 
 from django.db import migrations
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0013_auto_20200611_1121'),
     ]
index dbbdb141c35bcbf4a6e95d319cb161eee3c6adcc..3ddd807b197bcf5f7ba17d1f3957d40956afee09 100644 (file)
@@ -1,12 +1,9 @@
-# -*- coding: utf-8 -*-
 # Generated by Django 1.11.29 on 2020-06-11 12:50
-from __future__ import unicode_literals
 
 from django.db import migrations
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
         ('panikombo', '0014_remove_itemtopik_topik'),
     ]
diff --git a/panikombo/migrations/0016_soundscell.py b/panikombo/migrations/0016_soundscell.py
new file mode 100644 (file)
index 0000000..85a02fe
--- /dev/null
@@ -0,0 +1,53 @@
+# Generated by Django 1.11.29 on 2020-11-21 12:40
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('auth', '0008_alter_user_username_max_length'),
+        ('panikombo', '0015_auto_20200611_1250'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='SoundsCell',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('placeholder', models.CharField(max_length=20)),
+                ('order', models.PositiveIntegerField()),
+                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+                (
+                    'extra_css_class',
+                    models.CharField(
+                        blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+                    ),
+                ),
+                ('public', models.BooleanField(default=True, verbose_name='Public')),
+                (
+                    'restricted_to_unlogged',
+                    models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+                ),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                (
+                    'include_search_input',
+                    models.BooleanField(default=True, verbose_name='Include search input'),
+                ),
+                ('include_fragments', models.BooleanField(default=True, verbose_name='Include fragments')),
+                (
+                    'limit_to_focus',
+                    models.BooleanField(default=False, verbose_name='Limit to focused elements'),
+                ),
+                ('count', models.PositiveSmallIntegerField(default=20, verbose_name='Count')),
+                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
+                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page')),
+            ],
+            options={
+                'verbose_name': 'Sounds',
+            },
+        ),
+    ]
diff --git a/panikombo/migrations/0017_soundscell_title.py b/panikombo/migrations/0017_soundscell_title.py
new file mode 100644 (file)
index 0000000..43234f6
--- /dev/null
@@ -0,0 +1,17 @@
+# Generated by Django 1.11.29 on 2020-11-21 14:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0016_soundscell'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='soundscell',
+            name='title',
+            field=models.CharField(blank=True, max_length=150, verbose_name='Title'),
+        ),
+    ]
diff --git a/panikombo/migrations/0018_soundscell_sort_order.py b/panikombo/migrations/0018_soundscell_sort_order.py
new file mode 100644 (file)
index 0000000..04c86b0
--- /dev/null
@@ -0,0 +1,28 @@
+# Generated by Django 1.11.29 on 2020-11-21 20:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0017_soundscell_title'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='soundscell',
+            name='sort_order',
+            field=models.CharField(
+                choices=[
+                    ('-creation_timestamp', 'Reverse chronological (creation)'),
+                    ('-first_diffusion', 'Reverse chronological (diffusion)'),
+                    ('creation_timestamp', 'Chronological (creation)'),
+                    ('first_diffusion', 'Chronological (diffusion)'),
+                    ('?', 'Random'),
+                ],
+                default='-creation_timestamp',
+                max_length=30,
+                verbose_name='Sort order',
+            ),
+        ),
+    ]
diff --git a/panikombo/migrations/0019_soundscell_sound_format.py b/panikombo/migrations/0019_soundscell_sound_format.py
new file mode 100644 (file)
index 0000000..0f3205f
--- /dev/null
@@ -0,0 +1,25 @@
+# Generated by Django 1.11.29 on 2020-11-22 14:02
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('emissions', '0015_auto_20200404_1510'),
+        ('panikombo', '0018_soundscell_sort_order'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='soundscell',
+            name='sound_format',
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                to='emissions.Format',
+                verbose_name='Limit to format',
+            ),
+        ),
+    ]
diff --git a/panikombo/migrations/0020_auto_20201122_2005.py b/panikombo/migrations/0020_auto_20201122_2005.py
new file mode 100644 (file)
index 0000000..b52f926
--- /dev/null
@@ -0,0 +1,26 @@
+# Generated by Django 1.11.29 on 2020-11-22 20:05
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0019_soundscell_sound_format'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='soundscell',
+            name='maximal_duration',
+            field=models.PositiveIntegerField(
+                blank=True, default=None, null=True, verbose_name='Maximal duration (in minutes)'
+            ),
+        ),
+        migrations.AddField(
+            model_name='soundscell',
+            name='minimal_duration',
+            field=models.PositiveIntegerField(
+                blank=True, default=None, null=True, verbose_name='Minimal duration (in minutes)'
+            ),
+        ),
+    ]
diff --git a/panikombo/migrations/0021_soundscell_tags.py b/panikombo/migrations/0021_soundscell_tags.py
new file mode 100644 (file)
index 0000000..d6777ff
--- /dev/null
@@ -0,0 +1,24 @@
+# Generated by Django 1.11.29 on 2020-11-26 12:52
+
+import taggit.managers
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0020_auto_20201122_2005'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='soundscell',
+            name='tags',
+            field=taggit.managers.TaggableManager(
+                blank=True,
+                help_text='A comma-separated list of tags.',
+                through='taggit.TaggedItem',
+                to='taggit.Tag',
+                verbose_name='Tags',
+            ),
+        ),
+    ]
diff --git a/panikombo/migrations/0022_auto_20210326_1324.py b/panikombo/migrations/0022_auto_20210326_1324.py
new file mode 100644 (file)
index 0000000..1aa6f54
--- /dev/null
@@ -0,0 +1,61 @@
+# Generated by Django 2.2.19 on 2021-03-26 13:24
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0021_soundscell_tags'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='episodeautoselectioncell',
+            name='category',
+            field=models.ForeignKey(
+                blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.Category'
+            ),
+        ),
+        migrations.AlterField(
+            model_name='episodeautoselectioncell',
+            name='page',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+        ),
+        migrations.AlterField(
+            model_name='episodecell',
+            name='episode',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.Episode'
+            ),
+        ),
+        migrations.AlterField(
+            model_name='episodecell',
+            name='page',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+        ),
+        migrations.AlterField(
+            model_name='itemtopik',
+            name='page',
+            field=models.ForeignKey(
+                blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='data.Page'
+            ),
+        ),
+        migrations.AlterField(
+            model_name='newsitemautoselectioncell',
+            name='page',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+        ),
+        migrations.AlterField(
+            model_name='soundcell',
+            name='page',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page'),
+        ),
+        migrations.AlterField(
+            model_name='soundcell',
+            name='soundfile',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.CASCADE, to='emissions.SoundFile'
+            ),
+        ),
+    ]
diff --git a/panikombo/migrations/0023_auto_20210818_0906.py b/panikombo/migrations/0023_auto_20210818_0906.py
new file mode 100644 (file)
index 0000000..8f1711f
--- /dev/null
@@ -0,0 +1,27 @@
+# Generated by Django 2.2.19 on 2021-08-18 09:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0022_auto_20210326_1324'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='episodecell',
+            name='template_name',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+        ),
+        migrations.AddField(
+            model_name='soundcell',
+            name='template_name',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+        ),
+        migrations.AddField(
+            model_name='soundscell',
+            name='template_name',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+        ),
+    ]
diff --git a/panikombo/migrations/0024_auto_20210818_1158.py b/panikombo/migrations/0024_auto_20210818_1158.py
new file mode 100644 (file)
index 0000000..d5965c4
--- /dev/null
@@ -0,0 +1,22 @@
+# Generated by Django 2.2.19 on 2021-08-18 11:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0023_auto_20210818_0906'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='episodeautoselectioncell',
+            name='template_name',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+        ),
+        migrations.AddField(
+            model_name='newsitemautoselectioncell',
+            name='template_name',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+        ),
+    ]
diff --git a/panikombo/migrations/0025_auto_20220714_0830.py b/panikombo/migrations/0025_auto_20220714_0830.py
new file mode 100644 (file)
index 0000000..137f45a
--- /dev/null
@@ -0,0 +1,37 @@
+# Generated by Django 2.2.28 on 2022-07-14 08:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0024_auto_20210818_1158'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='episodeautoselectioncell',
+            name='condition',
+            field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+        ),
+        migrations.AddField(
+            model_name='episodecell',
+            name='condition',
+            field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+        ),
+        migrations.AddField(
+            model_name='newsitemautoselectioncell',
+            name='condition',
+            field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+        ),
+        migrations.AddField(
+            model_name='soundcell',
+            name='condition',
+            field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+        ),
+        migrations.AddField(
+            model_name='soundscell',
+            name='condition',
+            field=models.CharField(blank=True, max_length=1000, null=True, verbose_name='Display condition'),
+        ),
+    ]
diff --git a/panikombo/migrations/0026_auto_20230725_1711.py b/panikombo/migrations/0026_auto_20230725_1711.py
new file mode 100644 (file)
index 0000000..fd2c7b7
--- /dev/null
@@ -0,0 +1,40 @@
+# Generated by Django 3.2.19 on 2023-07-25 17:11
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('data', '0065_snapshot_uuids'),
+        ('auth', '0008_alter_user_username_max_length'),
+        ('panikombo', '0025_auto_20220714_0830'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='episodeautoselectioncell',
+            name='groups',
+            field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+        ),
+        migrations.AlterField(
+            model_name='episodecell',
+            name='groups',
+            field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+        ),
+        migrations.AlterField(
+            model_name='newsitemautoselectioncell',
+            name='groups',
+            field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+        ),
+        migrations.AlterField(
+            model_name='soundcell',
+            name='groups',
+            field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+        ),
+        migrations.AlterField(
+            model_name='soundscell',
+            name='groups',
+            field=models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles'),
+        ),
+    ]
diff --git a/panikombo/migrations/0027_weekprogramcell.py b/panikombo/migrations/0027_weekprogramcell.py
new file mode 100644 (file)
index 0000000..ecb557f
--- /dev/null
@@ -0,0 +1,55 @@
+# Generated by Django 3.2.19 on 2023-07-25 17:13
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('auth', '0008_alter_user_username_max_length'),
+        ('data', '0065_snapshot_uuids'),
+        ('panikombo', '0026_auto_20230725_1711'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='WeekProgramCell',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('placeholder', models.CharField(max_length=20)),
+                ('order', models.PositiveIntegerField()),
+                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+                (
+                    'extra_css_class',
+                    models.CharField(
+                        blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+                    ),
+                ),
+                (
+                    'template_name',
+                    models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+                ),
+                (
+                    'condition',
+                    models.CharField(
+                        blank=True, max_length=1000, null=True, verbose_name='Display condition'
+                    ),
+                ),
+                ('public', models.BooleanField(default=True, verbose_name='Public')),
+                (
+                    'restricted_to_unlogged',
+                    models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+                ),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+            ],
+            options={
+                'abstract': False,
+                'verbose_name': 'Week Program',
+            },
+        ),
+    ]
diff --git a/panikombo/migrations/0028_weekprogramcell_include_nonstop.py b/panikombo/migrations/0028_weekprogramcell_include_nonstop.py
new file mode 100644 (file)
index 0000000..50864c5
--- /dev/null
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.19 on 2023-07-25 17:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0027_weekprogramcell'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='weekprogramcell',
+            name='include_nonstop',
+            field=models.BooleanField(default=True, verbose_name='Include nonstop'),
+        ),
+    ]
diff --git a/panikombo/migrations/0029_focuscarrouselcell.py b/panikombo/migrations/0029_focuscarrouselcell.py
new file mode 100644 (file)
index 0000000..afc800f
--- /dev/null
@@ -0,0 +1,55 @@
+# Generated by Django 3.2.19 on 2023-07-25 18:24
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('auth', '0008_alter_user_username_max_length'),
+        ('data', '0065_snapshot_uuids'),
+        ('panikombo', '0028_weekprogramcell_include_nonstop'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='FocusCarrouselCell',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('placeholder', models.CharField(max_length=20)),
+                ('order', models.PositiveIntegerField()),
+                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+                (
+                    'extra_css_class',
+                    models.CharField(
+                        blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+                    ),
+                ),
+                (
+                    'template_name',
+                    models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+                ),
+                (
+                    'condition',
+                    models.CharField(
+                        blank=True, max_length=1000, null=True, verbose_name='Display condition'
+                    ),
+                ),
+                ('public', models.BooleanField(default=True, verbose_name='Public')),
+                (
+                    'restricted_to_unlogged',
+                    models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+                ),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                ('count', models.PositiveSmallIntegerField(default=3, verbose_name='Count')),
+                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+            ],
+            options={
+                'verbose_name': 'Focus carrousel',
+            },
+        ),
+    ]
diff --git a/panikombo/migrations/0030_emissionscell.py b/panikombo/migrations/0030_emissionscell.py
new file mode 100644 (file)
index 0000000..f7361b5
--- /dev/null
@@ -0,0 +1,71 @@
+# Generated by Django 3.2.19 on 2023-07-25 20:23
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('auth', '0008_alter_user_username_max_length'),
+        ('data', '0065_snapshot_uuids'),
+        ('panikombo', '0029_focuscarrouselcell'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='EmissionsCell',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('placeholder', models.CharField(max_length=20)),
+                ('order', models.PositiveIntegerField()),
+                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+                (
+                    'extra_css_class',
+                    models.CharField(
+                        blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+                    ),
+                ),
+                (
+                    'template_name',
+                    models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+                ),
+                (
+                    'condition',
+                    models.CharField(
+                        blank=True, max_length=1000, null=True, verbose_name='Display condition'
+                    ),
+                ),
+                ('public', models.BooleanField(default=True, verbose_name='Public')),
+                (
+                    'restricted_to_unlogged',
+                    models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+                ),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                ('title', models.CharField(max_length=50, verbose_name='Title', blank=True)),
+                ('count', models.PositiveSmallIntegerField(default=3, verbose_name='Count')),
+                ('include_active', models.BooleanField(default=True, verbose_name='Include active')),
+                ('include_archived', models.BooleanField(default=False, verbose_name='Include archived')),
+                (
+                    'sort_order',
+                    models.CharField(
+                        choices=[
+                            ('title', 'Alphabetical'),
+                            ('-creation_timestamp', 'Reverse chronological (latest emissions)'),
+                            ('?', 'Random'),
+                        ],
+                        default='-creation_timestamp',
+                        max_length=30,
+                        verbose_name='Sort order',
+                    ),
+                ),
+                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Roles')),
+                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.page')),
+            ],
+            options={
+                'verbose_name': 'Emissions',
+            },
+        ),
+    ]
diff --git a/panikombo/migrations/0031_auto_20230902_1801.py b/panikombo/migrations/0031_auto_20230902_1801.py
new file mode 100644 (file)
index 0000000..96b7fc6
--- /dev/null
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.19 on 2023-09-02 18:01
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('panikombo', '0030_emissionscell'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='episodeautoselectioncell',
+            options={'verbose_name': 'Episodes'},
+        ),
+        migrations.AlterModelOptions(
+            name='newsitemautoselectioncell',
+            options={'verbose_name': 'Newsitems'},
+        ),
+        migrations.AddField(
+            model_name='newsitemautoselectioncell',
+            name='count',
+            field=models.PositiveSmallIntegerField(default=20, verbose_name='Count'),
+        ),
+    ]
index a2ea7da099747f32f84ffd342f83c679eaab870e..96877ab7d87116084260c2fb75e6181b08c82d80 100644 (file)
@@ -1,35 +1,63 @@
-# coding: utf-8
 import collections
 
-COMBO_PUBLIC_TEMPLATES = collections.OrderedDict({
-    'standard': {
-        'name': 'Page normale',
-        'template': 'combo/page_template_sidebar.html',
-        'placeholders': collections.OrderedDict({
-            'content': {
-                'name': 'Contenu',
+COMBO_PUBLIC_TEMPLATES = collections.OrderedDict(
+    {
+        'standard': {
+            'name': 'Page avec barre latérale',
+            'template': 'combo/page_template_sidebar.html',
+            'placeholders': collections.OrderedDict(
+                {
+                    'introduction': {
+                        'name': 'Introduction',
+                        'optional': True,
+                    },
+                    'content': {
+                        'name': 'Contenu',
+                    },
+                    'sidebar': {
+                        'name': 'Barre latérale',
+                    },
+                }
+            ),
+        },
+        'fullwidth': {
+            'name': 'Page prenant toute la largeur',
+            'template': 'combo/page_template_full_width.html',
+            'placeholders': {
+                'introduction': {
+                    'name': 'Introduction',
+                    'optional': True,
+                },
+                'content': {
+                    'name': 'Contenu',
+                },
             },
-            'sidebar': {
-                'name': 'Barre latérale',
+        },
+        'standard-about': {
+            'name': 'Section « À propos »',
+            'template': 'combo/page_template_about.html',
+            'placeholders': {
+                'content': {
+                    'name': 'Contenu',
+                },
             },
-        })
-    },
-    'fullwidth': {
-        'name': 'Page prenant toute la largeur',
-        'template': 'combo/page_template_full_width.html',
-        'placeholders': {
-            'content': {
-                'name': 'Contenu',
-            },
-        }
-    },
-    'standard-about': {
-        'name': 'Section « À propos »',
-        'template': 'combo/page_template_about.html',
-        'placeholders': {
-            'content': {
-                'name': 'Contenu',
-            },
-        }
-    },
-})
+        },
+    }
+)
+
+COMBO_CELL_TEMPLATES = {
+    'data_menucell': {
+        'horizontal': {
+            'label': 'Horizontal',
+            'extra-css-classes': 'menu-horizontal',
+        },
+        'vertical': {
+            'label': 'Vertical',
+            'extra-css-classes': 'menu-vertical',
+        },
+        'topiks': {
+            'label': 'Topiks',
+            'template': 'cells/menu-topiks.html',
+        },
+    }
+}
index 905b7f2ff787f9a83e3c5ed8928f2428652719b2..de99b6732726e6eb5535a8811d0d8b73c0a74e12 100644 (file)
@@ -1,25 +1,20 @@
-from datetime import date
-import os
+from datetime import date, datetime, timedelta
 
+from combo.data.library import register_cell_class
+from combo.data.models import CellBase
 from django import template
 from django.db import models
-from django.db.models.functions import Lower
-from django.utils.encoding import force_text, python_2_unicode_compatible
-from django.utils.translation import ugettext_lazy as _
-
-from ckeditor.fields import RichTextField
-from taggit.models import Tag
+from django.utils.translation import gettext_lazy as _
+from emissions.models import Emission, Episode, Focus, NewsItem, SoundFile
+from emissions.utils import period_program
 from taggit.managers import TaggableManager
+from taggit.models import Tag
 from taggit.utils import parse_tags
 
-from combo.data.models import CellBase
-from combo.data.library import register_cell_class
-
-from emissions.models import Episode, NewsItem
 
 @register_cell_class
 class SoundCell(CellBase):
-    soundfile = models.ForeignKey('emissions.SoundFile', null=True)
+    soundfile = models.ForeignKey('emissions.SoundFile', null=True, on_delete=models.CASCADE)
 
     class Meta:
         verbose_name = _('Sound')
@@ -31,6 +26,7 @@ class SoundCell(CellBase):
 
     def get_default_form_class(self):
         from .forms import SoundCellForm
+
         return SoundCellForm
 
     def get_included_items(self):
@@ -41,21 +37,20 @@ class SoundCell(CellBase):
     def get_additional_label(self):
         if self.soundfile:
             if self.soundfile.fragment:
-                return u'%s - %s - %s' % (
-                        self.soundfile.episode.emission.title,
-                        self.soundfile.episode.title,
-                        self.soundfile.title)
+                return '%s - %s - %s' % (
+                    self.soundfile.episode.emission.title,
+                    self.soundfile.episode.title,
+                    self.soundfile.title,
+                )
             else:
-                return u'%s - %s' % (
-                        self.soundfile.episode.emission.title,
-                        self.soundfile.episode.title)
+                return '%s - %s' % (self.soundfile.episode.emission.title, self.soundfile.episode.title)
 
         return ''
 
 
 @register_cell_class
 class EpisodeCell(CellBase):
-    episode = models.ForeignKey('emissions.Episode', null=True)
+    episode = models.ForeignKey('emissions.Episode', null=True, on_delete=models.CASCADE)
 
     class Meta:
         verbose_name = _('Episode')
@@ -74,13 +69,12 @@ class EpisodeCell(CellBase):
 
     def get_default_form_class(self):
         from .forms import EpisodeCellForm
+
         return EpisodeCellForm
 
     def get_additional_label(self):
         if self.episode:
-            return u'%s - %s' % (
-                        self.episode.emission.title,
-                        self.episode.title)
+            return '%s - %s' % (self.episode.emission.title, self.episode.title)
         return ''
 
 
@@ -94,18 +88,15 @@ class EpisodeAutoSelectionCell(CellBase):
     title = models.CharField(_('Title'), max_length=50, blank=True)
     tags = TaggableManager(_('Tags'), blank=True)
     and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
-    category = models.ForeignKey('emissions.Category', null=True, blank=True)
+    category = models.ForeignKey('emissions.Category', null=True, blank=True, on_delete=models.CASCADE)
     period = models.PositiveSmallIntegerField(
-            _('Period'), default=0,
-            choices=((0, _('All')),
-                     (1, _('Future')),
-                     (2, _('Past'))))
-
-    template_name = 'panikombo/episode_auto_selection.html'
+        _('Period'), default=0, choices=((0, _('All')), (1, _('Future')), (2, _('Past')))
+    )
 
+    default_template_name = 'panikombo/episode_auto_selection.html'
 
     class Meta:
-        verbose_name = _('Automatic Episode Selection')
+        verbose_name = _('Episodes')
 
     def get_included_items(self):
         episodes_queryset = Episode.objects.select_related()
@@ -119,38 +110,53 @@ class EpisodeAutoSelectionCell(CellBase):
 
         if self.period == 0:
             episodes_queryset = episodes_queryset.extra(
-                    select={ 'first_diffusion': 'emissions_diffusion.datetime', },
-                    select_params=(False, True),
-                    where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
-                                           WHERE episode_id = emissions_episode.id)'''],
-                    tables=['emissions_diffusion'])
+                select={
+                    'first_diffusion': 'emissions_diffusion.datetime',
+                },
+                select_params=(False, True),
+                where=[
+                    '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
+                                           WHERE episode_id = emissions_episode.id)'''
+                ],
+                tables=['emissions_diffusion'],
+            )
             episodes_queryset = episodes_queryset.order_by('first_diffusion').distinct()
         elif self.period == 1:
             episodes_queryset = episodes_queryset.extra(
-                    select={ 'first_diffusion': 'emissions_diffusion.datetime', },
-                    select_params=(False, True),
-                    where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
+                select={
+                    'first_diffusion': 'emissions_diffusion.datetime',
+                },
+                select_params=(False, True),
+                where=[
+                    '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
                                            WHERE episode_id = emissions_episode.id) AND
-                                                 datetime >= CURRENT_TIMESTAMP'''],
-                    tables=['emissions_diffusion'])
+                                                 datetime >= CURRENT_TIMESTAMP'''
+                ],
+                tables=['emissions_diffusion'],
+            )
             episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
         elif self.period == 2:
             episodes_queryset = episodes_queryset.extra(
-                    select={ 'first_diffusion': 'emissions_diffusion.datetime', },
-                    select_params=(False, True),
-                    where=['''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
+                select={
+                    'first_diffusion': 'emissions_diffusion.datetime',
+                },
+                select_params=(False, True),
+                where=[
+                    '''datetime = (SELECT MIN(datetime) FROM emissions_diffusion
                                            WHERE episode_id = emissions_episode.id) AND
-                                                 datetime < CURRENT_TIMESTAMP'''],
-                    tables=['emissions_diffusion'])
+                                                 datetime < CURRENT_TIMESTAMP'''
+                ],
+                tables=['emissions_diffusion'],
+            )
             episodes_queryset = episodes_queryset.order_by('-first_diffusion').distinct()
 
         return episodes_queryset
 
     def get_cell_extra_context(self, context):
-        ctx = super(EpisodeAutoSelectionCell, self).get_cell_extra_context(context)
+        ctx = super().get_cell_extra_context(context)
         ctx['title'] = self.title
 
-        if (self.category or self.period or self.tags.count()):
+        if self.category or self.period or self.tags.count():
             ctx['episodes'] = self.get_included_items()
         else:
             ctx['episodes'] = []
@@ -159,6 +165,7 @@ class EpisodeAutoSelectionCell(CellBase):
 
     def get_default_form_class(self):
         from .forms import EpisodeAutoSelectionCellForm
+
         return EpisodeAutoSelectionCellForm
 
     def get_additional_label(self):
@@ -166,19 +173,22 @@ class EpisodeAutoSelectionCell(CellBase):
             return self.title
         return ''
 
+
 @register_cell_class
 class NewsItemAutoSelectionCell(CellBase):
     title = models.CharField(_('Title'), max_length=50, blank=True)
     tags = TaggableManager(_('Tags'), blank=True)
     and_tags = models.CharField(_('And Tags'), max_length=100, blank=True)
     future = models.BooleanField(_('Future Events Only'), default=True)
-    category = models.ForeignKey('emissions.NewsCategory',
-            verbose_name=_('Category'), null=True, blank=True)
+    category = models.ForeignKey(
+        'emissions.NewsCategory', verbose_name=_('Category'), null=True, blank=True, on_delete=models.SET_NULL
+    )
+    count = models.PositiveSmallIntegerField(_('Count'), default=20)
 
-    template_name = 'panikombo/newsitem_auto_selection.html'
+    default_template_name = 'panikombo/newsitem_auto_selection.html'
 
     class Meta:
-        verbose_name = _('Automatic Newsitem Selection')
+        verbose_name = _('Newsitems')
 
     def get_included_items(self):
         newsitems_queryset = NewsItem.objects.select_related()
@@ -192,21 +202,17 @@ class NewsItemAutoSelectionCell(CellBase):
         if self.category:
             newsitems_queryset = newsitems_queryset.filter(category=self.category)
         newsitems_queryset = newsitems_queryset.order_by('-event_date', '-creation_timestamp')
-        return newsitems_queryset
+        return newsitems_queryset[: self.count]
 
     def get_cell_extra_context(self, context):
-        ctx = super(NewsItemAutoSelectionCell, self).get_cell_extra_context(context)
+        ctx = super().get_cell_extra_context(context)
         ctx['title'] = self.title
-
-        if self.tags.count() or self.future or self.category:
-            ctx['newsitems'] = self.get_included_items()
-        else:
-            ctx['newsitems'] = []
-
+        ctx['newsitems'] = self.get_included_items()
         return ctx
 
     def get_default_form_class(self):
         from .forms import NewsItemAutoSelectionCellForm
+
         return NewsItemAutoSelectionCellForm
 
     def get_additional_label(self):
@@ -216,8 +222,205 @@ class NewsItemAutoSelectionCell(CellBase):
 
 
 class ItemTopik(models.Model):
-    newsitem = models.ForeignKey('emissions.NewsItem', verbose_name=_('News Item'),
-            null=True, blank=True)
-    episode = models.ForeignKey('emissions.Episode', verbose_name=_('Episode'),
-            null=True, blank=True)
-    page = models.ForeignKey('data.Page', null=True, blank=True)
+    newsitem = models.ForeignKey(
+        'emissions.NewsItem', verbose_name=_('News Item'), null=True, blank=True, on_delete=models.SET_NULL
+    )
+    episode = models.ForeignKey(
+        'emissions.Episode', verbose_name=_('Episode'), null=True, blank=True, on_delete=models.SET_NULL
+    )
+    page = models.ForeignKey('data.Page', null=True, blank=True, on_delete=models.SET_NULL)
+
+
+@register_cell_class
+class SoundsCell(CellBase):
+    title = models.CharField(_('Title'), max_length=150, blank=True)
+    include_search_input = models.BooleanField(_('Include search input'), default=True)
+    include_fragments = models.BooleanField(_('Include fragments'), default=True)
+    limit_to_focus = models.BooleanField(_('Limit to focused elements'), default=False)
+    sound_format = models.ForeignKey(
+        'emissions.Format', verbose_name=_('Limit to format'), null=True, blank=True, on_delete=models.CASCADE
+    )
+    tags = TaggableManager(_('Tags'), blank=True)
+    minimal_duration = models.PositiveIntegerField(
+        _('Minimal duration (in minutes)'), default=None, blank=True, null=True
+    )
+    maximal_duration = models.PositiveIntegerField(
+        _('Maximal duration (in minutes)'), default=None, blank=True, null=True
+    )
+    count = models.PositiveSmallIntegerField(_('Count'), default=20)
+    sort_order = models.CharField(
+        _('Sort order'),
+        default='-creation_timestamp',
+        max_length=30,
+        choices=[
+            ('-creation_timestamp', _('Reverse chronological (creation)')),
+            ('-first_diffusion', _('Reverse chronological (diffusion)')),
+            ('creation_timestamp', _('Chronological (creation)')),
+            ('first_diffusion', _('Chronological (diffusion)')),
+            ('?', _('Random')),
+        ],
+    )
+
+    class Meta:
+        verbose_name = _('Sounds')
+
+    def get_default_form_fields(self):
+        fields = super().get_default_form_fields()
+        fields.insert(fields.index('minimal_duration'), 'tags')
+        return fields
+
+    def get_cell_extra_context(self, context):
+        soundfiles = SoundFile.objects.prefetch_related('episode__emission__categories')
+        soundfiles = soundfiles.filter(podcastable=True)
+        soundfiles = soundfiles.exclude(creation_timestamp__isnull=True)
+        if not self.include_fragments:
+            soundfiles = soundfiles.filter(fragment=False)
+        if self.limit_to_focus:
+            soundfiles = soundfiles.filter(got_focus__isnull=False)
+        if self.sound_format:
+            soundfiles = soundfiles.filter(format_id=self.sound_format_id)
+        if self.minimal_duration:
+            soundfiles = soundfiles.filter(duration__gte=self.minimal_duration * 60)
+        if self.maximal_duration:
+            soundfiles = soundfiles.filter(duration__lte=self.maximal_duration * 60)
+        if self.tags.exists():
+            soundfiles = soundfiles.filter(episode__tags__in=self.tags.all())
+        soundfiles = (
+            soundfiles.select_related()
+            .extra(
+                select={
+                    'first_diffusion': 'emissions_diffusion.datetime',
+                },
+                select_params=(False, True),
+                where=[
+                    '''datetime = (SELECT MIN(datetime)
+                                            FROM emissions_diffusion
+                                        WHERE episode_id = emissions_episode.id)'''
+                ],
+                tables=['emissions_diffusion'],
+            )
+            .order_by(self.sort_order)
+            .distinct()
+        )
+        return {
+            'include_search_input': self.include_search_input,
+            'soundfiles': soundfiles[: self.count],
+        }
+
+
+@register_cell_class
+class WeekProgramCell(CellBase):
+    include_nonstop = models.BooleanField(_('Include nonstop'), default=True)
+
+    default_template_name = 'panikombo/week_program.html'
+
+    class Meta:
+        verbose_name = _('Week Program')
+
+    @staticmethod
+    def tofirstdayinisoweek(year, week):
+        # from http://stackoverflow.com/questions/5882405/get-date-from-iso-week-number-in-python
+        ret = datetime.strptime('%04d-%02d-1' % (year, week), '%Y-%W-%w')
+        if datetime(year, 1, 4).isoweekday() > 4:
+            ret -= timedelta(days=7)
+        return ret
+
+    def get_cell_extra_context(self, context):
+        ctx = super().get_cell_extra_context(context)
+        year = context['request'].GET.get('year') if 'request' in context else None
+        week = context['request'].GET.get('week') if 'request' in context else None
+        weekday = context['request'].GET.get('weekday') if 'request' in context else None
+        year = int(year if year else datetime.today().isocalendar()[0])
+        week = int(week if week else datetime.today().isocalendar()[1])
+        weekday = int(weekday if weekday is not None else datetime.today().weekday())
+
+        date = WeekProgramCell.tofirstdayinisoweek(year, week)
+        date = datetime(*date.timetuple()[:3])
+
+        previous_week = date - timedelta(days=7)
+        previous_week_year, previous_week_no = previous_week.isocalendar()[:2]
+
+        next_week = date + timedelta(days=7)
+        next_week_year, next_week_no = next_week.isocalendar()[:2]
+
+        program = period_program(date, date + timedelta(days=7), include_nonstop=self.include_nonstop)
+        days = []
+        for day in range(7):
+            days.append(
+                {
+                    'cells': [x for x in program if x.is_on_weekday(day + 1)],
+                    'datetime': date + timedelta(days=day),
+                }
+            )
+
+        ctx.update(
+            {
+                'days': days,
+                'weekday': weekday,
+                'week': week,
+                'year': year,
+                'previous_week_year': previous_week_year,
+                'previous_week_no': previous_week_no,
+                'next_week_year': next_week_year,
+                'next_week_no': next_week_no,
+            }
+        )
+
+        return ctx
+
+
+@register_cell_class
+class FocusCarrouselCell(CellBase):
+    count = models.PositiveSmallIntegerField(_('Count'), default=3)
+
+    default_template_name = 'panikombo/focus_carrousel.html'
+
+    class Meta:
+        verbose_name = _('Focus carrousel')
+
+    def get_cell_extra_context(self, context):
+        ctx = super().get_cell_extra_context(context)
+        ctx['news'] = (
+            Focus.objects.filter(current=True)
+            .select_related('emission', 'newsitem', 'soundfile', 'episode', 'newsitem__category')
+            .order_by('?')[: self.count]
+        )
+        return ctx
+
+
+@register_cell_class
+class EmissionsCell(CellBase):
+    title = models.CharField(_('Title'), max_length=50, blank=True)
+    count = models.PositiveSmallIntegerField(_('Count'), default=3)
+    include_active = models.BooleanField(_('Include active'), default=True)
+    include_archived = models.BooleanField(_('Include archived'), default=False)
+    sort_order = models.CharField(
+        _('Sort order'),
+        default='-creation_timestamp',
+        max_length=30,
+        choices=[
+            ('title', _('Alphabetical')),
+            ('-creation_timestamp', _('Reverse chronological (latest emissions)')),
+            ('?', _('Random')),
+        ],
+    )
+
+    default_template_name = 'panikombo/emissions.html'
+
+    class Meta:
+        verbose_name = _('Emissions')
+
+    def get_cell_extra_context(self, context):
+        ctx = super().get_cell_extra_context(context)
+
+        qs = Emission.objects.all()
+        if not self.include_active:
+            qs = qs.exclude(archived=False)
+        if not self.include_archived:
+            qs = qs.exclude(archived=True)
+
+        qs = qs.order_by(self.sort_order)
+
+        ctx['emissions'] = qs[: self.count]
+
+        return ctx
diff --git a/panikombo/templates/panikombo/audio.html b/panikombo/templates/panikombo/audio.html
new file mode 100644 (file)
index 0000000..074e369
--- /dev/null
@@ -0,0 +1,27 @@
+{% load paniktags thumbnail static %}
+{% if soundfile %}
+  <div class="wrapper extra-soundfiles">
+    <div class="logo">
+      {% if soundfile.episode.image %}
+        {% thumbnail soundfile.episode.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% elif soundfile.episode.emission.image %}
+        {% thumbnail soundfile.episode.emission.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% else %}
+        <img alt="" class="smooth"  style="width:60px;" src="{% static "img/emission.png" %}"/>
+      {% endif %}
+    </div>
+    <ul class="padded custom list">
+      <li>
+        <div class="soundfile-info"><strong>
+          <a href="{% url 'emission-view' slug=soundfile.episode.emission.slug%}">{{ soundfile.episode.emission.title }}</a> -
+          <a href="{% url 'episode-view' emission_slug=soundfile.episode.emission.slug slug=soundfile.episode.slug %}">{{ soundfile.episode.title }}</a></strong>
+          {% if soundfile.fragment %}<span> - {{ soundfile.title }}</span>{% endif %}
+        </div>
+        {% audio sound=soundfile %}</li>
+    </ul>
+  </div>
+{% endif %}
diff --git a/panikombo/templates/panikombo/emissions.html b/panikombo/templates/panikombo/emissions.html
new file mode 100644 (file)
index 0000000..680e373
--- /dev/null
@@ -0,0 +1,11 @@
+{% load i18n paniktags %}
+{% if cell.title %}
+  <h2 class="cell--title text-cell--title">{{ cell.title }}</h2>
+{% endif %}
+<ul class="custom list padded">
+  {% for emission in emissions %}
+    <li class="item">
+      {% emission_resume %}
+    </li>
+  {% endfor %}
+</ul>
diff --git a/panikombo/templates/panikombo/episode.html b/panikombo/templates/panikombo/episode.html
new file mode 100644 (file)
index 0000000..3335fb8
--- /dev/null
@@ -0,0 +1,31 @@
+{% load paniktags thumbnail static %}
+{% if episode %}
+  <div class="wrapper extra-soundfiles">
+    <div class="logo">
+      {% if episode.image %}
+        {% thumbnail episode.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% elif episode.emission.image %}
+        {% thumbnail episode.emission.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% else %}
+        <img alt="" class="smooth"  style="width:60px;" src="{% static "img/emission.png" %}"/>
+      {% endif %}
+    </div>
+    <ul class="padded custom list">
+      <li>
+        <div class="soundfile-info"><strong>
+          <a href="{% url 'emission-view' slug=episode.emission.slug%}">{{ episode.emission.title }}</a> -
+          <a href="{% url 'episode-view' emission_slug=episode.emission.slug slug=episode.slug %}">{{ episode.title }}</a></strong>
+          {% if soundfile.fragment %}<span> - {{ soundfile.title }}</span>{% endif %}
+        </div>
+        {% for diffusion in episode.diffusions %}
+          <span class="date">→ {{ diffusion.datetime|date:"l d M Y à H:i" }}</span>
+        {% endfor %}
+        {% if soundfile %}{% audio sound=soundfile %}{% endif %}
+      </li>
+    </ul>
+  </div>
+{% endif %}
diff --git a/panikombo/templates/panikombo/episode_auto_selection.html b/panikombo/templates/panikombo/episode_auto_selection.html
new file mode 100644 (file)
index 0000000..657c59f
--- /dev/null
@@ -0,0 +1,39 @@
+{% load paniktags thumbnail static %}
+{% if title and episodes %}<h3>{{title}}</h3>{% endif %}
+{% for episode in episodes %}
+
+  <div class="wrapper extra-soundfiles soundcell">
+    <div class="logo">
+      {% if episode.image %}
+        {% thumbnail episode.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% elif episode.emission.image %}
+        {% thumbnail episode.emission.image "60x60" crop="50% 25%" as im %}
+          <img alt="" width="60" height="60" src="{{im.url}}"/>
+        {% endthumbnail %}
+      {% else %}
+        <img alt="" class="smooth"  style="width:60px;" src="{% static "img/emission.png" %}"/>
+      {% endif %}
+    </div>
+    <ul class="padded custom list">
+      <li>
+        <div class="soundfile-info"><strong>
+          <a class="emission-title" href="{% url 'emission-view' slug=episode.emission.slug%}">{{ episode.emission.title }}</a>
+          <span class="sep">-</span>
+          <a class="episode-title" href="{% url 'episode-view' emission_slug=episode.emission.slug slug=episode.slug %}">{{ episode.title }}</a></strong>
+        </div>
+        {% for diffusion in episode.diffusions %}
+          <span class="date">→ {{ diffusion.datetime|date:"l d M Y à H:i" }}</span>
+        {% endfor %}
+        {% if episode.main_sound %}{% audio sound=episode.main_sound %}{% endif %}
+        {% for sound in episode.fragment_sounds %}
+          <div class="fragment-sound">
+            {% audio sound=sound display_fragment_name=True %}
+          </div>
+        {% endfor %}
+      </li>
+    </ul>
+  </div>
+
+{% endfor %}
diff --git a/panikombo/templates/panikombo/episodeautoselectioncell_form.html b/panikombo/templates/panikombo/episodeautoselectioncell_form.html
new file mode 100644 (file)
index 0000000..572164d
--- /dev/null
@@ -0,0 +1 @@
+{{form.as_p}}
diff --git a/panikombo/templates/panikombo/focus_carrousel.html b/panikombo/templates/panikombo/focus_carrousel.html
new file mode 100644 (file)
index 0000000..0eff3d6
--- /dev/null
@@ -0,0 +1,40 @@
+{% load thumbnail i18n paniktags %}
+<div id="newsRoll">
+  <div class="newsRoll">
+    <ul id="ticker" class="custom bigNews marged" style="height:300px;overflow:hidden;">
+      {% for focus in news %}
+        <li
+          id="newsRollId-{{ focus.id }}"
+          class="">
+          <a
+            {% thumbnail focus.content_image "500x375" crop="50% 25%" as im %}
+              style="max-width:100%;height:300px;background: no-repeat 50% 50% url('{{im.url}}');"
+            {% endthumbnail %}
+            class="block news relative"
+            href="{{ focus|get_focus_url }}">
+            {% if focus.content_category_title %}
+              <div class="labels">
+                <span>{{ focus.content_category_title }}</span>
+              </div>
+            {% endif %}
+
+            <div class="title"><div>{{ focus.focus_title }}</div></div>
+          </a>
+        </li>
+      {% endfor %}
+    </ul>
+    <div class="marged">
+      <ul class="custom padded" id="roller">
+        {% for focus in news %}
+          <li class="num-{{ forloop.counter }} padded">
+            <button data-about="newsRollId-{{ focus.id }}">
+              {% thumbnail focus.content_image "160x120" crop="50% 25%" as im %}
+                <img loading="lazy" alt="{{ focus.focus_title }}" style="width:95%;" src="{{im.url}}" />
+              {% endthumbnail %}
+            </button>
+          </li>
+        {% endfor %}
+      </ul>
+    </div>
+  </div>
+</div>
diff --git a/panikombo/templates/panikombo/newsitem_auto_selection.html b/panikombo/templates/panikombo/newsitem_auto_selection.html
new file mode 100644 (file)
index 0000000..d6fb769
--- /dev/null
@@ -0,0 +1,7 @@
+{% load paniktags %}
+{% if title and newsitems %}<h3>{{title}}</h3>{% endif %}
+<ul class="custom list newsList">
+  {% for content in newsitems %}
+    <li>{% news_inline %}</li>
+  {% endfor %}
+</ul>
diff --git a/panikombo/templates/panikombo/select2.html b/panikombo/templates/panikombo/select2.html
new file mode 100644 (file)
index 0000000..01d1766
--- /dev/null
@@ -0,0 +1,24 @@
+<select style="width: 100%" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %}>
+  {% if widget.value != None %}<option value="{{ widget.value }}">{{widget.view_value}}</option>{% endif %}
+</select>
+<script>
+  $(function() {
+    var options = {
+      placeholder: '',
+      minimumInputLength: 3,
+      ajax: {
+        url: function() {
+          return "{% url view_name %}";
+        },
+        dataType: 'json',
+        data: function(params) {
+          var query = {
+            term: params.term,
+          }
+          return query;
+        },
+      },
+    };
+    $('select[name={{widget.name}}]').select2(options);
+  })
+</script>
diff --git a/panikombo/templates/panikombo/week_program.html b/panikombo/templates/panikombo/week_program.html
new file mode 100644 (file)
index 0000000..a174966
--- /dev/null
@@ -0,0 +1,74 @@
+{% load i18n paniktags static %}
+
+{% block program-header %}
+  <div class="program tabs" data-tab-about="#weekProgramContent-{{ week|slugify }}">
+    <nav class="">
+      <ul class="days custom distributed">
+        <li class="week-arrow week-arrow-prev"><button data-year="{{previous_week_year}}" data-week="{{previous_week_no}}"
+                                                       class="icon-chevron-sign-left"><span class="sr-only">{% trans "Previous Week" %}</span></button></li>
+        {% for day in days %}
+          <li class="weektab-{{forloop.counter}}"><button class="{% if day.datetime.weekday == weekday %}active{% endif %}" data-tab="#Program-week-{{ day.datetime|slugify }}" data-neau-text="{{ day.datetime|date:"d.m.y"}}"><span class="day-label">{{ day.datetime|date:"D" }}</span> <span class="date-label">{{ day.datetime|date:"d/m" }}</span></button></li>
+        {% endfor %}
+        <li class="week-arrow week-arrow-next"><button data-year="{{next_week_year}}" data-week="{{next_week_no}}"
+                                                       class="icon-chevron-sign-right" ><span class="sr-only">{% trans "Next Week" %}</span></button></li>
+      </ul>
+    </nav>
+  </div>
+{% endblock %}
+
+{% block program-content %}
+  <div id="weekProgramContent-{{ week|slugify }}" class="program  {% if current_week %}current-week{% endif %}">
+
+    {% for day in days %}
+      <div data-tabbed="true" class="content" id="Program-week-{{ day.datetime|slugify }}"
+           {% if day.datetime.weekday != weekday %}style="display: none"{% endif %}
+      >
+        <ul class="custom program-week list">
+          {% for cell in day.cells %}
+            <li class="cf {% if cell.end_datetime < now %}past{% elif cell.datetime >= now %}future{% else %}current{% endif %}"
+                data-program-slug="{% firstof cell.emission.slug cell.episode.emission.slug cell.slug %}">
+              {% block week-program-line %}
+                <div class="programDate"><strong>{{ cell.datetime|date:"H:i" }}</strong></div>
+                <div class="programCell">
+                  {% if cell.episode %}
+                    {% with cell.episode as episode %}{% episode_resume model="inline" klass="standalone" date=False %}{% endwith %}
+                  {% elif cell.emission %}
+                    {% with cell.emission as emission %}{% emission_resume %}{% endwith %}
+                  {% else %}
+                    <a href="{% if cell.nonstop.redirect_path %}{{ cell.nonstop.redirect_path }}{% else %}{% url 'emission-view' slug=cell.slug %}{% endif %}" class="nonstop"><em>{{ cell.label }}</em></a> - <span class="smooth categories category">Musique en continu</span> - <a class="playlist" href="{% url 'nonstop-playlist' slug=cell.slug year=cell.datetime.year month=cell.datetime.month day=cell.datetime.day %}">playlist</a>
+                  {% endif %}
+                </div>
+              {% endblock %}
+            </li>
+          {% empty %}
+            <li>{% block week-program-empty %}<div class="info big">Non stop only!</div>{% endblock %}</li>
+          {% endfor %}
+        </ul>
+      </div>
+    {% endfor %}
+  </div>
+{% endblock %}
+
+{% block scripts %}
+  <script src="{% static "js/combo.public.js" %}"></script>
+  <script>
+    $(function() {
+      $('button[data-year][data-week]').on('click', function(e) {
+        var $cell = $(this).parents('[data-ajax-cell-url]');
+        $cell.data('extra-context',
+          $cell.data('extra-context') + '&year=' + $(this).data('year') + '&week=' + $(this).data('week'));
+        combo_load_cell($cell);
+        e.preventDefault();
+        return false;
+      });
+      if (! window.week_program_initialized) {
+        $(document).on('combo:cell-loaded', function(ev, cell) {
+          if ($(cell).is('.week-program-cell')) {
+            window.panikweb_init_page();
+          }
+        });
+        window.week_program_initialized = true;
+      }
+    });
+  </script>
+{% endblock %}
diff --git a/panikombo/urls.py b/panikombo/urls.py
new file mode 100644 (file)
index 0000000..d44f2ef
--- /dev/null
@@ -0,0 +1,8 @@
+from django.urls import path
+
+from . import views
+
+urlpatterns = [
+    path('select2/episodes/', views.episodes, name='panikombo-select2-episodes'),
+    path('select2/soundfiles/', views.soundfiles, name='panikombo-select2-soundfiles'),
+]
index faa454e1da73c2cf7322ba74efcdc57d06e69700..47752920c27ee081adc995114de724d87b6bfdcb 100644 (file)
@@ -1,60 +1,60 @@
-from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from django.db.models import Q
-from django.http import Http404, JsonResponse
-from django.views.generic.edit import UpdateView
-import django_select2.views
-
-from emissions.models import SoundFile, Episode
-
-
-class SoundFilesView(django_select2.views.AutoResponseView):
-    def get(self, request, *args, **kwargs):
-        terms = kwargs.get('term', request.GET.get('term', ''))
-        queryset = SoundFile.objects.all()
-        for term in terms.split():
-            queryset = queryset.filter(podcastable=True).filter(Q(title__icontains=term) |
-                    Q(episode__title__icontains=term) |
-                    Q(episode__emission__title__icontains=term))
-        def fmt(soundfile):
-            return '%s - %s - %s' % (soundfile.episode.emission.title,
-                    soundfile.episode.title,
-                    soundfile.title or soundfile.id)
-
-        return JsonResponse({
+from django.http import JsonResponse
+from emissions.models import Episode, SoundFile
+
+
+@login_required
+def soundfiles(request, *args, **kwargs):
+    terms = kwargs.get('term', request.GET.get('term', ''))
+    queryset = SoundFile.objects.all()
+    for term in terms.split():
+        queryset = queryset.filter(podcastable=True).filter(
+            Q(title__icontains=term)
+            | Q(episode__title__icontains=term)
+            | Q(episode__emission__title__icontains=term)
+        )
+
+    def fmt(soundfile):
+        return '%s - %s - %s' % (
+            soundfile.episode.emission.title,
+            soundfile.episode.title,
+            soundfile.title or soundfile.id,
+        )
+
+    return JsonResponse(
+        {
             'results': [
                 {
                     'text': fmt(x),
                     'id': x.pk,
                 }
                 for x in queryset
-                ],
-            'more': False
-        })
+            ],
+            'more': False,
+        }
+    )
 
 
-soundfiles = SoundFilesView.as_view()
+@login_required
+def episodes(request, *args, **kwargs):
+    terms = kwargs.get('term', request.GET.get('term', ''))
+    queryset = Episode.objects.all()
+    for term in terms.split():
+        queryset = queryset.filter(Q(title__icontains=term) | Q(emission__title__icontains=term))
 
+    def fmt(episode):
+        return '%s - %s' % (episode.emission.title, episode.title)
 
-class EpisodesView(django_select2.views.AutoResponseView):
-    def get(self, request, *args, **kwargs):
-        terms = kwargs.get('term', request.GET.get('term', ''))
-        queryset = Episode.objects.all()
-        for term in terms.split():
-            queryset = queryset.filter(Q(title__icontains=term) |
-                    Q(emission__title__icontains=term))
-        def fmt(episode):
-            return '%s - %s' % (episode.emission.title, episode.title)
-
-        return JsonResponse({
+    return JsonResponse(
+        {
             'results': [
                 {
                     'text': fmt(x),
                     'id': x.pk,
                 }
                 for x in queryset
-                ],
-            'more': False
-        })
-
-
-episodes = EpisodesView.as_view()
+            ],
+            'more': False,
+        }
+    )
index fc90cfca014d7ad1c185edeebb746ea6b2e3e37a..423f83f5be01a2e922340d2c92bad9c536543b9f 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,12 +3,12 @@
 import os
 import subprocess
 import sys
-
-from setuptools.command.install_lib import install_lib as _install_lib
+from distutils.cmd import Command
 from distutils.command.build import build as _build
 from distutils.command.sdist import sdist as _sdist
-from distutils.cmd import Command
-from setuptools import setup, find_packages
+
+from setuptools import find_packages, setup
+from setuptools.command.install_lib import install_lib as _install_lib
 
 
 class sdist(_sdist):
@@ -25,11 +25,14 @@ class sdist(_sdist):
 
 def get_version():
     if os.path.exists('VERSION'):
-        with open('VERSION', 'r') as v:
+        with open('VERSION') as v:
             return v.read()
     if os.path.exists('.git'):
-        p = subprocess.Popen(['git', 'describe', '--dirty=.dirty', '--match=v*'],
-                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        p = subprocess.Popen(
+            ['git', 'describe', '--dirty=.dirty', '--match=v*'],
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+        )
         result = p.communicate()[0]
         if p.returncode == 0:
             result = result.decode('ascii').strip()[1:]  # strip spaces/newlines and initial v
@@ -40,9 +43,7 @@ def get_version():
                 version = result
             return version
         else:
-            return '0.0.post%s' % len(
-                    subprocess.check_output(
-                            ['git', 'rev-list', 'HEAD']).splitlines())
+            return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
     return '0.0'
 
 
@@ -59,6 +60,7 @@ class compile_translations(Command):
     def run(self):
         try:
             from django.core.management import call_command
+
             for path, dirs, files in os.walk('panikombo'):
                 if 'locale' not in dirs:
                     continue
@@ -106,5 +108,5 @@ setup(
         'compile_translations': compile_translations,
         'install_lib': install_lib,
         'sdist': sdist,
-    }
+    },
 )