diff --git a/frontend/frontend/src/axios-override.js b/frontend/frontend/src/axios-override.js index c817af8a..be356899 100644 --- a/frontend/frontend/src/axios-override.js +++ b/frontend/frontend/src/axios-override.js @@ -20,6 +20,9 @@ const cachedAxios = setupCache(axios, { interpretHeader: false, cacheTakeover: false, methods: ['get', 'post'], + cachePredicate: { + allowUrls: ['api.github.com', HOST], + }, }); axios.get = cachedAxios.get.bind(cachedAxios); @@ -36,17 +39,21 @@ function createMockResponse(data, config) { }); } -// store isAuthenticated outside React context so the interceptor can access it -let isAuthenticated = null; +// store shouldMock outside React context so the interceptor can access it +let shouldMock = null; -export function setIsAuthenticated(newIsAuthenticated) { - isAuthenticated = newIsAuthenticated; +export function setShouldMock(newShouldMock) { + shouldMock = newShouldMock; } const defaultAdapter = getAdapter(axios.defaults.adapter); // mock responses to "anuraghazra" requests axios.defaults.adapter = async (config) => { + if (!shouldMock) { + return defaultAdapter(config); + } + const params = config.data ? JSON.parse(config.data) : {}; if ( diff --git a/frontend/frontend/src/components/Card/SVG.js b/frontend/frontend/src/components/Card/SVG.js index fb486538..8ddde7ad 100644 --- a/frontend/frontend/src/components/Card/SVG.js +++ b/frontend/frontend/src/components/Card/SVG.js @@ -9,7 +9,7 @@ import 'react-loading-skeleton/dist/skeleton.css'; import { createMockReq, createMockRes } from '../../mock-http'; import { default as router } from '../../backend/.vercel/output/functions/api.func/router.js'; -import { setIsAuthenticated } from '../../axios-override'; +import { setShouldMock } from '../../axios-override'; import { useIsAuthenticated, useUserToken, @@ -21,12 +21,12 @@ const SvgInline = (props) => { const containerRef = useRef(null); const userToken = useUserToken(); const isAuthenticated = useIsAuthenticated(); - const { url } = props; + const { url, stage } = props; - // provide isAuthenticated to non-react code in axios-override.js + // provide shouldMock to non-react code in axios-override.js useEffect(() => { - setIsAuthenticated(isAuthenticated); - }, [isAuthenticated]); + setShouldMock(stage === 0 || !isAuthenticated); + }, [isAuthenticated, props.stage]); useEffect(() => { const loadSvg = async () => { @@ -42,22 +42,20 @@ const SvgInline = (props) => { return; } - // if (isAuthenticated) { - const req = createMockReq({ - method: 'GET', - url: url, - }); - const res = createMockRes(); - await router(req, res); - body = res._getBody(); - status = res._getStatusCode(); - /* - } else { - let res = await axios.get(url); - body = res.data; - status = res.status; - } -*/ + if (stage === 4 && !isAuthenticated) { + let res = await axios.get(url); + body = res.data; + status = res.status; + } else { + const req = createMockReq({ + method: 'GET', + url: url, + }); + const res = createMockRes(); + await router(req, res); + body = res._getBody(); + status = res._getStatusCode(); + } if (status >= 300) { console.error('failed to fetch/generate SVG'); @@ -68,7 +66,7 @@ const SvgInline = (props) => { setLoaded(true); }; loadSvg(); - }, [userToken, isAuthenticated, props.url]); + }, [userToken, isAuthenticated, props.url, props.stage]); useEffect(() => { if (loaded && svg && containerRef.current) { @@ -103,6 +101,7 @@ SvgInline.propTypes = { url: PropTypes.string.isRequired, forceLoading: PropTypes.bool, compact: PropTypes.bool, + stage: PropTypes.number.isRequired, }; SvgInline.defaultProps = { diff --git a/frontend/frontend/src/components/Generic/Button.js b/frontend/frontend/src/components/Generic/Button.js index f245c95d..50db7cd4 100644 --- a/frontend/frontend/src/components/Generic/Button.js +++ b/frontend/frontend/src/components/Generic/Button.js @@ -11,7 +11,7 @@ const Button = (props) => { {...props} className={classnames( props.className, - 'border-0 py-2 px-6 inline-flex focus:outline-none rounded-s text-lg', + 'border-0 py-2 px-6 inline-flex focus:outline-none rounded-md text-lg', )} > {props.children} diff --git a/frontend/frontend/src/pages/Home/Home.js b/frontend/frontend/src/pages/Home/Home.js index 29d1eab5..3a0f36bc 100644 --- a/frontend/frontend/src/pages/Home/Home.js +++ b/frontend/frontend/src/pages/Home/Home.js @@ -44,6 +44,7 @@ const HomeScreen = ({ stage, setStage }) => { const login = (newUserId, userKey) => dispatch(_login(newUserId, userKey)); // for stage two + const [selectedUserId, setSelectedUserId] = useState(userId); const [repo, setRepo] = useState(DEMO_REPO); const [gist, setGist] = useState(DEMO_GIST); const [wakatimeUser, setWakatimeUser] = useState(DEMO_WAKATIME_USER); @@ -104,7 +105,7 @@ const HomeScreen = ({ stage, setStage }) => { switch (selectedCard) { case CardTypes.STATS: case CardTypes.TOP_LANGS: - fullSuffix += `username=${userId}`; + fullSuffix += `username=${selectedUserId}`; break; case CardTypes.PIN: fullSuffix += `username=${userId}&repo=${repo}`; @@ -374,6 +375,8 @@ const HomeScreen = ({ stage, setStage }) => { setIncludeAllCommits={setIncludeAllCommits} enableAnimations={enableAnimations} setEnableAnimations={setEnableAnimations} + selectedUserId={selectedUserId} + setSelectedUserId={setSelectedUserId} repo={repo} setRepo={setRepo} gist={gist} @@ -399,9 +402,8 @@ const HomeScreen = ({ stage, setStage }) => { filename={(() => { switch (selectedCard) { case CardTypes.STATS: - return `${userId}_card`; case CardTypes.TOP_LANGS: - return `${userId}_card`; + return `${selectedUserId}_card`; case CardTypes.PIN: return `${repo}_card`; case CardTypes.GIST: diff --git a/frontend/frontend/src/pages/Home/stages/Customize.js b/frontend/frontend/src/pages/Home/stages/Customize.js index 537f0811..0bc9cc70 100644 --- a/frontend/frontend/src/pages/Home/stages/Customize.js +++ b/frontend/frontend/src/pages/Home/stages/Customize.js @@ -8,7 +8,12 @@ import NumericSection from '../../../components/Home/NumericSection'; import StatsRankSection from '../../../components/Home/StatsRankSection'; import LanguagesLayoutSection from '../../../components/Home/LanguagesLayoutSection'; import WakatimeLayoutSection from '../../../components/Home/WakatimeLayoutSection'; -import { DEMO_GIST, DEMO_REPO, DEMO_WAKATIME_USER } from '../../../constants'; +import { + DEMO_GIST, + DEMO_REPO, + DEMO_USER, + DEMO_WAKATIME_USER, +} from '../../../constants'; import { useIsAuthenticated } from '../../../redux/selectors/userSelectors'; const CustomizeStage = ({ @@ -19,6 +24,8 @@ const CustomizeStage = ({ setSelectedLanguagesLayout, selectedWakatimeLayout, setSelectedWakatimeLayout, + selectedUserId, + setSelectedUserId, repo, setRepo, gist, @@ -93,6 +100,50 @@ const CustomizeStage = ({ setSelectedOption={setSelectedLanguagesLayout} /> )} + {(cardType === CardTypes.STATS || cardType === CardTypes.TOP_LANGS) && ( + + Enter a GitHub username. +
+ {!isAuthenticated && ( + <> + Please{' '} + { + e.preventDefault(); + setStage(0); + }} + className="underline text-blue-900" + > + log in + {' '} + to change the username. + + )} + + } + placeholder={`e.g. "${DEMO_USER}"`} + value={selectedUserId} + setValue={setSelectedUserId} + onPaste={(e) => { + e.preventDefault(); + let newValue = e.clipboardData.getData('text'); + // if the user pasted a full GitHub URL, extract username + if (newValue.endsWith('/')) { + newValue = newValue.slice(0, -1); + } + let parts = newValue.split('/'); + if (parts.length > 1) { + newValue = parts.slice(-1).join('/'); + } + setRepo(newValue); + }} + disabled={!isAuthenticated} + /> + )} {cardType === CardTypes.PIN && (