diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..0f9ec94 --- /dev/null +++ b/changelog.md @@ -0,0 +1,50 @@ +# Changelog + +#### Legend + +- Bug Fix (-) +- Feature Addition (+) +- Improvement (^) + +--- + +## com_tjreports v1.1.5 + +### + Features Additions: + +- #156044 Bulk Email sending +- #155499 Add a function in tjreports to get the reports that support google data studio connector +- #153710 Show summary report for Feedback + +### ^ Improvements: + +- #168311 Remove duplicates Language constant from language files. +- #160788 Added index in #__tjreports_com_users_user table +- #148927 Add reports API plugin in TJReport package + +#### - Bug Fixes: + +- #169471 Reports > In report data not showing count with link, it's showing href string +- #169429 Reports > Frontend > Reports > Radio button and Export CSV alignment messed up +- #169428 Reports > Frontend > Reports > Language constant missing +- #169363 CSV export not working when report name has special characters +- #169215 Reports > Reports having dynamic column shows different data with / without loading params +- #165179 Search tools on Reports not working on mobile devices +- #165071 Fix height for column level filter in report +- #164411 Getting Unknown column 'Array' in 'field list' error +- #164232 Single quotes and double quotes are getting removed +- #163952 Users com_fields are saving by converting some characters to HTML entities instead of the original value +- #163509 After Block the user from users list then 'user field' not showing in the user reports +- #160788 fix: TjReports Performance Issue in reports model as it fetches all the record from the database without pagination/limit +- #180 Added missing language constants for column wise sorting +- #176 Compatible date field filter for any date format and modified in query +- #172 Notice: Undefined index in reports model & reports default view + + + + + + + + + diff --git a/tjreports/administrator/models/indexer.php b/tjreports/administrator/models/indexer.php index e8b8416..79a6d64 100644 --- a/tjreports/administrator/models/indexer.php +++ b/tjreports/administrator/models/indexer.php @@ -69,7 +69,7 @@ public function createTable($context) // Create table $db = Factory::getDbo(); $query = 'CREATE TABLE IF NOT EXISTS ' . $db->quoteName($this->customFieldsTable) . ' ( - `record_id` int(11) NOT NULL + `record_id` int(11) NOT NULL, KEY `record_id` (`record_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8'; $db->setQuery($query); diff --git a/tjreports/administrator/models/tjreport.php b/tjreports/administrator/models/tjreport.php index 5ed7eeb..51b93e5 100644 --- a/tjreports/administrator/models/tjreport.php +++ b/tjreports/administrator/models/tjreport.php @@ -175,18 +175,31 @@ public function getReportPluginData($pluginId, $pluginName = null) $defaultColToHide = $plgModel->getState('defaultColToHide'); - $params = array(); - $params['filter_order'] = $plgModel->getState('list.ordering'); - $params['filter_order_Dir'] = $plgModel->getState('list.direction'); - $params['limit'] = $plgModel->getState('list.limit'); - $params['emailColumn'] = $plgModel->getState('emailColumn'); - $params['colToshow'] = $plgModel->getState('colToshow'); - $params['colToshow'] = array_combine($params['colToshow'], array_fill(0, count($params['colToshow']), true)); + $params = array(); + $params['filter_order'] = $plgModel->getState('list.ordering'); + $params['filter_order_Dir'] = $plgModel->getState('list.direction'); + $params['limit'] = $plgModel->getState('list.limit'); + + // Show summary report configuration in params + $params['showSummaryReport'] = $plgModel->getState('showSummaryReport'); + + $params['emailColumn'] = $plgModel->getState('emailColumn'); + $params['colToshow'] = $plgModel->getState('colToshow'); + $params['colToshow'] = array_combine($params['colToshow'], array_fill(0, count($params['colToshow']), true)); /* Here merge colToshow (array value is true) with defaultColToHide (array value is false) column - * so false value column not display on report by default.*/ if (!empty($defaultColToHide)) { + // Here remove dynamic column(for example: lesson::lesson_status) from defaultColToHide because no need to load dynamic column. + foreach ($defaultColToHide as $key => $colHide) + { + if (strpos($key, '::') !== false) + { + unset($defaultColToHide[$key]); + } + } + $params['colToshow'] = array_merge($params['colToshow'], $defaultColToHide); } diff --git a/tjreports/administrator/views/reports/tmpl/default_summary.php b/tjreports/administrator/views/reports/tmpl/default_summary.php new file mode 100644 index 0000000..a1cdd8f --- /dev/null +++ b/tjreports/administrator/views/reports/tmpl/default_summary.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access +defined('_JEXEC') or die; + +// Load the layout & push variables + +$path = $this->tjreportsHelper->getViewpath('com_tjreports', 'reports', 'default_summary', 'SITE', 'SITE'); +ob_start(); +include $path; +$html = ob_get_contents(); +ob_end_clean(); +echo $html; diff --git a/tjreports/administrator/views/tjreport/view.html.php b/tjreports/administrator/views/tjreport/view.html.php index f28c31b..cd55d2e 100644 --- a/tjreports/administrator/views/tjreport/view.html.php +++ b/tjreports/administrator/views/tjreport/view.html.php @@ -8,13 +8,22 @@ */ // No direct access to this file defined('_JEXEC') or die; + +Use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Toolbar\ToolbarHelper; + require_once JPATH_COMPONENT . '/helpers/tjreports.php'; + /** * tjreport View * * @since 0.0.1 */ -class TjreportsViewTjreport extends JViewLegacy +class TjreportsViewTjreport extends HtmlView { /** * View form @@ -44,7 +53,7 @@ public function display($tpl = null) return false; } - $input = JFactory::getApplication()->input; + $input = Factory::getApplication()->input; $extension = $input->get('extension', '', 'STRING'); $this->addToolBar(); @@ -63,7 +72,7 @@ public function display($tpl = null) */ protected function addToolBar() { - $input = JFactory::getApplication()->input; + $input = Factory::getApplication()->input; // Hide Joomla Administrator Main menu $input->set('hidemainmenu', true); @@ -71,17 +80,17 @@ protected function addToolBar() if ($isNew) { - $title = JText::_('COM_TJREPORTS_NEW'); + $title = Text::_('COM_TJREPORTS_NEW'); } else { - $title = JText::_('COM_TJREPORTS_EDIT'); + $title = Text::_('COM_TJREPORTS_EDIT'); } - JToolBarHelper::title($title, 'tjreport'); - JToolBarHelper::apply('tjreport.apply'); - JToolBarHelper::save('tjreport.save'); - JToolBarHelper::cancel( + ToolbarHelper::title($title, 'tjreport'); + ToolbarHelper::apply('tjreport.apply'); + ToolbarHelper::save('tjreport.save'); + ToolbarHelper::cancel( 'tjreport.cancel', $isNew ? 'JTOOLBAR_CANCEL' : 'JTOOLBAR_CLOSE' ); @@ -96,14 +105,17 @@ protected function addToolBar() */ protected function addDocumentHeaderData() { - JHtml::_('jquery.framework'); - JText::script('COM_TJREPORTS_FORM_DEFAULT_OPTION'); - JText::script('COM_TJREPORTS_INVALID_JSON_VALUE'); - $document = JFactory::getDocument(); - $document->addScript(JURI::root() . '/components/com_tjreports/assets/js/tjrContentService.js'); - $document->addScript(JURI::root() . '/components/com_tjreports/assets/js/tjrContentUI.js'); - $document->addStylesheet(JURI::root() . '/components/com_tjreports/assets/css/tjreports.css'); - $document->addScriptDeclaration('tjrContentUI.base_url = "' . Juri::base() . '"'); - $document->addScriptDeclaration('tjrContentUI.root_url = "' . Juri::root() . '"'); + HTMLHelper::_('jquery.framework'); + Text::script('COM_TJREPORTS_FORM_DEFAULT_OPTION'); + Text::script('COM_TJREPORTS_INVALID_JSON_VALUE'); + + $document = Factory::getDocument(); + + HTMLHelper::_('script', 'components/com_tjreports/assets/js/tjrContentService.min.js'); + HTMLHelper::_('script', 'components/com_tjreports/assets/js/tjrContentUI.min.js'); + HTMLHelper::_('stylesheet', 'components/com_tjreports/assets/css/tjreports.min.css'); + + $document->addScriptDeclaration('tjrContentUI.base_url = "' . Uri::base() . '"'); + $document->addScriptDeclaration('tjrContentUI.root_url = "' . Uri::root() . '"'); } } diff --git a/tjreports/languages/administrator/en-GB/en-GB.com_tjreports.ini b/tjreports/languages/administrator/en-GB/en-GB.com_tjreports.ini index cfbb861..02170ff 100755 --- a/tjreports/languages/administrator/en-GB/en-GB.com_tjreports.ini +++ b/tjreports/languages/administrator/en-GB/en-GB.com_tjreports.ini @@ -38,7 +38,7 @@ COM_TJREPORTS_LIST_ID="Id" COM_TJREPORTS_TITLE_REPORT="Reports" COM_TJREPORTS_CSV_EXPORT="CSV Export" -COM_TJREPORTS_FILTER_SELECT_COURSE="Select Course" +COM_TJREPORTS_FILTER_SELECT_COURSE="- Select Course -" COM_TJREPORTS_FORM_DEFAULT_OPTION="- Select Plugin -" COM_TJREPORT_SAVE_ALIAS_WARNING="Alias already existed so a number was added at the end. You can re-edit the article to customise the alias." COM_TJREPORT_VIEW_WITH_SAME_ALIAS="Alias name cannot be same as view names." @@ -48,7 +48,6 @@ COM_TJREPORTS_EXPORT_FILE_SUCCESS="100% Download Complete." ;Common for reports COM_TJREPORTS_FILTER_SELECT_ACCESSLEVEL="- Select Access Level -" -COM_TJREPORTS_FILTER_SELECT_COURSE="- Select Course -" COM_TJREPORTS_FILTER_SELECT_LESSON="Select lesson -" COM_TJREPORTS_FILTER_SELECT_COURSE_CATEGORY="- Select Category -" COM_TJREPORTS_FILTER_SELECT_COURSE_TYPE="- Select Type -" @@ -139,3 +138,16 @@ COM_TJREPORTS_QUERY_DELETE_SUCCESS="Query deleted successfully." ;Added in v1.0.2 COM_TJREPORTS_NOTHING_TO_DISCOVER_PLUGINS="Nothing to discover" COM_TJREPORTS_DISCOVER_NEW_PLUGINS="%d new plugin(s) discovered" + +; Column wise sorting +COM_TJREPORTS_PLUGIN_ASC="Plugin ascending" +COM_TJREPORTS_PLUGIN_DESC="Plugin descending" +COM_TJREPORTS_CLIENT_ASC="Client ascending" +COM_TJREPORTS_CLIENT_DESC="Client descending" +COM_TJREPORTS_SAVED_QUERY_ASC="Saved Query ascending" +COM_TJREPORTS_SAVED_QUERY_DESC="Saved Query descending" + +; Added in __DEPLOY_VERSION__ +COM_TJREPORTS_REPORT_SUMMARY="Summary Report" +COM_TJREPORTS_REPORT_DETAILS="Details Report" +COM_TJREPORTS_NO_RECORDS_FOUND_SUMMARY="No records found. Either you do not have any records or fields types found in records are not supported for showing summary report." diff --git a/tjreports/languages/site/en-GB/en-GB.com_tjreports.ini b/tjreports/languages/site/en-GB/en-GB.com_tjreports.ini index 5b8c998..2d9bedd 100755 --- a/tjreports/languages/site/en-GB/en-GB.com_tjreports.ini +++ b/tjreports/languages/site/en-GB/en-GB.com_tjreports.ini @@ -107,3 +107,6 @@ LIB_TECHJOOMLA_CSV_EXPORT_ABORT="Abort" LIB_TECHJOOMLA_CSV_EXPORT_CONFIRM_ABORT="Are you sure to abort CSV Export?" LIB_TECHJOOMLA_CSV_EXPORT_UESR_ABORTED="Export aborted." +; Since __DEPLOY_VERSION__ +COM_TJREPORTS_REPORT_DETAILS="Details Report" +COM_TJREPORTS_REPORT_SUMMARY="Summary Report" diff --git a/tjreports/media/js/chartBundle.min.js b/tjreports/media/js/chartBundle.min.js new file mode 100644 index 0000000..59afc3f --- /dev/null +++ b/tjreports/media/js/chartBundle.min.js @@ -0,0 +1,10 @@ +/*! + * Chart.js + * http://chartjs.org/ + * Version: 2.7.3 + * + * Copyright 2018 Chart.js Contributors + * Released under the MIT license + * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function r(o,s,l){function u(e,t){if(!s[e]){if(!o[e]){var n="function"==typeof require&&require;if(!t&&n)return n(e,!0);if(d)return d(e,!0);var i=new Error("Cannot find module '"+e+"'");throw i.code="MODULE_NOT_FOUND",i}var a=s[e]={exports:{}};o[e][0].call(a.exports,function(t){return u(o[e][1][t]||t)},a,a.exports,r,o,s,l)}return s[e].exports}for(var d="function"==typeof require&&require,t=0;t>>0,i=0;iwt(t)?(r=t+1,s-wt(t)):(r=t,s),{year:r,dayOfYear:o}}function Bt(t,e,n){var i,a,r=Vt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+Et(a=t.year()-1,e,n):o>Et(t.year(),e,n)?(i=o-Et(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function Et(t,e,n){var i=Vt(t,e,n),a=Vt(t+1,e,n);return(wt(t)-i+a)/7}B("w",["ww",2],"wo","week"),B("W",["WW",2],"Wo","isoWeek"),A("week","w"),A("isoWeek","W"),Y("week",5),Y("isoWeek",5),lt("w",J),lt("ww",J,G),lt("W",J),lt("WW",J,G),ft(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=M(t)});B("d",0,"do","day"),B("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),B("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),B("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),B("e",0,0,"weekday"),B("E",0,0,"isoWeekday"),A("day","d"),A("weekday","e"),A("isoWeekday","E"),Y("day",11),Y("weekday",11),Y("isoWeekday",11),lt("d",J),lt("e",J),lt("E",J),lt("dd",function(t,e){return e.weekdaysMinRegex(t)}),lt("ddd",function(t,e){return e.weekdaysShortRegex(t)}),lt("dddd",function(t,e){return e.weekdaysRegex(t)}),ft(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:v(n).invalidWeekday=t}),ft(["d","e","E"],function(t,e,n,i){e[i]=M(t)});var jt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ut="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var Gt="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qt=ot;var Zt=ot;var Xt=ot;function Jt(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=p([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=dt(s[e]),l[e]=dt(l[e]),u[e]=dt(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function $t(){return this.hours()%12||12}function Kt(t,e){B(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function Qt(t,e){return e._meridiemParse}B("H",["HH",2],0,"hour"),B("h",["hh",2],0,$t),B("k",["kk",2],0,function(){return this.hours()||24}),B("hmm",0,0,function(){return""+$t.apply(this)+W(this.minutes(),2)}),B("hmmss",0,0,function(){return""+$t.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),B("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),B("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),Kt("a",!0),Kt("A",!1),A("hour","h"),Y("hour",13),lt("a",Qt),lt("A",Qt),lt("H",J),lt("h",J),lt("k",J),lt("HH",J,G),lt("hh",J,G),lt("kk",J,G),lt("hmm",$),lt("hmmss",K),lt("Hmm",$),lt("Hmmss",K),ct(["H","HH"],vt),ct(["k","kk"],function(t,e,n){var i=M(t);e[vt]=24===i?0:i}),ct(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),ct(["h","hh"],function(t,e,n){e[vt]=M(t),v(n).bigHour=!0}),ct("hmm",function(t,e,n){var i=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i)),v(n).bigHour=!0}),ct("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i,2)),e[yt]=M(t.substr(a)),v(n).bigHour=!0}),ct("Hmm",function(t,e,n){var i=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i))}),ct("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[vt]=M(t.substr(0,i)),e[bt]=M(t.substr(i,2)),e[yt]=M(t.substr(a))});var te,ee=Ct("Hours",!0),ne={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:At,monthsShort:Ft,week:{dow:0,doy:6},weekdays:jt,weekdaysMin:Gt,weekdaysShort:Ut,meridiemParse:/[ap]\.?m?\.?/i},ie={},ae={};function re(t){return t?t.toLowerCase().replace("_","-"):t}function oe(t){var e=null;if(!ie[t]&&void 0!==jn&&jn&&jn.exports)try{e=te._abbr,En("./locale/"+t),se(e)}catch(t){}return ie[t]}function se(t,e){var n;return t&&((n=u(e)?ue(t):le(t,e))?te=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),te._abbr}function le(t,e){if(null===e)return delete ie[t],null;var n,i=ne;if(e.abbr=t,null!=ie[t])C("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=ie[t]._config;else if(null!=e.parentLocale)if(null!=ie[e.parentLocale])i=ie[e.parentLocale]._config;else{if(null==(n=oe(e.parentLocale)))return ae[e.parentLocale]||(ae[e.parentLocale]=[]),ae[e.parentLocale].push({name:t,config:e}),null;i=n._config}return ie[t]=new O(T(i,e)),ae[t]&&ae[t].forEach(function(t){le(t.name,t.config)}),se(t),ie[t]}function ue(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return te;if(!s(t)){if(e=oe(t))return e;t=[t]}return function(t){for(var e,n,i,a,r=0;r=e&&o(a,n,!0)>=e-1)break;e--}r++}return te}(t)}function de(t){var e,n=t._a;return n&&-2===v(t).overflow&&(e=n[mt]<0||11Ot(n[gt],n[mt])?pt:n[vt]<0||24Et(n,r,o)?v(t)._overflowWeeks=!0:null!=l?v(t)._overflowWeekday=!0:(s=Ht(n,i,a,r,o),t._a[gt]=s.year,t._dayOfYear=s.dayOfYear)}(t),null!=t._dayOfYear&&(r=he(t._a[gt],i[gt]),(t._dayOfYear>wt(r)||0===t._dayOfYear)&&(v(t)._overflowDayOfYear=!0),n=zt(r,0,t._dayOfYear),t._a[mt]=n.getUTCMonth(),t._a[pt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=o[e]=i[e];for(;e<7;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[vt]&&0===t._a[bt]&&0===t._a[yt]&&0===t._a[xt]&&(t._nextDay=!0,t._a[vt]=0),t._d=(t._useUTC?zt:function(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&0<=t&&isFinite(s.getFullYear())&&s.setFullYear(t),s}).apply(null,o),a=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[vt]=24),t._w&&void 0!==t._w.d&&t._w.d!==a&&(v(t).weekdayMismatch=!0)}}var fe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ge=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,me=/Z|[+-]\d\d(?::?\d\d)?/,pe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ve=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],be=/^\/?Date\((\-?\d+)/i;function ye(t){var e,n,i,a,r,o,s=t._i,l=fe.exec(s)||ge.exec(s);if(l){for(v(t).iso=!0,e=0,n=pe.length;en.valueOf():n.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},un.isLocal=function(){return!!this.isValid()&&!this._isUTC},un.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},un.isUtc=Ve,un.isUTC=Ve,un.zoneAbbr=function(){return this._isUTC?"UTC":""},un.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},un.dates=n("dates accessor is deprecated. Use date instead.",nn),un.months=n("months accessor is deprecated. Use month instead",Lt),un.years=n("years accessor is deprecated. Use year instead",Dt),un.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),un.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t={};if(x(t,this),(t=Se(t))._a){var e=t._isUTC?p(t._a):Ce(t._a);this._isDSTShifted=this.isValid()&&0');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(l){var u=l.data;return u.labels.length&&u.datasets.length?u.labels.map(function(t,e){var n=l.getDatasetMeta(0),i=u.datasets[0],a=n.data[e],r=a&&a.custom||{},o=O.valueAtIndexOrDefault,s=l.options.elements.arc;return{text:t,fillStyle:r.backgroundColor?r.backgroundColor:o(i.backgroundColor,e,s.backgroundColor),strokeStyle:r.borderColor?r.borderColor:o(i.borderColor,e,s.borderColor),lineWidth:r.borderWidth?r.borderWidth:o(i.borderWidth,e,s.borderWidth),hidden:isNaN(i.data[e])||n.data[e].hidden,index:e}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=Math.PI?-1:f<-Math.PI?1:0))+c,m=Math.cos(f),p=Math.sin(f),v=Math.cos(g),b=Math.sin(g),y=f<=0&&0<=g||f<=2*Math.PI&&2*Math.PI<=g,x=f<=.5*Math.PI&&.5*Math.PI<=g||f<=2.5*Math.PI&&2.5*Math.PI<=g,_=f<=-Math.PI&&-Math.PI<=g||f<=Math.PI&&Math.PI<=g,k=f<=.5*-Math.PI&&.5*-Math.PI<=g||f<=1.5*Math.PI&&1.5*Math.PI<=g,w=h/100,M=_?-1:Math.min(m*(m<0?1:w),v*(v<0?1:w)),S=k?-1:Math.min(p*(p<0?1:w),b*(b<0?1:w)),D=y?1:Math.max(m*(0');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(s){var l=s.data;return l.labels.length&&l.datasets.length?l.labels.map(function(t,e){var n=s.getDatasetMeta(0),i=l.datasets[0],a=n.data[e].custom||{},r=_.valueAtIndexOrDefault,o=s.options.elements.arc;return{text:t,fillStyle:a.backgroundColor?a.backgroundColor:r(i.backgroundColor,e,o.backgroundColor),strokeStyle:a.borderColor?a.borderColor:r(i.borderColor,e,o.borderColor),lineWidth:a.borderWidth?a.borderWidth:r(i.borderWidth,e,o.borderWidth),hidden:isNaN(i.data[e])||n.data[e].hidden,index:e}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}}},{26:26,46:46}],24:[function(t,e,n){"use strict";var s=t(22),l=t(23),h=t(26),c=t(46),a=t(29),r=t(31),f=t(49),g=t(32),m=t(34),i=t(36);e.exports=function(u){function d(t){return"top"===t||"bottom"===t}u.types={},u.instances={},u.controllers={},c.extend(u.prototype,{construct:function(t,e){var n,i,a=this;(i=(n=(n=e)||{}).data=n.data||{}).datasets=i.datasets||[],i.labels=i.labels||[],n.options=c.configMerge(h.global,h[n.type],n.options||{}),e=n;var r=f.acquireContext(t,e),o=r&&r.canvas,s=o&&o.height,l=o&&o.width;a.id=c.uid(),a.ctx=r,a.canvas=o,a.config=e,a.width=l,a.height=s,a.aspectRatio=s?l/s:null,a.options=e.options,a._bufferedRender=!1,(a.chart=a).controller=a,u.instances[a.id]=a,Object.defineProperty(a,"data",{get:function(){return a.config.data},set:function(t){a.config.data=t}}),r&&o?(a.initialize(),a.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return g.notify(t,"beforeInit"),c.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),g.notify(t,"afterInit"),t},clear:function(){return c.canvas.clear(this),this},stop:function(){return l.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(c.getMaximumWidth(i))),o=Math.max(0,Math.floor(a?r/a:c.getMaximumHeight(i)));if((e.width!==r||e.height!==o)&&(i.width=e.width=r,i.height=e.height=o,i.style.width=r+"px",i.style.height=o+"px",c.retinaScale(e,n.devicePixelRatio),!t)){var s={width:r,height:o};g.notify(e,"resize",[s]),e.options.onResize&&e.options.onResize(e,s),e.stop(),e.update({duration:e.options.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;c.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),c.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var o=this,t=o.options,s=o.scales||{},e=[],l=Object.keys(s).reduce(function(t,e){return t[e]=!1,t},{});t.scales&&(e=e.concat((t.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(t.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),t.scale&&e.push({options:t.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),c.each(e,function(t){var e=t.options,n=e.id,i=c.valueOrDefault(e.type,t.dtype);d(e.position)!==d(t.dposition)&&(e.position=t.dposition),l[n]=!0;var a=null;if(n in s&&s[n].type===i)(a=s[n]).options=e,a.ctx=o.ctx,a.chart=o;else{var r=m.getScaleConstructor(i);if(!r)return;a=new r({id:n,type:i,options:e,ctx:o.ctx,chart:o}),s[a.id]=a}a.mergeTicksOptions(),t.isDefault&&(o.scale=a)}),c.each(l,function(t,e){t||delete s[e]}),o.scales=s,m.addScalesToLayout(this)},buildOrUpdateControllers:function(){var r=this,o=[],s=[];return c.each(r.data.datasets,function(t,e){var n=r.getDatasetMeta(e),i=t.type||r.config.type;if(n.type&&n.type!==i&&(r.destroyDatasetMeta(e),n=r.getDatasetMeta(e)),n.type=i,o.push(n.type),n.controller)n.controller.updateIndex(e),n.controller.linkScales();else{var a=u.controllers[n.type];if(void 0===a)throw new Error('"'+n.type+'" is not a chart type.');n.controller=new a(r,e),s.push(n.controller)}},r),s},resetElements:function(){var n=this;c.each(n.data.datasets,function(t,e){n.getDatasetMeta(e).controller.reset()},n)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e,n,i=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n=(e=i).options,c.each(e.scales,function(t){r.removeBox(e,t)}),n=c.configMerge(u.defaults.global,u.defaults[e.config.type],n),e.options=e.config.options=n,e.ensureScalesHaveIDs(),e.buildOrUpdateScales(),e.tooltip._options=n.tooltips,e.tooltip.initialize(),g._invalidate(i),!1!==g.notify(i,"beforeUpdate")){i.tooltip._data=i.data;var a=i.buildOrUpdateControllers();c.each(i.data.datasets,function(t,e){i.getDatasetMeta(e).controller.buildOrUpdateElements()},i),i.updateLayout(),i.options.animation&&i.options.animation.duration&&c.each(a,function(t){t.reset()}),i.updateDatasets(),i.tooltip.initialize(),i.lastActive=[],g.notify(i,"afterUpdate"),i._bufferedRender?i._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:i.render(t)}},updateLayout:function(){!1!==g.notify(this,"beforeLayout")&&(r.update(this,this.width,this.height),g.notify(this,"afterScaleUpdate"),g.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==g.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t=e[t].length&&e[t].push({}),!e[t][a].type||o.type&&o.type!==e[t][a].type?g.merge(e[t][a],[l.getScaleDefaults(r),o]):g.merge(e[t][a],o)}else g._merger(t,e,n,i)}})},g.where=function(t,e){if(g.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return g.each(t,function(t){e(t)&&n.push(t)}),n},g.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},g.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},g.niceNum=function(t,e){var n=Math.floor(g.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},g.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},g.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.target||t.srcElement,o=r.getBoundingClientRect(),s=a.touches;i=s&&0n.length){for(var l=0;le&&(e=t.length)}),e},g.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},g.getHoverColor=function(t){return t instanceof CanvasPattern?t:g.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,26:26,34:34,46:46}],29:[function(t,e,n){"use strict";var i=t(46);function s(t,e){return t.native?{x:t.x,y:t.y}:i.getRelativePosition(t,e)}function l(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;it.maxHeight){r--;break}r++,l=o*s}t.labelRotation=r},afterCalculateTickRotation:function(){B.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){B.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=_(t._ticks),i=t.options,a=i.ticks,r=i.scaleLabel,o=i.gridLines,s=i.display,l=t.isHorizontal(),u=w(a),d=i.gridLines.tickMarkLength;if(e.width=l?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:s&&o.drawTicks?d:0,e.height=l?s&&o.drawTicks?d:0:t.maxHeight,r.display&&s){var h=M(r)+B.options.toPadding(r.padding).height;l?e.height+=h:e.width+=h}if(a.display&&s){var c=B.longestText(t.ctx,u.font,n,t.longestTextCache),f=B.numberOfLabelLines(n),g=.5*u.size,m=t.options.ticks.padding;if(l){t.longestLabelWidth=c;var p=B.toRadians(t.labelRotation),v=Math.cos(p),b=Math.sin(p)*c+u.size*f+g*(f-1)+g;e.height=Math.min(t.maxHeight,e.height+b+m),t.ctx.font=u.font;var y=k(t.ctx,n[0],u.font),x=k(t.ctx,n[n.length-1],u.font);0!==t.labelRotation?(t.paddingLeft="bottom"===i.position?v*y+3:v*g+3,t.paddingRight="bottom"===i.position?v*g+3:v*x+3):(t.paddingLeft=y/2+3,t.paddingRight=x/2+3)}else a.mirror?c=0:c+=m+g,e.width=Math.min(t.maxWidth,e.width+c),t.paddingTop=u.size/2,t.paddingBottom=u.size/2}t.handleMargins(),t.width=e.width,t.height=e.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){B.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(B.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:B.noop,getPixelForValue:B.noop,getValueForPixel:B.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:0r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+s.autoSkipPadding)*l/(r.width-(r.paddingLeft+r.paddingRight)))),a&&al.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;i="center"===h?(n=function(t){return t<=c},function(t){return c=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,T=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,o=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);o+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,l=e.footer.length,u=e.titleFontSize,d=e.bodyFontSize,h=e.footerFontSize;i+=s*u,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=o*d,i+=o?(o-1)*e.bodySpacing:0,i+=l?e.footerMarginTop:0,i+=l*h,i+=l?(l-1)*e.footerSpacing:0;var c=0,f=function(t){a=Math.max(a,n.measureText(t).width+c)};return n.font=R.fontString(u,e._titleFontStyle,e._titleFontFamily),R.each(e.title,f),n.font=R.fontString(d,e._bodyFontStyle,e._bodyFontFamily),R.each(e.beforeBody.concat(e.afterBody),f),c=e.displayColors?d+2:0,R.each(r,function(t){R.each(t.before,f),R.each(t.lines,f),R.each(t.after,f)}),c=0,n.font=R.fontString(h,e._footerFontStyle,e._footerFontFamily),R.each(e.footer,f),{width:a+=2*e.xPadding,height:i}}(this,M)),i=M,a=T,r=C,o=_._chart,s=i.x,l=i.y,u=i.caretSize,d=i.caretPadding,h=i.cornerRadius,c=r.xAlign,f=r.yAlign,g=u+d,m=h+d,"right"===c?s-=a.width:"center"===c&&((s-=a.width/2)+a.width>o.width&&(s=o.width-a.width),s<0&&(s=0)),"top"===f?l+=g:l-="bottom"===f?a.height+g:a.height/2,"center"===f?"left"===c?s+=g:"right"===c&&(s-=g):"left"===c?s-=m:"right"===c&&(s+=m),P={x:s,y:l}}else M.opacity=0;return M.xAlign=C.xAlign,M.yAlign=C.yAlign,M.x=P.x,M.y=P.y,M.width=T.width,M.height=T.height,M.caretX=O.x,M.caretY=O.y,_._model=M,t&&k.custom&&k.custom.call(_,M),_},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===c)s=g+p/2,l="left"===h?(a=(i=f)-u,r=i,o=s+u,s-u):(a=(i=f+m)+u,r=i,o=s-u,s+u);else if(r=(i="left"===h?(a=f+d+u)-u:"right"===h?(a=f+m-d-u)-u:(a=n.caretX)-u,a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,e,n,i){var a=e.title;if(a.length){n.textAlign=e._titleAlign,n.textBaseline="top";var r,o,s=e.titleFontSize,l=e.titleSpacing;for(n.fillStyle=c(e.titleFontColor,i),n.font=R.fontString(s,e._titleFontStyle,e._titleFontFamily),r=0,o=a.length;r=n.innerRadius&&r<=n.outerRadius;return l&&u}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{26:26,27:27,46:46}],38:[function(t,e,n){"use strict";var i=t(26),a=t(27),d=t(46),h=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:h.defaultColor,borderWidth:3,borderColor:h.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this._view,r=this._chart.ctx,o=a.spanGaps,s=this._children.slice(),l=h.elements.line,u=-1;for(this._loop&&s.length&&s.push(s[0]),r.save(),r.lineCap=a.borderCapStyle||l.borderCapStyle,r.setLineDash&&r.setLineDash(a.borderDash||l.borderDash),r.lineDashOffset=a.borderDashOffset||l.borderDashOffset,r.lineJoin=a.borderJoinStyle||l.borderJoinStyle,r.lineWidth=a.borderWidth||l.borderWidth,r.strokeStyle=a.borderColor||h.defaultColor,r.beginPath(),u=-1,t=0;t=t.left&&1.01*t.right>=n.x&&n.y>=t.top&&1.01*t.bottom>=n.y)&&(i.strokeStyle=e.borderColor||h,i.lineWidth=d.valueOrDefault(e.borderWidth,u.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||h,d.canvas.drawPoint(i,a,o,s,l,r))}})},{26:26,27:27,46:46}],40:[function(t,e,n){"use strict";var i=t(26),a=t(27);function l(t){return void 0!==t._view.width}function r(t){var e,n,i,a,r=t._view;if(l(t)){var o=r.width/2;e=r.x-o,n=r.x+o,i=Math.min(r.y,r.base),a=Math.max(r.y,r.base)}else{var s=r.height/2;e=Math.min(r.x,r.base),n=Math.max(r.x,r.base),i=r.y-s,a=r.y+s}return{left:e,top:i,right:n,bottom:a}}i._set("global",{elements:{rectangle:{backgroundColor:i.global.defaultColor,borderColor:i.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a,r,o,s=this._chart.ctx,l=this._view,u=l.borderWidth;if(o=l.horizontal?(t=l.base,e=l.x,n=l.y-l.height/2,i=l.y+l.height/2,a=t=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){if(!this._view)return!1;var n=r(this);return l(this)?t>=n.left&&t<=n.right:e>=n.top&&e<=n.bottom},inXRange:function(t){var e=r(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=r(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return e=l(this)?(t=n.x,(n.y+n.base)/2):(t=(n.x+n.base)/2,n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{26:26,27:27}],41:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(37),e.exports.Line=t(38),e.exports.Point=t(39),e.exports.Rectangle=t(40)},{37:37,38:38,39:39,40:40}],42:[function(t,e,n){"use strict";var i=t(43);n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,a/2-1e-7,i/2-1e-7);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.arcTo(e+i,n,e+i,n+o,o),t.lineTo(e+i,n+a-o),t.arcTo(e+i,n+a,e+i-o,n+a,o),t.lineTo(e+o,n+a),t.arcTo(e,n+a,e,n+a-o,o),t.lineTo(e,n+o),t.arcTo(e,n,e+o,n,o),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a,r){var o,s,l,u,d,h;if(r=r||0,!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(t.save(),t.translate(i,a),t.rotate(r*Math.PI/180),t.beginPath(),e){default:t.arc(0,0,n,0,2*Math.PI),t.closePath();break;case"triangle":d=(s=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(-s/2,d/3),t.lineTo(s/2,d/3),t.lineTo(0,-2*d/3),t.closePath();break;case"rect":h=1/Math.SQRT2*n,t.rect(-h,-h,2*h,2*h);break;case"rectRounded":var c=n/Math.SQRT2,f=-c,g=-c,m=Math.SQRT2*n;this.roundedRect(t,f,g,m,m,.425*n);break;case"rectRot":h=1/Math.SQRT2*n,t.moveTo(-h,0),t.lineTo(0,h),t.lineTo(h,0),t.lineTo(0,-h),t.closePath();break;case"cross":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0);break;case"crossRot":l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"star":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0),l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"line":t.moveTo(-n,0),t.lineTo(n,0);break;case"dash":t.moveTo(0,0),t.lineTo(n,0)}t.fill(),t.stroke(),t.restore()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments)}},{43:43}],43:[function(t,e,n){"use strict";var i,d={noop:function(){},uid:(i=0,function(){return i++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return d.valueOrDefault(d.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,i){var a,r,o;if(d.isArray(t))if(r=t.length,i)for(a=r-1;0<=a;a--)e.call(n,t[a],a);else for(a=0;a
';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var o=function(){e._reset(),t()};return y(a,"scroll",o.bind(a,"expand")),y(r,"scroll",o.bind(r,"shrink")),e}((r=!(i=function(){if(h.resizer)return t(x("resize",n))}),o=[],function(){o=Array.prototype.slice.call(arguments),a=a||this,r||(r=!0,f.requestAnimFrame.call(window,function(){r=!1,i.apply(a,o)}))}));l=function(){if(h.resizer){var t=e.parentNode;t&&t!==c.parentNode&&t.insertBefore(c,t.firstChild),c._reset()}},u=(s=e)[g]||(s[g]={}),d=u.renderProxy=function(t){t.animationName===v&&l()},f.each(b,function(t){y(s,t,d)}),u.reflow=!!s.offsetParent,s.classList.add(p)}function r(t){var e,n,i,a=t[g]||{},r=a.resizer;delete a.resizer,n=(e=t)[g]||{},(i=n.renderProxy)&&(f.each(b,function(t){o(e,t,i)}),delete n.renderProxy),e.classList.remove(p),r&&r.parentNode&&r.parentNode.removeChild(r)}e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,n,i="from{opacity:0.99}to{opacity:1}";e="@-webkit-keyframes "+v+"{"+i+"}@keyframes "+v+"{"+i+"}."+p+"{-webkit-animation:"+v+" 0.001s;animation:"+v+" 0.001s;}",n=(t=this)._style||document.createElement("style"),t._style||(e="/* Chart.js */\n"+e,(t._style=n).setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(function(t,e){var n=t.style,i=t.getAttribute("height"),a=t.getAttribute("width");if(t[g]={initial:{height:i,width:a,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===a||""===a){var r=l(t,"width");void 0!==r&&(t.width=r)}if(null===i||""===i)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var o=l(t,"height");void 0!==r&&(t.height=o)}}(t,e),n):null},releaseContext:function(t){var n=t.canvas;if(n[g]){var i=n[g].initial;["height","width"].forEach(function(t){var e=i[t];f.isNullOrUndef(e)?n.removeAttribute(t):n.setAttribute(t,e)}),f.each(i.style||{},function(t,e){n.style[e]=t}),n.width=n.width,delete n[g]}},addEventListener:function(r,t,o){var e=r.canvas;if("resize"!==t){var n=o[g]||(o[g]={});y(e,t,(n.proxies||(n.proxies={}))[r.id+"_"+t]=function(t){var e,n,i,a;o((n=r,i=s[(e=t).type]||e.type,a=f.getRelativePosition(e,n),x(i,n,a.x,a.y,e)))})}else a(e,o,r)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[g]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else r(i)}},f.addEvent=y,f.removeEvent=o},{46:46}],49:[function(t,e,n){"use strict";var i=t(46),a=t(47),r=t(48),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{46:46,47:47,48:48}],50:[function(t,e,n){"use strict";e.exports={},e.exports.filler=t(51),e.exports.legend=t(52),e.exports.title=t(53)},{51:51,52:52,53:53}],51:[function(t,e,n){"use strict";var u=t(26),c=t(41),d=t(46);u._set("global",{plugins:{filler:{propagate:!0}}});var f={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e');for(var n=0;n'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("");return e.push(""),e.join("")}});var o=i.extend({initialize:function(t){C.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:function(){var e=this,n=e.options.labels||{},t=C.callback(n.generateLabels,[e.chart],e)||[];n.filter&&(t=t.filter(function(t){return n.filter(t,e.chart.data)})),e.options.reverse&&t.reverse(),e.legendItems=t},afterBuildLabels:r,beforeFit:r,fit:function(){var i=this,t=i.options,a=t.labels,e=t.display,r=i.ctx,n=D.global,o=C.valueOrDefault,s=o(a.fontSize,n.defaultFontSize),l=o(a.fontStyle,n.defaultFontStyle),u=o(a.fontFamily,n.defaultFontFamily),d=C.fontString(s,l,u),h=i.legendHitBoxes=[],c=i.minSize,f=i.isHorizontal();if(c.height=f?(c.width=i.maxWidth,e?10:0):(c.width=e?10:0,i.maxHeight),e)if(r.font=d,f){var g=i.lineWidths=[0],m=i.legendItems.length?s+a.padding:0;r.textAlign="left",r.textBaseline="top",C.each(i.legendItems,function(t,e){var n=P(a,s)+s/2+r.measureText(t.text).width;g[g.length-1]+n+a.padding>=i.width&&(m+=s+a.padding,g[g.length]=i.left),h[e]={left:0,top:0,width:n,height:s},g[g.length-1]+=n+a.padding}),c.height+=m}else{var p=a.padding,v=i.columnWidths=[],b=a.padding,y=0,x=0,_=s+p;C.each(i.legendItems,function(t,e){var n=P(a,s)+s/2+r.measureText(t.text).width;x+_>c.height&&(b+=y+a.padding,v.push(y),x=y=0),y=Math.max(y,n),x+=_,h[e]={left:0,top:0,width:n,height:s}}),b+=y,v.push(y),c.width+=b}i.width=c.width,i.height=c.height},afterFit:r,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var h=this,c=h.options,f=c.labels,g=D.global,m=g.elements.line,p=h.width,v=h.lineWidths;if(c.display){var b,y=h.ctx,x=C.valueOrDefault,t=x(f.fontColor,g.defaultFontColor),_=x(f.fontSize,g.defaultFontSize),e=x(f.fontStyle,g.defaultFontStyle),n=x(f.fontFamily,g.defaultFontFamily),i=C.fontString(_,e,n);y.textAlign="left",y.textBaseline="middle",y.lineWidth=.5,y.strokeStyle=t,y.fillStyle=t,y.font=i;var k=P(f,_),w=h.legendHitBoxes,M=h.isHorizontal();b=M?{x:h.left+(p-v[0])/2,y:h.top+f.padding,line:0}:{x:h.left+f.padding,y:h.top+f.padding,line:0};var S=_+f.padding;C.each(h.legendItems,function(t,e){var n,i,a,r,o,s=y.measureText(t.text).width,l=k+_/2+s,u=b.x,d=b.y;M?p<=u+l&&(d=b.y+=S,b.line++,u=b.x=h.left+(p-v[b.line])/2):d+S>h.bottom&&(u=b.x=u+h.columnWidths[b.line]+f.padding,d=b.y=h.top+f.padding,b.line++),function(t,e,n){if(!(isNaN(k)||k<=0)){y.save(),y.fillStyle=x(n.fillStyle,g.defaultColor),y.lineCap=x(n.lineCap,m.borderCapStyle),y.lineDashOffset=x(n.lineDashOffset,m.borderDashOffset),y.lineJoin=x(n.lineJoin,m.borderJoinStyle),y.lineWidth=x(n.lineWidth,m.borderWidth),y.strokeStyle=x(n.strokeStyle,g.defaultColor);var i=0===x(n.lineWidth,m.borderWidth);if(y.setLineDash&&y.setLineDash(x(n.lineDash,m.borderDash)),c.labels&&c.labels.usePointStyle){var a=_*Math.SQRT2/2,r=a/Math.SQRT2,o=t+r,s=e+r;C.canvas.drawPoint(y,n.pointStyle,a,o,s)}else i||y.strokeRect(t,e,k,_),y.fillRect(t,e,k,_);y.restore()}}(u,d,t),w[e].left=u,w[e].top=d,n=t,i=s,r=k+(a=_/2)+u,o=d+a,y.fillText(n.text,r,o),n.hidden&&(y.beginPath(),y.lineWidth=2,y.moveTo(r,o),y.lineTo(r+i,o),y.stroke()),M?b.x+=l+f.padding:b.y+=S})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}});function s(t,e){var n=new o({ctx:t.ctx,options:e,chart:t});a.configure(t,n,e),a.addBox(t,n),t.legend=n}e.exports={id:"legend",_element:o,beforeInit:function(t){var e=t.options.legend;e&&s(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(C.mergeIf(e,D.global.legend),n?(a.configure(t,n,e),n.options=e):s(t,e)):n&&(a.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}},{26:26,27:27,31:31,46:46}],53:[function(t,e,n){"use strict";var _=t(26),i=t(27),k=t(46),a=t(31),r=k.noop;_._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var o=i.extend({initialize:function(t){k.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:r,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:r,beforeSetDimensions:r,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:r,beforeBuildLabels:r,buildLabels:r,afterBuildLabels:r,beforeFit:r,fit:function(){var t=k.valueOrDefault,e=this.options,n=e.display,i=t(e.fontSize,_.global.defaultFontSize),a=this.minSize,r=k.isArray(e.text)?e.text.length:1,o=k.options.toLineHeight(e.lineHeight,i),s=n?r*o+2*e.padding:0;this.isHorizontal()?(a.width=this.maxWidth,a.height=s):(a.width=s,a.height=this.maxHeight),this.width=a.width,this.height=a.height},afterFit:r,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this.ctx,e=k.valueOrDefault,n=this.options,i=_.global;if(n.display){var a,r,o,s=e(n.fontSize,i.defaultFontSize),l=e(n.fontStyle,i.defaultFontStyle),u=e(n.fontFamily,i.defaultFontFamily),d=k.fontString(s,l,u),h=k.options.toLineHeight(n.lineHeight,s),c=h/2+n.padding,f=0,g=this.top,m=this.left,p=this.bottom,v=this.right;t.fillStyle=e(n.fontColor,i.defaultFontColor),t.font=d,this.isHorizontal()?(r=m+(v-m)/2,o=g+c,a=v-m):(r="left"===n.position?m+c:v-c,o=g+(p-g)/2,a=p-g,f=Math.PI*("left"===n.position?-.5:.5)),t.save(),t.translate(r,o),t.rotate(f),t.textAlign="center",t.textBaseline="middle";var b=n.text;if(k.isArray(b))for(var y=0,x=0;xo.max&&(o.max=n))})});o.min=isFinite(o.min)&&!isNaN(o.min)?o.min:0,o.max=isFinite(o.max)&&!isNaN(o.max)?o.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var n=h.valueOrDefault(e.fontSize,i.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*n)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this.start,n=+this.getRightValue(t),i=this.end-e;return this.isHorizontal()?this.left+this.width/i*(n-e):this.bottom-this.height/i*(n-e)},getValueForPixel:function(t){var e=this.isHorizontal(),n=e?this.width:this.height,i=(e?t-this.left:this.bottom-t)/n;return this.start+(this.end-this.start)*i},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});a.registerScaleType("linear",n,e)}},{26:26,34:34,35:35,46:46}],56:[function(t,e,n){"use strict";var h=t(46),i=t(33);e.exports=function(t){var e=h.noop;t.LinearScaleBase=i.extend({getRightValue:function(t){return"string"==typeof t?+t:i.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=h.sign(t.min),i=h.sign(t.max);n<0&&i<0?t.max=0:0=t.max&&(a?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),i={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:h.valueOrDefault(e.fixedStepSize,e.stepSize)},a=t.ticks=function(t,e){var n,i,a,r=[];if(t.stepSize&&0o.max&&(o.max=n),0!==n&&(null===o.minNotZero||no.r&&(o.r=g.end,s.r=c),m.starto.b&&(o.b=m.end,s.b=c)}t.setReductions(r,o,s)}(this):(t=this,e=Math.min(t.height/2,t.width/2),t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0))},setReductions:function(t,e,n){var i=e.l/Math.sin(n.l),a=Math.max(e.r-this.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),o=-Math.max(e.b-this.height,0)/Math.cos(n.b);i=s(i),a=s(a),r=s(r),o=s(o),this.drawingArea=Math.min(Math.round(t-(i+a)/2),Math.round(t-(r+o)/2)),this.setCenterPoint(i,a,r,o)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-i-a.drawingArea;a.xCenter=Math.round((o+r)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/b(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){if(null===t)return 0;var e=this.drawingArea/(this.max-this.min);return this.options.ticks.reverse?(this.max-t)*e:(t-this.min)*e},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(n)*e)+this.xCenter,y:Math.round(Math.sin(n)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:0>1)-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e],l=s?(n-r[e])/s:0,u=(o[i]-r[i])*l;return r[i]+u}function M(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?y(t,i):(t instanceof y||(t=y(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function S(t,e){if(p.isNullOrUndef(t))return null;var n=e.options.time,i=M(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function D(t){for(var e=_.indexOf(t)+1,n=_.length;e=_.indexOf(e);a--)if(r=_[a],x[r].common&&o.as(r)>=t.length)return r;return _[e?_.indexOf(e):0]}(b,p.minUnit,c.min,c.max),c._majorUnit=D(c._unit),c._table=function(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a + * @copyright Copyright (C) 2009 - 2018 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access. +defined('_JEXEC') or die; + +jimport('joomla.plugin.plugin'); +JLoader::import('components.com_tjreports.models.report', JPATH_SITE); + +/** + * Tjreports API plugin + * + * @since 1.0 + */ +class PlgAPIReports extends ApiPlugin +{ + /** + * Constructor + * + * @param STRING &$subject subject + * @param array $config config + * + * @since 1.0 + */ + public function __construct(&$subject, $config = array()) + { + parent::__construct($subject, $config = array()); + + // Set resource path + ApiResource::addIncludePath(dirname(__FILE__) . '/reports'); + + // Load language files + $lang = JFactory::getLanguage(); + $lang->load('plg_api_reports', JPATH_SITE . "/plugins/api/reports/", 'en-GB', true); + } +} diff --git a/tjreports/plugins/api/reports/reports.xml b/tjreports/plugins/api/reports/reports.xml new file mode 100644 index 0000000..6bf8411 --- /dev/null +++ b/tjreports/plugins/api/reports/reports.xml @@ -0,0 +1,21 @@ + + + PLG_API_REPORTS + 1.0 + 28th May 2018 + Techjoomla + extensions@techjoomla.com + https://techjoomla.com + Techjoomla. All rights reserved. + http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + PLG_API_REPORTS_DESCRIPTION + + reports.php + reports + language + + + en-GB/en-GB.plg_api_reports.ini + en-GB/en-GB.plg_api_reports.sys.ini + + diff --git a/tjreports/plugins/api/reports/reports/filters.php b/tjreports/plugins/api/reports/reports/filters.php new file mode 100644 index 0000000..76226e5 --- /dev/null +++ b/tjreports/plugins/api/reports/reports/filters.php @@ -0,0 +1,63 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access. +defined('_JEXEC') or die; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; + +/** + * Tjreports API report class + * + * @since 1.0.0 + */ +class ReportsApiResourceFilters extends ApiResource +{ + /** + * Function get filters data + * + * @return boolean + */ + public function get() + { + $app = Factory::getApplication(); + $jinput = $app->input; + $reportName = $jinput->getString('id'); + + if (!isset($reportName)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_MISSSING'), 'APIValidationException'); + } + + $lang = Factory::getLanguage(); + //load default joomla language file + $lang->load('', JPATH_ADMINISTRATOR, 'en-GB', true); + + // Make object of the tjreports plugin to load filters for + JLoader::import('plugins.tjreports.' . $reportName . "." . $reportName, JPATH_SITE); + $className = 'TjreportsModel' . ucfirst($reportName); + + if (!class_exists($className)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_INVALID'), 'APIValidationException'); + } + + $reportPlugin = new $className; + + $filters = $reportPlugin->displayFilters(); + $filter_array = []; + foreach ($filters[0] as $key => $value) { + $value['name'] = $key; + $filter_array[] = $value; + } + + $this->plugin->setResponse($filter_array); + } +} diff --git a/tjreports/plugins/api/reports/reports/gdsfields.php b/tjreports/plugins/api/reports/reports/gdsfields.php new file mode 100644 index 0000000..5115102 --- /dev/null +++ b/tjreports/plugins/api/reports/reports/gdsfields.php @@ -0,0 +1,69 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access. +defined('_JEXEC') or die; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; + +/** + * Tjreports API Gs fields class + * This is used to get the fields for the Google studio connector + * + * @since __DEPLOY_VERSION__ + */ +class ReportsApiResourceGdsfields extends ApiResource +{ + /** + * Function to get fields + * + * @return json + */ + public function get() + { + $app = Factory::getApplication(); + $jinput = $app->input; + $reportName = $app->input->getString('id'); + + if (empty($reportName)) + { + $reportName = $app->input->getString('report'); + } + + if (!isset($reportName)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_MISSSING'), 'APIValidationException'); + } + + // Create object of tjreports plugin class + JLoader::import('plugins.tjreports.' . $reportName . "." . $reportName, JPATH_SITE); + $className = 'TjreportsModel' . ucfirst($reportName); + + if (!class_exists($className)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_INVALID'), 'APIValidationException'); + } + + $reportPlugin = new $className; + + // If plugin does not have getGoogleDsFields throw error + if (!method_exists($reportPlugin, 'getGDSFields')) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NO_GOOGLESTUDIO_SUPPORT'), 'APIValidationException'); + } + + // Load language files + $lang = Factory::getLanguage(); + $lang->load('com_tjreports', JPATH_ADMINISTRATOR, 'en-GB', true); + $lang->load('plg_tjreports_' . $reportName, JPATH_SITE . "/plugins/tjreports/" . $reportName, 'en-GB', true); + + $this->plugin->setResponse($reportPlugin->getGDSFields()); + } +} diff --git a/tjreports/plugins/api/reports/reports/gdsreports.php b/tjreports/plugins/api/reports/reports/gdsreports.php new file mode 100644 index 0000000..25f2056 --- /dev/null +++ b/tjreports/plugins/api/reports/reports/gdsreports.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access. +defined('_JEXEC') or die; +use Joomla\CMS\Factory; + +/** + * Tjreports API to get the tjreports plugin those support Google studio connector + * + * @since __DEPLOY_VERSION__ + */ +class ReportsApiResourceGdsreports extends ApiResource +{ + /** + * Function get reports + * + * @return boolean + */ + public function get() + { + // Create object of tjreports plugin class + JLoader::import('components.com_tjreports.models.reports', JPATH_SITE); + $reportModel = new TjreportsModelreports; + + $reports = $reportModel->getenableReportPlugins(); + $reportsArray = array(); + + foreach ($reports as $report) + { + $pluginModel = $reportModel->getPluginModel($report['plugin']); + + if (method_exists($pluginModel, 'getGDSFields')) + { + $reportsArray[] = $report; + } + } + + $this->plugin->setResponse($reportsArray); + } +} diff --git a/tjreports/plugins/api/reports/reports/report.php b/tjreports/plugins/api/reports/reports/report.php new file mode 100644 index 0000000..d9eeac0 --- /dev/null +++ b/tjreports/plugins/api/reports/reports/report.php @@ -0,0 +1,103 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// No direct access. +defined('_JEXEC') or die; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; + +/** + * Tjreports API report class + * + * @since 1.0.0 + */ +class ReportsApiResourceReport extends ApiResource +{ + /** + * Function to get report data from tjreports plugin + * + * @return json + */ + public function post() + { + $app = Factory::getApplication(); + $jinput = $app->input; + $formData = $jinput->post; + $reportName = $app->input->getString('id'); + + if (empty($reportName)) + { + $reportName = $formData->getString('report'); + } + + if (!isset($reportName)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_MISSSING'), 'APIValidationException'); + } + + // Create object of tjreports plugin class + + JLoader::import('plugins.tjreports.' . $reportName . "." . $reportName, JPATH_SITE); + $className = 'TjreportsModel' . ucfirst($reportName); + + if (!class_exists($className)) + { + ApiError::raiseError(400, Text::_('PLG_API_REPORTS_REPORT_NAME_INVALID'), 'APIValidationException'); + } + + $reportPlugin = new $className; + + // Load language files + $lang = Factory::getLanguage(); + $lang->load('com_tjreports', JPATH_ADMINISTRATOR, 'en-GB', true); + $lang->load('plg_tjreports_' . $reportName, JPATH_SITE . "/plugins/tjreports/" . $reportName, 'en-GB', true); + + // Get filters and cols + $reportId = $reportPlugin->getDefaultReport($reportName); + $reportFilters = ($formData->get('filters')) ? $formData->get('filters') : []; + $reportCols = ($formData->get('colToshow')) ? $formData->get('colToshow') : []; + + // Set reportId in input + $app->input->set('reportId', $reportId); + + $reportPlugin->setState('filters', $reportFilters); + $reportPlugin->setState('colToshow', $reportCols); + $reportPlugin->setState('reportId', $reportId); + + // Get results and errors if any + $report = $reportPlugin->getItems(); + $errors = $reportPlugin->getTJRMessages(); + + if (!empty($errors)) + { + ApiError::raiseError(400, $errors[0], 'APIValidationException'); + } + + // @TODO Handle else condition first to reduce nesting + if (!empty($reportCols)) + { + foreach ($report as $key => $value) + { + foreach ($value as $k => $v) + { + if (!in_array($k, $reportCols)) + { + unset($value[$k]); + } + } + + $report[$key] = $value; + } + } + + $this->plugin->customAttributes->set("total", $reportPlugin->getTotal()); + $this->plugin->setResponse($report); + } +} diff --git a/tjreports/plugins/user/tjreportsindexer/sql/tjreportsindexer.install.sql b/tjreports/plugins/user/tjreportsindexer/sql/tjreportsindexer.install.sql index d79fa56..73b2844 100755 --- a/tjreports/plugins/user/tjreportsindexer/sql/tjreportsindexer.install.sql +++ b/tjreports/plugins/user/tjreportsindexer/sql/tjreportsindexer.install.sql @@ -1,5 +1,6 @@ CREATE TABLE IF NOT EXISTS `#__tjreports_com_users_user` ( `record_id` int(11) NOT NULL, `username_hash` VARCHAR(100) NOT NULL, - `email_hash` VARCHAR(100) NOT NULL + `email_hash` VARCHAR(100) NOT NULL, + KEY `record_id` (`record_id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/tjreports/plugins/user/tjreportsindexer/sql/updates/mysql/1.1.5.sql b/tjreports/plugins/user/tjreportsindexer/sql/updates/mysql/1.1.5.sql new file mode 100644 index 0000000..a084750 --- /dev/null +++ b/tjreports/plugins/user/tjreportsindexer/sql/updates/mysql/1.1.5.sql @@ -0,0 +1 @@ +ALTER TABLE `#__tjreports_com_users_user` ADD KEY `record_id` (`record_id`); diff --git a/tjreports/plugins/user/tjreportsindexer/tjreportsindexer.php b/tjreports/plugins/user/tjreportsindexer/tjreportsindexer.php index e43c79d..2a93064 100644 --- a/tjreports/plugins/user/tjreportsindexer/tjreportsindexer.php +++ b/tjreports/plugins/user/tjreportsindexer/tjreportsindexer.php @@ -48,6 +48,12 @@ class PlgUserTjreportsindexer extends JPlugin */ public function onUserAfterSave($user, $isNew, $success, $msg) { + // If com_fields data is not in user data it should return. + if (!array_key_exists('com_fields', $user)) + { + return false; + } + // Delete existing user-data entry // Here record_id = user_id $this->deleteIndexerEntry($user['id']); @@ -129,9 +135,10 @@ protected function addIndexerEntry($user) continue; } - if ($fieldsDetails[$key]->type !== 'url') + // If select multiple values save as comma-separated. + if (is_array($fieldsDetails[$key]->rawvalue)) { - $value = $fieldsDetails[$key]->value; + $value = implode(', ', $fieldsDetails[$key]->rawvalue); } else { @@ -143,7 +150,7 @@ protected function addIndexerEntry($user) } // Add username & email hash values - array_push($columns, 'username_hash', 'email_hash'); + array_push($columns, $db->quoteName('username_hash'), $db->quoteName('email_hash')); array_push($values, "'" . md5($user['username']) . "'", "'" . md5($user['email']) . "'"); // Prepare the insert query diff --git a/tjreports/script.tjreports.php b/tjreports/script.tjreports.php index 7d95be2..1585029 100755 --- a/tjreports/script.tjreports.php +++ b/tjreports/script.tjreports.php @@ -59,6 +59,9 @@ class Com_TjreportsInstallerScript ), 'user' => array( 'tjreportsindexer' => 0 + ), + 'api' => array( + 'reports' => 1 ) ) ); diff --git a/tjreports/site/assets/css/tjreports.css b/tjreports/site/assets/css/tjreports.css index 09b5a40..6427662 100755 --- a/tjreports/site/assets/css/tjreports.css +++ b/tjreports/site/assets/css/tjreports.css @@ -136,7 +136,7 @@ table.tjrport-table { } .report-tbl { - min-height: 450px; + min-height: 450px !important; overflow-x: auto; } @@ -310,3 +310,40 @@ table.tjrport-table { margin-left:0; } } + +/* Equal height cols */ +.m-0{margin: 0 !important;} +.equal-height-col { + display: flex; + flex-wrap: wrap; + margin-top: 20px; +} +.equal-height-col > .equal-items { + display: flex; + flex-direction: column; +} +.tj-card{ + border:1px solid #F0F0F0; + height: 100%; + -webkit-box-shadow: 0 1px 4px 0 rgba(0,0,0,.3); + -moz-box-shadow: 0 1px 4px 0 rgba(0,0,0,.3); + box-shadow: 0 1px 4px 0 rgba(0,0,0,.3); + border-radius: 5px; +} +.tj-card-title{ + border-bottom:1px solid #F0F0F0; + margin: 0 !important; + padding: 15px; + font-size: 15px; + font-weight: bold; +} +.tj-card-body{ + margin:15px 0; +} +.chartItems{ + margin-bottom: 30px; +} +.summaryReport{ + margin-top: 0px !important; +} + diff --git a/tjreports/site/assets/css/tjreports.min.css b/tjreports/site/assets/css/tjreports.min.css new file mode 100644 index 0000000..a3a0ece --- /dev/null +++ b/tjreports/site/assets/css/tjreports.min.css @@ -0,0 +1 @@ +.other-filters{padding:0 14px}.hasPopover{display:block!important}a[disabled]{pointer-events:none}.show-hide-cols{position:relative}.ColVis_collection{list-style:none;min-width:150px;padding:8px 8px 4px 8px;margin:0;border:1px solid #ccc;border:1px solid rgba(0,0,0,.4);background-color:#f9f9f9;overflow:hidden;display:block;opacity:1;position:absolute;z-index:1}table#report-table .chzn-container{width:150px!important}ul#ul-columns-name li input{margin-top:0}ul#ul-columns-name li:hover label{background-color:#f0f0f0}ul#ul-columns-name li label{margin-bottom:0;padding-top:2px;padding-bottom:2px;cursor:pointer}div#report-containing-div{min-height:450px}div#reports-container .form-inline-header .controls{padding-right:5px}div#topFilters div.filter-search{display:inline-block;float:left;margin-right:5px}div#topFilters{margin-top:10px;float:left;width:100%}.ColVis_collection{display:none}#topFilters{display:none}#queryName{display:none}.header_title{display:inline-block}th.center:nth-child(odd){background-color:#d9edf7;border-left:1px solid #ddd}th.center:nth-child(even){background-color:#fcf8e3;border-left:1px solid #ddd}td.subdetails.lesson.attempts_done:nth-child(odd),th.subdetails.lesson.attempts_done:nth-child(odd){border-left:1px solid #ddd}table.tjrport-table{border-bottom:1px solid #ddd}#reportPagination .pagination.pagination-toolbar.clearfix{margin:0}#t3-content #report-table thead input{height:100%;max-width:120px}#t3-content #queryName{height:32px;font-size:14px}.report-top-bar{margin-top:10px}#t3-content .form-group{margin-bottom:15px}#reports-container h2{font-weight:500}#t3-mainbody #reports-container .field-calendar .tjrsmall-input{display:inline-block;height:32px!important;max-width:165px;font-size:14px}.report-tbl{min-height:450px!important;overflow-x:auto}#t3-mainbody #report-containing-div .table-responsive{margin-top:20px}#t3-content #reports-container .btn{padding:4px 12px;text-transform:none;font-size:14px}#t3-mainbody #report-table .custom-group{display:table;border-collapse:separate;margin-bottom:0}#content div.row{margin-left:0;margin-right:0}#t3-mainbody #report-table .custom-group-btn{vertical-align:baseline}.t3-content .btn-custom{color:#fff;background-color:#337ab7;border-color:#2e6da4}.t3-content .btn-custom:hover{color:#fff;background-color:#286090;border-color:#204d74}.t3-content .btn-custom:active{color:#fff;background-color:#286090;border-color:#204d74}.t3-content .btn-custom:focus{color:#fff;background-color:#286090;border-color:#204d74}.t3-content .btn-custom.active.focus,.t3-content .btn-custom.active:focus,.t3-content .btn-custom.active:hover,.t3-content .btn-custom:active.focus,.t3-content .btn-custom:active:focus,.t3-content .btn-custom:active:hover{color:#fff;background-color:#204d74;border-color:#122b40}#t3-content.chzn-container-single .chzn-single{height:32px;border-radius:0;background:no-repeat;padding-left:15px}#t3-content #report-table .chzn-container-single .chzn-single span,b{margin-top:3px}#t3-content .filter-search .chzn-container-single .chzn-single{height:32px;border-radius:0;background:no-repeat;padding-left:15px}#t3-content .filter-search .chzn-container-single .chzn-single b,#t3-content .filter-search .chzn-container-single .chzn-single span{margin-top:3px}#reports-container .ordering-select .input-group-btn,#t3-content #report-table .input-group-btn{width:0}.ordering-select a.chzn-single,.view-reports select{height:35px!important}#reports-container .input-append .field-calendar{font-size:14px}#reports-container .input-group .field-calendar .input-append,.view-reports .j-toggle-main input[type=text]{margin-bottom:0}#reports-container .filter-search .input-group-btn{border:1px solid #ccc;border-radius:0}.table-responsive.report-tbl .js-calendar{margin-top:0!important}.view-reports .chzn-container .chzn-single,.view-reports a.btn,.view-reports button,.view-reports button.btn,.view-reports input[type=button],.view-reports input[type=text],.view-reports select{height:35px;padding-top:6px!important;padding-bottom:6px!important;border-radius:0!important;box-shadow:none;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;line-height:18px!important}.view-reports #toolbar [class^=icon-]{height:28px;padding-top:5px!important}.view-reports #toolbar .export{padding-top:0!important;padding-bottom:0!important}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.show-hide-cols{margin-bottom:20px}#show-hide-cols-btn{width:100%}#queryName{margin-bottom:10px!important}.btn-csv{margin-bottom:20px}#t3-content #report-table .input-append input,#t3-content #report-table .input-append select{margin-bottom:0!important;width:auto}}@media screen and (max-width:768px){#t3-content #show-filter{margin-bottom:20px}#filterscourse_id,.ordering-select #filtersreport_filter{margin-bottom:20px}}@media (max-width:1024px) and (min-width:768px){.t3-content .row-fluid [class*=span]{margin-left:0}}.m-0{margin:0!important}.equal-height-col{display:flex;flex-wrap:wrap;margin-top:20px}.equal-height-col>.equal-items{display:flex;flex-direction:column}.tj-card{border:1px solid #f0f0f0;height:100%;-webkit-box-shadow:0 1px 4px 0 rgba(0,0,0,.3);-moz-box-shadow:0 1px 4px 0 rgba(0,0,0,.3);box-shadow:0 1px 4px 0 rgba(0,0,0,.3);border-radius:5px}.tj-card-title{border-bottom:1px solid #f0f0f0;margin:0!important;padding:15px;font-size:15px;font-weight:700}.tj-card-body{margin:15px 0}.chartItems{margin-bottom:30px}.summaryReport{margin-top:0!important} diff --git a/tjreports/site/assets/js/tjrContentService.min.js b/tjreports/site/assets/js/tjrContentService.min.js new file mode 100644 index 0000000..d5c040d --- /dev/null +++ b/tjreports/site/assets/js/tjrContentService.min.js @@ -0,0 +1 @@ +var tjrContentService={postData:function(t,e,a){return a||(a={}),a.url=this.getBaseUrl()+t,a.data=e,a.type=void 0!==a.type?a.type:"POST",a.async=void 0===a.async||a.async,a.dataType=void 0!==a.datatype?a.datatype:"json",jQuery.ajax(a)},getBaseUrl:function(){return"undefined"!=typeof tjrContentUI?tjrContentUI.base_url:""}}; diff --git a/tjreports/site/assets/js/tjrContentUI.js b/tjreports/site/assets/js/tjrContentUI.js index a76c1af..6fcc4a5 100755 --- a/tjreports/site/assets/js/tjrContentUI.js +++ b/tjreports/site/assets/js/tjrContentUI.js @@ -19,6 +19,30 @@ jQuery.extend(tjrContentUI.report, { url: 'index.php?option=com_tjreports&view=reports&format=json', querySaveUrl: 'index.php?option=com_tjreports&format=json', submitTJRData: function(task) { + + // Set the view layout on the basis of task + task = (typeof task == 'undefined' ) ? 'default' : task; + + // Default layout + + var layout = 'default'; + + if (task == "summary") + { + layout = 'summary'; + jQuery('#summaryReportLabel').addClass('btn-danger'); + jQuery('#detailsReportLabel').removeClass('btn-success'); + jQuery('#reportPagination').hide(); + jQuery('#pagination').hide(); + } + else + { + jQuery('#detailsReportLabel').removeClass('btn-success'); + jQuery('#summaryReportLabel').removeClass('btn-danger'); + jQuery('#reportPagination').show(); + jQuery('#pagination').show(); + } + jQuery('#reports-container .hasTooltip').tooltip('destroy'); this.searchToggle = jQuery('div#topFilters').is(':visible'); tjrContentUI.utility.loadingLayer('show'); @@ -28,7 +52,7 @@ jQuery.extend(tjrContentUI.report, { return false; } jQuery(".hasPopover").popover('destroy') - var promise = tjrContentService.postData(this.url, this.$form.serialize());//, {'datatype':'html'} + var promise = tjrContentService.postData(this.url+'&tpl='+layout, this.$form.serialize());//, {'datatype':'html'} promise.fail( function(response) { @@ -42,46 +66,56 @@ jQuery.extend(tjrContentUI.report, { } ).done( function(response) { - var containerSel = '#j-main-container'; + tjrContentUI.utility.loadingLayer('hide'); - var responseHTML = jQuery(response['html']).find(containerSel).html(); - jQuery(containerSel).html(responseHTML); - - // If sendEmail plug is enabled then try to add a column of checkboxes - if ( - typeof window.tjSendEmail != 'undefined' && - jQuery('body').find('.td-sendemail').length > 0 - ) + + if (layout == 'summary') { - window.tjemail = new window.tjSendEmail.UI("report-table", "td-sendemail", "cid"); + jQuery("#report-containing-div").html(response['html']); } + else + { + var containerSel = '#j-main-container'; + var responseHTML = jQuery(response['html']).find(containerSel).html(); + jQuery(containerSel).html(responseHTML); + + // If sendEmail plug is enabled then try to add a column of checkboxes + if ( + typeof tjutilitysendemail != 'undefined' && + jQuery('body').find('.td-sendemail').length > 0 + ) + { + tjutilitysendemail.addColumn('report-table'); + } - // Reinitialze some js like for calandar, tooltip, chosen - jQuery(".hasPopover").popover({"html": true,"trigger": "hover focus","container": "body"}); + // Reinitialze some js like for calandar, tooltip, chosen + jQuery(".hasPopover").popover({"html": true,"trigger": "hover focus","container": "body"}); - if (task == "showHide") - { - tjrContentUI.report.getColNames(); - } + if (task == "showHide") + { + tjrContentUI.report.getColNames(); + } - var elements = jQuery(containerSel + " .field-calendar"); - for (i = 0; i < elements.length; i++) { - JoomlaCalendar.init(elements[i]); - } + var elements = jQuery(containerSel + " .field-calendar"); + for (i = 0; i < elements.length; i++) { + JoomlaCalendar.init(elements[i]); + } - if(jQuery.prototype.chosen){ - jQuery(containerSel + ' select').chosen(); - } + if(jQuery.prototype.chosen){ + jQuery(containerSel + ' select').chosen(); + } - if (task == 'reset') - { - tjrContentUI.report.searchToggle = false; - } + if (task == 'reset') + { + tjrContentUI.report.searchToggle = false; + } - if (tjrContentUI.report.searchToggle) - { - jQuery('#show-filter').addClass('btn-primary').find('i').removeClass('fa-caret-down').addClass('fa-caret-up'); - jQuery('#topFilters').show(); + if (tjrContentUI.report.searchToggle) + { + jQuery('#show-filter').addClass('btn-primary').find('i').removeClass('fa-caret-down').addClass('fa-caret-up'); + jQuery('#topFilters').show(); + } + jQuery('.btn-displayReport').toggleClass('active btn-success'); } } ).always( diff --git a/tjreports/site/assets/js/tjrContentUI.min.js b/tjreports/site/assets/js/tjrContentUI.min.js new file mode 100644 index 0000000..b5dabfb --- /dev/null +++ b/tjreports/site/assets/js/tjrContentUI.min.js @@ -0,0 +1 @@ +if(void 0===tjrContentUI)var tjrContentUI={};tjrContentUI.root_url="undefined"==typeof root_url?"":root_url,tjrContentUI.base_url="undefined"==typeof root_url?"":root_url,tjrContentUI.report=tjrContentUI.report?tjrContentUI.report:{},jQuery.extend(tjrContentUI.report,{searchToggle:!0,$form:null,url:"index.php?option=com_tjreports&view=reports&format=json",querySaveUrl:"index.php?option=com_tjreports&format=json",submitTJRData:function(e){var t="default";if("summary"==(e=void 0===e?"default":e)?(t="summary",jQuery("#summaryReportLabel").addClass("btn-danger"),jQuery("#detailsReportLabel").removeClass("btn-success"),jQuery("#reportPagination").hide(),jQuery("#pagination").hide()):(jQuery("#detailsReportLabel").removeClass("btn-success"),jQuery("#summaryReportLabel").removeClass("btn-danger"),jQuery("#reportPagination").show(),jQuery("#pagination").show()),jQuery("#reports-container .hasTooltip").tooltip("destroy"),this.searchToggle=jQuery("div#topFilters").is(":visible"),tjrContentUI.utility.loadingLayer("show"),this.$form=jQuery("#adminForm"),!this.validate())return!1;jQuery(".hasPopover").popover("destroy"),tjrContentService.postData(this.url+"&tpl="+t,this.$form.serialize()).fail(function(e){console.log("Something went wrong."),tjrContentUI.utility.loadingLayer("hide"),403==e.status&&alert(Joomla.JText._("JERROR_ALERTNOAUTHOR"))}).done(function(r){if(tjrContentUI.utility.loadingLayer("hide"),"summary"==t)jQuery("#report-containing-div").html(r.html);else{var o=jQuery(r.html).find("#j-main-container").html();jQuery("#j-main-container").html(o),"undefined"!=typeof tjutilitysendemail&&jQuery("body").find(".td-sendemail").length>0&&tjutilitysendemail.addColumn("report-table"),jQuery(".hasPopover").popover({html:!0,trigger:"hover focus",container:"body"}),"showHide"==e&&tjrContentUI.report.getColNames();var n=jQuery("#j-main-container .field-calendar");for(i=0;i").html(e);return t.find("script").remove(),e=t.html()},displayMessage:function(e,t,r){this.parent.validation.messages={},this.parent.validation.addMessage(e,t),this.displayMessages()},displayMessages:function(e){Joomla.removeMessages(),Joomla.renderMessages(this.parent.validation.messages),e&&jQuery("body").animate({scrollTop:jQuery("#system-message-container").offset().top},500)},setJSCookie:function(e,t,r){var o="";if(r){var n=new Date;n.setTime(n.getTime()+24*r*60*60*1e3),o="; expires="+n.toUTCString()}document.cookie=e+"="+t+o+"; path=/"},getJSCookie:function(e){for(var t=e+"=",r=document.cookie.split(";"),o=0;oemailColumn = array_search( - 1, array_map( - function ($ar) { - if (!empty($ar['emailColumn'])) - { - return $ar['emailColumn']; - } - }, $this->columns - ) + 1, + array_map( + function ($ar) + { + if (!empty($ar['emailColumn'])) + { + return $ar['emailColumn']; + } + }, + $this->columns + ) ); // Check PII data permission @@ -154,7 +184,7 @@ protected function setCustomFieldsColumns() } // Get column name, type for custom fields index table - $db = JFactory::getDbo(); + $db = Factory::getDbo(); $columnsDetails = $db->getTableColumns($this->customFieldsTable); // If no columns, return @@ -179,9 +209,9 @@ protected function setCustomFieldsColumns() foreach ($columnNames as $columnName) { $customField = array ( - 'title' => ($columnLabels[$columnName]) ? $columnLabels[$columnName] : $columnName, - 'table_column' => $this->customFieldsTableAlias . '.' . $columnName, - 'not_show_hide' => false + 'title' => isset($columnLabels[$columnName]) ? $columnLabels[$columnName] : $columnName, + 'table_column' => $this->customFieldsTableAlias . '.' . $columnName, + 'not_show_hide' => false ); // Eg. tuf.dob @@ -214,7 +244,7 @@ protected function setCustomFieldsDisplayFilters(&$displayFilters) } // Get column name, type for custom fields index table - $db = JFactory::getDbo(); + $db = Factory::getDbo(); $columnsDetails = $db->getTableColumns($this->customFieldsTable); // If no columns, return @@ -275,13 +305,13 @@ protected function setCustomFieldsDisplayFilters(&$displayFilters) $this->customFieldsTableAlias . '.' . $key . '_from' => array ( 'attrib' => array ( 'placeholder' => 'YYYY-MM-DD', - 'onChange' => 'tjrContentUI.report.attachCalSubmit(this);' + 'onChange' => 'tjrContentUI.report.attachCalSubmit(this);' ) ), $this->customFieldsTableAlias . '.' . $key . '_to' => array ( 'attrib' => array ( 'placeholder' => 'YYYY-MM-DD', - 'onChange' => 'tjrContentUI.report.attachCalSubmit(this);' + 'onChange' => 'tjrContentUI.report.attachCalSubmit(this);' ) ) ); @@ -328,14 +358,14 @@ protected function setCustomFieldsDisplayFilters(&$displayFilters) */ protected function getCustomFieldsDisplayFilterOptions($column) { - $objArray = array(); - $obj = new stdClass; - $obj->text = JText::_('- Select ' . $column . ' -'); - $obj->value = ''; - $objArray[] = $obj; + $objArray = array(); + $obj = new stdClass; + $obj->text = Text::_('- Select ' . $column . ' -'); + $obj->value = ''; + $objArray[] = $obj; // Get column name, type for custom fields index table - $db = JFactory::getDbo(); + $db = Factory::getDbo(); // Get column labels from #__fields table for all indexed custom fields from this table $query = $db->getQuery(true); @@ -359,10 +389,11 @@ protected function getCustomFieldsDisplayFilterOptions($column) * */ private function initData() { - $columns = $this->columns; - $columnsKeys = array_keys($columns); + $columns = $this->columns; + $columnsKeys = array_keys($columns); + $this->sortableWoQuery = array(); + $this->defaultColToShow = $this->sortableColumns = $this->showhideCols = array_combine($columnsKeys, $columnsKeys); - $this->sortableWoQuery = array(); foreach ($columns as $key => $column) { @@ -430,9 +461,12 @@ public function getTJRMessages() public function getValidRequestVars() { $validVars = array( - 'colToshow' => 'ARRAY', 'filters' => 'ARRAY', - 'limit' => 'INT', 'limitstart' => 'INT', - 'filter_order' => 'STRING', 'filter_order_Dir' => 'STRING' + 'colToshow' => 'ARRAY', + 'filters' => 'ARRAY', + 'limit' => 'INT', + 'limitstart' => 'INT', + 'filter_order' => 'STRING', + 'filter_order_Dir' => 'STRING' ); return $validVars; @@ -524,8 +558,8 @@ protected function _getList($query, $limitstart = 0, $limit = 0) protected function populateState($ordering = '', $direction = 'ASC') { // List state information - $app = JFactory::getApplication(); - $input = JFactory::getApplication()->input; + $app = Factory::getApplication(); + $input = $app->input; if (!($reportId = $input->get('reportId', 0, 'uint'))) { @@ -542,13 +576,13 @@ protected function populateState($ordering = '', $direction = 'ASC') if (empty($colToshow)) { $reportParams = $this->getReportParams($reportId); - - $colToshow = $reportParams->get("colToshow"); - $piiColumns = array_flip($reportParams->get("piiColumns")); + $colToshow = (array) $reportParams->get("colToshow"); + $piiColumns = (array) $reportParams->get("piiColumns"); + $piiColumns = array_flip($piiColumns); if (!empty($piiColumns)) { - $colToshow = (object) array_diff_key((array) $colToshow, $piiColumns); + $colToshow = (object) array_diff_key($colToshow, $piiColumns); } } @@ -561,16 +595,22 @@ protected function populateState($ordering = '', $direction = 'ASC') $this->setState('colToshow', $colToshow); - $filters = $input->get('filters', array(), 'ARRAY'); + $filters = $input->get('filters', array(), 'ARRAY'); $this->setState('filters', $filters); // List state information - $value = $input->get('limit', $app->get('list_limit', 0), 'uint'); + $value = $input->get('limit', $app->get('list_limit', 0), 'int'); $this->setState('list.limit', $value); - $value = $input->get('limitstart', 0, 'uint'); + $value = $input->get('limitstart', 0, 'int'); $this->setState('list.start', $value); + // Set show summary report configuration in params + if (!empty($this->showSummaryReport)) + { + $this->setState('showSummaryReport', $this->showSummaryReport); + } + if (!empty($this->piiColumns)) { $this->setState('piiColumns', $this->piiColumns); @@ -609,6 +649,8 @@ protected function populateState($ordering = '', $direction = 'ASC') } $this->setState('list.direction', $this->default_order_dir); + + parent::populateState($this->default_order, $this->default_order_dir); } /** @@ -620,7 +662,8 @@ protected function populateState($ordering = '', $direction = 'ASC') */ protected function getListQuery() { - $db = JFactory::getDBO(); + $input = Factory::getApplication()->input; + $db = Factory::getDBO(); $query = $db->getQuery(true); $filters = (array) $this->getState('filters'); $displayFilters = (array) $this->displayFilters(); @@ -672,12 +715,14 @@ protected function getListQuery() if (!empty($filters[$fromCol])) { $fromTime = $filters[$fromCol] . ' 00:00:00'; + $fromTime = new Date($fromTime, 'UTC'); $query->where($dispFilter['searchin'] . ' >= ' . $db->quote($fromTime)); } if (!empty($filters[$toCol])) { $toTime = $filters[$toCol] . ' 23:59:59'; + $toTime = new Date($toTime, 'UTC'); $query->where($dispFilter['searchin'] . ' <= ' . $db->quote($toTime)); } } @@ -705,12 +750,21 @@ protected function getListQuery() $sortKey = $this->getState('list.ordering', $this->default_order); $orderDir = $this->getState('list.direction', $this->default_order_dir); - if (!empty($sortKey) && !in_array($sortKey, $this->sortableWoQuery)) + if (!empty($sortKey) && in_array($sortKey, $this->sortableColumns)) { $query->order($db->quoteName($sortKey) . ' ' . $orderDir); $this->canLimitQuery = true; } + // Remove limit while showing summary report + $tpl = $input->get('tpl', 'default', 'string'); + $tpl = ($tpl == 'default' || $tpl == 'submit') ? null : $tpl; + + if ($tpl != null) + { + $this->canLimitQuery = false; + } + // Joomla fields integration - Get custom fields data // Proceed if table exists, and at least one custom field is seleced for showing if ($this->customFieldsTableExists && !empty($this->customFieldsTableColumnsForQuery) && !empty($this->customFieldsQueryJoinOn)) @@ -760,11 +814,10 @@ protected function sortCustomColumns($items) // Apply sorting and Limit if sorted column is not table if (!empty($items) && !empty($sortKey) - && in_array($sortKey, $this->sortableWoQuery) && $limit) + && in_array($sortKey, $this->sortableColumns) && $limit) { - $orderDir = $this->getState('list.direction', $this->default_order_dir); + $orderDir = $this->getState('list.direction', $this->default_order_dir); $this->multi_d_sort($items, $sortKey, $orderDir); - $items = array_splice($items, $limitstart, $limit); } return $items; @@ -809,7 +862,7 @@ private function multi_d_sort(&$array, $column, $order) * * @param INT $reportToBuild report to build * - * @return object + * @return Mixed * * @since 1.0 */ @@ -817,7 +870,7 @@ public function getSavedQueries($user_id, $reportToBuild) { if (!empty($reportToBuild) && !empty($user_id)) { - $db = JFactory::getDBO(); + $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select('*'); $query->from('#__tj_reports'); @@ -843,7 +896,7 @@ public function getSavedQueries($user_id, $reportToBuild) */ public function getQueryData($queryId) { - $ol_user = JFactory::getUser()->id; + $ol_user = Factory::getUser()->id; $query = $this->_db->getQuery(true); $query->select('*'); $query->from('#__tj_reports'); @@ -859,23 +912,23 @@ public function getQueryData($queryId) /** * Get all plugins names * - * @return object + * @return Array * * @since 1.0 */ public function getenableReportPlugins() { - $user = JFactory::getUser(); - $input = JFactory::getApplication()->input; + $user = Factory::getUser(); + $input = Factory::getApplication()->input; $client = $input->get('client', '', 'STRING'); // Get all report plugin $dispatcher = JEventDispatcher::getInstance(); - $plugins = JPluginHelper::getPlugin('tjreports'); + $plugins = PluginHelper::getPlugin('tjreports'); $pluginExists = json_decode(json_encode($plugins), true); - $pluginNames = array_column($pluginExists, 'name'); + $pluginNames = array_column($pluginExists, 'name'); - $db = JFactory::getDBO(); + $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select(array('id as reportId, title, plugin, ordering')); @@ -905,7 +958,10 @@ public function getenableReportPlugins() // In view layouts - reports[0] is used, and since array indexes are unset above, // Let's re-arrange index accordingly - $reports = array_values($reports); + if (is_array($reports)) + { + $reports = array_values($reports); + } return $reports; } @@ -919,7 +975,7 @@ public function getenableReportPlugins() */ public function getUserFilter() { - $db = JFactory::getDbo(); + $db = Factory::getDbo(); $query = $db->getQuery(true); $query->select('u.id,u.username'); @@ -929,13 +985,13 @@ public function getUserFilter() $db->setQuery($query); $users = $db->loadObjectList(); - $userFilter[] = JHTML::_('select.option', '', JText::_('COM_TJREPORTS_FILTER_SELECT_USER')); + $userFilter[] = HTMLHelper::_('select.option', '', Text::_('COM_TJREPORTS_FILTER_SELECT_USER')); if (!empty($users)) { foreach ($users as $eachUser) { - $userFilter[] = JHTML::_('select.option', $eachUser->id, $eachUser->username); + $userFilter[] = HTMLHelper::_('select.option', $eachUser->id, $eachUser->username); } } @@ -952,9 +1008,9 @@ public function getUserFilter() public function getreportoptions() { // Initialize variables. - $db = JFactory::getDbo(); - $query = $db->getQuery(true); - $user_id = JFactory::getUser()->id; + $db = Factory::getDbo(); + $query = $db->getQuery(true); + $user_id = Factory::getUser()->id; $clients = $this->getState('client'); @@ -984,11 +1040,11 @@ public function getreportoptions() $db->setQuery($query); $reports = $db->loadObjectList(); - $options[] = JHTML::_('select.option', 0, JText::_('COM_TJREPORTS_SELONE_REPORTS')); + $options[] = HTMLHelper::_('select.option', 0, Text::_('COM_TJREPORTS_SELONE_REPORTS')); foreach ($reports as $repo) { - $options[] = JHtml::_('select.option', $repo->value, $repo->text); + $options[] = HTMLHelper::_('select.option', $repo->value, $repo->text); } return $options; @@ -1014,14 +1070,14 @@ public function canViewPiiData() * * @param INT $reportId report id * - * @return object + * @return Mixed * - * @since 1.0 + * @since 1.0 */ public function checkpermissions($reportId) { - $user = JFactory::getUser(); + $user = Factory::getUser(); if ($reportId) { @@ -1042,8 +1098,8 @@ public function checkpermissions($reportId) */ public function getUserGroupFilter($includeSuperAdmin = true) { - $groups = JHtml::_('user.groups', $includeSuperAdmin); - array_unshift($groups, JHtml::_('select.option', '', JText::_('JGLOBAL_FILTER_GROUPS_LABEL'))); + $groups = HTMLHelper::_('user.groups', $includeSuperAdmin); + array_unshift($groups, HTMLHelper::_('select.option', '', Text::_('JGLOBAL_FILTER_GROUPS_LABEL'))); return $groups; } @@ -1057,25 +1113,25 @@ public function getUserGroupFilter($includeSuperAdmin = true) */ public function datadenyset() { - $input = JFactory::getApplication()->input; + $input = Factory::getApplication()->input; $reportId = $input->get('reportId', '0', 'int'); if ($reportId) { $this->model = $this->getModel('reports'); - $reportData = $this->model->getReportNameById($reportId); - $reportName = $reportData->title; + $reportData = $this->model->getReportNameById($reportId); + $reportName = $reportData->title; } else { return false; } - $user_id = JFactory::getUser()->id; + $user_id = Factory::getUser()->id; if ($reportName && $user_id && $reportId) { - $db = JFactory::getDBO(); + $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select(array('param')); $query->from($db->quoteName('#__tj_reports')); @@ -1113,7 +1169,7 @@ public function loadLanguage($name, $type = 'tjreports', $extension = '', $baseP } $extension = strtolower($extension); - $lang = JFactory::getLanguage(); + $lang = Factory::getLanguage(); // If language already loaded, don't load it again. if ($lang->getPaths($extension)) @@ -1210,12 +1266,12 @@ private function processSavedReportColumns($queryId, &$selColToshow) ->from('#__tj_reports') ->where('id=' . (int) $queryId); $this->_db->setQuery($query); - $queryData = $this->_db->loadObject(); - $i = $parent = 0; + $queryData = $this->_db->loadObject(); + $i = $parent = 0; if (!empty($queryData->param)) { - $param = json_decode($queryData->param, true); + $param = json_decode($queryData->param, true); if (isset($param['showHideColumns'])) { @@ -1229,6 +1285,12 @@ private function processSavedReportColumns($queryId, &$selColToshow) } } + // Set the value of show summary report from param to variable + if (isset($param['showSummaryReport'])) + { + $this->showSummaryReport = $param['showSummaryReport']; + } + if (isset($param['piiColumns'])) { if (empty($this->filterPiiColumns)) @@ -1270,9 +1332,8 @@ private function processSavedReportColumns($queryId, &$selColToshow) /* Checked the columns which are hide(false) in load params & if set them as piiColumns * then it only returns the columns which are not available in piiColumns. */ $this->filterDefaultColToHide = array_diff($this->filterDefaultColToHide, $param['piiColumns']); - - $this->filterParamColToshow = array_diff($this->filterParamColToshow, $param['piiColumns']); - $this->filterShowhideCols = array_diff($this->filterShowhideCols, $param['piiColumns']); + $this->filterParamColToshow = array_diff($this->filterParamColToshow, $param['piiColumns']); + $this->filterShowhideCols = array_diff($this->filterShowhideCols, $param['piiColumns']); } $parent = $queryData->parent; @@ -1283,7 +1344,7 @@ private function processSavedReportColumns($queryId, &$selColToshow) if (!empty($this->piiColumns) && !$this->piiPermission) { $this->defaultColToShow = array_diff($this->defaultColToShow, $this->piiColumns); - $this->showhideCols = array_diff($this->showhideCols, $this->piiColumns); + $this->showhideCols = array_diff($this->showhideCols, $this->piiColumns); } } @@ -1295,15 +1356,15 @@ private function processSavedReportColumns($queryId, &$selColToshow) * * @param INT $reportId Report Id * - * @return Object + * @return Mixed * * @since 3.0 */ public function getReportNameById($reportId) { - $db = JFactory::getDBO(); - JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); - $reportTable = JTable::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); + $db = Factory::getDBO(); + Table::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); + $reportTable = Table::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); $reportTable->load(array('id' => $reportId)); return $reportTable; @@ -1321,9 +1382,8 @@ public function getReportNameById($reportId) */ public function getReportLink($reportToLink, $filters) { - $user = JFactory::getUser(); - - $reports = $this->getPluginReport($reportToLink); + $user = Factory::getUser(); + $reports = $this->getPluginReport($reportToLink); $filterLink = ''; foreach ($filters as $key => $value) @@ -1347,20 +1407,20 @@ public function getReportLink($reportToLink, $filters) /** * Method to get id of the report having default set as 1 * - * @param STRING $reportId Report id + * @param STRING $reportId Report Id * - * @return Integer + * @return Object * * @since 1.1.0 */ public function getReportParams($reportId) { - $db = JFactory::getDBO(); - JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); - $reportTable = JTable::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); + $db = Factory::getDBO(); + Table::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); + $reportTable = Table::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); $reportTable->load($reportId); - return new JRegistry($reportTable->param); + return new Registry($reportTable->param); } /** @@ -1374,9 +1434,9 @@ public function getReportParams($reportId) */ public function getDefaultReport($pluginName) { - $db = JFactory::getDBO(); - JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); - $reportTable = JTable::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); + $db = Factory::getDBO(); + Table::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); + $reportTable = Table::getInstance('Tjreport', 'TjreportsTable', array('dbo', $db)); $reportTable->load(array('plugin' => $pluginName, 'default' => 1)); return $reportTable->id; @@ -1397,7 +1457,7 @@ public function getPluginReport($pluginName) if (!isset($reports[$pluginName])) { - $db = JFactory::getDBO(); + $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select(array('id as reportId', 'client')); $query->from($db->quoteName('#__tj_reports')); @@ -1417,16 +1477,16 @@ public function getPluginReport($pluginName) * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * - * @return JModelLegacy|boolean Model object on success; otherwise false on failure. + * @return BaseDatabaseModel|boolean Model object on success; otherwise false on failure. * * @since 3.0 */ public function getPluginModel($name = '', $prefix = '', $config = array()) { - JModelLegacy::addIncludePath(JPATH_SITE . '/plugins/tjreports/' . $name); + BaseDatabaseModel::addIncludePath(JPATH_SITE . '/plugins/tjreports/' . $name); $this->loadLanguage($name, 'tjreports'); - return JModelLegacy::getInstance($name, 'TjreportsModel', $config); + return BaseDatabaseModel::getInstance($name, 'TjreportsModel', $config); } /** @@ -1459,7 +1519,7 @@ public function getPluginInstallationDetail($pluginName) if ($pluginName && !isset($clients[$pluginName])) { $clients[$pluginName] = ''; - $model = $this->getPluginModel($pluginName); + $model = $this->getPluginModel($pluginName); if ($model) { @@ -1477,7 +1537,7 @@ public function getPluginInstallationDetail($pluginName) */ public function addTjReportsPlugins() { - $db = JFactory::getDbo(); + $db = Factory::getDbo(); $query = $db->getQuery(true) ->select( $db->quoteName( @@ -1509,21 +1569,21 @@ public function addTjReportsPlugins() foreach ($plugins as $plugin) { - $pluginName = $plugin->name; - JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); - $reportTable = JTable::getInstance('Tjreport', 'TjreportsTable'); - $details = $this->getPluginInstallationDetail($pluginName); + $pluginName = $plugin->name; + Table::addIncludePath(JPATH_ROOT . '/administrator/components/com_tjreports/tables'); + $reportTable = Table::getInstance('Tjreport', 'TjreportsTable'); + $details = $this->getPluginInstallationDetail($pluginName); $reportTable->load(array('plugin' => $pluginName, 'userid' => 0)); if (!$reportTable->id) { - $data = array(); - $data['title'] = $details['title']; + $data = array(); + $data['title'] = $details['title']; $data['plugin'] = $pluginName; - $data['alias'] = $pluginName; + $data['alias'] = $pluginName; $data['client'] = $details['client']; $data['parent'] = 0; - $data['default'] = 1; + $data['default'] = 1; $reportTable->save($data); $count++; @@ -1532,4 +1592,38 @@ public function addTjReportsPlugins() return $count; } + + /** + * Method to get report plugin of particular type for inter linking + * + * @param Int $userId User Id + * + * @return Array + * + * @since __DEPLOY_VERSION__ + */ + protected function getUserGroups($userId) + { + if (!$userId) + { + return array(); + } + + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + // Get the titles for the user groups. + $query = $db->getQuery(true) + ->select($db->quoteName('ug.id')) + ->select($db->quoteName('ug.title')) + ->from($db->quoteName('#__usergroups', 'ug')) + ->join('INNER', $db->qn('#__user_usergroup_map', 'ugm') . ' ON (' . + $db->qn('ugm.group_id') . ' = ' . $db->qn('ug.id') . ')') + ->where($db->quoteName('ugm.user_id') . ' = ' . (int) $userId); + + $db->setQuery($query); + + // Set the titles for the user groups. + return $db->loadAssocList('id', 'title'); + } } diff --git a/tjreports/site/views/reports/tmpl/default.php b/tjreports/site/views/reports/tmpl/default.php index b63d2b3..826fb35 100644 --- a/tjreports/site/views/reports/tmpl/default.php +++ b/tjreports/site/views/reports/tmpl/default.php @@ -10,17 +10,24 @@ // no direct access defined('_JEXEC') or die; -JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); +Use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Factory; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Filter\OutputFilter; -$emailColmClass = 'td-sendemail'; +HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html'); -$app = JFactory::getApplication(); +$emailColmClass = 'td-sendemail'; +$emailColumCnt = 0; +$app = Factory::getApplication(); $headerLevel = $this->headerLevel; $this->listOrder = $this->state->get('list.ordering'); $this->listDirn = $this->state->get('list.direction'); $totalCount = 0; -foreach ($this->colToshow as $key=>$data) +foreach ($this->colToshow as $key => $data) { if (is_array($data)) { @@ -32,25 +39,25 @@ } } -$input = JFactory::getApplication()->input; +$input = Factory::getApplication()->input; $displayFilters = $this->userFilters; $totalHeadRows = count($displayFilters); $reportId = $app->getUserStateFromRequest('reportId', 'reportId', ''); -$user = JFactory::getUser(); +$user = Factory::getUser(); $userAuthorisedExport = $user->authorise('core.export', 'com_tjreports.tjreport.' . $reportId); -if ($app->isSite()) +if ($app->isClient('site')) { - $siteUrl = JUri::root(); - $message = array(); - $message['success'] = JText::_("COM_TJREPORTS_EXPORT_FILE_SUCCESS"); - $message['error'] = JText::_("COM_TJREPORTS_EXPORT_FILE_ERROR"); - $message['inprogress'] = JText::_("COM_TJREPORTS_EXPORT_FILE_NOTICE"); - $message['text'] = JText::_("COM_TJREPORTS_CSV_EXPORT"); + $siteUrl = Uri::root(); + $message = array(); + $message['success'] = Text::_("COM_TJREPORTS_EXPORT_FILE_SUCCESS"); + $message['error'] = Text::_("COM_TJREPORTS_EXPORT_FILE_ERROR"); + $message['inprogress'] = Text::_("COM_TJREPORTS_EXPORT_FILE_NOTICE"); + $message['text'] = Text::_("COM_TJREPORTS_CSV_EXPORT"); - JHtml::script(JUri::base() . 'libraries/techjoomla/assets/js/tjexport.js'); - $document = JFactory::getDocument(); - $csv_url = 'index.php?option=' . $input->get('option') . '&view=' . $input->get('view') . '&format=csv'; + HTMLHelper::script(Uri::base() . 'libraries/techjoomla/assets/js/tjexport.js'); + $document = Factory::getDocument(); + $csv_url = 'index.php?option=' . $input->get('option') . '&view=' . $input->get('view') . '&format=csv'; $document->addScriptDeclaration("var csv_export_url='{$csv_url}';"); $document->addScriptDeclaration("var csv_export_success='{$message['success']}';"); @@ -58,6 +65,12 @@ $document->addScriptDeclaration("var csv_export_inprogress='{$message['inprogress']}';"); $document->addScriptDeclaration("var tj_csv_site_root='{$siteUrl}';"); } + +if ($this->showSummaryReport == 'Yes') +{ + HTMLHelper::_('script', 'media/com_tjreports/js/chartBundle.min.js'); +} + ?>
@@ -75,14 +88,14 @@ isSite() && isset($this->reportData->title)) + if ($app->isClient('site') && isset($this->reportData->title)) { ?>

reportData->title, ENT_COMPAT, 'UTF-8'); ?>

