0byt3m1n1
Path:
/
home
/
mgatv524
/
medcenter.mgaplay.com.br
/
views
/
[
Home
]
File: display-page.twig
{# /** * Copyright (C) 2022 Xibo Signage Ltd * * Xibo - Digital Signage - http://www.xibo.org.uk * * This file is part of Xibo. * * Xibo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Xibo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Xibo. If not, see <http://www.gnu.org/licenses/>. */ #} {% extends "authed.twig" %} {% import "inline.twig" as inline %} {% block title %}{{ "Displays"|trans }} | {% endblock %} {% block actionMenu %} <div class="widget-action-menu pull-right"> {% if currentUser.featureEnabled("displays.add") %} <button class="btn btn-success XiboFormButton" title="{% trans "Add a Display via user_code displayed on the Player screen" %}" href="{{ url_for("display.addViaCode.form") }}"> <i class="fa fa-plus-circle" aria-hidden="true"></i> {% trans "Add Display (Code)" %}</button> {% endif %} <button class="btn btn-primary" id="refreshGrid" title="{% trans "Refresh the Table" %}" href="#"><i class="fa fa-refresh" aria-hidden="true"></i> {% trans "Refresh" %}</button> </div> {% endblock %} {% block pageContent %} <div class="widget"> <div class="widget-title">{% trans "Displays" %}</div> <div class="widget-body"> <div class="XiboGrid" id="{{ random() }}" data-grid-name="displayView"> <div class="XiboFilter card mb-3 bg-light"> <div class="FilterDiv card-body" id="Filter"> <ul class="nav nav-tabs" role="tablist"> <li class="nav-item"><a class="nav-link active" href="#filter-general" role="tab" data-toggle="tab">{% trans "General" %}</a></li> <li class="nav-item"><a class="nav-link" href="#filter-advanced" role="tab" data-toggle="tab">{% trans "Advanced" %}</a></li> </ul> <form class="form-inline"> <div class="tab-content"> <div class="tab-pane active" id="filter-general"> {% set title %}{% trans "ID" %}{% endset %} {{ inline.number("displayId", title) }} {% set title %}{% trans "Name" %}{% endset %} {{ inline.inputNameGrid('display', title) }} {% set title %}{% trans "Status" %}{% endset %} {% set check %}{% trans "Up to date" %}{% endset %} {% set cross %}{% trans "Downloading" %}{% endset %} {% set cloud %}{% trans "Out of date" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "1", option: check}, { optionid: "2", option: cross}, { optionid: "3", option: cloud} ] %} {{ inline.dropdown("mediaInventoryStatus", "single", title, "", options, "optionid", "option") }} {% set title %}{% trans "Logged In?" %}{% endset %} {% set yesOption %}{% trans "Yes" %}{% endset %} {% set noOption %}{% trans "No" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "1", option: yesOption}, { optionid: "0", option: noOption} ] %} {{ inline.dropdown("loggedIn", "single", title, "", options, "optionid", "option") }} {% set title %}{% trans "Authorised?" %}{% endset %} {% set yesOption %}{% trans "Yes" %}{% endset %} {% set noOption %}{% trans "No" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "1", option: yesOption }, { optionid: "0", option: noOption}, ] %} {{ inline.dropdown("authorised", "single", title, "", options, "optionid", "option") }} {% if currentUser.featureEnabled("tag.tagging") %} {% set title %}{% trans "Tags" %}{% endset %} {% set exactTagTitle %}{% trans "Exact match?" %}{% endset %} {% set logicalOperatorTitle %}{% trans "When filtering by multiple Tags, which logical operator should be used?" %}{% endset %} {% set helpText %}{% trans "A comma separated list of tags to filter by. Enter a Tag value preceded with | to filter by Tag values. Enter --no-tag to see items without tags." %}{% endset %} {{ inline.inputWithTags("tags", title, null, helpText, null, null, null, "exactTags", exactTagTitle, logicalOperatorTitle) }} {% endif %} {% if currentUser.featureEnabled("displaygroup.view") %} {% set title %}{% trans "Display Group" %}{% endset %} {{ inline.dropdown("displayGroupId", "single", title, "", [{displayGroupId:null, displayGroup:""}]|merge(displayGroups), "displayGroupId", "displayGroup") }} {% endif %} {% if currentUser.featureEnabled("displayprofile.view") %} {% set title %}{% trans "Display Profile" %}{% endset %} {{ inline.dropdown("displayProfileId", "single", title, "", [{displayProfileId:null, name:""}]|merge(displayProfiles), "displayProfileId", "name") }} {% endif %} {{ inline.hidden("folderId") }} </div> <div class="tab-pane" id="filter-advanced"> {% set title %}{% trans "Last Accessed" %}{% endset %} {{ inline.date("lastAccessed", title) }} {% set title %}{% trans "Player Type" %}{% endset %} {% set android %}{% trans "Android" %}{% endset %} {% set windows %}{% trans "Windows" %}{% endset %} {% set webos %}{% trans "webOS" %}{% endset %} {% set sssp %}{% trans "Tizen" %}{% endset %} {% set linux %}{% trans "Linux" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "android", option: android}, { optionid: "windows", option: windows}, { optionid: "lg", option: webos}, { optionid: "sssp", option: sssp}, { optionid: "linux", option: linux}, ] %} {{ inline.dropdown("clientType", "single", title, "", options, "optionid", "option") }} {% set title %}{% trans "Player Code" %}{% endset %} {{ inline.input("clientCode", title) }} {% set title %}{% trans "Custom ID" %}{% endset %} {{ inline.input("customId", title) }} {% set title %}{% trans "Mac Address" %}{% endset %} {{ inline.input("macAddress", title) }} {% set title %}{% trans "IP Address" %}{% endset %} {{ inline.input("clientAddress", title) }} {% set title %}{% trans "Orientation" %}{% endset %} {% set landscape %}{% trans "Landscape" %}{% endset %} {% set portrait %}{% trans "Portrait" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "landscape", option: landscape}, { optionid: "portrait", option: portrait} ] %} {{ inline.dropdown("orientation", "single", title, "", options, "optionid", "option") }} {% set title %}{% trans "Commercial Licence" %}{% endset %} {% set licensed %}{% trans "Licensed fully" %}{% endset %} {% set trial %}{% trans "Trial" %}{% endset %} {% set notLinceced %}{% trans "Not licenced" %}{% endset %} {% set notApplicable %}{% trans "Not applicable" %}{% endset %} {% set options = [ { optionid: "", option: "" }, { optionid: "1", option: licensed}, { optionid: "2", option: trial}, { optionid: "0", option: notLinceced}, { optionid: "3", option: notApplicable} ] %} {{ inline.dropdown("commercialLicence", "single", title, "", options, "optionid", "option") }} </div> </div> </form> </div> </div> <div class="row"> <div class="col-sm-2 p-3 bg-light" id="grid-folder-filter"> <div class="form-check"> <input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button"> <label class="form-check-label" for="folder-tree-clear-selection-button" title="{{ "Search in all folders"|trans }}">{{ "All Folders"|trans }}</label> </div> <div id="container-folder-tree"></div> </div> <div class="folder-controller d-none"> <button type="button" id="folder-tree-select-folder-button" class="btn btn-outline-secondary" title="{{ "Open / Close Folder Search options"|trans }}"><i class="fas fa-folder fa-1x"></i></button> <div id="breadcrumbs" class="mt-2 pl-2"></div> </div> <div class="map-controller d-none pl-1"> <button type="button" id="map_button" class="btn btn-primary" title="{{ "Map"|trans }}"><i class="fa fa-map"></i></button> </div> <div class="list-controller d-none pl-1"> <button type="button" id="list_button" class="btn btn-primary" title="{{ "List"|trans }}"><i class="fa fa-list"></i></button> </div> <div id="datatable-container" class="card col-sm-10 pt-4 px-2"> <div class="XiboData"> <table id="displays" class="table table-striped" data-content-type="display" data-content-id-name="displayId" data-state-preference-name="displayGrid" style="width: 100%;"> <thead> <tr> <th>{% trans "ID" %}</th> <th>{% trans "Display" %}</th> <th>{% trans "Display Type" %}</th> <th>{% trans "Address" %}</th> <th>{% trans "Status" %}</th> <th>{% trans "Authorised?" %}</th> <th>{% trans "Current Layout" %}</th> <th>{% trans "Storage Available" %}</th> <th>{% trans "Storage Total" %}</th> <th>{% trans "Storage Free %" %}</th> <th>{% trans "Description" %}</th> <th>{% trans "Orientation" %}</th> <th>{% trans "Resolution" %}</th> {% if currentUser.featureEnabled("tag.tagging") %}<th>{% trans "Tags" %}</th>{% endif %} <th>{% trans "Default Layout" %}</th> <th>{% trans "Interleave Default" %}</th> <th>{% trans "Email Alert" %}</th> <th>{% trans "Logged In" %}</th> <th>{% trans "Last Accessed" %}</th> <th>{% trans "Display Profile" %}</th> <th>{% trans "Version" %}</th> <th>{% trans "Device Name" %}</th> <th>{% trans "IP Address" %}</th> <th>{% trans "Mac Address" %}</th> <th>{% trans "Timezone" %}</th> <th>{% trans "Languages" %}</th> <th>{% trans "Latitude" %}</th> <th>{% trans "Longitude" %}</th> <th>{% trans "Screen shot?" %}</th> <th>{% trans "Thumbnail" %}</th> <th>{% trans "CMS Transfer?" %}</th> <th>{% trans "Bandwidth Limit" %}</th> <th>{% trans "Last Command" %}</th> <th>{% trans "XMR Registered" %}</th> <th>{% trans "Commercial Licence" %}</th> <th>{% trans "Remote" %}</th> <th>{% trans "Sharing" %}</th> <th>{% trans "Screen Size" %}</th> <th>{% trans "Is Mobile?" %}</th> <th>{% trans "Outdoor?" %}</th> <th>{% trans "Reference 1" %}</th> <th>{% trans "Reference 2" %}</th> <th>{% trans "Reference 3" %}</th> <th>{% trans "Reference 4" %}</th> <th>{% trans "Reference 5" %}</th> <th>{% trans "Custom ID" %}</th> <th>{% trans "Cost Per Play" %}</th> <th>{% trans "Impressions Per Play" %}</th> <th>{% trans "Created Date" %}</th> <th>{% trans "Modified Date" %}</th> <th>{% trans "Faults?" %}</th> <th class="rowMenu"></th> </tr> </thead> <tbody> </tbody> </table> <!-- Map --> <div class="row"> <div class="col-sm-12"> <div class="map-legend" style="display:none; position: absolute; z-index: 500; right: 20px; top: 10px;"> <div class="display-map-legend" style="font-size: 12px;"> <div>Logged in</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-green-check.png'/> - Up to date</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-yellow-check.png'/> - Out of date</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-red-check.png'/> - Downloading/Unknown</div> </br> <div>Logged out</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-green-cross.png'/> - Up to date</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-yellow-cross.png'/> - Out of date</div> <div><img style="width: 15%" src='{{ theme.rootUri() }}dist/assets/map-marker-red-cross.png'/> - Downloading/Unknown</div> </div> </div> <div id="display-map" data-displays-url="{{ url_for("display.map") }}"> </div> </div> </div> </div> </div> </div> </div> </div> </div> {% endblock %} {% block javaScript %} <script type="text/javascript"> var mapConfig = {{ mapConfig|json_encode|raw }}; {% if not currentUser.featureEnabled("folder.view") %} disableFolders(); {% endif %} $(document).ready(function() { //<editor-fold desc="Display Grid> var table = $("#displays").DataTable({ "language": dataTablesLanguage, dom: dataTablesTemplate, serverSide: true, stateSave: true, stateDuration: 0, responsive: true, stateLoadCallback: dataTableStateLoadCallback, stateSaveCallback: dataTableStateSaveCallback, filter: false, searchDelay: 3000, order: [[1, "asc"]], ajax: { "url": "{{ url_for("display.search") }}", "data": function (dataToSend) { //make a new object so as not to destroy the input. var data = {}; data.draw = dataToSend.draw; data.length = dataToSend.length; data.start = dataToSend.start; data.order = dataToSend.order; data.columns = []; $.each(dataToSend.columns, function (index, e) { var col = {}; col.data = e.data; if (e.name != null && e.name != "") col.name = e.name; data.columns.push(col); }); $.extend(data, $("#displays").closest(".XiboGrid").find(".FilterDiv form").serializeObject()); return data; } }, createdRow: function (row, data, index) { if (data.mediaInventoryStatus === 1) { $(row).addClass('table-success'); } else if (data.mediaInventoryStatus === 2) { $(row).addClass('table-danger'); } else { $(row).addClass('table-warning'); } }, "columns": [ {"data": "displayId", responsivePriority: 2}, {"data": "display", responsivePriority: 2}, {"data": "displayType", responsivePriority: 2}, {"data": "address", "visible": false, responsivePriority: 5}, { "data": "mediaInventoryStatus", responsivePriority: 2, "render": function (data, type, row) { if (type != "display") return data; var icon = ""; if (data == 1) icon = "fa-check"; else if (data == 2) icon = "fa-times"; else icon = "fa-cloud-download"; return '<span class="fa ' + icon + '" title="' + (row.statusDescription) + '"></span>'; } }, {"data": "licensed", "render": dataTableTickCrossColumn, responsivePriority: 3}, {"data": "currentLayout", "visible": false, "sortable": false, responsivePriority: 5}, { "data": "storageAvailableSpace", responsivePriority: 5, "visible": false, "render": function (data, type, row) { if (type != "display" && type != "export") { return data; } return row.storageAvailableSpaceFormatted; } }, { "data": "storageTotalSpace", responsivePriority: 5, "visible": false, "render": function (data, type, row) { if (type != "display" && type != "export") { return data; } return row.storageTotalSpaceFormatted; } }, {"data": "storagePercentage", "visible": false, "sortable": false, responsivePriority: 5}, {"data": "description", "visible": false, responsivePriority: 4}, {"data": "orientation", "visible": false, responsivePriority: 6}, {"data": "resolution", "visible": false, responsivePriority: 6}, {% if currentUser.featureEnabled("tag.tagging") %} { "name": "tags", responsivePriority: 3, "sortable": false, "visible": false, "data": dataTableCreateTags }, {% endif %} {"data": "defaultLayout", "visible": false, responsivePriority: 4}, {"data": "incSchedule", "render": dataTableTickCrossColumn, "visible": false, responsivePriority: 5}, {"data": "emailAlert", "render": dataTableTickCrossColumn, "visible": false, responsivePriority: 5}, {"data": "loggedIn", "render": dataTableTickCrossColumn, responsivePriority: 3}, {"data": "lastAccessed", "render": dataTableDateFromUnix, responsivePriority: 4}, { "name": "displayProfileId", responsivePriority: 5, "data": function (data, type) { return data.displayProfile; }, "visible": false }, { "name": "clientSort", responsivePriority: 4, "data": function (data) { if (data.clientType === 'lg') { data.clientType = 'webOS' } return data.clientType + ' ' + data.clientVersion + '-' + data.clientCode; }, "visible": false }, {"data": "deviceName", "visible": false, responsivePriority: 5}, {"data": "clientAddress", "visible": false, responsivePriority: 6}, {"data": "macAddress", responsivePriority: 5}, {"data": "timeZone", "visible": false, responsivePriority: 5}, { "data": "languages", "visible": false, "responsivePriority": 5, "render": function(data, type) { if (type !== "display") return data; let returnData = ''; if (typeof data !== undefined && data != null) { let arrayOfTags = data.split(','); returnData += '<div class="permissionsDiv">'; for (let i = 0; i < arrayOfTags.length; i++) { let name = arrayOfTags[i]; if (name !== '') { returnData += '<li class="badge">' + name + '</span></li>' } } returnData += '</div>'; } return returnData; } }, {"data": "latitude", "visible": false, responsivePriority: 6}, {"data": "longitude", "visible": false, responsivePriority: 6}, {"data": "screenShotRequested", "render": dataTableTickCrossColumn, "visible": false, "name": "screenShotRequested", responsivePriority: 7}, { "name": "thumbnail", responsivePriority: 4, "orderable": false, "data": function (data, type) { if (type != "display") return data.thumbnail; if (data.thumbnail != "") { return '<a class="display-screenshot-container" data-toggle="lightbox" data-type="image" href="' + data.thumbnail + '"><img class="display-screenshot" src="' + data.thumbnail + '" data-display-id="'+ data.displayId +'" data-type="'+ data.clientType +'" /></a>'; } else { return ""; } }, "visible": false }, { "data": "isCmsTransferInProgress", "render": dataTableTickCrossColumn, "visible": false, "name": "isCmsTransferInProgress" }, { "name": "bandwidthLimit", responsivePriority: 5, "data": null, "render": {"_": "bandwidthLimit", "display": "bandwidthLimitFormatted", "sort": "bandwidthLimit"}, "visible": false }, { "data": "lastCommandSuccess", responsivePriority: 6, "render": function (data, type, row) { if (type != "display") return data; var icon = ""; if (data == 1) icon = "fa-check"; else if (data == 0) icon = "fa-times"; else icon = "fa-question"; return "<span class='fa " + icon + "'></span>"; }, "visible": false }, { "data": "xmrChannel", responsivePriority: 6, "render": function (data, type, row) { if (type === "export") { return (data !== null && data !== "") ? 1 : 0; } if (type != "display") return data; var icon = ""; if (data != null && data != "") icon = "fa-check"; else icon = "fa-times"; return "<span class='fa " + icon + "'></span>"; }, "visible": false }, { "data": "commercialLicence", "name": "commercialLicence", responsivePriority: 5, "render": function (data, type, row) { if (type != "display") return data; var icon = ""; if (data == 3) { return "N/A"; } else { if (data == 1) { icon = "fa-check"; } else if (data == 0) { icon = "fa-times"; } else if (data == 2) { icon = "fa-clock-o"; } return '<span class="fa ' + icon + '" title="' + (row.commercialLicenceDescription) + '"></span>'; } }, "visible": false }, { "name": "remote", "data": null, responsivePriority: 4, "render": function (data, type, row) { if (type === "display") { var html = "<div class='remote-icons'>"; if ("{{ settings.SHOW_DISPLAY_AS_VNCLINK }}" !== "" && row.clientAddress != null && row.clientAddress !== "") { var link = "{{ settings.SHOW_DISPLAY_AS_VNCLINK }}".replace('%s', row.clientAddress); html += '<a href="' + link + '" title="{{ "VNC to this Display"|trans }}" target="{{ settings.SHOW_DISPLAY_AS_VNC_TGT }}">' + '<i class="fa fa-eye"></i></a>'; } if (row.teamViewerLink !== "") { html += '<a href="' + row.teamViewerLink + '" title="{{ "TeamViewer to this Display"|trans }}" target="_blank">' + '<img src="{{ theme.rootUri() }}theme/default/img/remote_icons/teamviewer.png" alt="TeamViewer Icon"></a>'; } if (row.webkeyLink !== "") { html += '<a href="' + row.webkeyLink + '" title="{{ "Webkey to this Display"|trans }}" target="_blank">' + '<img src="{{ theme.rootUri() }}theme/default/img/remote_icons/webkey.png" alt="Webkey Icon"></a>'; } return html + "</div>"; } else if (type === "export") { if (row.teamViewerLink !== "") { return "TeamViewer: " + row.teamViewerLink; } if (row.webkeyLink !== "") { return "Webkey: " + row.webkeyLink; } if (row.teamViewerLink === "" && row.webkeyLink === "") { return ""; } } else { return ""; } }, "visible": true, "orderable": false }, { "data": "groupsWithPermissions", visible: false, responsivePriority: 10, "render": dataTableCreatePermissions }, {"data": "screenSize", "visible": false, responsivePriority: 6}, { "data": "isMobile", "render": dataTableTickCrossColumn, "visible": false, "name": "isMobile" }, { "data": "isOutdoor", "render": dataTableTickCrossColumn, "visible": false, "name": "isOutdoor" }, {"data": "ref1", "visible": false, responsivePriority: 6}, {"data": "ref2", "visible": false, responsivePriority: 6}, {"data": "ref3", "visible": false, responsivePriority: 6}, {"data": "ref4", "visible": false, responsivePriority: 6}, {"data": "ref5", "visible": false, responsivePriority: 6}, {"data": "customId", "visible": false, responsivePriority: 6}, {"data": "costPerPlay", "visible": false, responsivePriority: 6}, {"data": "impressionsPerPlay", "visible": false, responsivePriority: 6}, {"data": "createdDt", "visible": false, responsivePriority: 6}, {"data": "modifiedDt", "visible": false, responsivePriority: 6}, { "data": "countFaults", "name": "countFaults", responsivePriority: 3, "render": function (data, type, row) { if (row.clientCode < 300) { return ''; } if (type !== "display") { return data; } if (data > 0) { return '<span class="badge" style="background-color: red; color: white">'+(row.countFaults)+'</span>'; } else { return ''; } } }, { "orderable": false, responsivePriority: 1, "data": dataTableButtonsColumn } ] }); table.on('draw', function(e, settings) { dataTableDraw(e, settings, function() { var target = $("#" + e.target.id); var $mapController = target.closest(".XiboGrid").find('.map-controller'); var $listController = target.closest(".XiboGrid").find('.list-controller'); // Move and show map button inside of the table container if ($mapController.length > 0 && target.closest(".dataTables_wrapper").find('.dataTables_folder .map-controller').length == 0) { $mapController.appendTo('.dataTables_folder'); $mapController.removeClass('d-none').addClass('d-inline-flex'); } // Move and show list button inside of the table container if ($listController.length > 0 && target.closest(".dataTables_wrapper").find('.dataTables_folder .list-controller').length == 0) { $listController.appendTo('.dataTables_folder'); $listController.removeClass('d-none').addClass('d-inline-flex'); } }) }); table.on('draw', { form: $("#displays").closest(".XiboGrid").find(".FilterDiv form") }, dataTableCreateTagEvents); table.on('processing.dt', dataTableProcessing); dataTableAddButtons(table, $('#displays_wrapper').find('.dataTables_buttons')); $("#refreshGrid").click(function () { table.ajax.reload(); }); // </editor-fold> //<editor-fold desc="The button click event displaying the map or grid> // Detect the dimensions of our container and set to match. const $displayMap = $('#display-map'); const $mapBtn = $('#map_button'); const $listBtn = $('#list_button'); const $mapParent = $displayMap.parent(); const $dataTablesFolder = $('.dataTables_folder'); $listBtn.hide(); $mapBtn.click(function () { $('.map-legend').show() $displayMap.show(); $mapBtn.hide(); $listBtn.show(); $dataTablesFolder.siblings().hide(); $dataTablesFolder.parent().siblings().hide(); }); $listBtn.click(function () { $('.map-legend').hide(); $displayMap.hide(); $listBtn.hide(); $mapBtn.show(); $dataTablesFolder.siblings().show(); $dataTablesFolder.parent().siblings().show(); }); // </editor-fold> // <editor-fold desc="Leaflet Map> let map; // Wait until we have a width and height. setTimeout(initializeMap, 1000); // Map resizing when folder is toggled window.refreshDisplayMap = function () { if (map) { // is display map visible?? if ($("#display-map").is(":visible")) { map.invalidateSize(); } else { map.setView(map.getCenter(), map.getZoom()); } } } // Initialise and build map function initializeMap() { $displayMap.width($mapParent.width() - 10); $displayMap.height($(window).height() - 100); // Create the map map = L.map('display-map', { center: [mapConfig.setArea.lat, mapConfig.setArea.long], zoom: mapConfig.setArea.zoom, fullscreenControl: true, fullscreenControlOptions: { position: 'topleft' } }); // Tile layer let tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' }).addTo(map); // Print button L.easyPrint({ tileLayer: tiles, sizeModes: ['Current', 'A4Landscape', 'A4Portrait'], filename: 'Displays on Map', hideControlContainer: true }).addTo(map); // Create the marker cluster group var markerClusterGroup = L.markerClusterGroup({ maxClusterRadius: function (mapZoom) { return mapZoom > 9 ? 20 : 80; }, // This defines the icon appearance of the cluster markers iconCreateFunction: function (cluster) { let upToDate = 0; let outOfDate = 0; let downloading = 0; const children = cluster.getAllChildMarkers(); for (const marker of children) { switch (marker.mediaInventoryStatus) { case 1: upToDate++; break; case 3: outOfDate++; break; default: downloading++; break; } } // Create a div showing number of displays by status in the cluster group let pieHtml = createPieChart( [upToDate, outOfDate, downloading], ['rgba(181, 226, 140, 0.9)', 'rgba(243, 194, 18, 0.9)', 'rgba(219, 70, 79, 0.9)'] ); // Create custom icons for the cluster markers return L.divIcon({ html: pieHtml, className: '', iconSize: L.point(40, 40) }); } }); let bounds; bounds = map.getBounds().toBBoxString(); map.on("moveend", _.debounce(function() { bounds = map.getBounds().toBBoxString(); // is display map visible?? const isDisplayMapVisible = $displayMap.is(":visible"); addMarkersToMap(!isDisplayMapVisible); }, 500)); map.on("resize", function() { map.invalidateSize(); }); // Get display points and add to the map // Do not clear layers addMarkersToMap(false); // Bind the filter form $('.XiboGrid').find(".XiboFilter form input").on("keyup", addMarkersToMap); $('.XiboGrid').find(".XiboFilter form input, .XiboFilter form select").on("change", addMarkersToMap); // Cache displayId var added = []; // Add display markers to the cluster group function addMarkersToMap(clear = true) { if (clear) { markerClusterGroup.clearLayers(); added = []; // console.log('Clear Layer'); } // Make an ajax request for the displays feature // Load GeoJSON data and add it to the marker cluster group $.ajax($displayMap.data('displaysUrl'), { method: 'GET', data: $('.XiboGrid').find(".XiboFilter form").serialize() + '&bounds=' + bounds, success: function(response) { // displays if (response.features.length > 0) { // Define icons for display let uptoDateLoggedInIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-green-check.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-green-check-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); let uptoDateLoggedOutIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-green-cross.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-green-cross-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); let outOfDateLoggedInIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-yellow-check.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-yellow-check-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); let outOfDateLoggedOutIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-yellow-cross.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-yellow-cross-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); let downloadingLoggedInIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-red-check.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-red-check-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); let downloadingLoggedOutIcon = L.icon({ iconUrl: '{{ theme.rootUri() }}dist/assets/map-marker-red-cross.png', iconRetinaUrl: '{{ theme.rootUri() }}dist/assets/map-marker-red-cross-2x.png', iconSize: [24, 40], iconAnchor: [12, 40] }); // Loop through features (GeoJSON data) and add each marker to the cluster let feature = L.geoJSON(response, { pointToLayer: function (feature, latlng) { let icon; const icons = { 1: { true: uptoDateLoggedInIcon, false: uptoDateLoggedOutIcon }, 3: { true: outOfDateLoggedInIcon, false: outOfDateLoggedOutIcon }, default: { true: downloadingLoggedInIcon, false: downloadingLoggedOutIcon } }; // The value of "mediaInventoryStatus" and "loggedIn" determines the "icon" const loggedIn = feature.properties.loggedIn ? true: false; const iconType = icons[feature.properties.mediaInventoryStatus] || icons.default; icon = iconType[loggedIn]; let options = { icon: icon }; let popup = '<strong>' + feature.properties.display + '</strong>'; if (feature.properties.orientation) { popup += '<br/><div style="width: 180px;"><span>Orientation: ' + feature.properties.orientation + '</span></div>'; } if (feature.properties.status) { popup += '<div style="width: 180px;"><span>Status: ' + feature.properties.status + '</span>'; if (feature.properties.loggedIn) { popup += '<span> (Logged in) </span></div>'; } else { popup += '<span> (Not logged in) </span></div>'; } } if (feature.properties.displayProfile) { popup += '<div style="width: 180px;"><span>Display profile: ' + feature.properties.displayProfile + '</span></div>'; } if (feature.properties.resolution) { popup += '<div style="width: 180px;"><span>Resolution: ' + feature.properties.resolution + '</span></div>'; } if (feature.properties.lastAccessed) { let lastAccessed = moment(feature.properties.lastAccessed, "X").tz ? moment(feature.properties.lastAccessed, "X").tz(timezone).format(jsDateFormat) : moment(feature.properties.lastAccessed, "X").format(jsDateFormat); popup += '<div style="width: 180px;"><span>Last accessed: ' + lastAccessed + '</span></div>'; } if (feature.properties.thumbnail) { popup += '<div style="width: 180px;"><img class="display-screenshot" src="' + feature.properties.thumbnail + '" /></div>'; } if (!added.includes(feature.properties.displayId)) { // Cache displayId added.push(feature.properties.displayId); var marker = L.marker(latlng, options); // Add the inventory status to each marker so that we can count // the status based displays in iconCreateFunction marker.mediaInventoryStatus = feature.properties.mediaInventoryStatus; // Add a marker return marker.bindPopup(popup) .openPopup() .addTo(markerClusterGroup); } }, }); } } }); // Add the cluster group to the map markerClusterGroup.addTo(map); markerClusterGroup.on('clustermouseover', function(event) { var clusterMarkers = event.layer.getAllChildMarkers(); let upToDate = 0; let outOfDate = 0; let downloading = 0; clusterMarkers.forEach(function(marker) { switch (marker.mediaInventoryStatus) { case 1: upToDate++; break; case 3: outOfDate++; break; default: downloading++; break; } }); let popContent = '<div><strong>Total number of displays</strong>'; const statuses = [ { count: upToDate, text: 'Up to date' }, { count: outOfDate, text: 'Out of date' }, { count: downloading, text: 'Downloading' } ]; for (const { count, text } of statuses) { if (count > 0) { popContent += `<div>${text}: ${count}</div>`; } } popContent += '</div>'; var popup = L.popup() .setLatLng(event.latlng) .setContent(popContent) .openOn(map); }).on('clustermouseout',function(event){ map.closePopup(); }).on('clusterclick',function(event){ map.closePopup(); }); } // Hide map/ Show Display List $displayMap.hide(); } // Creating a pie chart for cluster childrens using HTML, CSS var createPieChart = function(data, colors) { // Get the total of all the data let total = data.reduce(function(a, b) { return a + b; }); // Get the percentage of each data point let percentages = data.map(function(d) { return d / total; }); // Create the pie chart let pie = $('<div></div>'); pie.css('width', '30px'); pie.css('height', '30px'); pie.css('border-radius', '50%'); pie.css('display', 'flex'); pie.css('align-items', 'center'); pie.css('justify-content', 'center'); // Create conic-gradient for each data point let gradient = 'conic-gradient('; let percentageSum = 0; percentages.forEach(function(percentages, i) { let color = colors[i]; let percentStart = percentageSum * 100; let percentEnd = percentStart + percentages * 100; percentageSum += percentages; gradient += color + ' ' + percentStart + '%, ' + color + ' ' + percentEnd + '%, '; }); gradient += 'white 0%)'; // Set the pie chart's background to the conic-gradient pie.css('background', gradient); pie.css('box-shadow', '5px 5px 10px rgba(0, 0, 0, 0.3)'); pie.append('<div style="color: black; font-weight: bold;">'+ total + '</div>'); return $("<div />").append(pie.clone()).html(); }; // </editor-fold> }); {% set showThumbnailColumn = currentUser.getOptionValue("showThumbnailColumn", 1) %} function displayRequestScreenshotFormSubmit() { $("#displayRequestScreenshotForm").submit(); XiboDialogClose(); {% if showThumbnailColumn == 1 %} var table = $('#displays').DataTable(); if (!table.column(["thumbnail:name"]).visible()) { table.columns(["screenShotRequested:name", "thumbnail:name"]).visible(true); } {% endif %} } function setDefaultMultiSelectFormOpen(dialog) { console.log('Multi-select form opened for default layout'); // Inject a list of layouts into the form, in a drop down. var $select = $('<select name="layoutId" class="form-control" data-search-url="{{ url_for("layout.search") }}" data-search-term="layout" data-search-term-tags="tags" data-id-property="layoutId" data-text-property="layout">'); $select.on('change', function() { console.log('Setting commit data to ' + $(this).val()); dialog.data().commitData = {layoutId: $(this).val()}; }); // Add the list to the body. $(dialog).find('.modal-body').append($select); makePagedSelect($select, dialog); } function displayFormLicenceCheckSubmit(form) { // Display commercial licence table column $('table#displays').DataTable().column('commercialLicence:name').visible(true); // Submit form form.submit(); } function setMoveCmsMultiSelectFormOpen(dialog) { console.log('Multi-select form opened for move CMS'); var $message = $( '<div class="col-sm-12 alert alert-info">' + "<p>{{ 'Please note: Once the CMS Address and Key are authenticated in this form the Display will attempt to register with the CMS Instance details entered. Once transferred the Display will stop communicating with this CMS Instance.'|trans }}</p>" + '</div>' ); $(dialog).find('.modal-body').append($message); var $cmsAddress = $( '<div class="form-group row">' + '<label class="col-sm-2 control-label" for="newCmsAddress" accesskey="">New CMS Address</label>' + '<div class="col-sm-10">' + '<input class="form-control" name="newCmsAddress" type="text" id="newCmsAddress" value="">' + '<span class="help-block">{{ "Full URL to the new CMS, including https:// "|trans }}</span>' + '</div>' + '</div>' ); var $cmsKey = $( '<div class="form-group row">' + '<label class="col-sm-2 control-label" for="newCmsKey" accesskey="">New CMS Key</label>' + '<div class="col-sm-10">' + '<input class="form-control" name="newCmsKey" type="text" id="newCmsKey" value="">' + '<span class="help-block">{{ "CMS Secret Key associated with the provided new CMS Address"|trans }}</span>' + '</div>' + '</div>' ); var $authenticationCode = $( '<div class="form-group row">' + '<label class="col-sm-2 control-label" for="twoFactorCode" accesskey="">Two Factor Code</label>' + '<div class="col-sm-10">' + '<input class="form-control" name="twoFactorCode" type="text" id="twoFactorCode" value="">' + '<span class="help-block">{{ "Please enter your Two Factor authentication code"|trans }}</span>' + '</div>' + '</div>' ); $(dialog).find('.modal-body').append($cmsAddress, $cmsKey, $authenticationCode); $('#twoFactorCode, #newCmsAddress, #newCmsKey').on('change', function() { dialog.data().commitData = { newCmsAddress: $('#newCmsAddress').val(), newCmsKey: $('#newCmsKey').val(), twoFactorCode: $('#twoFactorCode').val() }; }); } function makeVenueSelect($element) { // Get the openOOH venue types $element.append(new Option('', '0', false, false)); $.ajax({ method: 'GET', url: $element.data('searchUrl'), dataType: 'json', success: function(response) { $.each(response.data, function(key, el) { const selected = el.venueId === $element.data('venueId'); $element.append(new Option(el.venueName, el.venueId, selected, selected)); }); $element.select2(); }, error: function(xhr) { SystemMessage(xhr.message || '{{"Unknown error"|trans}}', false); } }); } function displayEditFormOpen(dialog) { // Setup display profile form displayProfileFormOpen(); XiboInitialise('#settings-from-display-profile'); var $settings = $(dialog).find('#settings-from-display-profile').find('.form-group'); var $table = $(dialog).find('#settings-from-profile tbody').empty(); var override = $(dialog).data('extra'); var $venueIdSelect2 = $(dialog).find(".venue-select select.form-control"); if ($venueIdSelect2.data('initialValue')) { $venueIdSelect2.data('initialised', true); makeVenueSelect($venueIdSelect2); } else { dialog.find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { const activeTab = $(e.target).attr('href') if (activeTab === '#location' && !$venueIdSelect2.data('initialised')) { $venueIdSelect2.data('initialised', true); makeVenueSelect($venueIdSelect2); } }); } // Parse special fields override.forEach(function(field, index) { if(['lockOptions','pictureOptions', 'timers'].includes(field.name)) { var parsedValues = JSON.parse(field.value); // Add values to the override array $.each(parsedValues, function(name, value){ if(name == 'keylock') { $.each(value, function(keylockName, keylockValue){ if(keylockName == 'local') { keylockName = 'keylockLocal'; } if(keylockName == 'remote') { keylockName = 'keylockRemote'; } override.push({name: keylockName, value: keylockValue}) }); } // Convert boolean and numbers to string value = (['boolean','number'].includes(typeof value)) ? value.toString() : value; override.push({name: name, value: value}) }); } }); // Method to create a new input field based on the hidden form var createInputField = function(target, inputName, newValue = null) { var select2FixFlag = false; var timepickerFixFlag = false; var timepickerOptionsFixFlag = false; var sliderFixFlag = false; var sliderFixOptions = {}; // Grab input field from hidden table var $inputFields = $settings.find('#' + inputName); // If no input field is capture by ID, get special fields if($inputFields.length == 0) { if( $settings.find('.multiSelect').length > 0) { // Copy special fields ( timers, pictureOptions ) by selected option $inputFields = $settings.find('.multiSelect option:selected[value="' + inputName + '"]').parents('.form-group:first').find('.multiSelect, .multiSelectInputs'); $inputFields.each(function(key, el) { if($(el).find('.timePickerDisplayEditForm').length > 0) { timepickerOptionsFixFlag = true; $(el).find('.input-group.timerInit').removeClass('timerInit'); destroyDatePicker($(el).find('.timePickerDisplayEditForm:not(.datePickerHelper)')); } else if($(el).find('.pictureControlsSlider').length > 0) { sliderFixFlag = true; sliderFixOptions = $(el).find('.pictureControlsSlider').bootstrapSlider('getAttribute'); $(el).find('.pictureControlsSlider').bootstrapSlider('destroy'); } }); } } else if($inputFields.length == 1 && $inputFields.hasClass('timePicker')) { timepickerFixFlag = true; destroyDatePicker($inputFields); // Time inputs $inputFields = $inputFields.parent(); } else if($inputFields.length == 1 && $inputFields.hasClass('select2-hidden-accessible')) { select2FixFlag = true; // Destroy select2 before copying $inputFields.select2('destroy'); } // Save old field before cloning $inputFieldsOld = $inputFields; // Clone input fields ( to be able to reuse the originals ) $inputFields = $inputFields.clone(true); if(select2FixFlag) { // Mark old field as select2 with the select2 class // so it can be reinitialised if needed $inputFieldsOld.addClass('select2-hidden-accessible'); } // Add input field to the target $(target).html($inputFields); if(timepickerFixFlag) { XiboInitialise('#' + $inputFieldsOld.parents('form').attr('id')); XiboInitialise('#' + $(target).parents('form').attr('id')); } if(timepickerOptionsFixFlag) { timersFormInit($inputFieldsOld); timersFormInit($(target)); // Parent container var $inputParent = $inputFields.parent() $inputParent.addClass('timerOverride'); $inputParent.find('.date-clear-button').remove(); $inputParent.append('<div class="text-muted">{{ "Adjust the times of this timer. To add or remove a day, use the Display Profile."|trans }}</div>'); } if(sliderFixFlag) { $inputFieldsOld.find('.pictureControlsSlider').bootstrapSlider(sliderFixOptions); $inputFields.find('.pictureControlsSlider').bootstrapSlider(sliderFixOptions); } // Set value if defined if(newValue != null) { if($(target).find('.multiSelectInputs .pictureControlsSlider').length > 0) { // SLIDER if(!$.isNumeric(newValue)) { // If value is a label, get index $(target).find('.multiSelectInputs .slider-tick-label').each(function(idx, el) { if($(el).html() == newValue) { newValue = idx; return false; } }); } // Set value $(target).find('.pictureControlsSlider').bootstrapSlider('setValue', newValue); } else if($inputFields.attr('type') == 'checkbox') { // CHECKBOX $($inputFields).prop('checked', newValue); } else if(timepickerFixFlag) { $($inputFields).find('input').val(newValue); } else if(timepickerOptionsFixFlag) { $.each(newValue, function(name, value){ if(name == 'on') { $($inputFields).find('input.timersOn').val(value); } else if(name == 'off') { $($inputFields).find('input.timersOff').val(value); } }) } else { $($inputFields).val(newValue); } } // Reload select 2 with new value if(select2FixFlag) { // Restore select2 after value set makePagedSelect($inputFields); } // Android dimensions init if(inputName == 'screenDimensions') { setAndroidDimensions($(target)); // CSS fix $(target).find('.androidDimensionInput').removeClass('col-3').addClass('col-6'); } // If there's a multiselect, set the value of the dropdown ( it's not kept on cloning ) and hide it $(target).find('.multiSelect').val(inputName).hide(); // Style multi selects if($(target).find('.multiSelectInputs').length > 0) { // Calculate column size for bootstrap var colSize = Math.round(12/$(target).find('.multiSelectInputs').length); //Remove all style classes and add the new size class $(target).find('.multiSelectInputs').attr('class', 'multiSelectInputs col-sm-' + colSize) } // Set data propeties $(target).attr('data-editing', 'true'); $(target).attr('data-input-name', inputName); // Remove click to edit event $(target).unbind('click'); // Fixes for slider $(target).find('.slider').addClass('scaled-slider'); $(target).find('.pictureControlsSlider').bootstrapSlider('refresh', { useCurrentValue: true }); // Add help text if exists on label let inputHelpText = $(target).parent('tr').find('td:first strong').attr('title'); if(inputHelpText) { $(target).append('<div class="text-muted">' + inputHelpText + '</div>'); } var $newButton = $('<button class="btn btn-outline-danger btn-sm pull-right button-close-override" type="button"><i class="fa fa-times"></i></button>').click(function (e) { e.stopPropagation(); restoreInputField(target, inputName); }); $(target).append($newButton); }; // Method to restore the input field to the edit button var restoreInputField = function(target, inputName) { $(target).html('<button class="btn btn-block btn-outline-secondary" type="button"><i class="fa fa-edit"></i></button>'); // Handlers for field edit $(target).off().click(function() { if(!$(this).data('editing')) { createInputField($(this), inputName); } }); $(target).attr('data-editing', 'false'); }; // Build table $.each($settings, function(index, element) { var $label = $(element).find('label'); var $input = $(element).find('input,select'); var $help = $(element).find('small.form-text.text-muted'); var over = $label.prop("for"); var value = ''; var text = ''; var help = $help.length > 0 ? $help.text() : ''; // Skip for some fields if(['name', 'isDefault'].includes(over)) { return true; } if($(element).hasClass('form-group-timers')) { // Get text and override name over = $(element).find('.multiSelect').val(); text = $(element).find('.multiSelect option:selected').text(); // Get value value = $(element).find('.timersOn').val() + ' - ' + $(element).find('.timersOff').val(); } else if($(element).hasClass('form-group-picture-options')) { // Get text and override name over = $(element).find('.multiSelect').val(); text = $(element).find('.multiSelect option:selected').text(); // Get labels var labels = []; $(element).find('.multiSelectInputs .slider-tick-label').each(function(idx, el) { labels.push($(el).html()); }); // Get value value = $(element).find('.multiSelectInputs .pictureControlsSlider').bootstrapSlider('getValue'); // If specific value has a label, use it as value if(labels[value] != undefined) { value = labels[value]; } } else if($input.attr('type') == 'checkbox'){ // Get text and value text = $label.text(); value = $input.is(":checked"); } else if($input.is('select')){ // Get text and value text = $label.text(); value = $input.find('option:selected').text(); } else if(over === 'screenDimensions'){ // Get text and value text = $label.text(); value = $(element).find('#screenDimensions').val(); } else { // Get text and value text = $label.text(); value = $input.val(); } // Skip empty fields if(over == '' || over == undefined || over == null) { return true; } // Append new row to the table var $tableNewRow = $('<tr><td style="width: 40%;"><strong title="' + help + '">' + text + '</strong></td><td style="width: 25%; overflow-x: auto; max-width: 250px;"><div>' + value + '</div></td><td class="override-input text-center" style="width: 35%;" data-editing="false" data-input-name="' + over + '"><button class="btn btn-block btn-outline-secondary" type="button"><i class="fa fa-edit"></i></button></td></tr>').appendTo($table); // Get override element var overrideEl = override.find(function(x) { return x.name === over; }); if(overrideEl != undefined) { //If element was found, create an input // Create input with override value createInputField($tableNewRow.find('.override-input'), over, overrideEl.value); } }); // Handlers for field edit $(dialog).find('.override-input[data-editing="false"]').click(function() { var inputName = $(this).data('inputName'); createInputField($(this), inputName); }); // Refresh on tab switch to fix broken labels $('a[data-toggle="tab"]').on('shown.bs.tab', function() { $('.pictureControlsSlider').bootstrapSlider('refresh', { useCurrentValue: true }); }); // Call XiboInitialise on table XiboInitialise('#settings-from-profile'); } // Custom submit for display form function displayEditFormSubmit() { var $form = $('#displayEditForm'); // Grab and alter the value in the bandwidth limit field var bandwidthLimitField = $form.find("input[name=bandwidthLimit]"); var bandwidthLimitUnitsField = $form.find("select[name=bandwidthLimitUnits]"); var bandwidthLimit = bandwidthLimitField.val(); if (bandwidthLimitUnitsField.val() == 'mb') { bandwidthLimit = bandwidthLimit * 1024; } else if (bandwidthLimitUnitsField.val() == 'gb') { bandwidthLimit = bandwidthLimit * 1024 * 1024; } // Set the field bandwidthLimitField.prop('value', bandwidthLimit); // Remove temp fields and enable checkbox after submit $form.submit(function(event) { event.preventDefault(); // Re-enable checkboxes $form.find('input[type="checkbox"]').each(function () { // Enable checkbox $(this).attr('disabled', false); }); // Remove temp input fields $form.find('input.temp-input').each(function () { $(this).remove(); }); }); // Replace all checkboxes with hidden input fields $form.find('input[type="checkbox"]').each(function () { // Get checkbox values var value = $(this).is(':checked') ? 'on' : 'off'; var id = $(this).attr('id'); // Create hidden input $('<input type="hidden" class="temp-input">') .attr('id', id) .attr('name', id) .val(value) .appendTo($(this).parent()); // Disable checkbox so it won't be submitted $(this).attr('disabled', true); }); // Submit form $form.submit(); } $('body').on('click', '.display-screenshot', function(el) { var displayId = el.target.dataset.displayId; var displayType = el.target.dataset.type; var statusWindowData = {}; $.ajax({ url: "/display/status/" + displayId, method: "GET", dataType: "json", success: function (data) { if (data != null) { // do some processing on data received from webOS and Tizen Players. if (displayType === 'webOS' || displayType === 'sssp') { data.logMessagesArray = JSON.stringify(data.logMessagesArray); data.allLayouts = JSON.stringify(data.allLayouts); data.scheduledLayouts = JSON.stringify(data.scheduledLayouts); data.validLayouts = JSON.stringify(data.validLayouts); data.invalidLayouts = JSON.stringify(data.invalidLayouts); data.blacklistArray = JSON.stringify(data.blacklistArray); data.spaceTotal = formatBytes(data.spaceTotal, 2); data.spaceFree = formatBytes(data.spaceFree, 2); data.spaceUsed = formatBytes(data.spaceUsed, 2); } statusWindowData['data'] = data; statusWindowData['type'] = displayType; var statusWindowTemplate = Handlebars.compile($('#display-status-window-template').html()); $('.modal-body').append(statusWindowTemplate(statusWindowData)); } } }); }); </script> <style> #settings-from-profile tr.row-fluid { height: 50px; } </style> {% endblock %}