From b8d52e20d9a8fad2ef77b6a4b29cb3c12e9cd808 Mon Sep 17 00:00:00 2001 From: CyberCookie Date: Thu, 7 Apr 2016 10:20:37 -0400 Subject: [PATCH 01/10] Close GH-270: [#116219335] paginator update. --- .../core/directives/ot-paginator.directive.js | 45 ------------ src/app/core/directives/ot-paginator.html | 25 ------- .../ot-table-manager-popup.directive.js | 70 +------------------ .../directives/ot-table-manager-popup.html | 24 ++++++- .../directives/ot-table-manager.directive.js | 58 +-------------- src/app/core/directives/ot-table-manager.html | 24 ++++++- 6 files changed, 46 insertions(+), 200 deletions(-) delete mode 100644 src/app/core/directives/ot-paginator.directive.js delete mode 100644 src/app/core/directives/ot-paginator.html diff --git a/src/app/core/directives/ot-paginator.directive.js b/src/app/core/directives/ot-paginator.directive.js deleted file mode 100644 index 44671f0b..00000000 --- a/src/app/core/directives/ot-paginator.directive.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * getClass(page) - * setPage(page) - * getPages() - */ -angular.module('coreModule') - -.directive('otPaginator', ['$location', function($location) { - return { - restrict: 'E', - scope: { - 'parent': '=object' - }, - templateUrl: '/views/core/directives/ot-paginator.html', - controller: ['$scope', function($scope) { - - var countNeighbors = 4; - $scope.leftBreak = false; - $scope.rightBreak = false; - - $scope.isNeighbors = function(page) { - return Math.abs($scope.parent.paginator.page - page) <= countNeighbors; - }; - - $scope.$watch('parent.paginator.page', function() { - if (typeof $scope.parent.paginator === 'undefined') { - return true; - } - - var leftBorder = $scope.parent.paginator.page - countNeighbors; - var rightBorder = $scope.parent.paginator.page + countNeighbors; - - if (leftBorder > 2) { - $scope.leftBreak = true; - } - - if (rightBorder < $scope.parent.paginator.countPages - 1) { - $scope.rightBreak = true; - } - - }, true); - }] - }; -}]); - diff --git a/src/app/core/directives/ot-paginator.html b/src/app/core/directives/ot-paginator.html deleted file mode 100644 index f0bea3ec..00000000 --- a/src/app/core/directives/ot-paginator.html +++ /dev/null @@ -1,25 +0,0 @@ - -
- -
diff --git a/src/app/core/directives/ot-table-manager-popup.directive.js b/src/app/core/directives/ot-table-manager-popup.directive.js index b5b50da6..cdd3bd7b 100644 --- a/src/app/core/directives/ot-table-manager-popup.directive.js +++ b/src/app/core/directives/ot-table-manager-popup.directive.js @@ -259,78 +259,10 @@ angular.module("coreModule") return true; }; - /** PAGINATOR */ - - $scope.getPages = function () { - if (typeof $scope.paginator === "undefined") { - return false; - } - var p, result; - result = []; - - for (p = 1; p <= $scope.paginator.countPages; p += 1) { - result.push(p); - } - return result; - }; - - $scope.setPage = function (page) { - if (typeof $scope.paginator === "undefined" || page === $scope.paginator.page) { - return false; - } - - var _setPage = function (page) { - if ("prev" === page && $scope.paginator.page !== 1) { - $scope.paginator.page = $scope.paginator.page - 1; - } else if ("next" === page && $scope.paginator.page !== $scope.paginator.countPages) { - $scope.paginator.page = $scope.paginator.page + 1; - } else if (-1 === ["prev", "next"].indexOf(page)) { - $scope.paginator.page = page; - } else { - return false; - } - - return true; - }; - - if (!_setPage(page)) { - return false; - } - - $("#selectAll").removeAttr("checked"); - isSelectedAll = false; - + $scope.updateSearch = function () { $scope.parent.search = getSearchObj(); }; - /** - * Gets class for item of paginator - * - * @param {string} page - * @returns {string} - */ - $scope.getClass = function (page) { - if (typeof $scope.paginator === "undefined") { - return ''; - } - - var _class; - _class = ''; - - if (page === parseInt($scope.paginator.page, 10)) { - _class = 'active'; - } - - if (("prev" === page && $scope.paginator.page === 1) || - ("next" === page && $scope.paginator.page >= $scope.paginator.countPages)) { - _class = 'disabled'; - } - - return _class; - }; - - /** PAGINATOR END*/ - /** Sorting */ $scope.getSortClass = function (attr) { diff --git a/src/app/core/directives/ot-table-manager-popup.html b/src/app/core/directives/ot-table-manager-popup.html index 28b23055..c293db80 100644 --- a/src/app/core/directives/ot-table-manager-popup.html +++ b/src/app/core/directives/ot-table-manager-popup.html @@ -2,7 +2,17 @@
- +
+
+
+
@@ -81,7 +91,17 @@ - +
+
+
+
diff --git a/src/app/core/directives/ot-table-manager.directive.js b/src/app/core/directives/ot-table-manager.directive.js index 2e989d76..72b044b2 100644 --- a/src/app/core/directives/ot-table-manager.directive.js +++ b/src/app/core/directives/ot-table-manager.directive.js @@ -224,66 +224,11 @@ angular.module("coreModule") return true; }; - /** PAGINATOR */ - $scope.getPages = function () { - if (typeof $scope.paginator === "undefined") { - return false; - } - var p, result; - result = []; - - for (p = 1; p <= $scope.paginator.countPages; p += 1) { - result.push(p); - } - return result; - }; - - $scope.setPage = function (page) { - if (typeof $scope.paginator === "undefined") { - return false; - } - - if ("prev" === page && $scope.paginator.page !== 1) { - $scope.paginator.page = $scope.paginator.page - 1; - } else if ("next" === page && $scope.paginator.page !== $scope.paginator.countPages) { - $scope.paginator.page = $scope.paginator.page + 1; - } else if (-1 === ["prev", "next"].indexOf(page)) { - $scope.paginator.page = page; - } - + $scope.updateSearch = function () { $location.search(getQueryStr()); }; - /** - * Gets class for item of paginator - * - * @param {string} page - * @returns {string} - */ - $scope.getClass = function (page) { - if (typeof $scope.paginator === "undefined") { - return ''; - } - - var _class; - _class = ''; - - if (page === parseInt($scope.paginator.page, 10)) { - _class = 'active'; - } - - if (("prev" === page && $scope.paginator.page === 1) || - ("next" === page && $scope.paginator.page >= $scope.paginator.countPages)) { - _class = 'disabled'; - } - - return _class; - }; - - /** PAGINATOR END*/ - /** Sorting */ - $scope.getSortClass = function (attr) { var _class = ""; if (attr === $scope.sort.currentValue) { @@ -308,7 +253,6 @@ angular.module("coreModule") $scope.parent.idsSelectedRows[$scope.items[i][$scope.map.id]] = isSelectedAll; } }; - /** Sorting end*/ getQueryStr = function (reset) { diff --git a/src/app/core/directives/ot-table-manager.html b/src/app/core/directives/ot-table-manager.html index e55e4201..ba45db86 100644 --- a/src/app/core/directives/ot-table-manager.html +++ b/src/app/core/directives/ot-table-manager.html @@ -28,7 +28,17 @@ - +
+
+
+
@@ -113,7 +123,17 @@ - +
+
+
+
From 8df5ae91d2eee486c660a26fc837a7b31a892cb9 Mon Sep 17 00:00:00 2001 From: Adam Knox Date: Thu, 7 Apr 2016 11:02:10 -0400 Subject: [PATCH 02/10] reports - update tooltip, correct column group spacing --- src/app/reports/product.controller.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/app/reports/product.controller.js b/src/app/reports/product.controller.js index d6badd37..9ff872ae 100644 --- a/src/app/reports/product.controller.js +++ b/src/app/reports/product.controller.js @@ -73,11 +73,18 @@ angular.module('reportsModule') tooltip: { formatter: function() { return [ - this.series.name , ': ' , - '' , this.point.units_sold , ' units @ $' , this.y , '' + this.series.name , '
', + this.point.sku , ': ' , this.point.units_sold , ' units @ $' , this.y , '', ].join(''); } - } + }, + + // Removes the dead space to the sides of the column-group + plotOptions: { + series: { + groupPadding: 0 + }, + }, }); return { @@ -111,6 +118,11 @@ angular.module('reportsModule') tooltip: { headerFormat: '' }, + plotOptions: { + series: { + groupPadding: 0 + } + }, series: [], }; } @@ -122,7 +134,11 @@ angular.module('reportsModule') return { // sku, units_sold name: product.name, - data: [{y: product.gross_sales, units_sold: product.units_sold}] + data: [{ + y: product.gross_sales, + units_sold: product.units_sold, + sku: product.sku, + }], }; } } From c23e3f7622f013c463d552142863c7c624425c16 Mon Sep 17 00:00:00 2001 From: Adam Knox Date: Tue, 12 Apr 2016 12:01:26 -0700 Subject: [PATCH 03/10] Close GH-273: update packages [#115293923]. --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 49bb3e0f..f0ef0522 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,7 @@ "gulp-imagemin": "^2.0.0", "gulp-inline-css": "^3.0.1", "gulp-jshint": "^1.10.0", - "gulp-livereload": "^3.8.0", "gulp-load-plugins": "^1.2.0", - "gulp-minify-css": "^0.3.13", - "gulp-minify-html": "^0.1.8", "gulp-plumber": "^1.0.1", "gulp-rename": "^1.2.2", "gulp-replace-task": "^0.11.0", From ea47d61fd1f67f7a0bda3e44aa22c97bcb05348f Mon Sep 17 00:00:00 2001 From: Adam Willoughby-Knox Date: Fri, 15 Apr 2016 02:09:22 -0400 Subject: [PATCH 04/10] sales reports v2 (#274) [#117565443] * vetting * vet and add avg cart size * add sales avg to table * add reports page, and customer activity report * use uib dropdowns instead of coding it ourselves, add a link back to reports from product * use uib dropdown, add footer stats * add note about the limit that was imposed * add sorting * update title * add payment method report page * wrong module nesting --- src/app/config/service/timezone.js | 25 +- src/app/dashboard/controller.js | 24 +- src/app/dashboard/menu/service.js | 2 +- src/app/dashboard/service/statistic.js | 338 ++++++++++-------- src/app/dashboard/welcome.html | 5 + .../reports/customer-activity.controller.js | 45 +++ src/app/reports/customer-activity.html | 69 ++++ src/app/reports/init.js | 13 +- src/app/reports/payment-method.controller.js | 43 +++ src/app/reports/payment-method.html | 61 ++++ src/app/reports/product.controller.js | 9 - src/app/reports/product.html | 18 +- src/app/reports/service.js | 43 ++- src/app/reports/view.html | 50 +++ 14 files changed, 542 insertions(+), 203 deletions(-) create mode 100644 src/app/reports/customer-activity.controller.js create mode 100644 src/app/reports/customer-activity.html create mode 100644 src/app/reports/payment-method.controller.js create mode 100644 src/app/reports/payment-method.html create mode 100644 src/app/reports/view.html diff --git a/src/app/config/service/timezone.js b/src/app/config/service/timezone.js index bca68fc0..d16f12c5 100644 --- a/src/app/config/service/timezone.js +++ b/src/app/config/service/timezone.js @@ -1,8 +1,8 @@ //TODO: Consider moving to coreModule angular.module('configModule') -.factory('timezoneService', ['configApiService', '$q', - function(configApiService, $q) { +.factory('timezoneService', ['configApiService', '$q', 'moment', + function(configApiService, $q, moment) { var storeTz = null; var service = { @@ -30,7 +30,7 @@ angular.module('configModule') function getTz() { // We have the tz return a promise wrapped value if (null !== storeTz) { - return $q.resolve(storeTz) + return $q.resolve(storeTz); } var config = { @@ -40,9 +40,8 @@ angular.module('configModule') return configApiService.getPath(config).$promise .then(function(response) { storeTz = response.result.substr(3); - return storeTz - }) - + return storeTz; + }); } /** @@ -51,7 +50,7 @@ angular.module('configModule') */ function makeDateRange(rangeString) { return getTz().then(function(tz) { - return _make(tz, rangeString) + return _make(tz, rangeString); }); //////////////////////// @@ -62,6 +61,8 @@ angular.module('configModule') var endDate = moment().utcOffset(tz).endOf('day'); switch (rangeString.toLowerCase()) { + case 'all time': + return {}; case 'today': startDate = startDate.startOf('day'); break; @@ -75,11 +76,17 @@ angular.module('configModule') case 'last 30 days': startDate = startDate.subtract(30, 'days').startOf('day'); break; + case 'month to date': + startDate = startDate.startOf('month'); + break; + case 'year to date': + startDate = startDate.startOf('year'); + break; } return { - startDate: startDate, - endDate: endDate + start_date: startDate.toISOString(), + end_date: endDate.toISOString(), }; } } diff --git a/src/app/dashboard/controller.js b/src/app/dashboard/controller.js index 2a9afa7a..2fbbe450 100644 --- a/src/app/dashboard/controller.js +++ b/src/app/dashboard/controller.js @@ -1,13 +1,13 @@ -angular.module("dashboardModule") - -.controller("dashboardController", [ - "$scope", - "$location", - "dashboardStatisticService", - "coreImageService", - "dashboardUtilsService", - "$timeout", - "moment", +angular.module('dashboardModule') + +.controller('dashboardController', [ + '$scope', + '$location', + 'dashboardStatisticService', + 'coreImageService', + 'dashboardUtilsService', + '$timeout', + 'moment', function( $scope, $location, @@ -35,7 +35,7 @@ angular.module("dashboardModule") // Other Widgets $scope.referrers = []; $scope.conversions = {}; - $scope.topSellers = {} + $scope.topSellers = {}; // REFACTOR OUT $scope.getProductImage = getProductImage; @@ -110,7 +110,7 @@ angular.module("dashboardModule") tickAmount: 24, labels: { formatter: function() { - return moment.utc(this.value).format('ha') + return moment.utc(this.value).format('ha'); } } }, diff --git a/src/app/dashboard/menu/service.js b/src/app/dashboard/menu/service.js index 0ae5f5c9..7241afa2 100644 --- a/src/app/dashboard/menu/service.js +++ b/src/app/dashboard/menu/service.js @@ -72,7 +72,7 @@ angular.module('dashboardModule') icon: 'fa-random' }, { title: 'Reports', - link: '/reports/product', + link: '/reports', icon: 'fa-area-chart' }, { title: 'Settings', diff --git a/src/app/dashboard/service/statistic.js b/src/app/dashboard/service/statistic.js index aae8527f..0bef8f6d 100644 --- a/src/app/dashboard/service/statistic.js +++ b/src/app/dashboard/service/statistic.js @@ -1,171 +1,203 @@ -angular.module("dashboardModule") -/** -* dashboardStatisticService implementation -*/ -.service("dashboardStatisticService", [ -"dashboardApiService", -"$q", -"moment", -function ($api, $q, moment) { - - - var getReferrers = function () { - return $api.getReferrers().$promise.then(function (response) { - return response.result; - }); - }; - - var getVisits = function () { - - return $api.getVisits().$promise.then(function (response) { - - var defaults = { - // total: {today: 0, yesterday: 0, week: 0}, - total: {today: moment().milliseconds(), yesterday: 0, week: 0}, - unique: {today: 0, yesterday: 0, week: 0} +angular.module('dashboardModule') + +.service('dashboardStatisticService', [ + 'dashboardApiService', + '$q', + 'moment', + '_', + function( + $api, + $q, + moment, + _ + ) { + + var service = { + getReferrers: getReferrers, + getVisits: getVisits, + getVisitsDetail: getVisitsDetail, + getConversions: getConversions, + getSales: getSales, + getSalesDetail: getSalesDetail, + getTopSellers: getTopSellers, + getVisitorsOnline: getVisitorsOnline, + }; + + return service; + + ////////////////////////////// + + function getReferrers() { + return $api.getReferrers().$promise.then(function(response) { + return response.result; + }); + } + + function getVisits() { + + return $api.getVisits().$promise.then(function(response) { + + var defaults = { + total: { today: 0, yesterday: 0, week: 0 }, + unique: { today: 0, yesterday: 0, week: 0 }, + }; + + return response.result || defaults; + }); + } + + function getSales() { + + return $api.getSales().$promise + .then(function(response) { + var defaults = { + sales: { today: 0, yesterday: 0, week: 0, monthToDate: 0}, + orders: { today: 0, yesterday: 0, week: 0, monthToDate: 0}, + }; + + return response.result || defaults; + }) + .then(function(result){ + // Add in average cart size + result.salesAvg = { + today: getAverageOrderSize('today'), + yesterday: getAverageOrderSize('yesterday'), + week: getAverageOrderSize('week'), + monthToDate: getAverageOrderSize('monthToDate'), + }; + + return result; + + ////// + + function getAverageOrderSize(param) { + if (!result.orders[param]) { + return 0; + } + return (result.sales[param] / result.orders[param]).toFixed(2); + } + }); + } + + function _processDetailResponse(points) { + + // Split into two sets + var set1 = points.splice(0, 24).map(function(point) { + var pointTime = point[0]; + pointTime = moment.unix(pointTime).add(1, 'day').valueOf(); + + return [pointTime, point[1]]; + }); + + var set2 = points.map(function(point) { + var pointTime = point[0]; + pointTime = moment.unix(pointTime).valueOf(); + + return [pointTime, point[1]]; + }); + + // z-index insures that today is on top + var dataSets = [{ + name: 'Today', + data: set2, + zIndex: 2 + }, { + name: 'Yesterday', + data: set1, + zIndex: 1 + }, ]; + + return dataSets; + } + + function getVisitsDetail() { + + var options = { + 'from': moment().subtract(1, 'day').format('YYYY-MM-DD'), + 'to': moment().add(1, 'day').format('YYYY-MM-DD') }; - // return defaults - return response.result || defaults; - }); - }; - - var getSales = function () { - - return $api.getSales().$promise.then(function (response) { - var defaults = { - // sales: {today: 0, yesterday: 0, week: 0}, - sales: {today: moment().milliseconds() * 102, yesterday: 0, week: 0}, - orders: {today: 0, yesterday: 0, week: 0} + + return $api.getVisitsDetails(options).$promise.then(function(response) { + return _processDetailResponse(response.result); + }); + } + + function getSalesDetail() { + var options = { + 'from': moment().subtract(1, 'day').format('YYYY-MM-DD'), + 'to': moment().add(1, 'day').format('YYYY-MM-DD') }; - // return defaults - return response.result || defaults; - }); - }; - var _processDetailResponse = function(points) { + return $api.getSalesDetails(options).$promise.then(function(response) { + return _processDetailResponse(response.result); + }); + } - // Split into two sets - var set1 = points.splice(0,24).map(function(point){ - var pointTime = point[0]; - pointTime = moment.unix(pointTime).add(1,'day').valueOf(); + function getConversions() { - return [pointTime, point[1]]; - }); + var getPercents = function(val, total) { + return Math.round((Math.abs(val / total) * 100) * 100) / 100 || 0; + }; - var set2 = points.map(function(point){ - var pointTime = point[0]; - pointTime = moment.unix(pointTime).valueOf(); + return $api.getConversions().$promise.then(function(response) { + var result = response.result || []; + var conversion = {}; - return [pointTime, point[1]]; - }); + if (null === response.error) { + conversion.addedToCart = result.addedToCart; + conversion.addedToCartPercent = getPercents(result.addedToCart, result.totalVisitors); - // z-index insures that today is on top - var dataSets = [ - {name: 'Today', data: set2, zIndex: 2}, - {name: 'Yesterday', data: set1, zIndex: 1}, - ]; + conversion.purchased = result.purchased; + conversion.purchasedPercent = getPercents(result.purchased, result.totalVisitors); - return dataSets; - } + conversion.reachedCheckout = result.visitCheckout; + conversion.reachedCheckoutPercent = getPercents(result.visitCheckout, result.totalVisitors); - var getVisitsDetail = function () { + conversion.setPayment = result.setPayment; + conversion.setPaymentPercent = getPercents(result.setPayment, result.totalVisitors); - var options = { - "from": moment().subtract(1,'day').format('YYYY-MM-DD'), - "to": moment().add(1,'day').format('YYYY-MM-DD') - }; + conversion.totalVisitors = result.totalVisitors; + } - return $api.getVisitsDetails(options).$promise.then(function (response) { - return _processDetailResponse(response.result); - }); - }; + return conversion; + }); + } - var getSalesDetail = function () { - var options = { - "from": moment().subtract(1,'day').format('YYYY-MM-DD'), - "to": moment().add(1,'day').format('YYYY-MM-DD') - }; + function getTopSellers() { + return $api.getTopSellers().$promise.then(function(response) { + return response.result; + }); + } - return $api.getSalesDetails(options).$promise.then(function (response) { - return _processDetailResponse(response.result); - }); - }; + function getVisitorsOnline() { + var defer; + defer = $q.defer(); + $api.getVisitorsOnline().$promise.then(function(response) { + var result, visitorsDetail; - var getConversions = function () { + result = response.result || []; + visitorsDetail = {}; - var getPercents = function (val, total) { - return Math.round((Math.abs(val/total) * 100) * 100) / 100 || 0; - }; + if (null === response.error) { + + visitorsDetail.direct = result.Direct; + visitorsDetail.directRatio = (Math.abs(result.DirectRatio) * 100).toFixed(2); + visitorsDetail.online = result.Online; + visitorsDetail.onlineRatio = (Math.abs(result.OnlineRatio) * 100).toFixed(2); + visitorsDetail.search = result.Search; + visitorsDetail.searchRatio = (Math.abs(result.SearchRatio) * 100).toFixed(2); + visitorsDetail.site = result.Site; + visitorsDetail.siteRatio = (Math.abs(result.SiteRatio) * 100).toFixed(2); + + defer.resolve(visitorsDetail); + } else { + defer.resolve(visitorsDetail); + } + }); + + return defer.promise; + } + } +]); - return $api.getConversions().$promise.then(function (response) { - var result = response.result || []; - var conversion = {}; - - if (null === response.error) { - conversion.addedToCart = result["addedToCart"]; - conversion.addedToCartPercent = getPercents(result["addedToCart"], result["totalVisitors"]); - - conversion.purchased = result["purchased"]; - conversion.purchasedPercent = getPercents(result["purchased"], result["totalVisitors"]); - - conversion.reachedCheckout = result["visitCheckout"]; - conversion.reachedCheckoutPercent = getPercents(result["visitCheckout"], result["totalVisitors"]); - - conversion.setPayment = result["setPayment"]; - conversion.setPaymentPercent = getPercents(result["setPayment"], result["totalVisitors"]); - - conversion.totalVisitors = result["totalVisitors"]; - } - - return conversion; - }); - }; - - var getTopSellers = function () { - return $api.getTopSellers().$promise.then(function (response) { - return response.result; - }); - }; - - var getVisitorsOnline = function () { - var defer; - defer = $q.defer(); - - $api.getVisitorsOnline().$promise.then(function (response) { - var result, visitorsDetail; - - result = response.result || []; - visitorsDetail = {}; - - if (null === response.error) { - - visitorsDetail["direct"] = result.Direct; - visitorsDetail["directRatio"] = (Math.abs(result.DirectRatio) * 100).toFixed(2); - visitorsDetail["online"] = result.Online; - visitorsDetail["onlineRatio"] = (Math.abs(result.OnlineRatio) * 100).toFixed(2); - visitorsDetail["search"] = result.Search; - visitorsDetail["searchRatio"] = (Math.abs(result.SearchRatio) * 100).toFixed(2); - visitorsDetail["site"] = result.Site; - visitorsDetail["siteRatio"] = (Math.abs(result.SiteRatio) * 100).toFixed(2); - - defer.resolve(visitorsDetail); - } else { - defer.resolve(visitorsDetail); - } - }); - - return defer.promise; - }; - - return { - getReferrers: getReferrers, - getVisits: getVisits, - getVisitsDetail: getVisitsDetail, - getConversions: getConversions, - getSales: getSales, - getSalesDetail: getSalesDetail, - getTopSellers: getTopSellers, - getVisitorsOnline: getVisitorsOnline - }; -}]); diff --git a/src/app/dashboard/welcome.html b/src/app/dashboard/welcome.html index cd320b8f..1915df41 100644 --- a/src/app/dashboard/welcome.html +++ b/src/app/dashboard/welcome.html @@ -19,6 +19,7 @@

Sales

+ @@ -26,21 +27,25 @@

Sales

+ + + +
Total Sales Order CountSales Avg.
Today $ $
Yesterday {{salesStats.sales.yesterday | currency}} {{salesStats.orders.yesterday}}{{salesStats.salesAvg.yesterday | currency}}
Last 7 days {{salesStats.sales.week | currency}} {{salesStats.orders.week}}{{salesStats.salesAvg.week | currency}}
Month to date {{salesStats.sales.monthToDate | currency}} {{salesStats.orders.monthToDate}}{{salesStats.salesAvg.monthToDate | currency}}
diff --git a/src/app/reports/customer-activity.controller.js b/src/app/reports/customer-activity.controller.js new file mode 100644 index 00000000..25378e74 --- /dev/null +++ b/src/app/reports/customer-activity.controller.js @@ -0,0 +1,45 @@ +angular.module('reportsModule') + +.controller('reportsCustomerActivityController', [ + '$scope', 'timezoneService', 'reportsService', '$location', + function($scope, timezoneService, reportsService, $location) { + $scope.report = {}; + $scope.timeframe = { + frame: 'last 7 days', + options: [ + 'today', + 'last 7 days', + 'month to date', + 'year to date', + 'all time', + ], + set: setTimeframe, + }; + $scope.sort = $location.search().sort || ''; + + activate(); + + //////////////////// + + function activate(){ + fetchReport($scope.timeframe.frame); + } + + function setTimeframe(frame) { + $scope.timeframe.frame = frame; + fetchReport(frame); + } + + function fetchReport(frame) { + timezoneService.makeDateRange(frame) + .then(function(options) { + options.sort = $scope.sort; + return reportsService.customerActivity(options); + }) + .then(function(report){ + $scope.report = report; + }); + } + } +]); + diff --git a/src/app/reports/customer-activity.html b/src/app/reports/customer-activity.html new file mode 100644 index 00000000..f2d07345 --- /dev/null +++ b/src/app/reports/customer-activity.html @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EmailNameTotal SalesTotal OrdersAvg Order AmountFirst Purchase DateMost Recent Purchase
{{c.email}}{{c.name}}{{c.total_sales | currency}}{{c.total_orders}}{{c.avg_sales | currency}}{{c.earliest_purchase | otStoreDate}}{{c.latest_purchase | otStoreDate}}
+ No results found for this timeframe. +
+ + count: {{ report.meta.count }}, + limit: {{report.meta.limit}}, + perf: {{report.perf_ms.toFixed(2)}} ms, + frame: {{timeframe.frame}} + +
+ diff --git a/src/app/reports/init.js b/src/app/reports/init.js index 93e57b80..143a7add 100644 --- a/src/app/reports/init.js +++ b/src/app/reports/init.js @@ -7,9 +7,20 @@ angular.module('reportsModule', [ .config(['$routeProvider', function($routeProvider) { $routeProvider + .when('/reports', { + templateUrl: '/views/reports/view.html', + }) .when('/reports/product', { templateUrl: '/views/reports/product.html', - controller: 'reportsProductController' + controller: 'reportsProductController', + }) + .when('/reports/customer-activity', { + templateUrl: '/views/reports/customer-activity.html', + controller: 'reportsCustomerActivityController', + }) + .when('/reports/payment-method', { + templateUrl: '/views/reports/payment-method.html', + controller: 'reportsPaymentMethodController', }); }]); diff --git a/src/app/reports/payment-method.controller.js b/src/app/reports/payment-method.controller.js new file mode 100644 index 00000000..8e048dac --- /dev/null +++ b/src/app/reports/payment-method.controller.js @@ -0,0 +1,43 @@ +angular.module('reportsModule') + +.controller('reportsPaymentMethodController', [ + '$scope', 'timezoneService', 'reportsService', '$location', + function($scope, timezoneService, reportsService, $location) { + $scope.report = {}; + $scope.timeframe = { + frame: 'last 7 days', + options: [ + 'today', + 'last 7 days', + 'month to date', + 'year to date', + 'all time', + ], + set: setTimeframe, + }; + + activate(); + + //////////////////// + + function activate(){ + fetchReport($scope.timeframe.frame); + } + + function setTimeframe(frame) { + $scope.timeframe.frame = frame; + fetchReport(frame); + } + + function fetchReport(frame) { + timezoneService.makeDateRange(frame) + .then(function(options) { + return reportsService.paymentMethod(options); + }) + .then(function(report){ + $scope.report = report; + }); + } + } +]); + diff --git a/src/app/reports/payment-method.html b/src/app/reports/payment-method.html new file mode 100644 index 00000000..7e63ae4a --- /dev/null +++ b/src/app/reports/payment-method.html @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTotal SalesTotal OrdersAverage Order Size
{{pm.method_name}} ({{pm.key}}){{pm.total_sales | currency}}{{pm.total_orders}}{{pm.avg_sales | currency}}
+ No results found for this timeframe. +
+ + perf: {{report.perf_ms.toFixed(2)}} ms, + frame: {{timeframe.frame}} + +
+ diff --git a/src/app/reports/product.controller.js b/src/app/reports/product.controller.js index 9ff872ae..a1427585 100644 --- a/src/app/reports/product.controller.js +++ b/src/app/reports/product.controller.js @@ -16,9 +16,7 @@ angular.module('reportsModule') 'last 7 days', 'last 30 days', ], - isOpen: false, set: setTimeframe, - toggle: toggle, }; $scope.chartConfig = getChartConfig(); @@ -41,16 +39,9 @@ angular.module('reportsModule') */ function setTimeframe(frame) { $scope.timeframe.frame = frame; - $scope.timeframe.isOpen = false; - fetchReport(frame); } - // Open/Close the timeframe dropdown - function toggle() { - $scope.timeframe.isOpen = !$scope.timeframe.isOpen; - } - // Fetch a report for a timeframe string, and make sure // to modify the dates for the store tz function fetchReport(frame) { diff --git a/src/app/reports/product.html b/src/app/reports/product.html index 61e53996..347d87f1 100644 --- a/src/app/reports/product.html +++ b/src/app/reports/product.html @@ -1,17 +1,17 @@ \ No newline at end of file diff --git a/src/app/subscriptions/edit.html b/src/app/subscriptions/edit.html index 93ec8ec1..3f81479a 100644 --- a/src/app/subscriptions/edit.html +++ b/src/app/subscriptions/edit.html @@ -126,17 +126,17 @@

Details

Created At:
-
{{ subscription.created_at | otStoreDate }}
+
Last Submit:
-
{{ subscription.last_submit | otStoreDate }}
+
--
Updated At:
-
{{ subscription.updated_at | otStoreDate }}
+
Next Action:
-
{{ subscription.action_date | otStoreDate }}
+
diff --git a/src/app/visitor/edit.html b/src/app/visitor/edit.html index a45d30c7..b9d82b67 100644 --- a/src/app/visitor/edit.html +++ b/src/app/visitor/edit.html @@ -43,7 +43,7 @@

- {{ order.Extra.created_at | otStoreDate }} + {{ order.Extra._id }}
@@ -75,7 +75,7 @@

- {{ subscription.Extra.created_at | otStoreDate }} + {{ subscription.Extra._id }} {{ subscription.Extra.status }} From d4bbf46bb1eec90a54cbe0c1933747d51f52d4b9 Mon Sep 17 00:00:00 2001 From: Adam Willoughby-Knox Date: Wed, 20 Apr 2016 21:10:03 -0400 Subject: [PATCH 08/10] add shipping method report (#277) [#117565521] * add shipping method report * add two location reports - move simple table report into a directive From fb8c886a4808888f4a5885e8cb06ff49a0b9c821 Mon Sep 17 00:00:00 2001 From: Adam Knox Date: Thu, 21 Apr 2016 10:41:01 -0400 Subject: [PATCH 09/10] :bug: saving products against category --- src/app/category/api.service.js | 7 ++-- src/app/category/edit.controller.js | 52 ++++++++++++++++------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/app/category/api.service.js b/src/app/category/api.service.js index 934e6aac..2c8ba235 100644 --- a/src/app/category/api.service.js +++ b/src/app/category/api.service.js @@ -52,8 +52,11 @@ angular.module("categoryModule") "addProduct": { method: "POST", params: { - categoryID: "@categoryId", - productID: "@productId" + // this is a post method, but we don't really care about the data as much + // as the params, the `@` extracts the param values from the post data + // so that we don't have to write `addProduct({},params) + categoryID: "@categoryID", + productID: "@productID" }, url: REST_SERVER_URI + "/category/:categoryID/product/:productID" }, diff --git a/src/app/category/edit.controller.js b/src/app/category/edit.controller.js index db6e5fe5..9ee7887e 100644 --- a/src/app/category/edit.controller.js +++ b/src/app/category/edit.controller.js @@ -11,7 +11,7 @@ angular.module("categoryModule") function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtilsService, _) { var savedProducts = [] - + // Initialize SEO if (typeof $scope.initSeo === "function") { $scope.initSeo("category"); @@ -59,33 +59,31 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil }; $scope.saveProducts = function () { - var promises = []; - - var categoryId = $scope.category.id || $scope.category._id; + var categoryID = $scope.category.id || $scope.category._id; var newProductList = $scope.category.product_ids; - var products_to_remove = _.difference(savedProducts,newProductList); - var products_to_add = _.difference(newProductList,savedProducts); + var toRemove = _.difference(savedProducts, newProductList); + var toAdd = _.difference(newProductList, savedProducts); + + var promises = _.map(toRemove, removePid); + promises = promises.concat( _.map(toAdd, addPid) ); - var removePromise = _.map(toRemove, removePid); - var addPromise = _.map(toAdd, addPid); - return $q.all(promises); ///////////////// - - function removePids(productID){ + + function removePid(productID){ var params = { - categoryID: categoryId, - productID: productID + categoryID: categoryID, + productID: productID, }; - return categoryApiService.removeProduct(params).$promise + return categoryApiService.removeProduct(params).$promise; } - function addPids(productID){ + function addPid(productID){ var params = { - categoryID: categoryId, - productID: productID + categoryID: categoryID, + productID: productID, }; return categoryApiService.addProduct(params).$promise; } @@ -101,14 +99,17 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil var defer = $q.defer(); var id = $scope.category.id || $scope.category._id; - // Props that we don't want to pass up + // Props that aren't recognized by the server delete $scope.category.parent; delete $scope.category.path; delete $scope.category.products; - delete $scope.category.product_ids; if (!id) { if ($scope.category.name !== '') { + + // Props that aren't recognized by the server + delete $scope.category.product_ids; + categoryApiService.save($scope.category).$promise .then(saveSuccess, saveError) .then(function(){ @@ -118,7 +119,10 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil } else { $scope.category.id = id; $scope.saveProducts().then(function () { - + + // Props that aren't recognized by the server + delete $scope.category.product_ids; + categoryApiService.update($scope.category).$promise .then(updateSuccess, updateError) .then(function(){ @@ -128,7 +132,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil } return defer.promise; - + //////////////// function saveSuccess(response) { @@ -137,7 +141,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil $scope.message = dashboardUtilsService.getMessage(null, 'success', 'Category was created successfully'); defer.resolve(true); } - + allowSaving(); }; @@ -151,7 +155,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil $scope.category = response.result || getDefaultCategory(); $scope.message = dashboardUtilsService.getMessage(null, 'success', 'Product was updated successfully'); defer.resolve(true); - + allowSaving(); } }; @@ -160,7 +164,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil defer.resolve(false); allowSaving(); }; - + // Refactor function allowSaving() { $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); From e5bb2d74af0adade641949e5a3a0e9d7c865b9fb Mon Sep 17 00:00:00 2001 From: James Vastbinder Date: Thu, 21 Apr 2016 12:28:04 -0700 Subject: [PATCH 10/10] version bump for v1.1.16 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f0ef0522..02005906 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashboard", - "version": "1.1.141", + "version": "1.1.16", "description": "Ottemo Administration Tool", "main": "gulpfile.js", "repository": {