commit
693229ceac
File diff suppressed because one or more lines are too long
@ -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();
|
||||
|
||||
@ -18,3 +18,10 @@
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.col {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-self: stretch;
|
||||
}
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -1 +1 @@
|
||||
1.21.1
|
||||
1.21.2
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user