|
@@ -1,33 +1,70 @@
|
|
-import React, { useState } from 'react'
|
|
|
|
|
|
+import React, { useRef, useState } from 'react'
|
|
import { Link } from 'react-router-dom'
|
|
import { Link } from 'react-router-dom'
|
|
|
|
|
|
-import { TARGET_DEV_ENV, availableEnvs, setEnvInLocalStorage } from '@/config/envs'
|
|
|
|
|
|
+import { availableNodes } from '@/config/availableNodes'
|
|
|
|
+import { TARGET_DEV_ENV, availableEnvs } from '@/config/envs'
|
|
import { absoluteRoutes } from '@/config/routes'
|
|
import { absoluteRoutes } from '@/config/routes'
|
|
|
|
+import { NODE_URL } from '@/config/urls'
|
|
|
|
+import { useEnvironmentStore } from '@/providers/environment/store'
|
|
import { useSnackbar } from '@/providers/snackbars'
|
|
import { useSnackbar } from '@/providers/snackbars'
|
|
import { Button } from '@/shared/components/Button'
|
|
import { Button } from '@/shared/components/Button'
|
|
|
|
+import { Checkbox } from '@/shared/components/Checkbox'
|
|
import { Select } from '@/shared/components/Select'
|
|
import { Select } from '@/shared/components/Select'
|
|
import { Text } from '@/shared/components/Text'
|
|
import { Text } from '@/shared/components/Text'
|
|
|
|
+import { TextField } from '@/shared/components/TextField'
|
|
import { SentryLogger } from '@/utils/logs'
|
|
import { SentryLogger } from '@/utils/logs'
|
|
|
|
|
|
|
|
+type SelectValue = string | null
|
|
|
|
+
|
|
const items = availableEnvs().map((item) => ({ name: item, value: item }))
|
|
const items = availableEnvs().map((item) => ({ name: item, value: item }))
|
|
|
|
|
|
export const AdminView = () => {
|
|
export const AdminView = () => {
|
|
- const env = availableEnvs().includes(TARGET_DEV_ENV) ? TARGET_DEV_ENV : null
|
|
|
|
- const [value, setValue] = useState<null | string>(env)
|
|
|
|
|
|
+ const [customUrlError, setCustomUrlError] = useState<string | null>(null)
|
|
|
|
+ const { setSelectedNode, selectedNode, setTargetEnv, targetEnv } = useEnvironmentStore((state) => ({
|
|
|
|
+ ...state.actions,
|
|
|
|
+ ...state,
|
|
|
|
+ }))
|
|
|
|
+ const determinedNode = selectedNode || NODE_URL
|
|
|
|
+ const isCustomUrl = availableNodes.find(({ value }) => value === determinedNode)
|
|
|
|
+ const [customUrlChecked, setCustomUrlChecked] = useState(!isCustomUrl)
|
|
const { displaySnackbar } = useSnackbar()
|
|
const { displaySnackbar } = useSnackbar()
|
|
|
|
+ const customNodeRef = useRef<HTMLInputElement>(null)
|
|
|
|
|
|
- const handleEnvironmentChange = (value?: string | null | undefined) => {
|
|
|
|
|
|
+ const handleEnvironmentChange = (value?: SelectValue) => {
|
|
if (!value) {
|
|
if (!value) {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- setEnvInLocalStorage(value)
|
|
|
|
|
|
+ setTargetEnv(value)
|
|
|
|
|
|
if (TARGET_DEV_ENV) {
|
|
if (TARGET_DEV_ENV) {
|
|
- setValue(TARGET_DEV_ENV)
|
|
|
|
window.location.reload()
|
|
window.location.reload()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const handleNodeChange = (value?: SelectValue) => {
|
|
|
|
+ setSelectedNode(value as string)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const handleCustomNodeChange = () => {
|
|
|
|
+ if (customNodeRef.current) {
|
|
|
|
+ if (customNodeRef.current.value.length) {
|
|
|
|
+ setSelectedNode(customNodeRef.current.value)
|
|
|
|
+ } else {
|
|
|
|
+ setCustomUrlError('Custom url cannot be empty')
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const toggleCustomUrl = () => {
|
|
|
|
+ setCustomUrlError(null)
|
|
|
|
+ if (!customUrlChecked) {
|
|
|
|
+ setCustomUrlChecked(true)
|
|
|
|
+ } else {
|
|
|
|
+ setCustomUrlChecked(false)
|
|
|
|
+ setSelectedNode(isCustomUrl ? availableNodes[0].value : determinedNode)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
const handleExportClick = () => {
|
|
const handleExportClick = () => {
|
|
const storageKeys = Object.keys(window.localStorage)
|
|
const storageKeys = Object.keys(window.localStorage)
|
|
const storage = storageKeys.reduce((acc, key) => {
|
|
const storage = storageKeys.reduce((acc, key) => {
|
|
@@ -77,10 +114,29 @@ export const AdminView = () => {
|
|
}
|
|
}
|
|
|
|
|
|
return (
|
|
return (
|
|
- <>
|
|
|
|
|
|
+ <div style={{ padding: '40px' }}>
|
|
<div>
|
|
<div>
|
|
<Text variant="h2">Choose environment</Text>
|
|
<Text variant="h2">Choose environment</Text>
|
|
- <Select items={items} onChange={handleEnvironmentChange} value={value} />
|
|
|
|
|
|
+ <Select items={items} onChange={handleEnvironmentChange} value={targetEnv} />
|
|
|
|
+ </div>
|
|
|
|
+ <div style={{ margin: '20px 0' }}>
|
|
|
|
+ <Text variant="h2">
|
|
|
|
+ Choose node url <Checkbox value={customUrlChecked} label="Custom URL" onChange={toggleCustomUrl} />
|
|
|
|
+ </Text>
|
|
|
|
+ {customUrlChecked ? (
|
|
|
|
+ <>
|
|
|
|
+ <TextField
|
|
|
|
+ ref={customNodeRef}
|
|
|
|
+ placeholder="Type your Node URL"
|
|
|
|
+ defaultValue={determinedNode}
|
|
|
|
+ error={!!customUrlError}
|
|
|
|
+ helperText={customUrlError}
|
|
|
|
+ />
|
|
|
|
+ <Button onClick={handleCustomNodeChange}>Update node</Button>
|
|
|
|
+ </>
|
|
|
|
+ ) : (
|
|
|
|
+ <Select items={availableNodes} onChange={handleNodeChange} value={determinedNode} />
|
|
|
|
+ )}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div>
|
|
<Text variant="h2">Import/Export Local state</Text>
|
|
<Text variant="h2">Import/Export Local state</Text>
|
|
@@ -93,6 +149,6 @@ export const AdminView = () => {
|
|
{' '}
|
|
{' '}
|
|
<Link to={absoluteRoutes.viewer.index()}>Back to homepage</Link>
|
|
<Link to={absoluteRoutes.viewer.index()}>Back to homepage</Link>
|
|
</div>
|
|
</div>
|
|
- </>
|
|
|
|
|
|
+ </div>
|
|
)
|
|
)
|
|
}
|
|
}
|