Skip to content

Commit 5f2ba2e

Browse files
committed
feat: add Lazer environment switch and context management
1 parent 1e8558d commit 5f2ba2e

File tree

5 files changed

+163
-23
lines changed

5 files changed

+163
-23
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { Menu, Transition } from '@headlessui/react'
2+
import { useRouter } from 'next/router'
3+
import { Fragment, useCallback, useContext, useEffect } from 'react'
4+
import {
5+
LazerEnvContext,
6+
DEFAULT_LAZER_ENV,
7+
LazerEnv,
8+
} from '../contexts/LazerEnvContext'
9+
import Arrow from '@images/icons/down.inline.svg'
10+
11+
const LazerEnvSwitch = ({ light }: { light?: boolean | null }) => {
12+
const router = useRouter()
13+
14+
const { lazerEnv, setLazerEnv } = useContext(LazerEnvContext)
15+
const handleChange = useCallback(
16+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
17+
(event: any) => {
18+
if (event.target.value) {
19+
router.query.lazerEnv = event.target.value
20+
setLazerEnv(event.target.value)
21+
router.push(
22+
{
23+
pathname: router.pathname,
24+
query: router.query,
25+
},
26+
undefined,
27+
{ scroll: false }
28+
)
29+
}
30+
},
31+
[setLazerEnv, router]
32+
)
33+
34+
useEffect(() => {
35+
router?.query?.lazerEnv
36+
? setLazerEnv(router.query.lazerEnv as LazerEnv)
37+
: setLazerEnv(DEFAULT_LAZER_ENV)
38+
}, [setLazerEnv, router])
39+
40+
const environments = [
41+
{
42+
value: 'production',
43+
name: 'production',
44+
},
45+
{
46+
value: 'staging',
47+
name: 'staging',
48+
},
49+
]
50+
51+
return (
52+
<Menu as="div" className="relative z-[3] block w-[180px] text-left">
53+
{({ open }) => (
54+
<>
55+
<Menu.Button
56+
className={`inline-flex w-full items-center justify-between py-3 px-6 text-sm outline-0 ${
57+
light ? 'bg-beige2' : 'bg-darkGray2'
58+
}`}
59+
>
60+
<span className="mr-3">{lazerEnv}</span>
61+
<Arrow className={`${open && 'rotate-180'}`} />
62+
</Menu.Button>
63+
<Transition
64+
as={Fragment}
65+
enter="transition ease-out duration-100"
66+
enterFrom="transform opacity-0 scale-95"
67+
enterTo="transform opacity-100 scale-100"
68+
leave="transition ease-in duration-75"
69+
leaveFrom="transform opacity-100 scale-100"
70+
leaveTo="transform opacity-0 scale-95"
71+
>
72+
<Menu.Items className="absolute right-0 mt-2 w-full origin-top-right">
73+
{environments.map((env) => (
74+
<Menu.Item key={env.name}>
75+
<button
76+
className={`block w-full py-3 px-6 text-left text-sm ${
77+
light
78+
? 'bg-beige2 hover:bg-beige3'
79+
: 'bg-darkGray hover:bg-darkGray2'
80+
} `}
81+
value={env.value}
82+
onClick={handleChange}
83+
>
84+
{env.name}
85+
</button>
86+
</Menu.Item>
87+
))}
88+
</Menu.Items>
89+
</Transition>
90+
</>
91+
)}
92+
</Menu>
93+
)
94+
}
95+
96+
export default LazerEnvSwitch

