wip
This commit is contained in:
parent
e2ba157fdc
commit
d3ef3c16a2
File diff suppressed because one or more lines are too long
BIN
data/www/img/logo3.png
Normal file
BIN
data/www/img/logo3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@ -105,7 +105,7 @@ jQuery(function ($) {
|
||||
route = $(this).attr('data-entity-route') + '?id=' + $item.attr('data-id');
|
||||
}
|
||||
|
||||
if (confirm(l.common_are_you_sure)) {
|
||||
if (confirm(l.js_common_are_you_sure)) {
|
||||
document.location.href = route;
|
||||
}
|
||||
});
|
||||
@ -134,8 +134,14 @@ jQuery(function ($) {
|
||||
selectEpxlrLink(verticalNeighbors.above.find('.explr-link'));
|
||||
} else if (e.key === "ArrowDown" && verticalNeighbors.below) {
|
||||
selectEpxlrLink(verticalNeighbors.below.find('.explr-link'));
|
||||
} else if (e.key === "Backspace") {
|
||||
if ($('.explr-item-delete:visible').length) {
|
||||
$('.explr-item-delete:visible').click();
|
||||
}
|
||||
}
|
||||
} else if (e.key.indexOf('Arrow') === 0) {
|
||||
selectEpxlrLink($('.explr-dirview li:visible:eq(0)').find('.explr-link'));
|
||||
}
|
||||
});
|
||||
|
||||
// Explorer item selection
|
||||
|
||||
@ -18,7 +18,7 @@ const hideDropdowns = function () {
|
||||
const explrSidebarOpenFromFolder = function (folderId) {
|
||||
const $leaf = $('.li-explr-folder-' + folderId);
|
||||
let $parent = $leaf;
|
||||
while($parent.length > 0) {
|
||||
while ($parent.length > 0) {
|
||||
const $toggler = $parent.find('.explr-toggler:eq(0)');
|
||||
if ($toggler.hasClass('explr-plus')) {
|
||||
$parent.find('.explr-toggler:eq(0)').trigger('click');
|
||||
@ -112,7 +112,7 @@ jQuery(document).ready(function ($) {
|
||||
$('#entity-utrack-updated-at').val(prettyTimestamp(entity.updated_at * 1000));
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
$('.alert-timeout').remove();
|
||||
}, 3000);
|
||||
|
||||
@ -122,5 +122,17 @@ jQuery(document).ready(function ($) {
|
||||
$firstInputText.focus();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('click', '.copy-link', function (e) {
|
||||
e.preventDefault();
|
||||
const $input = $('#' + $(this).attr('data-target-id'));
|
||||
$input.select();
|
||||
$input[0].setSelectionRange(0, 99999);
|
||||
document.execCommand("copy");
|
||||
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText($input.val());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -159,10 +159,8 @@
|
||||
.find('ul') // hide every ul
|
||||
.hide()
|
||||
.end()
|
||||
.find('.explr-expand') // unless explicitly set to expand
|
||||
.show()
|
||||
.siblings('.explr-toggler')
|
||||
.addClass('explr-minus '+opts.classesMinus);
|
||||
.find('.explr-toggler')
|
||||
.addClass('explr-plus '+opts.classesPlus);
|
||||
} else {
|
||||
$tree
|
||||
.find('.explr-collapse') // hide every element set to collapse
|
||||
|
||||
1
data/www/js/lib/qrcode.min.js
vendored
Normal file
1
data/www/js/lib/qrcode.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,76 +1,24 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
const $tableActive = $('table.active-playlists');
|
||||
const $tableInactive = $('table.inactive-playlists');
|
||||
|
||||
const getId = function ($el) {
|
||||
return $el.is('tr') ? $el.attr('data-level') : $el.parents('tr:eq(0)').attr('data-level');
|
||||
};
|
||||
|
||||
const updateTable = function () {
|
||||
$('table').each(function () {
|
||||
if ($(this).find('tbody tr.playlist-item:visible').length === 0) {
|
||||
$(this).find('tr.empty-tr').removeClass('hidden');
|
||||
} else {
|
||||
$(this).find('tr.empty-tr').addClass('hidden');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const main = function () {
|
||||
const qrcodeElement = document.getElementById('qrcode');
|
||||
|
||||
};
|
||||
|
||||
$(document).on('change', 'input[type=checkbox]', function () {
|
||||
$.ajax({
|
||||
url: '/playlist/toggle',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
data: JSON.stringify({id: getId($(this)), enabled: $(this).is(':checked')}),
|
||||
method: 'POST',
|
||||
if (qrcodeElement) {
|
||||
new QRCode(qrcodeElement, {
|
||||
text: qrcodeElement.attributes['data-qrcode-payload'].value,
|
||||
width: 128,
|
||||
height: 128,
|
||||
colorDark: '#222',
|
||||
colorLight: '#fff',
|
||||
correctLevel: QRCode.CorrectLevel.H
|
||||
});
|
||||
|
||||
const $tr = $(this).parents('tr:eq(0)').remove().clone();
|
||||
|
||||
if ($(this).is(':checked')) {
|
||||
$tableActive.append($tr);
|
||||
} else {
|
||||
$tableInactive.append($tr);
|
||||
}
|
||||
|
||||
updateTable();
|
||||
});
|
||||
};
|
||||
|
||||
$(document).on('click', '.playlist-add', function () {
|
||||
showModal('modal-playlist-add');
|
||||
$('.modal-playlist-add input:eq(0)').focus().select();
|
||||
});
|
||||
|
||||
$(document).on('click', '.playlist-edit', function () {
|
||||
const playlist = JSON.parse($(this).parents('tr:eq(0)').attr('data-entity'));
|
||||
showModal('modal-playlist-edit');
|
||||
$('.modal-playlist-edit input:visible:eq(0)').focus().select();
|
||||
$('#playlist-edit-name').val(playlist.name);
|
||||
$('#playlist-edit-time-sync').val(playlist.time_sync ? '1' : '0');
|
||||
$('#playlist-edit-id').val(playlist.id);
|
||||
});
|
||||
|
||||
$(document).on('click', '.playlist-delete', function () {
|
||||
if (confirm(l.js_playlist_delete_confirmation)) {
|
||||
const $tr = $(this).parents('tr:eq(0)');
|
||||
$.ajax({
|
||||
method: 'DELETE',
|
||||
url: '/playlist/delete',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
data: JSON.stringify({id: getId($(this))}),
|
||||
success: function(data) {
|
||||
$tr.remove();
|
||||
updateTable();
|
||||
},
|
||||
error: function(data) {
|
||||
$('.alert-error').html(data.responseJSON.message).removeClass('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
main();
|
||||
});
|
||||
|
||||
@ -36,7 +36,7 @@ main {
|
||||
margin-right: 20px;
|
||||
|
||||
.trigger {
|
||||
color: white;
|
||||
color: $white;
|
||||
|
||||
.avatar {
|
||||
width: 32px;
|
||||
|
||||
@ -28,6 +28,15 @@ body, html {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.vertical {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
@ -51,7 +60,7 @@ main {
|
||||
border-bottom: $layoutBorder;
|
||||
|
||||
h1 {
|
||||
color: white;
|
||||
color: $white;
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
}
|
||||
@ -63,16 +72,13 @@ main {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.btn,
|
||||
button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alert {
|
||||
|
||||
}
|
||||
|
||||
.bottom-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -103,7 +103,7 @@ menu {
|
||||
padding-left: 10px;
|
||||
|
||||
i {
|
||||
color: white;
|
||||
color: $white;
|
||||
opacity: .2;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
@ -119,7 +119,7 @@ menu {
|
||||
}
|
||||
|
||||
&:after {
|
||||
background: white;
|
||||
background: $white;
|
||||
content: "";
|
||||
height: 195px;
|
||||
left: -200px;
|
||||
@ -156,11 +156,11 @@ menu {
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
color: $white;
|
||||
font-weight: bold;
|
||||
|
||||
i {
|
||||
color: white;
|
||||
color: $white;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,13 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
color: $white;
|
||||
text-align: center;
|
||||
padding: 0 3px;
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ button,
|
||||
$shadowOffset: 2px;
|
||||
|
||||
position: relative;
|
||||
padding: 10px 13px 8px 10px;
|
||||
padding: 10px 10px 8px 10px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
@ -35,15 +35,48 @@ button,
|
||||
color: #AAA;
|
||||
background: $neutralGrey;
|
||||
box-shadow: 0 $shadowOffset 0 0 darken($neutralGrey, 10%);
|
||||
&:hover { box-shadow: 0 $shadowOffset 0 1px #222 inset; background: darken($neutralGrey, 10%); }
|
||||
&:focus { background: darken($neutralGrey, 20%); }
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 $shadowOffset 0 1px #222 inset;
|
||||
background: darken($neutralGrey, 10%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: darken($neutralGrey, 20%);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-wire-neutral {
|
||||
background: transparent;
|
||||
border: 2px solid $neutralGrey;
|
||||
color: rgba($white, .8);
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
background: rgba($neutralGrey, 0.05);
|
||||
border-color: darken($neutralGrey, 10%);
|
||||
color: darken($neutralGrey, 10%);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: darken($neutralGrey, 20%);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-naked {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
&:hover { box-shadow: 0 $shadowOffset 0 1px #222 inset; background: darken($neutralGrey, 10%); }
|
||||
&:focus { background: darken($neutralGrey, 20%); }
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 $shadowOffset 0 1px #222 inset;
|
||||
background: darken($neutralGrey, 10%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: darken($neutralGrey, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
a {
|
||||
padding: 8px 16px 8px 8px;
|
||||
color: white;
|
||||
color: $white;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
@ -7,3 +7,18 @@ span.empty {
|
||||
padding: 2px 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.inner-empty {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 90px;
|
||||
opacity: 0.3;
|
||||
text-shadow: 0 -1px #333, 0 0px .5px #444;
|
||||
}
|
||||
}
|
||||
@ -19,11 +19,11 @@ ul.explr-tree {
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
color: $white;
|
||||
padding-right: 80px;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
||||
@ -36,9 +36,21 @@
|
||||
|
||||
h3 {
|
||||
align-self: stretch;
|
||||
border-bottom: 1px solid $lightGrey;
|
||||
padding: 15px 15px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
color: white;
|
||||
padding-bottom: 10px;
|
||||
text-decoration: none;
|
||||
|
||||
&.divide {
|
||||
border-top: 1px solid #222;
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,16 +118,16 @@ table.panes {
|
||||
|
||||
td {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
color: $white;
|
||||
|
||||
i.icon-legend {
|
||||
color: white;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
span,
|
||||
i.icon-value {
|
||||
background-color: rgba($white, .3);
|
||||
color: white;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&.description {
|
||||
|
||||
@ -31,7 +31,7 @@ ul.pills {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
color: $white;
|
||||
overflow: hidden;
|
||||
padding-right: 30px;
|
||||
text-align: center;
|
||||
|
||||
@ -1,116 +1,66 @@
|
||||
.pure-material-switch {
|
||||
z-index: 0;
|
||||
$toggleActiveColor: $limeGreen;
|
||||
$containerWidth: 42px;
|
||||
$containerHeight: 26px;
|
||||
$containerRadius: 15px;
|
||||
$containerShadowActive: 0 2px 2px #222 inset;
|
||||
$containerShadowInactive: 0 2px 2px #111 inset;
|
||||
$backgroundColorInactive: #222;
|
||||
$backgroundColorActive: darken($toggleActiveColor, 30%);
|
||||
$thumbColorActive: $toggleActiveColor;
|
||||
$thumbColorInactive: #777;
|
||||
$thumbWidth: 18px;
|
||||
$thumbHeight: $thumbWidth;
|
||||
$borderSize: 1px;
|
||||
$animationSpeed: 0.2s;
|
||||
|
||||
.toggle {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.pure-material-switch > input {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
z-index: -1;
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: -8px;
|
||||
input {
|
||||
display: none;
|
||||
|
||||
&:checked + label {
|
||||
background: darken($thumbColorActive, 30%);
|
||||
border: $borderSize solid rgba($white, .1);
|
||||
box-shadow: $containerShadowActive;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
margin: 0;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: rgba($black, 0.38);
|
||||
outline: none;
|
||||
opacity: 0;
|
||||
transform: scale(1);
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s 0.1s, transform 0.2s 0.1s;
|
||||
}
|
||||
margin-left: calc($containerWidth - 21px);
|
||||
width: $thumbWidth;
|
||||
height: $thumbHeight;
|
||||
transition: $animationSpeed;
|
||||
background: $thumbColorActive;
|
||||
box-shadow: 0 2px darken($thumbColorActive, 40%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pure-material-switch > span {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
label {
|
||||
width: $containerWidth + ($borderSize * 2);
|
||||
height: $containerHeight;
|
||||
border-radius: $containerRadius;
|
||||
background: $backgroundColorInactive;
|
||||
cursor: pointer;
|
||||
}
|
||||
border: $borderSize solid rgba($white, .1);
|
||||
box-shadow: $containerShadowInactive;
|
||||
|
||||
.pure-material-switch > span::before {
|
||||
&::after {
|
||||
content: "";
|
||||
float: right;
|
||||
display: inline-block;
|
||||
margin: 5px 0 5px 10px;
|
||||
border-radius: 7px;
|
||||
width: 36px;
|
||||
height: 14px;
|
||||
background-color: rgba($black, 0.38);
|
||||
vertical-align: top;
|
||||
transition: background-color 0.2s, opacity 0.2s;
|
||||
}
|
||||
|
||||
.pure-material-switch > span::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 16px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: $white;
|
||||
box-shadow: 0 3px 1px -2px rgba($black, 0.2), 0 2px 2px 0 rgba($black, 0.14), 0 1px 5px 0 rgba($black, 0.12);
|
||||
transition: background-color 0.2s, transform 0.2s;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:checked {
|
||||
right: -10px;
|
||||
background-color: $limeGreen;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:checked + span::before {
|
||||
background-color: rgba($limeGreen, 0.6);
|
||||
}
|
||||
|
||||
.pure-material-switch > input:checked + span::after {
|
||||
background-color: $limeGreen;
|
||||
transform: translateX(16px);
|
||||
}
|
||||
|
||||
.pure-material-switch:hover > input {
|
||||
opacity: 0.04;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:focus {
|
||||
opacity: 0.12;
|
||||
}
|
||||
|
||||
.pure-material-switch:hover > input:focus {
|
||||
opacity: 0.16;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:active {
|
||||
opacity: 1;
|
||||
transform: scale(0);
|
||||
transition: transform 0s, opacity 0s;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:active + span::before {
|
||||
background-color: rgba($limeGreen, 0.6);
|
||||
}
|
||||
|
||||
.pure-material-switch > input:checked:active + span::before {
|
||||
background-color: rgba($black, 0.38);
|
||||
}
|
||||
|
||||
.pure-material-switch > input:disabled {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:disabled + span {
|
||||
color: $black;
|
||||
opacity: 0.38;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pure-material-switch > input:disabled + span::before {
|
||||
background-color: rgba($black, 0.38);
|
||||
}
|
||||
|
||||
.pure-material-switch > input:checked:disabled + span::before {
|
||||
background-color: rgba($limeGreen, 0.6);
|
||||
width: $thumbWidth;
|
||||
height: $thumbHeight;
|
||||
margin: 3px;
|
||||
background: $thumbColorInactive;
|
||||
box-shadow: 0 2px rgba(0,0,0,0.9);
|
||||
transition: $animationSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
117
data/www/scss/components/_tiles.scss
Normal file
117
data/www/scss/components/_tiles.scss
Normal file
@ -0,0 +1,117 @@
|
||||
.tiles {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
|
||||
.tiles-inner {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
padding: 2px;
|
||||
|
||||
.tiles-empty {
|
||||
|
||||
}
|
||||
|
||||
.tile-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background: #222;
|
||||
align-self: stretch;
|
||||
color: $white;
|
||||
margin: 1px;
|
||||
padding: 15px;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background: #111;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.disabled {
|
||||
|
||||
.tile-header {
|
||||
.head-icon {
|
||||
i {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tile-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
|
||||
|
||||
.head-icon {
|
||||
flex: 1;
|
||||
|
||||
i {
|
||||
font-size: 6px;
|
||||
color: white;
|
||||
opacity: .8;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.status-icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tile-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0.8px;
|
||||
line-height: 22px;
|
||||
margin: 0 0 0 10px;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.tile-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
|
||||
.foot-span {
|
||||
opacity: .8;
|
||||
font-size: 13px;
|
||||
font-family: "Courier New";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
.form-holder {
|
||||
min-width: 686px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
flex: 1;
|
||||
|
||||
form {
|
||||
max-width: 434px;
|
||||
@ -24,8 +24,9 @@ form {
|
||||
font-size: 14px;
|
||||
margin: 0 0 25px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
@ -47,7 +48,7 @@ form {
|
||||
color: #666666;
|
||||
|
||||
&.btn-upload {
|
||||
color: white;
|
||||
color: $white;
|
||||
font-size: 14px;
|
||||
flex: 0;
|
||||
flex-basis: auto;
|
||||
@ -169,9 +170,24 @@ form {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
&.form-group-horizontal {
|
||||
margin: 10px 0 20px 0;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.widget {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
@ -191,5 +207,13 @@ form {
|
||||
margin-right: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
&.actions-center {
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,5 +84,5 @@ header nav ul li a {
|
||||
|
||||
header nav ul li a:hover,
|
||||
header nav ul li.active a {
|
||||
color: white;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
@ -23,8 +23,9 @@
|
||||
|
||||
// Legacy
|
||||
@import 'components/panes';
|
||||
@import 'components/tiles';
|
||||
@import 'components/empty';
|
||||
//@import 'components/switches';
|
||||
@import 'components/switches';
|
||||
//@import 'components/cards';
|
||||
//@import 'components/badges';
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
.page-panel.right-panel {
|
||||
flex: 1;
|
||||
flex: 2;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -29,7 +29,7 @@
|
||||
padding: 20px;
|
||||
|
||||
h3 {
|
||||
color: white;
|
||||
color: $white;
|
||||
padding: 10px 10px 10px 0;
|
||||
margin-bottom: 20px;
|
||||
font-size: 16px;
|
||||
|
||||
@ -1,28 +1,155 @@
|
||||
|
||||
.view-playlist-list main .main-container {
|
||||
|
||||
.modal-playlist-qrcode {
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qrcode-pic {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
img {
|
||||
border: 4px solid #555;
|
||||
border-radius: $baseRadius;
|
||||
}
|
||||
}
|
||||
|
||||
.view-playlist-edit main .main-container {
|
||||
}
|
||||
|
||||
.bottom-content {
|
||||
.page-content {
|
||||
flex: 1;
|
||||
|
||||
&.with-right-panel {
|
||||
flex: 0.5;
|
||||
}
|
||||
|
||||
.inner {
|
||||
padding: 0;
|
||||
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #DDD;
|
||||
text-decoration: none;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.form-holder {
|
||||
margin: 20px 10px 20px 20px;
|
||||
border-right: 1px solid #222;
|
||||
padding-right: 20px;
|
||||
flex: 1.3;
|
||||
|
||||
form {
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-holder {
|
||||
margin: 20px 20px 20px 10px;
|
||||
flex: 1;
|
||||
|
||||
.form-group {
|
||||
flex-grow: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
.widget {
|
||||
a,
|
||||
.btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
border: none;
|
||||
background: #000;
|
||||
border-radius: $baseRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-panel.right-panel {
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
color: white;
|
||||
padding-bottom: 10px;
|
||||
text-decoration: none;
|
||||
|
||||
&.divide {
|
||||
border-top: 1px solid #222;
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.qrcode-pic {
|
||||
margin-top: 10px;
|
||||
img {
|
||||
border: 1px dashed #555;
|
||||
padding: 5px;
|
||||
border-radius: $baseRadius;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
background: black;
|
||||
border: 1px solid rgba($white, .3);
|
||||
border-radius: $baseRadius;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
margin: 10px 0 20px 0;
|
||||
height: 300px;
|
||||
|
||||
iframe {
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slides-holder {
|
||||
margin-top: 40px;
|
||||
border-top: 1px solid #222;
|
||||
align-self: stretch;
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-panel.left-panel {
|
||||
flex: 0.3;
|
||||
max-width: initial;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -58,6 +58,29 @@
|
||||
background: darken($color, 20%);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-wire-#{"#{$name}"} {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border: 2px solid $color;
|
||||
color: rgba($white, .8);
|
||||
|
||||
i.btn-match {
|
||||
color: $color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba($color, 0.05);
|
||||
border-color: darken($color, 10%);
|
||||
color: darken($color, 10%);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: darken($color, 20%);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
lang/en.json
18
lang/en.json
@ -68,8 +68,12 @@
|
||||
"js_slideshow_content_delete_confirmation": "Are you sure?",
|
||||
|
||||
"playlist_page_title": "Playlists",
|
||||
"playlist_button_add": "Add a playlist",
|
||||
"playlist_panel_active": "Active playlists",
|
||||
"playlist_button_add": "Add Playlist",
|
||||
"playlist_button_delete": "Delete Playlist",
|
||||
"playlist_panel_about_playlist": "About playlist",
|
||||
"playlist_panel_content_management": "Content management",
|
||||
"playlist_panel_preview": "Playlist preview",
|
||||
"playlist_panel_preview_action": "Preview",
|
||||
"playlist_panel_inactive": "Inactive playlists",
|
||||
"playlist_panel_empty": "Currently, there are no playlists. %link% now.",
|
||||
"playlist_panel_th_name": "Name",
|
||||
@ -78,10 +82,12 @@
|
||||
"playlist_panel_th_activity": "Options",
|
||||
"playlist_form_add_title": "Add Playlist",
|
||||
"playlist_form_add_submit": "Add",
|
||||
"playlist_form_edit_title": "Edit Playlist",
|
||||
"playlist_form_edit_submit": "Save",
|
||||
"playlist_form_preview_url_desc": "You can use this link to play this playlist on any browser you want. Use copy button to get that in your clipboard.",
|
||||
"playlist_form_preview_qrcode_desc": "You can easily access your playlist using a tablet or phone. Just scan the QR code to begin.",
|
||||
"playlist_form_preview_iframe_desc": "You can view the playlist without leaving this screen by starting the preview from here.",
|
||||
"playlist_form_label_name": "Enter playlist name",
|
||||
"playlist_form_label_time_sync": "Sync slides across players",
|
||||
"playlist_form_label_enabled": "Enable/Disable playlist",
|
||||
"playlist_form_button_cancel": "Cancel",
|
||||
"js_playlist_delete_confirmation": "Are you sure?",
|
||||
"playlist_delete_has_slides": "Playlist has slides, please remove them before and retry",
|
||||
@ -165,7 +171,7 @@
|
||||
"settings_variable_desc_edition_auth_enabled": "Default user credentials will be admin/admin",
|
||||
"settings_variable_desc_external_url": "External url (i.e: https://studio-01.company.com or http://10.10.3.100)",
|
||||
"settings_variable_desc_slide_upload_limit": "Slide upload limit (in megabytes)",
|
||||
"settings_variable_desc_default_slide_duration": "Introduction slide duration (in seconds)",
|
||||
"settings_variable_desc_intro_slide_duration": "Introduction slide duration (in seconds)",
|
||||
"settings_variable_desc_default_slide_time_with_seconds": "Show the seconds on the clock in the introduction slide",
|
||||
"settings_variable_desc_polling_interval": "Refresh interval applied for settings to the player (in seconds)",
|
||||
"settings_variable_desc_playlist_default_time_sync": "Sync slides across players for default playlist",
|
||||
@ -175,6 +181,7 @@
|
||||
"settings_variable_desc_slide_animation_exit_effect": "Slide animation exit effect (generally better off without it)",
|
||||
"settings_variable_desc_slide_animation_speed": "Slide animation speed",
|
||||
|
||||
"settings_variable_desc_ro_start_counter": "Start counter",
|
||||
"settings_variable_desc_ro_last_folder_content": "Current folder in content explorer",
|
||||
"settings_variable_desc_ro_last_folder_node_player": "Current folder in player explorer",
|
||||
"settings_variable_desc_ro_editable": "Last application reboot datetime",
|
||||
@ -214,6 +221,7 @@
|
||||
"basic_month_11": "November",
|
||||
"basic_month_12": "December",
|
||||
|
||||
"common_untitled": "<untitled>",
|
||||
"common_loading": "Loading...",
|
||||
"common_default_node_player_group": "Default Playgroup",
|
||||
"common_default_playlist": "Default Playlist",
|
||||
|
||||
41
lang/es.json
41
lang/es.json
@ -1,6 +1,5 @@
|
||||
{
|
||||
"dynmenu_content": "Contenido",
|
||||
|
||||
"slideshow_slide_page_title": "Descripción General del Programa",
|
||||
"slideshow_slide_goto_player": "Ir al reproductor",
|
||||
"slideshow_slide_refresh_player": "Actualizar reproductor",
|
||||
@ -46,7 +45,6 @@
|
||||
"slideshow_slide_form_widget_cron_scheduled_placeholder": "Usar formato crontab: * * * * *",
|
||||
"slideshow_slide_form_button_cancel": "Cancelar",
|
||||
"js_slideshow_slide_delete_confirmation": "¿Estás seguro?",
|
||||
|
||||
"slideshow_content_page_title": "Biblioteca de contenidos",
|
||||
"slideshow_content_button_add": "Nuevo Contenido",
|
||||
"slideshow_content_referenced_in_slide_error": "Se hace referencia al contenido en una diapositiva; elimine la diapositiva primero",
|
||||
@ -66,10 +64,13 @@
|
||||
"slideshow_content_form_button_upload": "Subir un archivo",
|
||||
"slideshow_content_form_button_upload_choosen": "No hay archivos seleccionados",
|
||||
"js_slideshow_content_delete_confirmation": "¿Estás seguro?",
|
||||
|
||||
"playlist_page_title": "Playlist",
|
||||
"playlist_button_add": "Agregar una lista de reproducción",
|
||||
"playlist_panel_active": "Playlist activas",
|
||||
"playlist_page_title": "Playlists",
|
||||
"playlist_button_add": "Agregar Playlist",
|
||||
"playlist_button_delete": "Eliminar Playlist",
|
||||
"playlist_panel_about_playlist": "Acerca de la playlist",
|
||||
"playlist_panel_content_management": "Gestión de contenido",
|
||||
"playlist_panel_preview": "Vista previa de la playlist",
|
||||
"playlist_panel_preview_action": "Avance",
|
||||
"playlist_panel_inactive": "Playlist inactivas",
|
||||
"playlist_panel_empty": "Actualmente, no hay playlist. %link% ahora.",
|
||||
"playlist_panel_th_name": "Nombre",
|
||||
@ -78,15 +79,16 @@
|
||||
"playlist_panel_th_activity": "Opciones",
|
||||
"playlist_form_add_title": "Agregar Playlist",
|
||||
"playlist_form_add_submit": "Agregar",
|
||||
"playlist_form_edit_title": "Editar Playlist",
|
||||
"playlist_form_edit_submit": "Guardar",
|
||||
"playlist_form_preview_url_desc": "Puedes usar este enlace para reproducir esta playlist en cualquier navegador que desees. Usa el botón Copiar para guardarla en tu portapapeles.",
|
||||
"playlist_form_preview_qrcode_desc": "Puedes acceder fácilmente a tu playlist usando una tableta o un teléfono. Simplemente escanea el código QR para comenzar.",
|
||||
"playlist_form_preview_iframe_desc": "Puedes ver la playlist sin salir de esta pantalla iniciando la vista previa desde aquí.",
|
||||
"playlist_form_label_name": "Introduce el nombre de la playlist",
|
||||
"playlist_form_label_time_sync": "Sincronizar diapositivas entre reproductores",
|
||||
"playlist_form_label_enabled": "Activar/Desactivar playlist",
|
||||
"playlist_form_button_cancel": "Cancelar",
|
||||
"js_playlist_delete_confirmation": "¿Estás seguro?",
|
||||
"playlist_delete_has_slides": "La lista de reproducción tiene diapositivas, por favor elimínelas antes y reintente",
|
||||
"playlist_delete_has_node_player_groups": "La lista de reproducción está asignada a un playgroup",
|
||||
|
||||
"playlist_delete_has_slides": "La playlist tiene diapositivas, por favor elimínelas antes y reintente",
|
||||
"playlist_delete_has_node_player_groups": "La playlist está asignada a un playgroup",
|
||||
"fleet_node_player_page_title": "Reproductores",
|
||||
"fleet_node_player_button_add": "Agregar un reproductor",
|
||||
"fleet_node_player_panel_active": "Reproductores activos",
|
||||
@ -107,7 +109,6 @@
|
||||
"fleet_node_player_form_label_operating_system": "OS",
|
||||
"fleet_node_player_form_button_cancel": "Cancelar",
|
||||
"js_fleet_node_player_delete_confirmation": "¿Estás seguro?",
|
||||
|
||||
"fleet_node_player_group_page_title": "Playgroups",
|
||||
"fleet_node_player_group_button_add": "Agregar Playgroup",
|
||||
"fleet_node_player_group_panel_active": "Playgroup activos",
|
||||
@ -124,7 +125,6 @@
|
||||
"fleet_node_player_group_form_button_cancel": "Cancelar",
|
||||
"js_fleet_node_player_group_delete_confirmation": "¿Estás seguro?",
|
||||
"node_player_group_delete_has_node_player": "El playgroup tiene reproductores, por favor elimínelos o desasígnelos antes y reintente",
|
||||
|
||||
"login_page_title": "Iniciar Sesión",
|
||||
"auth_page_title": "Usuarios",
|
||||
"auth_user_button_add": "Agregar un usuario",
|
||||
@ -143,7 +143,6 @@
|
||||
"auth_user_form_button_cancel": "Cancelar",
|
||||
"auth_user_delete_at_least_one_account": "Debe tener al menos un usuario activo mientras usa la función de autenticación",
|
||||
"js_auth_user_delete_confirmation": "¿Estás seguro?",
|
||||
|
||||
"settings_page_title": "Configuración",
|
||||
"settings_plugin_page_title": "Plugins",
|
||||
"settings_variable_panel_system_variables": "Configuración general",
|
||||
@ -165,22 +164,20 @@
|
||||
"settings_variable_desc_edition_auth_enabled": "Las credenciales predeterminadas del usuario serán admin/admin",
|
||||
"settings_variable_desc_external_url": "URL externa (ej.: https://studio-01.company.com o http://10.10.3.100)",
|
||||
"settings_variable_desc_slide_upload_limit": "Límite de carga de diapositivas (en megabytes)",
|
||||
"settings_variable_desc_default_slide_duration": "Duración de la diapositiva de introducción (en segundos)",
|
||||
"settings_variable_desc_intro_slide_duration": "Duración de la diapositiva de introducción (en segundos)",
|
||||
"settings_variable_desc_default_slide_time_with_seconds": "Mostrar los segundos en el reloj de la diapositiva de introducción",
|
||||
"settings_variable_desc_polling_interval": "Intervalo de actualización aplicado para configuraciones del reproductor (en segundos)",
|
||||
"settings_variable_desc_playlist_default_time_sync": "Sincronizar diapositivas entre reproductores para la lista de reproducción predeterminada",
|
||||
|
||||
"settings_variable_desc_playlist_default_time_sync": "Sincronizar diapositivas entre reproductores para la playlist predeterminada",
|
||||
"settings_variable_desc_slide_animation_enabled": "Habilitar efecto de animación entre diapositivas",
|
||||
"settings_variable_desc_slide_animation_entrance_effect": "Efecto de entrada de animación de diapositiva",
|
||||
"settings_variable_desc_slide_animation_exit_effect": "Efecto de salida de animación de diapositiva (generalmente mejor sin él)",
|
||||
"settings_variable_desc_slide_animation_speed": "Velocidad de animación de diapositiva",
|
||||
|
||||
"settings_variable_desc_ro_start_counter": "Contador de inicio",
|
||||
"settings_variable_desc_ro_last_folder_content": "Carpeta actual en el explorador de contenidos",
|
||||
"settings_variable_desc_ro_last_folder_node_player": "Carpeta actual en el explorador del reproductor",
|
||||
"settings_variable_desc_ro_editable": "Fecha y hora del último reinicio de la aplicación",
|
||||
"settings_variable_desc_ro_last_slide_update": "Fecha y hora de la última actualización de diapositiva",
|
||||
"settings_variable_desc_ro_refresh_player_request": "Fecha y hora de la última solicitud de actualización del reproductor",
|
||||
|
||||
"sysinfo_page_title": "Información del sistema",
|
||||
"sysinfo_panel_button_restart": "Reiniciar",
|
||||
"sysinfo_panel_table_section_system": "Sistema",
|
||||
@ -193,7 +190,6 @@
|
||||
"logs_panel_last_logs": "Registros (últimas 100 líneas)",
|
||||
"js_sysinfo_restart_confirmation": "¿Estás seguro?",
|
||||
"js_sysinfo_restart_loading": "Reiniciando, por favor espera...",
|
||||
|
||||
"basic_day_1": "Lunes",
|
||||
"basic_day_2": "Martes",
|
||||
"basic_day_3": "Miércoles",
|
||||
@ -213,7 +209,7 @@
|
||||
"basic_month_10": "Octubre",
|
||||
"basic_month_11": "Noviembre",
|
||||
"basic_month_12": "Diciembre",
|
||||
|
||||
"common_untitled": "<sin-título>",
|
||||
"common_loading": "Cargando...",
|
||||
"common_default_node_player_group": "Playgroup predeterminado",
|
||||
"common_default_playlist": "Lista de reproducción predeterminada",
|
||||
@ -245,7 +241,6 @@
|
||||
"updated_by": "Última actualización por",
|
||||
"close": "Cerrar",
|
||||
"anonymous": "Anónimo",
|
||||
|
||||
"enum_animation_speed_slower": "Más lento",
|
||||
"enum_animation_speed_slow": "Lento",
|
||||
"enum_animation_speed_normal": "Normal",
|
||||
@ -279,7 +274,6 @@
|
||||
"enum_operating_system_redhat": "RedHat",
|
||||
"enum_operating_system_centos": "CentOS",
|
||||
"enum_operating_system_other": "Otro",
|
||||
|
||||
"sysinfo_rpi_model": "Modelo de Raspberry Pi",
|
||||
"sysinfo_rpi_model_unknown": "No es una Raspberry Pi o la información del modelo no está disponible",
|
||||
"sysinfo_storage_free_space": "Espacio de almacenamiento libre",
|
||||
@ -289,6 +283,5 @@
|
||||
"sysinfo_network_interface": "Interfaz de red",
|
||||
"sysinfo_mac_address": "Dirección MAC",
|
||||
"sysinfo_ip_address": "Dirección IP",
|
||||
|
||||
"player_default_welcome_message": "Para gestionar este reproductor, ve a un navegador en %link%"
|
||||
}
|
||||
|
||||
34
lang/fr.json
34
lang/fr.json
@ -1,6 +1,5 @@
|
||||
{
|
||||
"dynmenu_content": "Contenu",
|
||||
|
||||
"slideshow_slide_page_title": "Vue Planning",
|
||||
"slideshow_slide_goto_player": "Voir le lecteur",
|
||||
"slideshow_slide_refresh_player": "Rafraîchir le lecteur",
|
||||
@ -46,7 +45,6 @@
|
||||
"slideshow_slide_form_widget_cron_scheduled_placeholder": "Utiliser le format crontab: * * * * *",
|
||||
"slideshow_slide_form_button_cancel": "Annuler",
|
||||
"js_slideshow_slide_delete_confirmation": "Êtes-vous sûr ?",
|
||||
|
||||
"slideshow_content_page_title": "Bibliothèque de contenus",
|
||||
"slideshow_content_button_add": "Nouveau Contenu",
|
||||
"slideshow_content_referenced_in_slide_error": "Le contenu est référencé dans une slide, supprimez d'abord la slide",
|
||||
@ -66,10 +64,13 @@
|
||||
"slideshow_content_form_button_upload": "Uploader un fichier",
|
||||
"slideshow_content_form_button_upload_choosen": "Aucun fichier sélectionné",
|
||||
"js_slideshow_content_delete_confirmation": "Êtes-vous sûr ?",
|
||||
|
||||
"playlist_page_title": "Playlist",
|
||||
"playlist_button_add": "Ajouter une playlist",
|
||||
"playlist_panel_active": "Playlist actives",
|
||||
"playlist_page_title": "Playlists",
|
||||
"playlist_button_add": "Ajouter Playlist",
|
||||
"playlist_button_delete": "Supprimer Playlist",
|
||||
"playlist_panel_about_playlist": "À propos de la playlist",
|
||||
"playlist_panel_content_management": "Elements de la playlist",
|
||||
"playlist_panel_preview": "Playlist preview",
|
||||
"playlist_panel_preview_action": "Prévisualiser",
|
||||
"playlist_panel_inactive": "Playlist inactives",
|
||||
"playlist_panel_empty": "Actuellement, il n'y a pas de playlist. %link% maintenant.",
|
||||
"playlist_panel_th_name": "Nom",
|
||||
@ -78,15 +79,17 @@
|
||||
"playlist_panel_th_activity": "Options",
|
||||
"playlist_form_add_title": "Ajout d'une Playlist",
|
||||
"playlist_form_add_submit": "Ajouter",
|
||||
"playlist_form_edit_title": "Modification d'une Playlist",
|
||||
"playlist_form_preview_url_desc": "Vous pouvez utiliser ce lien pour lire cette playlist sur n'importe quel navigateur de votre choix. Utilisez le bouton Copier pour l'obtenir dans votre presse-papiers.",
|
||||
"playlist_form_preview_qrcode_desc": "Vous pouvez facilement accéder à votre playlist à l'aide d'une tablette ou d'un téléphone. Scannez simplement le code QR pour commencer.",
|
||||
"playlist_form_preview_iframe_desc": "Vous pouvez visualiser la playlist sans quitter cet écran en démarrant l'aperçu à partir d'ici.",
|
||||
"playlist_form_edit_submit": "Enregistrer",
|
||||
"playlist_form_label_name": "Entrez le nom de la playlist",
|
||||
"playlist_form_label_time_sync": "Synchroniser les slides des lecteurs",
|
||||
"playlist_form_label_enabled": "Activer/Désactiver la playlist",
|
||||
"playlist_form_button_cancel": "Annuler",
|
||||
"js_playlist_delete_confirmation": "Êtes-vous sûr ?",
|
||||
"playlist_delete_has_slides": "La playlist contient des slides, supprimez-les avant et réessayez",
|
||||
"playlist_delete_has_node_player_groups": "La playlist est attribuée à un playgroup",
|
||||
|
||||
"fleet_node_player_page_title": "Lecteurs",
|
||||
"fleet_node_player_button_add": "Ajouter un lecteur",
|
||||
"fleet_node_player_panel_active": "Players actifs",
|
||||
@ -107,7 +110,6 @@
|
||||
"fleet_node_player_form_label_operating_system": "OS",
|
||||
"fleet_node_player_form_button_cancel": "Annuler",
|
||||
"js_fleet_node_player_delete_confirmation": "Êtes-vous sûr ?",
|
||||
|
||||
"fleet_node_player_group_page_title": "Playgroups",
|
||||
"fleet_node_player_group_button_add": "Ajouter un Playgroup",
|
||||
"fleet_node_player_group_panel_active": "Playgroups",
|
||||
@ -124,7 +126,6 @@
|
||||
"fleet_node_player_group_form_button_cancel": "Annuler",
|
||||
"js_fleet_node_player_group_delete_confirmation": "Êtes-vous sûr ?",
|
||||
"node_player_group_delete_has_node_player": "Le playgroup a des lecteurs, supprimez-les ou réassignez-les avant de le supprimer",
|
||||
|
||||
"login_page_title": "Connexion",
|
||||
"auth_page_title": "Utilisateurs",
|
||||
"auth_user_button_add": "Ajouter un utilisateur",
|
||||
@ -143,7 +144,6 @@
|
||||
"auth_user_form_button_cancel": "Annuler",
|
||||
"auth_user_delete_at_least_one_account": "Vous devez avoir au moins un utilisateur actif lorsque vous activez la gestion de l'authentification",
|
||||
"js_auth_user_delete_confirmation": "Êtes-vous sûr ?",
|
||||
|
||||
"settings_page_title": "Paramètres",
|
||||
"settings_plugin_page_title": "Plugins",
|
||||
"settings_variable_panel_system_variables": "Paramètres généraux",
|
||||
@ -165,22 +165,20 @@
|
||||
"settings_variable_desc_edition_auth_enabled": "Les identifiants de l'utilisateur par défaut seront admin/admin",
|
||||
"settings_variable_desc_external_url": "URL externe (i.e: https://studio-01.company.com or http://10.10.3.100)",
|
||||
"settings_variable_desc_slide_upload_limit": "Limite d'upload du fichier d'une slide (en mégaoctets)",
|
||||
"settings_variable_desc_default_slide_duration": "Durée de la slide d'introduction (en secondes)",
|
||||
"settings_variable_desc_intro_slide_duration": "Durée de la slide d'introduction (en secondes)",
|
||||
"settings_variable_desc_default_slide_time_with_seconds": "Afficher les secondes de l'horloge de la slide d'introduction",
|
||||
"settings_variable_desc_polling_interval": "Intervalle de rafraîchissement des paramètres à appliquer au lecteur (en secondes)",
|
||||
"settings_variable_desc_playlist_default_time_sync": "Synchroniser les slides des lecteurs pour la playlist par défaut",
|
||||
|
||||
"settings_variable_desc_slide_animation_enabled": "Activer les effets d'animation entre les slides",
|
||||
"settings_variable_desc_slide_animation_entrance_effect": "Effet d'animation d'arrivée de la slide",
|
||||
"settings_variable_desc_slide_animation_exit_effect": "Effet d'animation de sortie de la slide (généralement mieux sans)",
|
||||
"settings_variable_desc_slide_animation_speed": "Vitesse de l'animation de la slide",
|
||||
|
||||
"settings_variable_desc_ro_start_counter": "Compteur de démarrage",
|
||||
"settings_variable_desc_ro_last_folder_content": "Dossier courant dans l'explorateur de contenu",
|
||||
"settings_variable_desc_ro_last_folder_node_player": "Dossier courant dans l'explorateur du lecteur",
|
||||
"settings_variable_desc_ro_editable": "Date de dernier redémarrage de l'application",
|
||||
"settings_variable_desc_ro_last_slide_update": "Date de dernière modification d'une slide",
|
||||
"settings_variable_desc_ro_refresh_player_request": "Date de dernière demande de rafraîchissement du lecteur",
|
||||
|
||||
"sysinfo_page_title": "Système",
|
||||
"sysinfo_panel_button_restart": "Redémarrer",
|
||||
"sysinfo_panel_table_section_system": "Système",
|
||||
@ -193,7 +191,6 @@
|
||||
"logs_panel_last_logs": "Journaux (100 dernières lignes)",
|
||||
"js_sysinfo_restart_confirmation": "Êtes-vous sûr ?",
|
||||
"js_sysinfo_restart_loading": "Redémarrage en cours, veuillez patienter...",
|
||||
|
||||
"basic_day_1": "Lundi",
|
||||
"basic_day_2": "Mardi",
|
||||
"basic_day_3": "Mercredi",
|
||||
@ -213,7 +210,7 @@
|
||||
"basic_month_10": "Octobre",
|
||||
"basic_month_11": "Novembre",
|
||||
"basic_month_12": "Décembre",
|
||||
|
||||
"common_untitled": "<sans-titre>",
|
||||
"common_loading": "Chargement...",
|
||||
"common_default_node_player_group": "Playgroup par défaut",
|
||||
"common_default_playlist": "Playlist par défaut",
|
||||
@ -245,7 +242,6 @@
|
||||
"updated_by": "Dernière modification par",
|
||||
"close": "Fermer",
|
||||
"anonymous": "Anon",
|
||||
|
||||
"enum_animation_speed_slower": "Très lent",
|
||||
"enum_animation_speed_slow": "Lent",
|
||||
"enum_animation_speed_normal": "Normal",
|
||||
@ -279,7 +275,6 @@
|
||||
"enum_operating_system_redhat": "RedHat",
|
||||
"enum_operating_system_centos": "CentOS",
|
||||
"enum_operating_system_other": "Autre",
|
||||
|
||||
"sysinfo_rpi_model": "Modèle du Raspberry Pi",
|
||||
"sysinfo_rpi_model_unknown": "Le modèle n'est pas un Raspberry Pi",
|
||||
"sysinfo_storage_free_space": "Stockage Disponible",
|
||||
@ -289,6 +284,5 @@
|
||||
"sysinfo_network_interface": "Interface Réseau",
|
||||
"sysinfo_mac_address": "Addresse MAC",
|
||||
"sysinfo_ip_address": "Addresse IP",
|
||||
|
||||
"player_default_welcome_message": "Pour gérer ce lecteur, allez sur un navigateur à l'adresse %link%"
|
||||
}
|
||||
|
||||
35
lang/it.json
35
lang/it.json
@ -1,6 +1,5 @@
|
||||
{
|
||||
"dynmenu_content": "Contenuti",
|
||||
|
||||
"slideshow_slide_page_title": "Programmazione",
|
||||
"slideshow_slide_goto_player": "Vai al player",
|
||||
"slideshow_slide_refresh_player": "Aggiorna player",
|
||||
@ -46,7 +45,6 @@
|
||||
"slideshow_slide_form_widget_cron_scheduled_placeholder": "Utilizza formato crontab: * * * * *",
|
||||
"slideshow_slide_form_button_cancel": "Annulla",
|
||||
"js_slideshow_slide_delete_confirmation": "Sei sicuro?",
|
||||
|
||||
"slideshow_content_page_title": "Libreria dei contenuti",
|
||||
"slideshow_content_button_add": "Nuovo Contenuto",
|
||||
"slideshow_content_referenced_in_slide_error": "Si fa riferimento al contenuto in una diapositiva, rimuovere prima la diapositiva",
|
||||
@ -66,10 +64,13 @@
|
||||
"slideshow_content_form_button_upload": "Carica un file",
|
||||
"slideshow_content_form_button_upload_choosen": "Nessun file selezionato",
|
||||
"js_slideshow_content_delete_confirmation": "Sei sicuro?",
|
||||
|
||||
"playlist_page_title": "Playlist",
|
||||
"playlist_button_add": "Aggiungi alla playlist",
|
||||
"playlist_panel_active": "Attiva playlist",
|
||||
"playlist_page_title": "Playlists",
|
||||
"playlist_button_add": "Aggiungi Playlist",
|
||||
"playlist_button_delete": "Elimina Playlist",
|
||||
"playlist_panel_about_playlist": "Informazioni sulla playlist",
|
||||
"playlist_panel_content_management": "Gestione dei contenuti",
|
||||
"playlist_panel_preview": "Anteprima della playlist",
|
||||
"playlist_panel_preview_action": "Anteprima",
|
||||
"playlist_panel_inactive": "Playlist inattive",
|
||||
"playlist_panel_empty": "Attualmente, non ci sono playlist. %link% adesso.",
|
||||
"playlist_panel_th_name": "Nome",
|
||||
@ -78,15 +79,16 @@
|
||||
"playlist_panel_th_activity": "Opzioni",
|
||||
"playlist_form_add_title": "Aggiungi Playlist",
|
||||
"playlist_form_add_submit": "Aggiungi",
|
||||
"playlist_form_edit_title": "Modifica Playlist",
|
||||
"playlist_form_edit_submit": "Salva",
|
||||
"playlist_form_preview_url_desc": "Puoi utilizzare questo collegamento per riprodurre questa playlist su qualsiasi browser desideri. Utilizza il pulsante Copia per inserirla negli appunti.",
|
||||
"playlist_form_preview_qrcode_desc": "Puoi accedere facilmente alla tua playlist utilizzando un tablet o un telefono. Basta scansionare il codice QR per iniziare.",
|
||||
"playlist_form_preview_iframe_desc": "Puoi visualizzare la playlist senza uscire da questa schermata avviando l'anteprima da qui.",
|
||||
"playlist_form_label_name": "Inserisci il nome della playlist",
|
||||
"playlist_form_label_time_sync": "Sincronizza le slide tra gli schermi",
|
||||
"playlist_form_label_enabled": "Abilita/Disabilita playlist",
|
||||
"playlist_form_button_cancel": "Cancella",
|
||||
"js_playlist_delete_confirmation": "Sei sicuro?",
|
||||
"playlist_delete_has_slides": "Sono presenti slide nella playlist, annullale e riprova",
|
||||
"playlist_delete_has_node_player_groups": "La playlist è collegata ad un playgroup",
|
||||
|
||||
"fleet_node_player_page_title": "Schermi",
|
||||
"fleet_node_player_button_add": "Aggiungi allo schermo",
|
||||
"fleet_node_player_panel_active": "Schermi attivi",
|
||||
@ -107,7 +109,6 @@
|
||||
"fleet_node_player_form_label_operating_system": "OS",
|
||||
"fleet_node_player_form_button_cancel": "Cancella",
|
||||
"js_fleet_node_player_delete_confirmation": "Sei sicuro?",
|
||||
|
||||
"fleet_node_player_group_page_title": "Playgroups",
|
||||
"fleet_node_player_group_button_add": "Aggiungi Playgroup",
|
||||
"fleet_node_player_group_panel_active": "Playgroup attivi",
|
||||
@ -124,7 +125,6 @@
|
||||
"fleet_node_player_group_form_button_cancel": "Cancella",
|
||||
"js_fleet_node_player_group_delete_confirmation": "Sei sicuro?",
|
||||
"node_player_group_delete_has_node_player": "Lo playgroup ha una playlist, rumuovila o riassegnala e riprova",
|
||||
|
||||
"login_page_title": "Login",
|
||||
"auth_page_title": "Utente",
|
||||
"auth_user_button_add": "Aggiungi utente",
|
||||
@ -143,7 +143,6 @@
|
||||
"auth_user_form_button_cancel": "Cancella",
|
||||
"auth_user_delete_at_least_one_account": "È necessario avere almeno un utente attivo durante l'utilizzo della funzione di autenticazione",
|
||||
"js_auth_user_delete_confirmation": "Sei sicuro?",
|
||||
|
||||
"settings_page_title": "Impostazioni",
|
||||
"settings_plugin_page_title": "Plugins",
|
||||
"settings_variable_panel_system_variables": "Impostazioni generali",
|
||||
@ -165,22 +164,20 @@
|
||||
"settings_variable_desc_edition_auth_enabled": "Le credenziali utente predefinite sono admin/admin",
|
||||
"settings_variable_desc_external_url": "Url esterno (esempio: https://studio-01.company.com or http://10.10.3.100)",
|
||||
"settings_variable_desc_slide_upload_limit": "Limite upload slide (in megabytes)",
|
||||
"settings_variable_desc_default_slide_duration": "Durata introduzione slide (in secondi)",
|
||||
"settings_variable_desc_intro_slide_duration": "Durata introduzione slide (in secondi)",
|
||||
"settings_variable_desc_default_slide_time_with_seconds": "Mostra secondi introduzione slide",
|
||||
"settings_variable_desc_polling_interval": "Intervallo di aggiornamento applicato per le impostazioni del monitor (in secondi)",
|
||||
"settings_variable_desc_playlist_default_time_sync": "Sincronizza le diapositive tra i lettori per la playlist predefinita",
|
||||
|
||||
"settings_variable_desc_slide_animation_enabled": "Abilita l'effetto di animazione tra le diapositive",
|
||||
"settings_variable_desc_slide_animation_entrance_effect": "Effetto ingresso diapositiva",
|
||||
"settings_variable_desc_slide_animation_exit_effect": "Effetto di uscita della diapositiva (meglio senza)",
|
||||
"settings_variable_desc_slide_animation_speed": "Velicita animazione slide",
|
||||
|
||||
"settings_variable_desc_ro_start_counter": "Avvia contatore",
|
||||
"settings_variable_desc_ro_last_folder_content": "Cartella corrente in Esplora contenuti",
|
||||
"settings_variable_desc_ro_last_folder_node_player": "Cartella corrente in Player Explorer",
|
||||
"settings_variable_desc_ro_editable": "Data/ora dell'ultimo riavvio dell'applicazione",
|
||||
"settings_variable_desc_ro_last_slide_update": "Data e ora dell'ultimo aggiornamento della diapositiva",
|
||||
"settings_variable_desc_ro_refresh_player_request": "Data e ora della richiesta di aggiornamento dell monitor",
|
||||
|
||||
"sysinfo_page_title": "Informazione sistema",
|
||||
"sysinfo_panel_button_restart": "Riavvia",
|
||||
"sysinfo_panel_table_section_system": "Sistema",
|
||||
@ -193,7 +190,6 @@
|
||||
"logs_panel_last_logs": "Logs (ultime 100 righe)",
|
||||
"js_sysinfo_restart_confirmation": "Sei sicuro?",
|
||||
"js_sysinfo_restart_loading": "Riavvio in corso, attendi...",
|
||||
|
||||
"basic_day_1": "Lunedi",
|
||||
"basic_day_2": "Martedi",
|
||||
"basic_day_3": "Mercoledi",
|
||||
@ -213,7 +209,7 @@
|
||||
"basic_month_10": "Ottobre",
|
||||
"basic_month_11": "Novembre",
|
||||
"basic_month_12": "Dicembre",
|
||||
|
||||
"common_untitled": "<senza-titolo>",
|
||||
"common_loading": "Caricamento...",
|
||||
"common_default_node_player_group": "Playgroup di default",
|
||||
"common_default_playlist": "Default playlist",
|
||||
@ -245,7 +241,6 @@
|
||||
"updated_by": "Aggiornato da",
|
||||
"close": "Chiuso",
|
||||
"anonymous": "Anonimo",
|
||||
|
||||
"enum_animation_speed_slower": "Lentamente",
|
||||
"enum_animation_speed_slow": "Lento",
|
||||
"enum_animation_speed_normal": "Normale",
|
||||
@ -279,7 +274,6 @@
|
||||
"enum_operating_system_redhat": "RedHat",
|
||||
"enum_operating_system_centos": "CentOS",
|
||||
"enum_operating_system_other": "Altro",
|
||||
|
||||
"sysinfo_rpi_model": "Raspberry Pi Model",
|
||||
"sysinfo_rpi_model_unknown": "Informazioni Raspberry Pi non disponibili",
|
||||
"sysinfo_storage_free_space": "Spazio libero",
|
||||
@ -289,6 +283,5 @@
|
||||
"sysinfo_network_interface": "interfaccia di rete",
|
||||
"sysinfo_mac_address": "Indirizzo MAC",
|
||||
"sysinfo_ip_address": "indirizzo IP",
|
||||
|
||||
"player_default_welcome_message": "Per gestire questo lettore, vai al browser all'indirizzo %link%"
|
||||
}
|
||||
@ -24,6 +24,11 @@ class Application:
|
||||
signal.signal(signal.SIGINT, self.signal_handler)
|
||||
|
||||
def start(self) -> None:
|
||||
variable = self._model_store.variable().get_one_by_name('start_counter')
|
||||
|
||||
if variable:
|
||||
self._model_store.variable().update_by_name(variable.name, variable.as_int() + 1)
|
||||
|
||||
self._web_server.run()
|
||||
|
||||
def signal_handler(self, signal, frame) -> None:
|
||||
|
||||
@ -30,17 +30,17 @@ class AuthController(ObController):
|
||||
login_error = None
|
||||
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
if not self._model_store.variable().map().get('auth_enabled').as_bool():
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
if len(request.form):
|
||||
user = self._model_store.user().get_one_by_username(request.form['username'], enabled=True)
|
||||
if user:
|
||||
if user.password == self._model_store.user().encode_password(request.form['password']):
|
||||
login_user(user)
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
return redirect(url_for('playlist'))
|
||||
else:
|
||||
login_error = 'bad_credentials'
|
||||
else:
|
||||
|
||||
@ -37,13 +37,22 @@ class PlayerController(ObController):
|
||||
playlist_id = current_playlist.id if current_playlist else None
|
||||
|
||||
items = self._get_playlist(playlist_id=playlist_id, preview_content_id=preview_content_id)
|
||||
intro_slide_duration = self._model_store.variable().get_one_by_name('intro_slide_duration').eval()
|
||||
|
||||
if items['preview_mode'] or request.args.get('intro', '1') == '0':
|
||||
intro_slide_duration = 0
|
||||
|
||||
animation_enabled = self._model_store.variable().get_one_by_name('slide_animation_enabled').eval()
|
||||
|
||||
if request.args.get('animation', '1') == '0':
|
||||
animation_enabled = False
|
||||
|
||||
return render_template(
|
||||
'player/player.jinja.html',
|
||||
items=items,
|
||||
default_slide_duration=0 if items['preview_mode'] else self._model_store.variable().get_one_by_name('default_slide_duration').eval(),
|
||||
intro_slide_duration=intro_slide_duration,
|
||||
polling_interval=self._model_store.variable().get_one_by_name('polling_interval'),
|
||||
slide_animation_enabled=self._model_store.variable().get_one_by_name('slide_animation_enabled'),
|
||||
slide_animation_enabled=animation_enabled,
|
||||
slide_animation_entrance_effect=self._model_store.variable().get_one_by_name('slide_animation_entrance_effect'),
|
||||
slide_animation_exit_effect=self._model_store.variable().get_one_by_name('slide_animation_exit_effect'),
|
||||
slide_animation_speed=self._model_store.variable().get_one_by_name('slide_animation_speed'),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import json
|
||||
|
||||
from flask import Flask, render_template, redirect, request, url_for, jsonify
|
||||
from flask import Flask, render_template, redirect, request, url_for, jsonify, abort
|
||||
from src.exceptions.PlaylistSlugAlreadyExist import PlaylistSlugAlreadyExist
|
||||
from src.service.ModelStore import ModelStore
|
||||
from src.model.entity.Playlist import Playlist
|
||||
from src.interface.ObController import ObController
|
||||
@ -17,20 +18,31 @@ class PlaylistController(ObController):
|
||||
return decorated_function
|
||||
|
||||
def register(self):
|
||||
self._app.add_url_rule('/playlist/list', 'playlist_list', self.guard_playlist(self._auth(self.playlist_list)), methods=['GET'])
|
||||
self._app.add_url_rule('/playlist', 'playlist', self.guard_playlist(self._auth(self.playlist)), methods=['GET'])
|
||||
self._app.add_url_rule('/playlist/list/<playlist_id>', 'playlist_list', self.guard_playlist(self._auth(self.playlist_list)), methods=['GET'])
|
||||
self._app.add_url_rule('/playlist/add', 'playlist_add', self.guard_playlist(self._auth(self.playlist_add)), methods=['POST'])
|
||||
self._app.add_url_rule('/playlist/edit', 'playlist_edit', self.guard_playlist(self._auth(self.playlist_edit)), methods=['POST'])
|
||||
self._app.add_url_rule('/playlist/toggle', 'playlist_toggle', self.guard_playlist(self._auth(self.playlist_toggle)), methods=['POST'])
|
||||
self._app.add_url_rule('/playlist/delete', 'playlist_delete', self.guard_playlist(self._auth(self.playlist_delete)), methods=['DELETE'])
|
||||
self._app.add_url_rule('/playlist/save', 'playlist_save', self.guard_playlist(self._auth(self.playlist_save)), methods=['POST'])
|
||||
self._app.add_url_rule('/playlist/delete/<playlist_id>', 'playlist_delete', self.guard_playlist(self._auth(self.playlist_delete)), methods=['GET'])
|
||||
|
||||
def playlist_list(self):
|
||||
def playlist(self):
|
||||
return redirect(url_for('playlist_list', playlist_id=0))
|
||||
|
||||
def playlist_list(self, playlist_id: int = 0):
|
||||
current_playlist = self._model_store.playlist().get(playlist_id)
|
||||
playlists = self._model_store.playlist().get_all(sort="created_at", ascending=False)
|
||||
durations = self._model_store.playlist().get_durations_by_playlists()
|
||||
|
||||
if not current_playlist and len(playlists) > 0:
|
||||
current_playlist = playlists[0]
|
||||
|
||||
return render_template(
|
||||
'playlist/list.jinja.html',
|
||||
playlists=self._model_store.playlist().get_all(ascending=True),
|
||||
enabled_playlists=self._model_store.playlist().get_enabled_playlists(with_default=True),
|
||||
disabled_playlists=self._model_store.playlist().get_disabled_playlists(),
|
||||
durations=durations
|
||||
error=request.args.get('error', None),
|
||||
current_playlist=current_playlist,
|
||||
playlists=playlists,
|
||||
durations=durations,
|
||||
slides=self._model_store.slide().get_slides(playlist_id=current_playlist.id),
|
||||
contents={content.id: content for content in self._model_store.content().get_contents()},
|
||||
)
|
||||
|
||||
def playlist_add(self):
|
||||
@ -40,32 +52,28 @@ class PlaylistController(ObController):
|
||||
time_sync=False
|
||||
)
|
||||
|
||||
self._model_store.playlist().add_form(playlist)
|
||||
try:
|
||||
playlist = self._model_store.playlist().add_form(playlist)
|
||||
except PlaylistSlugAlreadyExist as e:
|
||||
abort(409)
|
||||
|
||||
return redirect(url_for('playlist_list'))
|
||||
return redirect(url_for('playlist_list', playlist_id=playlist.id))
|
||||
|
||||
def playlist_edit(self):
|
||||
def playlist_save(self):
|
||||
self._model_store.playlist().update_form(
|
||||
id=request.form['id'],
|
||||
name=request.form['name'],
|
||||
time_sync=request.form['time_sync'],
|
||||
time_sync=True if 'time_sync' in request.form else False,
|
||||
enabled=True if 'enabled' in request.form else False
|
||||
)
|
||||
return redirect(url_for('playlist_list'))
|
||||
return redirect(url_for('playlist_list', playlist_id=request.form['id']))
|
||||
|
||||
def playlist_toggle(self):
|
||||
data = request.get_json()
|
||||
self._model_store.playlist().update_enabled(data.get('id'), data.get('enabled'))
|
||||
return jsonify({'status': 'ok'})
|
||||
def playlist_delete(self, playlist_id: int):
|
||||
if self._model_store.slide().count_slides_for_playlist(playlist_id) > 0:
|
||||
return redirect(url_for('playlist_list', playlist_id=playlist_id, error='playlist_delete_has_slides'))
|
||||
|
||||
def playlist_delete(self):
|
||||
data = request.get_json()
|
||||
id = data.get('id')
|
||||
if self._model_store.node_player_group().count_node_player_groups_for_playlist(playlist_id) > 0:
|
||||
return redirect(url_for('playlist_list', playlist_id=playlist_id, error='playlist_delete_has_node_player_groups'))
|
||||
|
||||
if self._model_store.slide().count_slides_for_playlist(id) > 0:
|
||||
return jsonify({'status': 'error', 'message': self.t('playlist_delete_has_slides')}), 400
|
||||
|
||||
if self._model_store.node_player_group().count_node_player_groups_for_playlist(id) > 0:
|
||||
return jsonify({'status': 'error', 'message': self.t('playlist_delete_has_node_player_groups')}), 400
|
||||
|
||||
self._model_store.playlist().delete(id)
|
||||
return jsonify({'status': 'ok'})
|
||||
self._model_store.playlist().delete(playlist_id)
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
@ -16,31 +16,14 @@ class SlideController(ObController):
|
||||
|
||||
def register(self):
|
||||
self._app.add_url_rule('/manage', 'manage', self.manage, methods=['GET'])
|
||||
self._app.add_url_rule('/slideshow', 'slideshow_slide_list', self._auth(self.slideshow), methods=['GET'])
|
||||
self._app.add_url_rule('/slideshow/playlist/set/<playlist_id>', 'slideshow_slide_list_playlist_use', self._auth(self.slideshow), methods=['GET'])
|
||||
self._app.add_url_rule('/slideshow/slide/add', 'slideshow_slide_add', self._auth(self.slideshow_slide_add), methods=['POST'])
|
||||
self._app.add_url_rule('/slideshow/slide/edit', 'slideshow_slide_edit', self._auth(self.slideshow_slide_edit), methods=['POST'])
|
||||
self._app.add_url_rule('/slideshow/slide/toggle', 'slideshow_slide_toggle', self._auth(self.slideshow_slide_toggle), methods=['POST'])
|
||||
self._app.add_url_rule('/slideshow/slide/delete', 'slideshow_slide_delete', self._auth(self.slideshow_slide_delete), methods=['DELETE'])
|
||||
self._app.add_url_rule('/slideshow/slide/position', 'slideshow_slide_position', self._auth(self.slideshow_slide_position), methods=['POST'])
|
||||
self._app.add_url_rule('/slideshow/player-refresh', 'slideshow_player_refresh', self._auth(self.slideshow_player_refresh), methods=['GET'])
|
||||
self._app.add_url_rule('/slideshow/player-refresh', 'slideshow_player_refresh/<playlist_id>', self._auth(self.slideshow_player_refresh), methods=['GET'])
|
||||
|
||||
def manage(self):
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
|
||||
def slideshow(self, playlist_id: int = 0):
|
||||
current_playlist = self._model_store.playlist().get(playlist_id)
|
||||
playlist_id = current_playlist.id if current_playlist else None
|
||||
return render_template(
|
||||
'slideshow/slides/list.jinja.html',
|
||||
current_playlist=current_playlist,
|
||||
playlists=self._model_store.playlist().get_enabled_playlists(),
|
||||
enabled_slides=self._model_store.slide().get_slides(playlist_id=playlist_id, enabled=True),
|
||||
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
|
||||
)
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
def slideshow_slide_add(self):
|
||||
content = None
|
||||
@ -67,9 +50,9 @@ class SlideController(ObController):
|
||||
self._post_update()
|
||||
|
||||
if slide.playlist_id:
|
||||
return redirect(url_for('slideshow_slide_list_playlist_use', playlist_id=slide.playlist_id))
|
||||
return redirect(url_for('playlist_list', playlist_id=slide.playlist_id))
|
||||
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
def slideshow_slide_edit(self):
|
||||
slide = self._model_store.slide().update_form(
|
||||
@ -83,15 +66,9 @@ class SlideController(ObController):
|
||||
self._post_update()
|
||||
|
||||
if slide.playlist_id:
|
||||
return redirect(url_for('slideshow_slide_list_playlist_use', playlist_id=slide.playlist_id))
|
||||
return redirect(url_for('playlist_list', playlist_id=slide.playlist_id))
|
||||
|
||||
return redirect(url_for('slideshow_slide_list'))
|
||||
|
||||
def slideshow_slide_toggle(self):
|
||||
data = request.get_json()
|
||||
self._model_store.slide().update_enabled(data.get('id'), data.get('enabled'))
|
||||
self._post_update()
|
||||
return jsonify({'status': 'ok'})
|
||||
return redirect(url_for('playlist'))
|
||||
|
||||
def slideshow_slide_delete(self):
|
||||
data = request.get_json()
|
||||
@ -105,11 +82,12 @@ class SlideController(ObController):
|
||||
self._post_update()
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
def slideshow_player_refresh(self):
|
||||
def slideshow_player_refresh(self, playlist_id: int):
|
||||
self._model_store.variable().update_by_name("refresh_player_request", time.time())
|
||||
return redirect(
|
||||
url_for(
|
||||
'slideshow_slide_list',
|
||||
'playlist_list',
|
||||
playlist_id=playlist_id,
|
||||
refresh_player=self._model_store.variable().get_one_by_name('polling_interval').as_int()
|
||||
)
|
||||
)
|
||||
|
||||
2
src/exceptions/PlaylistSlugAlreadyExist.py
Normal file
2
src/exceptions/PlaylistSlugAlreadyExist.py
Normal file
@ -0,0 +1,2 @@
|
||||
class PlaylistSlugAlreadyExist(Exception):
|
||||
pass
|
||||
@ -120,8 +120,13 @@ class DatabaseManager:
|
||||
params=tuple(v for v in values.values())
|
||||
)
|
||||
|
||||
def get_one_by_query(self, table_name: str, query: str = "1=1", sort: Optional[str] = None, ascending=True, values: dict = {}) -> list:
|
||||
query = "select * from {} where {} {}".format(table_name, query, "ORDER BY {} {}".format(sort, "ASC" if ascending else "DESC") if sort else "")
|
||||
def get_one_by_query(self, table_name: str, query: str = "1=1", values: dict = {}, sort: Optional[str] = None, ascending=True, limit: Optional[int] = None) -> list:
|
||||
query = "select * from {} where {} {} {}".format(
|
||||
table_name,
|
||||
query,
|
||||
"ORDER BY {} {}".format(sort, "ASC" if ascending else "DESC") if sort else "",
|
||||
"LIMIT {}".format(limit) if limit else ""
|
||||
)
|
||||
lines = self.execute_read_query(query=query, params=tuple(v for v in values.values()))
|
||||
count = len(lines)
|
||||
|
||||
@ -216,6 +221,7 @@ class DatabaseManager:
|
||||
"DROP TABLE IF EXISTS fleet_studio",
|
||||
"ALTER TABLE slideshow RENAME TO slides",
|
||||
"DELETE FROM settings WHERE name = 'fleet_studio_enabled'",
|
||||
"DELETE FROM settings WHERE name = 'default_slide_duration'",
|
||||
"UPDATE content SET uuid = id WHERE uuid = '' or uuid is null",
|
||||
]
|
||||
|
||||
|
||||
@ -72,10 +72,9 @@ class NodePlayerGroupManager(ModelManager):
|
||||
|
||||
def get_node_players_groups(self, playlist_id: Optional[int] = None) -> List[NodePlayerGroup]:
|
||||
query = " 1=1 "
|
||||
|
||||
if playlist_id:
|
||||
query = "{} {}".format(query, "AND playlist_id = {}".format(playlist_id))
|
||||
else:
|
||||
query = "{} {}".format(query, "AND playlist_id is NULL")
|
||||
|
||||
return self.get_by(query=query, sort="name")
|
||||
|
||||
|
||||
@ -3,7 +3,8 @@ import os
|
||||
from typing import Dict, Optional, List, Tuple, Union
|
||||
|
||||
from src.model.entity.Playlist import Playlist
|
||||
from src.util.utils import get_optional_string, get_yt_video_id, slugify
|
||||
from src.util.utils import get_optional_string, get_yt_video_id, slugify, slugify_next
|
||||
from src.exceptions.PlaylistSlugAlreadyExist import PlaylistSlugAlreadyExist
|
||||
from src.manager.DatabaseManager import DatabaseManager
|
||||
from src.manager.SlideManager import SlideManager
|
||||
from src.manager.LangManager import LangManager
|
||||
@ -54,8 +55,8 @@ class PlaylistManager(ModelManager):
|
||||
def get_by(self, query, sort: Optional[str] = None, values: dict = {}) -> List[Playlist]:
|
||||
return self.hydrate_list(self._db.get_by_query(self.TABLE_NAME, query=query, sort=sort, values=values))
|
||||
|
||||
def get_one_by(self, query, values: dict = {}) -> Optional[Playlist]:
|
||||
object = self._db.get_one_by_query(self.TABLE_NAME, query=query, values=values)
|
||||
def get_one_by(self, query, values: dict = {}, sort: Optional[str] = None, ascending=True, limit: Optional[int] = None) -> Optional[Playlist]:
|
||||
object = self._db.get_one_by_query(self.TABLE_NAME, query=query, values=values, sort=sort, ascending=ascending, limit=limit)
|
||||
|
||||
if not object:
|
||||
return None
|
||||
@ -105,8 +106,25 @@ class PlaylistManager(ModelManager):
|
||||
for playlist_id, edits in edits_playlists.items():
|
||||
self._db.update_by_id(self.TABLE_NAME, playlist_id, edits)
|
||||
|
||||
def get_available_slug(self, slug) -> str:
|
||||
known_playlist = {"slug": slug}
|
||||
next_slug = slug
|
||||
while known_playlist is not None:
|
||||
next_slug = slugify_next(next_slug)
|
||||
known_playlist = self.get_one_by(query="slug = ?", values={"slug": next_slug}, sort="created_at", ascending=False, limit=1)
|
||||
|
||||
return next_slug
|
||||
|
||||
def pre_add(self, playlist: Dict) -> Dict:
|
||||
playlist["slug"] = slugify(playlist["name"])
|
||||
|
||||
known_playlist = self.get_one_by(query="slug = ?", values={
|
||||
"slug": playlist["slug"]
|
||||
}, sort="created_at", ascending=False, limit=1)
|
||||
|
||||
if known_playlist:
|
||||
playlist["slug"] = self.get_available_slug(playlist["slug"])
|
||||
|
||||
self.user_manager.track_user_on_create(playlist)
|
||||
self.user_manager.track_user_on_update(playlist)
|
||||
return playlist
|
||||
@ -131,7 +149,7 @@ class PlaylistManager(ModelManager):
|
||||
def post_delete(self, playlist_id: str) -> str:
|
||||
return playlist_id
|
||||
|
||||
def update_form(self, id: int, name: str, time_sync: bool) -> None:
|
||||
def update_form(self, id: int, name: str, time_sync: bool, enabled: bool) -> None:
|
||||
playlist = self.get(id)
|
||||
|
||||
if not playlist:
|
||||
@ -139,13 +157,14 @@ class PlaylistManager(ModelManager):
|
||||
|
||||
form = {
|
||||
"name": name,
|
||||
"time_sync": time_sync
|
||||
"time_sync": time_sync,
|
||||
"enabled": enabled
|
||||
}
|
||||
|
||||
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update(form))
|
||||
self.post_update(id)
|
||||
|
||||
def add_form(self, playlist: Union[Playlist, Dict]) -> None:
|
||||
def add_form(self, playlist: Union[Playlist, Dict]) -> Playlist:
|
||||
form = playlist
|
||||
|
||||
if not isinstance(playlist, dict):
|
||||
@ -153,7 +172,11 @@ class PlaylistManager(ModelManager):
|
||||
del form['id']
|
||||
|
||||
self._db.add(self.TABLE_NAME, self.pre_add(form))
|
||||
playlist = self.get_one_by(query="slug = ?", values={
|
||||
"slug": form["slug"]
|
||||
})
|
||||
self.post_add(playlist.id)
|
||||
return playlist
|
||||
|
||||
def delete(self, id: int) -> None:
|
||||
playlist = self.get(id)
|
||||
|
||||
@ -73,13 +73,14 @@ class SlideManager(ModelManager):
|
||||
for slide_id, edits in edits_slides.items():
|
||||
self._db.update_by_id(self.TABLE_NAME, slide_id, edits)
|
||||
|
||||
def get_slides(self, playlist_id: Optional[int] = None, content_id: Optional[int] = None, enabled: bool = True) -> List[Slide]:
|
||||
query = "enabled = {}".format("1" if enabled else "0")
|
||||
def get_slides(self, playlist_id: Optional[int] = None, content_id: Optional[int] = None, enabled: Optional[bool] = None) -> List[Slide]:
|
||||
query = " 1=1 "
|
||||
|
||||
if enabled is not None:
|
||||
query = "{} AND enabled = {} ".format(query, "1" if enabled else "0")
|
||||
|
||||
if playlist_id:
|
||||
query = "{} {}".format(query, "AND playlist_id = {}".format(playlist_id))
|
||||
else:
|
||||
query = "{} {}".format(query, "AND playlist_id is NULL")
|
||||
|
||||
if content_id:
|
||||
query = "{} {}".format(query, "AND content_id = {}".format(content_id))
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import json
|
||||
import time
|
||||
import math
|
||||
from typing import Dict, Optional, List, Tuple, Union
|
||||
|
||||
from src.manager.DatabaseManager import DatabaseManager
|
||||
@ -111,7 +112,7 @@ class VariableManager:
|
||||
{"name": "slide_upload_limit", "section": self.t(VariableSection.GENERAL), "value": 32, "unit": VariableUnit.MEGABYTE, "type": VariableType.INT, "editable": True, "description": self.t('settings_variable_desc_slide_upload_limit'), "refresh_player": False},
|
||||
|
||||
### Player Options
|
||||
{"name": "default_slide_duration", "section": self.t(VariableSection.PLAYER_OPTIONS), "value": 3, "unit": VariableUnit.SECOND, "type": VariableType.INT, "editable": True, "description": self.t('settings_variable_desc_default_slide_duration'), "refresh_player": False},
|
||||
{"name": "intro_slide_duration", "section": self.t(VariableSection.PLAYER_OPTIONS), "value": 3, "unit": VariableUnit.SECOND, "type": VariableType.INT, "editable": True, "description": self.t('settings_variable_desc_intro_slide_duration'), "refresh_player": False},
|
||||
{"name": "default_slide_time_with_seconds", "section": self.t(VariableSection.PLAYER_OPTIONS), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_default_slide_time_with_seconds'), "refresh_player": False},
|
||||
{"name": "polling_interval", "section": self.t(VariableSection.PLAYER_OPTIONS), "value": 5, "unit": VariableUnit.SECOND, "type": VariableType.INT, "editable": True, "description": self.t('settings_variable_desc_polling_interval'), "refresh_player": True},
|
||||
|
||||
@ -132,6 +133,7 @@ class VariableManager:
|
||||
{"name": "auth_enabled", "section": self.t(VariableSection.SECURITY), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_auth_enabled'), "description_edition": self.t('settings_variable_desc_edition_auth_enabled'), "refresh_player": False},
|
||||
|
||||
# Not editable (System information)
|
||||
{"name": "start_counter", "value": 0, "type": VariableType.INT, "editable": False, "description": self.t('settings_variable_desc_ro_start_counter')},
|
||||
{"name": "last_folder_content", "value": FOLDER_ROOT_PATH, "type": VariableType.STRING, "editable": False, "description": self.t('settings_variable_desc_ro_last_folder_content')},
|
||||
{"name": "last_folder_node_player", "value": FOLDER_ROOT_PATH, "type": VariableType.STRING, "editable": False, "description": self.t('settings_variable_desc_ro_last_folder_node_player')},
|
||||
{"name": "last_restart", "value": time.time(), "type": VariableType.TIMESTAMP, "editable": False, "description": self.t('settings_variable_desc_ro_editable')},
|
||||
|
||||
@ -89,7 +89,7 @@ class Playlist:
|
||||
return f"Playlist(" \
|
||||
f"id='{self.id}',\n" \
|
||||
f"name='{self.name}',\n" \
|
||||
f"nameslug='{self.slug}',\n" \
|
||||
f"slug='{self.slug}',\n" \
|
||||
f"enabled='{self.enabled}',\n" \
|
||||
f"time_sync='{self.time_sync}',\n" \
|
||||
f"created_by='{self.created_by}',\n" \
|
||||
|
||||
@ -3,11 +3,6 @@ from enum import Enum
|
||||
|
||||
class HookType(Enum):
|
||||
|
||||
H_SLIDESHOW_SLIDES_TOOLBAR_ACTIONS_START = 'h_slideshow_slides_toolbar_actions_start'
|
||||
H_SLIDESHOW_SLIDES_TOOLBAR_ACTIONS_END = 'h_slideshow_slides_toolbar_actions_end'
|
||||
H_SLIDESHOW_SLIDES_CSS = 'h_slideshow_slides_css'
|
||||
H_SLIDESHOW_SLIDES_JAVASCRIPT = 'h_slideshow_slides_javascript'
|
||||
|
||||
H_SLIDESHOW_CONTENT_TOOLBAR_ACTIONS_START = 'h_slideshow_toolbar_actions_start'
|
||||
H_SLIDESHOW_CONTENT_TOOLBAR_ACTIONS_END = 'h_slideshow_toolbar_actions_end'
|
||||
H_SLIDESHOW_CONTENT_CSS = 'h_slideshow_css'
|
||||
|
||||
@ -255,3 +255,13 @@ def merge_dicts(dict1, dict2):
|
||||
|
||||
def dictsort(dict1, attribute="position"):
|
||||
return dict(sorted(dict1.items(), key=lambda item: item[1][attribute]))
|
||||
|
||||
|
||||
def slugify_next(slug: str) -> str:
|
||||
parts = slug.rsplit('-', 1)
|
||||
|
||||
if len(parts) > 1 and parts[-1].isdigit():
|
||||
next_number = int(parts[-1]) + 1
|
||||
return f"{parts[0]}-{next_number}"
|
||||
else:
|
||||
return f"{slug}-1"
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
"position": 0,
|
||||
"pills": [
|
||||
{"name": "Bibliothèque", "route": "slideshow_content_list", "icon": "fa-image"},
|
||||
{"name": "Playlists", "route": "playlist_list", "icon": "fa-play"},
|
||||
{"name": "Playlists", "route": "playlist", "icon": "fa-play"},
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
@ -115,7 +115,7 @@
|
||||
{% block header %}
|
||||
<menu>
|
||||
<h1 class="logo">
|
||||
<a href="{{ url_for('slideshow_slide_list') }}">
|
||||
<a href="{{ url_for('playlist') }}">
|
||||
<img src="{{ STATIC_PREFIX }}img/logo2.png" class="before"/>
|
||||
<img src="{{ STATIC_PREFIX }}img/logo2white.png" class="after"/>
|
||||
Obscreen
|
||||
@ -164,7 +164,8 @@
|
||||
<ul class="pills">
|
||||
{% for menu in current_dynmenu.pills %}
|
||||
<li class="{{ 'active' if active_route == menu.route }}">
|
||||
<a href="{{ url_for(menu.route) }}">
|
||||
{% set href = menu.url_for if menu.url_for else url_for(menu.route) %}
|
||||
<a href="{{ href }}">
|
||||
<span class="icon">
|
||||
<i class="fa {{ menu.icon }}"></i>
|
||||
</span>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
{% block add_css %}
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/jquery-explr-1.4.css"/>
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_CSS) }}
|
||||
{{ HOOK(H_FLEET_NODE_PLAYER_CSS) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block add_js %}
|
||||
@ -14,8 +14,7 @@
|
||||
<script src="{{ STATIC_PREFIX }}js/explorer.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/fleet/node-players.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/jquery-ui.min.js"></script>
|
||||
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_JAVASCRIPT) }}
|
||||
{{ HOOK(H_FLEET_NODE_PLAYER_JAVASCRIPT) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body_class %}view-node-player-list{% endblock %}
|
||||
@ -27,7 +26,7 @@
|
||||
</h1>
|
||||
|
||||
<div class="top-actions">
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_TOOLBAR_ACTIONS_START) }}
|
||||
{{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_START) }}
|
||||
|
||||
<div class="explr-selection-actions">
|
||||
<button class="explr-item-edit explr-selection-entity btn-info" data-entity-route="{{ url_for('fleet_node_player_edit', node_player_id='!c!') }}">
|
||||
@ -49,7 +48,7 @@
|
||||
<i class="fa fa-folder-plus icon-left"></i>
|
||||
{{ l.common_new_folder }}
|
||||
</button>
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_TOOLBAR_ACTIONS_END) }}
|
||||
{{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_END) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -74,7 +73,7 @@
|
||||
{% set node_player_children = node_players[folder.id]|default([]) %}
|
||||
{% set has_children = folder.children or node_player_children %}
|
||||
|
||||
<li class="icon-folder li-explr-folder li-explr-folder-{{ folder.id }}">
|
||||
<li class="icon-folder li-explr-folder li-explr-folder-{{ folder.id if folder.id else 0 }}">
|
||||
<a href="{{ url_for('fleet_node_player_cd') }}?path={{ folder.path }}" class="{% if folder.path == working_folder_path %}active{% endif %}">
|
||||
{{ folder.name }}
|
||||
</a>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="google" content="notranslate">
|
||||
<link rel="shortcut icon" href="{{ STATIC_PREFIX }}/favicon.ico">
|
||||
{% if slide_animation_enabled.eval() %}
|
||||
{% if slide_animation_enabled %}
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/animate.min.css" />
|
||||
{% endif %}
|
||||
<style>
|
||||
@ -20,7 +20,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="IntroSlide" class="slide" style="z-index: 10000;">
|
||||
{% if default_slide_duration > 0 %}
|
||||
{% if intro_slide_duration > 0 %}
|
||||
<iframe src="/player/default"></iframe>
|
||||
{% endif %}
|
||||
</div>
|
||||
@ -37,7 +37,7 @@
|
||||
<script type="text/javascript">
|
||||
// Backend config
|
||||
let items = {{ json_dumps(items) | safe}};
|
||||
const introDuration = {{ default_slide_duration * 1000 }};
|
||||
const introDuration = {{ intro_slide_duration * 1000 }};
|
||||
const playlistCheckResolutionMs = {{ polling_interval.eval() * 1000 }};
|
||||
|
||||
// Backend flag updates
|
||||
@ -59,9 +59,9 @@
|
||||
let pauseClockValue = null;
|
||||
|
||||
// Animations
|
||||
const animate = {{ 'true' if slide_animation_enabled.eval() and not items.preview_mode else 'false' }};
|
||||
const animate = {{ 'true' if slide_animation_enabled and not items.preview_mode else 'false' }};
|
||||
const animate_speed = "animate__{{ slide_animation_speed.eval()|default("normal") }}";
|
||||
const animation_speed_duration = {{ animation_speed_duration[slide_animation_speed.eval()] if slide_animation_enabled.eval() else 0 }};
|
||||
const animation_speed_duration = {{ animation_speed_duration[slide_animation_speed.eval()] if slide_animation_enabled else 0 }};
|
||||
const animate_transitions = [
|
||||
"animate__{{ slide_animation_entrance_effect.eval()|default("fadeIn") }}",
|
||||
"animate__{{ slide_animation_exit_effect.eval()|default("none") }}"
|
||||
|
||||
113
views/playlist/component/edit.jinja.html
Normal file
113
views/playlist/component/edit.jinja.html
Normal file
@ -0,0 +1,113 @@
|
||||
<div class="horizontal">
|
||||
<div class="form-holder vertical">
|
||||
|
||||
<h3>
|
||||
{{ l.playlist_panel_about_playlist }}
|
||||
</h3>
|
||||
|
||||
<form class="form" action="{{ url_for('playlist_save') }}" method="POST">
|
||||
<input type="hidden" name="id" id="playlist-edit-id" value="{{ current_playlist.id }}"/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="playlist-edit-name">{{ l.playlist_form_label_name }}</label>
|
||||
<div class="widget">
|
||||
<input type="text" name="name" id="playlist-edit-name" required="required"
|
||||
value="{{ current_playlist.name }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-horizontal">
|
||||
<label for="playlist-edit-enabled">{{ l.playlist_form_label_enabled }}</label>
|
||||
<div class="widget">
|
||||
<div class="toggle">
|
||||
<input type="checkbox" id="playlist-edit-enabled" name="enabled"
|
||||
{% if current_playlist.enabled %}checked="checked"{% endif %}>
|
||||
<label for="playlist-edit-enabled"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-horizontal">
|
||||
<label for="playlist-edit-time-sync">{{ l.playlist_form_label_time_sync }}</label>
|
||||
<div class="widget">
|
||||
<div class="toggle">
|
||||
<input type="checkbox" id="playlist-edit-time-sync" name="time_sync"
|
||||
{% if current_playlist.time_sync %}checked="checked"{% endif %}>
|
||||
<label for="playlist-edit-time-sync"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions actions-right">
|
||||
<button type="submit" class="btn-success-alt">
|
||||
<i class="fa fa-save icon-left"></i>
|
||||
{{ l.common_save }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="slides-holder">
|
||||
<h3>
|
||||
{{ l.playlist_panel_content_management }}
|
||||
|
||||
<div>
|
||||
<button class="btn btn-info slide-add">
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
{% with slides=slides %}
|
||||
{% include 'slideshow/slides/component/table.jinja.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="preview-holder vertical">
|
||||
<div class="form-group">
|
||||
<h4>
|
||||
URL
|
||||
</h4>
|
||||
<p>
|
||||
{{ l.playlist_form_preview_url_desc }}
|
||||
</p>
|
||||
{% set preview_url = request.scheme ~ '://' ~ request.headers.get('host') ~ url_for('player_use', playlist_slug_or_id=current_playlist.slug) %}
|
||||
<div class="widget">
|
||||
<input type="text" name="name" id="playlist-preview-url" required="required" value="{{ preview_url }}"
|
||||
class="disabled" disabled="disabled"/>
|
||||
<button class="btn btn-naked copy-link" data-target-id="playlist-preview-url">
|
||||
<i class="fa fa-copy"></i>
|
||||
</button>
|
||||
|
||||
<a href="{{ preview_url }}" class="btn btn-neutral" target="_blank">
|
||||
<i class="fa-solid fa-up-right-from-square"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h4 class="divide">
|
||||
QR Code
|
||||
</h4>
|
||||
<p>
|
||||
{{ l.playlist_form_preview_qrcode_desc }}
|
||||
</p>
|
||||
<div id="qrcode" class="qrcode-pic" data-qrcode-payload="{{ preview_url }}"></div>
|
||||
</div>
|
||||
|
||||
<h4 class="divide">
|
||||
Iframe
|
||||
</h4>
|
||||
<p>
|
||||
{{ l.playlist_form_preview_iframe_desc }}
|
||||
</p>
|
||||
|
||||
<div class="preview">
|
||||
<button class="btn btn-info btn-naked"
|
||||
onclick="$(this).parent().find('iframe').removeClass('hidden');$(this).addClass('hidden');">
|
||||
<i class="fa fa-eye icon-left"></i> {{ l.playlist_panel_preview_action }}
|
||||
</button>
|
||||
<iframe src="{{ preview_url }}?intro=0&animation=0" frameborder="0" class="hidden"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,86 +1,46 @@
|
||||
<table class="{{ tclass }}-playlists">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ l.playlist_panel_th_name }}</th>
|
||||
{% if AUTH_ENABLED %}
|
||||
<th class="tac">
|
||||
<i class="fa fa-user"></i>
|
||||
</th>
|
||||
{% endif %}
|
||||
<th class="tac"><i class="fa fa-compass"></i></th>
|
||||
<th class="tac">{{ l.playlist_panel_th_enabled }}</th>
|
||||
<th class="tac">{{ l.playlist_panel_th_duration }}</th>
|
||||
<th class="tac">{{ l.playlist_panel_th_activity }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="empty-tr {% if playlists|length != 0 %}hidden{% endif %}">
|
||||
<td colspan="4">
|
||||
{{ l.playlist_panel_empty|replace(
|
||||
'%link%',
|
||||
('<a href="javascript:void(0);" class="item-add playlist-add">'~l.playlist_button_add~'</a>')|safe
|
||||
) }}
|
||||
</td>
|
||||
</tr>
|
||||
<div class="tiles playlists">
|
||||
<div class="tiles-inner">
|
||||
{% for playlist in playlists %}
|
||||
<tr class="playlist-item" data-level="{{ playlist.id }}" data-entity="{{ playlist.to_json({"created_by": track_created(playlist).username, "updated_by": track_updated(playlist).username}) }}">
|
||||
<td class="infos">
|
||||
<div class="inner">
|
||||
{% if playlist.id %}
|
||||
<div class="badge"><i class="fa fa-key icon-left"></i> {{ playlist.id }}</div>
|
||||
{% else %}
|
||||
<div class="badge"><i class="fa fa-lock"></i></div>
|
||||
{% endif %}
|
||||
<i class="fa fa-bars-staggered icon-left"></i>
|
||||
|
||||
{{ playlist.name }}
|
||||
{% set active = current_playlist and ''~playlist.id == ''~current_playlist.id %}
|
||||
<a href="{{ url_for('playlist_list', playlist_id=playlist.id) }}"
|
||||
class="{% if active %}active{% endif %} tile-item {% if not playlist.enabled %}disabled{% endif %} playlist-item"
|
||||
data-level="{{ playlist.id }}"
|
||||
data-entity="{{ playlist.to_json({"created_by": track_created(playlist).username, "updated_by": track_updated(playlist).username}) }}">
|
||||
<div class="tile-header">
|
||||
<div class="head-icon">
|
||||
<i class="fa {{ 'fa fa-circle' if active else 'fa fa-circle' }}"></i>
|
||||
</div>
|
||||
</td>
|
||||
{% if AUTH_ENABLED %}
|
||||
<td class="tac">
|
||||
{% if playlist.id %}
|
||||
{% set creator = track_created(playlist) %}
|
||||
{% if creator.username %}
|
||||
<a href="javascript:void(0);" class="badge item-utrack playlist-utrack {% if not creator.enabled %}anonymous{% endif %}">
|
||||
{{ creator.username }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td class="tac">
|
||||
{% if playlist.time_sync %}
|
||||
<i class="fa fa-check"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-times"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="tac">
|
||||
{% if playlist.id %}
|
||||
<label class="pure-material-switch">
|
||||
<input type="checkbox" {% if playlist.enabled %}checked="checked"{% endif %}><span></span>
|
||||
</label>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="tac">
|
||||
</div>
|
||||
<div class="tile-body">
|
||||
{% set title = playlist.name|trim %}
|
||||
{% set title = title if title|length > 0 %}
|
||||
{{ truncate((title)|default(l.common_untitled), 35, '...') }}
|
||||
</div>
|
||||
<div class="tile-footer">
|
||||
<div class="foot-span">
|
||||
{% set total_duration = seconds_to_hhmmss(durations[playlist.id]) %}
|
||||
{% if total_duration %}
|
||||
{{ total_duration }}
|
||||
{% else %}
|
||||
{{ l.common_empty }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="actions tac">
|
||||
</div>
|
||||
{% if AUTH_ENABLED %}
|
||||
{% if playlist.id %}
|
||||
<a href="javascript:void(0);" class="item-edit playlist-edit">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a href="javascript:void(0);" class="item-delete playlist-delete">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
{% set creator = track_created(playlist) %}
|
||||
{% if creator.username %}
|
||||
<div class="foot-span {% if not creator.enabled %}anonymous{% endif %}">
|
||||
{{ creator.username }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="inner-empty empty-flag {% if playlists|length != 0 %}hidden{% endif %}">
|
||||
<i class="fa fa-play"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -6,13 +6,34 @@
|
||||
|
||||
{% block add_css %}
|
||||
{{ HOOK(H_PLAYLIST_CSS) }}
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/flatpickr.min.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block add_js %}
|
||||
<script type="text/javascript">
|
||||
var schedule_start_choices = {
|
||||
'loop': '{{ l.slideshow_slide_form_label_cron_scheduled_loop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'cron': '{{ l.slideshow_slide_form_label_cron_scheduled_cron }}',
|
||||
};
|
||||
var schedule_end_choices = {
|
||||
'stayloop': '{{ l.slideshow_slide_form_label_cron_scheduled_stayloop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'duration': '{{ l.slideshow_slide_form_label_cron_scheduled_duration }}',
|
||||
};
|
||||
var contents = {{ json_dumps(contents) | safe }}
|
||||
</script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/flatpickr.min.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/tablednd-fixed.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/qrcode.min.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/slideshow/slides.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/playlist/playlists.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/restart.js"></script>
|
||||
{{ HOOK(H_PLAYLIST_JAVASCRIPT) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body_class %}view-playlist-list{% endblock %}
|
||||
|
||||
{% block page %}
|
||||
|
||||
<div class="top-content">
|
||||
@ -26,21 +47,49 @@
|
||||
<i class="fa fa-play icon-left"></i>
|
||||
{{ l.playlist_button_add }}
|
||||
</button>
|
||||
|
||||
{% if current_playlist %}
|
||||
<a href="{{ url_for('playlist_delete', playlist_id=current_playlist.id) }}" class="btn btn-danger-alt protected">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{{ HOOK(H_PLAYLIST_TOOLBAR_ACTIONS_END) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info tiles-empty empty-flag {% if playlists|length != 0 %}hidden{% endif %}">
|
||||
{{ l.playlist_panel_empty|replace(
|
||||
'%link%',
|
||||
('<a href="javascript:void(0);" class="item-add playlist-add">'~l.playlist_button_add~'</a>')|safe
|
||||
) }}
|
||||
</div>
|
||||
|
||||
{% if request.args.get('refresh_player') %}
|
||||
<div class="alert alert-success">
|
||||
<i class="fa fa-refresh icon-left"></i>
|
||||
{{ l.slideshow_slide_refresh_player_success|replace('%time%', request.args.get('refresh_player')) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ l[error] }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="bottom-content">
|
||||
<div class="page-content">
|
||||
<div class="inner">
|
||||
<div class="panel">
|
||||
<div class="panel-body">
|
||||
<h3>{{ l.sysinfo_panel_title }}</h3>
|
||||
<div class="page-panel left-panel">
|
||||
{% with playlists=playlists %}
|
||||
{% include 'playlist/component/table.jinja.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="inner">
|
||||
{% with playlists=playlists %}
|
||||
{% include 'playlist/component/edit.jinja.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -49,6 +98,9 @@
|
||||
<div class="modals-outer">
|
||||
<div class="modals-inner">
|
||||
{% include 'playlist/modal/add.jinja.html' %}
|
||||
{% include 'playlist/modal/qrcode.jinja.html' %}
|
||||
{% include 'slideshow/slides/modal/add.jinja.html' %}
|
||||
{% include 'slideshow/slides/modal/edit.jinja.html' %}
|
||||
{% include 'core/utrack.jinja.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
<div class="modal modal-playlist-edit modal-playlist hidden">
|
||||
<h2>
|
||||
{{ l.playlist_form_edit_title }}
|
||||
</h2>
|
||||
|
||||
|
||||
<form class="form" action="/playlist/edit" method="POST">
|
||||
|
||||
<input type="hidden" name="id" id="playlist-edit-id" />
|
||||
|
||||
<div class="form-group">
|
||||
<label for="playlist-edit-name">{{ l.playlist_form_label_name }}</label>
|
||||
<div class="widget">
|
||||
<input type="text" name="name" id="playlist-edit-name" required="required" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="playlist-edit-time-sync">{{ l.playlist_form_label_time_sync }}</label>
|
||||
<div class="widget">
|
||||
<select name="time_sync" type="text" id="playlist-edit-time-sync" required="required">
|
||||
<option value="1">✅</option>
|
||||
<option value="0">❌</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" class="btn-normal modal-close">
|
||||
{{ l.playlist_form_button_cancel }}
|
||||
</button>
|
||||
<button type="submit" class="green">
|
||||
<i class="fa fa-save icon-left"></i>{{ l.playlist_form_edit_submit }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
13
views/playlist/modal/qrcode.jinja.html
Normal file
13
views/playlist/modal/qrcode.jinja.html
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="modal modal-playlist-qrcode modal-playlist">
|
||||
<h2>
|
||||
{{ l.playlist_form_show_qrcode }}
|
||||
</h2>
|
||||
|
||||
<div id="qrcode" class="qrcode-pic"></div>
|
||||
|
||||
<div class="actions actions-center">
|
||||
<button type="button" class="btn btn-naked modal-close">
|
||||
<i class="fa fa-close icon-left"></i>{{ l.common_close }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,77 +1,15 @@
|
||||
{% extends 'base.jinja.html' %}
|
||||
|
||||
{% block page_title %}
|
||||
{{ l.slideshow_slide_page_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block add_css %}
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/flatpickr.min.css" />
|
||||
{{ HOOK(H_SLIDESHOW_SLIDES_CSS) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block add_js %}
|
||||
<script type="text/javascript">
|
||||
var schedule_start_choices = {
|
||||
'loop': '{{ l.slideshow_slide_form_label_cron_scheduled_loop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'cron': '{{ l.slideshow_slide_form_label_cron_scheduled_cron }}',
|
||||
};
|
||||
var schedule_end_choices = {
|
||||
'stayloop': '{{ l.slideshow_slide_form_label_cron_scheduled_stayloop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'duration': '{{ l.slideshow_slide_form_label_cron_scheduled_duration }}',
|
||||
};
|
||||
var contents = {{ json_dumps(contents) | safe }}
|
||||
</script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/flatpickr.min.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/tablednd-fixed.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/slideshow/slides.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/restart.js"></script>
|
||||
{{ HOOK(H_SLIDESHOW_SLIDES_JAVASCRIPT) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block page %}
|
||||
<div class="toolbar">
|
||||
<h2><i class="fa-regular fa-clock icon-left"></i>{{ l.slideshow_slide_page_title }}</h2>
|
||||
|
||||
<div class="toolbar-actions">
|
||||
{{ HOOK(H_SLIDESHOW_SLIDES_TOOLBAR_ACTIONS_START) }}
|
||||
|
||||
<a href="{% if current_playlist %}{{ url_for('player_use', playlist_slug_or_id=current_playlist.slug) }}{% else %}{{ url_for('player') }}{% endif %}" target="_blank" class="btn" title="{{ l.slideshow_slide_goto_player }}">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('slideshow_player_refresh') }}" class="btn" title="{{ l.slideshow_slide_refresh_player }}">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</a>
|
||||
|
||||
<button class="purple slide-add item-add"><i class="fa fa-plus icon-left"></i>{{ l.slideshow_slide_button_add }}</button>
|
||||
|
||||
|
||||
{% if PLAYLIST_ENABLED %}
|
||||
<select class="select-item-picker playlist-picker">
|
||||
<option value="{{ url_for('slideshow_slide_list') }}" {% if not current_playlist %}selected="selected"{% endif %}>
|
||||
{{ l.common_default_playlist }}
|
||||
</option>
|
||||
{% for playlist in playlists %}
|
||||
{% set is_active_playlist = str(current_playlist.id) == str(playlist.id) %}
|
||||
<option value="{{ url_for('slideshow_slide_list_playlist_use', playlist_id=playlist.id) }}" {% if is_active_playlist %}selected="selected"{% endif %}>
|
||||
{{ playlist.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
|
||||
{{ HOOK(H_SLIDESHOW_SLIDES_TOOLBAR_ACTIONS_END) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if request.args.get('refresh_player') %}
|
||||
<div class="alert alert-success">
|
||||
<i class="fa fa-refresh icon-left"></i>
|
||||
{{ l.slideshow_slide_refresh_player_success|replace('%time%', request.args.get('refresh_player')) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="panel {% if PLAYLIST_ENABLED %}panel-active{% endif %}">
|
||||
<div class="panel-body">
|
||||
@ -82,26 +20,5 @@
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-inactive">
|
||||
<div class="panel-body">
|
||||
<h3>{{ l.slideshow_slide_panel_inactive }}</h3>
|
||||
|
||||
{% with tclass='inactive', slides=disabled_slides %}
|
||||
{% include 'slideshow/slides/component/table.jinja.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modals hidden">
|
||||
<div class="modals-outer">
|
||||
<a href="javascript:void(0);" class="modal-close">
|
||||
<i class="fa fa-close"></i>
|
||||
</a>
|
||||
<div class="modals-inner">
|
||||
{% include 'slideshow/slides/modal/add.jinja.html' %}
|
||||
{% include 'slideshow/slides/modal/edit.jinja.html' %}
|
||||
{% include 'core/utrack.jinja.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{{ l.slideshow_slide_form_add_title }}
|
||||
</h2>
|
||||
|
||||
<form class="form" action="/slideshow/slide/add" method="POST" enctype="multipart/form-data">
|
||||
<form class="form" action="{{ url_for('slideshow_slide_add') }}" method="POST" enctype="multipart/form-data">
|
||||
|
||||
<h3>
|
||||
{{ l.slideshow_slide_form_section_content }}
|
||||
@ -36,7 +36,7 @@
|
||||
<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" />
|
||||
<input name="name" type="text" id="slide-add-name" required="required" disabled="disabled"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -56,25 +56,27 @@
|
||||
<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" />
|
||||
<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>
|
||||
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
<h3 class="divide">
|
||||
{{ l.slideshow_slide_form_section_scheduling }}
|
||||
</h3>
|
||||
|
||||
<div class="form-group slide-notification-group">
|
||||
<label for="slide-add-is-notification">{{ l.slideshow_slide_form_label_is_notification }}</label>
|
||||
<div class="widget">
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification" id="slide-add-is-notification" />
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification"
|
||||
id="slide-add-is-notification"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group slide-schedule-group">
|
||||
<label for="slide-add-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label>
|
||||
<div class="widget">
|
||||
@ -83,8 +85,10 @@
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<input type="text" id="slide-add-cron-schedule-datetimepicker" class="datetimepicker" value="" placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}" />
|
||||
<input type="text" name="cron_schedule" id="slide-add-cron-schedule" class="target hidden" placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}" />
|
||||
<input type="text" id="slide-add-cron-schedule-datetimepicker" class="datetimepicker" value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
<input type="text" name="cron_schedule" id="slide-add-cron-schedule" class="target hidden"
|
||||
placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -96,29 +100,32 @@
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<input type="text" id="slide-add-cron-schedule-end-datetimepicker" class="datetimepicker" value="" placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}" />
|
||||
<input type="text" name="cron_schedule_end" id="slide-add-cron-schedule-end" class="target hidden" placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}" />
|
||||
<input type="text" id="slide-add-cron-schedule-end-datetimepicker" class="datetimepicker" value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
<input type="text" name="cron_schedule_end" id="slide-add-cron-schedule-end" class="target hidden"
|
||||
placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group slide-duration-group">
|
||||
<label for="slide-add-duration">{{ l.slideshow_slide_form_label_duration }}</label>
|
||||
<div class="widget">
|
||||
<input type="number" name="duration" id="slide-add-duration" required="required" />
|
||||
<input type="number" name="duration" id="slide-add-duration" required="required"/>
|
||||
<span>{{ l.slideshow_slide_form_label_duration_unit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" class="btn-normal modal-close">
|
||||
{{ l.slideshow_slide_form_button_cancel }}
|
||||
<button type="button" class="btn btn-naked modal-close">
|
||||
{{ l.common_close }}
|
||||
</button>
|
||||
<button type="submit" class="green">
|
||||
<i class="fa fa-plus icon-left"></i> {{ l.slideshow_slide_form_add_submit }}
|
||||
<button type="submit" class="btn btn-info">
|
||||
<i class="fa fa-save icon-left"></i>{{ l.common_save }}
|
||||
</button>
|
||||
<button type="button" disabled="disabled" class="green hidden btn-loading">
|
||||
<button type="button" disabled="disabled" class="btn btn-naked hidden btn-loading">
|
||||
{{ l.common_loading }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@ -4,14 +4,14 @@
|
||||
</h2>
|
||||
|
||||
|
||||
<form class="form" action="/slideshow/slide/edit" method="POST">
|
||||
<form class="form" action="{{ url_for('slideshow_slide_edit') }}" method="POST">
|
||||
|
||||
<h3>
|
||||
{{ l.slideshow_slide_form_section_content }}
|
||||
</h3>
|
||||
|
||||
|
||||
<input type="hidden" name="id" id="slide-edit-id" />
|
||||
<input type="hidden" name="id" id="slide-edit-id"/>
|
||||
|
||||
|
||||
<div class="form-group slide-content-id-group">
|
||||
@ -22,14 +22,15 @@
|
||||
</div>
|
||||
|
||||
|
||||
<h3>
|
||||
<h3 class="divide">
|
||||
{{ l.slideshow_slide_form_section_scheduling }}
|
||||
</h3>
|
||||
|
||||
<div class="form-group slide-notification-group">
|
||||
<label for="slide-edit-is-notification">{{ l.slideshow_slide_form_label_is_notification }}</label>
|
||||
<div class="widget">
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification" id="slide-edit-is-notification" />
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification"
|
||||
id="slide-edit-is-notification"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -41,8 +42,10 @@
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<input type="text" id="slide-edit-cron-schedule-datetimepicker" class="datetimepicker" value="" placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}" />
|
||||
<input type="text" name="cron_schedule" id="slide-edit-cron-schedule" class="target hidden" placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}" />
|
||||
<input type="text" id="slide-edit-cron-schedule-datetimepicker" class="datetimepicker" value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
<input type="text" name="cron_schedule" id="slide-edit-cron-schedule" class="target hidden"
|
||||
placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,25 +56,30 @@
|
||||
<option value="duration">{{ l.slideshow_slide_form_label_cron_scheduled_duration }}</option>
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
</select>
|
||||
<input type="text" id="slide-edit-cron-schedule-end-datetimepicker" class="datetimepicker" value="" placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}" />
|
||||
<input type="text" name="cron_schedule_end" id="slide-edit-cron-schedule-end" class="target hidden" placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}" />
|
||||
<input type="text" id="slide-edit-cron-schedule-end-datetimepicker" class="datetimepicker" value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
<input type="text" name="cron_schedule_end" id="slide-edit-cron-schedule-end" class="target hidden"
|
||||
placeholder="{{ l.slideshow_slide_form_widget_cron_scheduled_placeholder }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group slide-duration-group">
|
||||
<label for="slide-edit-duration">{{ l.slideshow_slide_form_label_duration }}</label>
|
||||
<div class="widget">
|
||||
<input type="number" name="duration" id="slide-edit-duration" required="required" />
|
||||
<input type="number" name="duration" id="slide-edit-duration" required="required"/>
|
||||
<span>{{ l.slideshow_slide_form_label_duration_unit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" class="btn-normal modal-close">
|
||||
{{ l.slideshow_slide_form_button_cancel }}
|
||||
<button type="button" class="btn btn-naked modal-close">
|
||||
{{ l.common_close }}
|
||||
</button>
|
||||
<button type="submit" class="green">
|
||||
<i class="fa fa-save icon-left"></i>{{ l.slideshow_slide_form_edit_submit }}
|
||||
<button type="submit" class="btn btn-info">
|
||||
<i class="fa fa-save icon-left"></i>{{ l.common_save }}
|
||||
</button>
|
||||
<button type="button" disabled="disabled" class="btn btn-naked hidden btn-loading">
|
||||
{{ l.common_loading }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user