Add progress loader

pull/3813/head
Kamran Ahmed 2 years ago
parent 20db0baec5
commit 3825968106
  1. 2
      src/components/FrameRenderer/FrameRenderer.astro
  2. 124
      src/components/FrameRenderer/renderer.ts
  3. 7
      src/components/Setting/UpdatePasswordForm.tsx
  4. 7
      src/components/Setting/UpdateProfileForm.tsx
  5. 6
      src/lib/http.ts
  6. 17
      src/lib/resource-progress.ts

@ -27,4 +27,4 @@ const { resourceId, resourceType, jsonUrl, dimensions = null } = Astro.props;
</div>
</div>
<script src='./renderer.js'></script>
<script src='./renderer.ts'></script>

@ -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<SVGElement>}
*/
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 = `
<strong>There was an error.</strong><br>
Try loading the page again. or submit an issue on GitHub with following:<br><br>
${error.message} <br /> ${error.stack}
`;
this.containerEl.innerHTML = `<div class="error py-5 text-center text-red-600 mx-auto">${message}</div>`;
}),
this.loadProgress(),
]);
this.containerEl.innerHTML = `<div class="error py-5 text-center text-red-600 mx-auto">${message}</div>`;
});
}
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;

@ -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');

@ -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');

@ -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,

@ -49,15 +49,19 @@ export async function getResourceProgress(
resourceType: 'roadmap' | 'best-practice',
resourceId: string
): Promise<string[]> {
// 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 [];
}

Loading…
Cancel
Save