From 73e0a636892ecc56d9bb7b62c7579ef2cf67a04a Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 29 Nov 2016 17:12:53 +0000 Subject: [PATCH 01/10] Basic mark-up and styles. Change the controller to hold all notifications. --- services/web/app/views/project/list.jade | 18 +++++-- .../public/coffee/main/announcements.coffee | 24 ++++----- .../public/stylesheets/app/project-list.less | 54 +++++++++++++++++++ 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index 6f1d87424a..dc4bff9444 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -22,9 +22,21 @@ block content .content.content-alt(ng-controller="ProjectPageController") .container - //- div(ng-controller="AnnouncementsController", ng-cloak) - //- .alert.alert-success(ng-show="dataRecived") - //- a(href, ng-click="openLink()") {{title}} and {{totalAnnouncements}} others + div( + ng-controller="AnnouncementsController" + ng-cloak + ) + .announcements(ng-if="announcements.length") + span.announcements-badge {{ announcements.length }} + .announcements-body + .announcement( + ng-repeat="announcement in announcements" + ) + a.announcement-title(href, ng-click="openLink()") {{ announcement.title }} + p.announcement-description {{ announcement.excerpt }} + //- .card.card-thin(ng-show="dataReceived") + //- a.announcement-title(href, ng-click="openLink()") {{ title }} + //- p.announcement-description {{ excerpt }} .row(ng-cloak) span(ng-if="projects.length > 0") diff --git a/services/web/public/coffee/main/announcements.coffee b/services/web/public/coffee/main/announcements.coffee index b0960bcc09..36a1185d0c 100644 --- a/services/web/public/coffee/main/announcements.coffee +++ b/services/web/public/coffee/main/announcements.coffee @@ -2,19 +2,19 @@ define [ "base" ], (App) -> App.controller "AnnouncementsController", ($scope, $http, event_tracking, $window) -> + $scope.announcements = [] - $scope.dataRecived = false - announcement = null - $http.get("/announcements").success (announcements) -> - if announcements?[0]? - announcement = announcements[0] - $scope.title = announcement.title - $scope.totalAnnouncements = announcements.length - $scope.dataRecived = true + refreshAnnouncements = -> + $http.get("/announcements").success (announcements) -> + $scope.announcements = announcements + + dismissCurrentAnnouncement = -> + event_tracking.sendMB "announcement-alert-dismissed", { blogPostId:announcement.id } - dismissannouncement = -> - event_tracking.sendMB "announcement-alert-dismissed", {blogPostId:announcement.id} + refreshAnnouncements() $scope.openLink = -> - dismissannouncement() - $window.location.href = announcement.url + dismissCurrentAnnouncement() + .then(refreshAnnouncements) + + $window.open = announcement.url diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index de3307a017..1556252d2d 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -1,3 +1,14 @@ +@announcements-shadow: 0 2px 4px 1px rgba(0, 0, 0, 0.2); + +@keyframes pulse { + 0% { + opacity: .7; + } + 100% { + opacity: .9; + } +} + .project-header { .btn-group > .btn { padding-left: @line-height-base / 2; @@ -293,3 +304,46 @@ ul.project-list { margin-left:-100px; } } + +.announcements { + position: absolute; + bottom: 100px; + right: 100px; + width: 80px; + height: 80px; + background: url(/img/lion-128.png) no-repeat center/80% white; + border-radius: 50%; + box-shadow: @announcements-shadow; + z-index: 1; +} + + .announcements-badge { + display: inline-block; + position: absolute; + font-size: 11px; + height: 1.8em; + min-width: 1.8em; + border-radius: 0.9em; + line-height: 1.8; + padding: 0 2px; + top: 1px; + right: 1px; + font-weight: bold; + color: #FFF; + background-color: @red; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + animation: pulse 1s alternate infinite; + } + + .announcements-body { + position: absolute; + right: 0; + bottom: 80px; + width: 500px; + min-height: 100px; + background: #FFF; + box-shadow: @announcements-shadow; + border-radius: 10px; + } From a00acd7458e9cc9adf213404813a52f2254e6a7c Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Mon, 5 Dec 2016 15:32:38 +0000 Subject: [PATCH 02/10] Add animations and state toggling. --- services/web/app/views/project/list.jade | 37 ++++-- .../public/coffee/main/announcements.coffee | 5 +- .../public/stylesheets/app/project-list.less | 124 +++++++++++++----- 3 files changed, 118 insertions(+), 48 deletions(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index dc4bff9444..411536316c 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -19,24 +19,37 @@ block content } }; - .content.content-alt(ng-controller="ProjectPageController") + .content.content-alt.project-list-page(ng-controller="ProjectPageController") .container div( ng-controller="AnnouncementsController" ng-cloak ) - .announcements(ng-if="announcements.length") - span.announcements-badge {{ announcements.length }} - .announcements-body - .announcement( - ng-repeat="announcement in announcements" - ) - a.announcement-title(href, ng-click="openLink()") {{ announcement.title }} - p.announcement-description {{ announcement.excerpt }} - //- .card.card-thin(ng-show="dataReceived") - //- a.announcement-title(href, ng-click="openLink()") {{ title }} - //- p.announcement-description {{ excerpt }} + .announcements-backdrop(ng-if="ui.isOpen") + a.announcements-btn( + href + ng-if="announcements.length" + ng-click="ui.isOpen = !ui.isOpen" + ng-class="{ 'announcements-btn-open': ui.isOpen, 'announcements-btn-has-new': ui.hasNew }" + ) + span.announcements-badge(ng-if="ui.hasNew") {{ announcements.length }} + .announcements-body( + ng-if="ui.isOpen" + ) + .announcement( + ng-repeat="announcement in announcements" + ) + h2.announcement-header {{ announcement.title }} + p.announcement-date {{ announcement.date | date:"longDate" }} + p.announcement-description {{ announcement.excerpt }} + a( + ng-href="{{ announcement.url }}" + target="_blank" + ) Read more + //- .card.card-thin(ng-show="dataReceived") + //- a.announcement-title(href, ng-click="openLink()") {{ title }} + //- p.announcement-description {{ excerpt }} .row(ng-cloak) span(ng-if="projects.length > 0") diff --git a/services/web/public/coffee/main/announcements.coffee b/services/web/public/coffee/main/announcements.coffee index 36a1185d0c..910658ad2e 100644 --- a/services/web/public/coffee/main/announcements.coffee +++ b/services/web/public/coffee/main/announcements.coffee @@ -3,7 +3,10 @@ define [ ], (App) -> App.controller "AnnouncementsController", ($scope, $http, event_tracking, $window) -> $scope.announcements = [] - + $scope.ui = + isOpen: false + hasNew: false + refreshAnnouncements = -> $http.get("/announcements").success (announcements) -> $scope.announcements = announcements diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 1556252d2d..0bbe7e1e2c 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -8,6 +8,19 @@ opacity: .9; } } +@keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +.project-list-page { + position: relative; + overflow: hidden; +} .project-header { .btn-group > .btn { @@ -305,45 +318,86 @@ ul.project-list { } } -.announcements { - position: absolute; - bottom: 100px; - right: 100px; - width: 80px; - height: 80px; - background: url(/img/lion-128.png) no-repeat center/80% white; - border-radius: 50%; - box-shadow: @announcements-shadow; +.announcements-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.35); + opacity: 0; + animation: fade-in 0.35s forwards; z-index: 1; } - .announcements-badge { - display: inline-block; - position: absolute; - font-size: 11px; - height: 1.8em; - min-width: 1.8em; - border-radius: 0.9em; - line-height: 1.8; - padding: 0 2px; - top: 1px; - right: 1px; - font-weight: bold; - color: #FFF; - background-color: @red; - vertical-align: baseline; - white-space: nowrap; - text-align: center; - animation: pulse 1s alternate infinite; +.announcements-btn { + position: absolute; + bottom: -50px; + right: 3%; + width: 80px; + height: 80px; + background: url(/img/lion-128.png) no-repeat center/80% transparent; + border-radius: 50%; + box-shadow: none; + z-index: 1; + transition: bottom 0.25s cubic-bezier(0.68, -0.55, 0.265, 1.55), + background 0.25s ease, + box-shadow 0.25s ease; + + &:hover { + bottom: -45px; } - .announcements-body { - position: absolute; - right: 0; - bottom: 80px; - width: 500px; - min-height: 100px; - background: #FFF; + &-open, &-open:hover, + &-has-new, &-has-new:hover { + background-color: #FFF; box-shadow: @announcements-shadow; - border-radius: 10px; + bottom: 40px; } +} +.announcements-badge { + display: inline-block; + position: absolute; + font-size: 11px; + height: 1.8em; + min-width: 1.8em; + border-radius: 0.9em; + line-height: 1.8; + padding: 0 2px; + top: 1px; + right: 1px; + font-weight: bold; + color: #FFF; + background-color: @red; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + z-index: 1; + animation: pulse 1s alternate infinite; +} + +.announcements-body { + position: absolute; + right: 3%; + bottom: 130px; + width: 700px; + min-height: 100px; + background: #FFF; + z-index: 1; + box-shadow: @announcements-shadow; + padding: 0 @line-height-computed; + border-radius: @border-radius-base; + animation: fade-in 0.35s forwards; +} + .announcement { + margin-bottom: @line-height-computed; + } + .announcement-header { + .page-header; + margin-bottom: 0; + } + + .announcement-date { + .small; + margin: (@line-height-computed / 4) 0; + } From 6a9ab1f525513830623be2b1027a7cd5e96c9b71 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 6 Dec 2016 14:17:30 +0000 Subject: [PATCH 03/10] Style adjusments; make announcements close when backdrop is clicked. --- services/web/app/views/project/list.jade | 23 ++-- .../public/stylesheets/app/project-list.less | 105 ++++++++++++------ 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index 411536316c..e4ba2ae3f2 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -21,12 +21,15 @@ block content .content.content-alt.project-list-page(ng-controller="ProjectPageController") .container - - div( + .announcements( ng-controller="AnnouncementsController" + ng-class="{ 'announcements-open': ui.isOpen }" ng-cloak ) - .announcements-backdrop(ng-if="ui.isOpen") + .announcements-backdrop( + ng-if="ui.isOpen" + ng-click="ui.isOpen = false;" + ) a.announcements-btn( href ng-if="announcements.length" @@ -41,15 +44,13 @@ block content ng-repeat="announcement in announcements" ) h2.announcement-header {{ announcement.title }} - p.announcement-date {{ announcement.date | date:"longDate" }} p.announcement-description {{ announcement.excerpt }} - a( - ng-href="{{ announcement.url }}" - target="_blank" - ) Read more - //- .card.card-thin(ng-show="dataReceived") - //- a.announcement-title(href, ng-click="openLink()") {{ title }} - //- p.announcement-description {{ excerpt }} + .announcement-meta + p.announcement-date {{ announcement.date | date:"longDate" }} + a.announcement-link( + ng-href="{{ announcement.url }}" + target="_blank" + ) Read more .row(ng-cloak) span(ng-if="projects.length > 0") diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 0bbe7e1e2c..796ce3e747 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -1,4 +1,4 @@ -@announcements-shadow: 0 2px 4px 1px rgba(0, 0, 0, 0.2); +@announcements-shadow: 0 2px 20px rgba(0, 0, 0, 0.5); @keyframes pulse { 0% { @@ -318,6 +318,12 @@ ul.project-list { } } +.announcements { + position: absolute; + bottom: 0; + right: 3%; +} + .announcements-backdrop { position: fixed; top: 0; @@ -333,7 +339,7 @@ ul.project-list { .announcements-btn { position: absolute; bottom: -50px; - right: 3%; + right: 0; width: 80px; height: 80px; background: url(/img/lion-128.png) no-repeat center/80% transparent; @@ -352,52 +358,83 @@ ul.project-list { &-has-new, &-has-new:hover { background-color: #FFF; box-shadow: @announcements-shadow; - bottom: 40px; + bottom: 30px; } } -.announcements-badge { - display: inline-block; - position: absolute; - font-size: 11px; - height: 1.8em; - min-width: 1.8em; - border-radius: 0.9em; - line-height: 1.8; - padding: 0 2px; - top: 1px; - right: 1px; - font-weight: bold; - color: #FFF; - background-color: @red; - vertical-align: baseline; - white-space: nowrap; - text-align: center; - z-index: 1; - animation: pulse 1s alternate infinite; -} + .announcements-badge { + display: inline-block; + position: absolute; + font-size: 11px; + height: 1.8em; + min-width: 1.8em; + border-radius: 0.9em; + line-height: 1.8; + padding: 0 2px; + top: 1px; + right: 1px; + font-weight: bold; + color: #FFF; + background-color: @red; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + z-index: 1; + animation: pulse 1s alternate infinite; + } .announcements-body { position: absolute; - right: 3%; - bottom: 130px; + right: 95px; + bottom: 30px; width: 700px; min-height: 100px; background: #FFF; z-index: 1; box-shadow: @announcements-shadow; - padding: 0 @line-height-computed; + padding: @line-height-computed; border-radius: @border-radius-base; animation: fade-in 0.35s forwards; + + &::after { + content: "\25b8"; + position: absolute; + left: 100%; + bottom: 17px; + width: 30px; + color: #FFF; + text-shadow: @announcements-shadow; + font-size: 2em; + overflow: hidden; + text-indent: -6px; + } } .announcement { - margin-bottom: @line-height-computed; - } - .announcement-header { - .page-header; + margin-bottom: @line-height-computed * 1.5; + &:last-child { margin-bottom: 0; } - - .announcement-date { - .small; - margin: (@line-height-computed / 4) 0; + } + .announcement-header { + .page-header; + margin: 0; } + + .announcement-description { + margin: (@line-height-computed / 4) 0 (@line-height-computed / 2); + } + + .announcement-meta { + .clearfix; + font-size: 0.9em; + } + + .announcement-date { + float: left; + color: @gray; + margin: 0; + } + + .announcement-link { + float: right; + margin: 0; + } From 5d9ae252829c9a07a6a89c6347b74bf987fd77f0 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 6 Dec 2016 15:41:58 +0000 Subject: [PATCH 04/10] Allow announcements to overflow the header. --- .../web/public/stylesheets/app/project-list.less | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 796ce3e747..d2562d4546 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -19,7 +19,6 @@ .project-list-page { position: relative; - overflow: hidden; } .project-header { @@ -320,8 +319,12 @@ ul.project-list { .announcements { position: absolute; + top: -100%; bottom: 0; - right: 3%; + right: 0; + height: auto; + width: 100%; + overflow: hidden; } .announcements-backdrop { @@ -339,7 +342,7 @@ ul.project-list { .announcements-btn { position: absolute; bottom: -50px; - right: 0; + right: 3%; width: 80px; height: 80px; background: url(/img/lion-128.png) no-repeat center/80% transparent; @@ -384,7 +387,8 @@ ul.project-list { .announcements-body { position: absolute; - right: 95px; + right: 3%; + margin-right: 95px; bottom: 30px; width: 700px; min-height: 100px; From 821e556dd32e80b98a750c6f74b5af4b476cb792 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 6 Dec 2016 17:15:56 +0000 Subject: [PATCH 05/10] Better handling of overflowing content. --- services/web/app/views/project/list.jade | 23 ++++++++++--------- .../public/stylesheets/app/project-list.less | 12 ++++++++-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index e4ba2ae3f2..1311b1a2c8 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -40,17 +40,18 @@ block content .announcements-body( ng-if="ui.isOpen" ) - .announcement( - ng-repeat="announcement in announcements" - ) - h2.announcement-header {{ announcement.title }} - p.announcement-description {{ announcement.excerpt }} - .announcement-meta - p.announcement-date {{ announcement.date | date:"longDate" }} - a.announcement-link( - ng-href="{{ announcement.url }}" - target="_blank" - ) Read more + .announcements-scroller + .announcement( + ng-repeat="announcement in announcements" + ) + h2.announcement-header {{ announcement.title }} + p.announcement-description {{ announcement.excerpt }} + .announcement-meta + p.announcement-date {{ announcement.date | date:"longDate" }} + a.announcement-link( + ng-href="{{ announcement.url }}" + target="_blank" + ) Read more .row(ng-cloak) span(ng-if="projects.length > 0") diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index d2562d4546..e9aa20d2da 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -319,12 +319,18 @@ ul.project-list { .announcements { position: absolute; - top: -100%; bottom: 0; right: 0; - height: auto; + height: 150px; width: 100%; + pointer-events: none; overflow: hidden; + + &-open { + top: -100%; + height: auto; + pointer-events: all; + } } .announcements-backdrop { @@ -349,6 +355,7 @@ ul.project-list { border-radius: 50%; box-shadow: none; z-index: 1; + pointer-events: all; transition: bottom 0.25s cubic-bezier(0.68, -0.55, 0.265, 1.55), background 0.25s ease, box-shadow 0.25s ease; @@ -391,6 +398,7 @@ ul.project-list { margin-right: 95px; bottom: 30px; width: 700px; + max-height: 52%; min-height: 100px; background: #FFF; z-index: 1; From 3595aff5e2451947ab4213d1a0192b62a8be16e4 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 7 Dec 2016 11:10:02 +0000 Subject: [PATCH 06/10] Scrolling behaviour. --- .../public/stylesheets/app/project-list.less | 62 +++++++++++-------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index e9aa20d2da..50d02c251e 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -393,6 +393,8 @@ ul.project-list { } .announcements-body { + display: flex; + align-items: stretch; position: absolute; right: 3%; margin-right: 95px; @@ -403,7 +405,6 @@ ul.project-list { background: #FFF; z-index: 1; box-shadow: @announcements-shadow; - padding: @line-height-computed; border-radius: @border-radius-base; animation: fade-in 0.35s forwards; @@ -417,36 +418,43 @@ ul.project-list { text-shadow: @announcements-shadow; font-size: 2em; overflow: hidden; - text-indent: -6px; + text-indent: -7px; } } - .announcement { - margin-bottom: @line-height-computed * 1.5; - &:last-child { - margin-bottom: 0; - } - } - .announcement-header { - .page-header; - margin: 0; - } - .announcement-description { - margin: (@line-height-computed / 4) 0 (@line-height-computed / 2); - } - - .announcement-meta { - .clearfix; - font-size: 0.9em; - } - - .announcement-date { - float: left; - color: @gray; + .announcements-scroller { + padding: @line-height-computed; + flex-grow: 0; + overflow-x: hidden; + overflow-y: auto; + } + .announcement { + margin-bottom: @line-height-computed * 1.5; + &:last-child { + margin-bottom: 0; + } + } + .announcement-header { + .page-header; margin: 0; } - .announcement-link { - float: right; - margin: 0; + .announcement-description { + margin: (@line-height-computed / 4) 0 (@line-height-computed / 2); } + + .announcement-meta { + .clearfix; + font-size: 0.9em; + } + + .announcement-date { + float: left; + color: @gray; + margin: 0; + } + + .announcement-link { + float: right; + margin: 0; + } From e6eeb86046d6d72dd05d7475c8291fcf8daf9f92 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 7 Dec 2016 11:39:22 +0000 Subject: [PATCH 07/10] add read property to announcments --- .../Announcements/AnnouncementsHandler.coffee | 11 +++++-- .../AnnouncementsHandlerTests.coffee | 29 +++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee b/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee index a27608343a..ce41e3b96c 100644 --- a/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee +++ b/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee @@ -25,8 +25,15 @@ module.exports = announcementIndex = _.findIndex announcements, (announcement)-> announcement.id == lastSeenBlogId - if announcementIndex != -1 - announcements = announcements.slice(0, announcementIndex) + announcements = _.map announcements, (announcement, index)-> + if announcementIndex == -1 + read = false + else if index >= announcementIndex + read = true + else + read = false + announcement.read = read + return announcement logger.log announcementsLength:announcements?.length, user_id:user_id, "returning announcements" diff --git a/services/web/test/UnitTests/coffee/Announcement/AnnouncementsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Announcement/AnnouncementsHandlerTests.coffee index 7578ea3a64..49e8292f97 100644 --- a/services/web/test/UnitTests/coffee/Announcement/AnnouncementsHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Announcement/AnnouncementsHandlerTests.coffee @@ -42,10 +42,13 @@ describe 'AnnouncementsHandler', -> @BlogHandler.getLatestAnnouncements.callsArgWith(0, null, @stubbedAnnouncements) - it "should return all announcements if there are no getLastOccurance", (done)-> + it "should mark all announcements as read is false", (done)-> @AnalyticsManager.getLastOccurance.callsArgWith(2, null, []) @handler.getUnreadAnnouncements @user_id, (err, announcements)=> - announcements.length.should.equal 4 + announcements[0].read.should.equal false + announcements[1].read.should.equal false + announcements[2].read.should.equal false + announcements[3].read.should.equal false done() it "should should be sorted again to ensure correct order", (done)-> @@ -57,16 +60,30 @@ describe 'AnnouncementsHandler', -> announcements[0].should.equal @stubbedAnnouncements[0] done() - it "should return ones older than the last blog id", (done)-> + it "should return older ones marked as read as well", (done)-> @AnalyticsManager.getLastOccurance.callsArgWith(2, null, {segmentation:{blogPostId:"/2014/04/12/title-date-irrelivant"}}) @handler.getUnreadAnnouncements @user_id, (err, announcements)=> - announcements.length.should.equal 2 announcements[0].id.should.equal @stubbedAnnouncements[0].id + announcements[0].read.should.equal false + announcements[1].id.should.equal @stubbedAnnouncements[1].id + announcements[1].read.should.equal false + + announcements[2].id.should.equal @stubbedAnnouncements[3].id + announcements[2].read.should.equal true + + announcements[3].id.should.equal @stubbedAnnouncements[2].id + announcements[3].read.should.equal true + done() - it "should return none when the latest id is the first element", (done)-> + it "should return all of them marked as read", (done)-> @AnalyticsManager.getLastOccurance.callsArgWith(2, null, {segmentation:{blogPostId:"/2016/11/01/introducting-latex-code-checker"}}) @handler.getUnreadAnnouncements @user_id, (err, announcements)=> - announcements.length.should.equal 0 + announcements[0].read.should.equal true + announcements[1].read.should.equal true + announcements[2].read.should.equal true + announcements[3].read.should.equal true done() + + From c716b86def75cc13fe6eeb340a6864e56ba6ddc7 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 7 Dec 2016 14:26:10 +0000 Subject: [PATCH 08/10] Add logic to dismiss unread announcements, styling fixes. --- services/web/app/views/project/list.jade | 10 ++++----- .../public/coffee/main/announcements.coffee | 22 +++++++++++-------- .../public/stylesheets/app/project-list.less | 1 + 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index 1311b1a2c8..476ef0ca4c 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -28,21 +28,21 @@ block content ) .announcements-backdrop( ng-if="ui.isOpen" - ng-click="ui.isOpen = false;" + ng-click="toggleAnnouncementsUI();" ) a.announcements-btn( href ng-if="announcements.length" - ng-click="ui.isOpen = !ui.isOpen" - ng-class="{ 'announcements-btn-open': ui.isOpen, 'announcements-btn-has-new': ui.hasNew }" + ng-click="toggleAnnouncementsUI();" + ng-class="{ 'announcements-btn-open': ui.isOpen, 'announcements-btn-has-new': ui.newItems }" ) - span.announcements-badge(ng-if="ui.hasNew") {{ announcements.length }} + span.announcements-badge(ng-if="ui.newItems") {{ ui.newItems }} .announcements-body( ng-if="ui.isOpen" ) .announcements-scroller .announcement( - ng-repeat="announcement in announcements" + ng-repeat="announcement in announcements | filter:(ui.newItems ? { read: false } : '') track by announcement.id" ) h2.announcement-header {{ announcement.title }} p.announcement-description {{ announcement.excerpt }} diff --git a/services/web/public/coffee/main/announcements.coffee b/services/web/public/coffee/main/announcements.coffee index 910658ad2e..94303e921a 100644 --- a/services/web/public/coffee/main/announcements.coffee +++ b/services/web/public/coffee/main/announcements.coffee @@ -1,23 +1,27 @@ define [ "base" ], (App) -> - App.controller "AnnouncementsController", ($scope, $http, event_tracking, $window) -> + App.controller "AnnouncementsController", ($scope, $http, event_tracking, $window, _) -> $scope.announcements = [] $scope.ui = isOpen: false - hasNew: false - + newItems: 0 + refreshAnnouncements = -> $http.get("/announcements").success (announcements) -> $scope.announcements = announcements + $scope.ui.newItems = _.filter(announcements, (announcement) -> !announcement.read).length - dismissCurrentAnnouncement = -> - event_tracking.sendMB "announcement-alert-dismissed", { blogPostId:announcement.id } + markAnnouncementsAsRead = -> + event_tracking.sendMB "announcement-alert-dismissed", { blogPostId: $scope.announcements[0].id } refreshAnnouncements() - $scope.openLink = -> - dismissCurrentAnnouncement() - .then(refreshAnnouncements) + $scope.toggleAnnouncementsUI = -> + $scope.ui.isOpen = !$scope.ui.isOpen + + if !$scope.ui.isOpen and $scope.ui.newItems + $scope.ui.newItems = 0 + markAnnouncementsAsRead() + - $window.open = announcement.url diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 50d02c251e..5e03c1facc 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -394,6 +394,7 @@ ul.project-list { .announcements-body { display: flex; + flex-direction: column; align-items: stretch; position: absolute; right: 3%; From 58ab888f3f915df8b2272fce5e076f92d9a3fd85 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 7 Dec 2016 14:57:54 +0000 Subject: [PATCH 09/10] Add a button to show all, when filtering new items. --- services/web/app/views/project/list.jade | 7 +++++++ services/web/public/coffee/main/announcements.coffee | 2 ++ 2 files changed, 9 insertions(+) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index 476ef0ca4c..ac852da97e 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -52,6 +52,13 @@ block content ng-href="{{ announcement.url }}" target="_blank" ) Read more + div.text-center( + ng-if="ui.newItems > 0 && ui.newItems < announcements.length" + ) + a.btn.btn-default.btn-sm( + href + ng-click="showAll();" + ) Show all .row(ng-cloak) span(ng-if="projects.length > 0") diff --git a/services/web/public/coffee/main/announcements.coffee b/services/web/public/coffee/main/announcements.coffee index 94303e921a..cccebf56ad 100644 --- a/services/web/public/coffee/main/announcements.coffee +++ b/services/web/public/coffee/main/announcements.coffee @@ -24,4 +24,6 @@ define [ $scope.ui.newItems = 0 markAnnouncementsAsRead() + $scope.showAll = -> + $scope.ui.newItems = 0 From 42bd1852c6c8a3b99dd16746ffad7ab4946a0066 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 7 Dec 2016 15:45:22 +0000 Subject: [PATCH 10/10] Use HTML binding in the excerpt. --- services/web/app/views/project/list.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index ac852da97e..d9fbf0e6b1 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -45,7 +45,7 @@ block content ng-repeat="announcement in announcements | filter:(ui.newItems ? { read: false } : '') track by announcement.id" ) h2.announcement-header {{ announcement.title }} - p.announcement-description {{ announcement.excerpt }} + p.announcement-description(ng-bind-html="announcement.excerpt") .announcement-meta p.announcement-date {{ announcement.date | date:"longDate" }} a.announcement-link(