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

Commit bacc0dd

Browse files
author
vikasrohit
committed
Merge pull request #454 from appirio-tech/feature/empty-state-directive
Feature/empty state directive @parthshah merging so that we can get enough time before GA release. However, I am still open for any suggestion.
2 parents d1b49da + 4e0fa31 commit bacc0dd

28 files changed

+499
-526
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.empty-state-placeholder(ng-show="vm.show", class="{{vm.theme}}")
2+
.title(ng-bind="vm.title")
3+
.content(ng-transclude, ng-show="transcluded")
4+
.description(ng-bind="vm.description")
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}}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
(function() {
2+
'use strict';
3+
4+
angular.module('tcUIComponents')
5+
.directive('emptyStatePlaceholder', emptyStatePlaceholder);
6+
7+
emptyStatePlaceholder.$inject = ['CONSTANTS', 'EmptyStateService'];
8+
9+
function emptyStatePlaceholder(CONSTANTS, EmptyStateService) {
10+
return {
11+
restrict: 'E',
12+
transclude: true,
13+
templateUrl: 'directives/empty-state-placeholder/empty-state-placeholder.directive.html',
14+
scope: {
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;
25+
},
26+
controller: ['$scope', 'CONSTANTS', '$attrs', '$element',
27+
function($scope, CONSTANTS, $attrs, $element) {
28+
$scope.DOMAIN = CONSTANTS.domain;
29+
var vm = this;
30+
vm.title = null;
31+
vm.description = null;
32+
vm.theme = _.get($scope, 'theme', null);
33+
vm.helpLinks = null;
34+
vm.show = _.get($scope, 'show', false);
35+
36+
activate();
37+
38+
function activate() {
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+
}
48+
}
49+
}],
50+
controllerAs: "vm"
51+
};
52+
}
53+
})();

app/index.jade

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ html
7575
link(rel="stylesheet", href="assets/css/directives/history-graph.css")
7676
link(rel="stylesheet", href="assets/css/directives/external-link-data.css")
7777
link(rel="stylesheet", href="assets/css/directives/external-account.css")
78+
link(rel="stylesheet", href="assets/css/directives/empty-state-placeholder.css")
7879
link(rel="stylesheet", href="assets/css/directives/distribution-graph.css")
7980
link(rel="stylesheet", href="assets/css/directives/dev-challenge-user-place.css")
8081
link(rel="stylesheet", href="assets/css/directives/design-lightbox.css")
@@ -188,6 +189,7 @@ html
188189
script(src="directives/challenge-tile/challenge-tile.directive.js")
189190
script(src="directives/challenge-user-place/challenge-user-place.directive.js")
190191
script(src="directives/distribution-graph/distribution-graph.directive.js")
192+
script(src="directives/empty-state-placeholder/empty-state-placeholder.directive.js")
191193
script(src="directives/external-account/external-account.directive.js")
192194
script(src="directives/focus-on.directive.js")
193195
script(src="directives/header/header-menu-item.directive.js")
@@ -264,6 +266,7 @@ html
264266
script(src="services/authtoken.service.js")
265267
script(src="services/blog.service.js")
266268
script(src="services/challenge.service.js")
269+
script(src="services/emptyState.service.js")
267270
script(src="services/communityData.service.js")
268271
script(src="services/externalAccounts.service.js")
269272
script(src="services/helpers.service.js")

app/my-challenges/my-challenges.controller.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
$log = $log.getInstance('MyChallengesController');
1010
var vm = this;
1111
vm.domain = CONSTANTS.domain;
12+
vm.neverParticipated = false;
1213
vm.myChallenges = [];
1314
vm.loading = CONSTANTS.STATE_LOADING;
1415
vm.view = UserService.getPreference($state.$current.name+'.challengeListView') || 'tile';
@@ -82,10 +83,16 @@
8283
$q.all(promises)
8384
.then(function(data) {
8485
// data should be an array of 2 objects each with it's own array (2D array with metadata)
85-
vm.loading = CONSTANTS.STATE_READY;
8686

8787
vm.totalCount = _.sum(_.pluck(data, 'metadata.totalCount'));
8888
vm.myChallenges = vm.myChallenges.concat(_.union(data[0], data[1]));
89+
if (vm.totalCount === 0) {
90+
_checkForParticipation().then(function() {
91+
vm.loading = CONSTANTS.STATE_READY;
92+
});
93+
} else {
94+
vm.loading = CONSTANTS.STATE_READY;
95+
}
8996
})
9097
.catch(function(resp) {
9198
$log.error(resp);
@@ -141,5 +148,11 @@
141148
currentOffset+=1;
142149
vm.getChallenges(currentOffset, false);
143150
}
151+
152+
function _checkForParticipation() {
153+
return ChallengeService.checkChallengeParticipation(vm.handle, function(participated) {
154+
vm.neverParticipated = !participated;
155+
});
156+
}
144157
}
145158
})();

