missing youtube id extractor, player is ok

This commit is contained in:
JRK 2024-05-08 22:40:27 +02:00
parent 92605ba304
commit 82cd1e3a16
16 changed files with 90 additions and 32 deletions

View File

@ -154,7 +154,7 @@ jQuery(document).ready(function ($) {
$('.modal-slide-edit input:visible:eq(0)').focus().select(); $('.modal-slide-edit input:visible:eq(0)').focus().select();
$('#slide-edit-name').val(slide.name); $('#slide-edit-name').val(slide.name);
$('#slide-edit-type').val(slide.type); $('#slide-edit-type').val(slide.type);
$('#slide-edit-location').val(slide.location); $('#slide-edit-location').val(slide.location).prop('disabled', !slide.is_editable);
$('#slide-edit-duration').val(slide.duration); $('#slide-edit-duration').val(slide.duration);
$('#slide-edit-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || hasDateTime); $('#slide-edit-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || hasDateTime);
$('#slide-edit-cron-schedule-trigger').val(hasDateTime ? 'datetime' : (hasCron ? 'cron' : 'loop')); $('#slide-edit-cron-schedule-trigger').val(hasDateTime ? 'datetime' : (hasCron ? 'cron' : 'loop'));

View File

@ -22,9 +22,6 @@
"slideshow_slide_form_label_name": "Name", "slideshow_slide_form_label_name": "Name",
"slideshow_slide_form_label_location": "Location", "slideshow_slide_form_label_location": "Location",
"slideshow_slide_form_label_type": "Type", "slideshow_slide_form_label_type": "Type",
"slideshow_slide_form_label_type_url": "URL",
"slideshow_slide_form_label_type_video": "Video",
"slideshow_slide_form_label_type_picture": "Picture",
"slideshow_slide_form_label_object": "Object", "slideshow_slide_form_label_object": "Object",
"slideshow_slide_form_label_duration": "Duration", "slideshow_slide_form_label_duration": "Duration",
"slideshow_slide_form_label_duration_unit": "seconds", "slideshow_slide_form_label_duration_unit": "seconds",
@ -128,5 +125,9 @@
"enum_variable_section_player_animation": "Player animation", "enum_variable_section_player_animation": "Player animation",
"enum_variable_section_player_options": "Options du lecteur", "enum_variable_section_player_options": "Options du lecteur",
"enum_application_language_english": "English", "enum_application_language_english": "English",
"enum_application_language_french": "French" "enum_application_language_french": "French",
"enum_slide_type_url": "URL",
"enum_slide_type_video": "Video",
"enum_slide_type_picture": "Picture",
"enum_slide_type_youtube": "Youtube"
} }

View File

@ -22,9 +22,6 @@
"slideshow_slide_form_label_name": "Nom", "slideshow_slide_form_label_name": "Nom",
"slideshow_slide_form_label_location": "Chemin", "slideshow_slide_form_label_location": "Chemin",
"slideshow_slide_form_label_type": "Type", "slideshow_slide_form_label_type": "Type",
"slideshow_slide_form_label_type_url": "URL",
"slideshow_slide_form_label_type_video": "Vidéo",
"slideshow_slide_form_label_type_picture": "Image",
"slideshow_slide_form_label_object": "Objet", "slideshow_slide_form_label_object": "Objet",
"slideshow_slide_form_label_duration": "Durée", "slideshow_slide_form_label_duration": "Durée",
"slideshow_slide_form_label_duration_unit": "secondes", "slideshow_slide_form_label_duration_unit": "secondes",
@ -128,5 +125,9 @@
"enum_variable_section_player_animation": "Animation du lecteur", "enum_variable_section_player_animation": "Animation du lecteur",
"enum_variable_section_player_options": "Options du lecteur", "enum_variable_section_player_options": "Options du lecteur",
"enum_application_language_english": "Anglais", "enum_application_language_english": "Anglais",
"enum_application_language_french": "Français" "enum_application_language_french": "Français",
"enum_slide_type_url": "URL",
"enum_slide_type_video": "Vidéo",
"enum_slide_type_picture": "Image",
"enum_slide_type_youtube": "Youtube"
} }