-
+
@@ -115,14 +128,37 @@
isAdmin()) + /*if (!$app->isClient('administrator')) { echo $this->pagination->getPaginationLinks('joomla.pagination.links', array('showPagesLinks' => false,'showLimitStart' => false)); } else { echo $this->pagination->getLimitBox(); + }*/ + + $defaultLimits = array(5, 10, 15, 20, 25, 30, 50, 100, 200, 500); + $limits = array(); + + // Make the option list. + foreach ($defaultLimits as $lm) + { + $limits[] = (object) array( + 'value' => $lm, + 'text' => Text::_('J' . $lm), + ); } + + // Build the select list. + echo HTMLHelper::_( + 'select.genericlist', + $limits, + 'limit', + 'class="inputbox input-mini" size="1" onchange="Joomla.submitform();"', + 'value', + 'text', + $this->pagination->limit + ); ?>
@@ -136,7 +172,7 @@ { ?>
- savedQueries, "queryId", 'class="" size="1" onchange="tjrContentUI.report.getQueryResult(this.value);" name="filter_saveQuery"', "value", "text", $this->queryId); + savedQueries, "queryId", 'class="" size="1" onchange="tjrContentUI.report.getQueryResult(this.value);" name="filter_saveQuery"', "value", "text", $this->queryId); ?> queryId) @@ -153,7 +189,7 @@ isSite()) + if ($app->isClient('site')) { if ($this->isExport) { @@ -165,7 +201,7 @@ - +
@@ -181,9 +217,9 @@ if ($totalHeadRows > 1) { ?> -
+
@@ -192,7 +228,7 @@ ?>
- +
    showHideColumns as $colKey) @@ -210,13 +246,13 @@ if (in_array($colKey, $this->colToshow)) { - $checked = 'checked="checked"'; + $checked = 'checked="checked"'; } ?>
+ + + + + showSummaryReport == 'Yes') + { + $reportContainer = "hide"; + ?> +
+ + + +
+ + + isAdmin() && $userAuthorisedExport && $user) + if (!$app->isClient('administrator') && $userAuthorisedExport && $user) { ?> -
+ srButton !== -1) { ?> - -
@@ -323,15 +377,15 @@ echo ''; - $colTitle = JText::sprintf($subTextTitle, $keyDetails[1]) ; + $colTitle = Text::sprintf($subTextTitle, $keyDetails[1]) ; if (in_array($subKey, $this->sortable)) { - echo $sortHtml = JHtml::_('grid.sort', $colTitle, $subKey, $this->listDirn, $this->listOrder); + echo $sortHtml = HTMLHelper::_('grid.sort', $colTitle, $subKey, $this->listDirn, $this->listOrder); } else { - echo '
' . JText::_($colTitle) . '
'; + echo '
' . Text::_($colTitle) . '
'; } echo ''; @@ -340,7 +394,7 @@ else { $colKey = $detail; - $colKeyClass = JFilterOutput::stringURLSafe($colKey); + $colKeyClass = OutputFilter::stringURLSafe($colKey); if (!isset($this->columns[$colKey]['title'])) { $colTitle = 'PLG_TJREPORTS_' . strtoupper($this->pluginName . '_' . $colKey . '_TITLE'); @@ -359,11 +413,11 @@ if (in_array($colKey, $this->sortable)) { - echo $sortHtml = JHtml::_('grid.sort', $colTitle, $colKey, $this->listDirn, $this->listOrder); + echo $sortHtml = HTMLHelper::_('grid.sort', $colTitle, $colKey, $this->listDirn, $this->listOrder); } else { - echo '
' . JText::_($colTitle) . '
'; + echo '
' . Text::_($colTitle) . '
'; } if ($hasFilter) { @@ -433,8 +487,19 @@ } else { - $isSendEmailClass = ($key == $this->emailColumn) ? $emailColmClass : ''; - echo "{$item[$key]}"; + $isSendEmailClass = ''; + + if ($key == $this->emailColumn) + { + $isSendEmailClass = $emailColmClass; + $emailColumCnt++; + } + + $value = isset($item[$key]) ? $item[$key] : ''; + + // Wrap the report values + $value = wordwrap($value, 30, "\n", true); + echo "{$value}"; } } @@ -463,7 +528,7 @@
isAdmin()) + if (!$app->isClient('administrator')) { echo $this->pagination->getPaginationLinks('joomla.pagination.links', array('showLimitBox' => false)); } @@ -483,7 +548,7 @@ - +
@@ -493,3 +558,11 @@
+ + 0 && JPluginHelper::isEnabled('system', 'tjsendemail')) +{ + HTMLHelper::script('media/editors/tinymce/tinymce.min.js'); + HTMLHelper::script('plugins/system/tjsendemail/assets/bulksendemail.min.js'); +} diff --git a/tjreports/site/views/reports/tmpl/default_summary.php b/tjreports/site/views/reports/tmpl/default_summary.php new file mode 100644 index 0000000..389b18e --- /dev/null +++ b/tjreports/site/views/reports/tmpl/default_summary.php @@ -0,0 +1,99 @@ + + * @copyright Copyright (C) 2009 - 2019 Techjoomla. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// no direct access +defined('_JEXEC') or die; +use Joomla\CMS\Language\Text; + +$chartdata = $this->items; + +// Items conditional classes +if (count($chartdata) > 2){ + $itemsClass ="col-xs-12 col-md-4 chartItems"; +} +else +{ + $itemsClass ="col-xs-12 col-md-6 chartItems"; +} + +if (count($chartdata) > 0) +{ ?> +
+ +
+
+

+ +

+
+ + +
+
+
+ + +
+ +
+ + diff --git a/tjreports/site/views/reports/view.base.php b/tjreports/site/views/reports/view.base.php index 9e14e42..ca455f4 100644 --- a/tjreports/site/views/reports/view.base.php +++ b/tjreports/site/views/reports/view.base.php @@ -13,6 +13,13 @@ // No direct access defined('_JEXEC') or die; +Use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; + jimport('joomla.application.component.view'); JLoader::import('components.com_tjreports.helpers.tjreports', JPATH_ADMINISTRATOR); JLoader::import('components.com_tjreports.models.tjreports', JPATH_SITE); @@ -38,12 +45,30 @@ class ReportsViewBase extends JViewLegacy protected $reportData; - protected $savedQueries = array(); + protected $headerLevel; protected $reportId = 0; protected $queryId = 0; + protected $savedQueries = array(); + + protected $defaultColToHide; + + protected $columns; + + protected $showhideCols; + + protected $filterParamColToshow; + + protected $defaultColToShow; + + protected $sortableColumns; + + protected $showSearchResetButton; + + protected $showSummaryReport; + /** * Execute and display a template script. * @@ -53,15 +78,14 @@ class ReportsViewBase extends JViewLegacy */ public function processData($type = 'html') { - $app = JFactory::getApplication(); - $canDo = TjreportsHelper::getActions(); - $input = JFactory::getApplication()->input; - $user = JFactory::getUser(); + $canDo = TjreportsHelper::getActions(); + $input = Factory::getApplication()->input; + $user = Factory::getUser(); $this->reportId = $input->get('reportId', 0, 'INT'); - $this->model = $this->getModel('reports'); + $this->model = $this->getModel('reports'); - $reports = $this->model->getenableReportPlugins(); + $reports = $this->model->getenableReportPlugins(); $this->reportId = $this->reportId ? $this->reportId : (isset($reports['0']['reportId']) ? $reports['0']['reportId'] : ''); $this->reportData = $this->model->getReportNameById($this->reportId); @@ -75,13 +99,17 @@ public function processData($type = 'html') if (!$canDo->get('core.view') || !$this->pluginName) { - JError::raiseWarning(403, JText::_('JERROR_ALERTNOAUTHOR')); + JError::raiseWarning(403, Text::_('JERROR_ALERTNOAUTHOR')); return false; } $this->model = $this->getModel($this->pluginName); - $this->setModel($this->model, true); + + if ($this->model) + { + $this->setModel($this->model, true); + } if ($this->reportId) { @@ -89,14 +117,14 @@ public function processData($type = 'html') if (!$allow_permission) { - JError::raiseWarning(403, JText::_('JERROR_ALERTNOAUTHOR')); + JError::raiseWarning(403, Text::_('JERROR_ALERTNOAUTHOR')); return false; } } else { - JError::raiseWarning(403, JText::_('JERROR_ALERTNOAUTHOR')); + JError::raiseWarning(403, Text::_('JERROR_ALERTNOAUTHOR')); return false; } @@ -131,12 +159,12 @@ public function processData($type = 'html') if (!empty($savedQueries)) { - $qOptions = array(); - $qOptions[] = JHTML::_('select.option', '', JText::_('COM_TJREPORTS_SELONE_QUERY')); + $qOptions = array(); + $qOptions[] = HTMLHelper::_('select.option', '', Text::_('COM_TJREPORTS_SELONE_QUERY')); foreach ($savedQueries as $savedQuery) { - $qOptions[] = JHTML::_('select.option', $savedQuery->id, $savedQuery->title); + $qOptions[] = HTMLHelper::_('select.option', $savedQuery->id, $savedQuery->title); } $this->savedQueries = $qOptions; @@ -144,11 +172,11 @@ public function processData($type = 'html') // Get all report plugin $dispatcher = JEventDispatcher::getInstance(); - $pluginExists = JPluginHelper::getPlugin('tjreports', $this->pluginName); + $pluginExists = PluginHelper::getPlugin('tjreports', $this->pluginName); if (!$pluginExists || !$this->pluginName) { - JError::raiseError(404, JText::_('COM_TJREPORTS_PLUGIN_DESABLED_OR_NOT_EXISTS')); + JError::raiseError(404, Text::_('COM_TJREPORTS_PLUGIN_DESABLED_OR_NOT_EXISTS')); return false; } @@ -161,8 +189,9 @@ public function processData($type = 'html') $this->headerLevel = $this->model->headerLevel; // Array_key - defaultColToHide column are present then get the key as value. - $this->defaultColToHide = array_keys($this->model->getState('defaultColToHide')); - $this->columns = $this->model->columns; + $defaultColToHide = (array) $this->model->getState('defaultColToHide'); + $this->defaultColToHide = array_keys($defaultColToHide); + $this->columns = $this->model->columns; /* Array_merge - here colToshow means get all true value array so want to mearg defaultColToHide column and then using * array_intersect - only remove those column which is force fully added in load param in showhideCols config @@ -184,19 +213,16 @@ public function processData($type = 'html') $this->showHideColumns = array_intersect($this->model->showhideCols, array_merge($this->defaultColToshow, $this->defaultColToHide)); } - $this->sortable = $this->model->sortableColumns; - $this->emailColumn = $this->model->getState('emailColumn'); - $this->srButton = $this->model->showSearchResetButton; - - $this->colToshow = $this->model->getState('colToshow'); - - $this->filterValues = $this->model->getState('filters'); - - $this->userFilters = $this->model->displayFilters(); - $this->messages = $this->model->getTJRMessages(); - + $this->sortable = $this->model->sortableColumns; + $this->emailColumn = $this->model->getState('emailColumn'); + $this->srButton = $this->model->showSearchResetButton; + $this->colToshow = $this->model->getState('colToshow'); + $this->filterValues = $this->model->getState('filters'); + $this->userFilters = $this->model->displayFilters(); + $this->messages = $this->model->getTJRMessages(); + $this->showSummaryReport = $this->model->getState('showSummaryReport'); $this->enableReportPlugins = $this->model->getenableReportPlugins($this->client); - $this->isExport = $user->authorise('core.export', 'com_tjreports.tjreport.' . $this->reportId); + $this->isExport = $user->authorise('core.export', 'com_tjreports.tjreport.' . $this->reportId); return true; } @@ -208,14 +234,14 @@ public function processData($type = 'html') * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * - * @return JModelLegacy|boolean Model object on success; otherwise false on failure. + * @return BaseDatabaseModel|boolean Model object on success; otherwise false on failure. * * @since 3.0 */ public function getModel($name = '', $prefix = '', $config = array()) { - JModelLegacy::addIncludePath(JPATH_SITE . '/plugins/tjreports/' . $name); + BaseDatabaseModel::addIncludePath(JPATH_SITE . '/plugins/tjreports/' . $name); - return JModelLegacy::getInstance($name, 'TjreportsModel', $config); + return BaseDatabaseModel::getInstance($name, 'TjreportsModel', $config); } } diff --git a/tjreports/site/views/reports/view.csv.php b/tjreports/site/views/reports/view.csv.php index 429c4f0..ee81654 100644 --- a/tjreports/site/views/reports/view.csv.php +++ b/tjreports/site/views/reports/view.csv.php @@ -158,6 +158,9 @@ private function getItems() $this->headers = $colTitleArray; $pluginTitle = str_replace(" ", "_", $reportData->title); + + // Remove special character from plugin name + $pluginTitle = preg_replace('/[^A-Za-z0-9\-]/', '', $pluginTitle); $this->fileName = rtrim(strtolower($pluginTitle)) . "_report_" . date("Y-m-d_H-i", time()); // Loop through items @@ -204,10 +207,10 @@ private function filterValue($data) $finalValue = strip_tags($data); // Remove double Quotes from the data - $finalValue = str_replace('"', '', $finalValue); + // $finalValue = str_replace('"', '', $finalValue); // Remove single Quotes from the data - $finalValue = str_replace("'", '', $finalValue); + // $finalValue = str_replace("'", '', $finalValue); // Remove tabs and newlines from the data $finalValue = preg_replace('/(\r\n|\r|\n)+/', " ", $finalValue); diff --git a/tjreports/site/views/reports/view.html.php b/tjreports/site/views/reports/view.html.php index 094a890..9037021 100755 --- a/tjreports/site/views/reports/view.html.php +++ b/tjreports/site/views/reports/view.html.php @@ -13,6 +13,12 @@ // No direct access defined('_JEXEC') or die; +Use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Component\ComponentHelper; + require_once __DIR__ . '/view.base.php'; jimport('techjoomla.tjtoolbar.button.csvexport'); @@ -32,7 +38,7 @@ class TjreportsViewReports extends ReportsViewBase */ public function display($tpl = null) { - $input = JFactory::getApplication()->input; + $input = Factory::getApplication()->input; $result = $this->processData(); if (!$result) @@ -55,16 +61,16 @@ public function display($tpl = null) */ protected function addToolbar() { - $app = JFactory::getApplication(); + $app = Factory::getApplication(); $reportId = $app->getUserStateFromRequest('reportId', 'reportId', ''); - $user = JFactory::getUser(); + $user = Factory::getUser(); $userAuthorisedExport = $user->authorise('core.export', 'com_tjreports.tjreport.' . $reportId); $bar = JToolBar::getInstance('toolbar'); $canDo = TjreportsHelper::getActions(); if ($app->isAdmin()) { - $title = JText::_('COM_TJREPORTS_TITLE_REPORT'); + $title = Text::_('COM_TJREPORTS_TITLE_REPORT'); if (isset($this->reportData->title)) { @@ -100,11 +106,11 @@ protected function addToolbar() if ($canDo->get('core.export') && $userAuthorisedExport) { - $message = array(); - $message['success'] = JText::_("COM_TJREPORTS_EXPORT_FILE_SUCCESS"); - $message['error'] = JText::_("COM_TJREPORTS_EXPORT_FILE_ERROR"); - $message['inprogress'] = JText::_("COM_TJREPORTS_EXPORT_FILE_NOTICE"); - $message['text'] = JText::_("COM_TJREPORTS_CSV_EXPORT"); + $message = array(); + $message['success'] = Text::_("COM_TJREPORTS_EXPORT_FILE_SUCCESS"); + $message['error'] = Text::_("COM_TJREPORTS_EXPORT_FILE_ERROR"); + $message['inprogress'] = Text::_("COM_TJREPORTS_EXPORT_FILE_NOTICE"); + $message['text'] = Text::_("COM_TJREPORTS_CSV_EXPORT"); $bar->appendButton('CsvExport', $message); } @@ -113,7 +119,7 @@ protected function addToolbar() ' - . JText::_('COM_TJREPORTS_SAVE_THIS_QUERY') . ' + . Text::_('COM_TJREPORTS_SAVE_THIS_QUERY') . '