app/my-challenges/my-challenges.jade

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
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-
section.challenges
8+
.never-participated(ng-if="vm.neverParticipated")
9+
empty-state-placeholder(state-name="my-challenges-never-participated", show="vm.neverParticipated", theme="offwhite")
10+
section.participated(ng-if="!vm.neverParticipated")
911
.top
1012
.filters
1113
a(ng-click="vm.statusFilter !== 'active' && vm.changeFilter('active')", ng-class="{disabled: vm.statusFilter == 'active'}") Active
@@ -17,11 +19,12 @@
1719

1820
button.list(ng-click="vm.changeView('list')", ng-class="{ disabled: vm.view === 'list' }") List
1921

20-
.noChallenges(ng-show="vm.myChallenges.length === 0 && vm.loading === 'ready'")
21-
p(ng-show="vm.statusFilter === 'completed'") You have not participated in any challenges yet.
22-
p(ng-if="vm.statusFilter === 'active'") There are no upcoming challenges.
22+
section.noChallenges(ng-show="vm.myChallenges.length === 0 && vm.loading === 'ready'")
2323

24-
.hasChallenges(ng-show="vm.myChallenges.length")
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")
26+
27+
.hasChallenges(ng-show="vm.myChallenges.length", state="vm.loading")
2528

2629
.data(ng-class="vm.view + '-view'")
2730
challenge-tile(

app/my-dashboard/my-challenges/my-challenges.controller.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
function MyChallengesWidgetController(ChallengeService, UserService, $log, CONSTANTS, userIdentity, $q) {
99
var vm = this;
1010
vm.domain = CONSTANTS.domain;
11+
vm.neverParticipated = false;
1112
vm.loading = true;
1213
vm.userHasChallenges = true;
1314
vm.challengeView = 'tile';
@@ -44,15 +45,17 @@
4445

4546
if (!marathonMatches.length && !devDesignChallenges.length) {
4647
vm.userHasChallenges = false;
47-
vm.loading = false;
48+
_checkForParticipation().then(function() {
49+
vm.loading = false;
50+
});
4851

4952
} else {
5053
ChallengeService.processActiveDevDesignChallenges(devDesignChallenges);
5154
ChallengeService.processActiveMarathonMatches(marathonMatches);
5255
var userChallenges = marathonMatches.concat(devDesignChallenges);
5356

5457
userChallenges = _.sortBy(userChallenges, function(n) {
55-
return n.registrationEndDate
58+
return n.registrationEndDate;
5659
});
5760
vm.myChallenges = userChallenges.reverse().slice(0, 8);
5861
vm.userHasChallenges = true;
@@ -71,5 +74,11 @@
7174
vm.challengeView = view;
7275
}
7376
}
77+
78+
function _checkForParticipation() {
79+
return ChallengeService.checkChallengeParticipation(handle, function(participated) {
80+
vm.neverParticipated = !participated;
81+
});
82+
}
7483
}
7584
})();
Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
header(ng-hide="vm.loading")
2-
h1.section-title Active Challenges
1+
header(ng-hide="vm.loading || !vm.userHasChallenges")
2+
h1.section-title My Challenges
33

44
.challenge-view-toggle(ng-show="vm.userHasChallenges")
55
button.tile(ng-click="vm.toggleView('tile')", ng-class="{ disabled: vm.challengeView === 'tile' }") Grid
@@ -9,31 +9,9 @@ header(ng-hide="vm.loading")
99
.section-loading(ng-show="vm.loading")
1010

1111
section.noChallenges(ng-if="!vm.userHasChallenges && !vm.loading")
12-
h3 Win prize money and expand your knowledge
13-
14-
.tracks
15-
.track
16-
.develop-icon-outline
17-
p Development
18-
19-
.track
20-
.design-icon-outline
21-
p Design
22-
23-
.track
24-
.data-science-icon-outline
25-
p Data Science
26-
27-
.track
28-
.copilot-icon-outline
29-
p Co-Pilot
30-
31-
p.info Compete in challenges to win money, test yourself against the world's best, and learn new skills
32-
33-
.info-links
34-
a.tc-btn.tc-btn-l(ng-href="https://www.{{DOMAIN}}/challenges/?pageIndex=1") Find Challenges
35-
36-
a.tc-btn.tc-btn-ghost.tc-btn-l(href="https://www.{{DOMAIN}}/community/getting-started/") Learn More
12+
.never-participated(ng-if="vm.neverParticipated")
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")
3715