View File

@ -26,7 +26,6 @@ class FleetController(ObController):
def fleet_screen_list(self): def fleet_screen_list(self):
return render_template( return render_template(
'fleet/list.jinja.html', 'fleet/list.jinja.html',
l=self._model_store.lang().map(),
enabled_screens=self._model_store.screen().get_enabled_screens(), enabled_screens=self._model_store.screen().get_enabled_screens(),
disabled_screens=self._model_store.screen().get_disabled_screens(), disabled_screens=self._model_store.screen().get_disabled_screens(),
) )

View File

@ -51,8 +51,7 @@ class PlayerController(ObController):
ipaddr = get_ip_address() ipaddr = get_ip_address()
return render_template( return render_template(
'player/default.jinja.html', 'player/default.jinja.html',
ipaddr=ipaddr if ipaddr else self._model_store.lang().map().get('common_unknown_ipaddr'), ipaddr=ipaddr if ipaddr else self._model_store.lang().map().get('common_unknown_ipaddr')
l=self._model_store.lang().map()
) )
def player_playlist(self): def player_playlist(self):

View File

@ -15,7 +15,6 @@ class SettingsController(ObController):
def settings_variable_list(self): def settings_variable_list(self):
return render_template( return render_template(
'settings/list.jinja.html', 'settings/list.jinja.html',
l=self._model_store.lang().map(),
system_variables=self._model_store.variable().get_editable_variables(plugin=False), system_variables=self._model_store.variable().get_editable_variables(plugin=False),
plugin_variables=self._model_store.variable().get_editable_variables(plugin=True), plugin_variables=self._model_store.variable().get_editable_variables(plugin=True),
) )

View File

@ -29,11 +29,11 @@ class SlideshowController(ObController):
def slideshow(self): def slideshow(self):
return render_template( return render_template(
'slideshow/list.jinja.html', 'slideshow/list.jinja.html',
l=self._model_store.lang().map(),
enabled_slides=self._model_store.slide().get_enabled_slides(), enabled_slides=self._model_store.slide().get_enabled_slides(),
disabled_slides=self._model_store.slide().get_disabled_slides(), disabled_slides=self._model_store.slide().get_disabled_slides(),
var_last_restart=self._model_store.variable().get_one_by_name('last_restart'), var_last_restart=self._model_store.variable().get_one_by_name('last_restart'),
var_external_url=self._model_store.variable().get_one_by_name('external_url') var_external_url=self._model_store.variable().get_one_by_name('external_url'),
enum_slide_type=SlideType
) )
def slideshow_slide_add(self): def slideshow_slide_add(self):
@ -67,7 +67,13 @@ class SlideshowController(ObController):
return redirect(url_for('slideshow_slide_list')) return redirect(url_for('slideshow_slide_list'))
def slideshow_slide_edit(self): def slideshow_slide_edit(self):
self._model_store.slide().update_form(request.form['id'], request.form['name'], request.form['duration'], request.form['cron_schedule']) self._model_store.slide().update_form(
id=request.form['id'],
name=request.form['name'],
duration=request.form['duration'],
cron_schedule=request.form['cron_schedule'],
location=request.form['location'] if 'location' in request.form else None
)
self._post_update() self._post_update()
return redirect(url_for('slideshow_slide_list')) return redirect(url_for('slideshow_slide_list'))

View File

@ -24,7 +24,6 @@ class SysinfoController(ObController):
return render_template( return render_template(
'sysinfo/list.jinja.html', 'sysinfo/list.jinja.html',
ipaddr=ipaddr if ipaddr else self._model_store.lang().map().get('common_unknown_ipaddr'), ipaddr=ipaddr if ipaddr else self._model_store.lang().map().get('common_unknown_ipaddr'),
l=self._model_store.lang().map(),
ro_variables=self._model_store.variable().get_readonly_variables(), ro_variables=self._model_store.variable().get_readonly_variables(),
env_variables=self._model_store.config().map() env_variables=self._model_store.config().map()
) )

View File

