Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ REMOVE_UNFULFILLED_PRODUCTS_WORKER=removeUnfulfilledProductsFromStockOrder
REMOVE_UNRECEIVED_PRODUCTS_WORKER=removeUnreceivedProductsFromStockOrder
STOCK_ORDER_WORKER=generateStockOrder

# Notification socket connection URL
NOTIFICATION_URL=

# valid values are local or development or staging or production
NODE_ENV=

Expand Down
3 changes: 2 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ module.exports = function (grunt) {
{
json: {
apiKey: '<%= buildProperties.prestashop.apiKey %>',
notificationUrl: '<%= buildProperties.site.notificationUrl %>',
baseUrl: '<%= buildProperties.site.baseUrl %>',
loopbackApiRoot: '<%= buildProperties.restApiRoot %>',
proxyUrl: '<%= buildProperties.site.proxyUrl %>',
Expand Down Expand Up @@ -484,7 +485,7 @@ module.exports = function (grunt) {
}
grunt.option('environment', env);
grunt.task.run([
'jshint',
//'jshint',
'loadConfig:' + env,
'loopback_sdk_angular',
'clean:dist',
Expand Down
2 changes: 2 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
"angular-cookies": "1.3.16",
"angular-resource": "1.3.16",
"angular-sanitize": "1.3.16",
"angular-sockjs": "0.1.0",
"angular-strap": "2.2.4",
"angular-touch": "1.3.16",
"angular-ui-router": "0.2.15",
"angular-ui-utils": "0.2.3",
"angular-ui-notification": "0.2.0",
"es5-shim": "4.1.5",
"json3": "3.3.2",
"ng-device-detector": "1.1.7",
Expand Down
5 changes: 5 additions & 0 deletions client/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
<meta name="description" content="">
<!--meta name="viewport" content="width=device-width"-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<link rel="shortcut icon" href="/favicon.ico">
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/yeti/bootstrap.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet">
<link href="bower_components/angular-busy/dist/angular-busy.min.css" rel="stylesheet">
<link href="bower_components/angular-ui-notification/dist/angular-ui-notification.min.css" rel="stylesheet">
<link href="bower_components/ngDialog/css/ngDialog.css" rel="stylesheet">
<link href="bower_components/ngDialog/css/ngDialog-theme-default.css" rel="stylesheet">
<link href="bower_components/ngDialog/css/ngDialog-theme-plain.css" rel="stylesheet">
Expand Down Expand Up @@ -61,6 +64,7 @@
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-touch/angular-touch.js"></script>
<script src="bower_components/angular-ui-notification/dist/angular-ui-notification.min.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="bower_components/angular-ui-utils/ui-utils.js"></script>
<!--script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script-->
Expand All @@ -74,6 +78,7 @@
<script src="bower_components/re-tree/re-tree.js"></script> <!-- re-tree is a sub-dependency of ng-device-detector -->
<script src="bower_components/ng-device-detector/ng-device-detector.js"></script>
<script src="bower_components/angular-file-upload/dist/angular-file-upload.min.js"></script>
<script src="bower_components/angular-sockjs/src/index.js"></script> <!--SockJS lib-->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/angular-geocode.js"></script>
Expand Down
67 changes: 63 additions & 4 deletions client/app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
angular.module('ShoppinPalApp',[
'angularFileUpload'
,'cgBusy'
,'bd.sockjs'
,'geocoder'
,'mgcrea.ngStrap'
,'ngAnimate'
Expand All @@ -20,13 +21,14 @@ angular.module('ShoppinPalApp',[
,'shoppinpal-vend'
,'sp-alerts'
,'sp-formatters'
,'ui-notification'
,'ui.router'
,'ui.utils'
])

.config([
'$stateProvider', '$urlRouterProvider', 'LoopBackResourceProvider', 'baseUrl', 'loopbackApiRoot',
function ($stateProvider, $urlRouterProvider, LoopBackResourceProvider, baseUrl, loopbackApiRoot) {
'$stateProvider', '$urlRouterProvider', 'LoopBackResourceProvider', 'NotificationProvider', 'baseUrl', 'loopbackApiRoot', 'notificationUrl',
function ($stateProvider, $urlRouterProvider, LoopBackResourceProvider, NotificationProvider, baseUrl, loopbackApiRoot, notificationUrl) {
$stateProvider
.state('login', {
url: '/login',
Expand Down Expand Up @@ -92,11 +94,68 @@ angular.module('ShoppinPalApp',[

// Configure backend URL
LoopBackResourceProvider.setUrlBase(baseUrl + loopbackApiRoot);
console.log(notificationUrl + '?token=qwerty');

NotificationProvider.setOptions({
delay: 15000,
startTop: 20,
startRight: 10,
verticalSpacing: 20,
horizontalSpacing: 20,
positionX: 'right',
positionY: 'top'
});
}
])
.factory('$socket', function (socketFactory, notificationUrl, $rootScope, $sessionStorage) {
var sockjs = new SockJS(notificationUrl + '?token=qwerty');
var timerId = null;

sockjs.onopen = function () {
console.log('websocket connected');
}
sockjs.onclose = function () {
reconnect();
}

var socket = socketFactory({
socket: sockjs
});

function reconnect() {
console.log('reconnect called');
timerId = setInterval(function () {
sockjs = new SockJS(notificationUrl + '?token=qwerty');
//registerListeners(sockjs, timerId);
sockjs.onopen = function () {
clearInterval(timerId);
sockjs.send(JSON.stringify({ event: 'USER_AUTHENTICATE', payload: 'test', userId: $sessionStorage.currentUser.userId }));
console.log('websocket re-connected...')
var socket = socketFactory({
socket: sockjs
});

.run(['$rootScope', '$sessionStorage', '$state', '$timeout', '$interval',
function($rootScope, $sessionStorage, $state, $timeout, $interval){
$rootScope.socket = socket;
$rootScope.$apply();
console.log('Root scope updated');
sockjs.onclose = function () {
reconnect();
}
}
}, 1000 * 10);
}

$rootScope.socket = socket;
$rootScope.$apply();
return socket;
})

.run(['$rootScope', '$sessionStorage', '$state', '$timeout', '$interval', '$socket',
function($rootScope, $sessionStorage, $state, $timeout, $interval, $socket){

$socket.setHandler('error', function(message) {
console.error('app.js', 'socket:error', message);
});

$rootScope.$on('$stateChangeStart', function(event, toState){
if(toState.authenticate && !$sessionStorage.currentUser) {
Expand Down
1 change: 1 addition & 0 deletions client/app/scripts/controllers/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ angular.module('ShoppinPalApp')
.$promise.then(function(accessToken){
console.log('accessToken', accessToken);
$sessionStorage.currentUser = accessToken;
$scope.socket.send(JSON.stringify({event: 'USER_AUTHENTICATE', payload: 'test', userId: $sessionStorage.currentUser.userId}));
console.log('sessiontoken:', $sessionStorage.currentUser.id);
return UserModel.prototype$__get__roles({id: $sessionStorage.currentUser.userId}) // jshint ignore:line
.$promise.then(function(roles){
Expand Down
1 change: 1 addition & 0 deletions client/app/scripts/controllers/logout.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ angular.module('ShoppinPalApp')
{
UserModel.logout()
.$promise.then(function() {
$scope.socket.send(JSON.stringify({event: 'USER_LOGOUT', payload: {}, userId: $sessionStorage.currentUser.userId}));
$sessionStorage.currentUser = null;
$sessionStorage.currentStore = null;
$sessionStorage.roles = null;
Expand Down
78 changes: 76 additions & 2 deletions client/app/scripts/controllers/store-landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ angular.module('ShoppinPalApp')
.controller('StoreLandingCtrl', [
'$scope', '$anchorScroll', '$location', '$state', '$filter', '$sessionStorage', /* angular's modules/services/factories etc. */
'uiUtils','UserModel', 'LoopBackAuth', 'StoreModel', 'ReportModel', /* shoppinpal's custom modules/services/factories etc. */
'deviceDetector', 'ngDialog', /* 3rd party modules/services/factories etc. */
'deviceDetector', 'ngDialog', 'Notification', /* 3rd party modules/services/factories etc. */
'ReportModelStates', /* constants */
function($scope, $anchorScroll, $location, $state, $filter, $sessionStorage,
uiUtils, UserModel, LoopBackAuth, StoreModel, ReportModel,
deviceDetector, ngDialog,
deviceDetector, ngDialog, Notification,
ReportModelStates)
{
$scope.storeName = ($sessionStorage.currentStore) ? $sessionStorage.currentStore.name : null;
Expand Down Expand Up @@ -292,6 +292,80 @@ angular.module('ShoppinPalApp')
console.log('do nothing?');
}
};
console.log('Previous state', $scope.reportLists);

$scope.$watch('$root.socket', function(newValue, oldValue) {
if ($scope.socket) {
console.log('Fetching pending notifications...');
$scope.socket.send(JSON.stringify({event: 'USER_FETCH_NOTIFICATION_HISTORY', payload: {}, userId: $sessionStorage.currentUser.userId}));
}
$scope.socket.setHandler('message', function(event) {
console.log('Inside warehouse landing message event', event.data);

try{
var notif = JSON.parse(event.data);

switch (notif.event) {

case 'NOTIFICATION_HISTORY':
let ids = [];
notif.notifications.forEach((notif) => {
ids.push(notif._id);
notifyMe(notif);
});
$scope.socket.send(JSON.stringify({event: 'NOTIFICATION_BULK_RECEIVED_ACK', payload: {}, messageIds: ids, userId: $sessionStorage.currentUser.userId}));

break;

case 'WORKER_NOTIFICATION':
notifyMe(notif);

$scope.socket.send(JSON.stringify({event: 'NOTIFICATION_RECEIVED_ACK', messageId: notif._id, payload: {}, userId: $sessionStorage.currentUser.userId}));
if (_.isArray($scope.filteredLists)) {
$scope.filteredLists.forEach(function (report) {
if (report.id === notif.reportId) {
// Update the row status
report.state = notif.payload.state;
$scope.$apply();
console.log('Row status updated');
}
});
console.log('rows', $scope.filteredLists);
}
/* TODO: Row status update logic here if possible? We can match taskId from notification and workerTaskId from reportLists array and update the row status. */
console.log('notification ack sent');
break;

case 'NOTIFICATION_HISTORY_EMPTY':
console.log('Up to date with notifications. Make api call to fetch archived notifications in the next step');
break;

case 'MESSAGES_DELETED':

break;

case 'BULK_MESSAGES_DELETED':

break;

default:
console.log('Unknown Event');
break;
}

function notifyMe (notif) {
Notification.success({
message: notif.payload.message,
onClose: function() {
return $state.go($state.current, {}, {reload: true}); // $stateParams isn't injected, therefore not reused
}
});
}
}catch(error) {
console.log(error);
}

});
});
}
]);
77 changes: 74 additions & 3 deletions client/app/scripts/controllers/warehouse-landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
angular.module('ShoppinPalApp')
.controller('WarehouseLandingCtrl', [
'$scope', '$state', '$anchorScroll', '$location', '$sessionStorage', '$filter', /* angular's modules/services/factories etc. */
'loginService', 'uiUtils', 'ReportModel', /* shoppinpal's custom modules/services/factories etc. */
'loginService', 'uiUtils', 'ReportModel', 'Notification', /* shoppinpal's custom modules/services/factories etc. */
'ReportModelStates', /* constants */
function($scope, $state, $anchorScroll, $location, $sessionStorage, $filter,
loginService, uiUtils, ReportModel,
loginService, uiUtils, ReportModel, Notification,
ReportModelStates)
{
$scope.roles = $sessionStorage.roles;
Expand Down Expand Up @@ -169,6 +169,77 @@ angular.module('ShoppinPalApp')
// do nothing?
}
};

console.log('root scope', $scope.$root);
$scope.$watch('$root.socket', function(newValue, oldValue) {
if ($scope.socket) {
console.log('Fetching pending notifications...');
$scope.socket.send(JSON.stringify({event: 'USER_FETCH_NOTIFICATION_HISTORY', payload: {}, userId: $sessionStorage.currentUser.userId}));
}
$scope.socket.setHandler('message', function(event) {
console.log('Inside warehouse landing message event', event.data);

try{
var notif = JSON.parse(event.data);

switch (notif.event) {

case 'NOTIFICATION_HISTORY':
let ids = [];
notif.notifications.forEach((notif) => {
ids.push(notif._id);
notifyMe(notif);
});
$scope.socket.send(JSON.stringify({event: 'NOTIFICATION_BULK_RECEIVED_ACK', payload: {}, messageIds: ids, userId: $sessionStorage.currentUser.userId}));

break;

case 'WORKER_NOTIFICATION':
notifyMe(notif);
$scope.socket.send(JSON.stringify({event: 'NOTIFICATION_RECEIVED_ACK', messageId: notif._id, payload: {}, userId: $sessionStorage.currentUser.userId}));
if (_.isArray($scope.filteredLists)) {
$scope.filteredLists.forEach(function (report) {
if (report.id === notif.reportId) {
// Update the row status
report.state = notif.payload.state;
$scope.$apply();
console.log('Row status updated');
}
});
console.log('rows', $scope.filteredLists);
}
console.log('notification ack sent');
break;

case 'NOTIFICATION_HISTORY_EMPTY':
console.log('Up to date with notifications. Make api call to fetch archived notifications in the next step');
break;

case 'MESSAGES_DELETED':

break;

case 'BULK_MESSAGES_DELETED':

break;

default:
console.log('Unknown Event');
break;
}

function notifyMe (notif) {
Notification.success({
message: notif.payload.message,
onClose: function() {
return $state.go($state.current, {}, {reload: true}); // $stateParams isn't injected, therefore not reused
}
});
}
}catch(error) {
console.log(error);
}

});
});
}
]);
1 change: 1 addition & 0 deletions client/app/scripts/shoppinpal-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ angular.module('shoppinpal-constants', [])
'MANAGER_RECEIVE': 'manager_receive',
'REPORT_COMPLETE': 'report_complete'
})
.constant('notificationUrl', '@@notificationUrl')
.constant('proxyUrl', '@@proxyUrl')
.constant('vendClientId','@@vendClientId')
.constant('vendAuthEndpoint', '@@vendAuthEndpoint')
Expand Down
1 change: 1 addition & 0 deletions server/config-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"VM_EXTERNAL_IP":"process.env.VM_EXTERNAL_IP",
"VEND_CLIENT_ID":"process.env.VEND_CLIENT_ID",
"VEND_CLIENT_SECRET":"process.env.VEND_CLIENT_SECRET",
"NOTIFICATION_URL":"process.env.NOTIFICATION_URL",
"IW_URL":"process.env.IW_URL",
"IW_PROJECT_ID":"process.env.IW_PROJECT_ID",
"IW_OAUTH_TOKEN":"process.env.IW_OAUTH_TOKEN",
Expand Down
3 changes: 2 additions & 1 deletion server/config.mustache
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module.exports = {
'site': {
'baseUrl': {{SCHEME}} + '://' + {{VM_EXTERNAL_IP}},
'proxyUrl': ''
'proxyUrl': '',
'notificationUrl': {{NOTIFICATION_URL}}
},
'logging': {
'console': true,
Expand Down
Loading