3816
section.hasChallenges(ng-if="vm.userHasChallenges && !vm.loading", ng-class="{ 'list-view-active': vm.challengeView === 'list' }")
3917
.section-titles(ng-show="vm.challengeView === 'list'")
@@ -45,7 +23,7 @@ section.hasChallenges(ng-if="vm.userHasChallenges && !vm.loading", ng-class="{ '
4523

4624
challenge-tile(ng-repeat="challenge in vm.myChallenges | orderBy:registrationEndDate:true", challenge="challenge", view="vm.challengeView", ng-class="vm.challengeView + '-view'")
4725

48-
.my-challenges-links(id="viewAllChallenges", ng-show="vm.userHasChallenges && !vm.loading")
49-
a.active(ui-sref="my-challenges({status: 'active'})") View More
26+
.my-challenges-links(id="viewAllChallenges", ng-show="!vm.neverParticipated && !vm.loading")
27+
a.active(ui-sref="my-challenges({status: 'active'})", ng-if="vm.userHasChallenges") View More
5028

5129
a.past(ui-sref="my-challenges({status: 'completed'})") Past Challenges

app/my-dashboard/my-dashboard.jade

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.my-dashboard-container
44
.subtrack-stats(id="stats", ui-view="subtrack-stats")
55

6-
.my-challenges(id="challenges", ui-view="my-challenges")
6+
.challenges(id="challenges", ui-view="my-challenges")
77

88
.srms(id="srms", ui-view="srms", ng-show="dashboard.showSRMs")
99

app/my-dashboard/programs/programs.jade

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
header(ng-hide="vm.loading")
1+
header(ng-hide="vm.loading || !vm.registered")
22
h1.section-title #[span iOS]: Show Your Skills
33

44
.section-loading(ng-show="vm.loading")
55

66
section.ios(ng-hide="vm.loading")
77
.unregistered(ng-hide="vm.registered")
8-
img(src="/images/learn-and-improve.png", srcset="/images/learn-and-improve2x.png 2x")
9-
10-
.join-program
11-
h3 #[span iOS]: Show Your Skills
12-
13-
h4 Take the first steps to stand out in the Community
14-
15-
p Experienced and proven iOS developers are in high-demand. Prove your skills by earning these iOS topcoder badges and gain exclusive access to iOS challenges and prize accelerators, special previews into content and releases, and special community-related events and info.
16-
17-
.info-links
18-
a.tc-btn(ng-click="vm.registerUser()") Participate
19-
20-
a.tc-btn.tc-btn-ghost(ng-href="https://ios.{{DOMAIN}}", target="_blank") Learn More
8+
empty-state-placeholder(state-name="dashboard-ios-community", show="!vm.registered", theme="sky")
219

2210
.registered(ng-show="vm.registered")
2311
.badge-and-challenges

app/my-srms/my-srms.jade

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
button.list(ng-click="vm.changeView('list')", ng-class="{ disabled: vm.view === 'list' }") List
1717

1818
.no-srms(ng-if="!vm.srms.length && vm.loading === 'ready'")
19-
p(ng-if="vm.statusFilter === 'future'") There are no upcoming SRMs.
20-
p(ng-if="vm.statusFilter === 'past'") You have not participated in any SRMs yet.
19+
empty-state-placeholder(title="Past SRMs", description="You have not participated in any SRMs yet.", show="vm.statusFilter === 'past'")
20+
.info-links
21+
a.find-srms.tc-btn.tc-btn-s.tc-btn-ghost(ng-href="https://www.{{DOMAIN}}/challenges/data?pageIndex=1") Find SRMs
22+
a.learn-more(href="https://www.{{DOMAIN}}/member-onboarding") Learn More
23+
empty-state-placeholder(title="Upcoming SRMs", description="There are no upcoming SRMs.", show="vm.statusFilter === 'future'")
2124

2225
.has-srms(ng-show="vm.srms.length")
2326
.data(ng-class="vm.view + '-view'")
2427
srm-tile.srm-tile(
2528
ng-repeat="srm in vm.srms | orderBy:vm.orderBy:vm.reverseOrder",
2629
srm="srm", view="vm.view", ng-class="vm.view + '-view'", show-results="vm.statusFilter === 'past'")
2730

28-
tc-endless-paginator(state="vm.loading", page-params="vm.pageParams")
31+
tc-endless-paginator(state="vm.loading", page-params="vm.pageParams")

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

0 commit comments

Comments
 (0)