From 5eaac808d5e3f39e223f4268f3a1d98f55393210 Mon Sep 17 00:00:00 2001 From: Le Duy Tung Date: Sat, 23 May 2026 22:12:36 +0700 Subject: [PATCH 1/3] Update field name and hover question mark update --- app/views/kanaui/reports/_form.html.erb | 14 ++++---------- config/locales/en.bootstrap.yml | 4 ++-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/app/views/kanaui/reports/_form.html.erb b/app/views/kanaui/reports/_form.html.erb index d7ecce7..d212f32 100644 --- a/app/views/kanaui/reports/_form.html.erb +++ b/app/views/kanaui/reports/_form.html.erb @@ -128,13 +128,7 @@ } document.querySelectorAll('[data-kanaui-tooltip]').forEach(function (el) { - el.addEventListener('click', function (event) { - event.stopPropagation(); - if (activeTooltipTrigger === el && tooltip.classList.contains('is-visible')) { - hideTooltip(); - return; - } - + el.addEventListener('mouseenter', function () { var rect = el.getBoundingClientRect(); var left = window.pageXOffset + rect.right + 12; var top = window.pageYOffset + rect.top - 2; @@ -153,10 +147,10 @@ tooltip.classList.add('is-flipped'); } }); - }); - document.addEventListener('click', function () { - hideTooltip(); + el.addEventListener('mouseleave', function () { + hideTooltip(); + }); }); document.addEventListener('keydown', function (event) { diff --git a/config/locales/en.bootstrap.yml b/config/locales/en.bootstrap.yml index 37f976c..794dec8 100644 --- a/config/locales/en.bootstrap.yml +++ b/config/locales/en.bootstrap.yml @@ -37,7 +37,7 @@ en: source_query: "SQL Query" source_query_help: "Don't add a trailing ;" source_configuration_error: "Either Source Table Name or SQL Query is required." - source_name: "Source Name" + source_name: "Remote Database Name" source_name_help: "Must match a database configuration entry in the Analytics plugin" tooltips: report_name: "Unique identifier for your report." @@ -59,7 +59,7 @@ en: pretty_name: "Pretty Name" type: "Type" source: "Source" - source_name: "Source Name" + source_name: "Remote Database Name" source_query: "Source Query" refresh_procedure: "Refresh Procedure" refresh_frequency: "Refresh Frequency" From 48bbc577e7958c5b612f46627d67a8099bf0440f Mon Sep 17 00:00:00 2001 From: Le Duy Tung Date: Sun, 24 May 2026 22:44:57 +0700 Subject: [PATCH 2/3] Improve the graph --- .../kanaui/kiddo/charts/line_chart.js | 28 +++--- .../kanaui/kiddo/charts/utils/mouse_over.js | 31 ++++--- app/assets/javascripts/kanaui/kiddo/helper.js | 47 ++++++++-- .../javascripts/kanaui/kiddo/settings.js | 1 + app/assets/stylesheets/kanaui/kanaui.css | 90 ++++++++++++++++--- app/views/kanaui/dashboard/index.html.erb | 42 +++++++-- 6 files changed, 184 insertions(+), 55 deletions(-) diff --git a/app/assets/javascripts/kanaui/kiddo/charts/line_chart.js b/app/assets/javascripts/kanaui/kiddo/charts/line_chart.js index 42231e8..c03dbe5 100644 --- a/app/assets/javascripts/kanaui/kiddo/charts/line_chart.js +++ b/app/assets/javascripts/kanaui/kiddo/charts/line_chart.js @@ -68,26 +68,24 @@ return dataset.name; })); - // Create legend container at the top + // Create legend container to the right of the chart area var legendContainer = svg .append("g") .attr("class", "chart-legend") - .attr("transform", "translate(" + (self.width - 100) + ", -25)"); + .attr("transform", "translate(" + (self.width + self.margin_left + 15) + ", 10)"); // Calculate total values for legend var legendData = datasets.map(function (dataset, index) { var latestValue = dataset.values[dataset.values.length - 1]; - var totalCount = dataset.values.length; return { name: dataset.name, value: latestValue ? latestValue.y : 0, - count: totalCount, color: self.color(dataset.name), index: index, }; }); - // Create legend items + // Create legend items as a vertical column var legendItems = legendContainer .selectAll(".legend-item") .data(legendData) @@ -95,34 +93,30 @@ .append("g") .attr("class", "legend-item"); - var xOffset = 0; - legendItems.each(function (d, i) { + var yOffset = 0; + legendItems.each(function (d) { var legendItem = d3.select(this); - // Add colored circle legendItem .append("circle") - .attr("cx", xOffset + 6) - .attr("cy", 0) + .attr("cx", 6) + .attr("cy", yOffset) .attr("r", 6) .style("fill", d.color); - // Add text label var labelText = - helper.formatSeriesName(d.name) + " (" + d.count + "): " + d3.format(",.2f")(d.value); + helper.formatSeriesName(d.name, self.reportName) + ": " + helper.formatValue(d.value); legendItem .append("text") - .attr("x", xOffset + 18) - .attr("y", 0) + .attr("x", 18) + .attr("y", yOffset) .attr("dy", "0.35em") .style("font-size", "0.875rem") .style("font-weight", "500") .style("fill", "#6B7280") .text(labelText); - // Calculate width for next item - var textWidth = this.getBBox().width; - xOffset += textWidth + 40; // Add spacing between items + yOffset += 22; }); // Render data lines diff --git a/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js b/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js index 30df0e4..f7ded7a 100644 --- a/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js +++ b/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js @@ -59,15 +59,16 @@ var infoBox = info.node().getBBox(); var infoTitleBox = infoTitle.node().getBBox(); var margin = 40; + var minWidth = Math.max(box.width, infoTitleBox.width) + margin; info.attr("height", infoBox.height + box.height + 7); - if (infoBox.width < box.width) { - info.attr("width", box.width + margin); - infoTitleBg.attr("width", box.width + margin); + if (infoBox.width < minWidth) { + info.attr("width", minWidth); + infoTitleBg.attr("width", minWidth); $("#mouseover_canvas #info-title").attr( "dx", - (box.width + margin) / 2 - infoTitleBox.width / 2 + minWidth / 2 - infoTitleBox.width / 2 ); } }; @@ -81,7 +82,9 @@ }); function mousemove(event) { - var mouseX = d3.pointer(event, this)[0]; + var pointer = d3.pointer(event, this); + var mouseX = pointer[0]; + var mouseY = pointer[1]; $("#mouseover_canvas .chart_values").detach().remove(); $("#mouseover_canvas .chart_circles").detach().remove(); @@ -115,11 +118,7 @@ .attr("cy", y(d.y)) .style("fill", self.color(name)); - var canvasPosition = x(x0) > self.width / 2 ? 50 : self.width / 2; - - canvas.attr("transform", "translate(" + canvasPosition + ",0)"); - - canvas.select("#info-title").text(d.date); + canvas.select("#info-title").text(helper.formatDate(d.date)); elementsForLegend.push({ element: element, d: d }); }); @@ -150,11 +149,21 @@ .text( element.d === undefined ? element.element.name - : helper.formatValueDisplay(element.element.name, element.d) + : helper.formatValueDisplay(element.element.name, element.d, self.reportName) ); addInfoDimensions(text); }); + + // Position tooltip to follow the cursor; flip left when near the right edge + var tooltipOffset = 15; + var tooltipWidth = info.node().getBBox().width; + var tooltipHeight = info.node().getBBox().height; + var canvasX = (mouseX + tooltipOffset + tooltipWidth > self.width) + ? mouseX - tooltipWidth - tooltipOffset + : mouseX + tooltipOffset; + var canvasY = Math.max(0, mouseY - 150); + canvas.attr("transform", "translate(" + canvasX + "," + canvasY + ")"); } }, }; diff --git a/app/assets/javascripts/kanaui/kiddo/helper.js b/app/assets/javascripts/kanaui/kiddo/helper.js index 8a38332..3d62d90 100644 --- a/app/assets/javascripts/kanaui/kiddo/helper.js +++ b/app/assets/javascripts/kanaui/kiddo/helper.js @@ -1,9 +1,11 @@ (function (Kiddo, d3) { Kiddo.Helper = function () { + var formatValue = function (d) { + return d % 1 === 0 ? d3.format(",d")(d) : d3.format(",.2f")(d); + }; var formatCurrency = function (d) { return "$" + formatValue(d); }; - var formatValue = d3.format(",.2f"); var humanizeSegment = function (segment) { segment = String(segment || "") @@ -30,33 +32,64 @@ .join(" "); }; - var formatSeriesName = function (name) { + var formatSeriesName = function (name, reportName) { return String(name || "") .split(/\s*::\s*/) + .filter(function (segment) { + // Remove numeric-only segments (tenant record id) + return !/^\d+$/.test(segment.trim()); + }) .map(function (segment) { var parts = segment.split(/\s*:\s*/); if (parts.length > 1) { - return humanizeSegment(parts[0]) + " (" + humanizeSegment(parts.slice(1).join(": ")) + ")"; + var label = (reportName && parts[0].trim().toLowerCase() === "count") + ? reportName + : humanizeSegment(parts[0]); + return label + " (" + humanizeSegment(parts.slice(1).join(": ")) + ")"; } - return humanizeSegment(segment); }) .filter(function (segment) { return segment.length > 0; }) - .join(" / "); + .join(" : "); + }; + + // Extracts just the qualifier part (e.g. "EUR" from "count: EUR :: 1") for compact tooltip labels + var formatSeriesLabel = function (name) { + var segments = String(name || "") + .split(/\s*::\s*/) + .filter(function (segment) { + return !/^\d+$/.test(segment.trim()); + }); + + if (segments.length === 0) return humanizeSegment(name); + + var parts = segments[0].split(/\s*:\s*/); + if (parts.length > 1) { + return humanizeSegment(parts.slice(1).join(": ")); + } + return humanizeSegment(segments[0]); + }; + + var parseDateFn = d3.timeParse("%Y-%m-%d"); + var formatDateFn = d3.timeFormat("%b %d, %Y"); + var formatDate = function (dateStr) { + var parsed = parseDateFn(dateStr); + return parsed ? formatDateFn(parsed) : dateStr; }; return { - parseDate: d3.timeParse("%Y-%m-%d"), + parseDate: parseDateFn, bisectDate: d3.bisector(function (d) { return d.x; }).left, formatCurrency: formatCurrency, formatValue: formatValue, formatSeriesName: formatSeriesName, + formatDate: formatDate, formatValueDisplay: function (name, d) { - return formatSeriesName(name) + ": " + formatValue(d.y); // Add currency boolean on backend later -- formatCurrency(d.y); } + return formatSeriesLabel(name) + ": " + formatValue(d.y); }, }; }; diff --git a/app/assets/javascripts/kanaui/kiddo/settings.js b/app/assets/javascripts/kanaui/kiddo/settings.js index c061ee1..15eddd6 100644 --- a/app/assets/javascripts/kanaui/kiddo/settings.js +++ b/app/assets/javascripts/kanaui/kiddo/settings.js @@ -19,6 +19,7 @@ raw_height: raw_height, width: raw_width - margin_left - margin_right, height: raw_height - margin_top - margin_bottom, + reportName: $("#chartAnchor").data("report-name") || "", }; }; })((window.Kiddo = window.Kiddo || {}), d3); diff --git a/app/assets/stylesheets/kanaui/kanaui.css b/app/assets/stylesheets/kanaui/kanaui.css index daf1344..d62e96e 100644 --- a/app/assets/stylesheets/kanaui/kanaui.css +++ b/app/assets/stylesheets/kanaui/kanaui.css @@ -103,11 +103,40 @@ .kenui-analytics-dashboard-index .well ul { list-style-type: none; - margin-top: 0.625rem; + margin: 0.625rem 0 0; background: #fafafa; - width: fit-content; - padding: 0.625rem; + width: 100%; + padding: 1rem 1.25rem; border-radius: 0.5rem; + display: flex; + flex-wrap: wrap; + gap: 0.5rem 1.25rem; + align-items: flex-start; +} + +/* Smoothing option links (Weekly/Monthly average/sum) render as inline pills */ +.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) { + display: inline-flex; +} + +.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) > a { + display: inline-flex; + align-items: center; + background: #ffffff; + border: 0.0625rem solid #d5d7da; + border-radius: 999px; + padding: 0.375rem 0.75rem; + text-decoration: none; + color: #414651; + font-weight: 500; + font-size: 0.8125rem; + line-height: 1.25rem; + transition: all 0.15s ease-in-out; +} + +.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) > a:hover { + border-color: #1570ef; + color: #1570ef; } .kenui-analytics-dashboard-index .well ul li a { @@ -168,6 +197,26 @@ background: #ffffff; } +.kenui-analytics-dashboard-index .chart-title-container { + width: auto; + height: auto; + display: block; + justify-content: unset; + align-items: unset; + position: static; + margin-top: 15px; +} + +.kenui-analytics-dashboard-index .chart-title { + font-weight: 600; + font-size: 1.25rem; + line-height: 1.75rem; + color: #111827; + white-space: normal; + transform: none; + text-align: left; +} + .kenui-analytics-dashboard-index #chartAnchor svg { background: #ffffff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; @@ -619,20 +668,32 @@ .kenui-analytics-dashboard-index .advanced-controls { margin: 0.625rem 0; padding: 0; + flex: 1 1 100%; } .kenui-analytics-dashboard-index .advanced-controls .form-horizontal { - background: #fafafa; + background: #ffffff; border: 0.0625rem solid #e9eaeb; border-radius: 0.5rem; - padding: 0.625rem; + padding: 1rem 1.25rem; margin-top: 0.625rem; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem 1.5rem; + align-items: start; +} + +.kenui-analytics-dashboard-index .advanced-controls .form-horizontal > .form-group:last-of-type { + grid-column: 1 / -1; + justify-self: end; + margin-top: 0; } .kenui-analytics-dashboard-index .advanced-controls fieldset { border: none; margin: 0; padding: 0; + min-width: 0; } .kenui-analytics-dashboard-index .advanced-controls legend { @@ -647,10 +708,10 @@ } .kenui-analytics-dashboard-index .advanced-controls .form-group { - margin-bottom: 1rem; + margin-bottom: 0.75rem; display: flex; flex-direction: column; - align-items: center; + align-items: stretch; } .kenui-analytics-dashboard-index .advanced-controls .control-label { @@ -675,7 +736,7 @@ .kenui-analytics-dashboard-index .advanced-controls select.form-control { height: 6rem; - min-width: 16rem; + min-width: 0; width: 100%; } @@ -716,14 +777,15 @@ /* Current Analytics Query Section */ .kenui-analytics-dashboard-index .well ul li:has(.query-label) { - background: #f8f9fa; + background: #ffffff; border: 0.0625rem solid #e9eaeb; border-radius: 0.5rem; - padding: 0.625rem; - margin: 0.625rem 0; + padding: 0.75rem 1rem; + margin: 0; display: flex; flex-direction: column; - gap: 0.75rem; + gap: 0.5rem; + flex: 1 1 100%; } .kenui-analytics-dashboard-index .well ul li:has(.query-label) a { @@ -770,6 +832,10 @@ /* Responsive adjustments for smaller screens */ @media (max-width: 768px) { + .kenui-analytics-dashboard-index .advanced-controls .form-horizontal { + grid-template-columns: 1fr; + } + .kenui-analytics-dashboard-index .advanced-controls .form-group { flex-direction: column; align-items: flex-start; diff --git a/app/views/kanaui/dashboard/index.html.erb b/app/views/kanaui/dashboard/index.html.erb index 31ff95e..32cbc41 100644 --- a/app/views/kanaui/dashboard/index.html.erb +++ b/app/views/kanaui/dashboard/index.html.erb @@ -150,6 +150,11 @@
<% if params[:name] %> +
+

