{#
/**
 * Copyright (C) 2020 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 %}
{% set dataSetName = dataSet.dataSet %}

{% block title %}{% trans %}Data Entry for {{ dataSetName }}{% endtrans %} | {% endblock %}

{% block actionMenu %}
    <div class="widget-action-menu pull-right">
        <button class="btn btn-success XiboFormButton addRowButton" title="{% trans "Add a row to the end of this DataSet" %}" href="{{ url_for("dataSet.data.add.form", {"id": dataSet.dataSetId}) }}"><i class="fa fa-plus-circle" aria-hidden="true"></i> {% trans "Add Row" %}</button>
        <button class="btn btn-primary toggleMultiSelectMode" id="toggleMultiSelectMode" title="{% trans "Click to toggle between Data Edit and Multi Select modes" %}"><i class="fa fa-object-group" aria-hidden="true"></i> <span class="button-text">{% trans "Multi Select Mode" %}</span></button>
        <button class="btn btn-danger d-none deleteSelectedRows" id="deleteSelectedRows" title="{% trans "Click to delete selected rows" %}" disabled="disabled"><i class="fa fa-trash" aria-hidden="true"></i> <span class="button-text">{% trans "Delete Rows" %}</span></button>
        <button class="btn btn-info XiboRedirectButton" href="{{ url_for("dataSet.column.view", {"id": dataSet.dataSetId}) }}"><i class="fa fa-columns" aria-hidden="true"></i> {% trans "View Columns" %}</button>
        <button class="btn btn-primary" id="refreshGrid" title="{% trans "Refresh the Table" %}" href="#"><i class="fa fa-refresh" aria-hidden="true"></i></button>
    </div>
{% endblock %}


{% block pageContent %}
    {% set widgetTitle %}{% trans %}Data Entry for {{ dataSetName }}{% endtrans %}{% endset %}
    <div class="widget">
        <div class="widget-title">{{ widgetTitle }} | <strong class="dataset-edit-title-mode widget-sub-title">{% trans "Edit Mode" %}</strong><span title="{% trans "Click on any row to edit" %}" class="badge badge-pill badge-secondary px-1 mx-1">?</span></div>
        <div class="widget-body">
            <div class="XiboGrid" id="{{ random() }}">
                <div class="XiboFilter">
                    <div class="FilterDiv card-body" id="Filter">
                        <form class="form-inline">
                            {% for col in dataSet.getColumn() %}
                                {% if col.dataSetColumnTypeId == 1 and (col.dataTypeId == 1 or col.dataTypeId == 2) and col.showFilter == 1 %}
                                    {{ inline.input(col.heading, col.heading) }}
                                {% endif %}
                            {% endfor %}
                        </form>
                    </div>
                </div>
                <div class="XiboData card pt-3">
                    <table id="datasets" class="table table-striped" data-image-url="{{ url_for("library.download", {"id":":id"}) }}?preview=1&width=150&height=150">
                        <thead>
                        <tr>
                            <th>{% trans "ID" %}</th>
                            {% for col in dataSet.getColumn() %}
                                <th>{{ col.heading }}</th>
                            {% endfor %}
                            <th></th>
                        </tr>
                        </thead>
                        <tbody>

                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>

{% endblock %}

{% block javaScript %}
    <script type="text/javascript" nonce="{{ cspNonce }}">

        var imageUrl = $("#datasets").data("imageUrl");
        var cols = [];
        var editMode = true;
        var editModeTitleTrans = "{% trans "Edit Mode" %}";
        var multiSelectTitleTrans = "{% trans "Multi Select Mode" %}";
        var editModeHelpTrans = "{% trans "Click on any row to edit" %}";
        var multiSelectHelpTrans = "{% trans "Select one or more rows to delete" %}";
        const entityMap = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#39;',
            '/': '&#x2F;',
            '`': '&#x60;',
            '=': '&#x3D;'
        };

        function sanitizeHtml(string) {
            return String(string).replace(/[&<>"'`=\/]/g, function (s) {
                return entityMap[s];
            });
        }

        function validateHTMLData(str) {
            let doc = new DOMParser().parseFromString(str, "text/html");

            // If valid html, sanitize and format as a code
            if (Array.from(doc.body.childNodes).some(node => node.nodeType === 1)) {
                return `<code>${sanitizeHtml(str)}</code>`;
            }

            return str;
        }

        cols.push({ "name": "id", "data": "id" });
        {% for col in dataSet.getColumn() %}
            {% if col.dataTypeId == 3 %}
                cols.push({ "data": "{{ col.heading }}", "orderable": {% if col.showSort == 1 %}true{% else %}false{% endif %}, "render": dataTableDateFromIso });
            {% elseif col.dataTypeId == 5 %}
                cols.push({ "data": "{{ col.heading }}", "orderable": {% if col.showSort == 1 %}true{% else %}false{% endif %}, "render": function(data, type, row) {
                        if (type != "display")
                            return data;

                        if (data == null)
                            return "";

                        return '<img src="' + imageUrl.replace(":id", data) + '"/>';
                    }
                });
            {% else %}
                cols.push({
                    "data": "{{ col.heading }}",
                    "orderable": {% if col.showSort == 1 %}true{% else %}false{% endif %},
                    "render": function(data) {
                        return validateHTMLData(data);
                    }
                });
            {% endif %}
        {% endfor %}

        cols.push({
            "orderable": false,
            "data": function(data, type, row, meta) {
                if (type != "display")
                    return "";

                var url = "{{ url_for("dataSet.data.delete.form", {"id": dataSet.dataSetId, "rowId":':rowId'}) }}".replace(":rowId", data.id);

                return "<a href=\"" + url + "\" class=\"XiboFormButton\"><span class=\"fa fa-times\"></span></a>";
            }
        });

        var table = $("#datasets").DataTable({ "language": dataTablesLanguage,
            dom: dataTablesTemplate,
            serverSide: true, stateSave: true, stateDuration: 0,
            filter: false,
            responsive: true,
            searchDelay: 3000,
            "order": [[ 0, "asc"]],
            ajax: {
                "url": "{{ url_for("dataSet.data.search", {id: dataSet.dataSetId}) }}",
                "data": function(dataToSend) {
                    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.orderable) {
                            data.columns.push(col);
                        } else {
                            data.columns.push({});
                        }
                    });

                    $.extend(data, $("#datasets").closest(".XiboGrid").find(".FilterDiv form").serializeObject());
                    return data;
                },
                complete: function (response) {

                    if (response.responseJSON.data.exception != '' && response.responseJSON.data.exception != undefined) {
                        var error = response.responseJSON.data.exception;
                        $("#datasets tbody").html(error)
                    }
                }
            },
            "columns": cols
        });

        table.on('draw', dataTableDraw);
        table.on('processing.dt', dataTableProcessing);
        dataTableAddButtons(table, $('#datasets_wrapper').find('.dataTables_buttons'));

        $("#refreshGrid").click(function () {
            table.ajax.reload();
        });

        var dataSetEditFormOpen = _.debounce(function() {
            var data = table.row($(this)).data();

            // Load the edit form.
            var editUrl = "{{ url_for("dataSet.data.edit.form", {"id": dataSet.dataSetId, "rowId":':rowId'}) }}".replace(":rowId", data.id);
            XiboFormRender(editUrl);
        }, 500, true);

        // default is Edit mode, hence this should be our onclick event and deleteRows button should be hidden.
        $("#datasets tbody").on('click', 'tr', dataSetEditFormOpen);

        // Toggle between Edit and Multi Select modes
        // we also switch between two different onclick events depending on the mode and show/hide deleteRows button.
        $('#toggleMultiSelectMode').on("click", function(e) {
            e.preventDefault();

            if (editMode) {
                // switch to multi select mode
                editMode = false;
                $(this).find('.button-text').text(editModeTitleTrans);
                $(this).find('i').removeClass('fa-object-group').addClass('fa-edit');
                $('.dataset-edit-title-mode').text(multiSelectTitleTrans);
                $('.widget-title .badge').attr('title', multiSelectHelpTrans);
                $("#datasets tbody").off('click', 'tr');
                $('#datasets tbody tr.selected').removeClass('selected');
                $(".deleteSelectedRows").removeClass('d-none');
                $('#datasets tbody').on('click', 'tr', function(ev) {

                    // See if element has class already
                    var hasClass = $(ev.currentTarget).hasClass('selected')

                    // Add class to the clicked one ( or remove it if there was already there )
                    $(ev.currentTarget).toggleClass('selected', !hasClass);

                    // Change Delete button state according to the number of selected rows
                    if ($('#datasets tbody tr.selected').length > 0) {
                        $(".deleteSelectedRows").removeAttr('disabled');
                    } else {
                        $(".deleteSelectedRows").attr('disabled', 'disabled');
                    }
                     
                });
            } else {
                // switch to edit mode
                editMode = true;
                $(this).find('.button-text').text(multiSelectTitleTrans);
                $(this).find('i').removeClass('fa-edit').addClass('fa-object-group');
                $('.dataset-edit-title-mode').text(editModeTitleTrans);
                $('.widget-title .badge').attr('title', editModeHelpTrans);
                $(".deleteSelectedRows").addClass('d-none');
                $("#datasets tbody").off('click', 'tr');
                $('#datasets tbody tr.selected').removeClass('selected');
                $(".deleteSelectedRows").attr('disabled', 'disabled');
                $("#datasets tbody").on('click', 'tr', dataSetEditFormOpen);
            }
        });

        // get selected rows and their ids then pass it to dataSet data delete ajax call and reload the grid when done.
        $('#deleteSelectedRows').on("click", function(e) {
            e.preventDefault();

            var rows = [];
            var rowIds = [];
            var processedRows = 0;

            $('#datasets tbody tr.selected').each(function(idx, ele) {
                rows.push(table.row(ele).data());
            });

            for (var i = 0; i < rows.length; i++) {
                rowIds.push(rows[i].id);
            }

            rowIds.forEach(function(id) {
                $.ajax({
                    url: "{{ url_for("dataSet.data.delete", {"id": dataSet.dataSetId, "rowId":':rowId'}) }}".replace(":rowId", id),
                    type: "DELETE",
                    success: function (data) {
                        processedRows++;
                        if (processedRows === rowIds.length) {
                            table.ajax.reload();
                        }
                    }
                });
            });
        });

        // handle add row button when we don't have any value columns in the dataset
        var valueColumns = {{ dataSet.columns|filter(column => column.dataSetColumnTypeId == '1')|json_encode|raw }};
        var valueColumnsWarningMessage = "{% trans "No value columns have been configured for this dataset. Please configure your columns accordingly." %}";
        if(valueColumns.length === 0) {
            // remove class xibo form open to prevent opening the form
            $('.addRowButton')
                .addClass('disabled')
                .removeClass('XiboFormButton')
                .on('click', function(e) {
                    // show toast notification
                    toastr.error(valueColumnsWarningMessage);
                });
        }
    </script>
{% endblock %}