@ -96,7 +96,6 @@ class ObPlugin(abc.ABC):
template = self.get_rendering_env().get_template(template_file) template = self.get_rendering_env().get_template(template_file)
return template.render( return template.render(
l=self._model_store.lang().map(),
request=request, request=request,
url_for=url_for, url_for=url_for,
**parameters, **parameters,

View File

@ -82,12 +82,17 @@ class SlideManager(ModelManager):
for slide_id, slide_position in positions.items(): for slide_id, slide_position in positions.items():
self._db.update_by_id(slide_id, {"position": slide_position}) self._db.update_by_id(slide_id, {"position": slide_position})
def update_form(self, id: str, name: str, duration: int, cron_schedule: Optional[str] = '') -> None: def update_form(self, id: str, name: str, duration: int, cron_schedule: Optional[str] = '', location: Optional[str] = None) -> None:
self._db.update_by_id(id, { form = {
"name": name, "name": name,
"duration": duration, "duration": duration,
"cron_schedule": get_optional_string(cron_schedule) "cron_schedule": get_optional_string(cron_schedule)
}) }
if location is not None and location:
form["location"] = location
self._db.update_by_id(id, form)
def add_form(self, slide: Union[Slide, Dict]) -> None: def add_form(self, slide: Union[Slide, Dict]) -> None:
db_slide = slide db_slide = slide

View File

@ -1,7 +1,7 @@
import json import json
from typing import Optional, Union from typing import Optional, Union
from src.model.enum.SlideType import SlideType from src.model.enum.SlideType import SlideType, SlideInputType
from src.utils import str_to_enum from src.utils import str_to_enum
@ -99,6 +99,7 @@ class Slide:
"enabled": self.enabled, "enabled": self.enabled,
"position": self.position, "position": self.position,
"type": self.type.value, "type": self.type.value,
"is_editable": self.is_editable(),
"duration": self.duration, "duration": self.duration,
"location": self.location, "location": self.location,
"cron_schedule": self.cron_schedule, "cron_schedule": self.cron_schedule,
@ -109,3 +110,9 @@ class Slide:
self.type == SlideType.VIDEO self.type == SlideType.VIDEO
or self.type == SlideType.PICTURE or self.type == SlideType.PICTURE
) )
def get_input_type(self) -> SlideInputType:
return SlideType.get_input(self.type)
def is_editable(self) -> bool:
return SlideInputType.is_editable(self.get_input_type())

View File

@ -1,8 +1,33 @@
from enum import Enum from enum import Enum
class SlideInputType(Enum):
UPLOAD = 'upload'
TEXT = 'text'
@staticmethod
def is_editable(value: Enum) -> bool:
if value == SlideInputType.UPLOAD:
return False
elif value == SlideInputType.TEXT:
return True
class SlideType(Enum): class SlideType(Enum):
PICTURE = 'picture' PICTURE = 'picture'
YOUTUBE = 'youtube'
VIDEO = 'video' VIDEO = 'video'
URL = 'url' URL = 'url'
@staticmethod
def get_input(value: Enum) -> SlideInputType:
if value == SlideType.PICTURE:
return SlideInputType.UPLOAD
elif value == SlideType.VIDEO:
return SlideInputType.UPLOAD
elif value == SlideType.YOUTUBE:
return SlideInputType.TEXT
elif value == SlideType.URL:
return SlideInputType.TEXT

View File

@ -30,7 +30,9 @@ class TemplateRenderer:
LANG=self._model_store.variable().map().get('lang').as_string(), LANG=self._model_store.variable().map().get('lang').as_string(),
HOOK=self._render_hook, HOOK=self._render_hook,
cron_descriptor=self.cron_descriptor, cron_descriptor=self.cron_descriptor,
is_validate_cron_date_time=is_validate_cron_date_time is_validate_cron_date_time=is_validate_cron_date_time,
l=self._model_store.lang().map(),
t=self._model_store.lang().translate,
) )
for hook in HookType: for hook in HookType:
@ -48,7 +50,6 @@ class TemplateRenderer:
os.path.basename(hook_registration.template) os.path.basename(hook_registration.template)
)) ))
content.append(template.render( content.append(template.render(
l=self._model_store.lang().map(),
**self.get_view_globals() **self.get_view_globals()
)) ))
elif isinstance(hook_registration, FunctionalHookRegistration): elif isinstance(hook_registration, FunctionalHookRegistration):

