Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added celerybeat-schedule.db
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

est-ce que ce fichier binaire peut être créé automatiquement s'il est manquant ?
Si oui, ne pas l'inclure dans le git

Binary file not shown.
1 change: 1 addition & 0 deletions pod/duplicate/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def video_duplicate(request, slug):
date_delete=original_video.date_delete,
disable_comment=original_video.disable_comment,
tags=original_video.tags.get_tag_list(),
scheduled_publish_date=original_video.scheduled_publish_date,
)
# Duplicate the source file and assign it to the duplicated video
duplicated_video.video.name = duplicate_source_file(
Expand Down
Binary file modified pod/locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
9 changes: 9 additions & 0 deletions pod/main/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
"pod.main.tasks.*": {"queue": "celery"},
"pod.main.celery.*": {"queue": "celery"},
}
app.conf.task_routes.update({
"pod.main.tasks.publish_scheduled_videos": {"queue": "celery"},
})
app.conf.beat_schedule = {
'publish-scheduled-videos-every-minute': {
'task': 'pod.main.tasks.publish_scheduled_videos',
'schedule': 60.0,
},
}


@app.task(bind=True)
Expand Down
14 changes: 14 additions & 0 deletions pod/main/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from pod.main.celery import app
from pod.live.models import LiveTranscriptRunningTask, Broadcaster
from django.utils.timezone import now
from pod.video.models import Video


@app.task(bind=True)
Expand Down Expand Up @@ -78,3 +80,15 @@ def task_start_bbb_presentation_encode_and_move_to_destination(
from pod.import_video.views import bbb_encode_presentation_and_move_to_destination

bbb_encode_presentation_and_move_to_destination(filename, url, dest_file)


@app.task(bind=True)
def publish_scheduled_videos(self):
"""Publish videos that are scheduled to be published."""
videos_to_publish = Video.objects.filter(
scheduled_publish_date__lte=now(),
is_draft=True
)
for video in videos_to_publish:
video.is_draft = False
video.save()
3 changes: 3 additions & 0 deletions pod/video/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class VideoAdmin(admin.ModelAdmin):
"date_added",
"viewcount",
"is_draft",
"scheduled_publish_date",
"is_restricted",
"password",
"duration_in_time",
Expand Down Expand Up @@ -165,6 +166,8 @@ class VideoAdmin(admin.ModelAdmin):
)
readonly_fields = ("duration", "encoding_in_progress", "get_encoding_step")

exclude = ()

inlines = []

inlines += [
Expand Down
26 changes: 25 additions & 1 deletion pod/video/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ class VideoForm(forms.ModelForm):
help_text=_("Who can see your content (everyone, just you, or those granted)."),
)

enable_scheduling = forms.BooleanField(
label=_("Enable scheduling"),
required=False,
help_text=_("Enable scheduling for this video."),
)

required_css_class = "required"
videoattrs = {
"class": "form-control-file",
Expand Down Expand Up @@ -683,7 +689,7 @@ class VideoForm(forms.ModelForm):
{
"legend": _("Advanced options"),
"classes": "",
"fields": ["allow_downloading", "is_360", "disable_comment", "order"],
"fields": ["allow_downloading", "is_360", "disable_comment", "order", "scheduled_publish_date", "enable_scheduling"],
},
),
)
Expand Down Expand Up @@ -947,6 +953,19 @@ def __init__(self, *args, **kwargs) -> None:
# Manage required fields html
self.fields = add_placeholder_and_asterisk(self.fields)
self.fields = add_describedby_attr(self.fields)
self.fields['scheduled_publish_date'].widget.input_type = 'datetime-local'
self.fields['scheduled_publish_date'].widget.attrs['placeholder'] = 'AAAA-MM-JJTHH:MM'
self.fields['scheduled_publish_date'].help_text = _('Format attendu : AAAA-MM-JJTHH:MM (ex : 2025-06-11T14:30)')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

à mettre en anglais par défaut.

self.fields['scheduled_publish_date'].input_formats = ['%Y-%m-%dT%H:%M']

# Handle scheduling
from django.utils import timezone
if self.instance and self.instance.scheduled_publish_date:
self.fields["enable_scheduling"].initial = True
local_dt = timezone.localtime(self.instance.scheduled_publish_date)
self.initial["scheduled_publish_date"] = local_dt.strftime("%Y-%m-%dT%H:%M")
self.fields["scheduled_publish_date"].widget.attrs.pop("style", None)

