diff --git a/client/main.js b/client/main.js index b7ed7c9bd0..7e50247a10 100644 --- a/client/main.js +++ b/client/main.js @@ -124,6 +124,30 @@ main = (function(main, global) { Mousetrap.bind('g c', toggleMainChat); }); + function localStorageIO(item = '', input = null) { + if (input) { + try { + input = typeof input === 'string' ? input : JSON.stringify(input); + } catch (e) { + // Do Nothing + } + localStorage.setItem(item, input); + return input; + } else { + let data = typeof localStorage.getItem(item) + !== 'undefined' && localStorage.getItem(item) + !== null ? localStorage.getItem(item) : ''; + try { + data = JSON.parse(data); + } catch (e) { + // Do Nothing + } + return data; + } + } + + main.localStorageIO = localStorageIO; + return main; }(main, window)); @@ -612,4 +636,49 @@ $(document).ready(function() { // Repo window.location = 'https://github.com/freecodecamp/freecodecamp/'; }); + + function getCurrentBillBoard(cb) { + $.ajax({ + url: '/api/flyers/findOne?' + + 'filter=%7B%22order%22%3A%20%20%22id%20DESC%22%7D', + method: 'GET', + dataType: 'JSON', + data: {'order': 'id DESC'} + }).done((resp) => { + cb(resp); + }); + $('#dismissBill').on('click', (e) => { + const elemData + = e.target.parentNode.parentNode.children; + + const res + = elemData[Object.keys(elemData).filter((key)=> { + return elemData[key].id === 'billContent'; + + })[0]].innerHTML; + + main.localStorageIO('lastBillBoardSeen', res); + }); + } + + function handleNewBillBoard(resp) { + const data = typeof main.localStorageIO('lastBillBoardSeen') + !== 'undefined' && main.localStorageIO('lastBillBoardSeen') + !== null ? main.localStorageIO('lastBillBoardSeen') : ''; + if ( + data.replace(/\s*/gi, '') + .replace(/\&\w*\;/gi, '') + .replace(/(\<|\/|\>)/gi, '') + !== resp.message + .replace(/\s*/gi, '') + .replace(/\&\w*\;/gi, '') + .replace(/(\<|\/|\>)/gi, '') + && resp.active + ) { + $('#billContent').html(resp.message); + $('#billBoard').fadeIn(); + } + } + + getCurrentBillBoard(handleNewBillBoard); }); diff --git a/common/models/flyer.json b/common/models/flyer.json new file mode 100644 index 0000000000..251bbb0d15 --- /dev/null +++ b/common/models/flyer.json @@ -0,0 +1,34 @@ +{ + "name": "flyer", + "base": "PersistedModel", + "idInjection": true, + "trackChanges": false, + "properties": { + "message": { + "type": "string" + }, + "active": { + "type": "boolean", + "default": false + } + }, + "validations": [], + "relations": { + + }, + "acls": [ + { + "accessType": "*", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "DENY" + }, + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ], + "methods": [] +} diff --git a/server/model-config.json b/server/model-config.json index 1b9d552ab9..60800cf81b 100644 --- a/server/model-config.json +++ b/server/model-config.json @@ -66,5 +66,9 @@ "userIdentity": { "dataSource": "db", "public": true + }, + "flyer": { + "dataSource": "db", + "public": true } } diff --git a/server/views/account/show.jade b/server/views/account/show.jade index df88282365..568fd5ea4d 100644 --- a/server/views/account/show.jade +++ b/server/views/account/show.jade @@ -1,5 +1,6 @@ extends ../layout block content + include ../partials/flyer script(src="/bower_components/cal-heatmap/cal-heatmap.min.js") script. var challengeName = 'Profile View'; @@ -170,4 +171,4 @@ block content if (challenge.solution) a(href='/challenges/' + removeOldTerms(challenge.name) + '?solution=' + encodeURIComponent(encodeFcc(challenge.solution)), target='_blank')= removeOldTerms(challenge.name) else - a(href='/challenges/' + removeOldTerms(challenge.name))= removeOldTerms(challenge.name) \ No newline at end of file + a(href='/challenges/' + removeOldTerms(challenge.name))= removeOldTerms(challenge.name) diff --git a/server/views/challenges/showBonfire.jade b/server/views/challenges/showBonfire.jade index 8ab0684c4a..6bb918d579 100644 --- a/server/views/challenges/showBonfire.jade +++ b/server/views/challenges/showBonfire.jade @@ -4,6 +4,7 @@ block content link(rel='stylesheet', href='/bower_components/CodeMirror/addon/lint/lint.css') link(rel='stylesheet', href='/bower_components/CodeMirror/theme/monokai.css') link(rel='stylesheet', href='/css/ubuntu.css') + include ../partials/flyer .row .col-md-4.col-lg-3 .scroll-locker(id = "scroll-locker") diff --git a/server/views/challenges/showHTML.jade b/server/views/challenges/showHTML.jade index 0d08346825..7835148327 100644 --- a/server/views/challenges/showHTML.jade +++ b/server/views/challenges/showHTML.jade @@ -4,6 +4,7 @@ block content link(rel='stylesheet', href='/bower_components/CodeMirror/addon/lint/lint.css') link(rel='stylesheet', href='/bower_components/CodeMirror/theme/monokai.css') link(rel='stylesheet', href='/css/ubuntu.css') + include ../partials/flyer .row .col-md-3.col-lg-3 .scroll-locker(id = "scroll-locker") diff --git a/server/views/challenges/showJS.jade b/server/views/challenges/showJS.jade index eae63ab02a..3939b29bed 100644 --- a/server/views/challenges/showJS.jade +++ b/server/views/challenges/showJS.jade @@ -4,6 +4,7 @@ block content link(rel='stylesheet', href='/bower_components/CodeMirror/addon/lint/lint.css') link(rel='stylesheet', href='/bower_components/CodeMirror/theme/monokai.css') link(rel='stylesheet', href='/css/ubuntu.css') + include ../partials/flyer .row .col-md-4.col-lg-3 .scroll-locker(id = "scroll-locker") diff --git a/server/views/challenges/showStep.jade b/server/views/challenges/showStep.jade index 1249b842a2..d276c836c8 100644 --- a/server/views/challenges/showStep.jade +++ b/server/views/challenges/showStep.jade @@ -1,5 +1,6 @@ extends ../layout-wide block content + include ../partials/flyer .row .col-md-8.col-md-offset-2 for step, index in description diff --git a/server/views/challenges/showVideo.jade b/server/views/challenges/showVideo.jade index bf3d45636b..f29911013e 100644 --- a/server/views/challenges/showVideo.jade +++ b/server/views/challenges/showVideo.jade @@ -1,5 +1,6 @@ extends ../layout-wide block content + include ../partials/flyer .row .col-xs-12.col-sm-12.col-md-4 h4.text-center.challenge-instructions-title= name diff --git a/server/views/challenges/showZiplineOrBasejump.jade b/server/views/challenges/showZiplineOrBasejump.jade index 19197c1795..5c3639a8d6 100644 --- a/server/views/challenges/showZiplineOrBasejump.jade +++ b/server/views/challenges/showZiplineOrBasejump.jade @@ -1,5 +1,6 @@ extends ../layout-wide block content + include ../partials/flyer .row .col-md-4 h4.text-center.challenge-instructions-title= name diff --git a/server/views/layout.jade b/server/views/layout.jade index f64024fdf9..eefd4090e0 100644 --- a/server/views/layout.jade +++ b/server/views/layout.jade @@ -6,7 +6,7 @@ html(lang='en') body.top-and-bottom-margins include partials/scripts include partials/navbar + include partials/flash .container - include partials/flash block content include partials/footer diff --git a/server/views/partials/flash.jade b/server/views/partials/flash.jade index e76ab6edf4..8668a4174d 100644 --- a/server/views/partials/flash.jade +++ b/server/views/partials/flash.jade @@ -1,20 +1,21 @@ -.row.flashMessage - .col-xs-12 - if (messages.errors || messages.error) - .alert.alert-danger.fade.in - button.close(type='button', data-dismiss='alert') - span.ion-close-circled - for error in (messages.errors || messages.error) - div!= error.msg || error - if messages.info - .alert.alert-info.fade.in - button.close(type='button', data-dismiss='alert') - span.ion-close-circled - for info in messages.info - div!= info.msg - if messages.success - .alert.alert-success.fade.in - button.close(type='button', data-dismiss='alert') - span.ion-close-circled - for success in messages.success - div!= success.msg +.container + .row.flashMessage.negative-30 + .col-xs-12 + if (messages.errors || messages.error) + .alert.alert-danger.fade.in + button.close(type='button', data-dismiss='alert') + span.ion-close-circled + for error in (messages.errors || messages.error) + div!= error.msg || error + if messages.info + .alert.alert-info.fade.in + button.close(type='button', data-dismiss='alert') + span.ion-close-circled + for info in messages.info + div!= info.msg + if messages.success + .alert.alert-success.fade.in + button.close(type='button', data-dismiss='alert') + span.ion-close-circled + for success in messages.success + div!= success.msg diff --git a/server/views/partials/flyer.jade b/server/views/partials/flyer.jade new file mode 100644 index 0000000000..92d99e5c21 --- /dev/null +++ b/server/views/partials/flyer.jade @@ -0,0 +1,8 @@ +if (user && user.points > 5) + .container + .row.flashMessage.negative-30 + .col-xs-12 + #billBoard.alert.alert-info.fade.in(style="display: none;") + button.close(type='button', data-dismiss='alert') + span.ion-close-circled#dismissBill + #billContent