Merge pull request #95 from jr-k/develop

Release v1.21.2
This commit is contained in:
JRK 2024-07-03 14:31:36 +02:00 committed by GitHub
commit 693229ceac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 162 additions and 30 deletions

File diff suppressed because one or more lines are too long

View File

@ -56,6 +56,28 @@ jQuery(document).ready(function ($) {
});
};
const inputTypeUpdate = function () {
const $modal = $('.modal-slide:visible');
const $el = $('#slide-add-type');
const value = $el.val();
const inputType = $el.find('option').filter(function (i, el) {
return $(el).val() === value;
}).data('input');
if ($modal.find('.picker').length === 0) {
$modal.find('.upload').find('input, select').prop('disabled', false);
}
$('.slide-add-object-input')
.addClass('hidden')
.prop('disabled', true)
.filter('#slide-add-object-input-' + inputType)
.removeClass('hidden')
.prop('disabled', false)
;
};
const inputSchedulerUpdate = function() {
const $modal = $('.modal-slide:visible');
const $scheduleStartGroup = $modal.find('.slide-schedule-group');
@ -187,9 +209,19 @@ jQuery(document).ready(function ($) {
inputSchedulerUpdate();
});
$(document).on('change', '#slide-add-type', inputTypeUpdate);
$(document).on('click', '.picker button', function () {
const $parent = $(this).parents('.modal-slide-add');
$parent.find('.picker').remove();
$parent.find('.upload').removeClass('hidden');
inputTypeUpdate();
});
$(document).on('click', '.slide-add', function () {
showModal('modal-slide-add');
loadDateTimePicker($('.modal-slide-add .datetimepicker'))
inputTypeUpdate();
inputSchedulerUpdate();
inputContentUpdate();
$('.modal-slide-add input:eq(0)').focus().select();

View File

@ -18,3 +18,10 @@
a {
text-decoration: none;
}
.col {
display: flex;
flex: 1;
flex-direction: column;
align-self: stretch;
}

View File

@ -23,6 +23,8 @@
"slideshow_slide_form_section_content": "Media",
"slideshow_slide_form_section_scheduling": "Scheduling",
"slideshow_slide_form_label_name": "Name",
"slideshow_slide_form_label_add_content": "Add to library",
"slideshow_slide_form_label_from_library": "From library",
"slideshow_slide_form_label_content_id": "Content",
"slideshow_slide_form_label_location": "Location",
"slideshow_slide_form_label_type": "Type",

View File

@ -23,6 +23,8 @@
"slideshow_slide_form_section_content": "Medios",
"slideshow_slide_form_section_scheduling": "Programación",
"slideshow_slide_form_label_name": "Nombre",
"slideshow_slide_form_label_add_content": "Agregar a la biblioteca",
"slideshow_slide_form_label_from_library": "Dalla biblioteca",
"slideshow_slide_form_label_content_id": "Contenido",
"slideshow_slide_form_label_location": "Ubicación",
"slideshow_slide_form_label_type": "Tipo",

View File

@ -23,6 +23,8 @@
"slideshow_slide_form_section_content": "Media",
"slideshow_slide_form_section_scheduling": "Programmation",
"slideshow_slide_form_label_name": "Nom",
"slideshow_slide_form_label_add_content": "Ajouter à la bibliothèque",
"slideshow_slide_form_label_from_library": "Depuis la bibliothèque",
"slideshow_slide_form_label_content_id": "Contenu",
"slideshow_slide_form_label_location": "Chemin",
"slideshow_slide_form_label_type": "Type",

View File

@ -23,6 +23,8 @@
"slideshow_slide_form_section_content": "Media",
"slideshow_slide_form_section_scheduling": "Programmazione",
"slideshow_slide_form_label_name": "Nome",
"slideshow_slide_form_label_add_content": "Aggiunta alla biblioteca",
"slideshow_slide_form_label_from_library": "Dalla biblioteca",
"slideshow_slide_form_label_content_id": "Contenuti",
"slideshow_slide_form_label_location": "Posizione",
"slideshow_slide_form_label_type": "Tipo",

View File

@ -29,35 +29,18 @@ class ContentController(ObController):
)
def slideshow_content_add(self):
content = Content(
self._model_store.content().add_form_raw(
name=request.form['name'],
type=str_to_enum(request.form['type'], ContentType),
request_files=request.files,
upload_dir=self._app.config['UPLOAD_FOLDER'],
location=request.form['object'] if 'object' in request.form else None
)
if content.has_file():
if 'object' not in request.files:
return redirect(request.url)
object = request.files['object']
if object.filename == '':
return redirect(request.url)
if object:
object_name = randomize_filename(object.filename)
object_path = os.path.join(self._app.config['UPLOAD_FOLDER'], object_name)
object.save(object_path)
content.location = object_path
else:
content.location = request.form['object']
self._model_store.content().add_form(content)
self._post_update()
return redirect(url_for('slideshow_content_list'))
def slideshow_content_edit(self):
content = self._model_store.content().update_form(
self._model_store.content().update_form(
id=request.form['id'],
name=request.form['name'],
location=request.form['location'] if 'location' in request.form and request.form['location'] else None

View File

@ -6,6 +6,7 @@ from flask import Flask, render_template, redirect, request, url_for, send_from_
from werkzeug.utils import secure_filename
from src.service.ModelStore import ModelStore
from src.model.entity.Slide import Slide
from src.model.enum.ContentType import ContentType
from src.interface.ObController import ObController
from src.util.utils import str_to_enum, get_optional_string
from src.util.UtilFile import randomize_filename
@ -38,11 +39,23 @@ class SlideController(ObController):
disabled_slides=self._model_store.slide().get_slides(playlist_id=playlist_id, enabled=False),
var_last_restart=self._model_store.variable().get_one_by_name('last_restart'),
contents={content.id: content.name for content in self._model_store.content().get_contents()},
enum_content_type=ContentType
)
def slideshow_slide_add(self):
content = None
if 'type' in request.form:
content = self._model_store.content().add_form_raw(
name=request.form['name'],
type=str_to_enum(request.form['type'], ContentType),
request_files=request.files,
upload_dir=self._app.config['UPLOAD_FOLDER'],
location=request.form['object'] if 'object' in request.form else None
)
slide = Slide(
content_id=request.form['content_id'],
content_id=content.id if content else request.form['content_id'],
duration=request.form['duration'],
is_notification=True if 'is_notification' in request.form else False,
playlist_id=request.form['playlist_id'] if 'playlist_id' in request.form and request.form['playlist_id'] else None,

View File

@ -11,12 +11,14 @@ from src.manager.LangManager import LangManager
from src.manager.UserManager import UserManager
from src.manager.VariableManager import VariableManager
from src.service.ModelManager import ModelManager
from src.util.UtilFile import randomize_filename
class ContentManager(ModelManager):
TABLE_NAME = "content"
TABLE_MODEL = [
"uuid CHAR(255)",
"name CHAR(255)",
"type CHAR(30)",
"location TEXT",
@ -137,6 +139,32 @@ class ContentManager(ModelManager):
self._db.add(self.TABLE_NAME, self.pre_add(form))
self.post_add(content.id)
def add_form_raw(self, name: str, type: ContentType, request_files: Optional[Dict], upload_dir: str, location: Optional[str] = None) -> Content:
content = Content(
name=name,
type=type
)
if content.has_file():
if 'object' not in request_files:
return redirect(request.url)
object = request_files['object']
if object.filename == '':
return None
if object:
object_name = randomize_filename(object.filename)
object_path = os.path.join(upload_dir, object_name)
object.save(object_path)
content.location = object_path
else:
content.location = location
self.add_form(content)
return self.get_one_by(query="uuid = '{}'".format(content.uuid))
def delete(self, id: int) -> None:
content = self.get(id)

View File

@ -216,6 +216,7 @@ class DatabaseManager:
"DROP TABLE IF EXISTS fleet_studio",
"ALTER TABLE slideshow RENAME TO slides",
"DELETE FROM settings WHERE name = 'fleet_studio_enabled'",
"UPDATE content SET uuid = id WHERE uuid = '' or uuid is null",
]
for query in queries:

View File

@ -1,5 +1,6 @@
import json
import time
import uuid
from typing import Optional, Union
from src.model.enum.ContentType import ContentType, ContentInputType
@ -8,7 +9,8 @@ from src.util.utils import str_to_enum
class Content:
def __init__(self, location: str = '', type: Union[ContentType, str] = ContentType.URL, name: str = 'Untitled', id: Optional[int] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None):
def __init__(self, uuid: str = '', location: str = '', type: Union[ContentType, str] = ContentType.URL, name: str = 'Untitled', id: Optional[int] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None):
self._uuid = uuid if uuid else self.generate_and_set_uuid()
self._id = id if id else None
self._location = location
self._type = str_to_enum(type, ContentType) if isinstance(type, str) else type
@ -18,10 +20,23 @@ class Content:
self._created_at = int(created_at if created_at else time.time())
self._updated_at = int(updated_at if updated_at else time.time())
def generate_and_set_uuid(self) -> str:
self._uuid = str(uuid.uuid4())
return self._uuid
@property
def id(self) -> Optional[int]:
return self._id
@property
def uuid(self) -> str:
return self._uuid
@uuid.setter
def uuid(self, value: str):
self._uuid = value
@property
def location(self) -> str:
return self._location
@ -81,6 +96,7 @@ class Content:
def __str__(self) -> str:
return f"Content(" \
f"id='{self.id}',\n" \
f"uuid='{self.uuid}',\n" \
f"name='{self.name}',\n" \
f"type='{self.type}',\n" \
f"location='{self.location}',\n" \
@ -101,6 +117,7 @@ class Content:
def to_dict(self, with_virtual: bool = False) -> dict:
content = {
"id": self.id,
"uuid": self.uuid,
"name": self.name,
"type": self.type.value,
"location": self.location,

View File

@ -1 +1 @@
1.21.1
1.21.2

View File

@ -13,11 +13,54 @@
<input name="playlist_id" type="hidden" id="slide-add-playlist-id" value="{{ current_playlist.id }}">
{% endif %}
<div class="form-group slide-content-id-group">
<label for="slide-add-content-id">{{ l.slideshow_slide_form_label_content_id }}</label>
<select name="content_id" type="text" id="slide-add-content-id" required="required">
<div class="picker col">
<div class="form-group slide-content-id-group">
<label for="slide-add-content-id">{{ l.slideshow_slide_form_label_content_id }}</label>
<div class="widget">
<select name="content_id" type="text" id="slide-add-content-id" required="required"></select>
</div>
</div>
<div class="form-group content-new-group">
<label for=""></label>
<div class="widget">
<button class="btn purple" style="margin:0;">
<i class="fa fa-plus icon-left"></i>{{ l.slideshow_slide_form_label_add_content }}
</button>
</div>
</div>
</div>
<div class="upload col hidden">
<div class="form-group">
<label for="slide-add-name">{{ l.slideshow_slide_form_label_name }}</label>
<div class="widget">
<input name="name" type="text" id="slide-add-name" required="required" disabled="disabled" />
</div>
</div>
<div class="form-group">
<label for="slide-add-type">{{ l.slideshow_slide_form_label_type }}</label>
<div class="widget">
<select name="type" id="slide-add-type" disabled="disabled">
{% for type in enum_content_type %}
{% set input_type = enum_content_type.get_input(type) %}
<option value="{{ type.value }}" data-input="{{ input_type.value }}">
{{ t(type) }}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group object-input">
<label for="slide-add-duration">{{ l.slideshow_slide_form_label_object }}</label>
<div class="widget">
<input type="text" name="object" id="slide-add-object-input-text" class="slide-add-object-input" disabled="disabled" />
<input type="file" name="object" id="slide-add-object-input-upload" class="slide-add-object-input hidden" disabled="disabled" />
</div>
</div>
</select>
</div>
<h3>