backend ok, frontend ok, ready to use host and route playlists

This commit is contained in:
jr-k 2024-06-03 01:22:38 +02:00
parent 3e6cb11cc0
commit 5a0a51b349
17 changed files with 164 additions and 35 deletions

View File

@ -175,7 +175,7 @@ header nav ul li.active a {
align-items: center; align-items: center;
} }
select.playlist-picker, select.select-item-picker,
a.btn, a.btn,
button { button {
background-color: #fff; background-color: #fff;
@ -200,7 +200,7 @@ button:hover {
color: #bc48ff; color: #bc48ff;
} }
select.playlist-picker, select.select-item-picker,
button.purple { button.purple {
font-weight: bold; font-weight: bold;
border: 1px solid #692fbd; border: 1px solid #692fbd;

View File

@ -38,6 +38,10 @@ jQuery(document).ready(function ($) {
}); });
}; };
$(document).on('change', 'select.group-picker', function () {
document.location.href = $(this).val();
});
$(document).on('change', 'input[type=checkbox]', function () { $(document).on('change', 'input[type=checkbox]', function () {
$.ajax({ $.ajax({
url: '/fleet/node-player/toggle', url: '/fleet/node-player/toggle',
@ -83,6 +87,7 @@ jQuery(document).ready(function ($) {
showModal('modal-node-player-edit'); showModal('modal-node-player-edit');
$('.modal-node-player-edit input:visible:eq(0)').focus().select(); $('.modal-node-player-edit input:visible:eq(0)').focus().select();
$('#node-player-edit-name').val(nodePlayer.name); $('#node-player-edit-name').val(nodePlayer.name);
$('#node-player-edit-group-id').val(nodePlayer.group_id);
$('#node-player-edit-host').val(nodePlayer.host); $('#node-player-edit-host').val(nodePlayer.host);
$('#node-player-edit-id').val(nodePlayer.id); $('#node-player-edit-id').val(nodePlayer.id);
}); });

View File

@ -88,6 +88,7 @@
"fleet_node_player_panel_empty": "Currently, there are no players. %link% now.", "fleet_node_player_panel_empty": "Currently, there are no players. %link% now.",
"fleet_node_player_panel_th_name": "Name", "fleet_node_player_panel_th_name": "Name",
"fleet_node_player_panel_th_host": "Host", "fleet_node_player_panel_th_host": "Host",
"fleet_node_player_panel_th_group_id": "Group",
"fleet_node_player_panel_th_enabled": "Enabled", "fleet_node_player_panel_th_enabled": "Enabled",
"fleet_node_player_panel_th_activity": "Activity", "fleet_node_player_panel_th_activity": "Activity",
"fleet_node_player_form_add_title": "Add Player", "fleet_node_player_form_add_title": "Add Player",
@ -95,6 +96,7 @@
"fleet_node_player_form_edit_title": "Edit Player", "fleet_node_player_form_edit_title": "Edit Player",
"fleet_node_player_form_edit_submit": "Save", "fleet_node_player_form_edit_submit": "Save",
"fleet_node_player_form_label_name": "Name", "fleet_node_player_form_label_name": "Name",
"fleet_node_player_form_label_group_id": "Group",
"fleet_node_player_form_label_host": "Host", "fleet_node_player_form_label_host": "Host",
"fleet_node_player_form_button_cancel": "Cancel", "fleet_node_player_form_button_cancel": "Cancel",
"js_fleet_node_player_delete_confirmation": "Are you sure?", "js_fleet_node_player_delete_confirmation": "Are you sure?",
@ -146,10 +148,12 @@
"settings_variable_form_label_name": "Name", "settings_variable_form_label_name": "Name",
"settings_variable_form_label_value": "Value", "settings_variable_form_label_value": "Value",
"settings_variable_form_button_cancel": "Cancel", "settings_variable_form_button_cancel": "Cancel",
"settings_variable_form_error_not_playlist_enabled_while_fleet_player_enabled": "You can't disable playlists while fleet player management is on",
"settings_variable_desc_lang": "Server language", "settings_variable_desc_lang": "Server language",
"settings_variable_desc_playlist_enabled": "Enable playlist management", "settings_variable_desc_playlist_enabled": "Enable playlist management",
"settings_variable_desc_fleet_studio_enabled": "Enable fleet studio management", "settings_variable_desc_fleet_studio_enabled": "Enable fleet studio management",
"settings_variable_desc_fleet_player_enabled": "Enable fleet player management", "settings_variable_desc_fleet_player_enabled": "Enable fleet player management",
"settings_variable_desc_edition_fleet_player_enabled": "Playlist management will also be enabled",
"settings_variable_desc_auth_enabled": "Enable auth management", "settings_variable_desc_auth_enabled": "Enable auth management",
"settings_variable_desc_edition_auth_enabled": "Default user credentials will be admin/admin", "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_external_url": "External url (i.e: https://studio-01.company.com or http://10.10.3.100)",
@ -200,6 +204,7 @@
"basic_month_11": "November", "basic_month_11": "November",
"basic_month_12": "December", "basic_month_12": "December",
"common_default_node_player_group": "Default player group",
"common_default_playlist": "Default playlist", "common_default_playlist": "Default playlist",
"common_unknown_ipaddr": "Unknown IP address", "common_unknown_ipaddr": "Unknown IP address",
"common_empty": "[Empty]", "common_empty": "[Empty]",

View File

@ -88,6 +88,7 @@
"fleet_node_player_panel_empty": "Actuellement, il n'y a pas de lecteurs. %link% maintenant.", "fleet_node_player_panel_empty": "Actuellement, il n'y a pas de lecteurs. %link% maintenant.",
"fleet_node_player_panel_th_name": "Nom", "fleet_node_player_panel_th_name": "Nom",
"fleet_node_player_panel_th_host": "Hôte", "fleet_node_player_panel_th_host": "Hôte",
"fleet_node_player_panel_th_group_id": "Groupe",
"fleet_node_player_panel_th_enabled": "Activé", "fleet_node_player_panel_th_enabled": "Activé",
"fleet_node_player_panel_th_activity": "Options", "fleet_node_player_panel_th_activity": "Options",
"fleet_node_player_form_add_title": "Ajout d'un lecteur", "fleet_node_player_form_add_title": "Ajout d'un lecteur",
@ -95,6 +96,7 @@
"fleet_node_player_form_edit_title": "Modification d'un lecteur", "fleet_node_player_form_edit_title": "Modification d'un lecteur",
"fleet_node_player_form_edit_submit": "Enregistrer", "fleet_node_player_form_edit_submit": "Enregistrer",
"fleet_node_player_form_label_name": "Nom", "fleet_node_player_form_label_name": "Nom",
"fleet_node_player_form_label_group_id": "Groupe",
"fleet_node_player_form_label_host": "Hôte", "fleet_node_player_form_label_host": "Hôte",
"fleet_node_player_form_button_cancel": "Annuler", "fleet_node_player_form_button_cancel": "Annuler",
"js_fleet_node_player_delete_confirmation": "Êtes-vous sûr ?", "js_fleet_node_player_delete_confirmation": "Êtes-vous sûr ?",
@ -146,10 +148,12 @@
"settings_variable_form_label_name": "Nom", "settings_variable_form_label_name": "Nom",
"settings_variable_form_label_value": "Valeur", "settings_variable_form_label_value": "Valeur",
"settings_variable_form_button_cancel": "Annuler", "settings_variable_form_button_cancel": "Annuler",
"settings_variable_form_error_not_playlist_enabled_while_fleet_player_enabled": "Vous ne pouvez pas désactiver les listes de lecture tant que la gestion de flotte de lecteurs est activée",
"settings_variable_desc_lang": "Langage de l'application", "settings_variable_desc_lang": "Langage de l'application",
"settings_variable_desc_playlist_enabled": "Activer la gestion des playlists", "settings_variable_desc_playlist_enabled": "Activer la gestion des playlists",
"settings_variable_desc_fleet_studio_enabled": "Activer la gestion de flotte des studios", "settings_variable_desc_fleet_studio_enabled": "Activer la gestion de flotte des studios",
"settings_variable_desc_fleet_player_enabled": "Activer la gestion de flotte des players", "settings_variable_desc_fleet_player_enabled": "Activer la gestion de flotte des players",
"settings_variable_desc_edition_fleet_player_enabled": "Les listes de lecture seront également activées",
"settings_variable_desc_auth_enabled": "Activer la gestion de l'authentification", "settings_variable_desc_auth_enabled": "Activer la gestion de l'authentification",
"settings_variable_desc_edition_auth_enabled": "Les identifiants de l'utilisateur par défaut seront admin/admin", "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_external_url": "URL externe (i.e: https://studio-01.company.com or http://10.10.3.100)",
@ -200,6 +204,7 @@
"basic_month_11": "Novembre", "basic_month_11": "Novembre",
"basic_month_12": "Décembre", "basic_month_12": "Décembre",
"common_default_node_player_group": "Groupe de lecteur par défaut",
"common_default_playlist": "Playlist par défaut", "common_default_playlist": "Playlist par défaut",
"common_unknown_ipaddr": "Adresse IP inconnue", "common_unknown_ipaddr": "Adresse IP inconnue",
"common_empty": "[Vide]", "common_empty": "[Vide]",

View File

@ -18,28 +18,48 @@ class FleetNodePlayerController(ObController):
def register(self): def register(self):
self._app.add_url_rule('/fleet/node-player/list', 'fleet_node_player_list', self.guard_fleet(self._auth(self.fleet_node_player_list)), methods=['GET']) self._app.add_url_rule('/fleet/node-player/list', 'fleet_node_player_list', self.guard_fleet(self._auth(self.fleet_node_player_list)), methods=['GET'])
self._app.add_url_rule('/fleet/node-player/group/set/<group_id>', 'fleet_node_player_list_group_use', self._auth(self.fleet_node_player_list), methods=['GET'])
self._app.add_url_rule('/fleet/node-player/add', 'fleet_node_player_add', self.guard_fleet(self._auth(self.fleet_node_player_add)), methods=['POST']) self._app.add_url_rule('/fleet/node-player/add', 'fleet_node_player_add', self.guard_fleet(self._auth(self.fleet_node_player_add)), methods=['POST'])
self._app.add_url_rule('/fleet/node-player/edit', 'fleet_node_player_edit', self.guard_fleet(self._auth(self.fleet_node_player_edit)), methods=['POST']) self._app.add_url_rule('/fleet/node-player/edit', 'fleet_node_player_edit', self.guard_fleet(self._auth(self.fleet_node_player_edit)), methods=['POST'])
self._app.add_url_rule('/fleet/node-player/toggle', 'fleet_node_player_toggle', self.guard_fleet(self._auth(self.fleet_node_player_toggle)), methods=['POST']) self._app.add_url_rule('/fleet/node-player/toggle', 'fleet_node_player_toggle', self.guard_fleet(self._auth(self.fleet_node_player_toggle)), methods=['POST'])
self._app.add_url_rule('/fleet/node-player/delete', 'fleet_node_player_delete', self.guard_fleet(self._auth(self.fleet_node_player_delete)), methods=['DELETE']) self._app.add_url_rule('/fleet/node-player/delete', 'fleet_node_player_delete', self.guard_fleet(self._auth(self.fleet_node_player_delete)), methods=['DELETE'])
self._app.add_url_rule('/fleet/node-player/position', 'fleet_node_player_position', self.guard_fleet(self._auth(self.fleet_node_player_position)), methods=['POST']) self._app.add_url_rule('/fleet/node-player/position', 'fleet_node_player_position', self.guard_fleet(self._auth(self.fleet_node_player_position)), methods=['POST'])
def fleet_node_player_list(self): def fleet_node_player_list(self, group_id: int = 0):
current_group = self._model_store.node_player_group().get(group_id)
group_id = current_group.id if current_group else None
return render_template( return render_template(
'fleet/player/list.jinja.html', 'fleet/player/list.jinja.html',
enabled_node_players=self._model_store.node_player().get_enabled_node_players(), current_group=current_group,
disabled_node_players=self._model_store.node_player().get_disabled_node_players(), groups=self._model_store.node_player_group().get_all_labels_indexed(),
enabled_node_players=self._model_store.node_player().get_node_players(group_id=group_id, enabled=True),
disabled_node_players=self._model_store.node_player().get_node_players(group_id=group_id, enabled=False)
) )
def fleet_node_player_add(self): def fleet_node_player_add(self):
self._model_store.node_player().add_form(NodePlayer( node_player = NodePlayer(
name=request.form['name'], name=request.form['name'],
host=request.form['host'], host=request.form['host'],
)) group_id=request.form['group_id'] if 'group_id' in request.form and request.form['group_id'] else None,
)
self._model_store.node_player().add_form(node_player)
if node_player.group_id:
return redirect(url_for('fleet_node_player_list_group_use', group_id=node_player.group_id))
return redirect(url_for('fleet_node_player_list')) return redirect(url_for('fleet_node_player_list'))
def fleet_node_player_edit(self): def fleet_node_player_edit(self):
self._model_store.node_player().update_form(request.form['id'], request.form['name'], request.form['host']) node_player = self._model_store.node_player().update_form(
request.form['id'],
request.form['name'],
request.form['host'],
request.form['group_id']
)
if node_player.group_id:
return redirect(url_for('fleet_node_player_list_group_use', group_id=node_player.group_id))
return redirect(url_for('fleet_node_player_list')) return redirect(url_for('fleet_node_player_list'))
def fleet_node_player_toggle(self): def fleet_node_player_toggle(self):

View File

@ -25,7 +25,7 @@ class FleetNodePlayerGroupController(ObController):
def fleet_node_player_group_list(self): def fleet_node_player_group_list(self):
return render_template( return render_template(
'fleet/player-group/list.jinja.html', 'fleet/player-group/list.jinja.html',
node_player_groups=self._model_store.node_player_group().get_all(), node_player_groups=self._model_store.node_player_group().get_groups(with_default=True),
playlists=self._model_store.playlist().get_all_labels_indexed() playlists=self._model_store.playlist().get_all_labels_indexed()
) )

View File

@ -2,6 +2,7 @@ import time
import json import json
from flask import Flask, render_template, redirect, request, url_for from flask import Flask, render_template, redirect, request, url_for
from typing import Optional
from src.service.ModelStore import ModelStore from src.service.ModelStore import ModelStore
from src.interface.ObController import ObController from src.interface.ObController import ObController
@ -23,10 +24,25 @@ class SettingsController(ObController):
) )
def settings_variable_edit(self): def settings_variable_edit(self):
error = self._pre_update(request.form['id'])
if error:
return redirect(url_for('settings_variable_list', error=error))
self._model_store.variable().update_form(request.form['id'], request.form['value']) self._model_store.variable().update_form(request.form['id'], request.form['value'])
self._post_update(request.form['id']) self._post_update(request.form['id'])
return redirect(url_for('settings_variable_list')) return redirect(url_for('settings_variable_list'))
def _pre_update(self, id: int) -> Optional[str]:
variable = self._model_store.variable().get(id)
if variable.name == 'playlist_enabled':
fleet_player_enabled = self._model_store.variable().get_one_by_name(name='fleet_player_enabled')
if variable.as_bool() and fleet_player_enabled.as_bool():
return self.t('settings_variable_form_error_not_playlist_enabled_while_fleet_player_enabled')
return None
def _post_update(self, id: int) -> None: def _post_update(self, id: int) -> None:
variable = self._model_store.variable().get(id) variable = self._model_store.variable().get(id)
@ -39,11 +55,12 @@ class SettingsController(ObController):
if variable.name == 'fleet_studio_enabled': if variable.name == 'fleet_studio_enabled':
self.reload_web_server() self.reload_web_server()
# if variable.name == 'fleet_player_enabled': if variable.name == 'fleet_player_enabled':
# if variable.as_bool() and self._model_store.node_player_group().count_all_enabled() == 0: playlist_enabled = self._model_store.variable().get_one_by_name(name='playlist_enabled')
# self._model_store.user().add_form(NodePlayerGroup(name="default", enabled=True)) if variable.as_bool() and not playlist_enabled.as_bool():
# self._model_store.variable().update_by_name(name='playlist_enabled', value=True)
# self.reload_web_server()
self.reload_web_server()
if variable.name == 'auth_enabled': if variable.name == 'auth_enabled':
if variable.as_bool() and self._model_store.user().count_all_enabled() == 0: if variable.as_bool() and self._model_store.user().count_all_enabled() == 0:

View File

@ -51,6 +51,25 @@ class NodePlayerGroupManager(ModelManager):
def get_all(self, sort: bool = False) -> List[NodePlayerGroup]: def get_all(self, sort: bool = False) -> List[NodePlayerGroup]:
return self.hydrate_list(self._db.get_all(self.TABLE_NAME, "name" if sort else None)) return self.hydrate_list(self._db.get_all(self.TABLE_NAME, "name" if sort else None))
def get_all_labels_indexed(self, with_default: bool = False) -> Dict:
index = {}
for item in self.get_groups(with_default=with_default):
index[item.id] = item.name
return index
def get_groups(self, with_default: bool = False):
node_player_groups = self.get_all(sort=True)
if not with_default:
return node_player_groups
return [NodePlayerGroup(
id=None,
name=self.t('common_default_node_player_group'))
] + node_player_groups
def get_node_players_groups(self, playlist_id: Optional[int] = None) -> List[NodePlayerGroup]: def get_node_players_groups(self, playlist_id: Optional[int] = None) -> List[NodePlayerGroup]:
query = " 1=1 " query = " 1=1 "
if playlist_id: if playlist_id:
@ -89,7 +108,7 @@ class NodePlayerGroupManager(ModelManager):
return node_player_group_id return node_player_group_id
def update_form(self, id: int, name: str, playlist_id: Optional[int]) -> None: def update_form(self, id: int, name: str, playlist_id: Optional[int]) -> None:
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update({"name": name, "playlist_id": playlist_id})) self._db.update_by_id(self.TABLE_NAME, id, self.pre_update({"name": name, "playlist_id": playlist_id if playlist_id else None}))
self.post_update(id) self.post_update(id)
def add_form(self, node_player_group: Union[NodePlayerGroup, Dict]) -> None: def add_form(self, node_player_group: Union[NodePlayerGroup, Dict]) -> None:

View File

@ -105,9 +105,21 @@ class NodePlayerManager(ModelManager):
for node_player_id, node_player_position in positions.items(): for node_player_id, node_player_position in positions.items():
self._db.update_by_id(self.TABLE_NAME, node_player_id, {"position": node_player_position}) self._db.update_by_id(self.TABLE_NAME, node_player_id, {"position": node_player_position})
def update_form(self, id: int, name: str, host: str) -> None: def update_form(self, id: int, name: str, host: str, group_id: Optional[int]) -> NodePlayer:
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update({"name": name, "host": host})) node_player = self.get(id)
if not node_player:
return
form = {
"name": name,
"host": host,
"group_id": group_id if group_id else None
}
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update(form))
self.post_update(id) self.post_update(id)
return self.get(id)
def add_form(self, node_player: Union[NodePlayer, Dict]) -> None: def add_form(self, node_player: Union[NodePlayer, Dict]) -> None:
form = node_player form = node_player

View File

@ -125,7 +125,7 @@ class VariableManager:
{"name": "playlist_default_time_sync", "section": self.t(VariableSection.PLAYLIST), "value": True, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_playlist_default_time_sync'), "refresh_player": True}, {"name": "playlist_default_time_sync", "section": self.t(VariableSection.PLAYLIST), "value": True, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_playlist_default_time_sync'), "refresh_player": True},
### Fleet Management ### Fleet Management
{"name": "fleet_player_enabled", "section": self.t(VariableSection.FLEET), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_fleet_player_enabled'), "refresh_player": False}, {"name": "fleet_player_enabled", "section": self.t(VariableSection.FLEET), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_fleet_player_enabled'), "description_edition": self.t('settings_variable_desc_edition_fleet_player_enabled'), "refresh_player": False},
{"name": "fleet_studio_enabled", "section": self.t(VariableSection.FLEET), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_fleet_studio_enabled'), "refresh_player": False}, {"name": "fleet_studio_enabled", "section": self.t(VariableSection.FLEET), "value": False, "type": VariableType.BOOL, "editable": True, "description": self.t('settings_variable_desc_fleet_studio_enabled'), "refresh_player": False},
### Security ### Security

View File

@ -71,16 +71,16 @@
</li> </li>
{% endif %} {% endif %}
{% if FLEET_PLAYER_ENABLED %} {% if FLEET_PLAYER_ENABLED %}
<li class="{{ 'active' if request.url_rule.endpoint == 'fleet_node_player_list' }}">
<a href="{{ url_for('fleet_node_player_list') }}">
<i class="fa fa-tv"></i> {{ l.fleet_node_player_page_title }}
</a>
</li>
<li class="{{ 'active' if request.url_rule.endpoint == 'fleet_node_player_group_list' }}"> <li class="{{ 'active' if request.url_rule.endpoint == 'fleet_node_player_group_list' }}">
<a href="{{ url_for('fleet_node_player_group_list') }}"> <a href="{{ url_for('fleet_node_player_group_list') }}">
<i class="fa fa-layer-group"></i> {{ l.fleet_node_player_group_page_title }} <i class="fa fa-layer-group"></i> {{ l.fleet_node_player_group_page_title }}
</a> </a>
</li> </li>
<li class="{{ 'active' if request.url_rule.endpoint == 'fleet_node_player_list' }}">
<a href="{{ url_for('fleet_node_player_list') }}">
<i class="fa fa-tv"></i> {{ l.fleet_node_player_page_title }}
</a>
</li>
{% endif %} {% endif %}
{% if AUTH_ENABLED %} {% if AUTH_ENABLED %}
<li class="{{ 'active' if request.url_rule.endpoint == 'auth_user_list' }}"> <li class="{{ 'active' if request.url_rule.endpoint == 'auth_user_list' }}">

View File

@ -7,7 +7,9 @@
<i class="fa fa-user"></i> <i class="fa fa-user"></i>
</th> </th>
{% endif %} {% endif %}
<th class="tac">{{ l.fleet_node_player_group_panel_th_playlist }}</th> {% if PLAYLIST_ENABLED %}
<th class="tac">{{ l.fleet_node_player_group_panel_th_playlist }}</th>
{% endif %}
<th class="tac">{{ l.fleet_node_player_group_panel_th_activity }}</th> <th class="tac">{{ l.fleet_node_player_group_panel_th_activity }}</th>
</tr> </tr>
</thead> </thead>
@ -25,11 +27,11 @@
<tr class="node-player-group-item" data-level="{{ node_player_group.id }}" data-entity="{{ node_player_group.to_json({"created_by": track_created(node_player_group).username, "updated_by": track_updated(node_player_group).username}) }}"> <tr class="node-player-group-item" data-level="{{ node_player_group.id }}" data-entity="{{ node_player_group.to_json({"created_by": track_created(node_player_group).username, "updated_by": track_updated(node_player_group).username}) }}">
<td class="infos"> <td class="infos">
<div class="inner"> <div class="inner">
<a href="javascript:void(0);" class="item-sort node-player-group-sort"> {% if node_player_group.id %}
<i class="fa fa-sort icon-left"></i> <div class="badge"><i class="fa fa-key icon-left"></i> {{ node_player_group.id }}</div>
</a> {% else %}
<div class="badge"><i class="fa fa-lock"></i></div>
<div class="badge"><i class="fa fa-key icon-left"></i> {{ node_player_group.id }}</div> {% endif %}
<i class="fa fa-layer-group icon-left"></i> <i class="fa fa-layer-group icon-left"></i>
{{ node_player_group.name }} {{ node_player_group.name }}
@ -37,11 +39,13 @@
</td> </td>
{% if AUTH_ENABLED %} {% if AUTH_ENABLED %}
<td class="tac"> <td class="tac">
{% set creator = track_created(node_player_group) %} {% if node_player_group.id %}
{% if creator.username %} {% set creator = track_created(node_player_group) %}
<a href="javascript:void(0);" class="badge item-utrack node-player-group-utrack {% if not creator.enabled %}anonymous{% endif %}"> {% if creator.username %}
{{ creator.username }} <a href="javascript:void(0);" class="badge item-utrack node-player-group-utrack {% if not creator.enabled %}anonymous{% endif %}">
</a> {{ creator.username }}
</a>
{% endif %}
{% endif %} {% endif %}
</td> </td>
{% endif %} {% endif %}

View File

@ -21,6 +21,19 @@
<div class="toolbar-actions"> <div class="toolbar-actions">
{{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_START) }} {{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_START) }}
<button class="purple node-player-add item-add"><i class="fa fa-plus icon-left"></i>{{ l.fleet_node_player_button_add }}</button> <button class="purple node-player-add item-add"><i class="fa fa-plus icon-left"></i>{{ l.fleet_node_player_button_add }}</button>
<select class="select-item-picker group-picker">
<option value="{{ url_for('fleet_node_player_list') }}" {% if not current_group %}selected="selected"{% endif %}>
{{ l.common_default_node_player_group }}
</option>
{% for group_id, group_name in groups.items() %}
{% set is_active_group = str(current_group.id) == str(group_id) %}
<option value="{{ url_for('fleet_node_player_list_group_use', group_id=group_id) }}" {% if is_active_group %}selected="selected"{% endif %}>
{{ group_name }}
</option>
{% endfor %}
</select>
{{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_END) }} {{ HOOK(H_FLEET_NODE_PLAYER_TOOLBAR_ACTIONS_END) }}
</div> </div>
</div> </div>

