Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
{#
|
|
|
|
|
/*
|
|
|
|
|
* OTS Signs Theme - Applications Page
|
|
|
|
|
* Based on Xibo CMS applications-page.twig with OTS styling
|
|
|
|
|
*/
|
|
|
|
|
#}
|
|
|
|
|
{% extends "authed.twig" %}
|
|
|
|
|
{% import "inline.twig" as inline %}
|
|
|
|
|
|
|
|
|
|
{% block title %}{{ "Applications"|trans }} | {% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block actionMenu %}{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block pageContent %}
|
|
|
|
|
<div class="ots-displays-page">
|
|
|
|
|
<div class="page-header ots-page-header">
|
|
|
|
|
<h1>{% trans "Applications" %}</h1>
|
|
|
|
|
<p class="text-muted">{% trans "Manage API applications and connectors." %}</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
Refactor dashboard card classes to use 'content-card' instead of 'dashboard-card'
- Updated various views to replace 'dashboard-card' with 'content-card' for consistency in styling.
- Modified filter and table card classes across multiple pages including applications, campaigns, commands, datasets, dayparts, displays, display groups, display profiles, fonts, layouts, libraries, menu boards, modules, player software, playlists, resolutions, schedules, settings, sync groups, tags, tasks, templates, transitions, users, and user groups.
2026-02-11 09:17:45 -05:00
|
|
|
<div class="widget content-card ots-displays-card">
|
Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
<div class="widget-body ots-displays-body">
|
|
|
|
|
<div class="XiboGrid" id="{{ random() }}">
|
Refactor dashboard card classes to use 'content-card' instead of 'dashboard-card'
- Updated various views to replace 'dashboard-card' with 'content-card' for consistency in styling.
- Modified filter and table card classes across multiple pages including applications, campaigns, commands, datasets, dayparts, displays, display groups, display profiles, fonts, layouts, libraries, menu boards, modules, player software, playlists, resolutions, schedules, settings, sync groups, tags, tasks, templates, transitions, users, and user groups.
2026-02-11 09:17:45 -05:00
|
|
|
<div class="XiboFilter card mb-3 bg-light content-card ots-filter-card">
|
Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
<div class="ots-filter-header">
|
|
|
|
|
<h3 class="ots-filter-title">{% trans "Filter Applications" %}</h3>
|
|
|
|
|
<button type="button" class="ots-filter-toggle" id="ots-filter-collapse-btn" title="{% trans 'Toggle filter panel' %}">
|
|
|
|
|
<i class="fa fa-chevron-down"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ots-filter-content collapsed" id="ots-filter-content">
|
|
|
|
|
<div class="FilterDiv card-body" id="Filter">
|
|
|
|
|
<form class="form-inline">
|
|
|
|
|
{% set title %}{% trans "Name" %}{% endset %}
|
|
|
|
|
{{ inline.inputNameGrid('name', title) }}
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
Refactor dashboard card classes to use 'content-card' instead of 'dashboard-card'
- Updated various views to replace 'dashboard-card' with 'content-card' for consistency in styling.
- Modified filter and table card classes across multiple pages including applications, campaigns, commands, datasets, dayparts, displays, display groups, display profiles, fonts, layouts, libraries, menu boards, modules, player software, playlists, resolutions, schedules, settings, sync groups, tags, tasks, templates, transitions, users, and user groups.
2026-02-11 09:17:45 -05:00
|
|
|
<div class="XiboData card pt-3 content-card ots-table-card">
|
Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
<div class="ots-table-toolbar">
|
Refactor toolbar buttons across various pages to unify styling
- Updated button classes for consistency in the playersoftware-page, playlist-page, resolution-page, schedule-page, settings-page, syncgroup-page, tag-page, task-page, template-page, transition-page, user-page, and usergroup-page.
- Removed unnecessary text from button titles and ensured all buttons have the 'ots-toolbar-btn' class for uniformity.
- Cleaned up the code by removing commented-out sections and ensuring proper indentation.
2026-02-07 14:50:40 -05:00
|
|
|
<button class="btn btn-sm btn-success ots-toolbar-btn XiboFormButton" title="{% trans "Add an Application" %}" href="{{ url_for("application.add.form") }}"><i class="fa fa-plus-circle" aria-hidden="true"></i></button>
|
|
|
|
|
<button class="btn btn-sm btn-primary ots-toolbar-btn" id="refreshGrid" title="{% trans "Refresh the Table" %}" href="#"><i class="fa fa-refresh" aria-hidden="true"></i></button>
|
Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
</div>
|
|
|
|
|
<table id="applications" class="table table-striped">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>{% trans "Name" %}</th>
|
|
|
|
|
<th>{% trans "Owner" %}</th>
|
|
|
|
|
<th class="rowMenu"></th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
Refactor dashboard card classes to use 'content-card' instead of 'dashboard-card'
- Updated various views to replace 'dashboard-card' with 'content-card' for consistency in styling.
- Modified filter and table card classes across multiple pages including applications, campaigns, commands, datasets, dayparts, displays, display groups, display profiles, fonts, layouts, libraries, menu boards, modules, player software, playlists, resolutions, schedules, settings, sync groups, tags, tasks, templates, transitions, users, and user groups.
2026-02-11 09:17:45 -05:00
|
|
|
<div class="widget content-card ots-displays-card mt-2">
|
Add new pages for managing tags, tasks, transitions, users, user groups, and their respective JavaScript functionalities
- Implemented tag management page with filtering, data table, and AJAX functionality.
- Created task management page with task listing, filtering, and AJAX data loading.
- Developed transition management page with a data table for transitions.
- Added user management page with comprehensive user details, filtering options, and AJAX support.
- Introduced user group management page with filtering and data table for user groups.
- Enhanced JavaScript for data tables, including state saving, filtering, and AJAX data fetching for all new pages.
2026-02-06 23:54:21 -05:00
|
|
|
<div class="widget-body ots-displays-body">
|
|
|
|
|
<div class="page-header ots-page-header">
|
|
|
|
|
<h1>{% trans "Connectors" %}</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="connectors" class="card-deck">
|
|
|
|
|
{% if theme.getThemeConfig("app_name") == "Xibo" %}
|
|
|
|
|
<div class="card p3 mt-2" style="min-width: 250px; max-width: 250px;">
|
|
|
|
|
<img class="card-img-top" style="max-height: 250px" src="{{ theme.rootUri() }}theme/default/img/connectors/canva_logo.png" alt="Canva">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h5 class="card-title">Canva</h5>
|
|
|
|
|
<p class="card-text">
|
|
|
|
|
Publish your designs from Canva to Xibo at the push of a button.
|
|
|
|
|
<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
This connector is configured in Canva using the "Publish menu".
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-footer">
|
|
|
|
|
<a class="btn btn-primary" href="https://canva.com" target="_blank">Visit Canva</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block javaScript %}
|
|
|
|
|
<script type="text/javascript" nonce="{{ cspNonce }}">
|
|
|
|
|
|
|
|
|
|
{% autoescape "js" %}
|
|
|
|
|
var copyToClipboardTrans = "{{ "Copy to Clipboard"|trans }}";
|
|
|
|
|
var couldNotCopyTrans = "{{ "Could not copy"|trans }}";
|
|
|
|
|
var copiedTrans = "{{ "Copied!"|trans }}";
|
|
|
|
|
{% endautoescape %}
|
|
|
|
|
|
|
|
|
|
var table;
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
table = $('#applications').DataTable({
|
|
|
|
|
language: dataTablesLanguage,
|
|
|
|
|
dom: dataTablesTemplate,
|
|
|
|
|
serverSide: true,
|
|
|
|
|
stateSave: true,
|
|
|
|
|
responsive: true,
|
|
|
|
|
stateDuration: 0,
|
|
|
|
|
stateLoadCallback: dataTableStateLoadCallback,
|
|
|
|
|
stateSaveCallback: dataTableStateSaveCallback,
|
|
|
|
|
filter: false,
|
|
|
|
|
searchDelay: 3000,
|
|
|
|
|
"order": [[ 0, "asc"]],
|
|
|
|
|
ajax: {
|
|
|
|
|
url: "{{ url_for('application.search') }}",
|
|
|
|
|
data: function (d) {
|
|
|
|
|
$.extend(d, $('#applications').closest(".XiboGrid").find(".FilterDiv form").serializeObject());
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"columns": [
|
|
|
|
|
{ "data": "name", "render": dataTableSpacingPreformatted },
|
|
|
|
|
{ "data": "owner" },
|
|
|
|
|
{
|
|
|
|
|
"orderable": false,
|
|
|
|
|
responsivePriority: 1,
|
|
|
|
|
"data": dataTableButtonsColumn
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
table.on('draw', dataTableDraw);
|
|
|
|
|
table.on('processing.dt', dataTableProcessing);
|
|
|
|
|
dataTableAddButtons(table, $('#applications_wrapper').find('.dataTables_buttons'));
|
|
|
|
|
|
|
|
|
|
$("#refreshGrid").click(function () {
|
|
|
|
|
table.ajax.reload();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Connectors
|
|
|
|
|
loadConnectors();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function loadConnectors() {
|
|
|
|
|
var connectorTemplate = Handlebars.compile($('#template-connector-cards').html());
|
|
|
|
|
var $connectorContainer = $('#connectors');
|
|
|
|
|
$connectorContainer.find('.connector').remove();
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'GET',
|
|
|
|
|
url: '{{ url_for("connector.search") }}?isVisible=1&showUninstalled=1',
|
|
|
|
|
cache: false,
|
|
|
|
|
dataType:"json",
|
|
|
|
|
success: function(xhr, textStatus, error) {
|
|
|
|
|
$.each(xhr.data, function(index, element) {
|
|
|
|
|
if (element.isHidden) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
element.configureUrl = '{{ url_for("connector.edit.form", {id: ":id"}) }}'.replace(':id', element.connectorId);
|
|
|
|
|
element.proxyUrl = '{{ url_for("connector.edit.form.proxy", {id: ":id", method: ":method"}) }}'.replace(':id', element.connectorId);
|
|
|
|
|
element.thumbnail = element.thumbnail || 'theme/default/img/thumbs/placeholder.png';
|
|
|
|
|
if (!element.thumbnail.startsWith('http')) {
|
|
|
|
|
element.thumbnail = '{{ theme.rootUri() }}' + element.thumbnail;
|
|
|
|
|
}
|
|
|
|
|
element.enabledIcon = (element.isEnabled) ? 'fa-check' : 'fa-times';
|
|
|
|
|
element.classNameLast = element.className.substr(element.className.lastIndexOf('\\') + 1);
|
|
|
|
|
$connectorContainer.append(connectorTemplate(element));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$connectorContainer.trigger('connectors.loaded');
|
|
|
|
|
XiboInitialise('#connectors');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function connectorFormSubmit() {
|
|
|
|
|
XiboFormSubmit($('#connectorEditForm'), null, function() {
|
|
|
|
|
loadConnectors();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function copyFromSecretInput(dialog) {
|
|
|
|
|
$('#copy-button').tooltip();
|
|
|
|
|
|
|
|
|
|
$('#copy-button').bind('click', function() {
|
|
|
|
|
var input = $('#clientSecret');
|
|
|
|
|
input.focus();
|
|
|
|
|
input.select();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
var success = document.execCommand('copy');
|
|
|
|
|
if (success) {
|
|
|
|
|
$('#copy-button').trigger('copied', [copiedTrans]);
|
|
|
|
|
} else {
|
|
|
|
|
$('#copy-button').trigger('copied', [couldNotCopyTrans]);
|
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
$('#copy-button').trigger('copied', [couldNotCopyTrans]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input.blur();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('#copy-button').bind('copied', function(event, message) {
|
|
|
|
|
const $self = $(this);
|
|
|
|
|
$(this).tooltip('hide')
|
|
|
|
|
.attr('data-original-title', message)
|
|
|
|
|
.tooltip('show');
|
|
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
$self.tooltip('hide').attr('data-original-title', copyToClipboardTrans);
|
|
|
|
|
}, 1000);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onAuthCodeChanged(dialog);
|
|
|
|
|
$(dialog).find('#authCode').on('change', function() {
|
|
|
|
|
onAuthCodeChanged(dialog);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onAuthCodeChanged(dialog) {
|
|
|
|
|
var authCode = $(dialog).find("#authCode").is(":checked");
|
|
|
|
|
var $authCodeTab = $(dialog).find(".tabForAuthCode");
|
|
|
|
|
|
|
|
|
|
if (authCode) {
|
|
|
|
|
$authCodeTab.removeClass("d-none");
|
|
|
|
|
} else {
|
|
|
|
|
$authCodeTab.addClass("d-none");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
{% for js in connectorJavaScript %}
|
|
|
|
|
{% include js ~ ".twig" %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block javaScriptTemplates %}
|
|
|
|
|
{{ parent() }}
|
|
|
|
|
|
|
|
|
|
{% verbatim %}
|
|
|
|
|
<script type="text/x-handlebars-template" id="template-connector-cards">
|
|
|
|
|
<div class="connector card p3 mt-2" style="min-width: 250px; max-width: 250px;"
|
|
|
|
|
data-proxy-url="{{proxyUrl}}"
|
|
|
|
|
data-connector-class-name="{{className}}"
|
|
|
|
|
data-connector-class-name-last="{{classNameLast}}"
|
|
|
|
|
data-connector-id="{{ connectorId }}">
|
|
|
|
|
{{#if thumbnail}}<img class="card-img-top" style="max-height: 250px" src="{{ thumbnail }}" alt="{{ title }}">{{/if}}
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h5 class="card-title">{{ title }}</h5>
|
|
|
|
|
<p class="card-text">
|
|
|
|
|
{{ description }}
|
|
|
|
|
<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
{{#if isInstalled }}
|
|
|
|
|
{% endverbatim %}{{ "Enabled"|trans }}{% verbatim %}: <span class="fa {{ enabledIcon }}"></span>
|
|
|
|
|
{{/if}}
|
|
|
|
|
{{#unless isInstalled }}
|
|
|
|
|
{% endverbatim %}{{ "Installed"|trans }}{% verbatim %}: <span class="fa fa-times"></span>
|
|
|
|
|
{{/unless}}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-footer">
|
|
|
|
|
<button class="btn btn-primary XiboFormButton" href="{{ configureUrl }}">
|
|
|
|
|
{% endverbatim %}{{ "Configure"|trans }}{% verbatim %}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</script>
|
|
|
|
|
{% endverbatim %}
|
|
|
|
|
{% endblock %}
|