1
- import _ from 'lodash' ;
1
+ import { Box , Group , Loader , Stack , TagsInput , Tooltip , Text , TextInput } from '@mantine/core' ;
2
+ import classes from '../../styles/Management.module.css' ;
3
+ import { IconCheck , IconX , IconEdit } from '@tabler/icons-react' ;
2
4
import { useStreamStore } from '../../providers/StreamProvider' ;
3
- import { ChangeEvent , useCallback , useState , useEffect } from 'react' ;
5
+ import _ from 'lodash' ;
6
+ import { ChangeEvent , FC , useCallback , useEffect , useState } from 'react' ;
4
7
import { useLogStream } from '@/hooks/useLogStream' ;
5
8
import { useGetStreamInfo } from '@/hooks/useGetStreamInfo' ;
6
- import { Box , Loader , Stack , TextInput , Tooltip , Text , Group } from '@mantine/core' ;
7
- import { IconCheck , IconX , IconEdit } from '@tabler/icons-react' ;
8
- import classes from '../../styles/Management.module.css' ;
9
9
10
- const UpdateFieldButtons = ( props : { onClose : ( ) => void ; onUpdateClick : ( ) => void ; isUpdating : boolean } ) => {
10
+ interface UpdateFieldButtonsProps {
11
+ onClose : ( ) => void ;
12
+ onUpdateClick : ( ) => void ;
13
+ isUpdating : boolean ;
14
+ }
15
+
16
+ interface PartitionLimitProps {
17
+ timePartition : string ;
18
+ currentStream : string ;
19
+ }
20
+
21
+ type PartitionValue = string [ ] | number | undefined ;
22
+
23
+ const UpdateFieldButtons : FC < UpdateFieldButtonsProps > = ( { onClose, onUpdateClick, isUpdating } ) => {
11
24
return (
12
25
< Box >
13
- { ! props . isUpdating ? (
26
+ { ! isUpdating ? (
14
27
< Stack gap = { 4 } style = { { display : 'flex' , flexDirection : 'row' } } >
15
28
< Tooltip label = "Update" withArrow position = "top" >
16
- < IconCheck className = { classes . infoEditBtn } onClick = { ( ) => props . onUpdateClick ( ) } stroke = { 1.6 } size = { 16 } />
29
+ < IconCheck className = { classes . infoEditBtn } onClick = { ( ) => onUpdateClick ( ) } stroke = { 1.6 } size = { 16 } />
17
30
</ Tooltip >
18
31
19
32
< Tooltip label = "Close" withArrow position = "top" >
20
- < IconX className = { classes . infoEditBtn } stroke = { 1.6 } size = { 16 } onClick = { ( ) => props . onClose ( ) } />
33
+ < IconX className = { classes . infoEditBtn } stroke = { 1.6 } size = { 16 } onClick = { ( ) => onClose ( ) } />
21
34
</ Tooltip >
22
35
</ Stack >
23
36
) : (
@@ -27,27 +40,55 @@ const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => v
27
40
) ;
28
41
} ;
29
42
30
- function UpdateStreamInfo ( props : { timePartition : string ; currentStream : string } ) {
43
+ const UpdateStreamInfo : FC < PartitionLimitProps > = ( { timePartition, currentStream } ) => {
31
44
const [ info ] = useStreamStore ( ( store ) => store . info ) ;
32
- const timePartitonLimit = _ . get ( info , 'time_partition_limit' ) ;
33
- const [ value , setValue ] = useState < number | undefined > ( timePartitonLimit ) ;
34
- const [ updating , setUpdating ] = useState < boolean > ( false ) ;
45
+ const [ partitionFields ] = useStreamStore ( ( store ) => store . fieldNames ) ;
46
+
47
+ const isStaticSchema = _ . get ( info , 'static_schema_flag' , false ) ;
48
+ const initialPartitionValue = isStaticSchema
49
+ ? _ . get ( info , 'custom_partition' , '-' ) . split ( ',' )
50
+ : _ . get ( info , 'time_partition_limit' ) ;
51
+
52
+ const [ value , setValue ] = useState < PartitionValue > ( initialPartitionValue ) ;
53
+ const [ updating , setUpdating ] = useState ( false ) ;
35
54
const [ error , setError ] = useState < string | null > ( null ) ;
36
- const [ showEditField , setShowEditField ] = useState < boolean > ( false ) ;
55
+ const [ showEditField , setShowEditField ] = useState ( false ) ;
56
+
37
57
const { updateLogStreamMutation } = useLogStream ( ) ;
38
- const { getStreamInfoRefetch } = useGetStreamInfo ( props . currentStream , props . currentStream !== null ) ;
58
+ const { getStreamInfoRefetch } = useGetStreamInfo ( currentStream , currentStream !== null ) ;
39
59
40
60
useEffect ( ( ) => {
41
- setValue ( timePartitonLimit ) ;
42
- } , [ props . currentStream , info ] ) ;
61
+ setValue ( initialPartitionValue ) ;
62
+ } , [ currentStream , info , initialPartitionValue ] ) ;
63
+
64
+ const handleCustomPartitionChange = useCallback (
65
+ ( value : string [ ] ) => {
66
+ setValue ( value ) ;
67
+
68
+ if ( isStaticSchema ) {
69
+ value ?. forEach ( ( el ) => {
70
+ if ( ! partitionFields . includes ( el ) ) {
71
+ setError ( 'Unknown Field Included' ) ;
72
+ } else {
73
+ setError ( null ) ;
74
+ }
75
+ } ) ;
76
+ }
77
+ if ( Array . isArray ( value ) && value . length === 0 ) {
78
+ setError ( null ) ;
79
+ }
80
+ } ,
81
+ [ setValue ] ,
82
+ ) ;
43
83
44
- const onChange = useCallback (
84
+ const handleTimePartitionChange = useCallback (
45
85
( e : ChangeEvent < HTMLInputElement > ) => {
46
86
const inputTime = e . target . value ;
47
87
const numberRegex = / ^ \d * $ / ;
48
88
if ( numberRegex . test ( inputTime ) ) {
49
- if ( parseInt ( inputTime ) > 0 ) {
50
- setValue ( parseInt ( inputTime ) ) ;
89
+ const parsedValue = parseInt ( inputTime ) ;
90
+ if ( parsedValue > 0 ) {
91
+ setValue ( parsedValue ) ;
51
92
setError ( null ) ;
52
93
} else {
53
94
setValue ( 0 ) ;
@@ -66,35 +107,52 @@ function UpdateStreamInfo(props: { timePartition: string; currentStream: string
66
107
} , [ getStreamInfoRefetch ] ) ;
67
108
68
109
const updateLogStream = useCallback (
69
- ( updatedValue : number ) => {
110
+ ( updatedValue : string | number ) => {
70
111
updateLogStreamMutation ( {
71
- streamName : props . currentStream ,
72
- header : { 'x-p-time-partition-limit' : `${ updatedValue } d` } ,
112
+ streamName : currentStream ,
113
+ header : isStaticSchema
114
+ ? { 'x-p-custom-partition' : String ( updatedValue ) }
115
+ : { 'x-p-time-partition-limit' : `${ updatedValue } d` } ,
73
116
onSuccess : updateLogStreamSuccess ,
74
117
onError : ( ) => setUpdating ( false ) ,
75
118
} ) ;
76
119
} ,
77
- [ updateLogStreamMutation , props . currentStream ] ,
120
+ [ updateLogStreamMutation , currentStream , isStaticSchema ] ,
78
121
) ;
79
122
80
- const updateTimePartitionLimit = useCallback ( ( ) => {
81
- if ( value === undefined ) return ;
82
- if ( error !== null ) return ;
83
-
84
- setUpdating ( true ) ;
85
- updateLogStream ( value ) ;
123
+ const updatePartitionLimit = useCallback ( ( ) => {
124
+ if ( error ) return ;
125
+ if ( isStaticSchema ) {
126
+ if ( ! Array . isArray ( value ) || value . length === 0 ) return ;
127
+ setUpdating ( true ) ;
128
+ updateLogStream ( value . join ( ',' ) ) ;
129
+ } else {
130
+ if ( typeof value !== 'number' ) return ;
131
+ setUpdating ( true ) ;
132
+ updateLogStream ( value ) ;
133
+ }
86
134
} , [ value , updateLogStream ] ) ;
87
135
88
136
return (
89
- < Stack style = { { height : '3.5rem' , width : '33%' } } gap = { 6 } >
137
+ < Stack style = { { height : '3.5rem' , width : isStaticSchema ? '30rem' : '33%' } } gap = { 6 } >
90
138
< Group >
91
139
< Text
92
140
className = { classes . fieldDescription }
93
141
style = { { textOverflow : 'ellipsis' , whiteSpace : 'nowrap' , overflow : 'hidden' } } >
94
- Max Historical Difference
142
+ { isStaticSchema ? 'Custom Partition Field' : ' Max Historical Difference' }
95
143
</ Text >
96
144
97
- { props . timePartition !== '-' && (
145
+ { timePartition !== '-' && ! isStaticSchema && (
146
+ < Tooltip label = "Edit" withArrow position = "top" >
147
+ < IconEdit
148
+ className = { classes . infoEditBtn }
149
+ stroke = { 1.6 }
150
+ size = { 12 }
151
+ onClick = { ( ) => setShowEditField ( ( prev ) => ! prev ) }
152
+ />
153
+ </ Tooltip >
154
+ ) }
155
+ { isStaticSchema && ! showEditField && (
98
156
< Tooltip label = "Edit" withArrow position = "top" >
99
157
< IconEdit
100
158
className = { classes . infoEditBtn }
@@ -105,16 +163,30 @@ function UpdateStreamInfo(props: { timePartition: string; currentStream: string
105
163
</ Tooltip >
106
164
) }
107
165
</ Group >
166
+
108
167
{ showEditField ? (
109
168
< Group style = { { flexDirection : 'row' , alignItems : 'baseline' } } gap = { 6 } >
110
- < TextInput
111
- placeholder = "Max Historical Difference"
112
- value = { value }
113
- onChange = { ( e ) => onChange ( e ) }
114
- error = { error }
115
- />
169
+ { isStaticSchema ? (
170
+ < TagsInput
171
+ w = { '30rem' }
172
+ placeholder = "Select column from the list"
173
+ data = { partitionFields }
174
+ onChange = { handleCustomPartitionChange }
175
+ maxTags = { 3 }
176
+ value = { Array . isArray ( value ) ? value : [ ] }
177
+ error = { error }
178
+ />
179
+ ) : (
180
+ < TextInput
181
+ placeholder = "Max Historical Difference"
182
+ value = { typeof value === 'number' ? value . toString ( ) : '' }
183
+ onChange = { handleTimePartitionChange }
184
+ error = { error }
185
+ />
186
+ ) }
187
+
116
188
< UpdateFieldButtons
117
- onUpdateClick = { updateTimePartitionLimit }
189
+ onUpdateClick = { updatePartitionLimit }
118
190
onClose = { ( ) => setShowEditField ( false ) }
119
191
isUpdating = { updating }
120
192
/>
@@ -128,11 +200,17 @@ function UpdateStreamInfo(props: { timePartition: string; currentStream: string
128
200
overflow : 'hidden' ,
129
201
fontWeight : 400 ,
130
202
} } >
131
- { timePartitonLimit !== undefined ? `${ timePartitonLimit } day(s)` : '-' }
203
+ { isStaticSchema
204
+ ? Array . isArray ( value )
205
+ ? value . join ( ',' )
206
+ : '-'
207
+ : typeof value === 'number'
208
+ ? `${ value } day(s)`
209
+ : '-' }
132
210
</ Text >
133
211
) }
134
212
</ Stack >
135
213
) ;
136
- }
214
+ } ;
137
215
138
216
export default UpdateStreamInfo ;
0 commit comments