username input, buttons roundness, conditions for mocking & caching & local computation
This commit is contained in:
@@ -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 (
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) && (
|
||||
<TextSection
|
||||
title="Username"
|
||||
description={
|
||||
<>
|
||||
Enter a GitHub username.
|
||||
<br />
|
||||
{!isAuthenticated && (
|
||||
<>
|
||||
Please{' '}
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setStage(0);
|
||||
}}
|
||||
className="underline text-blue-900"
|
||||
>
|
||||
log in
|
||||
</a>{' '}
|
||||
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 && (
|
||||
<TextSection
|
||||
title="Repository"
|
||||
@@ -302,6 +353,8 @@ CustomizeStage.propTypes = {
|
||||
setSelectedLanguagesLayout: PropTypes.func.isRequired,
|
||||
selectedWakatimeLayout: PropTypes.object.isRequired,
|
||||
setSelectedWakatimeLayout: PropTypes.func.isRequired,
|
||||
selectedUserId: PropTypes.string.isRequired,
|
||||
setSelectedUserId: PropTypes.func.isRequired,
|
||||
repo: PropTypes.string.isRequired,
|
||||
setRepo: PropTypes.func.isRequired,
|
||||
gist: PropTypes.string.isRequired,
|
||||
|
||||
Reference in New Issue
Block a user