diff --git a/package.json b/package.json index 49bb3e0f..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": { @@ -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", diff --git a/src/app/app.scss b/src/app/app.scss index 06961629..58e924f8 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -22,6 +22,7 @@ @import 'login/login'; @import 'order/order'; @import 'product/product'; +@import 'reports/reports'; @import 'seo/seo'; @import 'subscriptions/subscriptions'; @import 'visitor/visitor'; \ No newline at end of file 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 027aa3c6..9ee7887e 100644 --- a/src/app/category/edit.controller.js +++ b/src/app/category/edit.controller.js @@ -9,13 +9,15 @@ angular.module("categoryModule") "dashboardUtilsService", "_", function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtilsService, _) { - var categoryId, rememberProducts, oldProducts, getDefaultCategory; + + var savedProducts = [] + // Initialize SEO if (typeof $scope.initSeo === "function") { $scope.initSeo("category"); } - categoryId = $routeParams.id; + var categoryId = $routeParams.id; if (!categoryId && categoryId !== "new") { $location.path("/categories"); @@ -25,9 +27,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil categoryId = null; } - oldProducts = []; - - getDefaultCategory = function () { + function getDefaultCategory() { return { name: "", "parent_id": "", @@ -35,11 +35,6 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil }; }; - /** - * Current selected category - * - * @type {Object} - */ $scope.category = {}; /** @@ -55,7 +50,7 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil var result = response.result || {}; $scope.category = result; $scope.category.parent = $scope.category['parent_id']; - $scope.category.products = $scope.category.product_ids; + savedProducts = $scope.category.product_ids; }); } @@ -64,34 +59,34 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil }; $scope.saveProducts = function () { - var promises = []; - - var categoryId = $scope.category.id || $scope.category._id; - var _prev = $scope.category.product_ids; - var _new = $scope.category.products; - - var products_to_remove = _.difference(_prev,_new); - var products_to_add = _.difference(_new,_prev); - - if (products_to_remove.length){ - _.each(products_to_remove, function(productID){ - promises.push(categoryApiService.removeProduct({ - categoryID: categoryId, - productID: productID - })) - }) - } + var categoryID = $scope.category.id || $scope.category._id; + var newProductList = $scope.category.product_ids; - if (products_to_add.length){ - _.each(products_to_add, function(productID){ - promises.push(categoryApiService.addProduct({ - categoryId: categoryId, - productId: productID - })) - }) - } + var toRemove = _.difference(savedProducts, newProductList); + var toAdd = _.difference(newProductList, savedProducts); + + var promises = _.map(toRemove, removePid); + promises = promises.concat( _.map(toAdd, addPid) ); return $q.all(promises); + + ///////////////// + + function removePid(productID){ + var params = { + categoryID: categoryID, + productID: productID, + }; + return categoryApiService.removeProduct(params).$promise; + } + + function addPid(productID){ + var params = { + categoryID: categoryID, + productID: productID, + }; + return categoryApiService.addProduct(params).$promise; + } }; /** @@ -101,75 +96,81 @@ function ($scope, $routeParams, $location, $q, categoryApiService, dashboardUtil $scope.save = function () { $('[ng-click="save()"]').addClass('disabled').append('').siblings('.btn').addClass('disabled'); - var id, defer, saveSuccess, saveError, updateSuccess, updateError; - defer = $q.defer(); + var defer = $q.defer(); + var id = $scope.category.id || $scope.category._id; + + // Props that aren't recognized by the server + delete $scope.category.parent; + delete $scope.category.path; + delete $scope.category.products; + + 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(){ + savedProducts = $scope.category.product_ids; + }); + } + } else { + $scope.category.id = id; + $scope.saveProducts().then(function () { + + // Props that aren't recognized by the server + delete $scope.category.product_ids; - if (typeof $scope.category !== "undefined") { - id = $scope.category.id || $scope.category._id; + categoryApiService.update($scope.category).$promise + .then(updateSuccess, updateError) + .then(function(){ + savedProducts = $scope.category.product_ids; + }); + }); } - saveSuccess = function (response) { + return defer.promise; + + //////////////// + + function saveSuccess(response) { if (response.error === null) { $scope.category = response.result || getDefaultCategory(); $scope.message = dashboardUtilsService.getMessage(null, 'success', 'Category was created successfully'); defer.resolve(true); } - $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); - $('[ng-click="save()"]').siblings('.btn').removeClass('disabled'); + + allowSaving(); }; - saveError = function () { + function saveError() { defer.resolve(false); - $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); - $('[ng-click="save()"]').siblings('.btn').removeClass('disabled'); + allowSaving(); }; - updateSuccess = function (response) { + function updateSuccess(response) { if (response.error === null) { $scope.category = response.result || getDefaultCategory(); $scope.message = dashboardUtilsService.getMessage(null, 'success', 'Product was updated successfully'); defer.resolve(true); - $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); - $('[ng-click="save()"]').siblings('.btn').removeClass('disabled'); + + allowSaving(); } }; - updateError = function () { + function updateError() { defer.resolve(false); - $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); - $('[ng-click="save()"]').siblings('.btn').removeClass('disabled'); + allowSaving(); }; - delete $scope.category.parent; - delete $scope.category.path; - - - if (!id) { - if ($scope.category.name !== '') { - - delete $scope.category.products; - categoryApiService.save($scope.category).$promise - .then(saveSuccess, saveError) - .then(function(){ - $scope.category.products = $scope.category.product_ids; - }); - } - } else { - $scope.category.id = id; - $scope.saveProducts().then(function () { - - // Clean the associated product list off, before posting up - delete $scope.category.products; - categoryApiService.update($scope.category).$promise - .then(updateSuccess, updateError) - .then(function(){ - $scope.category.products = $scope.category.product_ids; - }); - }); - + // Refactor + function allowSaving() { + $('[ng-click="save()"]').removeClass('disabled').children('i').remove(); + $('[ng-click="save()"]').siblings('.btn').removeClass('disabled'); } - return defer.promise; }; }]); \ No newline at end of file diff --git a/src/app/config/directives/ot-store-date.directive.js b/src/app/config/directives/ot-store-date.directive.js new file mode 100644 index 00000000..4df8773a --- /dev/null +++ b/src/app/config/directives/ot-store-date.directive.js @@ -0,0 +1,40 @@ +angular.module("configModule") + +.directive('otStoreDate', + ['timezoneService', '$filter', + function(timezoneService, $filter) { + return { + restrict: 'EA', + template: '{{localDate}}', + scope: { + 'date' : '=', + }, + link: function(scope, element, attrs) { + + scope.localDate = ''; + + activate(); + + //////////////// + + function activate() { + update(); + scope.$watch('date', update); + } + + function update() { + scope.localDate = scope.date ? 'Loading...' : '-'; + + if (!scope.date) { + return; + } + + timezoneService.get().then(function(tz){ + scope.localDate = $filter('date')(scope.date, 'MM/dd/yyyy hh:mma', tz); + }); + } + } + }; + } +]); + diff --git a/src/app/config/filters/ot-storedate.js b/src/app/config/filters/ot-storedate.js deleted file mode 100644 index 3845bfab..00000000 --- a/src/app/config/filters/ot-storedate.js +++ /dev/null @@ -1,12 +0,0 @@ -angular.module("configModule") - -.filter('otStoreDate', ['timezoneService', '$filter', - function(timezoneService, $filter) { - return function(input) { - if (!input) return ""; - - return $filter('date')(input, 'MM/dd/yyyy hh:mma', timezoneService.storeTz); - } - } -]); - diff --git a/src/app/config/init.js b/src/app/config/init.js index 03a49c1e..9b1d21b1 100644 --- a/src/app/config/init.js +++ b/src/app/config/init.js @@ -1,16 +1,14 @@ -/** - * Config Module - */ -angular.module("configModule", ["ngRoute", "ngResource", "coreModule"]) +angular.module('configModule', [ + 'ngRoute', + 'ngResource', + 'coreModule' +]) -.config(["$routeProvider", function ($routeProvider) { +.config(['$routeProvider', function($routeProvider) { $routeProvider - .when("/settings/:group", { - templateUrl: "/views/config/edit.html", - controller: "configEditController" + .when('/settings/:group', { + templateUrl: '/views/config/edit.html', + controller: 'configEditController', }); -}]) +}]); -.run(['timezoneService', function (timezoneService) { - timezoneService.init(); -}]); \ No newline at end of file diff --git a/src/app/config/service/timezone.js b/src/app/config/service/timezone.js index bca68fc0..c403e566 100644 --- a/src/app/config/service/timezone.js +++ b/src/app/config/service/timezone.js @@ -1,48 +1,30 @@ -//TODO: Consider moving to coreModule angular.module('configModule') -.factory('timezoneService', ['configApiService', '$q', - function(configApiService, $q) { - var storeTz = null; +.factory('timezoneService', ['configApiService', '$q', 'moment', + function(configApiService, $q, moment) { + var tzPromise = false; var service = { get: getTz, makeDateRange: makeDateRange, - init: init, // @deprecated - storeTz: 0, // @deprecated }; return service; //////////////////////// - function init() { - - // Cache the store tz - configApiService.getPath({ - path: 'general.store.timezone' - }).$promise - .then(function(response) { - service.storeTz = response.result.substr(3); - }); - } - function getTz() { - // We have the tz return a promise wrapped value - if (null !== storeTz) { - return $q.resolve(storeTz) - } - var config = { - path: 'general.store.timezone' - }; + if (!tzPromise){ + var config = { path: 'general.store.timezone' }; - return configApiService.getPath(config).$promise - .then(function(response) { - storeTz = response.result.substr(3); - return storeTz - }) + tzPromise = configApiService.getPath(config).$promise + .then(function(response) { + return response.result.substr(3); + }); + } + return tzPromise; } /** @@ -51,7 +33,7 @@ angular.module('configModule') */ function makeDateRange(rangeString) { return getTz().then(function(tz) { - return _make(tz, rangeString) + return _make(tz, rangeString); }); //////////////////////// @@ -62,6 +44,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 +59,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/core/directives/editor/ot-not-editable.html b/src/app/core/directives/editor/ot-not-editable.html index 5b2fe9c8..d449055b 100644 --- a/src/app/core/directives/editor/ot-not-editable.html +++ b/src/app/core/directives/editor/ot-not-editable.html @@ -1,6 +1,7 @@
- - {{ item[attribute.Attribute] | otStoreDate }} + {{ item[attribute.Attribute] }} 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..5333d465 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 @@