<html xmlns="http://www.w3.org/1999/xhtml"
      metal:use-macro="here/main_template/macros/master"
      i18n:domain="senaite.core">

  <metal:content-title fill-slot="content-title">
    <a href=""
       style="float:right;"
       i18n:translate=""
       tal:attributes="href string:${portal_url}?redirect_to=frontpage">
      Switch to frontpage
    </a>
    <h1 class="documentFirstHeading" i18n:translate="">System Dashboard</h1>
  </metal:content-title>

  <a style="float:right;" href="#" i18n:translate="">Switch to Frontpage</a>

  <metal:content-description fill-slot="content-description">
  </metal:content-description>

  <metal:content-core fill-slot="content-core">
    <style>
     .dashboard-section {
       padding: 0 0 20px;
     }
     .dashboard-section-head {
       border-bottom: 1px dotted #dfdfdf;
       margin: 0 0 10px;
     }
     .dashboard-section-head div.actions {
       float:right;
       text-align:right;
     }
     .dashboard-section-head div.actions select {
       padding: 0 5px;
       vertical-align: top;
     }
     .dashboard-section-head:after {
       clear: both;
       content: " ";
       display: block;
       font-size: 0;
       height: 0;
       visibility: hidden;
     }
     .dashboard-section h2 {
       float: left;
       font-size: 1.3em;
       font-weight: bold;
       letter-spacing: 0;
       padding: 5px 0 4px;
       width: 70%;
     }
     .dashboard-section .h2-legend {
       font-size: 0.9em;
       padding: 0 0 10px 2px;
     }
     .dashboard-panels {
     }
     .dashboard-info-panel-wrapper {
       float: left;
       margin-right: 1em;
     }
     .dashboard-info-panel {
     }
     #content .dashboard-info-panel-wrapper a {
       color:#333;
       text-decoration:none;
     }
     #content .dashboard-info-panel-wrapper a:hover div {
       opacity:0.8;
       filter:alpha(opacity=80);
       -webkit-transition: opacity 250ms ease-in-out;
       -moz-transition: opacity 250ms ease-in-out;
       -o-transition: opacity 250ms ease-in-out;
       -ms-transition: opacity 250ms ease-in-out;
       transition: opacity 250ms ease-in-out
     }
     .dashboard-info-panel-number {
       float: left;
       font-size: 2em;
       font-weight: normal;
       line-height: 1em;
       padding: 0px 4px 0 10px;
       text-align: left;
       color: #3b8686;
     }
     #content .dashboard-info-panel-wrapper {
       opacity:0.4;
       filter:alpha(opacity=40);
     }
     #content .dashboard-info-panel-wrapper.highlight {
       opacity:1;
       filter:alpha(opacity=100);
     }
     #content .dashboard-info-panel-wrapper.highlight .dashboard-info-panel-number {
       color:#ff7f0e;
       color:#79bd9a;
     }

     .dashboard-section .period-informative {
       color: #666;
       font-size: 0.85em;
       padding: 10px;
     }
     .dashboard-info-panel-description {
       background-color: #dfdfdf;
       clear: both;
       font-size: 0.85em;
       font-weight: normal;
       padding: 1em;
     }
     .dashboard-info-panel-total {
       color: #666;
       float: left;
       font-size: 0.85em;
       font-weight: normal;
       padding: 5px 0 0 10px;
       text-align: left;
       vertical-align: bottom;
     }
     #content ul.dashboard-time-selector {
       list-style:none;
       margin: 10px 0 10px -5px;
       padding:0;
     }
     #content ul.dashboard-time-selector li {
       display:inline;
     }
     #content ul.dashboard-time-selector li a {
       background-color: #efefef;
       border-radius: 5px;
       margin: 0 5px;
       padding: 4px 10px;
       color:#333;
     }
     #content ul.dashboard-time-selector li.selected a {
       background-color: #dcdcdc;
     }
     .clearfix {
       clear: both;
     }
     .bar-chart {
       width:100%;
       min-width:640px;
     }
     .bar-chart-period {
       clear: both;
       padding: 1px 0 0 15px;
     }
     .bar-chart .axis path,
     .bar-chart .axis line {
       fill: none;
       stroke: #aaa;
       shape-rendering: crispEdges;
     }
     .bar-chart .y.axis line {
       stroke: #ddd;
     }
     .bar-chart .axis text {
       fill:#777;
     }
     .bar-chart .bar {
       fill: steelblue;
     }
     .bar-chart g.legend {
       font-size: 0.8em;
     }
     .bar-chart .x.axis {
       font-size: 0.75em;
     }
     .bar-chart .y.axis {
       font-size: 0.75em;
     }
     .bar-chart .graph-text-bar {
       border:1px solid red;
       background-color:red;
     }
     div.dashboard-period {
       padding:10px;
       font-size:1.2em;
     }
     .toggle-barchart {
       text-align: left;
       padding: 0 0 10px;
     }
     .toggle-barchart a {
       padding: 0;
     }
     .bar-chart-no-data {
       color: #b22222;
       font-size: 0.9em;
       padding: 20px;
     }
     div.roles-visibility {
       align-self: right;
       background-color: #e3e3e3;
       border: 1px solid #cdcdcd;
       border-radius: 0 0 5px 5px;
       padding: 5px;
       position: absolute;
       text-align: left;
       z-index: 10;
     }
     div.roles-visibility div.checkbox label {
       font-weight:normal;
     }
     a.dashboard-visibility-link {
       margin-right:10px;
     }
     /* a.dashboard-visibility-link:after {
        content: " ▼";
        } */
     .dashboard-info-panel-vertbar {
       height:2em;
       float:left;
     }
     .vertbar-remaining, .vertbar-done {
       width:4px;
     }
     .vertbar-done {
       background-color: #A8DBA8;
     }
     .vertbar-remaining {
       background-color:#efefef;
       border-radius: 2px 2px 0 0;
     }
    </style>
    <script>
     document.addEventListener("DOMContentLoaded", () => {
       loadBarCharts();
       dashboard_cookie_controller();
       role_permission_input_controller();
       load_roles_visibility_links();

       function loadBarCharts() {
         $('.bar-chart').each(function(e){
           var id = $(this).attr('id');
           var vis = bika.lims.SiteView.readCookie('visible.'+id);
           if (vis == 1) {
             $('#'+id).show();
             $('#'+id+"-period").show();
             $('#'+id).closest('div.dashboard-panels').find('.dashboard-info-panel-wrapper').hide();
             $('#'+id).addClass('loaded');
             loadBarChart(id);
           }
         });

         $('div.toggle-barchart a').click(function(e) {
           e.preventDefault();
           var barchartid = $(this).attr('target-id');
           if ($('#'+barchartid).is(":visible")) {
             bika.lims.SiteView.setCookie('visible.'+barchartid, 0);
             $('#'+barchartid+'-period').hide();
             $('#'+barchartid).hide();
             $('#'+barchartid).closest('div.dashboard-panels').find('.dashboard-info-panel-wrapper').show();
           } else {
             bika.lims.SiteView.setCookie('visible.'+barchartid, 1);
             $('#'+barchartid+'-period').show();
             $('#'+barchartid).show();
             $('#'+barchartid).closest('div.dashboard-panels').find('.dashboard-info-panel-wrapper').hide();
             loadBarChart(barchartid);
             /*    if (!$('#'+barchartid).hasClass('loaded')) {
                loadBarChart(barchartid);
                $('#'+barchartid).addClass('loaded');
                }*/
           }
         });
       }

       function loadBarChart(id) {
         var container = $('#'+id);
         $(container).find('svg').remove();
         var raw_data = JSON.parse($(container).attr('data'));
         var data = raw_data.data;
         if (data.length == 0 || Object.keys(data[0]).length < 2) {
           return;
         }
         // All available states come sorted from by quantity descending, but we
         // only want those for which there is at least one entry in data
         var states = raw_data.states;
         states = states.filter(function(key) { return key in data[0] });

         $(container).html("");
         var margin = {top: 10, right: 200, bottom: 50, left: 50},
             width = $(container).innerWidth() - margin.left - margin.right,
             height = 200 - margin.top - margin.bottom;

         var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
         var y = d3.scale.linear().range([height, 0]);
         colors = JSON.parse($(container).attr('data-colors'));
         var color = d3.scale.ordinal().range(colors);
         color.domain(states);

         var xAxis = d3.svg.axis()
                       .scale(x)
                       .orient("bottom")
                       .ticks(10);
         var yAxis = d3.svg.axis()
                       .scale(y)
                       .orient("left")
                       .tickSize(-width, 0, 0)
                       .tickFormat(d3.format(".2s"));

         var svg = d3.select("#"+id).append("svg")
                     .attr("width", width + margin.left + margin.right)
                     .attr("height", height + margin.top + margin.bottom)
                     .append("g")
                     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

         data.forEach(function(d) {
           var y0=0;
           d.statuses=color.domain().map(function(name) {
             return {name: name, y0: y0, y1:y0 += +d[name]};
           });
           d.total = d.statuses[d.statuses.length - 1].y1;
         });

         x.domain(data.map(function(d) { return d.date;}));
         y.domain([0, d3.max(data, function(d) { return d.total; })]);

         svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis)
            .selectAll("text")
            .style("text-anchor", "end")
            .style("font-size", "9px")
            .attr("dx", "-.8em")
            .attr("dy", "-.55em")
            .attr("transform", "rotate(-90)" );

         svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);

         var state = svg.selectAll(".state")
                        .data(data)
                        .enter()
                        .append("g")
                        .attr("class", "g")
                        .attr("transform", function(d) { return "translate(" + x(d.date) + ",0)"; });

         state.selectAll("rect")
              .data(function(d) { return d.statuses; })
              .enter()
              .append("rect")
              .attr("width", x.rangeBand())
              .attr("y", function(d) { return y(d.y1); })
              .attr("height", function(d) { return y(d.y0) - y(d.y1); })
              .attr("data-date",function(d) { return d.x; })
              .attr("data-value", function(d) { return d.y1-d.y0; })
              .attr("data-name", function(d) { return d.name; })
              .style("fill", function(d) { return colors[d.name]; })
              .on("mouseout", function() {
                d3.select(this.parentNode.children[this.parentNode.children.length-1])
                  .remove();
              })
              .on("mouseover",  function() {
                var date = d3.select(this).attr('data-date');
                var name = d3.select(this).attr('data-name');
                var val = name+": "+d3.select(this).attr('data-value');
                var y = d3.select(this).attr('y');
                var x = d3.select(this).attr('x');
                d3.select(this.parentNode)
                  .append("text")
                  .attr("fill", "#333")
                  .style("font-size", "10px")
                  .style("font-weight", "bold")
                  .attr("x", x)
                  .attr("y", 0)
                  .attr("class", "graph-text-bar")
                  .text(val);
              });

         var legend = svg.selectAll(".legend")
                         .data(states.slice().reverse())
                         .enter().append("g")
                         .attr("class", "legend")
                         .attr("transform", function(d, i) {
                           return "translate(0," + i * 12 + ")";
                         });

         legend.append("rect")
               .attr("x", width + 15)
               .attr("width", 6)
               .attr("height", 6)
               .style("fill", function(d) { return colors[d]; });

         legend.append("text")
               .attr("x", width + 30)
               .attr("y", 0)
               .attr("dy", "6")
               .text(function(d) { return d; })
       }

       function load_roles_visibility_links() {
         $('a.dashboard-visibility-link').click(function(e){
           e.preventDefault();
           var parent = $(this).closest('div.dashboard-section');
           var panel = $(parent).find('div.roles-visibility');
           if ($(panel).is(':visible')) {
             $(panel).hide();
           } else {
             $(panel).show();
           }
         });
       }
       function dashboard_cookie_controller() {
         /* Links a linker controller to each dashboard filter selector.
            This controller reads the cookie data once the selector has been
            modified and updates its data.
          */
         var selector;
         var selector_section_id;
         var cookie;
         var counter;
         var cookie_id = 'dashboard_filter_cookie'
         var filter_selectors = $('select.dashboard_filters');
         for(counter = 0; counter < filter_selectors.length; counter++){
           selector = filter_selectors[counter];
           $(selector).live('change', function(){
             section_id = $(this).attr('section_id');
             selected = $(this).find(':selected').val();
             cookie_data = render_cookie_data(bika.lims.SiteView.readCookie(cookie_id));
             cookie_data[section_id] = selected;
             cookie_data = build_cookie_data(cookie_data);
             bika.lims.SiteView.setCookie('dashboard_filter_cookie', cookie_data);
             window.location.reload(true);
           });
         }
       };
       function render_cookie_data(data){
         return JSON.parse(data);
       };
       function build_cookie_data(data){
         return JSON.stringify(data);
       };
       function role_permission_input_controller() {
         /* Ajax post to update registry values */
         var section_id, role, chk_val;
         var role_checks = $('div.roles-visibility input[type="checkbox"]');
         for(counter = 0; counter < role_checks.length; counter++){
           selector = role_checks[counter];
           $(selector).live('change', function(){
             section_id = $(this).attr('section_id');
             role = $(this).attr('role_id');
             chk_val = $(this).is(':checked');
             // AJAX post
             $.ajax({
               dataType: 'json',
               async: false,
               type: 'POST',
               url: 'dashboard_view_permissions_update',
               data: {
                 'section_name': section_id,
                 'role_id': role,
                 'check_state': chk_val,
                 '_authenticator': $('input[name=\'_authenticator\']').val()
               }
             });
           });
         }
       }
     });
    </script>

    <tal:section repeat="section python:view.get_sections()">
      <div class='dashboard-section' tal:define="section_id section/id">
        <div class='dashboard-section-head'>
          <h2 tal:content="section/title" class='dashboard-section-title'></h2>
          <div class="actions" tal:condition="python:False">
            <!-- Disabled, because dysfunctional -->

            <!-- View permissions section -->
            <tal:roles_visibility_settings condition="python:view.is_admin_user()">
              <a class="dashboard-visibility-link" href="#">
                <span tal:omit-tag="" i18n:translate="">Visibility</span>
                <i class="fas fa-caret-down"></i>
              </a>
              <div class="roles-visibility" style="display:none">
                <tal:role-permission-block
                  repeat="role_value_pair python:view.get_dashboard_panels_visibility(section_id)">
                  <div class="checkbox">
                    <label>
                      <input type="checkbox" value=""
                             tal:attributes="
                                   checked python: role_value_pair[1] == 'yes';
                                   role_id python: role_value_pair[0];
                                   section_id section_id;
                                   disabled python: role_value_pair[0] in ['LabManager', 'Manager'];">
                      <span tal:omit-tag=""
                            tal:content="python: role_value_pair[0]"></span>
                    </label>
                  </div>
                </tal:role-permission-block>
              </div>
            </tal:roles_visibility_settings>

            <!-- Mine/All filter -->
            <select class="dashboard_filters"
                    tal:attributes="section_id section/id"
                    tal:define="section_id section/id">
              <tal:dashboard_filter_opts
                define="options python: view.get_filter_options()"
                repeat="option options">
                <option
                  tal:attributes="value python:option;
                                  selected python: 'selected' if view.is_filter_selected(section_id, option) else '';"
                  tal:content="python:options.getValue(option)">
                </option>
              </tal:dashboard_filter_opts>
            </select>
          </div>
        </div>
        <div class='dashboard-panels'>

          <!-- Bar-chart panels -->
          <tal:barchart_panels repeat="panel python:[p for p in section.get('panels',[]) if p.get('type','')=='bar-chart-panel']">
            <div tal:attributes="class python:'dashboard-bargraph-panel-wrapper %s' % panel.get('class', '');"
                 tal:define='itemnum repeat/panel/number;'>
              <div class="toggle-barchart" tal:condition="python:panel.get('data','[]')!='[]'">
                <a tal:attributes='target-id python:"bar-chart-%s-%s" % (section["id"],itemnum);'
                   href="#" i18n:translate="">Show/hide timeline summary</a>
              </div>
              <div class='bar-chart-period' tal:attributes='id python:"bar-chart-%s-%s-period" % (section["id"],itemnum)' style="display:none;">
                <h3 tal:content="python:panel.get('name', '')"></h3>
                <div class='h2-legend'>
                  <span i18n:translate="">From</span>&nbsp;
                  <span tal:content="python:plone_view.toLocalizedTime(view.date_from)"></span>
                  &nbsp;<span i18n:translate="">to</span>&nbsp;
                  <span tal:content="python:plone_view.toLocalizedTime(view.date_to)"></span>
                  (<span i18n:translate="">updated every 2 hours</span>)
                </div>
                <ul class='dashboard-time-selector'>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'd' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=d' i18n:translate="">Daily</a></li>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'w' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=w' i18n:translate="">Weekly</a></li>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'm' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=m' i18n:translate="">Monthly</a></li>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'q' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=q' i18n:translate="">Quarterly</a></li>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'b' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=b' i18n:translate="">Biannual</a></li>
                  <li tal:attributes="class python:'selected' if view.periodicity == 'y' else ''"><a tal:attributes='href string:${view/portal_url}/senaite-dashboard?p=y' i18n:translate="">Yearly</a></li>
                </ul>
              </div>
              <div class='bar-chart'
                   tal:attributes='id python:"bar-chart-%s-%s" % (section["id"],itemnum);
                          data panel/data;
                          data-colors panel/datacolors;'
                   style='display:none'>
                <div class="bar-chart-no-data" i18n:translate="">There is no available data for the selected period</div>
              </div>
            </div>
          </tal:barchart_panels>

          <!-- Simple panels -->
          <tal:simple_panels repeat="panel python:[p for p in section.get('panels',[]) if p.get('type','')=='simple-panel']">
            <div style="min-width: 12em;"
                 tal:define="num panel/number;
                        numclass python:'' if num==0 else 'highlight';"
                 tal:attributes="class python:'card my-2 dashboard-info-panel-wrapper %s %s' % (panel.get('class', ''), numclass);">
              <a tal:attributes="href panel/link">
                <div class='dashboard-info-panel'>
                  <div class="dashboard-info-panel-vertbar">
                    <div class="vertbar-remaining"
                         tal:attributes="style python:'height: {}%'.format(100 - panel.get('percentage', 0))"></div>
                    <div class="vertbar-done"
                         tal:attributes="style python:'height: {}%'.format(panel.get('percentage', 0))"></div>
                  </div>
                  <div tal:content="panel/number" class='dashboard-info-panel-number'></div>
                  <div tal:content="panel/legend" class='dashboard-info-panel-total' tal:condition="python:panel.get('legend','')"></div>
                  <div tal:content="panel/description" class='dashboard-info-panel-description'></div>
                </div>
              </a>
            </div>
          </tal:simple_panels>
          <div class='clearfix'></div>
        </div>
      </div>
    </tal:section>
    <input tal:replace="structure context/@@authenticator/authenticator"/>
  </metal:content-core>
</html>
