Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit 5e7f66e

Browse files
author
vikasrohit
committed
SUP-2231, New Empty States for Dashboard and Profile
-- Refactored the empty state directive to accommodate dynamic content html between title and description -- Created service for empty state data -- Added support for themes in empty state directive to avoid any css set in parent page's css -- Added empty states for profile page (skills, activity, external links)
1 parent 281dbe0 commit 5e7f66e

File tree

14 files changed

+315
-375
lines changed

14 files changed

+315
-375
lines changed
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
.empty-state-placeholder(ng-show="vm.show")
1+
.empty-state-placeholder(ng-show="vm.show", class="{{vm.theme}}")
22
.title(ng-bind="vm.title")
3+
.content(ng-transclude, ng-show="transcluded")
34
.description(ng-bind="vm.description")
4-
.upsell(ng-transclude)
5+
.help-links
6+
.help-link(ng-repeat="link in vm.helpLinks")
7+
a(class="{{link.cssClass}}", title="{{link.title}}", ng-href="{{link.url}}", ng-if="link.url") {{link.title}}
8+
a(class="{{link.cssClass}}", title="{{link.title}}", ui-sref="{{link.state}}", ng-if="link.state") {{link.title}}
9+
a(class="{{link.cssClass}}", title="{{link.title}}", ng-click="link.onClick", ng-if="link.onClick") {{link.title}}

app/directives/empty-state-placeholder/empty-state-placeholder.directive.js

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,47 @@
44
angular.module('tcUIComponents')
55
.directive('emptyStatePlaceholder', emptyStatePlaceholder);
66

