mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-23 09:22:52 +02:00
Refactor page progress implementation
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
"astro-compress": "^1.1.46",
|
"astro-compress": "^1.1.46",
|
||||||
"jose": "^4.14.4",
|
"jose": "^4.14.4",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"nanostores": "^0.8.1",
|
"nanostores": "^0.9.1",
|
||||||
"node-html-parser": "^6.1.5",
|
"node-html-parser": "^6.1.5",
|
||||||
"npm-check-updates": "^16.10.12",
|
"npm-check-updates": "^16.10.12",
|
||||||
"preact": "^10.15.1",
|
"preact": "^10.15.1",
|
||||||
|
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -17,7 +17,7 @@ specifiers:
|
|||||||
js-cookie: ^3.0.5
|
js-cookie: ^3.0.5
|
||||||
js-yaml: ^4.1.0
|
js-yaml: ^4.1.0
|
||||||
markdown-it: ^13.0.1
|
markdown-it: ^13.0.1
|
||||||
nanostores: ^0.8.1
|
nanostores: ^0.9.1
|
||||||
node-html-parser: ^6.1.5
|
node-html-parser: ^6.1.5
|
||||||
npm-check-updates: ^16.10.12
|
npm-check-updates: ^16.10.12
|
||||||
openai: ^3.2.1
|
openai: ^3.2.1
|
||||||
@@ -34,12 +34,12 @@ dependencies:
|
|||||||
'@astrojs/sitemap': 1.3.1
|
'@astrojs/sitemap': 1.3.1
|
||||||
'@astrojs/tailwind': 3.1.3_w4mihal45edfrnncnioktvfyqy
|
'@astrojs/tailwind': 3.1.3_w4mihal45edfrnncnioktvfyqy
|
||||||
'@fingerprintjs/fingerprintjs': 3.4.1
|
'@fingerprintjs/fingerprintjs': 3.4.1
|
||||||
'@nanostores/preact': 0.5.0_jsxc2udxlr5p4sp4ibwq7kjqyu
|
'@nanostores/preact': 0.5.0_m2wbkjxz7237icvaxqi7ignbgm
|
||||||
astro: 2.5.5
|
astro: 2.5.5
|
||||||
astro-compress: 1.1.46
|
astro-compress: 1.1.46
|
||||||
jose: 4.14.4
|
jose: 4.14.4
|
||||||
js-cookie: 3.0.5
|
js-cookie: 3.0.5
|
||||||
nanostores: 0.8.1
|
nanostores: 0.9.1
|
||||||
node-html-parser: 6.1.5
|
node-html-parser: 6.1.5
|
||||||
npm-check-updates: 16.10.12
|
npm-check-updates: 16.10.12
|
||||||
preact: 10.15.1
|
preact: 10.15.1
|
||||||
@@ -689,14 +689,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
|
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nanostores/preact/0.5.0_jsxc2udxlr5p4sp4ibwq7kjqyu:
|
/@nanostores/preact/0.5.0_m2wbkjxz7237icvaxqi7ignbgm:
|
||||||
resolution: {integrity: sha512-Zq5DEAY+kIfwJ1NPd43D1mpsbISuiD6N/SuTHrt/8jUoifLwXaReaZMAnvkvbIGOgcB1Hy++A9jZix2taNNYxQ==}
|
resolution: {integrity: sha512-Zq5DEAY+kIfwJ1NPd43D1mpsbISuiD6N/SuTHrt/8jUoifLwXaReaZMAnvkvbIGOgcB1Hy++A9jZix2taNNYxQ==}
|
||||||
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
|
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
nanostores: ^0.9.0
|
nanostores: ^0.9.0
|
||||||
preact: '>=10.0.0'
|
preact: '>=10.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
nanostores: 0.8.1
|
nanostores: 0.9.1
|
||||||
preact: 10.15.1
|
preact: 10.15.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@@ -3782,9 +3782,9 @@ packages:
|
|||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/nanostores/0.8.1:
|
/nanostores/0.9.1:
|
||||||
resolution: {integrity: sha512-1ZCfQtII2XeFDrtqXL2cdQ/diGrLxzRB3YMyQjn8m7GSGQrJfGST2iuqMpWnS/ZlifhtjgR/SX0Jy6Uij6lRLA==}
|
resolution: {integrity: sha512-DmAL3oTieICqnl2XVq5wegFE7EXIoPnIv1CNWNGEhXpwrHk7Prctch4/nX5x95i95WHdesI5sPeoNAUFpFsGtg==}
|
||||||
engines: {node: ^16.0.0 || >=18.0.0}
|
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/napi-build-utils/1.0.2:
|
/napi-build-utils/1.0.2:
|
||||||
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'preact/hooks';
|
|||||||
import { httpGet } from '../../lib/http';
|
import { httpGet } from '../../lib/http';
|
||||||
import { ActivityCounters } from './ActivityCounters';
|
import { ActivityCounters } from './ActivityCounters';
|
||||||
import { ResourceProgress } from './ResourceProgress';
|
import { ResourceProgress } from './ResourceProgress';
|
||||||
import { pageLoadingMessage } from '../../stores/page';
|
import { pageProgressMessage } from '../../stores/page';
|
||||||
import { EmptyActivity } from './EmptyActivity';
|
import { EmptyActivity } from './EmptyActivity';
|
||||||
|
|
||||||
type ActivityResponse = {
|
type ActivityResponse = {
|
||||||
@@ -71,7 +71,7 @@ export function ActivityPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadActivity().finally(() => {
|
loadActivity().finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
@@ -119,9 +119,9 @@ export function ActivityPage() {
|
|||||||
updatedAt={roadmap.updatedAt}
|
updatedAt={roadmap.updatedAt}
|
||||||
title={roadmap.title}
|
title={roadmap.title}
|
||||||
onCleared={() => {
|
onCleared={() => {
|
||||||
pageLoadingMessage.set('Updating activity');
|
pageProgressMessage.set('Updating activity');
|
||||||
loadActivity().finally(() => {
|
loadActivity().finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -145,9 +145,9 @@ export function ActivityPage() {
|
|||||||
title={bestPractice.title}
|
title={bestPractice.title}
|
||||||
updatedAt={bestPractice.updatedAt}
|
updatedAt={bestPractice.updatedAt}
|
||||||
onCleared={() => {
|
onCleared={() => {
|
||||||
pageLoadingMessage.set('Updating activity');
|
pageProgressMessage.set('Updating activity');
|
||||||
loadActivity().finally(() => {
|
loadActivity().finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { useStore } from '@nanostores/preact';
|
import { useStore } from '@nanostores/preact';
|
||||||
import { useIsFirstRender } from '../hooks/use-is-first-render';
|
|
||||||
import SpinnerIcon from '../icons/spinner.svg';
|
import SpinnerIcon from '../icons/spinner.svg';
|
||||||
import { pageLoadingMessage } from '../stores/page';
|
import { pageProgressMessage } from '../stores/page';
|
||||||
|
import { useEffect, useState } from 'preact/hooks';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
initialMessage: string;
|
initialMessage: string;
|
||||||
@@ -9,15 +9,17 @@ export interface Props {
|
|||||||
|
|
||||||
export function PageProgress(props: Props) {
|
export function PageProgress(props: Props) {
|
||||||
const { initialMessage } = props;
|
const { initialMessage } = props;
|
||||||
|
const [message, setMessage] = useState(initialMessage);
|
||||||
|
|
||||||
const isFirstRender = useIsFirstRender();
|
const $pageProgressMessage = useStore(pageProgressMessage);
|
||||||
const $pageLoadingMessage = useStore(pageLoadingMessage);
|
|
||||||
|
|
||||||
if (!$pageLoadingMessage) {
|
useEffect(() => {
|
||||||
if (!initialMessage || !isFirstRender) {
|
setMessage($pageProgressMessage);
|
||||||
|
}, [$pageProgressMessage]);
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -30,7 +32,7 @@ export function PageProgress(props: Props) {
|
|||||||
className="h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-4 sm:w-4"
|
className="h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-4 sm:w-4"
|
||||||
/>
|
/>
|
||||||
<h1 className="ml-2">
|
<h1 className="ml-2">
|
||||||
{$pageLoadingMessage || initialMessage}
|
{message}
|
||||||
<span className="animate-pulse">...</span>
|
<span className="animate-pulse">...</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -14,7 +14,7 @@ import {
|
|||||||
ResourceType,
|
ResourceType,
|
||||||
updateResourceProgress as updateResourceProgressApi,
|
updateResourceProgress as updateResourceProgressApi,
|
||||||
} from '../../lib/resource-progress';
|
} from '../../lib/resource-progress';
|
||||||
import { pageLoadingMessage, sponsorHidden } from '../../stores/page';
|
import { pageProgressMessage, sponsorHidden } from '../../stores/page';
|
||||||
import { TopicProgressButton } from './TopicProgressButton';
|
import { TopicProgressButton } from './TopicProgressButton';
|
||||||
|
|
||||||
export function TopicDetail() {
|
export function TopicDetail() {
|
||||||
@@ -64,7 +64,7 @@ export function TopicDetail() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pageLoadingMessage.set('Updating');
|
pageProgressMessage.set('Updating');
|
||||||
|
|
||||||
// Toggle the topic status
|
// Toggle the topic status
|
||||||
isTopicDone({ topicId, resourceId, resourceType })
|
isTopicDone({ topicId, resourceId, resourceType })
|
||||||
@@ -89,7 +89,7 @@ export function TopicDetail() {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'preact/hooks';
|
import { useEffect, useState } from 'preact/hooks';
|
||||||
import { httpGet, httpPost } from '../../lib/http';
|
import { httpGet, httpPost } from '../../lib/http';
|
||||||
import { pageLoadingMessage } from '../../stores/page';
|
import { pageProgressMessage } from '../../stores/page';
|
||||||
|
|
||||||
export default function UpdatePasswordForm() {
|
export default function UpdatePasswordForm() {
|
||||||
const [authProvider, setAuthProvider] = useState('');
|
const [authProvider, setAuthProvider] = useState('');
|
||||||
@@ -72,7 +72,7 @@ export default function UpdatePasswordForm() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadProfile().finally(() => {
|
loadProfile().finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'preact/hooks';
|
import { useEffect, useState } from 'preact/hooks';
|
||||||
import { httpGet, httpPost } from '../../lib/http';
|
import { httpGet, httpPost } from '../../lib/http';
|
||||||
import { pageLoadingMessage } from '../../stores/page';
|
import { pageProgressMessage } from '../../stores/page';
|
||||||
import UploadProfilePicture from './UploadProfilePicture';
|
import UploadProfilePicture from './UploadProfilePicture';
|
||||||
|
|
||||||
export function UpdateProfileForm() {
|
export function UpdateProfileForm() {
|
||||||
@@ -75,7 +75,7 @@ export function UpdateProfileForm() {
|
|||||||
// Make a request to the backend to fill in the form with the current values
|
// Make a request to the backend to fill in the form with the current values
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadProfile().finally(() => {
|
loadProfile().finally(() => {
|
||||||
pageLoadingMessage.set('');
|
pageProgressMessage.set('');
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
import { useRef } from "preact/hooks"
|
|
||||||
|
|
||||||
export function useIsFirstRender(): boolean {
|
|
||||||
const isFirst = useRef(true)
|
|
||||||
|
|
||||||
if (isFirst.current) {
|
|
||||||
isFirst.current = false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return isFirst.current
|
|
||||||
}
|
|
@@ -1,4 +1,4 @@
|
|||||||
import { atom } from 'nanostores';
|
import { atom } from 'nanostores';
|
||||||
|
|
||||||
export const pageLoadingMessage = atom('');
|
export const pageProgressMessage = atom('');
|
||||||
export const sponsorHidden = atom(false);
|
export const sponsorHidden = atom(false);
|
||||||
|
Reference in New Issue
Block a user