governance/xc_admin/packages/xc_admin_frontend/components/programs/PythLazer.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { useState, useContext } from 'react'
22
import { usePythContext } from '../../contexts/PythContext'
33
import { ClusterContext } from '../../contexts/ClusterContext'
4+
import { LazerEnvContext } from '../../contexts/LazerEnvContext'
5+
import LazerEnvSwitch from '../LazerEnvSwitch'
46
import Modal from '../common/Modal'
57
import {
68
validateUploadedConfig,
@@ -365,13 +367,14 @@ const PythLazer = ({
365367
}: PythLazerProps) => {
366368
const { dataIsLoading, lazerState } = usePythContext()
367369
const { cluster } = useContext(ClusterContext)
370+
const { lazerEnv } = useContext(LazerEnvContext)
371+
const { isLoading: isMultisigLoading, readOnlySquads } = useMultisigContext()
372+
const isRemote: boolean = isRemoteCluster(cluster)
368373

369374
const [dataChanges, setDataChanges] = useState<LazerConfigChanges>()
370375
const [isModalOpen, setIsModalOpen] = useState(false)
371376
const [isSendProposalButtonLoading, setIsSendProposalButtonLoading] =
372377
useState(false)
373-
const { isLoading: isMultisigLoading, readOnlySquads } = useMultisigContext()
374-
const isRemote: boolean = isRemoteCluster(cluster)
375378

376379
const openModal = () => {
377380
setIsModalOpen(true)
@@ -389,7 +392,7 @@ const PythLazer = ({
389392
encodeURIComponent(JSON.stringify(lazerState, null, 2))
390393
const downloadAnchor = document.createElement('a')
391394
downloadAnchor.setAttribute('href', dataStr)
392-
downloadAnchor.setAttribute('download', `lazer_config.json`)
395+
downloadAnchor.setAttribute('download', `lazer_config_${lazerEnv}.json`)
393396
document.body.appendChild(downloadAnchor) // required for firefox
394397
downloadAnchor.click()
395398
downloadAnchor.remove()
@@ -457,7 +460,7 @@ const PythLazer = ({
457460
{
458461
fundingAccount,
459462
},
460-
'lazer_production'
463+
`lazer_${lazerEnv}` // Use the selected lazer environment
461464
)
462465

463466
console.log('Generated instructions:', instructions)
@@ -492,6 +495,9 @@ const PythLazer = ({
492495
/>
493496
}
494497
/>
498+
<div className="mb-4 flex">
499+
<LazerEnvSwitch />
500+
</div>
495501
<div className="relative mt-6">
496502
{dataIsLoading || !lazerState ? (
497503
<div className="mt-3">

governance/xc_admin/packages/xc_admin_frontend/contexts/ClusterContext.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ export const ClusterContext = createContext<{
88
setCluster: (_cluster: PythCluster) => void
99
}>({
1010
cluster: DEFAULT_CLUSTER,
11-
setCluster: () => {},
11+
setCluster: () => {
12+
// Default no-op function
13+
},
1214
})
1315

1416
export const ClusterProvider = ({ children }: { children: ReactNode }) => {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React, { createContext, useState, ReactNode } from 'react'
2+
3+
export type LazerEnv = 'production' | 'staging'
4+
5+
export const DEFAULT_LAZER_ENV: LazerEnv = 'production'
6+
7+
interface LazerEnvContextType {
8+
lazerEnv: LazerEnv
9+
setLazerEnv: (env: LazerEnv) => void
10+
}
11+
12+
export const LazerEnvContext = createContext<LazerEnvContextType>({
13+
lazerEnv: DEFAULT_LAZER_ENV,
14+
setLazerEnv: () => {
15+
// Default no-op function
16+
},
17+
})
18+
19+
interface LazerEnvProviderProps {
20+
children: ReactNode
21+
}
22+
23+
export const LazerEnvProvider: React.FC<LazerEnvProviderProps> = ({
24+
children,
25+
}) => {
26+
const [lazerEnv, setLazerEnv] = useState<LazerEnv>(DEFAULT_LAZER_ENV)
27+
28+
return (
29+
<LazerEnvContext.Provider value={{ lazerEnv, setLazerEnv }}>
30+
{children}
31+
</LazerEnvContext.Provider>
32+
)
33+
}

governance/xc_admin/packages/xc_admin_frontend/pages/_app.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { ProgramProvider } from '../contexts/ProgramContext'
2424
import SEO from '../next-seo.config'
2525
import '../styles/globals.css'
2626
import { NuqsAdapter } from 'nuqs/adapters/next/pages'
27+
import { LazerEnvProvider } from '../contexts/LazerEnvContext'
2728

2829
const walletConnectConfig: WalletConnectWalletAdapterConfig = {
2930
network: WalletAdapterNetwork.Mainnet,
@@ -69,25 +70,27 @@ function MyApp({ Component, pageProps }: AppProps) {
6970
<WalletProvider wallets={wallets} autoConnect>
7071
<WalletModalProvider>
7172
<ClusterProvider>
72-
<ProgramProvider>
73-
<Head>
74-
<meta
75-
name="viewport"
76-
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
73+
<LazerEnvProvider>
74+
<ProgramProvider>
75+
<Head>
76+
<meta
77+
name="viewport"
78+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
79+
/>
80+
</Head>
81+
<DefaultSeo {...SEO} />
82+
<Component {...pageProps} />
83+
<Toaster
84+
position="bottom-left"
85+
toastOptions={{
86+
style: {
87+
wordBreak: 'break-word',
88+
},
89+
}}
90+
reverseOrder={false}
7791
/>
78-
</Head>
79-
<DefaultSeo {...SEO} />
80-
<Component {...pageProps} />
81-
<Toaster
82-
position="bottom-left"
83-
toastOptions={{
84-
style: {
85-
wordBreak: 'break-word',
86-
},
87-
}}
88-
reverseOrder={false}
89-
/>
90-
</ProgramProvider>
92+
</ProgramProvider>
93+
</LazerEnvProvider>
9194
</ClusterProvider>
9295
</WalletModalProvider>
9396
</WalletProvider>

0 commit comments

Comments
 (0)