+ <%= @report['reportPrettyName'] %> +

+
-
-
-

- <%= @raw_name.titleize %> -

-
-
-
+

@@ -318,4 +316,32 @@ // Safe to navigate window.location.href = url; } + + // Persist the open/closed state of #advanced-controls across page reloads + (function () { + var STORAGE_KEY = 'kanaui.advancedControls.open'; + var panel = document.getElementById('advanced-controls'); + if (!panel) { + return; + } + var toggle = document.querySelector('[data-bs-toggle="collapse"][href="#advanced-controls"]'); + + // Restore previous state before Bootstrap initializes + try { + if (localStorage.getItem(STORAGE_KEY) === '1') { + panel.classList.add('show'); + if (toggle) { + toggle.setAttribute('aria-expanded', 'true'); + toggle.classList.remove('collapsed'); + } + } + } catch (e) { /* localStorage may be unavailable */ } + + panel.addEventListener('shown.bs.collapse', function () { + try { localStorage.setItem(STORAGE_KEY, '1'); } catch (e) {} + }); + panel.addEventListener('hidden.bs.collapse', function () { + try { localStorage.setItem(STORAGE_KEY, '0'); } catch (e) {} + }); + })(); <% end %> \ No newline at end of file From b942ac2000fd2c7f56f9f1decc6d93b58315bb73 Mon Sep 17 00:00:00 2001 From: Le Duy Tung Date: Mon, 25 May 2026 13:47:49 +0700 Subject: [PATCH 3/3] Update Advanced Controls --- .../kanaui/kiddo/charts/utils/mouse_over.js | 7 ++++--- app/assets/stylesheets/kanaui/kanaui.css | 18 +++++++++--------- app/controllers/kanaui/dashboard_controller.rb | 5 ++--- app/helpers/kanaui/dashboard_helper.rb | 12 +++++++++--- app/views/kanaui/dashboard/index.html.erb | 12 ++++++------ 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js b/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js index f7ded7a..e9b770c 100644 --- a/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js +++ b/app/assets/javascripts/kanaui/kiddo/charts/utils/mouse_over.js @@ -149,19 +149,20 @@ .text( element.d === undefined ? element.element.name - : helper.formatValueDisplay(element.element.name, element.d, self.reportName) + : helper.formatValueDisplay(element.element.name, element.d) ); addInfoDimensions(text); }); - // Position tooltip to follow the cursor; flip left when near the right edge + // Position tooltip to follow the cursor; flip left when near the right edge. var tooltipOffset = 15; var tooltipWidth = info.node().getBBox().width; var tooltipHeight = info.node().getBBox().height; - var canvasX = (mouseX + tooltipOffset + tooltipWidth > self.width) + var localX = (mouseX + tooltipOffset + tooltipWidth > self.width) ? mouseX - tooltipWidth - tooltipOffset : mouseX + tooltipOffset; + var canvasX = localX + self.margin_left; var canvasY = Math.max(0, mouseY - 150); canvas.attr("transform", "translate(" + canvasX + "," + canvasY + ")"); } diff --git a/app/assets/stylesheets/kanaui/kanaui.css b/app/assets/stylesheets/kanaui/kanaui.css index d62e96e..65a6b2c 100644 --- a/app/assets/stylesheets/kanaui/kanaui.css +++ b/app/assets/stylesheets/kanaui/kanaui.css @@ -115,11 +115,11 @@ } /* Smoothing option links (Weekly/Monthly average/sum) render as inline pills */ -.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) { +.kenui-analytics-dashboard-index .well > ul > li.smoothing-option { display: inline-flex; } -.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) > a { +.kenui-analytics-dashboard-index .well > ul > li.smoothing-option > a { display: inline-flex; align-items: center; background: #ffffff; @@ -134,7 +134,7 @@ transition: all 0.15s ease-in-out; } -.kenui-analytics-dashboard-index .well > ul > li:not(.advanced-controls):not(:has(.query-label)) > a:hover { +.kenui-analytics-dashboard-index .well > ul > li.smoothing-option > a:hover { border-color: #1570ef; color: #1570ef; } @@ -776,7 +776,7 @@ } /* Current Analytics Query Section */ -.kenui-analytics-dashboard-index .well ul li:has(.query-label) { +.kenui-analytics-dashboard-index .well ul li.query-block { background: #ffffff; border: 0.0625rem solid #e9eaeb; border-radius: 0.5rem; @@ -788,7 +788,7 @@ flex: 1 1 100%; } -.kenui-analytics-dashboard-index .well ul li:has(.query-label) a { +.kenui-analytics-dashboard-index .well ul li.query-block a { color: #1570ef; text-decoration: none; font-weight: 500; @@ -801,12 +801,12 @@ transition: color 0.15s ease-in-out; } -.kenui-analytics-dashboard-index .well ul li:has(.query-label) a:hover { +.kenui-analytics-dashboard-index .well ul li.query-block a:hover { color: #0d5bb8; text-decoration: underline; } -.kenui-analytics-dashboard-index .well ul li:has(.query-label) pre { +.kenui-analytics-dashboard-index .well ul li.query-block pre { background: #ffffff; border: 0.0625rem solid #d5d7da; border-radius: 0.375rem; @@ -822,7 +822,7 @@ box-shadow: 0 0.0625rem 0.1875rem rgba(0, 0, 0, 0.1); } -.kenui-analytics-dashboard-index .well ul li:has(.query-label) .query-label { +.kenui-analytics-dashboard-index .well ul li.query-block .query-label { font-weight: 500; font-size: 0.875rem; line-height: 1.25rem; @@ -851,7 +851,7 @@ width: 100%; } - .kenui-analytics-dashboard-index .well ul li:has(.query-label) pre { + .kenui-analytics-dashboard-index .well ul li.query-block pre { font-size: 0.75rem; padding: 0.5rem 0.75rem; } diff --git a/app/controllers/kanaui/dashboard_controller.rb b/app/controllers/kanaui/dashboard_controller.rb index 06b53da..74c13d5 100644 --- a/app/controllers/kanaui/dashboard_controller.rb +++ b/app/controllers/kanaui/dashboard_controller.rb @@ -146,7 +146,7 @@ def build_slice_and_dice_query groups[field_name] = params["group_#{field_name}"] end - filter_query = '' + filter_query = +'' filters.each do |k, v| next if v.blank? @@ -158,8 +158,7 @@ def build_slice_and_dice_query groups.each do |k, v| next if v.blank? - # TODO: Make "no other" configurable - query << "^dimension:#{k}(#{v.join('|')}|-)" + query << "^dimension:#{k}(#{v.join('|')})" end # Template variables diff --git a/app/helpers/kanaui/dashboard_helper.rb b/app/helpers/kanaui/dashboard_helper.rb index 38136b4..9c576d3 100644 --- a/app/helpers/kanaui/dashboard_helper.rb +++ b/app/helpers/kanaui/dashboard_helper.rb @@ -18,9 +18,15 @@ def available_reports(options = {}) end def reports(start_date, end_date, name, smooth, sql_only, format, options = {}) - path = "#{KILLBILL_ANALYTICS_PREFIX}/reports?format=#{format}&startDate=#{start_date}&endDate=#{end_date}&name=#{name}" - path = "#{path}&smooth=#{smooth}" if smooth - path = "#{path}&sqlOnly=true" if sql_only.present? + query = { + 'format' => format, + 'startDate' => start_date, + 'endDate' => end_date, + 'name' => name + } + query['smooth'] = smooth if smooth + query['sqlOnly'] = 'true' if sql_only.present? + path = "#{KILLBILL_ANALYTICS_PREFIX}/reports?#{query.to_query}" response = KillBillClient::API.get path, {}, options response.body end diff --git a/app/views/kanaui/dashboard/index.html.erb b/app/views/kanaui/dashboard/index.html.erb index 32cbc41..b257c06 100644 --- a/app/views/kanaui/dashboard/index.html.erb +++ b/app/views/kanaui/dashboard/index.html.erb @@ -205,16 +205,16 @@ <% at_least_two_months = params[:start_date].blank? || params[:end_date].blank? || (params[:end_date].to_date.beginning_of_month - 1.month > params[:start_date].to_date) %> <% at_least_two_weeks = params[:start_date].blank? || params[:end_date].blank? || (params[:end_date].to_date.beginning_of_week - 1.week > params[:start_date].to_date) %> <% if params[:smooth] != 'AVERAGE_WEEKLY' && at_least_two_weeks %> -
  • <%= link_to 'Weekly average', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'AVERAGE_WEEKLY')) %>
  • +
  • <%= link_to 'Weekly average', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'AVERAGE_WEEKLY')) %>
  • <% end %> <% if params[:smooth] != 'AVERAGE_MONTHLY' && at_least_two_months %> -
  • <%= link_to 'Monthly average', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'AVERAGE_MONTHLY')) %>
  • +
  • <%= link_to 'Monthly average', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'AVERAGE_MONTHLY')) %>
  • <% end %> <% if params[:smooth] != 'SUM_WEEKLY' && at_least_two_weeks %> -
  • <%= link_to 'Weekly sum', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'SUM_WEEKLY')) %>
  • +
  • <%= link_to 'Weekly sum', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'SUM_WEEKLY')) %>
  • <% end %> <% if params[:smooth] != 'SUM_MONTHLY' && at_least_two_months %> -
  • <%= link_to 'Monthly sum', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'SUM_MONTHLY')) %>
  • +
  • <%= link_to 'Monthly sum', kanaui_engine.dashboard_index_path(params.to_h.merge(:smooth => 'SUM_MONTHLY')) %>
  • <% end %> <% end %> <% filter_fields = ((@report['schema'] || {})['fields'] || []).select { |field| !field['distinctValues'].blank? && field['dataType'] =~ /char/ } # To ignore tenant_record_id %> @@ -257,14 +257,14 @@
    <% end %> -
  • +
  • Current Analytics query: <%= link_to ''.html_safe, 'http://docs.killbill.io/latest/userguide_analytics.html#_dashboard_api', :target => '_blank' %>
    <%= params[:name] -%>
  • <% end %> -
  • <%= link_to t('kanaui.dashboard.advanced_controls.sql_query'), kanaui_engine.reports_path(params.to_h.merge(:sql_only => true)) %>
  • +
  • <%= link_to t('kanaui.dashboard.advanced_controls.sql_query'), kanaui_engine.reports_path(params.to_h.merge(:sql_only => true)) %>