Skip to content

Commit 363ead8

Browse files
authored
feat: adding generic resource interface (#5552)
1 parent 97fa280 commit 363ead8

File tree

5 files changed

+139
-0
lines changed

5 files changed

+139
-0
lines changed

src/dataExplorer/components/DataExplorerPage.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import SaveAsOverlay from 'src/dataExplorer/components/SaveAsOverlay'
2323
import ViewTypeDropdown from 'src/timeMachine/components/ViewTypeDropdown'
2424
import {AddAnnotationDEOverlay} from 'src/overlays/components/index'
2525
import {EditAnnotationDEOverlay} from 'src/overlays/components/index'
26+
import TemplatePage from 'src/dataExplorer/components/resources/TemplatePage'
2627

2728
// Utils
2829
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
@@ -67,6 +68,10 @@ const DataExplorerPage: FC = () => {
6768
return (
6869
<Page titleTag={pageTitleSuffixer(['Data Explorer'])}>
6970
<Switch>
71+
<Route
72+
path="/orgs/:orgID/data-explorer/from"
73+
component={TemplatePage}
74+
/>
7075
<Route
7176
path="/orgs/:orgID/data-explorer/save"
7277
component={SaveAsOverlay}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React, {FC, useEffect, useState, useContext} from 'react'
2+
import {useSelector} from 'react-redux'
3+
import {Switch, Route, useHistory, useParams} from 'react-router-dom'
4+
import {RemoteDataState} from 'src/types'
5+
6+
import {getOrg} from 'src/organizations/selectors'
7+
8+
import {RESOURCES} from 'src/dataExplorer/components/resources'
9+
import {
10+
PersistanceContext,
11+
PersistanceProvider,
12+
} from 'src/dataExplorer/context/persistance'
13+
14+
const Template: FC = () => {
15+
const {setQuery, setResource} = useContext(PersistanceContext)
16+
const params = useParams()[0].split('/')
17+
const org = useSelector(getOrg)
18+
const history = useHistory()
19+
const [loading, setLoading] = useState(RemoteDataState.NotStarted)
20+
21+
if (!params[0].endsWith('s')) {
22+
params[0] += 's'
23+
}
24+
25+
useEffect(() => {
26+
if (!RESOURCES[params[0]] || RESOURCES[params[0]].disabled) {
27+
setLoading(RemoteDataState.Error)
28+
return
29+
}
30+
31+
if (loading !== RemoteDataState.NotStarted) {
32+
return
33+
}
34+
35+
setLoading(RemoteDataState.Loading)
36+
setQuery('')
37+
setResource(null)
38+
39+
RESOURCES[params[0]].init.apply(this, params.slice(1)).then(data => {
40+
setQuery(data.flux)
41+
setResource(data)
42+
history.replace(`/orgs/${org.id}/data-explorer`)
43+
})
44+
}, [params])
45+
46+
return <div></div>
47+
}
48+
49+
const TemplatePage: FC = () => {
50+
const org = useSelector(getOrg)
51+
52+
return (
53+
<PersistanceProvider>
54+
<Switch>
55+
<Route
56+
path={`/orgs/${org.id}/data-explorer/from/*`}
57+
component={Template}
58+
/>
59+
<Route component={() => <div />} />
60+
</Switch>
61+
</PersistanceProvider>
62+
)
63+
}
64+
65+
export default TemplatePage
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {ReactNode} from 'react'
2+
import {ResourceType} from 'src/types/resources'
3+
4+
export interface ResourceConnectedQuery<T> {
5+
type: ResourceType
6+
flux: string
7+
data: T
8+
}
9+
10+
export interface ResourceRegistration {
11+
type: ResourceType
12+
disabled?: boolean
13+
editor: ReactNode
14+
init: (...args: string[]) => Promise<ResourceConnectedQuery<any>>
15+
persist: (
16+
query: ResourceConnectedQuery<any>
17+
) => Promise<ResourceConnectedQuery<any>>
18+
}
19+
20+
interface Resources {
21+
[type: string]: ResourceRegistration
22+
}
23+
24+
export const RESOURCES: Resources = {}
25+
// eslint-disable-next-line no-extra-semi
26+
;[].forEach(mod => {
27+
mod.default((def: ResourceRegistration) => {
28+
if (RESOURCES.hasOwnProperty(def.type)) {
29+
throw new Error(
30+
`Resource of type [${def.type}] has already been registered`
31+
)
32+
}
33+
34+
RESOURCES[def.type] = {
35+
...def,
36+
}
37+
})
38+
})

src/dataExplorer/context/persistance.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import {DEFAULT_TIME_RANGE} from 'src/shared/constants/timeRanges'
44
import {useSessionStorage} from 'src/dataExplorer/shared/utils'
55
import {Bucket, TagKeyValuePair} from 'src/types'
66
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
7+
import {
8+
RESOURCES,
9+
ResourceConnectedQuery,
10+
} from 'src/dataExplorer/components/resources'
711

812
interface SchemaComposition {
913
synced: boolean // true == can modify session's schema
@@ -23,13 +27,17 @@ interface ContextType {
2327
vertical: number[]
2428
range: TimeRange
2529
query: string
30+
resource: ResourceConnectedQuery<any>
2631
selection: SchemaSelection
2732

2833
setHorizontal: (val: number[]) => void
2934
setVertical: (val: number[]) => void
3035
setRange: (val: TimeRange) => void
3136
setQuery: (val: string) => void
37+
setResource: (val: ResourceConnectedQuery<any>) => void
3238
setSelection: (val: RecursivePartial<SchemaSelection>) => void
39+
40+
save: () => Promise<ResourceConnectedQuery<any>>
3341
}
3442

3543
export const DEFAULT_SCHEMA: SchemaSelection = {
@@ -48,13 +56,17 @@ const DEFAULT_CONTEXT = {
4856
vertical: [0.25, 0.8],
4957
range: DEFAULT_TIME_RANGE,
5058
query: '',
59+
resource: null,
5160
selection: DEFAULT_SCHEMA,
5261

5362
setHorizontal: (_: number[]) => {},
5463
setVertical: (_: number[]) => {},
5564
setRange: (_: TimeRange) => {},
5665
setQuery: (_: string) => {},
66+
setResource: (_: any) => {},
5767
setSelection: (_: RecursivePartial<SchemaSelection>) => {},
68+
69+
save: () => Promise.resolve(null),
5870
}
5971

6072
export const PersistanceContext = createContext<ContextType>(DEFAULT_CONTEXT)
@@ -80,6 +92,7 @@ export const PersistanceProvider: FC = ({children}) => {
8092
'dataExplorer.range',
8193
DEFAULT_CONTEXT.range
8294
)
95+
const [resource, setResource] = useSessionStorage('dataExplorer.resource', {})
8396
const [selection, setSelection] = useSessionStorage(
8497
'dataExplorer.schema',
8598
JSON.parse(JSON.stringify(DEFAULT_CONTEXT.selection))
@@ -107,20 +120,37 @@ export const PersistanceProvider: FC = ({children}) => {
107120
[selection, selection.composition, setSelection]
108121
)
109122

123+
const save = () => {
124+
if (!resource || !RESOURCES[resource.type]) {
125+
return Promise.resolve(null)
126+
}
127+
128+
resource.flux = query
129+
130+
return RESOURCES[resource.type].persist(resource).then(data => {
131+
setResource(data)
132+
return data
133+
})
134+
}
135+
110136
return (
111137
<PersistanceContext.Provider
112138
value={{
113139
horizontal,
114140
vertical,
115141
range,
116142
query,
143+
resource,
117144
selection,
118145

119146
setHorizontal,
120147
setVertical,
121148
setRange,
122149
setQuery,
150+
setResource,
123151
setSelection: setSchemaSelection,
152+
153+
save,
124154
}}
125155
>
126156
{children}

src/types/resources.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export enum ResourceType {
3636
Plugins = 'plugins',
3737
Scrapers = 'scrapers',
3838
Secrets = 'secrets',
39+
Scripts = 'scripts',
3940
Tasks = 'tasks',
4041
Templates = 'templates',
4142
Telegrafs = 'telegrafs',

0 commit comments

Comments
 (0)