Skip to content

Commit d1cfe01

Browse files
authored
feat(Codecov): add storage solution (#90693)
This PR adds a context to the Codecov product to hold state and functionality to save/get data to/from the url and local storage. This context is used in the CodecovProvider that will be the main wrapper for all things Codecov.
1 parent ee2a56f commit d1cfe01

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {useEffect} from 'react';
2+
3+
import type {CodecovContextData} from 'sentry/components/codecov/context/codecovContext';
4+
import {CodecovContext} from 'sentry/components/codecov/context/codecovContext';
5+
import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
6+
import {useLocation} from 'sentry/utils/useLocation';
7+
import useOrganization from 'sentry/utils/useOrganization';
8+
9+
type CodecovQueryParamsProviderProps = {
10+
children?: NonNullable<React.ReactNode>;
11+
};
12+
13+
export default function CodecovQueryParamsProvider({
14+
children,
15+
}: CodecovQueryParamsProviderProps) {
16+
const organization = useOrganization();
17+
18+
const location = useLocation();
19+
const [localStorageState, setLocalStorageState] = useLocalStorageState(
20+
`codecov-selection:${organization.slug}`,
21+
{}
22+
);
23+
24+
useEffect(() => {
25+
const validEntries = {
26+
repository: location.query.repository,
27+
integratedOrg: location.query.integratedOrg,
28+
branch: location.query.branch,
29+
codecovPeriod: location.query.codecovPeriod,
30+
};
31+
32+
for (const [key, value] of Object.entries(validEntries)) {
33+
if (!value || typeof value !== 'string') {
34+
delete validEntries[key as keyof CodecovContextData];
35+
}
36+
}
37+
38+
setLocalStorageState(prev => ({
39+
...prev,
40+
...validEntries,
41+
}));
42+
}, [setLocalStorageState, location.query]);
43+
44+
// Repository, org and branch default to null as its value to the option not being selected.
45+
// These only represent the unselected values and shouldn't be used when fetching backend data.
46+
const params: CodecovContextData = {
47+
repository:
48+
typeof location.query.repository === 'string'
49+
? decodeURIComponent(location.query.repository)
50+
: 'repository' in localStorageState
51+
? (localStorageState.repository as string)
52+
: null,
53+
integratedOrg:
54+
typeof location.query.integratedOrg === 'string'
55+
? decodeURIComponent(location.query.integratedOrg)
56+
: 'integratedOrg' in localStorageState
57+
? (localStorageState.integratedOrg as string)
58+
: null,
59+
branch:
60+
typeof location.query.branch === 'string'
61+
? decodeURIComponent(location.query.branch)
62+
: 'branch' in localStorageState
63+
? (localStorageState.branch as string)
64+
: null,
65+
codecovPeriod:
66+
typeof location.query.codecovPeriod === 'string'
67+
? decodeURIComponent(location.query.codecovPeriod)
68+
: 'codecovPeriod' in localStorageState
69+
? (localStorageState.codecovPeriod as string)
70+
: '24h',
71+
};
72+
73+
return <CodecovContext.Provider value={params}>{children}</CodecovContext.Provider>;
74+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {createContext, useContext} from 'react';
2+
3+
export type CodecovContextData = {
4+
branch: string | null;
5+
codecovPeriod: string | null;
6+
integratedOrg: string | null;
7+
repository: string | null;
8+
};
9+
10+
export const CodecovContext = createContext<CodecovContextData | undefined>(undefined);
11+
12+
export function useCodecovContext() {
13+
const context = useContext(CodecovContext);
14+
if (context === undefined)
15+
throw new Error('useCodecovContext was called outside of CodecovProvider');
16+
return context;
17+
}

0 commit comments

Comments
 (0)