diff --git a/.gitignore b/.gitignore index dd9a003..c51b143 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +websocket.out +ndli1718.jar .vscode .DS_Store node_modules/ diff --git a/package.json b/package.json index dab4121..7ba1cf2 100755 --- a/package.json +++ b/package.json @@ -10,7 +10,11 @@ "build:bundle": "cross-env NODE_ENV=production webpack --progress --hide-modules", "build:dev": "cross-env NODE_ENV=development webpack --progress --hide-modules", "dev": "npm run build:clean; npm run build:dev", - "build": "npm run build:clean; npm run build:bundle" + "build": "npm run build:clean; npm run build:bundle", + + "ws-start": "java -jar ./ndli1718.jar > ./websocket.out 2>&1 &", + "ws-stop": "ps -aux | grep 'java -jar ./ndli1718.jar' | grep -v 'grep' && echo 'killing process..' && kill `ps -aux | grep \"java -jar ./ndli1718.jar\" | grep -v \"grep\" | awk '{print $2}'` && echo 'killed' || return 0", + "ws-restart": "npm run ws-stop; npm run ws-start" }, "dependencies": { "vue": "^2.5.9" diff --git a/public_html/css/layout.css b/public_html/css/layout.css index 8e21df4..9435521 100644 --- a/public_html/css/layout.css +++ b/public_html/css/layout.css @@ -91,4 +91,29 @@ body{ #WRAPPER.min #CONTAINER{ left: 3.5em; width: calc( 100% - 3.5em ); +} + + +/* Notification Stack */ +#WRAPPER #NOTIF-STACK{ + display: none; + position: absolute; + top: 4em; + left: calc( 100% - 15em ); + width: 14em; + min-height: 2em; + height: auto; + + border: 1px solid #ddd; + border-radius: 3px; + + background-color: #fff; + + overflow: hidden; + + z-index: 101; +} + +#WRAPPER #NOTIF-STACK.active{ + display: block; } \ No newline at end of file diff --git a/public_html/css/notification-stack.css b/public_html/css/notification-stack.css new file mode 100644 index 0000000..a9be6d7 --- /dev/null +++ b/public_html/css/notification-stack.css @@ -0,0 +1,58 @@ +/* Header */ +#NOTIF-STACK > .head{ + display: block; + position: relative; + width: 100%; + + padding: .7em 0; + + border-radius: 3px 3px 0 0; + border-bottom: 1px solid #ddd; + + text-align: center; + color: #888; +} + +/* Container */ +#NOTIF-STACK > .body{ + display: block; + position: relative; + width: 100%; + min-height: 2em; + height: auto; + max-height: 12em; + + border-radius: 0 0 3px 3px; + + overflow: auto; + +} + +/* Items */ +#NOTIF-STACK > .body > span{ + display: block; + position: relative; + + padding: .8em 1em; + + border-bottom: 1px solid #ddd; + + background-color: #fff; + + color: #555; + + cursor: pointer; + + transition: background-color .2s ease-in-out, + color .2s ease-in-out; +} + +#NOTIF-STACK > .body > span:hover{ + background-color: #eee; + color: #333; +} + +#NOTIF-STACK > .body > span:last-child{ + border: 0; + border-radius: 0 0 3px 3px; +} \ No newline at end of file diff --git a/view/home.php b/view/home.php index 0565d56..a50101e 100755 --- a/view/home.php +++ b/view/home.php @@ -18,6 +18,7 @@ + diff --git a/view/main.js b/view/main.js index 6484cb3..00bd819 100755 --- a/view/main.js +++ b/view/main.js @@ -16,17 +16,18 @@ import wrapper_vue from './vue/wrapper.vue' /* (2) Initialisation ---------------------------------------------------------*/ -/* (1) API */ -window.api = new API("http://ndli1718/api/v/1.0/"); - -/* (2) wsclient */ -window.wsc = new WSClientBuilder("wss://websocket.xdrm.io"); - -/* (3) global store init */ +/* (1) global store init */ require('./vue-config'); window.gstore.add('server', window._SERVER); window.infobox = new InfoBox(gstore.data.info); +/* (2) API */ +window.api = new API(gstore.data.is_local ? 'http://ndli1718/api/v/1.0/' : 'https://ndli1718.xdrm.io/api/v/1.0/'); + +/* (3) wsclient */ +window.wsc = new WSClientBuilder(gstore.data.is_local ? 'ws://localhost:9999' : 'wss://websocket.xdrm.io'); + + /* (4) Init vue router */ Vue.use(VueRouter); const router = new VueRouter({ @@ -74,7 +75,7 @@ window.wsc_connect = wsc.channel('connect').listen(function(msg, err){ gstore.data.notif[0].data = gstore.data.notif[0].data.filter(function(item, i, arr){ return arr.indexOf(item) === i; }); // -3- Update count if not already on page - if( router.app.$route.path != 'notifications' ) + if( router.app.$route.path != '/notifications' ) gstore.data.notif[0].count += gstore.data.notif[0].data.length - lastLen; } @@ -88,7 +89,7 @@ window.wsc_connect = wsc.channel('connect').listen(function(msg, err){ gstore.data.notif[0].data = gstore.data.notif[0].data.filter(function(item){ return msg.disconnected.indexOf(item) === -1; }); // -2- Update count if not already on page - if( router.app.$route.path != 'notifications' ) + if( router.app.$route.path != '/notifications' ) gstore.data.notif[0].count += lastLen - gstore.data.notif[0].data.length; } @@ -112,23 +113,15 @@ window.wsc_chat = wsc.channel('chat').listen(function(msg, err){ return; // {4} Play sound if 1msg received + not already on page // - if( msg.msg.length == 1 && router.app.$route.path != 'inbox' ) - ( new Audio('/sound/notification.mp3') ).play(); + // note: 1msg means a new message but not the page load past buffer + if( msg.msg.length == 1 && router.app.$route.path != '/inbox' ) + ( new Audio('https://notificationsounds.com/message-tones/communication-channel-519/download/mp3') ).play(); // {5} Add messages to stack // gstore.data.notif[1].data = gstore.data.notif[1].data.concat( msg.msg ); // {6} Add notification count if not already on page // - if( router.app.$route.path != 'inbox' ) - gstore.data.notif[1].count += msg.msg.length + if( router.app.$route.path != '/inbox' ) + gstore.data.notif[1].count += msg.msg.length; -}).send({name: _SERVER.session.name}); - - - -/* (4) Clean sockets before page quit ----------------------------------------------------------*/ -window.onbeforeunload = function() { - wsc_chat.send('{"close": true}'); - wsc_connect.send('{"close": true}'); -}; \ No newline at end of file +}).send({name: _SERVER.session.name}); \ No newline at end of file diff --git a/view/vue-config.js b/view/vue-config.js index 2ea0a30..9e1eecf 100644 --- a/view/vue-config.js +++ b/view/vue-config.js @@ -34,6 +34,7 @@ gstore.add('menu_item', { }); gstore.add('URI', document.URL.replace(/^(?:\/\/|[^\/]+)*/, '')); +gstore.add('is_local', document.URL.replace(/^http:\/\/([^\/]+).*$/, '$1') == 'ndli1718'); gstore.add('min_menu', false); // Proccess current page from url @@ -89,4 +90,7 @@ gstore.add('func', { // new-message container -gstore.add('new_msg', ''); \ No newline at end of file +gstore.add('new_msg', ''); + +// notification stack visibility +gstore.add('nstack', false); \ No newline at end of file diff --git a/view/vue/notification-stack.vue b/view/vue/notification-stack.vue new file mode 100644 index 0000000..ae0f4e1 --- /dev/null +++ b/view/vue/notification-stack.vue @@ -0,0 +1,24 @@ + + + + \ No newline at end of file diff --git a/view/vue/wrapper.vue b/view/vue/wrapper.vue index 9e01d8c..d0c649b 100755 --- a/view/vue/wrapper.vue +++ b/view/vue/wrapper.vue @@ -10,6 +10,13 @@ + + + + + + + @@ -18,13 +25,16 @@ import header_vue from './header.vue' import menu_vue from './menu.vue' + import notifstack_vue from './notification-stack.vue' + // import loginform_vue from './login-form.vue' export default { name: 'wrapper', data(){ return { gstore: gstore.data }; }, components: { - 'HeaderComp': header_vue, - 'MenuComp': menu_vue + 'HeaderComp': header_vue, + 'MenuComp': menu_vue, + 'NotifstackComp': notifstack_vue } }