View File

@ -11,6 +11,18 @@
</div> </div>
</div> </div>
<div class="form-group">
<label for="node-player-add-group-id">{{ l.fleet_node_player_group_form_label_group_id }}</label>
<div class="widget">
<select name="group_id" id="node-player-add-group-id">
<option value="" {% if not current_group.id %}selected="selected"{% endif %}>{{ l.common_default_node_player_group }}</option>
{% for group_id, group_name in groups.items() %}
<option value="{{ group_id }}" {% if current_group.id == str(group_id) %}selected="selected"{% endif %}>{{ group_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="node-player-add-host">{{ l.fleet_node_player_form_label_host }}</label> <label for="node-player-add-host">{{ l.fleet_node_player_form_label_host }}</label>
<div class="widget"> <div class="widget">

View File

@ -13,6 +13,18 @@
</div> </div>
</div> </div>
<div class="form-group">
<label for="node-player-edit-group-id">{{ l.fleet_node_player_group_form_label_group_id }}</label>
<div class="widget">
<select name="group_id" id="node-player-edit-group-id">
<option value="">{{ l.common_default_node_player_group }}</option>
{% for group_id, group_name in groups.items() %}
<option value="{{ group_id }}">{{ group_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="node-player-edit-host">{{ l.fleet_node_player_form_label_host }}</label> <label for="node-player-edit-host">{{ l.fleet_node_player_form_label_host }}</label>
<div class="widget"> <div class="widget">

View File

@ -13,6 +13,11 @@
<div class="toolbar"> <div class="toolbar">
<h2><i class="fa fa-cogs icon-left"></i>{{ l.settings_page_title }}</h2> <h2><i class="fa fa-cogs icon-left"></i>{{ l.settings_page_title }}</h2>
</div> </div>
{% if request.args.get('error') %}
<div class="alert alert-error">{{ request.args.get('error') }}</div>
{% endif %}
<div class="panel"> <div class="panel">
<div class="panel-body"> <div class="panel-body">
<h3>{{ l.settings_variable_panel_system_variables }}</h3> <h3>{{ l.settings_variable_panel_system_variables }}</h3>

View File

@ -39,7 +39,7 @@
{% if PLAYLIST_ENABLED %} {% if PLAYLIST_ENABLED %}
<select class="playlist-picker"> <select class="select-item-picker playlist-picker">
<option value="{{ url_for('slideshow_slide_list') }}" {% if not current_playlist %}selected="selected"{% endif %}> <option value="{{ url_for('slideshow_slide_list') }}" {% if not current_playlist %}selected="selected"{% endif %}>
{{ l.common_default_playlist }} {{ l.common_default_playlist }}
</option> </option>