diff --git a/app/assets/javascripts/discourse/components/badge-card.js.es6 b/app/assets/javascripts/discourse/components/badge-card.js.es6 new file mode 100644 index 000000000..bb694471c --- /dev/null +++ b/app/assets/javascripts/discourse/components/badge-card.js.es6 @@ -0,0 +1,15 @@ +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + size: 'medium', + classNameBindings: [':badge-card', 'size'], + + @computed('size') + summary(size) { + if (size === 'large') { + return Discourse.Emoji.unescape(this.get('badge.long_description') || ''); + } + return this.get('badge.translatedDescription'); + } + +}); diff --git a/app/assets/javascripts/discourse/components/check-mark.js.es6 b/app/assets/javascripts/discourse/components/check-mark.js.es6 index 702af6a15..a934a490a 100644 --- a/app/assets/javascripts/discourse/components/check-mark.js.es6 +++ b/app/assets/javascripts/discourse/components/check-mark.js.es6 @@ -1,11 +1,16 @@ import computed from 'ember-addons/ember-computed-decorators'; export default Ember.Component.extend({ - tagName: 'i', - classNameBindings: [':fa', 'iconClass'], + tagName: 'span', + classNameBindings: [':check-display', 'status'], @computed('checked') - iconClass(checked) { - return checked ? 'fa-check' : 'fa-times'; + status(checked) { + return checked ? 'status-checked' : 'status-unchecked'; + }, + + render(buffer) { + const icon = this.get('checked') ? 'check' : 'times'; + buffer.push(``); } }); diff --git a/app/assets/javascripts/discourse/controllers/badges/show.js.es6 b/app/assets/javascripts/discourse/controllers/badges/show.js.es6 index 52a4c7395..714635f60 100644 --- a/app/assets/javascripts/discourse/controllers/badges/show.js.es6 +++ b/app/assets/javascripts/discourse/controllers/badges/show.js.es6 @@ -44,11 +44,6 @@ export default Ember.Controller.extend({ @observes('canLoadMore') _showFooter() { this.set("controllers.application.showFooter", !this.get("canLoadMore")); - }, - - @computed('model.long_description') - longDescription(modelLongDesc) { - return Discourse.Emoji.unescape(modelLongDesc || ''); } }); diff --git a/app/assets/javascripts/discourse/models/badge.js.es6 b/app/assets/javascripts/discourse/models/badge.js.es6 index 6e3d852c7..3181739a2 100644 --- a/app/assets/javascripts/discourse/models/badge.js.es6 +++ b/app/assets/javascripts/discourse/models/badge.js.es6 @@ -33,13 +33,6 @@ const Badge = RestModel.extend({ return I18n.t(i18nKey, {defaultValue: this.get('name')}); }.property('name', 'i18nNameKey'), - /** - The i18n translated description for this badge. Returns the null if no - translation exists. - - @property translatedDescription - @type {String} - **/ translatedDescription: function() { const i18nKey = "badges.badge." + this.get('i18nNameKey') + ".description"; let translation = I18n.t(i18nKey); diff --git a/app/assets/javascripts/discourse/templates/badges/index.hbs b/app/assets/javascripts/discourse/templates/badges/index.hbs index 2d6de7fbd..093c258ee 100644 --- a/app/assets/javascripts/discourse/templates/badges/index.hbs +++ b/app/assets/javascripts/discourse/templates/badges/index.hbs @@ -1,21 +1,17 @@

{{i18n 'badges.title'}}

- - - {{#each bg in badgeGroups}} - - - - {{#each b in bg.badges}} - - - - - - +
+ {{#each bg in badgeGroups}} +
+
+

{{bg.badgeGrouping.displayName}}

+
+ + {{#each bg.badges as |b|}} + {{badge-card badge=b}} {{/each}} - {{/each}} -
-

{{bg.badgeGrouping.displayName}}

{{#if b.has_badge}}{{/if}}{{user-badge badge=b}}{{{b.displayDescriptionHtml}}}{{b.grant_count}}
+
+ {{/each}} + diff --git a/app/assets/javascripts/discourse/templates/badges/show.hbs b/app/assets/javascripts/discourse/templates/badges/show.hbs index c60cbb216..83b2c74db 100644 --- a/app/assets/javascripts/discourse/templates/badges/show.hbs +++ b/app/assets/javascripts/discourse/templates/badges/show.hbs @@ -5,18 +5,16 @@ {{model.displayName}} - {{#if longDescription}} - - {{/if}} - -
-
-
{{i18n 'badges.granted' count=grantCount}}
-
- {{i18n 'badges.allow_title'}} {{check-mark checked=model.allow_title}}
- {{i18n 'badges.multiple_grant'}} {{check-mark checked=model.multiple_grant}} +
+ {{badge-card badge=model size="large"}} +
+
+
+ {{check-mark checked=model.allow_title}} {{i18n 'badges.allow_title'}} +
+
+ {{check-mark checked=model.multiple_grant}} {{i18n 'badges.multiple_grant'}} +
diff --git a/app/assets/javascripts/discourse/templates/components/badge-card.hbs b/app/assets/javascripts/discourse/templates/components/badge-card.hbs new file mode 100644 index 000000000..6ba8ac189 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/badge-card.hbs @@ -0,0 +1,19 @@ +{{#link-to 'badges.show' badge}} + {{#if badge.grant_count}} + {{badge.grant_count}} + {{/if}} + {{#if badge.has_badge}} + {{fa-icon "check"}} + {{/if}} +
+
+ {{icon-or-image badge.icon}} +
+
+
+

{{badge.displayName}}

+
{{{summary}}}
+
+
+
+{{/link-to}} diff --git a/app/assets/stylesheets/common/base/user-badges.scss b/app/assets/stylesheets/common/base/user-badges.scss index 4501f7331..c18c6ac36 100644 --- a/app/assets/stylesheets/common/base/user-badges.scss +++ b/app/assets/stylesheets/common/base/user-badges.scss @@ -32,6 +32,7 @@ } } + /* User badge listing. */ .user-badges-list { text-align: center; @@ -64,55 +65,6 @@ } } -/* Badge listing in /badges. */ -.badges-listing { - - margin: 20px 0; - - tr.title { - border-bottom: 2px solid dark-light-diff($primary, $secondary, 90%, -60%); - } - - td { - padding: 10px 0; - } - - width: 90%; - padding: 10px; - display: table; - color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%)); - - .row { - display: table-row; - > div { - display: table-cell; - vertical-align: middle; - } - } - - .user-badge { - font-size: $base-font-size; - } - - .grant-count { - font-size: 120%; - font-weight: bold; - } - - .badge, .grant-count { - white-space: nowrap; - } - - .info { - font-size: 0.9em; - text-align: right; - } - - .description { - } - -} - @media all and (max-width: 750px) { .show-badge .user-badge-with-posts .badge-user a.post-link { width: auto; @@ -202,3 +154,127 @@ margin-bottom: 15px; margin-top: 15px; } + +.badge-card { + position: relative; + display: inline-block; + background-color: dark-light-diff($primary, $secondary, 95%, -65%); + margin-right: 5px; + margin-bottom: 10px; + box-shadow: 1px 1px 3px rgba(0.0, 0.0, 0.0, 0.2); + + .check-display { + position: absolute; + left: 5px; + top: 5px; + } + + .grant-count { + position: absolute; + right: 5px; + top: 5px; + font-weight: bold; + color: dark-light-diff($primary, $secondary, 50%, -65%); + font-size: 1.2em; + } + + .badge-contents { + display: flex; + flex-direction: row; + min-height: 128px; + + .badge-icon { + min-width: 90px; + display: flex; + align-items: center; + justify-content: center; + background-color: dark-light-diff($primary, $secondary, 92%, -60%); + font-size: 3em; + + &.badge-type-gold .fa { + color: #ffd700 !important; + } + + &.badge-type-silver .fa { + color: #c0c0c0 !important; + } + + &.badge-type-bronze .fa { + color: #cd7f32 !important; + } + } + + .badge-info { + display: flex; + align-items: center; + justify-content: center; + padding: 15px; + color: $primary; + + h3 { + margin-bottom: 0.25em; + } + } + } +} + +.badge-card.medium { + width: 360px; +} + +.badge-card.large { + width: 750px; + a { + cursor: default; + } +} + + +.badge-groups { + margin: 20px 0; + color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%)); + h3 { + margin-bottom: 1.0em; + } +} + +.badge-grouping { + margin-bottom: 1.5em; +} + +.show-badge-details { + display: flex; + flex-direction: row; + margin-bottom: 2em; + margin-top: 1em; + + .badge-grant-info { + display: flex; + align-items: center; + margin-left: 1em; + } + .grant-info-item { + margin-bottom: 1em; + color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%)); + } +} + +.check-display { + display: inline-block; + width: 18px; + border-radius: 10px; + text-align: center; + .fa { + font-size: 0.9em; + color: $secondary; + } +} + +.check-display.status-checked { + background-color: dark-light-diff($primary, $secondary, 40%, -60%); +} + +.check-display.status-unchecked { + background-color: $danger; +} + diff --git a/app/serializers/badge_index_serializer.rb b/app/serializers/badge_index_serializer.rb index 533c71133..85c013a4b 100644 --- a/app/serializers/badge_index_serializer.rb +++ b/app/serializers/badge_index_serializer.rb @@ -9,4 +9,5 @@ class BadgeIndexSerializer < BadgeSerializer def has_badge @options[:user_badges].include?(object.id) end + end diff --git a/test/javascripts/acceptance/badges-test.js.es6 b/test/javascripts/acceptance/badges-test.js.es6 index ec7d26fdb..77148f10f 100644 --- a/test/javascripts/acceptance/badges-test.js.es6 +++ b/test/javascripts/acceptance/badges-test.js.es6 @@ -5,12 +5,12 @@ acceptance("Badges"); test("Visit Badge Pages", () => { visit("/badges"); andThen(() => { - ok(exists('.badges-listing tr'), "has a list of badges"); + ok(exists('.badge-groups .badge-card'), "has a list of badges"); }); visit("/badges/9/autobiographer"); andThen(() => { - ok(exists('.badges-listing div'), "has the badge in the listing"); + ok(exists('.badge-card'), "has the badge in the listing"); ok(exists('.user-info'), "has the list of users with that badge"); }); });