{% extends "base.twig" %}

{% block resources %}
    <link href={{asset('dist/css/CaseView.css')}} rel="stylesheet">
    <link href={{asset('dist/css/mapReport.css')}} rel="stylesheet">
    
    <!-- DataTables -->
    <link href={{asset('bower_components/datatables/media/css/jquery.dataTables.min.css')}}>
{% endblock %}

{% block nav %}
    {% if is_granted('ROLE_REPORTS_ALL') == true %}
        <li>
            <a href="{{ path('sync-report') }}"><i class="fa fa-table fa-fw"></i> Sync Report<span
                    class="fa arrow"></span></a>
            <ul id="sync-report-dictionaries" class="nav nav-second-level collapse in">
            </ul>
        </li>
            <li>
            <a href="{{ path('map-report') }}"><i class="fa fa-table fa-fw"></i> Map Report<span
                    class="fa arrow"></span></a>
        </li>
    {% endif %}
{% endblock %}
{# nav #}

{% block modal %}
    <!-- Import progress modal -->
    <div id="main-progress-modal" class="modal" data-keyboard="false" data-backdrop="static">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header"><h4>Processing....</h4>
                    <div class="progress">
                        <div style="width:0%" class="progress-bar progress-bar-striped progress-bar-animated" 
                                role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="2">
                            <div class="progressText">0% Complete</div>
                        </div>
                    </div>
                    <!-- /.progress -->
                </div>
                <!-- /.modal-header -->
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.main-progress-modal -->
    
    <div id="pointInfoModal" class="modal fade" role="dialog" aria-labelledby="pointInfoModalLabel">
        <div class="modal-dialog" style = "width: 80%">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                    <h4 class="modal-title" id="pointInfoModalLabel">Case</h4>
                </div>
                <!-- /.modal-header -->
                <div class="modal-body" id="pointInfoModalBody" style="overflow-x: scroll;">
                </div>
                <!-- .modal-body -->
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- #pointInfoModal -->
    
    <div id="multipleCaseViewSelectModal" class="modal fade" role="dialog" aria-labelledby="pointInfoModalLabel">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                    <h4 class="modal-title">Select case</h4>
                </div>
                <div class="modal-body" id="multipleCaseViewSelectModalBody">
                </div>
            </div>
        </div>
    </div>
    <!-- #multipleCaseViewSelectModal -->
{% endblock %}
{# modal #}
{% block content %}
    <div class="row">
        <div class="col-xs-12">
            <div id="alert" class="alert-placeholder-cspro alert-margin-cspro"></div>
            <!-- /.alert -->
        </div>
        <!-- /.col-xs-12 -->
    </div>
    <!-- /.row -->
    <div class="row">
        <div class="col-xs-12">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <div class="btn-toolbar">
                        <i class="fa fa-table fa-fw"></i> Sync Report <div id="dictionary-id-dropdown-container" class="pull-right"></div>
                    </div>
                </div>
                <!-- /.panel-heading -->
                <div class="panel-body">
                    <div id="store-area-names-column-count" class="table-responsive" data-area-names-column-count="0">
                        <table id="table-responsive" class="table table-striped table-bordered table-hover" style="width:100%">
                        </table>
                    </div>
                    <!-- /.table-responsive -->
                </div>
                <!-- /.panel-body -->
            </div>
            <!-- /.panel -->
        </div>
        <!-- /.col-xs-12 -->
    </div>
    <!-- /.row -->
{% endblock %}

{% block scripts %}
    <script src={{asset('bower_components/bootstrap-validator/dist/validator.min.js')}}></script>

    <!-- Page-Level Scripts -->
    <script>
        "use strict";
        
        var filterLevels = [];

        $(document).ready(function () {

            var dictionaryDropdown = document.getElementById('dictionary-id-dropdown-container');
            dictionaryDropdown.addEventListener('change', function () {
                dataTables.initSyncReport();
            });

            chain.updateSyncReportAfterPageReload();
            
            /*
                // Data tables
                $('[data-toggle="popover"]').popover();
                $.fn.dataTable.ext.errMode = 'none'; //user custom error processing for the datatable to handle redirects
                
                var syncTable = $('#table-responsive')
                .on('xhr.dt', function ( e, settings, json, xhr ) {
                if (xhr.status === 401 || xhr.status === 405) {
                window.location.href = "{{ path('logout') }}";
                }
                // Note no return - manipulate the data directly in the JSON object.
                } )
                .on( 'error.dt', function ( e, settings, techNote, message ) {
                console.log( 'An error has been reported by DataTables: ', message );
                } )
                .DataTable({
                "dom": 'lrtip',
                "processing": true,
                "searching": true,
                "paging": true,
                "order": [[0, "asc"]],
                "columnDefs": [
                {"name": "region", "orderable": true, "searchable": true, "targets": 0},
                {"name": "district", "orderable": true, "searchable": true, "targets": 1},
                {"name": "state", "orderable": true, "searchable": true, "targets": 2},
                {"name": "synchronized", "orderable": true, "searchable": true, "targets": 3},
                ],
                "ajax": "{{ url('syncReportJson') }}",
                "serverSide": true,
                "columns": [
                {"data": "id_REGION_CODE"},
                {"data": "id_DIVISION_CODE"},
                {"data": "id_STATE_CODE"},
                {"data": "total_count"},
                ],
                // ALW - TODO: Comment out column filters
                initComplete: function () {
                this.api().columns().every( function () {
                var column = this;
                var select = $('<select><option value=""></option></select>')
                .appendTo( $(column.footer()).empty() )
                .on( 'change', function () {
                var val = $.fn.dataTable.util.escapeRegex(
                $(this).val()
                );
                
                column
                .search( val, false, false )
                .draw();
                } );
                
                column.data().unique().sort().each( function ( d, j ) {
                select.append( '<option value="'+d+'">'+d+'</option>' )
                } );
                } );
                },
                }); // Data tables
                */
        }); // $(document).ready

        var chain =
                {
                    updateSyncReportAfterPageReload: function () {
                        // Chain Ajax calls (getAreaNamesColumnCount, getDictionaries, getDictionaryIds, initSyncReport)
                        $("body").addClass("loading");
                        var gettingAreaNamesColumnCount = db.getAreaNamesColumnCount();
                        db.getDictionaries().then(function (response) {
                            // Done getDictionaries
                            return $.when(gettingAreaNamesColumnCount, db.getDictionaryIds());
                        }, function () {
                            // Fail getDictionaries
                        }).then(function () {
                            // Done getAreaNamesColumnCount + getDictionaryIds
                            $("body").removeClass("loading");
                            dataTables.initSyncReport();
                        }, function () {
                            // Fail getAreaNamesColumnCount + getDictionaryIds
                            $("body").removeClass("loading");
                        });
                    },

                    updateSyncReportAfterChangeDictionaries: function () {
                        // Chain Ajax calls (getDictionaryIds, initSyncReport)
                        $("body").addClass("loading");
                        db.getDictionaryIds().then(function () {
                            // Done getDictionaryIds
                            $("body").removeClass("loading");
                            dataTables.initSyncReport();
                        }, function () {
                            // Fail getDictionaryIds
                            $("body").removeClass("loading");
                        });
                    }
                }

        var db =
                {
                    getAreaNamesColumnCount: function () {
                        // Get column count for cspro_area_names table
                        return $.ajax({
                            type: "GET",
                            url: "{{ url('report-area-names-column-count-json') }}",
                            dataType: "json"
                        }).then(function (response) {
                            // Done getAreaNamesColumnCount
                            if (response.type === "error") {
                                // Only invalid responses will have a type
                                ui.showAlert(response.message, "alert alert-danger");
                                //if (response.status === 401) {
                                //    window.location.href = "{{ path('logout') }}";
                                //}
                                //else {
                                // Convert success to failure
                                return $.Deferred().reject(response).promise();
                                //}
                            } else {
                                // Update data attribute w/ column count
                                var areaNamesColumnCount = document.getElementById('store-area-names-column-count');
                                areaNamesColumnCount.dataset.areaNamesColumnCount = response;
                            }
                        }, function (response) {
                            // Fail getAreaNamesColumnCount
                            if (response.status === 200) {
                                // TODO: Hack to catch expired token
                                window.location.href = "{{ path('logout') }}";
                            } else {
                                ui.showAlert(response.message, "alert alert-danger");
                            }
                        });
                    },

                    getDictionaries: function () {
                        // Get all dictionary names and labels
                        return $.ajax({
                            type: "GET",
                            url: "{{ url('report-dictionaries-json') }}",
                            dataType: "json"
                        }).then(function (response) {
                            // Done getDictionaries
                            if (response.type === "error") {
                                // Only invalid responses will have a type
                                ui.showAlert(response.message, "alert alert-danger");
                                //if (response.status === 401) {
                                //    window.location.href = "{{ path('logout') }}";
                                //}
                                //else {
                                // Convert success to failure
                                return $.Deferred().reject(response).promise();
                                //}
                            } else {
                                if (response.length > 0) {
                                    ui.buildDictionaryList(response, "sync-report-dictionaries");
                                    return response;
                                } else {
                                    ui.showAlert("To view report add a configuration and process the cases", "alert alert-danger");
                                    // Convert success to failure
                                    return $.Deferred().reject(response).promise();
                                }
                            }
                        }, function (response) {
                            // Fail getDictionaries
                            if (response.status === 200) {
                                // TODO: Hack to catch expired token
                                window.location.href = "{{ path('logout') }}";
                            } else {
                                ui.showAlert(response.message, "alert alert-danger");
                            }
                        });
                    },

                    getDictionaryIds: function () {
                        // Get id items from dictionary (eventual columns for DataTables)
                        var selectedDictionary = ui.getSelectedDictionary();

                        return $.ajax({
                            type: "GET",
                            url: "{{ url('report-dictionary-ids-json') }}",
                            dataType: "json",
                            data: {
                                dictionary: selectedDictionary
                            }
                        }).then(function (response) {
                            // Done getDictionaryIds
                            if (response.type === "error") {
                                // Only invalid responses will have a type
                                ui.showAlert(response.message, "alert alert-danger");
                                //if (response.status === 401) {
                                //    window.location.href = "{{ path('logout') }}";
                                //}
                                //else {
                                // Convert success to failure
                                return $.Deferred().reject(response).promise();
                                //}
                            } else {
                                ui.buildDictionaryIdDropdown(response, "dictionary-id-dropdown-container");
                            }
                        }, function (response) {
                            // Fail getDictionaryIds
                            if (response.status === 200) {
                                // TODO: Hack to catch expired token
                                window.location.href = "{{ path('logout') }}";
                            } else {
                                ui.showAlert(response.message, "alert alert-danger");
                            }
                        });
                    }
                }

        var ui =
                {
                    buildDictionaryList: function (dictionaryObjects, containerId)
                    {
                        var container = document.getElementById(containerId);

                        while (container.firstChild) {
                            // Remove a previous dictionary list or message
                            container.removeChild(container.firstChild);
                        }

                        var dictionaryList = document.createElement("ul");
                        dictionaryList.setAttribute("id", "dictionary-list");

                        Array.prototype.forEach.call(dictionaryObjects, function (el, i) {
                            var listItem = document.createElement("li");
                            listItem.setAttribute("id", el.dictionary_name);
                            if (i === 0) {
                                // Default first dictionary in list as selected
                                listItem.setAttribute("class", "selected");
                            }
                            var anchor = document.createElement("a");
                            anchor.innerHTML = el.dictionary_label;
                            var callback = "ui.changeDictionary('" + listItem.id + "')";
                            anchor.setAttribute("onclick", callback);

                            listItem.appendChild(anchor);
                            dictionaryList.appendChild(listItem);
                        });

                        container.appendChild(dictionaryList);
                    },

                    getSelectedDictionary: function ()
                    {
                        // Return selected dictionary from list
                        var lis = document.getElementById("dictionary-list").getElementsByTagName("li");

                        for (var i = 0; i < lis.length; i++) {
                            if (lis[i].className === "selected") {
                                return lis[i].id;
                            }
                        }
                    },

                    buildDictionaryIdDropdown: function (dictionaryIdObjects, containerId)
                    {
                        var container = document.getElementById(containerId);

                        while (container.firstChild) {
                            // Remove a previous dictionary id list
                            container.removeChild(container.firstChild);
                        }

                        var dictionaryIdList = document.createElement("select");
                        dictionaryIdList.setAttribute("id", "dictionary-id-dropdown");
                        dictionaryIdList.setAttribute("class", "form-control");

                        // Loop through each dictionary id object and append the option to the dictionary-id-dropdown
                        Array.prototype.forEach.call(dictionaryIdObjects, function (el, i) {
                            var option = document.createElement("option");
                            option.text = ui.prettifyDictionaryName(el);
                            option.value = el;

                            dictionaryIdList.appendChild(option);
                        });

                        container.appendChild(dictionaryIdList);
                    },

                    getSelectedDictionaryIds: function (prettify)
                    {
                        // Get dictionary ids from dropdown selection. If ids are id_1, id_2,
                        // id_3 and id_2 is selected then an array of id_1 and id_2 are returned.
                        var element = document.getElementById("dictionary-id-dropdown");
                        var currentSelection = element.options[element.selectedIndex].value;
                        var ids = [];

                        for (var i = 0; i < element.options.length; i++) {
                            if (prettify)
                                ids[i] = element.options[i].text;
                            else
                                ids[i] = element.options[i].value;

                            if (currentSelection === element.options[i].value)
                                break;
                        }

                        return ids;
                    },

                    changeDictionary: function (selectedId) {
                        // Loop through dictionaries in list and update which is selected
                        var lis = document.getElementById("dictionary-list").getElementsByTagName("li");
                        for (var i = 0; i < lis.length; i++) {
                            if (lis[i].className === "selected") {
                                // Remove class selected from previously selected dictionary
                                lis[i].classList.remove("selected");
                            }

                            if (lis[i].id === selectedId) {
                                // Add class selected to currently selected dictionary
                                lis[i].setAttribute("class", "selected");
                            }
                        }

                        chain.updateSyncReportAfterChangeDictionaries();
                    },

                    attachFooterHeader: function (columnCount, containerId) {
                        // Add footer header, so column filter can be attached
                        var container = document.getElementById(containerId);

                        while (container.firstChild) {
                            // Remove a previous footer
                            container.removeChild(container.firstChild);
                        }

                        var footer = document.createElement("tfoot");
                        var tableRow = document.createElement("tr");
                        footer.appendChild(tableRow);

                        // Loop through each column and append a table header to the table row
                        for (var i = 0; i < columnCount; i++) {
                            var tableHeader = document.createElement("th");
                            //var t = document.createTextNode("th" + i);
                            //tableHeader.appendChild(t);

                            tableRow.appendChild(tableHeader);
                        }

                        container.appendChild(footer);
                    },

                    prettifyDictionaryName: function (dictionaryName) {
                        // Remove ID
                        //dictionaryName = dictionaryName.substr(2);
                        // Replace underscores with spaces
                        //dictionaryName = dictionaryName.replace(/_/g, ' ');
                        return dictionaryName;
                    },

                    showAlert: function (message, alertStyle) {
                        $("#alert").replaceWith("<div id='alert' class='" + alertStyle + " alert-margin-cspro'>" + message + "</div>");
                        $("#alert").show();
                    },

                    clearAlert: function () {
                        $("#alert").replaceWith("<div id='alert' class='alert-placeholder-cspro alert-margin-cspro'></div>");
                        $("#alert").show();
                    },

                    showImportAlert: function (message, alertStyle) {
                        $("#import-modal-alert").replaceWith("<div id='import-modal-alert' class='" + alertStyle + " alert-margin-cspro'>" + message + "</div>");
                        $("#import-modal-alert").show();
                    }
                }

        var dataTables =
                {
                    initSyncReport: function () {
                        $.fn.dataTable.ext.errMode = 'none';

                        if ($.fn.dataTable.isDataTable('#table-responsive')) {
                            // DataTable exists and number of columns may have changed
                            $('#table-responsive').DataTable().destroy();  // Destroy table
                            $('#table-responsive').empty();                // Remove all <thead>
                        }

                        var storeAreaNamesColumnCount = document.getElementById('store-area-names-column-count');
                        var areaNamesColumnCount = storeAreaNamesColumnCount.dataset.areaNamesColumnCount;
                        var selectedDictionary = ui.getSelectedDictionary();
                        var selectedDictionaryIds = ui.getSelectedDictionaryIds(true);
                        var columns = [];

                        Array.prototype.forEach.call(selectedDictionaryIds, function (el, i) {
                            columns.push({title: el, data: i});
                        });
                        columns.push({title: "TOTAL", data: "total_count"});                  

                        var columnCount = selectedDictionaryIds.length + 1;
                        ui.attachFooterHeader(columnCount, "table-responsive");

                        selectedDictionaryIds = ui.getSelectedDictionaryIds(false);

                        $('#table-responsive')
                                .on('xhr.dt', function (e, settings, json, xhr) {
                                })
                                .on('error.dt', function (e, settings, techNote, message) {
                                    var strLogin = '<title>CSWeb: Login</title>';
                                    if (settings && settings.jqXHR && settings.jqXHR.responseText && settings.jqXHR.responseText.includes(strLogin)) {
                                        // TODO: Hack to catch expired token
                                        window.location.href = "{{ path('logout') }}";
                                        return;
                                    }
                                    console.log('An error has been reported by DataTables: ', message);
                                })
                                .DataTable({
                                    serverSide: true,
                                    processing: true,
                                    searching: true,
                                    paging: true,
                                    pageLength: 10,
                                    order: [[0, "asc"]],
                                    columns: columns,
                                    ajax: {
                                        url: "{{ url('syncReportJson') }}",
                                        data: {
                                            areaNamesColumnCount: areaNamesColumnCount,
                                            dictionary: selectedDictionary,
                                            dictionaryIds: selectedDictionaryIds
                                        }
                                    },

                                    initComplete: function () {
                                        $('#table-responsive_wrapper')
                                                .find('div.row')
                                                .css({"margin-left": "0", "margin-right": "0"});
                                        
                                        filterLevels = [];
                                        drawFilters(this, selectedDictionary);
                                        
                                        // Create column filter dropdown
                                        /*
                                        this.api().columns().every(function () {
                                            var column = this;
                                            var select = $('<select><option value=""></option></select>')
                                                    .appendTo($(column.footer()).empty())
                                                    .on('change', function () {
                                                        var val = $.fn.dataTable.util.escapeRegex(
                                                                $(this).val()
                                                                );

                                                        column
                                                                .search(val, false, false)
                                                                .draw();
                                                    });
                                            column.data().unique().sort().each(function (value, index) {
                                                select.append('<option value="' + value + '">' + value + '</option>');
                                            });
                                        });
                                         */
                                    },
                                            
                                    drawCallback: function(){
                                        renderCaseViewButtons(this, selectedDictionary);
                                    }
                                },
                            )
                            .on('draw', function(){
                                
                            });
                    }
                }

                function drawFilters(context, selectedDictionary) {
                    var params = new URLSearchParams();
                    params.append('dictionary', selectedDictionary);

                    var i = 0;
                    filterLevels.forEach(function(id) {
                        params.append(`ids[${i++}]`, id);
                    });

                    $.ajax({
                        type: "GET",
                        url: "{{ url('report-filter-dictionary-ids-json') }}",
                        data: params.toString()
                    }).done(function(msg){
                        context.api().columns().every(function () {
                            var column = this;
                            if (column.index() >= context.api().columns(':visible').nodes().length - 1){
                                return;
                            }
                            
                            if (column.index() === filterLevels.length){
                                var select = $('<select class="form-control"><option value=""></option></select>')
                                        .appendTo($(column.footer()).empty())
                                        .on('change', function () {
                                            var val = $.fn.dataTable.util.escapeRegex(
                                                    $(this).val()
                                                    );
                                            
                                            //removing all lower level filters
                                            while (filterLevels.length > column.index()) {
                                                filterLevels.pop();
                                                context.api().column(filterLevels.length)
                                                    .search("", false, false);
                                            }
                                            
                                            column
                                                    .search(val, false, false)
                                                    .draw();
                                            
                                            if (val.length > 0){
                                                filterLevels.push(val);
                                            }
                                            drawFilters(context, selectedDictionary);
                                        });

                                var msgJson = JSON.parse(msg);
                                var primaryCols = msgJson["firstLevel"];
                                primaryCols.forEach((col) => {
                                    select.append('<option value="' + col.id + '">' + col.label + '</option>');
                                });
                            } else if (column.index() > filterLevels.length){
                                $(column.footer()).empty();
                            }
                        });
                    });
                }
                
                function renderCaseViewButtons(context, selectedDictionary) {
                    var colCount = context.api().columns().count() - 1;
                    var dictIdCount = $('#dictionary-id-dropdown').children().length;
                    var rIndex = 0;
                    $('#table-responsive')
                        .find('tbody')
                        .children()
                        .each(function() {
                            var lastChild = $(this).children().last();
                            if (parseInt(lastChild.html()) === 1 || colCount === dictIdCount) {
                                $(`<a href="#" rowIndex="${rIndex}" style="float:right;">View case</a>`)
                                    .appendTo(lastChild)
                                    .click(function() {
                                        var rowIndex = parseInt($(this).attr('rowIndex'));
                                        
                                        //handing duplicate cases
                                        if (parseInt(lastChild.html()) > 1)
                                            buildMultipleCasePopup(context, selectedDictionary, colCount, rowIndex)
                                        else
                                            getCase(context, selectedDictionary, colCount, rowIndex);
                                    });
                            }
                            rIndex++;
                        });
                }
                
                function buildMultipleCasePopup(context, selectedDictionary, colCount, rowIndex){
                    var params = new URLSearchParams();
                    params.append('dictionary', selectedDictionary);    

                    var j = 0;
                    for (var i = colCount; i < colCount * 2; i++) {
                        params.append(`ids[${j++}]`, context.api().rows().data()[rowIndex][i]);
                    }
                    
                    $("body").addClass("loading");
                    $.ajax({
                        type: "GET",
                        url: "{{ url('report-get-dupl-case-guids-json') }}",
                        data: params.toString()
                    }).done(function(msg){
                        var caseList = $('<div class="list-group"></div>')
                            .appendTo($('#multipleCaseViewSelectModalBody').empty());
                        
                        var msgJson = JSON.parse(msg);
                        
                        var caseIdx = 0;
                        msgJson.forEach((caseId) => {
                            var lItem = $(`<a href="#" class="list-group-item" style="border:0;"></a>`)
                                .append(`<h4 style="color:#337AB7;">• Case #${++caseIdx}</h4>`)
                                .append(`<div style="padding-left: 12px;" value="${caseId["case-id"]}">Globaly unique ID: ${caseId["case-id"]}</div>`)
                                .click(function(){
                                    $('#multipleCaseViewSelectModal').modal("hide");
                                    var caseGuid = $(this).find('div').attr('value');
                                    getCaseByGuid(selectedDictionary, caseGuid);
                                });
                            
                            caseList.append(lItem);
                        });
                        
                        $("body").removeClass("loading");
                        $('#multipleCaseViewSelectModal').modal("show");
                    });
                }
                
                function getCase(context, selectedDictionary, colCount, rowIndex){
                    var params = new URLSearchParams();
                    params.append('dictionary', selectedDictionary);    

                    var j = 0;
                    for (var i = colCount; i < colCount * 2; i++) {
                        params.append(`ids[${j++}]`, context.api().rows().data()[rowIndex][i]);
                    }

                    $("body").addClass("loading");
                    $.ajax({
                        type: "GET",
                        url: "{{ url('report-view-case-json') }}",
                        data: params.toString()
                    }).done((showModal));
                }
                
                function getCaseByGuid(selectedDictionary, caseGuid) {
                    var params = new URLSearchParams();
                    params.append('dictionary', selectedDictionary);
                    params.append('caseguid', caseGuid);
                    $("body").addClass("loading");
                    $.ajax({
                        type: "GET",
                        url: "{{ url('report-view-case-json') }}",
                        data: params.toString()
                    }).done((showModal));
                }
                
                function showModal(data)
                {
                    var modalBody = document.getElementById("pointInfoModalBody");
                    modalBody.childNodes.forEach((child) => {
                        modalBody.removeChild(child);
                    });
                    modalBody.innerHTML = data;
                    $("body").removeClass("loading");
                    $("#pointInfoModal").modal("show");
                }
    </script>
{% endblock %}