diff --git a/src/components/FrameRenderer/FrameRenderer.astro b/src/components/FrameRenderer/FrameRenderer.astro index 6c274de9a..d050be9c2 100644 --- a/src/components/FrameRenderer/FrameRenderer.astro +++ b/src/components/FrameRenderer/FrameRenderer.astro @@ -27,4 +27,4 @@ const { resourceId, resourceType, jsonUrl, dimensions = null } = Astro.props; - + diff --git a/src/components/FrameRenderer/renderer.js b/src/components/FrameRenderer/renderer.ts similarity index 66% rename from src/components/FrameRenderer/renderer.js rename to src/components/FrameRenderer/renderer.ts index a5e769f95..1719c4ba7 100644 --- a/src/components/FrameRenderer/renderer.js +++ b/src/components/FrameRenderer/renderer.ts @@ -1,9 +1,18 @@ import { wireframeJSONToSVG } from 'roadmap-renderer'; -import Cookies from 'js-cookie'; -import { TOKEN_COOKIE_NAME } from '../../lib/jwt.ts'; -import { httpGet } from '../../lib/http.ts'; +import { + renderResourceProgress, + ResourceType, +} from '../../lib/resource-progress'; export class Renderer { + resourceId: string; + resourceType: string; + jsonUrl: string; + loaderHTML: string | null; + + containerId: string; + loaderId: string; + constructor() { this.resourceId = ''; this.resourceType = ''; @@ -35,83 +44,64 @@ export class Renderer { } // Clone it so we can use it later - this.loaderHTML = this.loaderEl.innerHTML; + this.loaderHTML = this.loaderEl!.innerHTML; const dataset = this.containerEl.dataset; - this.resourceType = dataset.resourceType; - this.resourceId = dataset.resourceId; - this.jsonUrl = dataset.jsonUrl; + this.resourceType = dataset.resourceType!; + this.resourceId = dataset.resourceId!; + this.jsonUrl = dataset.jsonUrl!; return true; } - async loadProgress() { - const token = Cookies.get(TOKEN_COOKIE_NAME); - if (!token) { - return; - } - - const { response, error } = await httpGet( - `${import.meta.env.PUBLIC_API_URL}/v1-get-user-resource-progress`, - { - resourceId: this.resourceId, - resourceType: this.resourceType, - } - ); - - if (!response) { - console.error(error); - return; - } - - const { done } = response; - done.forEach((topic) => { - const topicEl = document.querySelector(`[data-group-id$="-${topic}"]`); - - if (topicEl) { - topicEl.classList.add('done'); - } - }); - } - /** * @param { string } jsonUrl * @returns {Promise} */ - jsonToSvg(jsonUrl) { + jsonToSvg(jsonUrl: string) { if (!jsonUrl) { console.error('jsonUrl not defined in frontmatter'); return null; } - this.containerEl.innerHTML = this.loaderHTML; - return Promise.all([ - fetch(jsonUrl) - .then((res) => { - return res.json(); - }) - .then((json) => { - return wireframeJSONToSVG(json, { - fontURL: '/fonts/balsamiq.woff2', - }); - }) - .then((svg) => { - this.containerEl.replaceChildren(svg); - }) - .catch((error) => { - const message = ` + if (!this.containerEl) { + return null; + } + + this.containerEl.innerHTML = this.loaderHTML!; + + return fetch(jsonUrl) + .then((res) => { + return res.json(); + }) + .then((json) => { + return wireframeJSONToSVG(json, { + fontURL: '/fonts/balsamiq.woff2', + }); + }) + .then((svg) => { + this.containerEl?.replaceChildren(svg); + }) + .then(() => { + return renderResourceProgress( + this.resourceType as ResourceType, + this.resourceId + ); + }) + .catch((error) => { + if (!this.containerEl) { + return; + } + + const message = ` There was an error.
Try loading the page again. or submit an issue on GitHub with following:

${error.message}
${error.stack} `; - - this.containerEl.innerHTML = `
${message}
`; - }), - - this.loadProgress(), - ]); + this.containerEl.innerHTML = `
${message}
`; + }); } onDOMLoaded() { @@ -129,16 +119,16 @@ export class Renderer { } } - switchRoadmap(newJsonUrl) { - const newJsonFileSlug = newJsonUrl.split('/').pop().replace('.json', ''); + switchRoadmap(newJsonUrl: string) { + const newJsonFileSlug = newJsonUrl.split('/').pop()?.replace('.json', ''); // Update the URL and attach the new roadmap type if (window?.history?.pushState) { - const url = new URL(window.location); + const url = new URL(window.location.href); const type = this.resourceType[0]; // r for roadmap, b for best-practices url.searchParams.delete(type); - url.searchParams.set(type, newJsonFileSlug); + url.searchParams.set(type, newJsonFileSlug!); window.history.pushState(null, '', url.toString()); } @@ -154,13 +144,13 @@ export class Renderer { label: `${newJsonFileSlug}`, }); - this.jsonToSvg(newJsonUrl).then(() => { - this.containerEl.setAttribute('style', ''); + this.jsonToSvg(newJsonUrl)?.then(() => { + this.containerEl?.setAttribute('style', ''); }); } - handleSvgClick(e) { - const targetGroup = e.target.closest('g') || {}; + handleSvgClick(e: any) { + const targetGroup = e.target?.closest('g') || {}; const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : ''; if (!groupId) { return; diff --git a/src/components/Setting/UpdatePasswordForm.tsx b/src/components/Setting/UpdatePasswordForm.tsx index 8d1d2af00..8608d145d 100644 --- a/src/components/Setting/UpdatePasswordForm.tsx +++ b/src/components/Setting/UpdatePasswordForm.tsx @@ -59,13 +59,6 @@ export default function UpdatePasswordForm() { ); if (error || !response) { - if (error?.status === 401) { - Cookies.remove(TOKEN_COOKIE_NAME); - window.location.reload(); - - return; - } - setIsLoading(false); setError(error?.message || 'Something went wrong'); diff --git a/src/components/Setting/UpdateProfileForm.tsx b/src/components/Setting/UpdateProfileForm.tsx index c9c4cabf5..2628d9787 100644 --- a/src/components/Setting/UpdateProfileForm.tsx +++ b/src/components/Setting/UpdateProfileForm.tsx @@ -52,13 +52,6 @@ export function UpdateProfileForm() { ); if (error || !response) { - if (error?.status === 401) { - Cookies.remove(TOKEN_COOKIE_NAME); - window.location.reload(); - - return; - } - setIsLoading(false); setError(error?.message || 'Something went wrong'); diff --git a/src/lib/http.ts b/src/lib/http.ts index 3bba87272..79f5dc103 100644 --- a/src/lib/http.ts +++ b/src/lib/http.ts @@ -55,6 +55,12 @@ export async function httpCall< }; } + // Logout user if token is invalid + if (data.status === 401) { + Cookies.remove(TOKEN_COOKIE_NAME); + window.location.reload(); + } + return { response: undefined, error: data as ErrorType, diff --git a/src/lib/resource-progress.ts b/src/lib/resource-progress.ts index e98d6df95..c4e0d8733 100644 --- a/src/lib/resource-progress.ts +++ b/src/lib/resource-progress.ts @@ -49,15 +49,19 @@ export async function getResourceProgress( resourceType: 'roadmap' | 'best-practice', resourceId: string ): Promise { + // No need to load progress if user is not logged in + if (!Cookies.get(TOKEN_COOKIE_NAME)) { + return []; + } + const progressKey = `${resourceType}-${resourceId}-progress`; + const rawProgress = localStorage.getItem(progressKey); const progress = JSON.parse(rawProgress || 'null'); const progressTimestamp = progress?.timestamp; const diff = new Date().getTime() - parseInt(progressTimestamp || '0', 10); - const isProgressExpired = diff > 10 * 60 * 1000; // 10 minutes - - console.log(progressKey); + const isProgressExpired = diff > 15 * 60 * 1000; // 15 minutes if (!progress || isProgressExpired) { return loadFreshProgress(resourceType, resourceId); @@ -79,13 +83,6 @@ async function loadFreshProgress( ); if (error) { - if (error.status === 401) { - Cookies.remove(TOKEN_COOKIE_NAME); - window.location.reload(); - - return []; - } - console.error(error); return []; }