if self.fields.get("video"):
# Remove label, as it will be included in customclearablefileinput
self.fields["video"].label = ""
Expand Down Expand Up @@ -1095,6 +1114,11 @@ class Meta(object):
"date_evt": datetime.date.today(),
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.scheduled_publish_date:
self.fields["enable_scheduling"].initial = True


class ChannelForm(forms.ModelForm):
"""Form class for Channel editing."""
Expand Down
5 changes: 4 additions & 1 deletion pod/video/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,6 @@ class Video(models.Model):
default=False,
help_text=_("Check this box if you want to use the 360 player for the video"),
)

is_draft = models.BooleanField(
verbose_name=_("Draft"),
help_text=_(
Expand All @@ -819,6 +818,10 @@ class Video(models.Model):
),
default=True,
)
scheduled_publish_date = models.DateTimeField(
null=True, blank=True,
help_text="Date and hour of the scheduled publication."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

à traduire

)
is_restricted = models.BooleanField(
verbose_name=_("Authentication restricted access"),
help_text=_(
Expand Down
20 changes: 20 additions & 0 deletions pod/video/static/js/video_edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,23 @@ if (notificationMessage) {
"Get notified when the video encoding is finished.",
);
}

// Scheduling logic
var schedulingCheckbox = document.getElementById("id_enable_scheduling");
var dateGroup = document.getElementById("scheduled_publish_date_group");
var dateInput = document.getElementById("id_scheduled_publish_date");
if (schedulingCheckbox && dateGroup && dateInput) {
function toggleScheduledDate() {
if (schedulingCheckbox.checked) {
dateGroup.style.display = "block";
dateInput.style.display = "";
} else {
dateGroup.style.display = "none";
dateInput.style.display = "none";
dateInput.value = "";
}
}
schedulingCheckbox.addEventListener("change", toggleScheduledDate);
// Initial state
toggleScheduledDate();
}
32 changes: 30 additions & 2 deletions pod/video/templates/videos/video_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,20 @@ <h1 class="h2">
{{field_hidden}}
{% endfor %}

<div class="form-group mt-3">
<div class="form-check">
{{ form.enable_scheduling }}
<label for="id_enable_scheduling" class="form-check-label">{% trans "Schedule the post" %}</label>
</div>
</div>
<div class="form-group mt-2" id="scheduled_publish_date_group" {% if not form.enable_scheduling.value %}style="display:none;"{% endif %}>
<label for="id_scheduled_publish_date">{% trans "Scheduled publish date" %}</label>
{{ form.scheduled_publish_date }}
</div>

<div class="accordion">
{% for fieldset in form.fieldsets %}
{% with options=fieldset|last name=fieldset|first%}
{% with options=fieldset|last name=fieldset|first %}
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button{% if 'show' in options.classes %}" aria-expanded="true{% else %} collapsed{% endif %}"
Expand All @@ -106,7 +117,7 @@ <h2 class="accordion-header">
{% endif %}

{% for field in form.visible_fields %}
{% if field.name in options.fields %}
{% if field.name in options.fields and field.name not in 'enable_scheduling scheduled_publish_date' %}
<div class="mt-3 field-{{ field.name }} {% if 'description_' in field.name or 'title_' in field.name %}collapse ms-4{% endif %}{% if 'description_' in field.name %} description{% endif %}{% if 'title_' in field.name %} title{% endif %}{% with 'is_restricted restrict_access_to_groups password' as res %} {% if field.name in res.split %}collapse restricted_access{% endif %}{% endwith %}">
<div class="form-group{% if field.field.required %} form-group-required{% endif %}{% if field.errors %} errors{% endif %}{% if "form-control-file" in field.field.widget.attrs.class and form.instance.video %} pod-largelink{% endif %}">
{% if "form-check-input" in field.field.widget.attrs.class %}
Expand Down Expand Up @@ -303,6 +314,23 @@ <h2 class="h4 card-header card-title pod-card__title ps-2">{% trans "Help for fo
});
change_transcript();
}

document.addEventListener("DOMContentLoaded", function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ajouter un petit jsdoc

var checkbox = document.getElementById("id_enable_scheduling");
var dateGroup = document.getElementById("scheduled_publish_date_group");
if (checkbox) {
checkbox.addEventListener("change", function() {
if (checkbox.checked) {
dateGroup.style.display = "block";
} else {
dateGroup.style.display = "none";
var dateInput = document.getElementById("id_scheduled_publish_date");
if (dateInput) dateInput.value = "";
}
});
}
});

</script>
{% if USE_NOTIFICATIONS and form.instance.encoding_in_progress and request.user.owner.accepts_notifications is not False %}
<script>
Expand Down
Loading