From fc3305f316c6b4e3947eec8a584ffd199da0fba2 Mon Sep 17 00:00:00 2001 From: mimidotuser Date: Thu, 20 May 2021 23:58:14 +0300 Subject: [PATCH 01/25] feat: users & badges admin page UI design --- frontend/app/components/admin/sidenav.hbs | 5 + .../app/controllers/admin/badges/users.js | 88 +++++++ frontend/app/models/badge.js | 24 ++ frontend/app/router.js | 4 +- frontend/app/routes/admin/badges/users.js | 8 + .../app/styles/admin/_badge-management.scss | 235 ++++++++++++++++++ frontend/app/styles/admin/admin.scss | 1 + frontend/app/templates/admin/badges.hbs | 5 +- frontend/app/templates/admin/badges/users.hbs | 184 ++++++++++++++ frontend/public/images/icons/target.svg | 1 + .../controllers/admin/badges/users-test.js | 12 + frontend/tests/unit/models/badge-test.js | 13 + .../unit/routes/admin/badges/users-test.js | 11 + frontend/translations/admin/en-us.yaml | 20 ++ frontend/translations/admin/sw-ke.yaml | 20 ++ frontend/translations/en-us.yaml | 12 + frontend/translations/sw-ke.yaml | 12 + 17 files changed, 652 insertions(+), 3 deletions(-) create mode 100644 frontend/app/controllers/admin/badges/users.js create mode 100644 frontend/app/models/badge.js create mode 100644 frontend/app/routes/admin/badges/users.js create mode 100644 frontend/app/templates/admin/badges/users.hbs create mode 100644 frontend/public/images/icons/target.svg create mode 100644 frontend/tests/unit/controllers/admin/badges/users-test.js create mode 100644 frontend/tests/unit/models/badge-test.js create mode 100644 frontend/tests/unit/routes/admin/badges/users-test.js diff --git a/frontend/app/components/admin/sidenav.hbs b/frontend/app/components/admin/sidenav.hbs index a065f4e1b..c80ea77f4 100644 --- a/frontend/app/components/admin/sidenav.hbs +++ b/frontend/app/components/admin/sidenav.hbs @@ -41,6 +41,11 @@ {{t "admin.sidenav.manage_badges"}} + diff --git a/frontend/app/controllers/admin/badges/users.js b/frontend/app/controllers/admin/badges/users.js new file mode 100644 index 000000000..6a3bef77e --- /dev/null +++ b/frontend/app/controllers/admin/badges/users.js @@ -0,0 +1,88 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +export default class AdminBadgesUsersController extends Controller { + @service me; + @service store; + @tracked userSearchTerm; + @tracked showPerPage = 10; + @tracked currentPage = 1; + + perPageOptions = [ + { value: 5, selected: false }, + { value: 10, selected: true }, + { value: 20, selected: false }, + { value: 50, selected: false }, + { value: 100, selected: false }, + ]; + + get badges() { + return this.store.peekAll('badge'); + } + + get badgesUnlockedCount() { + return 0; //TODO + } + + @action + updatePerPage(evt) { + this.currentPage = 1; // It's easier than doing calculations. + this.showPerPage = +evt.target.selectedOptions[0].value; + } + + get pageNumericSummary() { + const recordsCount = this.model.length; + + let firstIndex = 1; + if (this.currentPage > 1) { + firstIndex = this.showPerPage * this.currentPage - (this.showPerPage - 1); + } + + let lastIndex = this.showPerPage * this.currentPage; + if (lastIndex > recordsCount) { + lastIndex = recordsCount; + } + + return { firstIndex, lastIndex, recordsCount }; + } + + get paginationSummary() { + const { + recordsCount, + firstIndex: pageFirstIndex, + lastIndex: pageLastIndex, + } = this.pageNumericSummary; + + if (recordsCount <= this.showPerPage) { + return `Showing All Users`; + } + + return `Showing ${pageFirstIndex} - ${pageLastIndex} of ${recordsCount}`; + } + + @action + goToPrevPage() { + if (this.hasPreviousPage) { + this.currentPage = --this.currentPage; + } + } + + @action + goToNextPage() { + if (this.hasNextPage) { + this.currentPage = ++this.currentPage; + } + } + + get hasNextPage() { + const { recordsCount, lastIndex } = this.pageNumericSummary; + return lastIndex !== recordsCount; + } + + get hasPreviousPage() { + const { recordsCount } = this.pageNumericSummary; + return this.currentPage > 1 && recordsCount > this.showPerPage; + } +} diff --git a/frontend/app/models/badge.js b/frontend/app/models/badge.js new file mode 100644 index 000000000..fa8d486e6 --- /dev/null +++ b/frontend/app/models/badge.js @@ -0,0 +1,24 @@ +import Model, { attr } from '@ember-data/model'; + +export default class BadgeModel extends Model { + @attr() name; + @attr() slug; + @attr() badgeUri; + @attr() triggerId; + @attr('number') points; + @attr() description; + @attr() expiry; + @attr('boolean') isDeleted; + @attr('boolean') published; + @attr('number') frequency; + @attr('number') reminder; + @attr() creatorId; + @attr() reminderMessage; + @attr() metadata; + @attr('date') createdAt; + @attr('date') updatedAt; + + get iconUrl() { + return this.badgeUri; + } +} diff --git a/frontend/app/router.js b/frontend/app/router.js index 7f5d5529c..57d6b628b 100644 --- a/frontend/app/router.js +++ b/frontend/app/router.js @@ -46,7 +46,9 @@ Router.map(function () { this.route('admin', function () { this.route('dashboard', { path: '/' }); this.route('users'); - this.route('badges'); + this.route('badges', function () { + this.route('users'); + }); }); // 404 page should always be the last diff --git a/frontend/app/routes/admin/badges/users.js b/frontend/app/routes/admin/badges/users.js new file mode 100644 index 000000000..081bfb354 --- /dev/null +++ b/frontend/app/routes/admin/badges/users.js @@ -0,0 +1,8 @@ +import Route from '@ember/routing/route'; + +export default class AdminBadgesUsersRoute extends Route { + async afterModel(resolvedModel, transition) { + await this.store.query('badge', { isDeleted: false }); + return super.afterModel(resolvedModel, transition); + } +} diff --git a/frontend/app/styles/admin/_badge-management.scss b/frontend/app/styles/admin/_badge-management.scss index e69de29bb..c51f593b1 100644 --- a/frontend/app/styles/admin/_badge-management.scss +++ b/frontend/app/styles/admin/_badge-management.scss @@ -0,0 +1,235 @@ +$palette: ( + primary: #F57010, + black: #000000, + boxShadow: #0A4B6D2E, + gray30: #3F484D, + darkCharchoal: #333333, + luckyGrey: #777777, + white: #FFFF +); + +.badges .users-badges-homepage { + + .header-section { + .title { + font-size: 22px; + color: map-get($palette, black); + font-weight: bold; + } + + .card { + box-shadow: 0px 3px 16px map-get($palette, boxShadow); + height: 100%; + + .card-body { + padding-top: 15px; + } + } + + .action-prompt-card { + .prompt-title { + font-size: 16px; + font-weight: 600; + padding-bottom: 8px; + } + + .btn-primary svg { + font-size: 14px; + + circle { + fill: #F5D4BD; + } + + path { + stroke-width: 10; + } + } + } + + .card-sect-title { + padding-top: 10px; + } + + .badges-earned-total-card, .badges-total-card { + .badges-total-count { + font-size: 26px; + } + + .see-all { + font-size: 14px; + + .link-icon { + margin-left: -5px; + + svg path { + stroke: map-get($palette, primary); + } + } + } + } + } +} + +.badges .users-badges-homepage { + .user-badges-section .submenu-section { + .search-form { + position: relative; + margin-top: -5px; + + .search-input { + border-radius: 18px; + padding: .275rem .45rem; + height: initial; + + &::placeholder { + font-size: 14px; + } + } + + .search-icon { + position: absolute; + top: 7px; + right: 16px; + width: 18px; + height: 18px; + border-width: 1px; + + &:after { + left: 18px; + top: 10px; + width: 1px; + height: 10px; + } + } + } + } + + .badges-users-table { + border-collapse: separate; + border-spacing: 0 10px; + + thead td { + font-size: 16px; + font-weight: 500; + border: none; + } + + tbody { + tr { + margin-bottom: 10px; + box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.06); + border-radius: 5px; + background-color: map-get($palette, white); + } + + td { + font-size: 14px; + color: map-get($palette, gray30); + vertical-align: middle; + border: none; + } + + td.user-profile { + + .image-container { + max-width: 40px; + max-height: 40px; + + .user-profile-image { + width: 100%; + height: 100%; + border-radius: 50%; + } + } + + .details { + padding-left: 15px; + + .name { + font-size: 16px; + color: map-get($palette, darkCharchoal); + font-weight: 600; + } + + .location { + color: map-get($palette, luckyGrey); + font-size: 16px; + } + } + } + + td.points { + font-size: 16px; + font-weight: 500; + } + + td.badges-container { + .badges { + display: flex; + flex-direction: row; + align-content: center; + justify-content: flex-start; + align-items: center; + + .extra-badges-total { + font-size: 16px; + background-color: #3F484D5C; + width: 34px; + height: 34px; + color: #FFFFFF; + + display: flex; + border-radius: 100%; + justify-content: center; + align-content: center; + flex-direction: column; + align-items: center; + } + + .mini-badge-container { + width: 50px; + height: 65px; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-content: center; + justify-content: center; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.08); + border: 0.5px solid rgba(86, 16, 245, 0.11); + margin-right: 9px; + padding: 4px; + + .badge-icon { + width: 100%; + height: 100%; + } + } + } + } + + td { + .view-profile-btn { + font-size: 13px; + padding-bottom: 4px; + padding-top: 4px; + } + } + } + + } + + .footer-pagination { + margin-top: 40px; + + select { + padding-right: 11px; + padding-bottom: 4px; + padding-top: 4px; + } + + .pagination .page-link { + padding-top: 6px; + padding-bottom: 6px; + } + } +} diff --git a/frontend/app/styles/admin/admin.scss b/frontend/app/styles/admin/admin.scss index 5ae646d21..ccd5cf4cf 100644 --- a/frontend/app/styles/admin/admin.scss +++ b/frontend/app/styles/admin/admin.scss @@ -10,6 +10,7 @@ gray85: #FAFDFF height: 100%; width: 100%; background-color: map-get($palette,gray85); + overflow: auto; } } diff --git a/frontend/app/templates/admin/badges.hbs b/frontend/app/templates/admin/badges.hbs index e2535d225..03c2c2593 100644 --- a/frontend/app/templates/admin/badges.hbs +++ b/frontend/app/templates/admin/badges.hbs @@ -1,2 +1,3 @@ - -{{outlet}} \ No newline at end of file +
+ {{outlet}} +
\ No newline at end of file diff --git a/frontend/app/templates/admin/badges/users.hbs b/frontend/app/templates/admin/badges/users.hbs new file mode 100644 index 000000000..351162ade --- /dev/null +++ b/frontend/app/templates/admin/badges/users.hbs @@ -0,0 +1,184 @@ +
+
+

{{t "admin.users_and_badges.title"}}

+
+
+
+
+

+ {{t "admin.users_and_badges.labels.badge_create_prompt" name=this.me.name}} +

+ + {{svg-jar "plus-circle" height="21" width="21" stroke="white"}} + {{t "admin.users_and_badges.buttons.create"}} + +
+
+
+ +
+
+
+
+ {{svg-jar "target" height="50" width="50" stroke="white"}} +
+
{{t "admin.users_and_badges.labels.badges_total"}}
+
+ {{this.badges.length}} +
+ + {{t "admin.users_and_badges.buttons.view_all"}} + {{svg-jar "chevron-right" height="30"}} + +
+
+
+ +
+
+
+
+ {{svg-jar "badge" height="50" width="50" stroke="white"}} +
+
{{t "admin.users_and_badges.labels.badges_earned"}}
+
+ {{this.badgesUnlockedCount}} +
+ + {{t "admin.users_and_badges.buttons.view_all"}} + {{svg-jar "chevron-right" height="30"}} + +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{t "admin.users_and_badges.table.header.name"}}{{t "admin.users_and_badges.table.header.points"}}{{t "admin.users_and_badges.table.header.badges"}}{{t "admin.users_and_badges.table.header.view"}}
+ 2000 + +
+
+ +
+
+ +
+
+ +
+
+
+ + {{t "admin.users_and_badges.buttons.view_user"}} + +
+ 2000 + +
+
+ +
+
+ +
+
+ +
+
+ 2+ +
+
+
+ + {{t "admin.users_and_badges.buttons.view_user"}} + +
+ +
+
\ No newline at end of file diff --git a/frontend/public/images/icons/target.svg b/frontend/public/images/icons/target.svg new file mode 100644 index 000000000..48ff6b5ff --- /dev/null +++ b/frontend/public/images/icons/target.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/tests/unit/controllers/admin/badges/users-test.js b/frontend/tests/unit/controllers/admin/badges/users-test.js new file mode 100644 index 000000000..c17e443f8 --- /dev/null +++ b/frontend/tests/unit/controllers/admin/badges/users-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | admin/badges/users', function (hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function (assert) { + let controller = this.owner.lookup('controller:admin/badges/users'); + assert.ok(controller); + }); +}); diff --git a/frontend/tests/unit/models/badge-test.js b/frontend/tests/unit/models/badge-test.js new file mode 100644 index 000000000..0a90168b0 --- /dev/null +++ b/frontend/tests/unit/models/badge-test.js @@ -0,0 +1,13 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Model | badge', function (hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function (assert) { + let store = this.owner.lookup('service:store'); + let model = store.createRecord('badge', {}); + assert.ok(model); + }); +}); diff --git a/frontend/tests/unit/routes/admin/badges/users-test.js b/frontend/tests/unit/routes/admin/badges/users-test.js new file mode 100644 index 000000000..83d32327b --- /dev/null +++ b/frontend/tests/unit/routes/admin/badges/users-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | admin/badges/users', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:admin/badges/users'); + assert.ok(route); + }); +}); diff --git a/frontend/translations/admin/en-us.yaml b/frontend/translations/admin/en-us.yaml index 7fa357285..5916d98fd 100644 --- a/frontend/translations/admin/en-us.yaml +++ b/frontend/translations/admin/en-us.yaml @@ -6,3 +6,23 @@ sidenav: badges: Badges manage_badges: Manage Badges badge_users: Users & Badges + +users_and_badges: + title: All Users & Badges + buttons: + create: Create new badge + details: Details + view_all: See All + view_user: View profile + + labels: + badge_create_prompt: Hi {name},would you like to create a new badge today? + badges_total: Number of Badges + badges_earned: Badges Earned + search_placeholder: Search user + table: + header: + name: People + points: Points earned + badges: Badges earned + view: view diff --git a/frontend/translations/admin/sw-ke.yaml b/frontend/translations/admin/sw-ke.yaml index f21b95e74..5654205da 100644 --- a/frontend/translations/admin/sw-ke.yaml +++ b/frontend/translations/admin/sw-ke.yaml @@ -6,3 +6,23 @@ sidenav: badges: Beji manage_badges: Usimamizi wa Beji badge_users: Watumiaji na Beji + +users_and_badges: + title: Watumiaji wote na Beji + buttons: + create: Unda beji mpya + details: Maelezo + view_all: Ona yote + view_user: Angalia wasifu + + labels: + badge_create_prompt: Halo {name}, ungependa kuunda baji mpya leo? + badges_total: Idadi ya Beji + badges_earned: Beji Zilizopatikana + search_placeholder: Tafuta mtumiaji + table: + header: + name: Watu + points: Pointi zilizopatikana + badges: Beji zilizopatikana + view: Mtazamo diff --git a/frontend/translations/en-us.yaml b/frontend/translations/en-us.yaml index 6670dc0bb..0f83e36a7 100644 --- a/frontend/translations/en-us.yaml +++ b/frontend/translations/en-us.yaml @@ -99,3 +99,15 @@ main_navbar: notifications: title: Notifications empty: You have no new notifications + +table: + empty: No records to show + pagination: + per_page: Per Page + previous: Previous + next: Next + +badge_popup: + title: How to earn this badge + ok: OK, GOT IT + points: Points diff --git a/frontend/translations/sw-ke.yaml b/frontend/translations/sw-ke.yaml index 35594a560..f0d2e9e93 100644 --- a/frontend/translations/sw-ke.yaml +++ b/frontend/translations/sw-ke.yaml @@ -99,3 +99,15 @@ main_navbar: notifications: title: Arifa empty: Huna arifa mpya + +table: + empty: Hakuna rekodi za kuonyesha + pagination: + per_page: Idadi kwa Ukurasa + previous: Iliyotangulia + next: Ifuatayo + +badge_popup: + title: Jinsi ya kupata hii beji + ok: SAWA NIMEPATA! + points: Pointi From 70c2c86555176397b0c1fcad2a6570dd9ab71a8e Mon Sep 17 00:00:00 2001 From: mimidotuser Date: Fri, 21 May 2021 12:24:58 +0300 Subject: [PATCH 02/25] feat: leaderboard UI design --- frontend/app/router.js | 2 + frontend/app/routes/leaderboard.js | 4 + frontend/app/styles/_leaderboard.scss | 331 ++++++++++++++++++ frontend/app/styles/app.scss | 1 + frontend/app/templates/leaderboard.hbs | 261 ++++++++++++++ frontend/public/images/confetti-1.svg | 1 + frontend/public/images/confetti.svg | 1 + .../tests/unit/routes/leaderboard-test.js | 11 + frontend/translations/leaderboard/en-us.yaml | 13 + frontend/translations/leaderboard/sw-ke.yaml | 0 10 files changed, 625 insertions(+) create mode 100644 frontend/app/routes/leaderboard.js create mode 100644 frontend/app/styles/_leaderboard.scss create mode 100644 frontend/app/templates/leaderboard.hbs create mode 100644 frontend/public/images/confetti-1.svg create mode 100644 frontend/public/images/confetti.svg create mode 100644 frontend/tests/unit/routes/leaderboard-test.js create mode 100644 frontend/translations/leaderboard/en-us.yaml create mode 100644 frontend/translations/leaderboard/sw-ke.yaml diff --git a/frontend/app/router.js b/frontend/app/router.js index 57d6b628b..5a0cdf36f 100644 --- a/frontend/app/router.js +++ b/frontend/app/router.js @@ -43,6 +43,8 @@ Router.map(function () { this.route('reset_password'); this.route('verify'); + this.route('leaderboard'); + this.route('admin', function () { this.route('dashboard', { path: '/' }); this.route('users'); diff --git a/frontend/app/routes/leaderboard.js b/frontend/app/routes/leaderboard.js new file mode 100644 index 000000000..6c6028d2b --- /dev/null +++ b/frontend/app/routes/leaderboard.js @@ -0,0 +1,4 @@ +import Route from '@ember/routing/route'; + +export default class LeaderboardRoute extends Route { +} diff --git a/frontend/app/styles/_leaderboard.scss b/frontend/app/styles/_leaderboard.scss new file mode 100644 index 000000000..85a5c383d --- /dev/null +++ b/frontend/app/styles/_leaderboard.scss @@ -0,0 +1,331 @@ +$palette: ( + primary: #F57010, + white: #FFFF, + darkCharcoal: rgba(87, 92, 88, 1), + teach: #32A583, + eucalyptus: #28A745, +); +.leaderboard-wrapper { + position: relative; + + .bg-panel { + width: 100%; + height: 135px; + background-color: map-get($palette, primary); + opacity: 0.22; + position: absolute; + z-index: 1; + top: 0; + margin-top: -30px; + } + + .leaderboard-main-container { + position: relative; + z-index: 10; + background-color: map-get($palette, white); + margin-top: 30px; + padding: 20px; + } + + .leaderboard-main-container { + .title { + font-size: 19px; + font-weight: 700; + color: map-get($palette, darkCharcoal); + padding-left: 10px; + padding-bottom: 12px; + } + + .sub-title { + font-size: 19px; + font-weight: 500; + color: map-get($palette, darkCharcoal); + padding-left: 50px; + } + } + + .top-leaders { + padding-bottom: 25px; + + .leader-card { + + width: 422px; + height: 155px; + box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.29); + border-radius: 5px; + margin-left: 8px; + padding: 15px; + + + .image-container { + max-height: 52px; + max-width: 52px; + + img { + box-shadow: 0px 3px 6px rgb(0 0 0 / 7%); + border: 3px solid rgba(255, 255, 255, 1); + } + } + + .details { + padding-left: 8px; + + .name { + font-size: 19px; + color: map-get($palette, darkCharcoal); + font-weight: 500; + } + + .location { + font-size: 15px; + color: map-get($palette, darkCharcoal); + } + } + + .points { + color: map-get($palette, eucalyptus); + font-weight: 700; + font-size: 19px; + } + + .points-title { + font-size: 15px; + color: map-get($palette, darkCharcoal); + } + } + + .leader-card { + .badges-list { + display: flex; + position: relative; + + .badge-icon-container { + width: 30px; + height: 30px; + position: absolute; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-items: center; + justify-content: center; + border-radius: 50%; + background-color: white; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05); + border: 3px solid rgba(255, 255, 255, 1); + font-size: 11px; + font-weight: 700; + + .badge-icon { + width: 100%; + height: 100%; + } + + &:nth-child(2) { + margin-left: 20px; + } + + &:nth-child(3) { + margin-left: 40px; + } + + &:nth-child(4) { + margin-left: 60px; + } + } + } + } + + .leader-card.first-winner { + height: 180px; + background-repeat: no-repeat; + background-position: 0% 0%; + background-origin: padding-box; + background-image: linear-gradient(119deg, rgba(126, 87, 194, 1) 0%, rgba(171, 71, 188, 1) 100%); + background-color: transparent; + background-clip: padding-box; + + .image-container { + max-height: 62px; + max-width: 62px; + } + + .name, .location, .points, .points-title { + color: map-get($palette, white); + } + + .bottom { + padding-bottom: 10px; + padding-top: 10px; + } + + .view-profile-btn { + background-color: map-get($palette, white); + border-color: map-get($palette, white); + color: map-get($palette, darkCharcoal); + } + } + } + + .top-leaders { + .first-winner { + position: relative; + + .confetti-one { + position: absolute; + background-image: url("/images/confetti.svg"); + width: 70%; + height: 55px; + background-size: cover; + top: -40px; + left: -30px; + background-repeat: no-repeat; + z-index: -1; + } + + .confetti-two { + position: absolute; + background-image: url("/images/confetti-1.svg"); + width: 70%; + height: 55px; + background-size: cover; + top: -40px; + right: -60px; + background-repeat: no-repeat; + z-index: -1; + } + } + } + + .leaderboard-table { + border-collapse: separate; + border-spacing: 0 10px; + + thead td { + font-size: 16px; + font-weight: 500; + border: none; + color: map-get($palette, darkCharcoal); + + &:first-of-type { + padding-right: 0; + } + + &:nth-of-type(2) { + padding-left: 25px; + } + } + + tbody { + tr { + margin-bottom: 10px; + box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.06); + border-radius: 5px; + background-color: map-get($palette, white); + } + + td { + font-size: 14px; + color: map-get($palette, gray30); + vertical-align: middle; + border: none; + + &:first-of-type { + padding-right: 0; + width: 10px; + } + } + + td.position span { + height: 23px; + width: 23px; + background-color: lighten(map-get($palette, teach), 25%); + display: flex; + border-radius: 50%; + align-items: center; + justify-content: center; + } + + .details { + padding-left: 15px; + + .name { + font-size: 16px; + color: map-get($palette, darkCharcoal); + font-weight: 600; + } + + .location { + color: map-get($palette, luckyGrey); + font-size: 16px; + } + } + } + + td.points { + font-size: 16px; + font-weight: 500; + } + + td.badges-container { + .badges { + display: flex; + flex-direction: row; + align-content: center; + justify-content: flex-start; + align-items: center; + + .extra-badges-total { + font-size: 16px; + background-color: #3F484D5C; + width: 34px; + height: 34px; + color: #FFFFFF; + + display: flex; + border-radius: 100%; + justify-content: center; + align-content: center; + flex-direction: column; + align-items: center; + } + + .mini-badge-container { + width: 50px; + height: 65px; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-content: center; + justify-content: center; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.08); + border: 0.5px solid rgba(86, 16, 245, 0.11); + margin-right: 9px; + padding: 4px; + + .badge-icon { + width: 100%; + height: 100%; + } + } + } + } + + } + + .image-container { + max-width: 40px; + max-height: 40px; + + .user-profile-image { + width: 100%; + height: 100%; + border-radius: 50%; + } + } + + .view-profile-btn { + font-size: 13px; + padding-bottom: 4px; + padding-top: 4px; + } +} diff --git a/frontend/app/styles/app.scss b/frontend/app/styles/app.scss index c195c56c0..9fe2a1c3f 100644 --- a/frontend/app/styles/app.scss +++ b/frontend/app/styles/app.scss @@ -164,5 +164,6 @@ pre { @import "h5p-player"; @import "notifications-dropdown"; @import "user-acc-dropdown"; +@import "leaderboard"; @import "admin/admin"; diff --git a/frontend/app/templates/leaderboard.hbs b/frontend/app/templates/leaderboard.hbs new file mode 100644 index 000000000..7fe772d3a --- /dev/null +++ b/frontend/app/templates/leaderboard.hbs @@ -0,0 +1,261 @@ +
+ +
+
+
{{t "leaderboard.title"}}
+ +
+
+
+
+
+ +
+
+ Jane Doe + Nairobi +
+
+ +
+ 1,000 + {{t "leaderboard.earnedPoints"}} + +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +5 +
+
+ + + {{t "admin.users_and_badges.buttons.view_user"}} + +
+
+ +
+
+
+
+ +
+
+ Jane Doe + Nairobi +
+
+ +
+ 1,000 + {{t "leaderboard.earnedPoints"}} + +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +5 +
+
+ + + {{t "admin.users_and_badges.buttons.view_user"}} + +
+
+
+
+ + +
+
+
+
+ +
+
+ Charles Kiprop + Mombasa +
+
+ +
+ 9,000 + {{t "leaderboard.earnedPoints"}} + +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +4 +
+
+ + + {{t "admin.users_and_badges.buttons.view_user"}} + +
+
+ +
+
{{t "leaderboard.subtitle"}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{t "leaderboard.table.header.user"}}{{t "leaderboard.table.header.points"}}{{t "leaderboard.table.header.badges"}}{{t "leaderboard.table.header.action"}}
4 + 2000 + +
+
+ +
+
+ +
+
+ +
+
+
+ + {{t "admin.users_and_badges.buttons.view_user"}} + +
5 + 2000 + +
+
+ +
+
+ +
+
+ +
+
+ 2+ +
+
+
+ + {{t "admin.users_and_badges.buttons.view_user"}} + +
+ + + + +
+ + +
\ No newline at end of file diff --git a/frontend/public/images/confetti-1.svg b/frontend/public/images/confetti-1.svg new file mode 100644 index 000000000..a84d19ffa --- /dev/null +++ b/frontend/public/images/confetti-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/images/confetti.svg b/frontend/public/images/confetti.svg new file mode 100644 index 000000000..c260b136b --- /dev/null +++ b/frontend/public/images/confetti.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/tests/unit/routes/leaderboard-test.js b/frontend/tests/unit/routes/leaderboard-test.js new file mode 100644 index 000000000..eadf96be1 --- /dev/null +++ b/frontend/tests/unit/routes/leaderboard-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | leaderboard', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:leaderboard'); + assert.ok(route); + }); +}); diff --git a/frontend/translations/leaderboard/en-us.yaml b/frontend/translations/leaderboard/en-us.yaml new file mode 100644 index 000000000..cb0017c2d --- /dev/null +++ b/frontend/translations/leaderboard/en-us.yaml @@ -0,0 +1,13 @@ +title: Leaderboard +subtitle: Top gainers +earnedPoints: Points earned +table: + header: + user: People + points: Points earned + badges: Badges earned + action: view + +buttons: + view_profile: View profile + diff --git a/frontend/translations/leaderboard/sw-ke.yaml b/frontend/translations/leaderboard/sw-ke.yaml new file mode 100644 index 000000000..e69de29bb From 88735d66809e0a394d97fc8c1b20d6e493b3e93e Mon Sep 17 00:00:00 2001 From: mimidotuser Date: Fri, 21 May 2021 12:28:34 +0300 Subject: [PATCH 03/25] feat: leaderboard pagination base functions --- frontend/app/controllers/leaderboard.js | 74 +++++++++++++++++++ frontend/app/routes/leaderboard.js | 3 +- .../unit/controllers/leaderboard-test.js | 12 +++ .../tests/unit/routes/leaderboard-test.js | 4 +- 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 frontend/app/controllers/leaderboard.js create mode 100644 frontend/tests/unit/controllers/leaderboard-test.js diff --git a/frontend/app/controllers/leaderboard.js b/frontend/app/controllers/leaderboard.js new file mode 100644 index 000000000..41cd6f40a --- /dev/null +++ b/frontend/app/controllers/leaderboard.js @@ -0,0 +1,74 @@ +import Controller from '@ember/controller'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; + +export default class LeaderboardController extends Controller { + @tracked showPerPage = 20; + @tracked currentPage = 1; + + perPageOptions = [ + { value: 20, selected: true }, + { value: 50, selected: false }, + { value: 100, selected: false }, + ]; + + @action + updatePerPage(evt) { + this.currentPage = 1; // It's easier than doing calculations. + this.showPerPage = +evt.target.selectedOptions[0].value; + } + + get pageNumericSummary() { + const recordsCount = this.model.length; + + let firstIndex = 1; + if (this.currentPage > 1) { + firstIndex = this.showPerPage * this.currentPage - (this.showPerPage - 1); + } + + let lastIndex = this.showPerPage * this.currentPage; + if (lastIndex > recordsCount) { + lastIndex = recordsCount; + } + + return { firstIndex, lastIndex, recordsCount }; + } + + get paginationSummary() { + const { + recordsCount, + firstIndex: pageFirstIndex, + lastIndex: pageLastIndex, + } = this.pageNumericSummary; + + if (recordsCount <= this.showPerPage) { + return `Showing All Users`; + } + + return `Showing ${pageFirstIndex} - ${pageLastIndex} of ${recordsCount}`; + } + + @action + goToPrevPage() { + if (this.hasPreviousPage) { + this.currentPage = --this.currentPage; + } + } + + @action + goToNextPage() { + if (this.hasNextPage) { + this.currentPage = ++this.currentPage; + } + } + + get hasNextPage() { + const { recordsCount, lastIndex } = this.pageNumericSummary; + return lastIndex !== recordsCount; + } + + get hasPreviousPage() { + const { recordsCount } = this.pageNumericSummary; + return this.currentPage > 1 && recordsCount > this.showPerPage; + } +} diff --git a/frontend/app/routes/leaderboard.js b/frontend/app/routes/leaderboard.js index 6c6028d2b..67a5bf020 100644 --- a/frontend/app/routes/leaderboard.js +++ b/frontend/app/routes/leaderboard.js @@ -1,4 +1,3 @@ import Route from '@ember/routing/route'; -export default class LeaderboardRoute extends Route { -} +export default class LeaderboardRoute extends Route {} diff --git a/frontend/tests/unit/controllers/leaderboard-test.js b/frontend/tests/unit/controllers/leaderboard-test.js new file mode 100644 index 000000000..11b40c308 --- /dev/null +++ b/frontend/tests/unit/controllers/leaderboard-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | leaderboard', function (hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function (assert) { + let controller = this.owner.lookup('controller:leaderboard'); + assert.ok(controller); + }); +}); diff --git a/frontend/tests/unit/routes/leaderboard-test.js b/frontend/tests/unit/routes/leaderboard-test.js index eadf96be1..56203f6eb 100644 --- a/frontend/tests/unit/routes/leaderboard-test.js +++ b/frontend/tests/unit/routes/leaderboard-test.js @@ -1,10 +1,10 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -module('Unit | Route | leaderboard', function(hooks) { +module('Unit | Route | leaderboard', function (hooks) { setupTest(hooks); - test('it exists', function(assert) { + test('it exists', function (assert) { let route = this.owner.lookup('route:leaderboard'); assert.ok(route); }); From 1223314b7f995b4535314d69129dd8095136e3df Mon Sep 17 00:00:00 2001 From: mimidotuser Date: Fri, 21 May 2021 12:32:35 +0300 Subject: [PATCH 04/25] fix: valid alt text required lint errors --- frontend/app/templates/admin/badges/users.hbs | 10 +++++----- frontend/app/templates/leaderboard.hbs | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/app/templates/admin/badges/users.hbs b/frontend/app/templates/admin/badges/users.hbs index 351162ade..0f0e27cfa 100644 --- a/frontend/app/templates/admin/badges/users.hbs +++ b/frontend/app/templates/admin/badges/users.hbs @@ -84,7 +84,7 @@
- +
Jane Doe @@ -119,7 +119,7 @@
- +
Marete Buda @@ -133,13 +133,13 @@
- +
- +
- +
2+ diff --git a/frontend/app/templates/leaderboard.hbs b/frontend/app/templates/leaderboard.hbs index 7fe772d3a..c7050dc13 100644 --- a/frontend/app/templates/leaderboard.hbs +++ b/frontend/app/templates/leaderboard.hbs @@ -9,7 +9,7 @@
- +
Jane Doe @@ -51,7 +51,7 @@
- +
Jane Doe @@ -96,7 +96,7 @@
- +
Charles Kiprop @@ -155,7 +155,7 @@
- +
Jane Doe @@ -191,7 +191,7 @@
- +
Marete Buda @@ -205,13 +205,13 @@
- +
- +
- +
2+ From 0a4be59fb6b02df64efa6ed0b9d0a18682afccaa Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 20:44:59 +0300 Subject: [PATCH 05/25] fix: user-survey model relation points 2 wrong column --- server/models/user-survey.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/server/models/user-survey.js b/server/models/user-survey.js index 25dc0c0f7..2774ca3c3 100644 --- a/server/models/user-survey.js +++ b/server/models/user-survey.js @@ -6,6 +6,17 @@ class UserSurvey extends Model { return 'user_surveys'; } + static get jsonSchema() { + return { + type: 'object', + required: ['survey_id', 'user_id'], + properties: { + survey_id: {type: 'string'}, + user_id: {type: 'string'}, + }, + }; + } + static get relationMappings() { return { survey: { @@ -20,7 +31,7 @@ class UserSurvey extends Model { relation: Model.BelongsToOneRelation, modelClass: `${__dirname}/users`, join: { - from: 'user_surveys.creator_id', + from: 'user_surveys.user_id', to: 'users.id' } }, From 33426d9e577a6f378c8c384cdb3a88b90904747a Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 21:04:42 +0300 Subject: [PATCH 06/25] chore: number badge seeder file --- server/db/seeds/dev/{badges.js => 21_badges.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename server/db/seeds/dev/{badges.js => 21_badges.js} (100%) diff --git a/server/db/seeds/dev/badges.js b/server/db/seeds/dev/21_badges.js similarity index 100% rename from server/db/seeds/dev/badges.js rename to server/db/seeds/dev/21_badges.js From da892c19f3e1dab52aed8d8987493f8b5d3f5c8f Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 21:13:05 +0300 Subject: [PATCH 07/25] feat: add user badges migration, seed, & model --- .../20210918171859_user_badges_table.js | 19 ++++++++ server/db/seeds/dev/22_user_badges.js | 30 +++++++++++++ server/models/user-badge.js | 44 +++++++++++++++++++ server/models/user-survey.js | 6 +-- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 server/db/migrations/20210918171859_user_badges_table.js create mode 100644 server/db/seeds/dev/22_user_badges.js create mode 100644 server/models/user-badge.js diff --git a/server/db/migrations/20210918171859_user_badges_table.js b/server/db/migrations/20210918171859_user_badges_table.js new file mode 100644 index 000000000..ffea9d2f5 --- /dev/null +++ b/server/db/migrations/20210918171859_user_badges_table.js @@ -0,0 +1,19 @@ +const { idGenerator } = require('../id_generator'); + +exports.up = (knex) => { + return knex.schema + .raw(idGenerator) + .createTable('user_badges', table => { + table.text('id').primary().notNullable().defaultTo(knex.raw('next_id()')); + table.text('badge_id').references('badges.id').onDelete('CASCADE'); + table.text('user_id').references('users.id').onDelete('CASCADE'); + table.timestamps(); // date created == date awarded + }); + + +}; + +exports.down = (knex) => { + return knex.schema + .dropTableIfExists('user_badges'); +}; diff --git a/server/db/seeds/dev/22_user_badges.js b/server/db/seeds/dev/22_user_badges.js new file mode 100644 index 000000000..c663768a4 --- /dev/null +++ b/server/db/seeds/dev/22_user_badges.js @@ -0,0 +1,30 @@ +const { faker, seed_number } = require('../_seeds'); +const BadgeModel = require('../../../models/badges'); +const UserBadgeModel = require('../../../models/user-badge'); +const UserModel = require('../../../models/user'); + +exports.seed = async (knex) => { + // Deletes ALL existing entries + await knex(UserBadgeModel.tableName).del(); + + const userIds = await knex(UserModel.tableName).pluck('id'); + const badgesIds = await knex(BadgeModel.tableName).pluck('id'); + + const userAwardedBadges = []; + + for (let index = 0; index < seed_number; index++) { + const dateUnlocked = faker.date.past(); + + userAwardedBadges.push({ + badge_id: faker.random.arrayElement(badgesIds), + user_id: faker.random.arrayElement(userIds), + created_at: dateUnlocked, + updated_at: faker.datatype.boolean() ? dateUnlocked : faker.date.recent(), + }); + } + + // Inserts seed entries + return knex(UserBadgeModel.tableName).insert(userAwardedBadges); +}; + + diff --git a/server/models/user-badge.js b/server/models/user-badge.js new file mode 100644 index 000000000..422e7c4ef --- /dev/null +++ b/server/models/user-badge.js @@ -0,0 +1,44 @@ +const Model = require('./_model'); +const knex = require('../db/db'); + +class UserBadge extends Model { + static get tableName() { + return 'user_badges'; + } + + + static get jsonSchema() { + return { + type: 'object', + required: ['badgeId', 'userId'], + properties: { + badgeId: {type: 'string'}, + userId: {type: 'string'}, + }, + }; + } + + static get relationMappings() { + return { + badge: { + relation: Model.BelongsToOneRelation, + modelClass: `${__dirname}/badges`, + join: { + from: 'user_badges.badge_id', + to: 'badges.id' + } + }, + user: { + relation: Model.BelongsToOneRelation, + modelClass: `${__dirname}/users`, + join: { + from: 'user_badges.user_id', + to: 'users.id' + } + }, + }; + } +} + +UserBadge.knex(knex); +module.exports = UserBadge; diff --git a/server/models/user-survey.js b/server/models/user-survey.js index 2774ca3c3..5c11bae51 100644 --- a/server/models/user-survey.js +++ b/server/models/user-survey.js @@ -9,10 +9,10 @@ class UserSurvey extends Model { static get jsonSchema() { return { type: 'object', - required: ['survey_id', 'user_id'], + required: ['surveyId', 'userId'], properties: { - survey_id: {type: 'string'}, - user_id: {type: 'string'}, + surveyId: {type: 'string'}, + userId: {type: 'string'}, }, }; } From e35c8c65d2f2777e9ed2432db1d53cfe09c3ac20 Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 23:35:56 +0300 Subject: [PATCH 08/25] feat: define relationship between badge and user badges --- server/models/badges.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/server/models/badges.js b/server/models/badges.js index 7c872d43c..52ef08b91 100644 --- a/server/models/badges.js +++ b/server/models/badges.js @@ -32,10 +32,18 @@ class Badge extends softDelete({ columnName: 'is_deleted' })(Model) { relation: Model.BelongsToOneRelation, modelClass: `${__dirname}/badge_triggers`, join: { - from: 'badges.trigger', - to: 'badge_triggers.id' + from: 'badge_triggers.id', + to: 'badges.trigger_id' } - } + }, + badge_awardees: { + relation: Model.HasManyRelation, + modelClass: `${__dirname}/user-badge`, + join: { + from: 'badges.id', + to: 'user_badges.badge_id' + } + }, }; } } From 41e53326da483213fac5be0f7c5ede51b48c870b Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 23:37:07 +0300 Subject: [PATCH 09/25] feat: add events listeners for triggers to award badge to users --- server/event-handlers/badge-awarding.js | 358 ++++++++++++++++++++++++ server/index.js | 1 + 2 files changed, 359 insertions(+) create mode 100644 server/event-handlers/badge-awarding.js diff --git a/server/event-handlers/badge-awarding.js b/server/event-handlers/badge-awarding.js new file mode 100644 index 000000000..a2ba40d0c --- /dev/null +++ b/server/event-handlers/badge-awarding.js @@ -0,0 +1,358 @@ +const { raw } = require('objection'); + +const NotificationModel = require('../models/notification'); +const BadgeModel = require('../models/badges'); +const UserBadgeModel = require('../models/user-badge'); +const { notificationTypes } = require('../utils/notification-constants'); +const { events } = require('../utils/storage-hooks-events'); +const { SHooksEventEmitter } = require('../utils/event-emitter'); + +module.exports = () => { + + const triggers = { + learner: { + chapter: { + approved: 'chapter_approved', + published: 'chapter_publish', + completed: 'chapter_completed', + attempted: 'chapter_attempted', + }, + comment: { + create: 'comment_create', + reply: 'comment_reply', + }, + reaction: { + create: 'reaction_create', + }, + rating: { + create: 'rating_create' + } + } + }; + + /** + * On Chapter Approved + */ + SHooksEventEmitter.on(events.user.chapter.countOnApproved, async (payload) => { + /** 1) query all badges that user might have unlocked * */ + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) // paying attention to published badges only + .where('expiry', '>=', raw('now()')) // only query non expired badges (ignores time region difference challenge_) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.chapter.approved) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + + /** 2) for all badges the user have unlocked **/ + for (let i = 0; i < badges.length; i++) { + + /** 3) Create a notification for the chapter author **/ + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + + /** 4) Add activity record (badge that user has unlocked) **/ + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + + /** + * On chapter published + */ + SHooksEventEmitter.on(events.user.chapter.countOnPublished, async (payload) => { + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) // paying attention to published badges only + .where('is_deleted', false) // badges deleted through the api are partially deleted + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.chapter.published) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + /** + * On Comment create + */ + + SHooksEventEmitter.on(events.user.comment.countOnCreate, async (payload) => { + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.comment.create) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + + }); + + /** + * On Reply create + */ + SHooksEventEmitter.on(events.user.reply.countOnCreate, async (payload) => { + + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.comment.reply) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + + /** + * On reaction created + */ + SHooksEventEmitter.on(events.user.reaction.countOnCreate, async (payload) => { + + const badges = await BadgeModel.query() + .where('frequency', payload.totalReactions) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.reaction.create) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + }); + + /** + * On ratings created + */ + SHooksEventEmitter.on(events.user.rating.countOnCreate, async (payload) => { + const badges = await BadgeModel.query() + .where('frequency', payload.totalRatings) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.rating.create) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + + + /** + * On chapter attempted + */ + SHooksEventEmitter.on(events.user.chapter.countOnInteractionAttempt, async (payload) => { + + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.chapter.attempted) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + metadata: { sendEmail: false }, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + + /** + * On chapter completed + */ + SHooksEventEmitter.on(events.user.chapter.countOnInteractionComplete, async (payload) => { + + const badges = await BadgeModel.query() + .where('frequency', payload.total) + .where('published', true) + .where('is_deleted', false) + .where('expiry', '>=', raw('now()')) + .withGraphJoined('badge_triggers') + .where('badge_triggers.name', triggers.learner.chapter.completed) + .withGraphJoined('badge_awardees') + .where((builder) => { + builder.where('badge_awardees.userId', '<>', payload.creatorId) + .orWhereNull('badge_awardees.userId'); + }); + + for (let i = 0; i < badges.length; i++) { + //add a notification + await NotificationModel.query() + .insert({ + title: 'You have unlocked a new badge', + body: badges[i].name, + itemId: badges[i].id, + eventType: notificationTypes.badge.unlocked, + model: 'badge', + recipientId: payload.creatorId, + read: false, + metadata: { sendEmail: false }, + }); + + await UserBadgeModel.query() + .insert({ + badgeId: badges[i].id, + userId: payload.creatorId + }); + } + + }); + + +}; \ No newline at end of file diff --git a/server/index.js b/server/index.js index 610cd8d57..06241cf12 100644 --- a/server/index.js +++ b/server/index.js @@ -36,6 +36,7 @@ const io = socketIO(server); require('./event-handlers/socket-events')(io); require('./event-handlers/mne-surveys')(); +require('./event-handlers/badge-awarding')(); From 2bcd3f581ee27f492a0ecc5cad62cc939f29cea1 Mon Sep 17 00:00:00 2001 From: murage Date: Sat, 18 Sep 2021 23:37:25 +0300 Subject: [PATCH 10/25] feat: add badge awarding tests --- server/test/badge-awarding.js | 215 ++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 server/test/badge-awarding.js diff --git a/server/test/badge-awarding.js b/server/test/badge-awarding.js new file mode 100644 index 000000000..080732bab --- /dev/null +++ b/server/test/badge-awarding.js @@ -0,0 +1,215 @@ +const chai = require('chai'); +const chaiHttp = require('chai-http'); +const chaiJSON = require('chai-json-schema'); + +const knex = require('../db/db'); +const triggerModel = require('../models/triggers'); +const userModel = require('../models/user'); +const badgeModel = require('../models/badges'); +const chapterModel = require('../models/chapter'); +const commentModel = require('../models/comment'); +const reactionModel = require('../models/reaction'); +const ratingModel = require('../models/rating'); +const { socketEventEmitter } = require('../utils/event-emitter'); +const { events } = require('../utils/socket-events'); +const { notificationTypes } = require('../utils/notification-constants'); + + +chai.use(chaiHttp); +chai.use(chaiJSON); +chai.should(); + + +describe('User badges awarding', () => { + + before(async () => { + + await knex.migrate.rollback(); //reset tables + await knex.migrate.latest(); // rerun the migrations + //seed users only + await knex.seed.run({ + specific: '01_users.js' + }); + const triggers = await knex(triggerModel.tableName).select('id'); + const userIds = await knex(userModel.tableName).select('id'); + + // seed badges with static data + const badges = []; + for (let i = 0; i < triggers.length; i++) { + badges.push({ + name: `Test Badge ${i}`, + slug: `test-badge-${i}`, + published: true, + expiry: new Date(new Date().setFullYear(new Date().getFullYear() + 1)), + frequency: 1, // we will test with one X + trigger_id: triggers[i].id, + creator_id: userIds[0].id, + description: 'Test description', + is_deleted: false, + reminder: 10, + reminder_message: 'This is a sample reminder message', + }); + } + await knex(badgeModel.tableName).insert(badges); + }); + + + async function createChapter() { + await knex(chapterModel.tableName).delete(); + const userIds = await knex(userModel.tableName).select('id'); + + const chapter = { + name: 'This is a test chapter', + description: 'test', + approved: false, + status: 'draft', + creatorId: userIds[0].id + }; + return await chapterModel.query().insertAndFetch(chapter); + } + + it('Should unlock a badge on publishing a chapter', async () => { + + const chapter = await createChapter(); + + await chapterModel.query() + .patchAndFetchById(chapter.id, { + status: 'published' + }); + + return new Promise(((resolve, reject) => { + socketEventEmitter.on(events.user.notification.created, (model) => { + if (model.eventType === notificationTypes.badge.unlocked) { + resolve(true); + } else { + reject('Invalid notification type'); + } + }); + })); + + }); + + it('Should unlock a badge on chapter approval', async () => { + + const chapter = await createChapter(); + + await chapterModel.query() + .patchAndFetchById(chapter.id, { + approved: true, + status: 'published' + }); + + return new Promise(((resolve, reject) => { + socketEventEmitter.on(events.user.notification.created, (model) => { + if (model.eventType === notificationTypes.badge.unlocked) { + resolve(true); + } else { + reject('Invalid notification type'); + } + }); + })); + + }); + + it('Should unlock a badge on chapter comment creation', async () => { + + const chapter = await createChapter(); + const userIds = await knex(userModel.tableName).select('id'); + + await commentModel.query() + .insert({ + chapterId: chapter.id, + comment: 'Test comment', + creatorId: userIds[0].id, + }); + + return new Promise(((resolve, reject) => { + socketEventEmitter.on(events.user.notification.created, (model) => { + if (model.eventType === notificationTypes.badge.unlocked) { + resolve(true); + } else { + reject('Invalid notification type'); + } + }); + })); + + }); + + it('Should unlock a badge on comment reply creation', async () => { + + const chapter = await createChapter(); + const userIds = await knex(userModel.tableName).select('id'); + const commentIds = await knex(commentModel.tableName).select('id') + .where('parent_id', 'false'); + + await commentModel.query() + .insert({ + chapterId: chapter.id, + comment: 'Test reply', + parentId: commentIds[0] ? commentIds[0].id : 'follow', + creatorId: userIds[0].id, + }); + + return new Promise(((resolve, reject) => { + socketEventEmitter.on(events.user.notification.created, (model) => { + if (model.eventType === notificationTypes.badge.unlocked) { + resolve(true); + } else { + reject('Invalid notification type'); + } + }); + })); + + }); + + it('Should unlock a badge on chapter reaction creation', async () => { + + const chapter = await createChapter(); + const userIds = await knex(userModel.tableName).select('id'); + + await reactionModel.query() + .insert({ + chapterId: chapter.id, + reaction: 'like', + userId: userIds[0].id, + }); + + return new Promise(((resolve, reject) => { + socketEventEmitter.on(events.user.notification.created, (model) => { + if (model.eventType === notificationTypes.badge.unlocked) { + resolve(true); + } else { + reject('Invalid notification type'); + } + }); + })); + + }); + + it('Should unlock a badge on chapter rating creation', async () => { + + const chapter = await createChapter(); + const userIds = await knex(userModel.tableName).select('id'); + + await ratingModel.query() + .insert({ + chapterId: chapter.id, + userId: userIds[0].id, + averageRating: 10, + reaction: 'like', + isDeleted: false, + }); + + return new Promise((resolve => { + socketEventEmitter.on(events.user.notification.created, () => { + resolve(false); + }); + })); + + }); + + after(async () => { + await knex.migrate.latest(); + return await knex.seed.run(); + }); +}); \ No newline at end of file From 6f39793f0b9c14ac8272eb0b83f63510d2acef1b Mon Sep 17 00:00:00 2001 From: murage Date: Sun, 19 Sep 2021 00:11:40 +0300 Subject: [PATCH 11/25] feat(frontend): add logic to resolve badge unlocked notification --- frontend/app/models/notification.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frontend/app/models/notification.js b/frontend/app/models/notification.js index 1609046da..286b1e18f 100644 --- a/frontend/app/models/notification.js +++ b/frontend/app/models/notification.js @@ -32,12 +32,15 @@ export default class NotificationModel extends Model { * Resolve dynamic properties based on the model or/and event type */ get resolveDynamicProps() { + // survey unlocked notification if (this.model === 'survey') { return { url: this.router.urlFor('surveys', this.itemId), svgIcon: 'form', }; } + + // comment created notification if (this.model === 'comment' && notificationTypes.comment.created) { return { url: this.router.urlFor('chapter.index', this.itemId), @@ -45,6 +48,17 @@ export default class NotificationModel extends Model { }; } + // badge unlocked notification + if (this.model === 'badge' && notificationTypes.badge.unlocked) { + return { + url: this.router.urlFor( + 'profile.achievements', + this.recipient.get('id') + ), + iconUrl: '/images/badges-earned.png', + }; + } + return { url: undefined, svgIcon: '', iconUrl: '' }; } } From dba4e83bf408f4ad132719c9d2dcd5669811ffbb Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Thu, 23 Sep 2021 16:46:59 +0300 Subject: [PATCH 12/25] add linter for css --- frontend/.stylelintrc | 30 ++ frontend/package.json | 5 + frontend/yarn.lock | 1008 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 1022 insertions(+), 21 deletions(-) create mode 100644 frontend/.stylelintrc diff --git a/frontend/.stylelintrc b/frontend/.stylelintrc new file mode 100644 index 000000000..1903148c6 --- /dev/null +++ b/frontend/.stylelintrc @@ -0,0 +1,30 @@ +{ + "extends": [ + "stylelint-prettier/recommended" + ], + "plugins": [ + "stylelint-prettier" + ], + "rules": { + "prettier/prettier": [ + true, + { + "printWidth": 120 + } + ], + "declaration-no-important": [ + true, + { + "severity": "warning" + } + ], + "property-disallowed-list": [ + [ + "font" + ], + { + "message": "Use seperate font-* attributes" + } + ] + } +} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index d5be5d27c..4771125e3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,6 +18,7 @@ "lint:hbs:fix": "ember-template-lint . --fix", "lint:js": "eslint . --cache", "lint:js:fix": "eslint . --fix", + "lint:styles": "stylelint **/*.scss --quiet", "start": "ember serve --proxy http://localhost:3000", "docker:start": "ember serve --proxy http://backend:3000", "ci:start": "ember serve --path dist --proxy http://localhost:3000", @@ -51,6 +52,7 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-meta-tags": "^6.1.2", "ember-cli-sass": "^10.0.1", + "ember-cli-stylelint": "^4.0.0", "ember-cli-terser": "^4.0.1", "ember-config-service": "^1.0.0", "ember-data": "~3.24.0", @@ -91,6 +93,9 @@ "rsvp": "^4.8.5", "sass": "^1.23.0", "socket.io-client": "^4.0.1", + "stylelint": "^13.13.1", + "stylelint-config-prettier": "^8.0.2", + "stylelint-prettier": "^1.2.0", "title-case": "^3.0.3" }, "engines": { diff --git a/frontend/yarn.lock b/frontend/yarn.lock index aaf61eba1..1ef6308ae 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -21,6 +21,32 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08" integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw== +"@babel/compat-data@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" + integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== + +"@babel/core@>=7.9.0": + version "7.15.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9" + integrity sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.4" + "@babel/helper-compilation-targets" "^7.15.4" + "@babel/helper-module-transforms" "^7.15.4" + "@babel/helpers" "^7.15.4" + "@babel/parser" "^7.15.5" + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/core@^7.1.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.3.4", "@babel/core@^7.8.4", "@babel/core@^7.9.0": version "7.14.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.6.tgz#e0814ec1a950032ff16c13a2721de39a8416fcab" @@ -51,6 +77,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0" + integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw== + dependencies: + "@babel/types" "^7.15.4" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" @@ -76,6 +111,16 @@ browserslist "^4.16.6" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" + integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.14.6", "@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.8.3": version "7.14.6" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz#f114469b6c06f8b5c59c6c4e74621f5085362542" @@ -126,6 +171,15 @@ "@babel/template" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helper-function-name@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" + integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== + dependencies: + "@babel/helper-get-function-arity" "^7.15.4" + "@babel/template" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-get-function-arity@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" @@ -133,6 +187,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-get-function-arity@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" + integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-hoist-variables@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" @@ -140,6 +201,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-hoist-variables@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" + integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-member-expression-to-functions@^7.14.5": version "7.14.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz#97e56244beb94211fe277bd818e3a329c66f7970" @@ -147,6 +215,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-member-expression-to-functions@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" + integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3" @@ -154,6 +229,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-module-imports@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" + integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-module-transforms@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz#7de42f10d789b423eb902ebd24031ca77cb1e10e" @@ -168,6 +250,20 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helper-module-transforms@^7.15.4": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226" + integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw== + dependencies: + "@babel/helper-module-imports" "^7.15.4" + "@babel/helper-replace-supers" "^7.15.4" + "@babel/helper-simple-access" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-validator-identifier" "^7.15.7" + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.6" + "@babel/helper-optimise-call-expression@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" @@ -175,6 +271,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-optimise-call-expression@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" + integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" @@ -199,6 +302,16 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helper-replace-supers@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" + integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.15.4" + "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-simple-access@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz#66ea85cf53ba0b4e588ba77fc813f53abcaa41c4" @@ -206,6 +319,13 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-simple-access@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" + integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-skip-transparent-expression-wrappers@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz#96f486ac050ca9f44b009fbe5b7d394cab3a0ee4" @@ -220,11 +340,23 @@ dependencies: "@babel/types" "^7.14.5" +"@babel/helper-split-export-declaration@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" + integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-validator-identifier@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== +"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -249,6 +381,15 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/helpers@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" + integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== + dependencies: + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" @@ -263,6 +404,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595" integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA== +"@babel/parser@^7.15.4", "@babel/parser@^7.15.5": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" + integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e" @@ -944,6 +1090,15 @@ "@babel/parser" "^7.14.5" "@babel/types" "^7.14.5" +"@babel/template@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" + integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/traverse@^7.1.6", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": version "7.14.7" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753" @@ -959,6 +1114,21 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" + integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.4" + "@babel/helper-function-name" "^7.15.4" + "@babel/helper-hoist-variables" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.1.6", "@babel/types@^7.12.1", "@babel/types@^7.14.5", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff" @@ -967,6 +1137,14 @@ "@babel/helper-validator-identifier" "^7.14.5" to-fast-properties "^2.0.0" +"@babel/types@^7.15.4", "@babel/types@^7.15.6": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" + integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== + dependencies: + "@babel/helper-validator-identifier" "^7.14.9" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -1569,6 +1747,21 @@ resolved "https://registry.yarnpkg.com/@simple-dom/interface/-/interface-1.4.0.tgz#e8feea579232017f89b0138e2726facda6fbb71f" integrity sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA== +"@stylelint/postcss-css-in-js@^0.37.2": + version "0.37.2" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz#7e5a84ad181f4234a2480803422a47b8749af3d2" + integrity sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA== + dependencies: + "@babel/core" ">=7.9.0" + +"@stylelint/postcss-markdown@^0.36.2": + version "0.36.2" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz#0a540c4692f8dcdfc13c8e352c17e7bfee2bb391" + integrity sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ== + dependencies: + remark "^13.0.0" + unist-util-find-all-after "^3.0.2" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -1840,6 +2033,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -1850,6 +2050,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/minimist@^1.2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + "@types/node@*", "@types/node@>=10.0.0": version "16.3.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.3.2.tgz#655432817f83b51ac869c2d51dd8305fb8342e16" @@ -1860,6 +2065,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.61.tgz#29f124eddd41c4c74281bd0b455d689109fc2a2d" integrity sha512-/aKAdg5c8n468cYLy2eQrcR5k6chlbNwZNGUj3TboyPa2hcO2QAJcfymlqPzMiRj8B6nYKXjzQz36minFE0RwQ== +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "@types/q@^1.5.1": version "1.5.5" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" @@ -1906,6 +2121,11 @@ resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a" integrity sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg== +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -2280,6 +2500,13 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +aot-test-generators@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/aot-test-generators/-/aot-test-generators-0.1.0.tgz#43f0f615f97cb298d7919c1b0b4e6b7310b03cd0" + integrity sha1-Q/D2Ffl8spjXkZwbC05rcxCwPNA= + dependencies: + jsesc "^2.5.0" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -2352,6 +2579,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -2478,6 +2710,19 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +autoprefixer@^9.8.6: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== + dependencies: + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" + await-lock@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.1.0.tgz#bc78c51d229a34d5d90965a1c94770e772c6145e" @@ -3177,11 +3422,21 @@ backo2@~1.0.2: resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +balanced-match@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" + integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== + base-64@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" @@ -3665,7 +3920,7 @@ broccoli-merge-trees@^2.0.0: broccoli-plugin "^1.3.0" merge-trees "^2.0.0" -broccoli-merge-trees@^4.2.0: +broccoli-merge-trees@^4.1.0, broccoli-merge-trees@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-4.2.0.tgz#692d3c163ecea08c5714a9434d664e628919f47c" integrity sha512-nTrQe5AQtCrW4enLRvbD/vTLHqyW2tz+vsLXQe4IEaUhepuMGVKJJr+I8n34Vu6fPjmPLwTjzNC8izMIDMtHPw== @@ -3698,6 +3953,11 @@ broccoli-node-info@^2.1.0: resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz#feb01c13020792f429e01d7f7845dc5b3a7932b3" integrity sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg== +broccoli-node-info@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-2.1.0.tgz#ca84560e8570ff78565bea1699866ddbf58ad644" + integrity sha512-l6qDuboJThHfRVVWQVaTs++bFdrFTP0gJXgsWenczc1PavRVUmL1Eyb2swTAXXMpDOnr2zhNOBLx4w9AxkqbPQ== + broccoli-output-wrapper@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/broccoli-output-wrapper/-/broccoli-output-wrapper-2.0.0.tgz#f1e0b9b2f259a67fd41a380141c3c20b096828e6" @@ -3951,6 +4211,21 @@ broccoli-string-replace@^0.1.2: broccoli-persistent-filter "^1.1.5" minimatch "^3.0.3" +broccoli-stylelint@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/broccoli-stylelint/-/broccoli-stylelint-4.0.0.tgz#2890dead7ac608a07937225bf71d0a1a4d1f48c7" + integrity sha512-m1IM4yjfZoP5SlfoDMDUQijur8e2a1xNmtAi6S4lZc27cVeBRP7bDpjK7S3FfXl6CslbxFb2ba4T0tL+y66jjw== + dependencies: + aot-test-generators "^0.1.0" + broccoli-concat "^3.2.2" + broccoli-node-info "~2.1.0" + broccoli-persistent-filter "^2.1.1" + chalk "~3.0.0" + ignore "^5.0.2" + js-string-escape "~1.0.1" + lodash.defaultsdeep "^4.6.0" + stylelint "^13.2.1" + broccoli-svg-optimizer@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/broccoli-svg-optimizer/-/broccoli-svg-optimizer-2.0.0.tgz#22b6920bee5e126e86b95ae0cdf8ad6cc4be3735" @@ -4109,6 +4384,17 @@ browserslist@^4.0.0, browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.71" +browserslist@^4.12.0: + version "4.17.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" + integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== + dependencies: + caniuse-lite "^1.0.30001259" + electron-to-chromium "^1.3.846" + escalade "^3.1.1" + nanocolors "^0.1.5" + node-releases "^1.1.76" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -4229,6 +4515,20 @@ callsites@^3.0.0, callsites@^3.1.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + can-symlink@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/can-symlink/-/can-symlink-1.0.0.tgz#97b607d8a84bb6c6e228b902d864ecb594b9d219" @@ -4251,6 +4551,13 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001219: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001245.tgz#45b941bbd833cb0fa53861ff2bae746b3c6ca5d4" integrity sha512-768fM9j1PKXpOCKws6eTo3RHmvTUsG9UrpT4WoREFeZgJBTi4/X9g565azS/rVUGtqb8nt7FjLeF5u4kukERnA== +caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001259: + version "1.0.30001260" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001260.tgz#e3be3f34ddad735ca4a2736fa9e768ef34316270" + integrity sha512-Fhjc/k8725ItmrvW5QomzxLeojewxvqiYCKeFcfFEhut28IVLdpHU19dneOmltZQIE5HNbawj1HYD+1f2bM1Dg== + dependencies: + nanocolors "^0.1.0" + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -4299,6 +4606,29 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -4491,6 +4821,13 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone-regexp@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" + integrity sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q== + dependencies: + is-regexp "^2.0.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -4547,6 +4884,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + colorette@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" @@ -4795,6 +5137,17 @@ cors@~2.8.5: object-assign "^4" vary "^1" +cosmiconfig@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + coveralls@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" @@ -4938,6 +5291,11 @@ css-what@^3.2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + csso@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" @@ -5023,6 +5381,19 @@ debug@^3.0.1, debug@^3.1.0, debug@^3.1.1: dependencies: ms "^2.1.1" +decamelize-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + decimal.js@^10.2.1: version "10.3.1" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" @@ -5284,6 +5655,11 @@ electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.723: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.775.tgz#046517d1f2cea753e06fff549995b9dc45e20082" integrity sha512-EGuiJW4yBPOTj2NtWGZcX93ZE8IGj33HJAx4d3ouE2zOfW2trbWU+t1e0yzLr1qQIw81++txbM3BH52QwSRE6Q== +electron-to-chromium@^1.3.846: + version "1.3.848" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.848.tgz#94cc196e496f33c0d71cd98561448f10018584cc" + integrity sha512-wchRyBcdcmibioggdO7CbMT5QQ4lXlN/g7Mkpf1K2zINidnqij6EVu94UIZ+h5nB2S9XD4bykqFv9LonAWLFyw== + elliptic@^6.5.3: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -5741,6 +6117,17 @@ ember-cli-string-utils@^1.0.0, ember-cli-string-utils@^1.1.0: resolved "https://registry.yarnpkg.com/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz#39b677fc2805f55173735376fcef278eaa4452a1" integrity sha1-ObZ3/CgF9VFzc1N2/O8njqpEUqE= +ember-cli-stylelint@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-stylelint/-/ember-cli-stylelint-4.0.0.tgz#420e14ac9460eafd2048c24d9aa01bcdca42031d" + integrity sha512-HaRFVDvMpGrVNdoWxYED/DJOlYcfIFG33eNuQMY2asgrRuZX3K7OVzVq3o9TXfcj819n8ghpOVZ+vMPNNxlHlg== + dependencies: + broccoli-funnel "^3.0.2" + broccoli-merge-trees "^4.1.0" + broccoli-stylelint "^4.0.0" + ember-cli-version-checker "^5.0.2" + js-string-escape "^1.0.1" + ember-cli-terser@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/ember-cli-terser/-/ember-cli-terser-4.0.2.tgz#c436a9e4159f76a615b051cba0584844652b7dcd" @@ -5858,7 +6245,7 @@ ember-cli-version-checker@^4.1.0: semver "^6.3.0" silent-error "^1.1.1" -ember-cli-version-checker@^5.1.1, ember-cli-version-checker@^5.1.2: +ember-cli-version-checker@^5.0.2, ember-cli-version-checker@^5.1.1, ember-cli-version-checker@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-5.1.2.tgz#649c7b6404902e3b3d69c396e054cea964911ab0" integrity sha512-rk7GY+FmLn/2e22HsZs0Ycrz8HQ1W3Fv+2TFOuEFW9optnDXDgkntPBIl6gact/LHsfBM5RKbM3dHsIIeLgl0Q== @@ -7097,6 +7484,13 @@ execa@^4.0.0, execa@^4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execall@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" + integrity sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow== + dependencies: + clone-regexp "^2.1.0" + exists-sync@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/exists-sync/-/exists-sync-0.0.3.tgz#b910000bedbb113b378b82f5f5a7638107622dcf" @@ -7253,7 +7647,7 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1: +fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.5: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== @@ -7322,6 +7716,11 @@ fastboot-transform@^0.1.0: broccoli-stew "^1.5.0" convert-source-map "^1.5.1" +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + fastq@^1.6.0: version "1.11.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" @@ -7459,7 +7858,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -7937,6 +8336,13 @@ global-modules@^1.0.0: is-windows "^1.0.1" resolve-dir "^1.0.0" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" @@ -7948,6 +8354,15 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -7996,11 +8411,23 @@ globby@^11.0.2, globby@^11.0.3: merge2 "^1.3.0" slash "^3.0.0" +globjoin@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= + globrex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== +gonzales-pe@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== + dependencies: + minimist "^1.2.5" + good-listener@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" @@ -8056,6 +8483,11 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -8253,7 +8685,12 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -htmlparser2@^3.9.1: +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== + +htmlparser2@^3.10.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -8374,7 +8811,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: +ignore@^5.0.2, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -8387,6 +8824,11 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-lazy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -8397,6 +8839,11 @@ include-path-searcher@^0.1.0: resolved "https://registry.yarnpkg.com/include-path-searcher/-/include-path-searcher-0.1.0.tgz#c0cf2ddfa164fb2eae07bc7ca43a7f191cb4d7bd" integrity sha1-wM8t36Fk+y6uB7x8pDp/GRy0170= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + infer-owner@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -8435,7 +8882,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4: +ini@^1.3.4, ini@^1.3.5: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -8546,6 +8993,19 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -8582,7 +9042,7 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.2: +is-buffer@^2.0.0, is-buffer@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -8599,6 +9059,13 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" +is-core-module@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" + integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -8618,6 +9085,11 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5" integrity sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A== +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -8699,6 +9171,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -8736,11 +9213,16 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== -is-plain-obj@2.1.0: +is-plain-obj@2.1.0, is-plain-obj@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -8768,6 +9250,11 @@ is-regex@^1.1.3: call-bind "^1.0.2" has-symbols "^1.0.2" +is-regexp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" + integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA== + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -8909,7 +9396,7 @@ jquery@^3.5.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== -js-string-escape@^1.0.1: +js-string-escape@^1.0.1, js-string-escape@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= @@ -8975,7 +9462,7 @@ jsesc@^1.3.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= -jsesc@^2.5.1: +jsesc@^2.5.0, jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== @@ -8995,6 +9482,11 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -9103,7 +9595,7 @@ kind-of@^5.0.0: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -9115,6 +9607,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +known-css-properties@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.21.0.tgz#15fbd0bbb83447f3ce09d8af247ed47c68ede80d" + integrity sha512-sZLUnTqimCkvkgRS+kbPlYW5o8q5w1cu+uIisKpEWkj31I8mx8kNG162DwRav8Zirkva6N5uoFsm9kzK4mUXjw== + lcov-parse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" @@ -9153,6 +9650,11 @@ line-column@^1.0.2: isarray "^1.0.0" isobject "^2.0.0" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + linkify-it@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" @@ -9337,7 +9839,7 @@ lodash.defaults@^4.0.1, lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= -lodash.defaultsdeep@^4.6.1: +lodash.defaultsdeep@^4.6.0, lodash.defaultsdeep@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA== @@ -9499,6 +10001,11 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +longest-streak@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -9568,6 +10075,16 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -9623,6 +10140,11 @@ matcher-collection@^2.0.0, matcher-collection@^2.0.1: "@types/minimatch" "^3.0.3" minimatch "^3.0.2" +mathml-tag-names@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" + integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -9632,6 +10154,34 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdast-util-from-markdown@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + +mdast-util-to-markdown@^0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== + dependencies: + "@types/unist" "^2.0.0" + longest-streak "^2.0.0" + mdast-util-to-string "^2.0.0" + parse-entities "^2.0.0" + repeat-string "^1.0.0" + zwitch "^1.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -9685,6 +10235,24 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -9725,6 +10293,14 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= +micromark@~2.11.0: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -9787,6 +10363,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -9804,6 +10385,15 @@ minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + minimist@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.1.tgz#827ba4e7593464e7c221e8c5bed930904ee2c455" @@ -9950,6 +10540,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== +nanocolors@^0.1.0, nanocolors@^0.1.5: + version "0.1.12" + resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" + integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -10063,6 +10658,11 @@ node-releases@^1.1.71: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== +node-releases@^1.1.76: + version "1.1.76" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e" + integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA== + node-watch@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/node-watch/-/node-watch-0.7.1.tgz#0caaa6a6833b0d533487f953c52a6c787769ba7c" @@ -10075,7 +10675,7 @@ nopt@3.x, nopt@^3.0.6: dependencies: abbrev "1" -normalize-package-data@^2.3.2: +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -10085,6 +10685,16 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -10097,6 +10707,16 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-selector@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= + npm-git-info@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/npm-git-info/-/npm-git-info-1.0.3.tgz#a933c42ec321e80d3646e0d6e844afe94630e1d5" @@ -10164,6 +10784,11 @@ nth-check@^1.0.2, nth-check@~1.0.1: dependencies: boolbase "~1.0.0" +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -10482,6 +11107,18 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -10490,6 +11127,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse-ms@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" @@ -10708,6 +11355,79 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postcss-html@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== + dependencies: + htmlparser2 "^3.10.0" + +postcss-less@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad" + integrity sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA== + dependencies: + postcss "^7.0.14" + +postcss-media-query-parser@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= + +postcss-resolve-nested-selector@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= + +postcss-safe-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" + integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g== + dependencies: + postcss "^7.0.26" + +postcss-sass@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.4.4.tgz#91f0f3447b45ce373227a98b61f8d8f0785285a3" + integrity sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg== + dependencies: + gonzales-pe "^4.3.0" + postcss "^7.0.21" + +postcss-scss@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.1.1.tgz#ec3a75fa29a55e016b90bf3269026c53c1d2b383" + integrity sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA== + dependencies: + postcss "^7.0.6" + +postcss-selector-parser@^6.0.5: + version "6.0.6" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" + integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-syntax@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== + +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.6: + version "7.0.36" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" + integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -10898,6 +11618,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5, quick-temp@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408" @@ -10969,6 +11694,15 @@ raw-body@~1.1.0: bytes "1" string_decoder "0.10" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -10978,6 +11712,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -11047,6 +11791,14 @@ recast@^0.18.1: private "^0.1.8" source-map "~0.6.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + redeyed@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" @@ -11168,6 +11920,29 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + +remark-stringify@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894" + integrity sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg== + dependencies: + mdast-util-to-markdown "^0.6.0" + +remark@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-13.0.0.tgz#d15d9bf71a402f40287ebe36067b66d54868e425" + integrity sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA== + dependencies: + remark-parse "^9.0.0" + remark-stringify "^9.0.0" + unified "^9.1.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -11178,7 +11953,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.6.1: +repeat-string@^1.0.0, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -11264,6 +12039,11 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-package-path@^1.0.11, resolve-package-path@^1.2.2, resolve-package-path@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e" @@ -11927,6 +12707,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f" integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ== +specificity@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -12045,7 +12830,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== @@ -12165,6 +12950,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -12175,11 +12967,89 @@ striptags@^3.1.1: resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== +style-search@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= + styled_string@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a" integrity sha1-0ieCvYEpVFm8Tx3xjEutjpTdEko= +stylelint-config-prettier@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-8.0.2.tgz#da9de33da4c56893cbe7e26df239a7374045e14e" + integrity sha512-TN1l93iVTXpF9NJstlvP7nOu9zY2k+mN0NSFQ/VEGz15ZIP9ohdDZTtCWHs5LjctAhSAzaILULGbgiM0ItId3A== + +stylelint-prettier@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stylelint-prettier/-/stylelint-prettier-1.2.0.tgz#a133d75c794ba820ee47136fc4bf8c72ea185427" + integrity sha512-/MYz6W2CNgKHblPzPtk7cybu8H5dGG3c2GevL64RButERj1uJg4SdBIIat1hMfDOmN6QQpldc6tCc//ZAWh9WQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +stylelint@^13.13.1, stylelint@^13.2.1: + version "13.13.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.13.1.tgz#fca9c9f5de7990ab26a00f167b8978f083a18f3c" + integrity sha512-Mv+BQr5XTUrKqAXmpqm6Ddli6Ief+AiPZkRsIrAoUKFuq/ElkUh9ZMYxXD0iQNZ5ADghZKLOWz1h7hTClB7zgQ== + dependencies: + "@stylelint/postcss-css-in-js" "^0.37.2" + "@stylelint/postcss-markdown" "^0.36.2" + autoprefixer "^9.8.6" + balanced-match "^2.0.0" + chalk "^4.1.1" + cosmiconfig "^7.0.0" + debug "^4.3.1" + execall "^2.0.0" + fast-glob "^3.2.5" + fastest-levenshtein "^1.0.12" + file-entry-cache "^6.0.1" + get-stdin "^8.0.0" + global-modules "^2.0.0" + globby "^11.0.3" + globjoin "^0.1.4" + html-tags "^3.1.0" + ignore "^5.1.8" + import-lazy "^4.0.0" + imurmurhash "^0.1.4" + known-css-properties "^0.21.0" + lodash "^4.17.21" + log-symbols "^4.1.0" + mathml-tag-names "^2.1.3" + meow "^9.0.0" + micromatch "^4.0.4" + normalize-selector "^0.2.0" + postcss "^7.0.35" + postcss-html "^0.36.0" + postcss-less "^3.1.4" + postcss-media-query-parser "^0.2.3" + postcss-resolve-nested-selector "^0.1.1" + postcss-safe-parser "^4.0.2" + postcss-sass "^0.4.4" + postcss-scss "^2.1.1" + postcss-selector-parser "^6.0.5" + postcss-syntax "^0.36.2" + postcss-value-parser "^4.1.0" + resolve-from "^5.0.0" + slash "^3.0.0" + specificity "^0.4.1" + string-width "^4.2.2" + strip-ansi "^6.0.0" + style-search "^0.1.0" + sugarss "^2.0.0" + svg-tags "^1.0.0" + table "^6.6.0" + v8-compile-cache "^2.3.0" + write-file-atomic "^3.0.3" + +sugarss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" + integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== + dependencies: + postcss "^7.0.2" + sum-up@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/sum-up/-/sum-up-1.0.3.tgz#1c661f667057f63bcb7875aa1438bc162525156e" @@ -12206,6 +13076,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -12213,6 +13090,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= + svgo@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" @@ -12269,7 +13151,7 @@ tabbable@^5.2.0: resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.2.0.tgz#4fba60991d8bb89d06e5d9455c92b453acf88fb2" integrity sha512-0uyt8wbP0P3T4rrsfYg/5Rg3cIJ8Shl1RJ54QMqYxm1TLdWqJD1u6+RQjr2Lor3wmfT7JRHkirIwy99ydBsyPg== -table@^6.0.9: +table@^6.0.9, table@^6.6.0: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== @@ -12612,11 +13494,21 @@ tree-sync@^2.0.0, tree-sync@^2.1.0: quick-temp "^0.1.5" walk-sync "^0.3.3" +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -12663,6 +13555,11 @@ type-fest@^0.11.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -12673,6 +13570,16 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -12754,6 +13661,18 @@ unicode-property-aliases-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== +unified@^9.1.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -12785,6 +13704,25 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +unist-util-find-all-after@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6" + integrity sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ== + dependencies: + unist-util-is "^4.0.0" + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -12899,7 +13837,7 @@ uuid@^8.3.0, uuid@^8.3.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: +v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== @@ -12946,6 +13884,24 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -13132,7 +14088,7 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which@^1.1.1, which@^1.2.14, which@^1.2.9: +which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -13220,7 +14176,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== @@ -13293,7 +14249,12 @@ yam@^1.0.0: fs-extra "^4.0.2" lodash.merge "^4.6.0" -yargs-parser@^20.2.2: +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== @@ -13320,3 +14281,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== From 8241dd8800f0fc2e4b580dacea3ea7e52648833e Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Thu, 23 Sep 2021 16:47:12 +0300 Subject: [PATCH 13/25] css lint fixes --- frontend/app/styles/_badge-modal.scss | 8 +- frontend/app/styles/_course.scss | 85 +++++---- frontend/app/styles/_custom-checkbox.scss | 5 +- frontend/app/styles/_custom-search-icon.scss | 2 +- frontend/app/styles/_dropdown.scss | 15 +- frontend/app/styles/_edit-profile.scss | 20 +-- frontend/app/styles/_h5p-editor.scss | 1 - frontend/app/styles/_h5p-player.scss | 2 +- frontend/app/styles/_loader.scss | 2 +- .../app/styles/_notifications-dropdown.scss | 16 +- frontend/app/styles/_popular-cards.scss | 13 +- frontend/app/styles/_profile.scss | 47 +++-- frontend/app/styles/_rating-and-review.scss | 29 ++- frontend/app/styles/_reaction-buttons.scss | 10 +- frontend/app/styles/_survey.scss | 15 +- frontend/app/styles/_tags-list.scss | 25 +-- frontend/app/styles/_user-acc-dropdown.scss | 27 ++- .../app/styles/admin/_badge-management.scss | 25 ++- frontend/app/styles/admin/_main-header.scss | 13 +- frontend/app/styles/admin/_side-nav.scss | 12 +- .../app/styles/admin/_survey-management.scss | 24 ++- frontend/app/styles/admin/admin.scss | 29 ++- frontend/app/styles/app.scss | 74 ++++---- frontend/app/styles/bs4.scss | 166 ++++++++++-------- frontend/app/styles/cms-desktop.scss | 7 +- frontend/app/styles/comments.scss | 6 +- frontend/app/styles/common/colors.scss | 2 +- frontend/app/styles/common/forms.scss | 30 +--- frontend/app/styles/common/typography.scss | 6 +- frontend/app/styles/common/variables.scss | 10 +- frontend/app/styles/forgot-password.scss | 2 +- frontend/app/styles/h5p-list-item.scss | 19 +- frontend/app/styles/header.scss | 7 +- frontend/app/styles/home.scss | 25 +-- frontend/app/styles/landing.scss | 25 +-- frontend/app/styles/login.scss | 12 +- frontend/app/styles/nav.scss | 42 ++--- frontend/app/styles/search.scss | 8 +- frontend/app/styles/signup.scss | 12 +- frontend/app/styles/single-chapter.scss | 42 ++--- frontend/app/styles/teach-login.scss | 9 +- .../app/styles/teacher/content-creation.scss | 21 ++- frontend/app/styles/teacher/teacher.scss | 4 +- frontend/app/styles/toc-component.scss | 28 ++- frontend/app/styles/warning-component.scss | 2 +- 45 files changed, 457 insertions(+), 527 deletions(-) diff --git a/frontend/app/styles/_badge-modal.scss b/frontend/app/styles/_badge-modal.scss index e8b547302..45dd8db79 100644 --- a/frontend/app/styles/_badge-modal.scss +++ b/frontend/app/styles/_badge-modal.scss @@ -1,8 +1,8 @@ $palette: ( - primary: #F57010, - studio: #5A47AD, - windsor: #4E0B80, - white: #FFFF + primary: #f57010, + studio: #5a47ad, + windsor: #4e0b80, + white: #ffff, ); .badge-popup { diff --git a/frontend/app/styles/_course.scss b/frontend/app/styles/_course.scss index 7660fdae0..95be70741 100644 --- a/frontend/app/styles/_course.scss +++ b/frontend/app/styles/_course.scss @@ -1,25 +1,25 @@ $palette: ( - primary: #F57010, + primary: #f57010, black: #0000, - white: #FFFF, - gray30: #3F484D, - gray75: #B0BABF, - gray95: #EBF0F2, - alto: #DCDCDC, - osloGray: #8A9296, + white: #ffff, + gray30: #3f484d, + gray75: #b0babf, + gray95: #ebf0f2, + alto: #dcdcdc, + osloGray: #8a9296, silver: #bebebe, cinderella: #fcdfca, doveGray: #707070, - gallery: #F0F0F0, - nevada: #696C6E, + gallery: #f0f0f0, + nevada: #696c6e, mercury: #e3e3e3, - electricViolet: #651CF0, - dustyGray: #A08C8C + electricViolet: #651cf0, + dustyGray: #a08c8c, ); .cpc-container { .course-preview-card { - box-shadow: 0 3px 6px rgba(0, 0, 0, .075); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.075); border: 1px solid map-get($palette, mercury); height: 100%; display: flex; @@ -49,7 +49,7 @@ $palette: ( color: map-get($palette, nevada); svg { - fill: map-get($palette, gray30) + fill: map-get($palette, gray30); } } } @@ -65,8 +65,7 @@ $palette: ( padding-left: 8px; padding-right: 8px; font-size: 12px; - color: map-get($palette, gray30) - + color: map-get($palette, gray30); } .tags-section { @@ -80,7 +79,7 @@ $palette: ( .tag-list { .course-tag { - padding: .3em .6em; + padding: 0.3em 0.6em; font-size: 12px; color: map-get($palette, gray45); background-color: map-get($palette, gray95); @@ -114,7 +113,6 @@ $palette: ( } .course-form { - .image-upload-section { .image-upload-card { padding: 12px; @@ -177,7 +175,9 @@ $palette: ( border-color: map-get($palette, gray95); font-size: 12px; - &:active, &.active, &:focus { + &:active, + &.active, + &:focus { outline: none; background-color: map-get($palette, primary); color: map-get($palette, white); @@ -185,7 +185,7 @@ $palette: ( &.selected { .close-icon { - opacity: .5; + opacity: 0.5; font-weight: 700; } @@ -240,10 +240,10 @@ $palette: ( background: transparent; } - &::-webkit-scrollbar-thumb, ::-webkit-scrollbar-thumb:hover { + &::-webkit-scrollbar-thumb, + ::-webkit-scrollbar-thumb:hover { background: #71797c; } - } .playlist-manager-section { @@ -256,14 +256,15 @@ $palette: ( padding-right: 10px; .rank-actions { - .btn-down, .btn-up { + .btn-down, + .btn-up { padding: 0; border-radius: 0; width: 28px; border-width: 0; svg { - fill: #CCD9E0; + fill: #ccd9e0; } } } @@ -323,14 +324,15 @@ $palette: ( .playlist-item:hover { .rank-actions { - .btn-down, .btn-up { + .btn-down, + .btn-up { padding: 0; border-radius: 0; width: 28px; border-width: 0; svg { - fill: #174A84; + fill: #174a84; } } } @@ -368,7 +370,6 @@ $palette: ( color: map-get($palette, gray30); font-size: 20px; } - } .mini-user-menu { @@ -380,7 +381,7 @@ $palette: ( color: map-get($palette, gray30); &.active:after { - content: ""; + content: ''; position: absolute; width: 68%; bottom: -1px; @@ -392,7 +393,6 @@ $palette: ( } } } - } .course-sections-menu { @@ -409,7 +409,7 @@ $palette: ( line-height: initial; &.active { - background-color: #ECF0F2; + background-color: #ecf0f2; } } } @@ -449,14 +449,15 @@ $palette: ( .search-input { border-radius: 18px; - padding: .275rem .45rem; + padding: 0.275rem 0.45rem; height: initial; &::placeholder { font-size: 14px; } - &:focus, &:hover { + &:focus, + &:hover { background-image: none; } } @@ -488,7 +489,8 @@ $palette: ( .search-input { background: none; - &:focus, &:hover { + &:focus, + &:hover { background: none; } } @@ -517,7 +519,8 @@ $palette: ( bottom: 10px; right: 0; - .btn-add-to-course, .btn-remove-from-course { + .btn-add-to-course, + .btn-remove-from-course { background-color: transparent; border: none; color: map-get($palette, primary); @@ -549,10 +552,8 @@ $palette: ( right: 10px; bottom: 10px; } - } - .view-course-page { position: relative; @@ -592,12 +593,12 @@ $palette: ( .course-main-details-card { .tags-section { .section-header { - color: map-get($palette, dustyGray) + color: map-get($palette, dustyGray); } .tag-list { .course-tag { - padding: .3em .6em; + padding: 0.3em 0.6em; font-size: 12px; color: map-get($palette, gray45); background-color: map-get($palette, gray95); @@ -680,16 +681,15 @@ $palette: ( } } } - - } .view-course-page { .ft-section { .side-bar { - .popular-tags, .popular-courses { + .popular-tags, + .popular-courses { box-shadow: 0 3px 6px #00000019; - border: 1px solid #DCDCDC; + border: 1px solid #dcdcdc; border-radius: 5px; min-height: 150px; padding: 8px 5px 5px; @@ -698,7 +698,6 @@ $palette: ( color: map-get($palette, gray30); font-weight: 500; padding-left: 3px; - } } } @@ -748,7 +747,6 @@ $palette: ( width: 70%; padding: 20px 15% 20px 20px; background-color: map-get($palette, white); - } .course-image-container { @@ -775,4 +773,3 @@ $palette: ( max-width: 1230px; } } - diff --git a/frontend/app/styles/_custom-checkbox.scss b/frontend/app/styles/_custom-checkbox.scss index c56c00f25..afb50d39c 100644 --- a/frontend/app/styles/_custom-checkbox.scss +++ b/frontend/app/styles/_custom-checkbox.scss @@ -10,11 +10,10 @@ cursor: pointer; &:before { - } &:after { - content: "\2714"; + content: '\2714'; position: absolute; top: -4px; width: 14px; @@ -29,7 +28,7 @@ box-shadow: inset 20px 0 0 0 $primary; &:after { - left: 2px + left: 2px; } } } diff --git a/frontend/app/styles/_custom-search-icon.scss b/frontend/app/styles/_custom-search-icon.scss index dfdc67585..e81d0d7de 100644 --- a/frontend/app/styles/_custom-search-icon.scss +++ b/frontend/app/styles/_custom-search-icon.scss @@ -1,6 +1,6 @@ $palette: ( circle: black, - stick: black + stick: black, ); .search-icon { width: 40px; diff --git a/frontend/app/styles/_dropdown.scss b/frontend/app/styles/_dropdown.scss index cc1243a80..e1e098b8c 100644 --- a/frontend/app/styles/_dropdown.scss +++ b/frontend/app/styles/_dropdown.scss @@ -1,8 +1,7 @@ -$palette: ( -); +$palette: (); -.dropdown-toggle{ - &:hover{ +.dropdown-toggle { + &:hover { text-decoration: none; } } @@ -12,11 +11,11 @@ $palette: ( -ms-transform: rotate(45deg); transform: rotate(45deg); top: 0; - content: ""; + content: ''; border: 0.13em solid map-get($palette, white); - -webkit-transition: all .3s ease; - -o-transition: all .3s ease; - transition: all .3s ease; + -webkit-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; overflow: hidden; border-left: 1px solid transparent; border-top: 1px solid transparent; diff --git a/frontend/app/styles/_edit-profile.scss b/frontend/app/styles/_edit-profile.scss index 4e7ec80ad..c93a1c534 100644 --- a/frontend/app/styles/_edit-profile.scss +++ b/frontend/app/styles/_edit-profile.scss @@ -1,15 +1,14 @@ $palette: ( - blizzardBlue: #ABD5F0, - white: #FFFF, - gray30:#3F484D, - mako: #3F484D, + blizzardBlue: #abd5f0, + white: #ffff, + gray30: #3f484d, + mako: #3f484d, corvette: #fac7a1, - portage: #AF7EF4, - black: #000 + portage: #af7ef4, + black: #000, ); .edit-profile-page { - background-color: map-get($palette, blizzardBlue); .container-wrap { @@ -17,7 +16,6 @@ $palette: ( top: 15px; background-color: map-get($palette, white); padding: 25px; - } .header-section { @@ -32,7 +30,7 @@ $palette: ( padding-top: 2px; } } - + .edit-profile-form { .section-title { font-size: 19px; @@ -61,7 +59,6 @@ $palette: ( font-size: 12px; } } - } .btn-submit { @@ -105,14 +102,11 @@ $palette: ( } } } - } @media (min-width: 768px) { - .edit-profile-page { .edit-profile-form { - .form-group { .col-form-label { text-align: right; diff --git a/frontend/app/styles/_h5p-editor.scss b/frontend/app/styles/_h5p-editor.scss index fd036f246..336d40665 100644 --- a/frontend/app/styles/_h5p-editor.scss +++ b/frontend/app/styles/_h5p-editor.scss @@ -5,7 +5,6 @@ .h5p-editor-section { margin: 0 auto; max-width: 960px; - } iframe.h5p-editor-iframe { diff --git a/frontend/app/styles/_h5p-player.scss b/frontend/app/styles/_h5p-player.scss index 53b462087..79d95a7d3 100644 --- a/frontend/app/styles/_h5p-player.scss +++ b/frontend/app/styles/_h5p-player.scss @@ -1,3 +1,3 @@ -.h5p-iframe-wrapper iframe{ +.h5p-iframe-wrapper iframe { background-color: black !important; } diff --git a/frontend/app/styles/_loader.scss b/frontend/app/styles/_loader.scss index 5e0635a5d..fd7c62e25 100644 --- a/frontend/app/styles/_loader.scss +++ b/frontend/app/styles/_loader.scss @@ -1,6 +1,6 @@ $palette: ( primary: #007bff, - lightGray: #B0BABF + lightGray: #b0babf, ); .circular-loader { diff --git a/frontend/app/styles/_notifications-dropdown.scss b/frontend/app/styles/_notifications-dropdown.scss index 92c0fdf73..6eca483a7 100644 --- a/frontend/app/styles/_notifications-dropdown.scss +++ b/frontend/app/styles/_notifications-dropdown.scss @@ -1,10 +1,10 @@ $palette: ( - gray30: #3F484D, - gray40: #B3BAC566, - primary:#F57010, - red: #EA0606, - white: #FFFF, - jungleGreen: #32A583 + gray30: #3f484d, + gray40: #b3bac566, + primary: #f57010, + red: #ea0606, + white: #ffff, + jungleGreen: #32a583, ); .notifications-dropdown { @@ -71,7 +71,6 @@ $palette: ( .empty-state { font-weight: 300; } - } .notification-item { @@ -176,7 +175,6 @@ $palette: ( On large screen */ @media (min-width: 992px) { - .notifications-dropdown { .dropdown-menu.show { width: 320px; @@ -193,7 +191,7 @@ On large screen border-width: 8px; bottom: 100%; left: 88%; - content: " "; + content: ' '; height: 0; pointer-events: none; position: absolute; diff --git a/frontend/app/styles/_popular-cards.scss b/frontend/app/styles/_popular-cards.scss index 08d561c62..d8221013d 100644 --- a/frontend/app/styles/_popular-cards.scss +++ b/frontend/app/styles/_popular-cards.scss @@ -1,8 +1,8 @@ $palette: ( - primary: #F57010, - gray30: #3F484D, - gray45: #5E6C73, - gray95: #EBF0F2, + primary: #f57010, + gray30: #3f484d, + gray45: #5e6c73, + gray95: #ebf0f2, ); .popular-courses, @@ -26,7 +26,6 @@ $palette: ( font-size: 14px; padding-left: 5px; padding-right: 5px; - } } } @@ -60,7 +59,8 @@ $palette: ( width: 100%; } - .people-enrolled, .tags-list .tag { + .people-enrolled, + .tags-list .tag { font-size: 12px; color: map-get($palette, gray30); @@ -68,7 +68,6 @@ $palette: ( text-decoration: none; } } - } &:hover { diff --git a/frontend/app/styles/_profile.scss b/frontend/app/styles/_profile.scss index b4b54825c..60b8a2b0a 100644 --- a/frontend/app/styles/_profile.scss +++ b/frontend/app/styles/_profile.scss @@ -1,17 +1,17 @@ $palette: ( - primary: #F57010, - white: #FFFF, + primary: #f57010, + white: #ffff, darkCharcoal: rgba(87, 92, 88, 1), - teach: #32A583, - eucalyptus: #28A745, + teach: #32a583, + eucalyptus: #28a745, cardBoxShadow: rgba(0, 0, 0, 0.29), - gray30: #3F484D, - gray95: #EBF0F2, - aliceBlue: #F7FCFF, - bombay: #B2B4B6, - bonjour: #EAE7E7, + gray30: #3f484d, + gray95: #ebf0f2, + aliceBlue: #f7fcff, + bombay: #b2b4b6, + bonjour: #eae7e7, black: #000000, - gallery: #F0F0F0, + gallery: #f0f0f0, ); .account-profile-page { @@ -79,13 +79,12 @@ $palette: ( .badges-unlocked-card { background-color: map-get($palette, white); - box-shadow: 0px 0px 4px 0px map-get($palette, cardBoxShadow);; + box-shadow: 0px 0px 4px 0px map-get($palette, cardBoxShadow); border-radius: 5px; } } } - // profile card .account-details-list { .profile-card { @@ -95,7 +94,6 @@ $palette: ( padding-bottom: 15px; .body-content { - .left-container { min-width: 120px; padding-right: 1px; @@ -147,7 +145,9 @@ $palette: ( color: map-get($palette, gray30); } - .phone, .email, .location { + .phone, + .email, + .location { font-size: 12px; padding-bottom: 12px; @@ -171,7 +171,6 @@ $palette: ( // counters .account-details-list { - .achievements-list { .achievement-card { padding: 7px; @@ -206,24 +205,22 @@ $palette: ( .achievement-card { &.created-chapters { .section-icon { - background-image: url("/images/notes-42.png"); + background-image: url('/images/notes-42.png'); } } &.completed-chapters { .section-icon { - background-image: url("/images/completed-55.png"); + background-image: url('/images/completed-55.png'); } } &.earned-points { .section-icon { - background-image: url("/images/earned-47.png"); + background-image: url('/images/earned-47.png'); } } - } - } } @@ -242,7 +239,7 @@ $palette: ( padding-bottom: 5px; .section-icon { - background-image: url("/images/achievement-38.png"); + background-image: url('/images/achievement-38.png'); display: inline-block; height: 40px; width: 45px; @@ -365,7 +362,7 @@ $palette: ( width: fit-content; border: 1px solid map-get($palette, bonjour); border-radius: 18px; - padding: .385rem 1.45rem; + padding: 0.385rem 1.45rem; background-color: map-get($palette, white); font-size: 14px; @@ -472,7 +469,6 @@ $palette: ( } @media (max-width: 992px) { - .account-profile-page { .account-details-list .profile-card { margin-bottom: 8px; @@ -502,11 +498,9 @@ $palette: ( } @media (min-width: 768px) { - .account-profile-page { .account-details-list .profile-card { flex: 0 0 31%; - } .badges-unlocked-card { @@ -520,7 +514,8 @@ $palette: ( @media (min-width: 1200px) { .account-profile-page { - .dashboard-content-wrapper, .main-content-wrapper { + .dashboard-content-wrapper, + .main-content-wrapper { max-width: 1240px; } } diff --git a/frontend/app/styles/_rating-and-review.scss b/frontend/app/styles/_rating-and-review.scss index 64c6af3a3..9d656dafd 100644 --- a/frontend/app/styles/_rating-and-review.scss +++ b/frontend/app/styles/_rating-and-review.scss @@ -1,14 +1,14 @@ $palette: ( - primary: #F57010, - white: #FFFF, + primary: #f57010, + white: #ffff, blue: #007bff, - gray45:#5E6C73, - dark: #1E2326, - terrible: #F05F56, - bad: #EA7900BC, - okay: #F1DF5B, - good: #9ACD32, - great: #03A543 + gray45: #5e6c73, + dark: #1e2326, + terrible: #f05f56, + bad: #ea7900bc, + okay: #f1df5b, + good: #9acd32, + great: #03a543, ); .rating-review-section { @@ -61,13 +61,13 @@ $palette: ( &.selected { background-color: map-get($palette, blue); - } } } .rating-group { - .rating-star, .rating-emoji { + .rating-star, + .rating-emoji { display: inline-block; cursor: pointer; } @@ -110,10 +110,8 @@ $palette: ( &.great.active svg g g { fill: map-get($palette, great); stroke: map-get($palette, great); - } } - } .rating-review-feedback-modal { @@ -137,13 +135,13 @@ $palette: ( display: inline-block; &:after { - content: " "; + content: ' '; display: block; border-color: map-get($palette, white); border-style: solid; width: 1.2em; height: 2.7em; - border-width: 0 .4em 0.4em 0; + border-width: 0 0.4em 0.4em 0; position: absolute; left: 48%; top: 12%; @@ -170,5 +168,4 @@ $palette: ( color: map-get($palette, gray45); } } - } diff --git a/frontend/app/styles/_reaction-buttons.scss b/frontend/app/styles/_reaction-buttons.scss index b3662555b..d59ae28e1 100644 --- a/frontend/app/styles/_reaction-buttons.scss +++ b/frontend/app/styles/_reaction-buttons.scss @@ -1,5 +1,7 @@ -$palette: (primary: $primary, - gray75: #B0BABF); +$palette: ( + primary: $primary, + gray75: #b0babf, +); .reaction-btn { background: none; @@ -15,8 +17,6 @@ $palette: (primary: $primary, display: inline-flex; align-items: center; - - span.count { padding-left: 5px; } @@ -34,4 +34,4 @@ $palette: (primary: $primary, display: inline-block; fill: currentColor; } -} \ No newline at end of file +} diff --git a/frontend/app/styles/_survey.scss b/frontend/app/styles/_survey.scss index 43d94d294..5d3cc6ef0 100644 --- a/frontend/app/styles/_survey.scss +++ b/frontend/app/styles/_survey.scss @@ -1,14 +1,12 @@ $palette: ( - studio: #5A47AD, - windsor: #4E0B80, - white: #FFFF, - primary: #F57010, - gray30:#3F484D, - + studio: #5a47ad, + windsor: #4e0b80, + white: #ffff, + primary: #f57010, + gray30: #3f484d, ); .surveys-page { - .breadcrumbs { span.divider { padding-left: 3px; @@ -22,7 +20,6 @@ $palette: ( transform: translate(0, -70px) !important; } - .modal-header { border: none; padding-bottom: 0; @@ -63,7 +60,7 @@ $palette: ( padding-top: 12px; padding-bottom: 12px; margin-top: 8px; - &:hover{ + &:hover { display: block; width: 100%; border: solid 1px; diff --git a/frontend/app/styles/_tags-list.scss b/frontend/app/styles/_tags-list.scss index f75a43f14..ffc710517 100644 --- a/frontend/app/styles/_tags-list.scss +++ b/frontend/app/styles/_tags-list.scss @@ -1,7 +1,7 @@ $palette: ( - primary: #F57010, - grey45: #9DA3A2, - grey75: #B0BABF + primary: #f57010, + grey45: #9da3a2, + grey75: #b0babf, ); .tags-filter-dropdown { @@ -24,7 +24,7 @@ $palette: ( border-radius: 3px; max-height: 400px; overflow-y: scroll; - box-shadow: 0 3px 6px rgba(0, 0, 0, .075); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.075); .tag-select-item { padding: 8px 15px; @@ -33,13 +33,13 @@ $palette: ( label { text-align: left; font-size: 15px; - color: #5C6267; + color: #5c6267; font-weight: normal; margin: 0; } &:hover { - background-color: #F7F9FA; + background-color: #f7f9fa; } } } @@ -94,10 +94,9 @@ $palette: ( outline: none; &.active { - color: map_get($palette, primary);; + color: map_get($palette, primary); } } - } .tag-list { @@ -148,12 +147,13 @@ $palette: ( border-radius: 0; white-space: nowrap; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { background-color: transparent; color: $primary; box-shadow: none; border-width: 0 0 2px 0; - } &.hidden-sm { @@ -162,13 +162,14 @@ $palette: ( line-height: 1.5; border: none; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { border-width: 0; background-color: transparent; color: $primary; box-shadow: none !important; } } - } } diff --git a/frontend/app/styles/_user-acc-dropdown.scss b/frontend/app/styles/_user-acc-dropdown.scss index 9e05b9d0e..0dbd4f65e 100644 --- a/frontend/app/styles/_user-acc-dropdown.scss +++ b/frontend/app/styles/_user-acc-dropdown.scss @@ -1,6 +1,6 @@ $palette: ( - white: #FFFF, - primary: #F57010 + white: #ffff, + primary: #f57010, ); .user-profile-dropdown { @@ -14,11 +14,11 @@ $palette: ( -ms-transform: rotate(45deg); transform: rotate(45deg); top: 0; - content: ""; - border: 0.13em solid map-get($palette,white); - -webkit-transition: all .3s ease; - -o-transition: all .3s ease; - transition: all .3s ease; + content: ''; + border: 0.13em solid map-get($palette, white); + -webkit-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; overflow: hidden; border-left: 1px solid transparent; border-top: 1px solid transparent; @@ -28,16 +28,13 @@ $palette: ( margin-left: 9px; opacity: 1; } - } - - .signup-menu-link { color: map-get($palette, white) !important; } -.signin-menu-link{ +.signin-menu-link { color: map-get($palette, white); } @@ -45,12 +42,11 @@ $palette: ( On large screen */ @media (min-width: 992px) { - .signin-menu-link, .signup-menu-link { font-size: 15px; letter-spacing: 0; - border: 1px solid map-get($palette,white); + border: 1px solid map-get($palette, white); border-radius: 2px; padding-top: 8px; padding-bottom: 8px; @@ -63,12 +59,12 @@ On large screen border-color: map-get($palette, white); } .user-profile-dropdown .dropdown-menu.show::after { - border-color: transparent transparent map-get($palette,white); + border-color: transparent transparent map-get($palette, white); border-image: none; border-style: solid; border-width: 8px; bottom: 100%; - content: " "; + content: ' '; height: 0; pointer-events: none; position: absolute; @@ -76,5 +72,4 @@ On large screen left: 55%; margin-left: 0; } - } diff --git a/frontend/app/styles/admin/_badge-management.scss b/frontend/app/styles/admin/_badge-management.scss index 9dcf95f5e..9cf47aaec 100644 --- a/frontend/app/styles/admin/_badge-management.scss +++ b/frontend/app/styles/admin/_badge-management.scss @@ -1,8 +1,8 @@ $palette: ( - primary: #F57010, + primary: #f57010, black: #000000, - boxShadow: #0A4B6D2E, - gray30: #3F484D, + boxShadow: #0a4b6d2e, + gray30: #3f484d, ); .badges .badges-homepage { @@ -33,7 +33,7 @@ $palette: ( font-size: 14px; circle { - fill: #F5D4BD; + fill: #f5d4bd; } path { @@ -46,7 +46,8 @@ $palette: ( padding-top: 10px; } - .badges-earned-total-card, .badges-total-card { + .badges-earned-total-card, + .badges-total-card { .badges-total-count { font-size: 26px; } @@ -68,7 +69,6 @@ $palette: ( .badges .badges-homepage { .badges-section .submenu-section { - .dropdown-toggle { color: map-get($palette, black); } @@ -106,11 +106,9 @@ $palette: ( } } } - } } - .badges .badges-manage-page { .title { font-size: 16px; @@ -133,7 +131,8 @@ $palette: ( padding-bottom: 20px; } - .badge-card, .create-badge-card { + .badge-card, + .create-badge-card { border: 1px solid rgba(201, 202, 203, 1); box-shadow: 0px 3px 16px rgba(10, 75, 109, 0.18); min-height: 165px; @@ -279,10 +278,8 @@ $palette: ( .badges .badges-manage-page { .creation-form { - - .badge-icon-card { - box-shadow: 0 3px 16px rgba(10, 75, 109, 0.18);; + box-shadow: 0 3px 16px rgba(10, 75, 109, 0.18); min-width: 400px; min-height: 194px; @@ -327,9 +324,9 @@ $palette: ( } input::placeholder, - select:invalid, { + select:invalid { font-size: 13px; - color: #A6ADB4; + color: #a6adb4; } } } diff --git a/frontend/app/styles/admin/_main-header.scss b/frontend/app/styles/admin/_main-header.scss index 3fd432b22..7a43a0a40 100644 --- a/frontend/app/styles/admin/_main-header.scss +++ b/frontend/app/styles/admin/_main-header.scss @@ -1,8 +1,8 @@ $palette: ( - gray30: #3F484D, - primary:#F57010, - red: #EA0606, - white: #FFFF + gray30: #3f484d, + primary: #f57010, + red: #ea0606, + white: #ffff, ); .admin-main-header { .notifications-dropdown { @@ -20,9 +20,8 @@ $palette: ( .nav-link .count { position: absolute; - background-color: map-get($palette,red); - color: map-get($palette,white); + background-color: map-get($palette, red); + color: map-get($palette, white); } } } - diff --git a/frontend/app/styles/admin/_side-nav.scss b/frontend/app/styles/admin/_side-nav.scss index 92e1d21a7..9879a8228 100644 --- a/frontend/app/styles/admin/_side-nav.scss +++ b/frontend/app/styles/admin/_side-nav.scss @@ -1,8 +1,8 @@ $palette: ( - primary: #F57010, - gray75:#EDF4F8, - gray45: #6E6E6E, - black: #000000 + primary: #f57010, + gray75: #edf4f8, + gray45: #6e6e6e, + black: #000000, ); .sidenav { @@ -37,14 +37,14 @@ $palette: ( color: map-get($palette, gray45); font-weight: 400; white-space: nowrap; - padding: .75em .75em .75em 25px; + padding: 0.75em 0.75em 0.75em 25px; &.active { color: map-get($palette, black); font-weight: 500; svg path { - fill: map-get($palette, primary) + fill: map-get($palette, primary); } } } diff --git a/frontend/app/styles/admin/_survey-management.scss b/frontend/app/styles/admin/_survey-management.scss index 1c02f873b..5abc868df 100644 --- a/frontend/app/styles/admin/_survey-management.scss +++ b/frontend/app/styles/admin/_survey-management.scss @@ -1,13 +1,13 @@ $palette: ( - primary: #F57010, + primary: #f57010, black: #000000, - boxShadow: #0A4B6D2E, - gray30: #3F484D, - gainsboro: #EAE7E7, - white: #FFFF, - jungleGreen: #32A583, + boxShadow: #0a4b6d2e, + gray30: #3f484d, + gainsboro: #eae7e7, + white: #ffff, + jungleGreen: #32a583, carrotOrange: rgba(245, 112, 16, 0.39), - grayChateau: #A6ADB4 + grayChateau: #a6adb4, ); .survey-manage-page { @@ -54,7 +54,7 @@ $palette: ( } .horizontal-divider { - margin-top: .5rem; + margin-top: 0.5rem; } .surveys-list { @@ -64,7 +64,8 @@ $palette: ( grid-template-columns: 255px 255px 255px 255px; padding-bottom: 20px; - .create-card, .survey-card { + .create-card, + .survey-card { border: 1px solid rgba(201, 202, 203, 1); box-shadow: 0px 3px 16px rgba(10, 75, 109, 0.18); min-height: 165px; @@ -121,7 +122,6 @@ $palette: ( &.pending { background-color: map-get($palette, carrotOrange); - } } } @@ -173,7 +173,6 @@ $palette: ( } } } - } .surveys-list { @@ -199,7 +198,7 @@ $palette: ( input::placeholder, textarea::placeholder, - select:invalid, { + select:invalid { font-size: 13px; color: map-get($palette, grayChateau); } @@ -240,7 +239,6 @@ $palette: ( } } - @media (min-width: 768px) { .survey-manage-page { .survey-form { diff --git a/frontend/app/styles/admin/admin.scss b/frontend/app/styles/admin/admin.scss index daf7ca5fb..e614aac64 100644 --- a/frontend/app/styles/admin/admin.scss +++ b/frontend/app/styles/admin/admin.scss @@ -1,5 +1,5 @@ -$palette:( -gray85: #FAFDFF +$palette: ( + gray85: #fafdff, ); .admin-base { padding: 0; @@ -7,10 +7,10 @@ gray85: #FAFDFF height: 100%; min-height: 100vh; - .main-content-wrapper{ + .main-content-wrapper { height: 100%; width: 100%; - background-color: map-get($palette,gray85); + background-color: map-get($palette, gray85); overflow: auto; min-height: 100vh; } @@ -21,7 +21,7 @@ gray85: #FAFDFF .search-input { border-radius: 18px; - padding: .275rem .45rem; + padding: 0.275rem 0.45rem; height: initial; &::placeholder { @@ -46,8 +46,8 @@ gray85: #FAFDFF } } - .custom-form{ - .help-button{ + .custom-form { + .help-button { position: relative; top: 0; cursor: pointer; @@ -55,12 +55,11 @@ gray85: #FAFDFF } } - -.admin-base{ - @import "side-nav"; - @import "main-header"; - @import "badge-management"; - @import "user-management"; - @import "content-approval"; - @import "_survey-management"; +.admin-base { + @import 'side-nav'; + @import 'main-header'; + @import 'badge-management'; + @import 'user-management'; + @import 'content-approval'; + @import '_survey-management'; } diff --git a/frontend/app/styles/app.scss b/frontend/app/styles/app.scss index bbd3c8c2f..962a2b8de 100644 --- a/frontend/app/styles/app.scss +++ b/frontend/app/styles/app.scss @@ -6,21 +6,21 @@ @import 'home'; @import 'nav'; @import 'search'; -@import "warning-component"; +@import 'warning-component'; @import 'common/typography'; @import 'profile'; -@import "cms-desktop"; -@import "common/utils"; +@import 'cms-desktop'; +@import 'common/utils'; @import 'toc-component'; -@import "ember-modal-dialog/ember-modal-structure"; -@import "ember-modal-dialog/ember-modal-appearance"; +@import 'ember-modal-dialog/ember-modal-structure'; +@import 'ember-modal-dialog/ember-modal-appearance'; @import url('https://rsms.me/inter/inter.css'); html { font-family: 'Inter', sans-serif; height: 100%; - scroll-behavior:smooth; + scroll-behavior: smooth; } @supports (font-variation-settings: normal) { @@ -43,7 +43,6 @@ body { body { font-family: 'Inter var', sans-serif; - } .kkl-cover { @@ -57,8 +56,7 @@ body { .kkl-jumbo-text { color: white; width: 100%; - -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, - from(rgba(252, 113, 0, 0)), to(rgba(0, 0, 0, 1))); + -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(252, 113, 0, 0)), to(rgba(0, 0, 0, 1))); } body { @@ -66,7 +64,6 @@ body { /* Margin bottom by footer height */ } - .replaced { visibility: hidden; position: relative; @@ -83,7 +80,7 @@ body { padding: 4px; display: block; left: 0; - content: "Check it out"; + content: 'Check it out'; } .add-pre { @@ -138,7 +135,7 @@ pre { } .drop-area { - background-color: #EBF0F2; + background-color: #ebf0f2; height: 300px; } @@ -155,30 +152,29 @@ footer .row { //@import "ember-bootstrap/bootstrap"; //@import "ember-power-select"; - -@import "reaction-buttons"; -@import "h5p-list-item"; -@import "single-chapter"; -@import "comments.scss"; -@import "tags-list"; -@import "custom-checkbox"; -@import "h5p-editor"; -@import "loader"; -@import "teach-login"; -@import "forgot-password"; -@import "login"; -@import "signup"; -@import "rating-and-review"; -@import "teacher/teacher"; -@import "h5p-player"; -@import "notifications-dropdown"; -@import "user-acc-dropdown"; -@import "custom-search-icon"; -@import "dropdown"; -@import "badge-modal"; -@import "edit-profile"; -@import "survey"; -@import "course"; -@import "popular-cards"; - -@import "admin/admin"; +@import 'reaction-buttons'; +@import 'h5p-list-item'; +@import 'single-chapter'; +@import 'comments.scss'; +@import 'tags-list'; +@import 'custom-checkbox'; +@import 'h5p-editor'; +@import 'loader'; +@import 'teach-login'; +@import 'forgot-password'; +@import 'login'; +@import 'signup'; +@import 'rating-and-review'; +@import 'teacher/teacher'; +@import 'h5p-player'; +@import 'notifications-dropdown'; +@import 'user-acc-dropdown'; +@import 'custom-search-icon'; +@import 'dropdown'; +@import 'badge-modal'; +@import 'edit-profile'; +@import 'survey'; +@import 'course'; +@import 'popular-cards'; + +@import 'admin/admin'; diff --git a/frontend/app/styles/bs4.scss b/frontend/app/styles/bs4.scss index 69d501e84..2b0d05b82 100644 --- a/frontend/app/styles/bs4.scss +++ b/frontend/app/styles/bs4.scss @@ -3,17 +3,16 @@ * **/ - // Brand Colors $blue: #007bff; $indigo: #6610f2; $purple: #670098; $pink: #e83e8c; $red: #dc3545; -$orange: #FF6700; -$yellow: #FFD300; +$orange: #ff6700; +$yellow: #ffd300; $green: #00aa83; -$teal: #FFEBAF; +$teal: #ffebaf; $cyan: #17a2b8; $white: #fff; $gray-100: #f8f9fa; @@ -26,17 +25,68 @@ $gray-700: #495057; $gray-800: #343a40; $gray-900: #212529; $black: #000; -$grays: (100: $gray-100, 200: $gray-200, 300: $gray-300, 400: $gray-400, 500: $gray-500, 600: $gray-600, 700: $gray-700, 800: $gray-800, 900: $gray-900); -$theme-colors: (primary: $orange, secondary: $gray-600, success: $green, info: $cyan, warning: $yellow, danger: $red, light: $gray-100, dark: $gray-800); -$colors: (blue: $orange, indigo: $indigo, purple: $purple, pink: $pink, red: $red, orange: $orange, yellow: $yellow, green: $green, teal: $teal, cyan: $cyan, white: $white, gray: $gray-600, gray-dark: $gray-800); +$grays: ( + 100: $gray-100, + 200: $gray-200, + 300: $gray-300, + 400: $gray-400, + 500: $gray-500, + 600: $gray-600, + 700: $gray-700, + 800: $gray-800, + 900: $gray-900, +); +$theme-colors: ( + primary: $orange, + secondary: $gray-600, + success: $green, + info: $cyan, + warning: $yellow, + danger: $red, + light: $gray-100, + dark: $gray-800, +); +$colors: ( + blue: $orange, + indigo: $indigo, + purple: $purple, + pink: $pink, + red: $red, + orange: $orange, + yellow: $yellow, + green: $green, + teal: $teal, + cyan: $cyan, + white: $white, + gray: $gray-600, + gray-dark: $gray-800, +); $theme-color-interval: 8%; - // Spacing $spacer: 1rem; -$spacers: (0: 0, 1: ($spacer * 0.25), 2: ($spacer * 0.5), 3: $spacer, 4: ($spacer * 1.5), 5: ($spacer * 3)); -$sizes: (25: 25%, 50: 50%, 75: 75%, 100: 100%); - +$spacers: ( + 0: 0, + 1: ( + $spacer * 0.25, + ), + 2: ( + $spacer * 0.5, + ), + 3: $spacer, + 4: ( + $spacer * 1.5, + ), + 5: ( + $spacer * 3, + ), +); +$sizes: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100%, +); // Options $enable-rounded: true; @@ -47,26 +97,33 @@ $enable-hover-media-query: false; $enable-grid-classes: true; $enable-print-styles: true; - // Body $body-bg: $white; $body-color: $gray-900; - // Links $link-color: theme-color('primary'); $link-decoration: none; $link-hover-color: darken($link-color, 15%); $link-hover-decoration: underline; - // Grid -$grid-breakpoints: (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px); -$container-max-widths: (sm: 540px, md: 720px, lg: 960px, xl: 1140px); +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px, +); +$container-max-widths: ( + sm: 540px, + md: 720px, + lg: 960px, + xl: 1140px, +); $grid-columns: 12; $grid-gutter-width: 30px; - // Components $line-height-lg: 1.5; $line-height-sm: 1.5; @@ -81,21 +138,9 @@ $transition-base: all 0.2s ease-in-out; $transition-fade: opacity 0.15s linear; $transition-collapse: height 0.35s ease; - // Fonts -$font-family-sans-serif: -apple-system, -BlinkMacSystemFont, -'Segoe UI', -Roboto, -'Helvetica Neue', -Arial, -sans-serif; -$font-family-monospace: Menlo, -Monaco, -Consolas, -'Liberation Mono', -'Courier New', -monospace; +$font-family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; +$font-family-monospace: Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; $font-family-base: $font-family-sans-serif; $font-size-base: 1rem; $font-size-lg: 1.25rem; @@ -139,7 +184,6 @@ $nested-kbd-font-weight: $font-weight-bold; $list-inline-padding: 5px; $mark-bg: #fcf8e3; - // Buttons $input-btn-padding-y: 0.5rem; $input-btn-padding-x: 0.75rem; @@ -151,8 +195,7 @@ $input-btn-padding-y-lg: 0.5rem; $input-btn-padding-x-lg: 1rem; $input-btn-line-height-lg: 1.5; $btn-font-weight: $font-weight-normal; -$btn-box-shadow: inset 0 1px 0 rgba($white, 0.15), -0 1px 1px rgba($black, 0.075); +$btn-box-shadow: inset 0 1px 0 rgba($white, 0.15), 0 1px 1px rgba($black, 0.075); $btn-focus-box-shadow: 0 0 0 3px rgba(theme-color('primary'), 0.25); $btn-active-box-shadow: inset 0 3px 5px rgba($black, 0.125); $btn-link-disabled-color: $gray-600; @@ -162,7 +205,6 @@ $btn-border-radius-lg: $border-radius-lg; $btn-border-radius-sm: $border-radius-sm; $btn-transition: all 0.15s ease-in-out; - // Forms $input-bg: $white; $input-disabled-bg: $gray-200; @@ -175,19 +217,17 @@ $input-border-radius-lg: $border-radius-lg; $input-border-radius-sm: $border-radius-sm; $input-focus-bg: $input-bg; $input-focus-border-color: lighten(theme-color('primary'), 25%); -$input-focus-box-shadow: $input-box-shadow, -$btn-focus-box-shadow; +$input-focus-box-shadow: $input-box-shadow, $btn-focus-box-shadow; $input-focus-color: $input-color; $input-placeholder-color: $gray-600; $input-height-border: $input-btn-border-width * 2; -$input-height-inner: ($font-size-base * $input-btn-line-height)+($input-btn-padding-y * 2); +$input-height-inner: ($font-size-base * $input-btn-line-height)+ ($input-btn-padding-y * 2); $input-height: calc(#{$input-height-inner} + #{$input-height-border}); -$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm)+($input-btn-padding-y-sm * 2); +$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm)+ ($input-btn-padding-y-sm * 2); $input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}); -$input-height-inner-lg: ($font-size-sm * $input-btn-line-height-lg)+($input-btn-padding-y-lg * 2); +$input-height-inner-lg: ($font-size-sm * $input-btn-line-height-lg)+ ($input-btn-padding-y-lg * 2); $input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}); -$input-transition: border-color ease-in-out 0.15s, -box-shadow ease-in-out 0.15s; +$input-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; $form-text-margin-top: 0.25rem; $form-check-margin-bottom: 0.5rem; $form-check-input-gutter: 1.25rem; @@ -209,8 +249,7 @@ $custom-control-description-disabled-color: $gray-600; $custom-control-indicator-checked-color: $white; $custom-control-indicator-checked-bg: theme-color('primary'); $custom-control-indicator-checked-box-shadow: none; -$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, -0 0 0 3px theme-color('primary'); +$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, 0 0 0 3px theme-color('primary'); $custom-control-indicator-active-color: $white; $custom-control-indicator-active-bg: lighten(theme-color('primary'), 35%); $custom-control-indicator-active-box-shadow: none; @@ -235,13 +274,12 @@ $custom-select-border-color: $input-border-color; $custom-select-border-radius: $border-radius; $custom-select-focus-border-color: lighten(theme-color('primary'), 25%); $custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, 0.075), -0 0 5px rgba($custom-select-focus-border-color, 0.5); + 0 0 5px rgba($custom-select-focus-border-color, 0.5); $custom-select-font-size-sm: 75%; $custom-select-height-sm: $input-height-sm; $custom-file-height: 2.5rem; $custom-file-width: 14rem; -$custom-file-focus-box-shadow: 0 0 0 0.075rem $white, -0 0 0 0.2rem theme-color('primary'); +$custom-file-focus-box-shadow: 0 0 0 0.075rem $white, 0 0 0 0.2rem theme-color('primary'); $custom-file-padding-y: 1rem; $custom-file-padding-x: 0.5rem; $custom-file-line-height: 1.5; @@ -253,11 +291,17 @@ $custom-file-border-radius: $border-radius; $custom-file-box-shadow: inset 0 0.2rem 0.4rem rgba($black, 0.05); $custom-file-button-color: $custom-file-color; $custom-file-button-bg: $gray-200; -$custom-file-text: (placeholder: (en: 'Choose file...'), button-label: (en: 'Browse')); +$custom-file-text: ( + placeholder: ( + en: 'Choose file...', + ), + button-label: ( + en: 'Browse', + ), +); $form-feedback-valid-color: theme-color('success'); $form-feedback-invalid-color: theme-color('danger'); - // Dropdown $dropdown-min-width: 10rem; $dropdown-padding-y: 0.5rem; @@ -277,7 +321,6 @@ $dropdown-item-padding-y: 0.25rem; $dropdown-item-padding-x: 1.5rem; $dropdown-header-color: $gray-600; - // Navs $nav-link-padding-y: 0.5rem; $nav-link-padding-x: 1rem; @@ -293,7 +336,6 @@ $nav-pills-border-radius: $border-radius; $nav-pills-link-active-color: $component-active-color; $nav-pills-link-active-bg: $component-active-bg; - // Navbar $navbar-padding-y: ($spacer / 2); $navbar-padding-x: $spacer; @@ -316,7 +358,6 @@ $navbar-light-active-color: rgba($black, 0.9); $navbar-light-disabled-color: rgba($black, 0.3); $navbar-light-toggler-border-color: rgba($black, 0.1); - // Tables $table-cell-padding: 0.75rem; $table-cell-padding-sm: 0.3rem; @@ -334,7 +375,6 @@ $table-inverse-hover-bg: rgba($white, 0.075); $table-inverse-border-color: lighten($gray-900, 7.5%); $table-inverse-color: $body-bg; - // Z Index $zindex-dropdown: 1000; $zindex-sticky: 1020; @@ -344,7 +384,6 @@ $zindex-modal: 1050; $zindex-popover: 1060; $zindex-tooltip: 1070; - // Pagination $pagination-padding-y: 0.5rem; $pagination-padding-x: 0.75rem; @@ -367,12 +406,10 @@ $pagination-disabled-color: $gray-600; $pagination-disabled-bg: $white; $pagination-disabled-border-color: #ddd; - // Jumbotron $jumbotron-padding: 2rem; $jumbotron-bg: $gray-200; - // Cards $card-spacer-y: 0.75rem; $card-spacer-x: 1.25rem; @@ -388,7 +425,6 @@ $card-columns-count: 3; $card-columns-gap: 1.25rem; $card-columns-margin: $card-spacer-y; - // Tooltip $tooltip-max-width: 200px; $tooltip-color: $white; @@ -401,7 +437,6 @@ $tooltip-arrow-width: 5px; $tooltip-arrow-height: 5px; $tooltip-arrow-color: $tooltip-bg; - // Popovers $popover-inner-padding: 1px; $popover-bg: $white; @@ -422,7 +457,6 @@ $popover-arrow-color: $popover-bg; $popover-arrow-outer-width: ($popover-arrow-width + 1px); $popover-arrow-outer-color: fade-in($popover-border-color, 0.05); - // Badges $badge-color: $white; $badge-font-size: 75%; @@ -432,7 +466,6 @@ $badge-padding-x: 0.4em; $badge-pill-padding-x: 0.6em; $badge-pill-border-radius: 10rem; - // Modals $modal-inner-padding: 15px; $modal-dialog-margin: 10px; @@ -455,7 +488,6 @@ $modal-md: 500px; $modal-sm: 300px; $modal-transition: transform 0.3s ease-out; - // Alerts $alert-padding-y: 0.75rem; $alert-padding-x: 1.25rem; @@ -464,7 +496,6 @@ $alert-border-radius: $border-radius; $alert-link-font-weight: $font-weight-bold; $alert-border-width: $border-width; - // Progress bars $progress-height: 1rem; $progress-font-size: 0.75rem; @@ -476,7 +507,6 @@ $progress-bar-bg: theme-color('primary'); $progress-bar-animation-timing: 1s linear infinite; $progress-bar-transition: width 0.6s ease; - // List group $list-group-bg: $white; $list-group-border-color: rgba($black, 0.125); @@ -495,7 +525,6 @@ $list-group-action-hover-color: $list-group-action-color; $list-group-action-active-color: $body-color; $list-group-action-active-bg: $gray-200; - // Image thumbnails $thumbnail-padding: 0.25rem; $thumbnail-bg: $body-bg; @@ -505,12 +534,10 @@ $thumbnail-border-radius: $border-radius; $thumbnail-box-shadow: 0 1px 2px rgba($black, 0.075); $thumbnail-transition: all 0.2s ease-in-out; - // Figures $figure-caption-font-size: 90%; $figure-caption-color: $gray-600; - // Breadcrumbs $breadcrumb-padding-y: 0.75rem; $breadcrumb-padding-x: 1rem; @@ -520,7 +547,6 @@ $breadcrumb-divider-color: $gray-600; $breadcrumb-active-color: $gray-600; $breadcrumb-divider: '/'; - // Carousel $carousel-control-color: $white; $carousel-control-width: 15%; @@ -534,14 +560,12 @@ $carousel-caption-color: $white; $carousel-control-icon-width: 20px; $carousel-transition: transform 0.6s ease; - // Close $close-font-size: $font-size-base * 1.5; $close-font-weight: $font-weight-bold; $close-color: $black; $close-text-shadow: 0 1px 0 $white; - // Code $code-font-size: 90%; $code-padding-y: 0.2rem; @@ -553,7 +577,6 @@ $kbd-bg: $gray-900; $pre-color: $gray-900; $pre-scrollable-max-height: 340px; - // Options $enable-rounded: true; $enable-shadows: false; @@ -563,7 +586,6 @@ $enable-hover-media-query: false; $enable-grid-classes: true; $enable-print-styles: true; - // My Variables $primary: $orange; -$secondary: $blue; \ No newline at end of file +$secondary: $blue; diff --git a/frontend/app/styles/cms-desktop.scss b/frontend/app/styles/cms-desktop.scss index f881275fa..41b3c642e 100644 --- a/frontend/app/styles/cms-desktop.scss +++ b/frontend/app/styles/cms-desktop.scss @@ -10,8 +10,6 @@ font-size: 12px; } - - } .flat-button { @@ -38,7 +36,6 @@ border-left: 6px solid $primary-purple; background-color: lightgrey; - } .card { @@ -52,9 +49,7 @@ h5 { align-self: center; - } - } .list-group-item:hover { @@ -71,4 +66,4 @@ .cms-column-action { align-self: center; font-size: 12px; -} \ No newline at end of file +} diff --git a/frontend/app/styles/comments.scss b/frontend/app/styles/comments.scss index 97f7cd511..1b1fde06b 100644 --- a/frontend/app/styles/comments.scss +++ b/frontend/app/styles/comments.scss @@ -29,8 +29,8 @@ form { } .replies { - border-left: 2px solid transparentize(#F57010, 0.6); - background-color: transparentize(#F57010, 0.9); + border-left: 2px solid transparentize(#f57010, 0.6); + background-color: transparentize(#f57010, 0.9); width: 100%; padding: 3px; } @@ -46,4 +46,4 @@ form { outline: none; background-color: inherit; } -} \ No newline at end of file +} diff --git a/frontend/app/styles/common/colors.scss b/frontend/app/styles/common/colors.scss index ecd0ee71f..d3b3df45b 100644 --- a/frontend/app/styles/common/colors.scss +++ b/frontend/app/styles/common/colors.scss @@ -1,4 +1,4 @@ $base-green: #32a583; $base-red: #ff6b6b; $dark-blue: #ff6b6b; -$primary: #ff6b6b; \ No newline at end of file +$primary: #ff6b6b; diff --git a/frontend/app/styles/common/forms.scss b/frontend/app/styles/common/forms.scss index 2497745f5..9ee872eb2 100644 --- a/frontend/app/styles/common/forms.scss +++ b/frontend/app/styles/common/forms.scss @@ -1,4 +1,4 @@ -@import "variables"; +@import 'variables'; .auth-btn { background-color: bisque; @@ -7,7 +7,7 @@ .auth-title { font-size: 30px; color: black; - background-color: #FAF1DB; + background-color: #faf1db; text-align: left; font-weight: bold; padding: 0 1.6rem 0.8rem 1.6rem; @@ -23,14 +23,14 @@ } input:focus { - border-color: coral + border-color: coral; } } .auth-title { font-size: 30px; color: white; - background-color: #FAF1DB; + background-color: #faf1db; text-align: left; font-weight: bold; padding: 0 1.6rem 0.8rem 1.6rem; @@ -39,7 +39,6 @@ .sort-list { display: flex; flex-direction: row; - } .form-actions { @@ -52,9 +51,9 @@ } // .invalid-feedback { - // font-size: 0.2rem; - // color: red; - // } +// font-size: 0.2rem; +// color: red; +// } label { color: grey; @@ -62,15 +61,8 @@ label { font-weight: 600; } - - - - - .form { - padding: 2rem; - } .form-title { @@ -84,14 +76,12 @@ label { padding: 0 1.6rem 0.8rem 1.6rem; } - .submit { color: red; padding-top: 1em; width: 100%; } - .form-text { color: #afafaf; font-size: 0.9rem; @@ -112,7 +102,6 @@ slightly narrower for forms .form-container { .form-primary-fields { margin-bottom: 2rem; - } .cms-button { @@ -132,7 +121,6 @@ slightly narrower for forms .form-container { &:hover { color: white; text-decoration: none; - background-color: #00AA83; + background-color: #00aa83; } - -} \ No newline at end of file +} diff --git a/frontend/app/styles/common/typography.scss b/frontend/app/styles/common/typography.scss index ec7ce85c9..6a67df87e 100644 --- a/frontend/app/styles/common/typography.scss +++ b/frontend/app/styles/common/typography.scss @@ -1,4 +1,4 @@ .underlined-link { - color: inherit; - text-decoration: underline; -} \ No newline at end of file + color: inherit; + text-decoration: underline; +} diff --git a/frontend/app/styles/common/variables.scss b/frontend/app/styles/common/variables.scss index 2f02a2a8a..2fc5367d0 100644 --- a/frontend/app/styles/common/variables.scss +++ b/frontend/app/styles/common/variables.scss @@ -1,8 +1,6 @@ @import url('https://fonts.googleapis.com/css?family=Karla&display=swap'); -$karla: 'Karla', -sans-serif; +$karla: 'Karla', sans-serif; $primary-purple: rgb(145, 12, 127); -$primary-dark:$primary-purple; -$font-family-form: 'Inter', -sans-serif; -$profile-image: '/public/assets/profile.svg' +$primary-dark: $primary-purple; +$font-family-form: 'Inter', sans-serif; +$profile-image: '/public/assets/profile.svg'; diff --git a/frontend/app/styles/forgot-password.scss b/frontend/app/styles/forgot-password.scss index 87689cb81..fda6657ee 100644 --- a/frontend/app/styles/forgot-password.scss +++ b/frontend/app/styles/forgot-password.scss @@ -16,7 +16,7 @@ margin-bottom: 1rem; padding: 0.5rem; height: 30%; - background-color: lighten(#F57010, 10%); + background-color: lighten(#f57010, 10%); background-image: url('/images/logo-background.png'); color: white; display: flex; diff --git a/frontend/app/styles/h5p-list-item.scss b/frontend/app/styles/h5p-list-item.scss index 9950005b2..0530879ea 100644 --- a/frontend/app/styles/h5p-list-item.scss +++ b/frontend/app/styles/h5p-list-item.scss @@ -1,13 +1,13 @@ $palette: ( - primary: #F57010, - white: #FFFFFF, - gray30: #3F484D, + primary: #f57010, + white: #ffffff, + gray30: #3f484d, gray45: rgb(94, 108, 115), gray60: #829199, - gray75: #B0BABF, - gray95: #EBF0F2, + gray75: #b0babf, + gray95: #ebf0f2, black: #000000, - mystic: #ebf0f2 + mystic: #ebf0f2, ); .chapter-thumbnail { @@ -20,7 +20,8 @@ $palette: ( fill: map-get($palette, primary); } - .watch-icon, .eye-icon { + .watch-icon, + .eye-icon { fill: map-get($palette, gray75); } @@ -59,13 +60,13 @@ $palette: ( font-size: 12px; .tag { display: inline-block; - padding: 0.3em .6em; + padding: 0.3em 0.6em; font-size: 90%; text-align: center; white-space: nowrap; background-color: map-get($palette, mystic); color: map-get($palette, gray45); border-radius: 4px; - margin:0 0 5px 0; + margin: 0 0 5px 0; } } diff --git a/frontend/app/styles/header.scss b/frontend/app/styles/header.scss index 66de29f14..b5300842d 100644 --- a/frontend/app/styles/header.scss +++ b/frontend/app/styles/header.scss @@ -11,11 +11,9 @@ html { body { background-color: #f8f9fa; margin: 0 auto; - } .btn-link { - background: none !important; border: none; @@ -27,7 +25,6 @@ body { display: block; -webkit-transition: 0.3s; transition: 0.3s; - } .closebtn { @@ -51,8 +48,6 @@ body { font-size: 12px; text-decoration: none; } - - } .main-header { @@ -73,4 +68,4 @@ body { font-size: 2rem; color: $primary; } -} \ No newline at end of file +} diff --git a/frontend/app/styles/home.scss b/frontend/app/styles/home.scss index 663e222d4..7599883cc 100644 --- a/frontend/app/styles/home.scss +++ b/frontend/app/styles/home.scss @@ -1,7 +1,6 @@ #home { //@include pages-main; - h3 { font-size: 24px; color: $dark-blue; @@ -9,9 +8,7 @@ p { font-size: 13px; - } - } .heading { @@ -20,15 +17,15 @@ .ember-notify { &.alert { - &.alert-success , - &.alert-success .close{ + &.alert-success, + &.alert-success .close { color: white; background-color: #4caf50; font-weight: 400; opacity: 1; } - &.alert-danger , - &.alert-danger .close{ + &.alert-danger, + &.alert-danger .close { color: white; background-color: #f44336; font-weight: 400; @@ -37,10 +34,7 @@ } } - .course-item { - - margin-top: 1em; display: flex; justify-content: flex-start; @@ -48,7 +42,6 @@ hr { margin: 0px; padding: 0px; - } .course-image { @@ -93,20 +86,20 @@ } } -.chapters-infinity-loader{ +.chapters-infinity-loader { .infinity-loader { padding-bottom: 50px; .loading-indicator { text-align: center; } - .records-loaded-indicator{ + .records-loaded-indicator { display: none; } - &.reached-infinity{ - .loading-indicator{ + &.reached-infinity { + .loading-indicator { display: none; } - .records-loaded-indicator{ + .records-loaded-indicator { display: block; } } diff --git a/frontend/app/styles/landing.scss b/frontend/app/styles/landing.scss index dda3bb24f..a080d495b 100644 --- a/frontend/app/styles/landing.scss +++ b/frontend/app/styles/landing.scss @@ -13,7 +13,6 @@ color: white; } - } .centered { @@ -23,7 +22,6 @@ } .page-content { - padding-top: 70px; } @@ -38,31 +36,27 @@ background-color: white; color: black; text-decoration: none; - } } .learn { @include btnx; - background-color: #F57010; + background-color: #f57010; border: 0; - } .teach { @include btnx; - background-color: #32A583; + background-color: #32a583; border: 0; - } .buildr { @include btnx; - background-color: #FFCF00; + background-color: #ffcf00; border: 0; - } .login { @@ -74,8 +68,6 @@ border-color: white; } - - @mixin header { position: fixed; width: 100%; @@ -96,13 +88,13 @@ .orange-header { @include header; - background-color: #F57010; + background-color: #f57010; } .auth-header { @include header; - background-color: #FAF1DB; + background-color: #faf1db; } .yellow-header { @@ -121,7 +113,6 @@ .bg-green { background-color: #32a583; color: white; - } .bg-yellow { @@ -130,16 +121,16 @@ } .bg-orange { - background-color: #F57010; + background-color: #f57010; color: white; } .bg-red { - background-color: #DE4830; + background-color: #de4830; color: white; } .bg-purple { background-color: $primary-purple; color: white; -} \ No newline at end of file +} diff --git a/frontend/app/styles/login.scss b/frontend/app/styles/login.scss index 62a39e6ce..11338d581 100644 --- a/frontend/app/styles/login.scss +++ b/frontend/app/styles/login.scss @@ -17,7 +17,7 @@ margin-bottom: 1rem; padding: 0.5rem; height: 150px; - background-color: lighten(#F57010, 10%); + background-color: lighten(#f57010, 10%); background-image: url('/images/logo-background.png'); display: flex; align-items: center; @@ -27,14 +27,14 @@ .line-text { width: 100%; text-align: center; - border-bottom: 1px solid #B0BABF; + border-bottom: 1px solid #b0babf; line-height: 0.1em; margin: 47px 0 40px; } .line-text span { background: #fff; - color: #3F484D; + color: #3f484d; padding: 0 10px; } @@ -43,10 +43,10 @@ } .btn-facebook { - background-color: #1877F2; + background-color: #1877f2; } .btn-linkedIn { - background-color: #0077B5; + background-color: #0077b5; } -} \ No newline at end of file +} diff --git a/frontend/app/styles/nav.scss b/frontend/app/styles/nav.scss index 10c7d5cd7..20f9fa5c4 100644 --- a/frontend/app/styles/nav.scss +++ b/frontend/app/styles/nav.scss @@ -1,37 +1,36 @@ $palette: ( - primary: #F57010, - white: #FFFF, + primary: #f57010, + white: #ffff, darkCharcoal: rgba(87, 92, 88, 1), - teach: #32A583, - eucalyptus: #28A745, + teach: #32a583, + eucalyptus: #28a745, cardBoxShadow: rgba(0, 0, 0, 0.29), - gray30: #3F484D, - gray95: #EBF0F2, - aliceBlue: #F7FCFF, - bombay: #B2B4B6, - bonjour: #EAE7E7, + gray30: #3f484d, + gray95: #ebf0f2, + aliceBlue: #f7fcff, + bombay: #b2b4b6, + bonjour: #eae7e7, black: #000000, - gallery: #F0F0F0, + gallery: #f0f0f0, ); .main-header { - .navbar-nav { .nav-link { - color: #FFFFFF; + color: #ffffff; &.active { - color: #FFFFFF; + color: #ffffff; font-weight: bold; } - &:hover, { - color: #FFFFFF; + &:hover { + color: #ffffff; } } .show > .nav-link { - color: #FFFFFF; + color: #ffffff; } } } @@ -43,22 +42,21 @@ $palette: ( margin-right: -1px !important; padding-right: 0; border: 0; - } .search-button { - background: #FAF1DB; + background: #faf1db; color: white; border-radius: 0; .search-icon { - color: white + color: white; } } } .navbar-toggler { - color: #FFFFFF; + color: #ffffff; border-color: transparent; transform: scaleX(-1); -webkit-transform: scaleX(-1); @@ -76,7 +74,7 @@ $palette: ( position: relative; &.active:after { - content: ""; + content: ''; position: absolute; bottom: 0; right: 0; @@ -94,12 +92,10 @@ $palette: ( } } - /** On large screen */ @media (min-width: 992px) { - .main-header { height: 60px; } diff --git a/frontend/app/styles/search.scss b/frontend/app/styles/search.scss index 366e6a4bd..c4e6a269f 100644 --- a/frontend/app/styles/search.scss +++ b/frontend/app/styles/search.scss @@ -9,7 +9,7 @@ white-space: normal; overflow-wrap: break-word; display: flex; - padding: .25rem 1rem; + padding: 0.25rem 1rem; } #myDropdown .dropdown-item:hover, @@ -46,11 +46,11 @@ .search-input:focus { flex: 1; background-image: url(/images/icons/search.svg); - padding-right: calc(1.5em + .75rem); + padding-right: calc(1.5em + 0.75rem); background-repeat: no-repeat; - background-position: right calc(.375em + .1875rem) center; + background-position: right calc(0.375em + 0.1875rem) center; } .search-thumbnail { margin-right: 10px; -} \ No newline at end of file +} diff --git a/frontend/app/styles/signup.scss b/frontend/app/styles/signup.scss index 2a236c9f0..cb02950fd 100644 --- a/frontend/app/styles/signup.scss +++ b/frontend/app/styles/signup.scss @@ -18,7 +18,7 @@ header { padding: 0.5rem; height: 150px; - background-color: lighten(#F57010, 10%); + background-color: lighten(#f57010, 10%); background-image: url('/images/logo-background.png'); color: white; display: flex; @@ -28,14 +28,14 @@ .line-text { width: 100%; text-align: center; - border-bottom: 1px solid #B0BABF; + border-bottom: 1px solid #b0babf; line-height: 0.1em; margin: 47px 0 40px; } .line-text span { background: #fff; - color: #3F484D; + color: #3f484d; padding: 0 10px; } @@ -44,10 +44,10 @@ } .btn-facebook { - background-color: #1877F2; + background-color: #1877f2; } .btn-linkedIn { - background-color: #0077B5; + background-color: #0077b5; } -} \ No newline at end of file +} diff --git a/frontend/app/styles/single-chapter.scss b/frontend/app/styles/single-chapter.scss index 8f9be8186..1ccf5c66c 100644 --- a/frontend/app/styles/single-chapter.scss +++ b/frontend/app/styles/single-chapter.scss @@ -1,8 +1,8 @@ $palette: ( - primary: #F57010, - white: #FFF, + primary: #f57010, + white: #fff, gray60: #829199, - lighterPrimary: #FDE9DA + lighterPrimary: #fde9da, ); .breadcrumbs { color: #829199; @@ -72,12 +72,11 @@ $palette: ( } #facebook-share-icon { - background-color: #4267B2; + background-color: #4267b2; } - #twitter-share-icon { - background-color: #1DA1F2; + background-color: #1da1f2; } #email-share-icon { @@ -85,7 +84,7 @@ $palette: ( } #reddit-share-icon { - background-color: #FF4500; + background-color: #ff4500; } #facebook-share-icon svg path, @@ -95,24 +94,25 @@ $palette: ( } .share-modal-container { - background: #222; - color: white; - margin-left: -25px; - margin-top: 10px; - width: 300px; - border-radius: 0; + background: #222; + color: white; + margin-left: -25px; + margin-top: 10px; + width: 300px; + border-radius: 0; } .reaction-feedback-popover { - background-color: map-get($palette,lighterPrimary); + background-color: map-get($palette, lighterPrimary); - .arrow:before,.arrow:after { - border-bottom-color: map-get($palette,lighterPrimary); + .arrow:before, + .arrow:after { + border-bottom-color: map-get($palette, lighterPrimary); } .btn-close { padding: 0; - background-color: map-get($palette,white); + background-color: map-get($palette, white); border-radius: 50%; outline: 0; border-color: transparent; @@ -122,16 +122,16 @@ $palette: ( display: flex; justify-content: center; align-items: center; - color: map-get($palette,gray60); + color: map-get($palette, gray60); } - .title{ + .title { font-weight: 600; font-size: 16px; - color: map-get($palette,primary); + color: map-get($palette, primary); } } -.comment-section{ +.comment-section { padding-bottom: 8em; } diff --git a/frontend/app/styles/teach-login.scss b/frontend/app/styles/teach-login.scss index 302d7920f..ce05f4c99 100644 --- a/frontend/app/styles/teach-login.scss +++ b/frontend/app/styles/teach-login.scss @@ -5,14 +5,9 @@ body { #teach-login { .hero { background: rgb(2, 252, 178); - background: linear-gradient( - 90deg, - rgba(2, 252, 178, 1) 0%, - rgba(194, 199, 217, 1) 46%, - rgba(255, 255, 255, 1) 97% - ); + background: linear-gradient(90deg, rgba(2, 252, 178, 1) 0%, rgba(194, 199, 217, 1) 46%, rgba(255, 255, 255, 1) 97%); padding: 5% 15%; - fill: #F57010; + fill: #f57010; h1 { color: white; diff --git a/frontend/app/styles/teacher/content-creation.scss b/frontend/app/styles/teacher/content-creation.scss index 744cf0314..43196b01d 100644 --- a/frontend/app/styles/teacher/content-creation.scss +++ b/frontend/app/styles/teacher/content-creation.scss @@ -1,10 +1,10 @@ $palette: ( - white: #FFFF, - warning: #FFD300, + white: #ffff, + warning: #ffd300, dark: #343a40, grey: grey, - gray95: #EBF0F2, - primary: #F57010, + gray95: #ebf0f2, + primary: #f57010, ); .content-creation-section { @@ -36,12 +36,10 @@ $palette: ( } } } - } //ratings and review section .review-question-section { - .review-question-option { .btn { min-height: 34px; @@ -49,7 +47,8 @@ $palette: ( box-shadow: none; display: flex; - &:hover, &:active { + &:hover, + &:active { outline: none; box-shadow: none; color: map-get($palette, dark); @@ -57,7 +56,6 @@ $palette: ( } &.btn-warning { - &:hover, &:focus { color: map-get($palette, dark); @@ -66,10 +64,9 @@ $palette: ( } } } - } -.tags-selection-section{ +.tags-selection-section { .tag-action-button { padding: 2px 4px; background-color: map-get($palette, gray95); @@ -77,7 +74,9 @@ $palette: ( color: map-get($palette, gray45); font-size: 12px; - &:active, &.active, &:focus { + &:active, + &.active, + &:focus { outline: none; background-color: map-get($palette, primary); color: map-get($palette, white); diff --git a/frontend/app/styles/teacher/teacher.scss b/frontend/app/styles/teacher/teacher.scss index 875b7b62c..3e68f04e9 100644 --- a/frontend/app/styles/teacher/teacher.scss +++ b/frontend/app/styles/teacher/teacher.scss @@ -1,3 +1,3 @@ -.teach-layout{ - @import "content-creation"; +.teach-layout { + @import 'content-creation'; } diff --git a/frontend/app/styles/toc-component.scss b/frontend/app/styles/toc-component.scss index e6ee577cf..b3ea3fdfb 100644 --- a/frontend/app/styles/toc-component.scss +++ b/frontend/app/styles/toc-component.scss @@ -1,19 +1,17 @@ ul#toc { - list-style-type: none; - display: flex; - justify-content: center; + list-style-type: none; + display: flex; + justify-content: center; - li { - display: inline; - float: left; - margin: 10px; - padding-bottom: 5px; - border-bottom: 4px solid #DAE2E6; - white-space: nowrap; - &.active { - border-bottom: 4px solid #07B788; - } + li { + display: inline; + float: left; + margin: 10px; + padding-bottom: 5px; + border-bottom: 4px solid #dae2e6; + white-space: nowrap; + &.active { + border-bottom: 4px solid #07b788; } + } } - - diff --git a/frontend/app/styles/warning-component.scss b/frontend/app/styles/warning-component.scss index 6565eca94..a01c202c1 100644 --- a/frontend/app/styles/warning-component.scss +++ b/frontend/app/styles/warning-component.scss @@ -4,4 +4,4 @@ span { font-size: 250px; } -} \ No newline at end of file +} From b5c73d98b7ad53d4d05de313bba1322362cc2b39 Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Sat, 25 Sep 2021 07:59:18 +0300 Subject: [PATCH 14/25] add badge unlocked component --- .../app/components/badge/badge-unlocked.hbs | 48 ++++++++++++ .../app/components/badge/badge-unlocked.js | 31 ++++++++ .../app/components/survey/prompt-popup.js | 16 ++-- frontend/app/styles/_badge-unlocked.scss | 77 +++++++++++++++++++ frontend/app/styles/app.scss | 1 + frontend/app/templates/application.hbs | 4 +- .../components/badge/achievement-test.js | 26 +++++++ frontend/translations/badge/en-us.yaml | 5 ++ frontend/translations/badge/sw-ke.yaml | 3 + server/event-handlers/socket-events.js | 4 + 10 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 frontend/app/components/badge/badge-unlocked.hbs create mode 100644 frontend/app/components/badge/badge-unlocked.js create mode 100644 frontend/app/styles/_badge-unlocked.scss create mode 100644 frontend/tests/integration/components/badge/achievement-test.js create mode 100644 frontend/translations/badge/en-us.yaml create mode 100644 frontend/translations/badge/sw-ke.yaml diff --git a/frontend/app/components/badge/badge-unlocked.hbs b/frontend/app/components/badge/badge-unlocked.hbs new file mode 100644 index 000000000..5cbf54921 --- /dev/null +++ b/frontend/app/components/badge/badge-unlocked.hbs @@ -0,0 +1,48 @@ + + +
+ {{t 'badge.unlocked.title'}} +
+
+ {{t 'badge.unlocked.points' numOfPoints=this.badge.points}} +
+
+ {{#if this.badge.iconUrl}} + + {{else}} + {{svg-jar 'badge' width='100' height='100'}} + {{/if}} +
+
+ {{this.badge.name}} +
+
+ {{this.badge.description}} +
+
+ + {{t 'badge.unlocked.publish'}} + + + {{t 'badge.unlocked.share'}} + +
+
+ + + {{t 'badge_popup.ok'}} + + +
+ \ No newline at end of file diff --git a/frontend/app/components/badge/badge-unlocked.js b/frontend/app/components/badge/badge-unlocked.js new file mode 100644 index 000000000..8b63e4928 --- /dev/null +++ b/frontend/app/components/badge/badge-unlocked.js @@ -0,0 +1,31 @@ +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { events } from '../../utils/socket-events'; + +export default class BadgeUnlockedComponent extends Component { + @service socket; + @service store; + @service router; + + @tracked showBadgeUnlockedModal = false; + @tracked badge; + + @action + hideBadgeUnlockedModal() { + this.showBadgeUnlockedModal = false; + } + + @action + notificationEventIntercept() { + this.socket.socket.on(events.user.notification.created, (notification) => { + setTimeout(async () => { + if (!this.showBadgeUnlockedModal) { + this.badge = await this.store.find('badge', notification.itemId); + this.showBadgeUnlockedModal = true; + } + }, 3000); + }); + } +} diff --git a/frontend/app/components/survey/prompt-popup.js b/frontend/app/components/survey/prompt-popup.js index 5848cbbda..dfaa6eea6 100644 --- a/frontend/app/components/survey/prompt-popup.js +++ b/frontend/app/components/survey/prompt-popup.js @@ -19,14 +19,14 @@ export default class SurveyPromptPopupComponent extends Component { @action notificationEventIntercept() { - this.socket.socket.on(events.user.notification.created, (notification) => { - setTimeout(async () => { - if (!this.showSurveyFillPrompt) { - this.survey = await this.store.find('survey', notification.itemId); - this.showSurveyFillPrompt = true; - } - }, 3000); - }); + // this.socket.socket.on(events.user.notification.created, (notification) => { + // setTimeout(async () => { + // if (!this.showSurveyFillPrompt) { + // this.survey = await this.store.find('survey', notification.itemId); + // this.showSurveyFillPrompt = true; + // } + // }, 3000); + // }); } @action diff --git a/frontend/app/styles/_badge-unlocked.scss b/frontend/app/styles/_badge-unlocked.scss new file mode 100644 index 000000000..19d1ee40c --- /dev/null +++ b/frontend/app/styles/_badge-unlocked.scss @@ -0,0 +1,77 @@ +$palette: ( + primary: #f57010, + studio: #5a47ad, + windsor: #4e0b80, + white: #ffff, + teach: #32a583, +); + +.badge-unlocked { + .modal-dialog { + max-width: 400px; + } + + .modal-body { + background-color: map-get($palette, studio); + color: map-get($palette, white); + + .title { + font-size: 24px; + line-height: 15px; + font-weight: 500; + padding-top: 24px; + } + + .name { + font-weight: bold; + font-size: 25px; + padding-bottom: 15px; + padding-top: 30px; + } + + .badge-icon-container { + max-width: 150px; + max-height: 210px; + margin: 0 auto; + padding: 10px; + + .badge-icon { + width: 100%; + height: 100%; + padding: 10px; + padding-top: 50px; + } + } + + .points { + width: max-content; + background-color: map-get($palette, teach); + padding: 2px 10px; + font-size: 20px; + border-radius: 4px; + margin: 25px auto 14px; + font-weight: 500; + } + + .actions { + button { + background-color: map-get($palette, primary); + color: map-get($palette, white); + } + } + } + + .modal-footer { + background-color: map-get($palette, studio); + border: none; + + button { + width: 100%; + background-color: map-get($palette, windsor); + padding-bottom: 10px; + padding-top: 11px; + font-size: 20px; + color: map-get($palette, white); + } + } +} diff --git a/frontend/app/styles/app.scss b/frontend/app/styles/app.scss index 962a2b8de..35b235166 100644 --- a/frontend/app/styles/app.scss +++ b/frontend/app/styles/app.scss @@ -172,6 +172,7 @@ footer .row { @import 'custom-search-icon'; @import 'dropdown'; @import 'badge-modal'; +@import 'badge-unlocked'; @import 'edit-profile'; @import 'survey'; @import 'course'; diff --git a/frontend/app/templates/application.hbs b/frontend/app/templates/application.hbs index f43822044..35b90a23e 100644 --- a/frontend/app/templates/application.hbs +++ b/frontend/app/templates/application.hbs @@ -18,8 +18,8 @@ {{!-- --}} - - + + {{else }} {{outlet}} diff --git a/frontend/tests/integration/components/badge/achievement-test.js b/frontend/tests/integration/components/badge/achievement-test.js new file mode 100644 index 000000000..4d00087c7 --- /dev/null +++ b/frontend/tests/integration/components/badge/achievement-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | badge/achievement', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs``); + + assert.equal(this.element.textContent.trim(), ''); + + // Template block usage: + await render(hbs` + + template block text + + `); + + assert.equal(this.element.textContent.trim(), 'template block text'); + }); +}); diff --git a/frontend/translations/badge/en-us.yaml b/frontend/translations/badge/en-us.yaml new file mode 100644 index 000000000..9d2982821 --- /dev/null +++ b/frontend/translations/badge/en-us.yaml @@ -0,0 +1,5 @@ +unlocked: + title: Yeey! you unlocked a badge! + points: "{numOfPoints} points earned" + publish: Publish + share: Share \ No newline at end of file diff --git a/frontend/translations/badge/sw-ke.yaml b/frontend/translations/badge/sw-ke.yaml new file mode 100644 index 000000000..89019ecb9 --- /dev/null +++ b/frontend/translations/badge/sw-ke.yaml @@ -0,0 +1,3 @@ +unlocked: + title: Yeey! you unlocked a badge! + points: "{numOfPoints} points earned" \ No newline at end of file diff --git a/server/event-handlers/socket-events.js b/server/event-handlers/socket-events.js index da9862069..95c6bc25f 100644 --- a/server/event-handlers/socket-events.js +++ b/server/event-handlers/socket-events.js @@ -123,5 +123,9 @@ module.exports = (io) => { socketEventEmitter.on(events.user.comment.created, (payload) => { io.to(socketChannel.learners).emit(events.user.comment.created, payload); }); + + socketEventEmitter.on(events.user.badge.unlocked, (payload) => { + io.to(socketChannel.learners).emit(events.user.badge.unlocked, payload); + }); return io; }; \ No newline at end of file From 7751307d19c3614d407faa2f6b486a89b925ce68 Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Mon, 27 Sep 2021 11:56:17 +0300 Subject: [PATCH 15/25] Emit socket event when user unlocks a badge --- server/models/user-badge.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/models/user-badge.js b/server/models/user-badge.js index 422e7c4ef..25d298ae9 100644 --- a/server/models/user-badge.js +++ b/server/models/user-badge.js @@ -1,5 +1,7 @@ const Model = require('./_model'); const knex = require('../db/db'); +const {socketEventEmitter} = require('../utils/event-emitter'); +const {events} = require('../utils/socket-events'); class UserBadge extends Model { static get tableName() { @@ -38,6 +40,11 @@ class UserBadge extends Model { }, }; } + + async $afterInsert(){ + await super.$afterInsert(); + socketEventEmitter.emit(events.user.badge.unlocked, this); + } } UserBadge.knex(knex); From 4dccf87b3b408573413bb6d417a5fa655d541a9f Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Mon, 27 Sep 2021 12:37:29 +0300 Subject: [PATCH 16/25] listen to badge unlocked event in frontend --- frontend/app/components/badge/badge-unlocked.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/badge/badge-unlocked.js b/frontend/app/components/badge/badge-unlocked.js index 8b63e4928..b4ebc3d8a 100644 --- a/frontend/app/components/badge/badge-unlocked.js +++ b/frontend/app/components/badge/badge-unlocked.js @@ -19,10 +19,10 @@ export default class BadgeUnlockedComponent extends Component { @action notificationEventIntercept() { - this.socket.socket.on(events.user.notification.created, (notification) => { + this.socket.socket.on(events.user.badge.unlocked, (notification) => { setTimeout(async () => { if (!this.showBadgeUnlockedModal) { - this.badge = await this.store.find('badge', notification.itemId); + this.badge = await this.store.find('badge', notification.badgeId); this.showBadgeUnlockedModal = true; } }, 3000); From c60109ad21d400341e7b81053e84e9ad5d11f572 Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Mon, 27 Sep 2021 12:38:48 +0300 Subject: [PATCH 17/25] fix copy for when user earns a badge --- frontend/translations/badge/en-us.yaml | 2 +- frontend/translations/badge/sw-ke.yaml | 2 +- server/event-handlers/badge-awarding.js | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/translations/badge/en-us.yaml b/frontend/translations/badge/en-us.yaml index 9d2982821..16ee19425 100644 --- a/frontend/translations/badge/en-us.yaml +++ b/frontend/translations/badge/en-us.yaml @@ -1,5 +1,5 @@ unlocked: - title: Yeey! you unlocked a badge! + title: Yeey! you earned a badge! points: "{numOfPoints} points earned" publish: Publish share: Share \ No newline at end of file diff --git a/frontend/translations/badge/sw-ke.yaml b/frontend/translations/badge/sw-ke.yaml index 89019ecb9..a0665b421 100644 --- a/frontend/translations/badge/sw-ke.yaml +++ b/frontend/translations/badge/sw-ke.yaml @@ -1,3 +1,3 @@ unlocked: - title: Yeey! you unlocked a badge! + title: Yeey! you earned a badge! points: "{numOfPoints} points earned" \ No newline at end of file diff --git a/server/event-handlers/badge-awarding.js b/server/event-handlers/badge-awarding.js index a2ba40d0c..c8a5a7ae8 100644 --- a/server/event-handlers/badge-awarding.js +++ b/server/event-handlers/badge-awarding.js @@ -54,7 +54,7 @@ module.exports = () => { /** 3) Create a notification for the chapter author **/ await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -96,7 +96,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -135,7 +135,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -176,7 +176,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -216,7 +216,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -253,7 +253,7 @@ module.exports = () => { for (let i = 0; i < badges.length; i++) { await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -294,7 +294,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, @@ -335,7 +335,7 @@ module.exports = () => { //add a notification await NotificationModel.query() .insert({ - title: 'You have unlocked a new badge', + title: 'You have earned a new badge', body: badges[i].name, itemId: badges[i].id, eventType: notificationTypes.badge.unlocked, From 4f0c601849450261d98bbdf73daaae9c0bfa5063 Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Fri, 1 Oct 2021 15:30:41 +0300 Subject: [PATCH 18/25] leaderboard api --- server/models/user.js | 19 ++++++++++++++++--- server/routes/leaderboard.js | 31 +++++++++++++++++++++++++++++++ server/server.js | 2 ++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 server/routes/leaderboard.js diff --git a/server/models/user.js b/server/models/user.js index 94d767202..4abd82b82 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -169,9 +169,22 @@ class User extends Model { to: 'courses.creatorId' } }, - - - }; + badgesAwarded: { + relation: Model.ManyToManyRelation, + modelClass: __dirname + '/badges', + join: { + from: 'users.id', + through: { + from: 'user_badges.user_id', + to: 'user_badges.badge_id', + extra: { + user_badge_id: 'id' + } + }, + to: 'badges.id' + } + } + } } static get modifiers() { diff --git a/server/routes/leaderboard.js b/server/routes/leaderboard.js new file mode 100644 index 000000000..e48407cf7 --- /dev/null +++ b/server/routes/leaderboard.js @@ -0,0 +1,31 @@ +const Router = require('koa-router'); +const { requireAuth, grantAccess } = require('../middleware/permController'); +const User = require('../models/user'); + +const router = new Router({ + prefix: '/leaderboard' +}); + + +/** + * @api {get} /api/v1/groups GET all user groups + * @apiName Get user groups + * @apiGroup Group + * @apiPermission authenticated user[moderator/admin/superadmin] + * @apiVersion 0.4.0 + * + * @apiHeader {String} Authorization Bearer << JWT here>> + * + */ + +router.get('/', requireAuth, async ctx => { + const users = await User.query() + .withGraphJoined('badgesAwarded') + // .whereNotNull(); + + ctx.status = 200; + ctx.body = { users }; +}); + + +module.exports = router.routes(); diff --git a/server/server.js b/server/server.js index 557413a4d..9c62db4a7 100644 --- a/server/server.js +++ b/server/server.js @@ -93,6 +93,8 @@ router.use(jwt.authenticate, require('./routes/tag-followers')); router.use(jwt.authenticate, require('./routes/course-enrollments')); +router.use(jwt.authenticate, require('./routes/leaderboard')); + router.use(require('./routes/search')); From f21d626dd6594fcbb66f9c680392272e8da6fa7d Mon Sep 17 00:00:00 2001 From: murage Date: Fri, 1 Oct 2021 16:21:05 +0300 Subject: [PATCH 19/25] fix: column reference "metadata" is ambiguous on joined query --- server/models/user.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/models/user.js b/server/models/user.js index 4abd82b82..cff759cc9 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -184,19 +184,19 @@ class User extends Model { to: 'badges.id' } } - } + }; } static get modifiers() { return { selectNameAndId: (builder) => { - builder.select('users.id', 'name'); + builder.select('users.id', 'users.name'); }, selectNameAndProfile: (builder) => { - builder.select('username', 'profileUri'); + builder.select('users.username', 'users.profileUri'); }, - selectBasicInfo: (query) => { - query.select('users.id', 'username', 'metadata', 'profileUri','email'); + selectBasicInfo: (query) => { // metadata is required to build correct user's name + query.select('users.id', 'users.username', 'users.metadata', 'users.profileUri','users.email'); }, }; } From 42686c3a8ddef67df5fefe68ec62294261f1eece Mon Sep 17 00:00:00 2001 From: murage Date: Fri, 1 Oct 2021 16:25:08 +0300 Subject: [PATCH 20/25] feat: use right join to only return users with badges --- server/routes/leaderboard.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/routes/leaderboard.js b/server/routes/leaderboard.js index e48407cf7..13eac7f47 100644 --- a/server/routes/leaderboard.js +++ b/server/routes/leaderboard.js @@ -1,5 +1,5 @@ const Router = require('koa-router'); -const { requireAuth, grantAccess } = require('../middleware/permController'); +const {requireAuth, grantAccess} = require('../middleware/permController'); const User = require('../models/user'); const router = new Router({ @@ -20,11 +20,10 @@ const router = new Router({ router.get('/', requireAuth, async ctx => { const users = await User.query() - .withGraphJoined('badgesAwarded') - // .whereNotNull(); + .withGraphJoined('badgesAwarded', {joinOperation: 'rightJoin'}); ctx.status = 200; - ctx.body = { users }; + ctx.body = {users}; }); From 5dd4fc2a8a1f68e78cbd3059adc98d5e7534e1a9 Mon Sep 17 00:00:00 2001 From: murage Date: Fri, 1 Oct 2021 16:25:43 +0300 Subject: [PATCH 21/25] feat: reduce the amount of user info returned --- server/routes/leaderboard.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/routes/leaderboard.js b/server/routes/leaderboard.js index 13eac7f47..3b5db205d 100644 --- a/server/routes/leaderboard.js +++ b/server/routes/leaderboard.js @@ -20,7 +20,9 @@ const router = new Router({ router.get('/', requireAuth, async ctx => { const users = await User.query() - .withGraphJoined('badgesAwarded', {joinOperation: 'rightJoin'}); + .withGraphJoined('badgesAwarded', {joinOperation: 'rightJoin'}) + .modify('selectBasicInfo'); //select only user basic info + ctx.status = 200; ctx.body = {users}; From fafa37a7e17780f25ba9ac21537eb2bf87b703fb Mon Sep 17 00:00:00 2001 From: Brian Marete Date: Sun, 3 Oct 2021 09:55:22 +0300 Subject: [PATCH 22/25] Add link to leaderboard in main header --- frontend/app/components/main-header.hbs | 5 +++++ frontend/translations/en-us.yaml | 1 + frontend/translations/sw-ke.yaml | 1 + 3 files changed, 7 insertions(+) diff --git a/frontend/app/components/main-header.hbs b/frontend/app/components/main-header.hbs index 763ca3831..76a998f87 100644 --- a/frontend/app/components/main-header.hbs +++ b/frontend/app/components/main-header.hbs @@ -36,6 +36,11 @@ {{t "buttons.teach"}} +
-
-
-
-
- -
-
- - Jane Doe - - - Nairobi - -
-
-
- - 3,000 - - - {{t 'leaderboard.earnedPoints'}} - -
-
-
-
-
-
- -
-
- -
-
- -
-
- +5 -
-
- - {{t 'admin.users_and_badges.buttons.view_user'}} - -
-
+
-
-
+
+
-
+
9,000 @@ -101,7 +35,7 @@

-
+
Date: Wed, 16 Mar 2022 18:46:59 +0300 Subject: [PATCH 25/25] refactor: create top leader component --- .../app/components/leaderboard/top-leader.hbs | 41 +- .../components/leaderboard/top-leader.scss | 416 ++++++------------ frontend/app/styles/_leaderboard.scss | 161 +------ frontend/app/styles/app.scss | 18 +- frontend/app/templates/leaderboard.hbs | 148 +------ 5 files changed, 177 insertions(+), 607 deletions(-) diff --git a/frontend/app/components/leaderboard/top-leader.hbs b/frontend/app/components/leaderboard/top-leader.hbs index 67725cec1..2c0afc4e7 100644 --- a/frontend/app/components/leaderboard/top-leader.hbs +++ b/frontend/app/components/leaderboard/top-leader.hbs @@ -1,64 +1,67 @@ -
+
-
+
-
- +
+ Jane Doe - + Nairobi
-
- +
+ 3,000 - + {{t 'leaderboard.earnedPoints'}}

-
-
+
+
-
+
-
+
-
+
+5
- + {{!-- {{t 'admin.users_and_badges.buttons.view_user'}} - + --}}
+ {{#if (eq @position 'first')}} +
+ {{/if}}
\ No newline at end of file diff --git a/frontend/app/components/leaderboard/top-leader.scss b/frontend/app/components/leaderboard/top-leader.scss index 47ba14e62..4b7864122 100644 --- a/frontend/app/components/leaderboard/top-leader.scss +++ b/frontend/app/components/leaderboard/top-leader.scss @@ -5,331 +5,171 @@ $palette: ( teach: #32a583, eucalyptus: #28a745, ); -.leaderboard-wrapper { - position: relative; - .bg-panel { - width: 100%; - height: 135px; - background-color: map-get($palette, primary); - opacity: 0.22; - position: absolute; - z-index: 1; - top: 0; - margin-top: -30px; - } +.leader-card { + width: 422px; + height: 155px; + box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.29); + border-radius: 5px; + margin-left: 8px; + padding: 15px; - .leaderboard-main-container { - position: relative; - z-index: 10; - background-color: map-get($palette, white); - margin-top: 30px; - padding: 20px; + .image-container { + max-height: 52px; + max-width: 52px; + + img { + box-shadow: 0px 3px 6px rgb(0 0 0 / 7%); + border: 3px solid rgba(255, 255, 255, 1); + } } - .leaderboard-main-container { - .title { + .details { + padding-left: 8px; + + .name { font-size: 19px; - font-weight: 700; color: map-get($palette, darkCharcoal); - padding-left: 10px; - padding-bottom: 12px; + font-weight: 500; } - .sub-title { - font-size: 19px; - font-weight: 500; + .location { + font-size: 15px; color: map-get($palette, darkCharcoal); - padding-left: 50px; } } - .top-leaders { - padding-bottom: 25px; - - .leader-card { - width: 422px; - height: 155px; - box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.29); - border-radius: 5px; - margin-left: 8px; - padding: 15px; - - .image-container { - max-height: 52px; - max-width: 52px; - - img { - box-shadow: 0px 3px 6px rgb(0 0 0 / 7%); - border: 3px solid rgba(255, 255, 255, 1); - } - } - - .details { - padding-left: 8px; - - .name { - font-size: 19px; - color: map-get($palette, darkCharcoal); - font-weight: 500; - } - - .location { - font-size: 15px; - color: map-get($palette, darkCharcoal); - } - } - - .points { - color: map-get($palette, eucalyptus); - font-weight: 700; - font-size: 19px; - } - - .points-title { - font-size: 15px; - color: map-get($palette, darkCharcoal); - } - } - - .leader-card { - .badges-list { - display: flex; - position: relative; - - .badge-icon-container { - width: 30px; - height: 30px; - position: absolute; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - align-items: center; - justify-content: center; - border-radius: 50%; - background-color: white; - box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05); - border: 3px solid rgba(255, 255, 255, 1); - font-size: 11px; - font-weight: 700; - - .badge-icon { - width: 100%; - height: 100%; - } - - &:nth-child(2) { - margin-left: 20px; - } + .points { + color: map-get($palette, eucalyptus); + font-weight: 700; + font-size: 19px; + } - &:nth-child(3) { - margin-left: 40px; - } + .points-title { + font-size: 15px; + color: map-get($palette, darkCharcoal); + } +} - &:nth-child(4) { - margin-left: 60px; - } - } - } - } +.leader-card { + .badges-list { + display: flex; + position: relative; - .leader-card.first-winner { - height: 180px; - background-repeat: no-repeat; - background-position: 0% 0%; - background-origin: padding-box; - background-image: linear-gradient( - 119deg, - rgba(126, 87, 194, 1) 0%, - rgba(171, 71, 188, 1) 100% - ); - background-color: transparent; - background-clip: padding-box; + .badge-icon-container { + width: 30px; + height: 30px; + position: absolute; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-items: center; + justify-content: center; + border-radius: 50%; + background-color: white; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05); + border: 3px solid rgba(255, 255, 255, 1); + font-size: 11px; + font-weight: 700; - .image-container { - max-height: 62px; - max-width: 62px; + .badge-icon { + width: 100%; + height: 100%; } - .name, - .location, - .points, - .points-title { - color: map-get($palette, white); + &:nth-child(2) { + margin-left: 20px; } - .bottom { - padding-bottom: 10px; - padding-top: 10px; + &:nth-child(3) { + margin-left: 40px; } - .view-profile-btn { - background-color: map-get($palette, white); - border-color: map-get($palette, white); - color: map-get($palette, darkCharcoal); + &:nth-child(4) { + margin-left: 60px; } } } +} - .top-leaders { - .first-winner { - position: relative; - - .confetti-one { - position: absolute; - background-image: url('/images/confetti.svg'); - width: 70%; - height: 55px; - background-size: cover; - top: -40px; - left: -30px; - background-repeat: no-repeat; - z-index: -1; - } +.leader-card.first { + height: 180px; + background-repeat: no-repeat; + background-position: 0% 0%; + background-origin: padding-box; + background-image: linear-gradient( + 119deg, + rgba(126, 87, 194, 1) 0%, + rgba(171, 71, 188, 1) 100% + ); + background-color: transparent; + background-clip: padding-box; - .confetti-two { - position: absolute; - background-image: url('/images/confetti-1.svg'); - width: 70%; - height: 55px; - background-size: cover; - top: -40px; - right: -60px; - background-repeat: no-repeat; - z-index: -1; - } - } + .image-container { + max-height: 62px; + max-width: 62px; } - .leaderboard-table { - border-collapse: separate; - border-spacing: 0 10px; - - thead td { - font-size: 16px; - font-weight: 500; - border: none; - color: map-get($palette, darkCharcoal); - - &:first-of-type { - padding-right: 0; - } - - &:nth-of-type(2) { - padding-left: 25px; - } - } - - tbody { - tr { - margin-bottom: 10px; - box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.06); - border-radius: 5px; - background-color: map-get($palette, white); - } - - td { - font-size: 14px; - color: map-get($palette, gray30); - vertical-align: middle; - border: none; - - &:first-of-type { - padding-right: 0; - width: 10px; - } - } - - td.position span { - height: 23px; - width: 23px; - background-color: lighten(map-get($palette, teach), 25%); - display: flex; - border-radius: 50%; - align-items: center; - justify-content: center; - } - - .details { - padding-left: 15px; - - .name { - font-size: 16px; - color: map-get($palette, darkCharcoal); - font-weight: 600; - } - - .location { - color: map-get($palette, luckyGrey); - font-size: 16px; - } - } - } - - td.points { - font-size: 16px; - font-weight: 500; - } + .name, + .location, + .points, + .points-title { + color: map-get($palette, white); + } - td.badges-container { - .badges { - display: flex; - flex-direction: row; - align-content: center; - justify-content: flex-start; - align-items: center; + .bottom { + padding-bottom: 10px; + padding-top: 10px; + } - .extra-badges-total { - font-size: 16px; - background-color: #3f484d5c; - width: 34px; - height: 34px; - color: #ffffff; + .view-profile-btn { + background-color: map-get($palette, white); + border-color: map-get($palette, white); + color: map-get($palette, darkCharcoal); + } +} - display: flex; - border-radius: 100%; - justify-content: center; - align-content: center; - flex-direction: column; - align-items: center; - } +.first { + position: relative; - .mini-badge-container { - width: 50px; - height: 65px; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-content: center; - justify-content: center; - box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.08); - border: 0.5px solid rgba(86, 16, 245, 0.11); - margin-right: 9px; - padding: 4px; + .confetti-one { + position: absolute; + background-image: url('/images/confetti.svg'); + width: 70%; + height: 55px; + background-size: cover; + top: -40px; + left: -30px; + background-repeat: no-repeat; + z-index: -1; + } - .badge-icon { - width: 100%; - height: 100%; - } - } - } - } + .confetti-two { + position: absolute; + background-image: url('/images/confetti-1.svg'); + width: 70%; + height: 55px; + background-size: cover; + top: -40px; + right: -60px; + background-repeat: no-repeat; + z-index: -1; } +} - .image-container { - max-width: 40px; - max-height: 40px; +.image-container { + max-width: 40px; + max-height: 40px; - .user-profile-image { - width: 100%; - height: 100%; - border-radius: 50%; - } + .user-profile-image { + width: 100%; + height: 100%; + border-radius: 50%; } +} - .view-profile-btn { - font-size: 13px; - padding-bottom: 4px; - padding-top: 4px; - } +.view-profile-btn { + font-size: 13px; + padding-bottom: 4px; + padding-top: 4px; } diff --git a/frontend/app/styles/_leaderboard.scss b/frontend/app/styles/_leaderboard.scss index 85a5c383d..8405542a0 100644 --- a/frontend/app/styles/_leaderboard.scss +++ b/frontend/app/styles/_leaderboard.scss @@ -1,9 +1,9 @@ $palette: ( - primary: #F57010, - white: #FFFF, + primary: #f57010, + white: #ffff, darkCharcoal: rgba(87, 92, 88, 1), - teach: #32A583, - eucalyptus: #28A745, + teach: #32a583, + eucalyptus: #28a745, ); .leaderboard-wrapper { position: relative; @@ -46,154 +46,6 @@ $palette: ( .top-leaders { padding-bottom: 25px; - - .leader-card { - - width: 422px; - height: 155px; - box-shadow: 0px 3px 30px rgba(0, 0, 0, 0.29); - border-radius: 5px; - margin-left: 8px; - padding: 15px; - - - .image-container { - max-height: 52px; - max-width: 52px; - - img { - box-shadow: 0px 3px 6px rgb(0 0 0 / 7%); - border: 3px solid rgba(255, 255, 255, 1); - } - } - - .details { - padding-left: 8px; - - .name { - font-size: 19px; - color: map-get($palette, darkCharcoal); - font-weight: 500; - } - - .location { - font-size: 15px; - color: map-get($palette, darkCharcoal); - } - } - - .points { - color: map-get($palette, eucalyptus); - font-weight: 700; - font-size: 19px; - } - - .points-title { - font-size: 15px; - color: map-get($palette, darkCharcoal); - } - } - - .leader-card { - .badges-list { - display: flex; - position: relative; - - .badge-icon-container { - width: 30px; - height: 30px; - position: absolute; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - align-items: center; - justify-content: center; - border-radius: 50%; - background-color: white; - box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05); - border: 3px solid rgba(255, 255, 255, 1); - font-size: 11px; - font-weight: 700; - - .badge-icon { - width: 100%; - height: 100%; - } - - &:nth-child(2) { - margin-left: 20px; - } - - &:nth-child(3) { - margin-left: 40px; - } - - &:nth-child(4) { - margin-left: 60px; - } - } - } - } - - .leader-card.first-winner { - height: 180px; - background-repeat: no-repeat; - background-position: 0% 0%; - background-origin: padding-box; - background-image: linear-gradient(119deg, rgba(126, 87, 194, 1) 0%, rgba(171, 71, 188, 1) 100%); - background-color: transparent; - background-clip: padding-box; - - .image-container { - max-height: 62px; - max-width: 62px; - } - - .name, .location, .points, .points-title { - color: map-get($palette, white); - } - - .bottom { - padding-bottom: 10px; - padding-top: 10px; - } - - .view-profile-btn { - background-color: map-get($palette, white); - border-color: map-get($palette, white); - color: map-get($palette, darkCharcoal); - } - } - } - - .top-leaders { - .first-winner { - position: relative; - - .confetti-one { - position: absolute; - background-image: url("/images/confetti.svg"); - width: 70%; - height: 55px; - background-size: cover; - top: -40px; - left: -30px; - background-repeat: no-repeat; - z-index: -1; - } - - .confetti-two { - position: absolute; - background-image: url("/images/confetti-1.svg"); - width: 70%; - height: 55px; - background-size: cover; - top: -40px; - right: -60px; - background-repeat: no-repeat; - z-index: -1; - } - } } .leaderboard-table { @@ -276,10 +128,10 @@ $palette: ( .extra-badges-total { font-size: 16px; - background-color: #3F484D5C; + background-color: #3f484d5c; width: 34px; height: 34px; - color: #FFFFFF; + color: #ffffff; display: flex; border-radius: 100%; @@ -309,7 +161,6 @@ $palette: ( } } } - } .image-container { diff --git a/frontend/app/styles/app.scss b/frontend/app/styles/app.scss index e6718d583..f27313be1 100644 --- a/frontend/app/styles/app.scss +++ b/frontend/app/styles/app.scss @@ -57,7 +57,13 @@ body { .kkl-jumbo-text { color: white; width: 100%; - -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(252, 113, 0, 0)), to(rgba(0, 0, 0, 1))); + -webkit-mask-image: -webkit-gradient( + linear, + left top, + left bottom, + from(rgba(252, 113, 0, 0)), + to(rgba(0, 0, 0, 1)) + ); } body { @@ -89,11 +95,13 @@ body { } button.like { - filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%); + filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) + brightness(104%) contrast(97%); } button.dislike { - filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%); + filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) + brightness(104%) contrast(97%); } .icon { @@ -101,7 +109,8 @@ button.dislike { width: 70px; height: 40px; background-size: cover; - filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%); + filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) + brightness(104%) contrast(97%); } pre { @@ -177,5 +186,6 @@ footer .row { @import 'survey'; @import 'course'; @import 'popular-cards'; +@import 'leaderboard'; @import 'admin'; diff --git a/frontend/app/templates/leaderboard.hbs b/frontend/app/templates/leaderboard.hbs index a93ef28c4..32d9ecc89 100644 --- a/frontend/app/templates/leaderboard.hbs +++ b/frontend/app/templates/leaderboard.hbs @@ -5,143 +5,9 @@ {{t 'leaderboard.title'}}
- -
-
-
-
- -
-
- - Jane Doe - - - Nairobi - -
-
-
- - 9,000 - - - {{t 'leaderboard.earnedPoints'}} - -
-
-
-
-
-
- -
-
- -
-
- -
-
- +5 -
-
- - {{t 'admin.users_and_badges.buttons.view_user'}} - -
-
-
-
-
-
-
-
- -
-
- - Charles Kiprop - - - Mombasa - -
-
-
- - 2,000 - - - {{t 'leaderboard.earnedPoints'}} - -
-
-
-
-
-
- -
-
- -
-
- -
-
- +4 -
-
- - {{t 'admin.users_and_badges.buttons.view_user'}} - -
-
+ + +
{{t 'leaderboard.subtitle'}} @@ -210,12 +76,12 @@
- {{t 'admin.users_and_badges.buttons.view_user'}} - + --}} @@ -262,12 +128,12 @@
- {{t 'admin.users_and_badges.buttons.view_user'}} - + --}}