From 1ca404bc207409082edc5fc31de207e448fdbdb1 Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Sat, 17 Oct 2015 14:18:08 -0700 Subject: [PATCH] SUP-2155, Dashboard: Subtracks should not limit to 5 in the carousel -- Created new directive for responsive carousel -- Created new directive for fixing scope issue(https://github.com/angular/angular.js/issues/7874#issuecomment-47647528) with ng-transclude --- .../responsive-carousel.directive.jade | 5 ++ .../responsive-carousel.directive.js | 75 +++++++++++++++++++ app/directives/tc-transclude.directive.js | 24 ++++++ app/index.jade | 3 + .../subtrack-stats.controller.js | 30 ++------ .../subtrack-stats/subtrack-stats.jade | 19 +++-- .../css/directives/responsive-carousel.scss | 71 ++++++++++++++++++ assets/css/my-dashboard/subtrack-stats.scss | 66 ++++------------ 8 files changed, 206 insertions(+), 87 deletions(-) create mode 100644 app/directives/responsive-carousel/responsive-carousel.directive.jade create mode 100644 app/directives/responsive-carousel/responsive-carousel.directive.js create mode 100644 app/directives/tc-transclude.directive.js create mode 100644 assets/css/directives/responsive-carousel.scss diff --git a/app/directives/responsive-carousel/responsive-carousel.directive.jade b/app/directives/responsive-carousel/responsive-carousel.directive.jade new file mode 100644 index 000000000..b4d903f59 --- /dev/null +++ b/app/directives/responsive-carousel/responsive-carousel.directive.jade @@ -0,0 +1,5 @@ +.tc-carousel + ul(rn-carousel, rn-carousel-controls, slide-count="{{slideCounts[carouselIndex]}}") + li(ng-repeat="slides in slidesCollection") + .slide(ng-repeat="item in slides") + tc-transclude \ No newline at end of file diff --git a/app/directives/responsive-carousel/responsive-carousel.directive.js b/app/directives/responsive-carousel/responsive-carousel.directive.js new file mode 100644 index 000000000..84a4b0af2 --- /dev/null +++ b/app/directives/responsive-carousel/responsive-carousel.directive.js @@ -0,0 +1,75 @@ +(function() { + 'use strict'; + angular.module('tcUIComponents').directive('responsiveCarousel', function() { + return { + restrict: 'E', + transclude: true, + replace: true, + templateUrl: 'directives/responsive-carousel/responsive-carousel.directive.html', + scope: { + data: '=' + }, + controller: ['$log', '$scope', '$element', '$window', + function($log, $scope, $element, $window) { + $scope.slideCounts = {}; + + activate(); + + function activate() { + init(); + + var window = angular.element($window); + window.on('resize', function() { + init(); + // don't forget manually trigger $digest() + $scope.$digest(); + }); + } + + function init() { + var width = $window.innerWidth; + console.log(width); + if(width > 1070) { + // desktop + buildCarouselSlide(6); + } else if(width > 900) { + // desktop + buildCarouselSlide(5); + } else if(width <= 900 && width > 768) { + // tablet + buildCarouselSlide(4); + } else { + // phone + buildCarouselSlide(2); + } + } + + + function buildCarouselSlide(numItemsPerSlide) { + var slidesCollection = []; + var slide = []; + // Might be able to change number of subtracks per slide based + // on screen size if the width of each subtrack is consistent: + // http://stackoverflow.com/questions/26252038/multi-item-responsive-carousel + numItemsPerSlide = numItemsPerSlide || 5; + + for(var i = 0; i < $scope.data.length; i++) { + if (slide.length === numItemsPerSlide) { + // When slide is full, push it to collection and make a new slide [] + slidesCollection.push(slide); + // updates the slide count object + $scope.slideCounts[slidesCollection.length - 1] = slide.length; + slide = []; + } + slide.push($scope.data[i]); + } + slidesCollection.push(slide); + // updates the slide count object + $scope.slideCounts[slidesCollection.length - 1] = slide.length; + $scope.slidesCollection = slidesCollection; + } + + }] + }; + }); +})(); \ No newline at end of file diff --git a/app/directives/tc-transclude.directive.js b/app/directives/tc-transclude.directive.js new file mode 100644 index 000000000..313954cac --- /dev/null +++ b/app/directives/tc-transclude.directive.js @@ -0,0 +1,24 @@ +(function() { + 'use strict'; + angular.module('tcUIComponents').directive('tcTransclude', function() { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + if (!$transclude) { + throw minErr('ngTransclude')('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + var innerScope = $scope.$new(); + $transclude(innerScope, function(clone) { + $element.empty(); + $element.append(clone); + $element.on('$destroy', function() { + innerScope.$destroy(); + }); + }); + } + }; + }); +})(); \ No newline at end of file diff --git a/app/index.jade b/app/index.jade index f6a278b41..ab7c7a055 100644 --- a/app/index.jade +++ b/app/index.jade @@ -63,6 +63,7 @@ html link(rel="stylesheet", href="assets/css/directives/tc-paginator.css") link(rel="stylesheet", href="assets/css/directives/srm-tile.css") link(rel="stylesheet", href="assets/css/directives/skill-tile.css") + link(rel="stylesheet", href="assets/css/directives/responsive-carousel.css") link(rel="stylesheet", href="assets/css/directives/profile-widget.css") link(rel="stylesheet", href="assets/css/directives/ios-card.css") link(rel="stylesheet", href="assets/css/directives/input-sticky-placeholder.css") @@ -168,11 +169,13 @@ html script(src="directives/ios-card/ios-card.directive.js") script(src="directives/on-file-change.directive.js") script(src="directives/profile-widget/profile-widget.directive.js") + script(src="directives/responsive-carousel/responsive-carousel.directive.js") script(src="directives/skill-tile/skill-tile.directive.js") script(src="directives/slideable.directive.js") script(src="directives/srm-tile/srm-tile.directive.js") script(src="directives/tc-paginator/tc-paginator.directive.js") script(src="directives/tc-section/tc-section.directive.js") + script(src="directives/tc-transclude.directive.js") script(src="directives/track-toggle/track-toggle.directive.js") script(src="topcoder.module.js") script(src="filters/deadline-msg.filter.js") diff --git a/app/my-dashboard/subtrack-stats/subtrack-stats.controller.js b/app/my-dashboard/subtrack-stats/subtrack-stats.controller.js index 7d2886f34..a12f49625 100644 --- a/app/my-dashboard/subtrack-stats/subtrack-stats.controller.js +++ b/app/my-dashboard/subtrack-stats/subtrack-stats.controller.js @@ -3,9 +3,9 @@ angular.module('tc.myDashboard').controller('SubtrackStatsController', SubtrackStatsController); - SubtrackStatsController.$inject = ['ProfileService', 'userIdentity']; + SubtrackStatsController.$inject = ['$filter', 'ProfileService', 'userIdentity']; - function SubtrackStatsController(ProfileService, userIdentity) { + function SubtrackStatsController($filter, ProfileService, userIdentity) { var vm = this; vm.loading = true; @@ -20,11 +20,12 @@ var subtrackRanks = compileSubtracks(trackRanks); processStats(subtrackRanks); + // sort subtrack ranks + subtrackRanks = $filter('orderBy')(subtrackRanks, 'mostRecentEventDate', true); + vm.subtrackRanks = subtrackRanks; vm.hasRanks = !!vm.subtrackRanks.length; - buildCarouselSlide(); - vm.loading = false; }) .catch(function(err) { @@ -64,26 +65,5 @@ } }); } - - // This function aids in showing multiple items (subtracks) per slide - function buildCarouselSlide(numItemsPerSlide) { - var subtrackRanksCollection = []; - var slide = []; - // Might be able to change number of subtracks per slide based - // on screen size if the width of each subtrack is consistent: - // http://stackoverflow.com/questions/26252038/multi-item-responsive-carousel - numItemsPerSlide = numItemsPerSlide || 4; - - for(var i = 0; i < vm.subtrackRanks.length; i++) { - if (slide.length === numItemsPerSlide) { - // When slide is full, push it to collection and make a new slide [] - subtrackRanksCollection.push(slide); - slide = []; - } - slide.push(vm.subtrackRanks[i]); - } - subtrackRanksCollection.push(slide); - vm.subtrackRanksCollection = subtrackRanksCollection; - } } })(); diff --git a/app/my-dashboard/subtrack-stats/subtrack-stats.jade b/app/my-dashboard/subtrack-stats/subtrack-stats.jade index 8a2835b9d..821bb0c78 100644 --- a/app/my-dashboard/subtrack-stats/subtrack-stats.jade +++ b/app/my-dashboard/subtrack-stats/subtrack-stats.jade @@ -3,7 +3,7 @@ .ratings(ng-if="vm.hasRanks && !vm.loading") .tracks - .track(ng-repeat="subtrack in vm.subtrackRanks | orderBy:'mostRecentEventDate':true", ui-sref="profile.subtrack({userHandle: vm.handle, track: subtrack.track, subTrack: subtrack.subTrack})") + .track(ng-repeat="subtrack in vm.subtrackRanks", ui-sref="profile.subtrack({userHandle: vm.handle, track: subtrack.track, subTrack: subtrack.subTrack})") .flex-wrapper p.subtrack {{subtrack.subTrack | underscoreStrip}} @@ -14,15 +14,14 @@ p {{subtrack.statType}} - ul(rn-carousel, rn-carousel-controls) - li(ng-repeat="subtracks in vm.subtrackRanksCollection") - .track(ng-repeat="subtrack in subtracks | orderBy:'mostRecentEventDate':true", ui-sref="profile.subtrack({userHandle: vm.handle, track: subtrack.track, subTrack: subtrack.subTrack})") - .flex-wrapper - p.subtrack {{subtrack.subTrack | underscoreStrip}} + responsive-carousel(data="vm.subtrackRanks") + .track(ui-sref="profile.subtrack({userHandle: vm.handle, track: item.track, subTrack: item.subTrack})") + .flex-wrapper + p.subtrack {{item.subTrack | underscoreStrip}} - p.rating(ng-if="subtrack.track !== 'DESIGN'", style="color: {{subtrack.stat | ratingColor}}") {{subtrack.stat | number}} - span(style="background-color: {{subtrack.stat | ratingColor}}", ng-if="subtrack.track === 'DEVELOP' || subtrack.track === 'DATA_SCIENCE'") + p.rating(ng-if="item.track !== 'DESIGN'", style="color: {{item.stat | ratingColor}}") {{item.stat | number}} + span(style="background-color: {{item.stat | ratingColor}}", ng-if="item.track === 'DEVELOP' || item.track === 'DATA_SCIENCE'") - p.rating(ng-if="subtrack.track === 'DESIGN'", style="color: #21B2F1") {{subtrack.stat | number}} + p.rating(ng-if="item.track === 'DESIGN'", style="color: #21B2F1") {{item.stat | number}} - p {{subtrack.statType}} + p {{item.statType}} diff --git a/assets/css/directives/responsive-carousel.scss b/assets/css/directives/responsive-carousel.scss new file mode 100644 index 000000000..1346f8ef7 --- /dev/null +++ b/assets/css/directives/responsive-carousel.scss @@ -0,0 +1,71 @@ +@import 'topcoder-includes'; +@import '../partials/combined'; + +.tc-carousel { + + ul { + display: block; + height: 148px; + margin: 0 auto; + @media only screen and (max-width: 767px) { + display: none; + } + &[slide-count="1"] { + width: 170px; + } + &[slide-count="2"] { + width: 340px; + } + &[slide-count="3"] { + width: 510px; + } + &[slide-count="4"] { + width: 680px; + } + &[slide-count="5"] { + width: 850px; + } + &[slide-count="6"] { + width: 1020px; + } + &[slide-count="7"] { + width: 1190px; + } + + li { + div:last-child { + margin-right: 0; + } + } + } + + .rn-carousel-controls { + position: relative; + @media only screen and (max-width: 767px) { + display: none; + } + + .rn-carousel-control { + height: 148px; + width: 80px; + line-height: 148px; + top: -148px; + background-color: $gray-lightest; + color: $accent-gray; + text-align: center; + } + + .rn-carousel-control-prev { + left: 0; + } + + .rn-carousel-control-next { + right: 0; + } + + } + + .slide { + display: inline-block; + } +} \ No newline at end of file diff --git a/assets/css/my-dashboard/subtrack-stats.scss b/assets/css/my-dashboard/subtrack-stats.scss index daa445f4f..22f299f84 100644 --- a/assets/css/my-dashboard/subtrack-stats.scss +++ b/assets/css/my-dashboard/subtrack-stats.scss @@ -10,48 +10,25 @@ } } - ul { - display: block; - height: 148px; - width: 665px; - margin: 0 auto; - @media only screen and (max-width: 767px) { - display: none; - } + .slide { - li { - div:last-child { - margin-right: 0; + &:not(:first-child) { + .track:before { + content: ''; + display: block; + position: absolute; + top: 32px; + left: -30px; + @include forward-slash(1px, 60px, 0, 2px, 30deg); + background-color: #D1D3D4; + @media only screen and (min-width: 768px) { + top: 42px; + left: -18px; + } } } } - .rn-carousel-controls { - position: relative; - @media only screen and (max-width: 767px) { - display: none; - } - - .rn-carousel-control { - height: 148px; - width: 80px; - line-height: 148px; - top: -148px; - background-color: $gray-lightest; - color: $accent-gray; - text-align: center; - } - - .rn-carousel-control-prev { - left: 0; - } - - .rn-carousel-control-next { - right: 0; - } - - } - .track { position: relative; display: inline-block; @@ -91,21 +68,6 @@ align-items: center; } - - &:not(:first-child):before { - content: ''; - display: block; - position: absolute; - top: 32px; - left: -30px; - @include forward-slash(1px, 60px, 0, 2px, 30deg); - background-color: #D1D3D4; - @media only screen and (min-width: 768px) { - top: 42px; - left: -18px; - } - } - p { @include sofia-pro-regular; font-size: 12px;