View File

@ -116,13 +116,16 @@
case 'video': case 'video':
loadVideo(element, callbackReady, item); loadVideo(element, callbackReady, item);
break; break;
case 'youtube':
loadYoutube(element, callbackReady, item);
break;
default: default:
loadUrl(element, callbackReady, item); loadUrl(element, callbackReady, item);
break; break;
} }
} }
function loadUrl(element, callbackReady, item) { function loadUrl(element, callbackReady, item, delay) {
element.innerHTML = `<iframe src="${item.location}"></iframe>`; element.innerHTML = `<iframe src="${item.location}"></iframe>`;
callbackReady(function () {}); callbackReady(function () {});
} }
@ -132,6 +135,15 @@
callbackReady(function () {}); callbackReady(function () {});
} }
function loadYoutube(element, callbackReady, item) {
element.innerHTML = ``;
callbackReady(function () {});
setTimeout(function() {
element.innerHTML = `<iframe src="https://www.youtube.com/embed/HfWhaPEH-Ck?version=3&autoplay=1&showinfo=0&controls=0&modestbranding=1&fs=1&rel=0" frameborder="0" allow="autoplay" allowfullscreen></iframe>`;
}, Math.max(100, duration - 2000));
}
function loadVideo(element, callbackReady, item) { function loadVideo(element, callbackReady, item) {
element.innerHTML = `<video><source src=${item.location} type="video/mp4" /></video>`; element.innerHTML = `<video><source src=${item.location} type="video/mp4" /></video>`;
var video = element.querySelector('video'); var video = element.querySelector('video');

View File

@ -14,9 +14,12 @@
<label for="slide-add-type">{{ l.slideshow_slide_form_label_type }}</label> <label for="slide-add-type">{{ l.slideshow_slide_form_label_type }}</label>
<div class="widget"> <div class="widget">
<select name="type" id="slide-add-type"> <select name="type" id="slide-add-type">
<option value="url" data-input="text">{{ l.slideshow_slide_form_label_type_url }}</option> {% for type in enum_slide_type %}
<option value="video" data-input="upload">{{ l.slideshow_slide_form_label_type_video }}</option> {% set input_type = enum_slide_type.get_input(type) %}
<option value="picture" data-input="upload">{{ l.slideshow_slide_form_label_type_picture }}</option> <option value="{{ type.value }}" data-input="{{ input_type.value }}">
{{ t(type) }}
</option>
{% endfor %}
</select> </select>
</div> </div>
</div> </div>

View File

@ -16,9 +16,11 @@
<label for="slide-edit-type">{{ l.slideshow_slide_form_label_type }}</label> <label for="slide-edit-type">{{ l.slideshow_slide_form_label_type }}</label>
<div class="widget"> <div class="widget">
<select id="slide-edit-type" name="type" disabled="disabled"> <select id="slide-edit-type" name="type" disabled="disabled">
<option value="url" data-input="text">{{ l.slideshow_slide_form_label_type_url }}</option> {% for type in enum_slide_type %}
<option value="video" data-input="upload">{{ l.slideshow_slide_form_label_type_video }}</option> <option value="{{ type.value }}" data-input="{% if type.value == 'url' or type.value == 'youtube' %}text{% else %}upload{% endif %}">
<option value="picture" data-input="upload">{{ l.slideshow_slide_form_label_type_picture }}</option> {{ t(type) }}
</option>
{% endfor %}
</select> </select>
</div> </div>
</div> </div>
@ -26,7 +28,7 @@
<div class="form-group"> <div class="form-group">
<label for="slide-edit-location">{{ l.slideshow_slide_form_label_location }}</label> <label for="slide-edit-location">{{ l.slideshow_slide_form_label_location }}</label>
<div class="widget"> <div class="widget">
<input type="text" name="location" id="slide-edit-location" disabled="disabled" /> <input type="text" name="location" id="slide-edit-location" />
</div> </div>
</div> </div>