From 2ca98bbb10d6aee71ff41130a0122278b447fafe Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 17 Jun 2023 11:47:25 +0100 Subject: [PATCH] Show resource progress on best practices --- src/components/BestPracticeHint.astro | 14 +-- src/components/ResourceProgressStats.astro | 57 +++++++++++ src/components/RoadmapHint.astro | 30 +----- src/components/TopicDetail/TopicDetail.tsx | 2 + src/lib/resource-progress.ts | 106 ++++++++++++++------- 5 files changed, 137 insertions(+), 72 deletions(-) create mode 100644 src/components/ResourceProgressStats.astro diff --git a/src/components/BestPracticeHint.astro b/src/components/BestPracticeHint.astro index 484a7d582..fc0709fb9 100644 --- a/src/components/BestPracticeHint.astro +++ b/src/components/BestPracticeHint.astro @@ -1,20 +1,10 @@ --- +import ResourceProgressStats from './ResourceProgressStats.astro'; export interface Props { bestPracticeId: string; } ---
- - - - -

- Click the best practices for details and resources -

+
diff --git a/src/components/ResourceProgressStats.astro b/src/components/ResourceProgressStats.astro new file mode 100644 index 000000000..de0bc1813 --- /dev/null +++ b/src/components/ResourceProgressStats.astro @@ -0,0 +1,57 @@ +--- +export interface Props { + isSecondaryBanner?: boolean; +} + +const { isSecondaryBanner = false } = Astro.props; +--- + +
+

+ + 0% Done + + + 0 completed· + 0 in progress· + 0 skipped· + 0 Total +

+
+ +

+ + + 0% Done + + + + 0 of 0 Done + + +

diff --git a/src/components/RoadmapHint.astro b/src/components/RoadmapHint.astro index eca421903..0334705fd 100644 --- a/src/components/RoadmapHint.astro +++ b/src/components/RoadmapHint.astro @@ -2,6 +2,7 @@ import { ClearProgress } from './Activity/ClearProgress'; import AstroIcon from './AstroIcon.astro'; import Icon from './AstroIcon.astro'; +import ResourceProgressStats from './ResourceProgressStats.astro'; export interface Props { roadmapId: string; @@ -43,32 +44,5 @@ const roadmapTitle = ) } - -
-

- - 0% Done - - - 0 completed· - 0 learning· - 0 skipped· - 0 Total -

-
- - -

- Track your progress and learn about the topics by clicking the roadmap items. -