7-
function emptyStatePlaceholder() {
7+
emptyStatePlaceholder.$inject = ['CONSTANTS', 'EmptyStateService'];
8+
9+
function emptyStatePlaceholder(CONSTANTS, EmptyStateService) {
810
return {
911
restrict: 'E',
1012
transclude: true,
1113
templateUrl: 'directives/empty-state-placeholder/empty-state-placeholder.directive.html',
1214
scope: {
13-
title: '@',
14-
description: '@',
15-
show: '='
15+
show: '=',
16+
stateName: '@',
17+
theme: '@'
18+
},
19+
link : function(scope, element, attrs) {
20+
var rootDiv = angular.element(element.children()[0]);
21+
var contentDiv = _.find(rootDiv.children(), function(el) {
22+
return angular.element(el).hasClass("content");
23+
});
24+
scope.transcluded = angular.element(contentDiv)[0].children.length > 0;
1625
},
17-
controller: ['$scope', 'CONSTANTS', '$attrs',
18-
function($scope, CONSTANTS, $attrs) {
26+
controller: ['$scope', 'CONSTANTS', '$attrs', '$element',
27+
function($scope, CONSTANTS, $attrs, $element) {
1928
$scope.DOMAIN = CONSTANTS.domain;
2029
var vm = this;
21-
vm.title = $scope.title;
22-
vm.description = $scope.description;
30+
vm.title = null;
31+
vm.description = null;
32+
vm.theme = _.get($scope, 'theme', null);
33+
vm.helpLinks = null;
2334
vm.show = _.get($scope, 'show', false);
2435

2536
activate();
2637

2738
function activate() {
28-
$scope.$watch('show', function (newValue, oldValue) {
29-
vm.show = newValue;
30-
})
39+
var state = EmptyStateService.getState($scope.stateName);
40+
if (state) {
41+
vm.title = state.title;
42+
vm.description = state.description;
43+
vm.helpLinks = state.helpLinks;
44+
$scope.$watch('show', function (newValue, oldValue) {
45+
vm.show = newValue;
46+
});
47+
}
3148
}
3249
}],
3350
controllerAs: "vm"

app/index.jade

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ html
258258
script(src="services/authtoken.service.js")
259259
script(src="services/blog.service.js")
260260
script(src="services/challenge.service.js")
261+
script(src="services/emptyState.service.js")
261262
script(src="services/externalAccounts.service.js")
262263
script(src="services/helpers.service.js")
263264
script(src="services/image.service.js")

app/my-challenges/my-challenges.jade

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,8 @@
55
page-state-header(handle="{{vm.handle}}", page-title="My Challenges", hide-money="true", show-back-link="true", default-state="dashboard")
66

77
.content
8-
98
.never-participated(ng-if="vm.neverParticipated")
10-
empty-state-placeholder(title="My Challenges", description="Compete in challenges to win money, test yourself against the world's best, and learn new skills", show="vm.neverParticipated")
11-
.info-links
12-
a.find-challenges.tc-btn.tc-btn-s(ng-href="https://www.{{DOMAIN}}/challenges/?pageIndex=1") Find Challenges
13-
14-
a.learn-more(href="https://www.{{DOMAIN}}/member-onboarding") Learn More
9+
empty-state-placeholder(state-name="my-challenges-never-participated", show="vm.neverParticipated", theme="offwhite")
1510
section.participated(ng-if="!vm.neverParticipated")
1611
.top
1712
.filters
@@ -25,13 +20,9 @@
2520
button.list(ng-click="vm.changeView('list')", ng-class="{ disabled: vm.view === 'list' }") List
2621

2722
section.noChallenges(ng-show="vm.myChallenges.length === 0 && vm.loading === 'ready'")
28-
empty-state-placeholder(title="Past Challenges", description="You have not participated in any challenges yet.", show="vm.statusFilter === 'completed'")
29-
.info-links
30-
a.find-challenges.tc-btn.tc-btn-s(ng-href="https://www.{{DOMAIN}}/challenges/?pageIndex=1") Find Challenges
31-
a.learn-more(href="https://www.{{DOMAIN}}/member-onboarding") Learn More
32-
empty-state-placeholder(title="Active Challenges", description="You don't have any active challenges. Ready to find your next challenge?", show="vm.statusFilter === 'active'")
33-
.info-links
34-
a.find-challenges.tc-btn.tc-btn-s(ng-click="vm.changeFilter('completed')") Explore Open Challenges
23+
24+
empty-state-placeholder(state-name="my-challenges-past", show="vm.statusFilter === 'completed'", theme="offwhite")
25+
empty-state-placeholder(state-name="my-challenges-active", show="vm.statusFilter === 'active'", theme="offwhite")
3526

3627
.hasChallenges(ng-show="vm.myChallenges.length", state="vm.loading")
3728

app/my-dashboard/my-challenges/my-challenges.jade

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,8 @@ header(ng-hide="vm.loading || !vm.userHasChallenges")
1010

1111
section.noChallenges(ng-if="!vm.userHasChallenges && !vm.loading")
1212
.never-participated(ng-if="vm.neverParticipated")
13-
empty-state-placeholder(title="My Challenges", description="Compete in challenges to win money, test yourself against the world's best, and learn new skills", show="vm.neverParticipated")
14-
.info-links
15-
a.find-challenges.tc-btn.tc-btn-s(ng-href="https://www.{{DOMAIN}}/challenges/?pageIndex=1") Find Challenges
16-
17-
a.learn-more(href="https://www.{{DOMAIN}}/member-onboarding") Learn More
18-
empty-state-placeholder(title="My Challenges", description="You don't have any active challenges. Ready to find your next challenge?", show="!vm.userHasChallenges && !vm.neverParticipated")
19-
.info-links
20-
a.find-challenges.tc-btn.tc-btn-s(ui-sref="my-challenges({status: 'completed'})") Explore Open Challenges
13+
empty-state-placeholder(state-name="dashboard-challenges-never-participated", show="vm.neverParticipated", theme="black")
14+
empty-state-placeholder(state-name="dashboard-challenges", show="!vm.userHasChallenges && !vm.neverParticipated", theme="black")
2115

2216
section.hasChallenges(ng-if="vm.userHasChallenges && !vm.loading", ng-class="{ 'list-view-active': vm.challengeView === 'list' }")
2317
.section-titles(ng-show="vm.challengeView === 'list'")

app/my-dashboard/programs/programs.jade

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ header(ng-hide="vm.loading || !vm.registered")
55

66
section.ios(ng-hide="vm.loading")
77
.unregistered(ng-hide="vm.registered")
8-
empty-state-placeholder(title="iOS COMMUNITY", description="Earn iOS topcoder badges and exclusive access to iOS challenges, prizes and special community-related events.", show="!vm.registered")
9-
.info-links
10-
a.participate.tc-btn.tc-btn-s(ng-click="vm.registerUser()") Participate
11-
12-
a.learn-more(ng-href="https://ios.{{DOMAIN}}", target="_blank") Learn More
8+
empty-state-placeholder(state-name="dashboard-ios-community", show="!vm.registered", theme="sky")
139

1410
.registered(ng-show="vm.registered")
1511
.badge-and-challenges

app/profile/about/about.jade

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
tc-section(ng-show="vm.displaySection.skills", state="profileVm.status.skills")
1616

1717
.skills
18-
h3.activity Skills
18+
h3.activity(ng-hide="!profileVm.skills || (profileVm.skills && profileVm.skills.length == 0)") Skills
1919

2020
.list(ng-show="profileVm.skills && profileVm.skills.length > 0")
2121

@@ -25,31 +25,21 @@
2525
button.tc-btn.tc-btn-s.more(ng-if="vm.skills.length < vm.fullSkills.length", ng-click="vm.skills = vm.fullSkills") VIEW ALL
2626
button.tc-btn.tc-btn-s.more(ng-if="vm.skills.length > 10", ng-click="vm.skills = vm.someSkills") VIEW LESS
2727

28-
.empty-state(ng-show="!profileVm.skills || (profileVm.skills && profileVm.skills.length == 0)")
29-
.action-text Tell everyone what you know
28+
.empty-state
29+
empty-state-placeholder(state-name="profile-skills", show="!profileVm.skills || (profileVm.skills && profileVm.skills.length == 0)")
30+
.sample-skills
31+
.skill(ng-repeat="skill in vm.sampleSkills")
32+
skill-tile(skill="skill")
3033

31-
.list
32-
.skill(ng-repeat="skill in vm.sampleSkills")
33-
skill-tile(skill="skill")
3434

35-
.description You can add languages, environments, frameworks, libraries, platforms, tools, and any other technologies that you know well.
36-
37-
button.tc-btn.tc-btn-s.link-button(ui-sref="settings.profile") ADD SKILLS
3835

3936
#tcActivity
4037
tc-section(ng-show="vm.displaySection.stats", state="profileVm.status.stats")
4138

4239
.categories
4340

44-
.empty-state(ng-if="!profileVm.numProjects")
45-
.action-text Start competing within the community
46-
.tracks
47-
.track.noclick(ng-repeat="track in ['DEVELOP', 'DESIGN', 'DATA_SCIENCE']")
48-
div(class="{{profileVm.imgMap[track]}}-icon")
49-
div
50-
.text {{track | track}}
51-
.description Compete in challenges to win money, test yourself against the world's best, and learn new skills. Your performance rating will show up here.
52-
a.tc-btn.tc-btn-s.link-button(href="/challenges") FIND CHALLENGES
41+
.empty-state
42+
empty-state-placeholder(state-name="profile-topcoder-activity", show="!profileVm.numProjects", theme="offwhite")
5343

5444
.track(
5545
ng-repeat="track in profileVm.profile.tracks",
@@ -97,14 +87,10 @@
9787
#externalLinks
9888
tc-section(ng-show="vm.displaySection.externalLinks", state="profileVm.status.externalLinks")
9989
.external-links
100-
h3.activity on the web
90+
h3.activity(ng-if="vm.hasLinks") on the web
10191
external-links-data(ng-show="vm.hasLinks", external-links="vm.linkedExternalAccounts", linked-accounts-data="vm.linkedExternalAccountsData")
10292

103-
.empty-state(ng-hide="vm.hasLinks")
104-
.action-text Showcase your work from around the web
105-
106-
external-accounts.external-account-container(linked-accounts="[]", links-data="{}", read-only="true")
107-
108-
.description Show off your work and experience outside of Topcoder. Connect accounts from popular services and networks or add a link to any site.
93+
.empty-state
94+
empty-state-placeholder(state-name="profile-external-links", show="!vm.hasLinks")
95+
external-accounts.external-account-container(linked-accounts="[]", links-data="{}", read-only="true")
10996

110-
button.tc-btn.tc-btn-s.link-button(ui-sref="settings.profile") CONNECT ACCOUNTS

app/services/emptyState.service.js

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
(function() {
2+
'use strict';
3+
4+
angular.module('tc.services').factory('EmptyStateService', EmptyStateService);
5+
6+
EmptyStateService.$inject = ['CONSTANTS'];
7+
8+
function EmptyStateService(CONSTANTS) {
9+
var states = null;
10+
var domain = CONSTANTS.domain;
11+
_init();
12+
13+
var service = {
14+
getState: getState
15+
};
16+
17+
return service;
18+
19+
function getState(stateName) {
20+
if (states[stateName]) {
21+
return states[stateName];
22+
}
23+
return null;
24+
}
25+
26+
function _getUrl (path) {
27+
return "https://www." + domain + path;
28+
}
29+
30+
function _getIOSUrl(path) {
31+
return "https://ios." + domain + path;
32+
}
33+
34+
function _init() {
35+
states = {
36+
"dashboard-challenges": {
37+
title: "My Challenges",
38+
description: "You don't have any active challenges. Ready to find your next challenge?",
39+
helpLinks: [{
40+
title: "Explore Open Challenges",
41+
state: "my-challenges({status: 'completed'})",
42+
cssClass: "find-challenges tc-btn tc-btn-s"
43+
}]
44+
},
45+
"dashboard-ios-community": {
46+
title: "iOS COMMUNITY",
47+
description: "Earn iOS topcoder badges and exclusive access to iOS challenges, prizes and special community-related events.",
48+
helpLinks: [{
49+
title: "Participate",
50+
onClick: "vm.registerUser()",
51+
cssClass: "participate tc-btn tc-btn-s tc-btn-ghost"
52+
}, {
53+
title: "Learn More",
54+
url: _getIOSUrl("/"),
55+
cssClass: "learn-more"
56+
}]
57+
},
58+
"dashboard-challenges-never-participated": {
59+
title: "My Challenges",
60+
description: "Compete in challenges to win money, test yourself against the world's best, and learn new skills",
61+
helpLinks: [{
62+
title: "Find Challenges",
63+
url: _getUrl("/challenges/?pageIndex=1"),
64+
cssClass: "find-challenges tc-btn tc-btn-s"
65+
}, {
66+
title: "Learn More",
67+
url: _getUrl("/member-onboarding"),
68+
cssClass: "learn-more"
69+
}]
70+
},
71+
"my-challenges-active": {
72+
title: "Active Challenges",
73+
description: "You don't have any active challenges. Ready to find your next challenge?",
74+
helpLinks: [{
75+
title: "Explore Open Challenges",
76+
state: "my-challenges({status: 'completed'})",
77+
cssClass: "find-challenges tc-btn tc-btn-s tc-btn-ghost"
78+
}]
79+
},
80+
"my-challenges-past": {
81+
title: "Past Challenges",
82+
description: "You have not participated in any challenges yet.",
83+
helpLinks: [{
84+
title: "Find Challenges",
85+
url: _getUrl("/challenges/?pageIndex=1"),
86+
cssClass: "find-challenges tc-btn tc-btn-s tc-btn-ghost"
87+
}, {
88+
title: "Learn More",
89+
url: _getUrl("/member-onboarding"),
90+
cssClass: "learn-more"
91+
}]
92+
},
93+
"my-challenges-never-participated": {
94+
title: "My Challenges",
95+
description: "Compete in challenges to win money, test yourself against the world's best, and learn new skills",
96+
helpLinks: [{
97+
title: "Find Challenges",
98+
url: _getUrl("/challenges/?pageIndex=1"),
99+
cssClass: "find-challenges tc-btn tc-btn-s tc-btn-ghost"
100+
}, {
101+
title: "Learn More",
102+
url: _getUrl("/member-onboarding"),
103+
cssClass: "learn-more"
104+
}]
105+
},
106+
"profile-topcoder-activity": {
107+
title: "My Challenges",
108+
description: "You have not participated in any challenges yet.",
109+
helpLinks: [{
110+
title: "Explore Challenges",
111+
url: _getUrl("/challenges/?pageIndex=1"),
112+
cssClass: "find-challenges tc-btn tc-btn-s tc-btn-ghost"
113+
}, {
114+
title: "Learn More",
115+
url: _getUrl("/member-onboarding"),
116+
cssClass: "learn-more"
117+
}]
118+
},
119+
"profile-skills": {
120+
title: "Skills",
121+
description: "You can add languages, environments, frameworks, libraries, platforms, tools, and any other technologies that you know well.",
122+
helpLinks: [{
123+
title: "Add Your Skills",
124+
state: "settings.profile",
125+
cssClass: "add-skills tc-btn tc-btn-s tc-btn-ghost"
126+
}]
127+
},
128+
"profile-external-links": {
129+
title: "External Links",
130+
description: "You can add languages, environments, frameworks, libraries, platforms, tools, and any other technologies that you know well.",
131+
helpLinks: [{
132+
title: "Connect Your Accounts",
133+
state: "settings.profile",
134+
cssClass: "connect-external-accounts tc-btn tc-btn-s tc-btn-ghost"
135+
}]
136+
}
137+
}
138+
}
139+
};
140+
})();

0 commit comments

Comments
 (0)