+ \ No newline at end of file diff --git a/src/components/TopicDetail/TopicDetail.tsx b/src/components/TopicDetail/TopicDetail.tsx index a07ddc881..10afd0574 100644 --- a/src/components/TopicDetail/TopicDetail.tsx +++ b/src/components/TopicDetail/TopicDetail.tsx @@ -10,6 +10,7 @@ import { httpGet } from '../../lib/http'; import { isLoggedIn } from '../../lib/jwt'; import { isTopicDone, + refreshProgressCounters, renderTopicProgress, ResourceType, updateResourceProgress as updateResourceProgressApi, @@ -87,6 +88,7 @@ export function TopicDetail() { topicId, done.includes(topicId) ? 'done' : 'pending' ); + refreshProgressCounters(); }) .catch((err) => { alert(err.message); diff --git a/src/lib/resource-progress.ts b/src/lib/resource-progress.ts index fe6c616f2..fe72cd1ec 100644 --- a/src/lib/resource-progress.ts +++ b/src/lib/resource-progress.ts @@ -67,7 +67,7 @@ export async function updateResourceProgress( resourceId, response.done, response.learning, - response.skipped, + response.skipped ); return response; @@ -76,7 +76,7 @@ export async function updateResourceProgress( export async function getResourceProgress( resourceType: 'roadmap' | 'best-practice', resourceId: string -): Promise<{ done: string[]; learning: string[], skipped: string[] }> { +): Promise<{ done: string[]; learning: string[]; skipped: string[] }> { // No need to load progress if user is not logged in if (!Cookies.get(TOKEN_COOKIE_NAME)) { return { @@ -129,7 +129,7 @@ async function loadFreshProgress( resourceId, response?.done || [], response?.learning || [], - response?.skipped || [], + response?.skipped || [] ); return response; @@ -140,7 +140,7 @@ export function setResourceProgress( resourceId: string, done: string[], learning: string[], - skipped: string [], + skipped: string[] ): void { localStorage.setItem( `${resourceType}-${resourceId}-progress`, @@ -209,8 +209,11 @@ export async function renderResourceProgress( resourceType: ResourceType, resourceId: string ) { - const { done = [], learning = [], skipped = [] } = - (await getResourceProgress(resourceType, resourceId)) || {}; + const { + done = [], + learning = [], + skipped = [], + } = (await getResourceProgress(resourceType, resourceId)) || {}; done.forEach((topicId) => { renderTopicProgress(topicId, 'done'); @@ -228,9 +231,11 @@ export async function renderResourceProgress( } export function refreshProgressCounters() { - const progressNumsContainer = document.getElementById('progress-nums-container'); - const progressNums = document.getElementById('progress-nums'); - if (!progressNumsContainer || !progressNums) { + const progressNumsContainers = document.querySelectorAll( + '[data-progress-nums-container]' + ); + const progressNums = document.querySelectorAll('[data-progress-nums]'); + if (progressNumsContainers.length === 0 || progressNums.length === 0) { return; } @@ -241,43 +246,80 @@ export function refreshProgressCounters() { const roadmapSwitchers = document.querySelectorAll( '[data-group-id^="json:"]' ).length; + const checkBoxes = document.querySelectorAll( + '[data-group-id^="check:"]' + ).length; + + const totalCheckBoxesDone = document.querySelectorAll( + '[data-group-id^="check:"].done' + ).length; + const totalCheckBoxesLearning = document.querySelectorAll( + '[data-group-id^="check:"].learning' + ).length; + const totalCheckBoxesSkipped = document.querySelectorAll( + '[data-group-id^="check:"].skipped' + ).length; + + const totalItems = + totalClickable - externalLinks - roadmapSwitchers - checkBoxes; - const totalItems = totalClickable - externalLinks - roadmapSwitchers; - const totalDone = document.querySelectorAll('.clickable-group.done').length; + const totalDone = + document.querySelectorAll('.clickable-group.done').length - + totalCheckBoxesDone; const totalLearning = document.querySelectorAll( '.clickable-group.learning' - ).length; + ).length - totalCheckBoxesLearning; const totalSkipped = document.querySelectorAll( '.clickable-group.skipped' - ).length; + ).length - totalCheckBoxesSkipped; - const doneCountEl = document.querySelector('.progress-done'); - if (doneCountEl) { - doneCountEl.innerHTML = `${totalDone}`; + const doneCountEls = document.querySelectorAll('[data-progress-done]'); + if (doneCountEls.length > 0) { + doneCountEls.forEach( + (doneCountEl) => (doneCountEl.innerHTML = `${totalDone}`) + ); } - const learningCountEl = document.querySelector('.progress-learning'); - if (learningCountEl) { - learningCountEl.innerHTML = `${totalLearning}`; + const learningCountEls = document.querySelectorAll( + '[data-progress-learning]' + ); + if (learningCountEls.length > 0) { + learningCountEls.forEach( + (learningCountEl) => (learningCountEl.innerHTML = `${totalLearning}`) + ); } - const skippedCountEl = document.querySelector('.progress-skipped'); - if (skippedCountEl) { - skippedCountEl.innerHTML = `${totalSkipped}`; + const skippedCountEls = document.querySelectorAll('[data-progress-skipped]'); + if (skippedCountEls.length > 0) { + skippedCountEls.forEach( + (skippedCountEl) => (skippedCountEl.innerHTML = `${totalSkipped}`) + ); } - const totalCountEl = document.querySelector('.progress-total'); - if (totalCountEl) { - totalCountEl.innerHTML = `${totalItems}`; + const totalCountEls = document.querySelectorAll('[data-progress-total]'); + if (totalCountEls.length > 0) { + totalCountEls.forEach( + (totalCountEl) => (totalCountEl.innerHTML = `${totalItems}`) + ); } - const progressPercentage = Math.round(((totalDone + totalSkipped) / totalItems) * 100); - const progressPercentageEl = document.querySelector('.progress-percentage'); - if (progressPercentageEl) { - progressPercentageEl.innerHTML = `${progressPercentage}`; + const progressPercentage = Math.round( + ((totalDone + totalSkipped) / totalItems) * 100 + ); + const progressPercentageEls = document.querySelectorAll( + '[data-progress-percentage]' + ); + if (progressPercentageEls.length > 0) { + progressPercentageEls.forEach( + (progressPercentageEl) => + (progressPercentageEl.innerHTML = `${progressPercentage}`) + ); } - progressNumsContainer.classList.remove('striped-loader') - progressNums.classList.remove('opacity-0'); - progressNums.classList.remove('opacity-100'); + progressNumsContainers.forEach((progressNumsContainer) => + progressNumsContainer.classList.remove('striped-loader') + ); + progressNums.forEach((progressNum) => { + progressNum.classList.remove('opacity-0'); + }); }