From 3727508b21577518e269bd6a070eacc9dfb48f66 Mon Sep 17 00:00:00 2001 From: Praveen K B Date: Sat, 9 Nov 2024 10:17:18 +0530 Subject: [PATCH 1/5] Refactor: Merging CustomPartitionLimit & TimePartitionLimit into one component --- src/pages/Stream/Views/Manage/Info.tsx | 13 +- .../Manage/UpdateCustomPartitionField.tsx | 147 ------------------ .../Views/Manage/UpdateTimePartitionLimit.tsx | 138 ---------------- 3 files changed, 3 insertions(+), 295 deletions(-) delete mode 100644 src/pages/Stream/Views/Manage/UpdateCustomPartitionField.tsx delete mode 100644 src/pages/Stream/Views/Manage/UpdateTimePartitionLimit.tsx diff --git a/src/pages/Stream/Views/Manage/Info.tsx b/src/pages/Stream/Views/Manage/Info.tsx index 64d20f08..d00cfa4c 100644 --- a/src/pages/Stream/Views/Manage/Info.tsx +++ b/src/pages/Stream/Views/Manage/Info.tsx @@ -3,10 +3,9 @@ import classes from '../../styles/Management.module.css'; import { useStreamStore } from '../../providers/StreamProvider'; import _ from 'lodash'; import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider'; -import UpdateTimePartitionLimit from './UpdateTimePartitionLimit'; -import UpdateCustomPartitionField from './UpdateCustomPartitionField'; import timeRangeUtils from '@/utils/timeRangeUtils'; import ErrorView from './ErrorView'; +import PartitionLimit from './PartitionLimit'; const { formatDateWithTimezone } = timeRangeUtils; @@ -76,16 +75,10 @@ const InfoData = (props: { isLoading: boolean }) => { - + - + )} diff --git a/src/pages/Stream/Views/Manage/UpdateCustomPartitionField.tsx b/src/pages/Stream/Views/Manage/UpdateCustomPartitionField.tsx deleted file mode 100644 index 2eba0307..00000000 --- a/src/pages/Stream/Views/Manage/UpdateCustomPartitionField.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { Box, Group, Loader, Stack, TagsInput, Tooltip, Text } from '@mantine/core'; -import classes from '../../styles/Management.module.css'; -import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; -import { useStreamStore } from '../../providers/StreamProvider'; -import _ from 'lodash'; -import { useCallback, useEffect, useState } from 'react'; -import { useLogStream } from '@/hooks/useLogStream'; -import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; - -const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => void; isUpdating: boolean }) => { - return ( - - {!props.isUpdating ? ( - - - props.onUpdateClick()} stroke={1.6} size={16} /> - - - - props.onClose()} /> - - - ) : ( - - )} - - ); -}; - -export default function UpdateCustomPartitionField(props: { timePartition: string; currentStream: string }) { - const [info] = useStreamStore((store) => store.info); - const isStaticSchema = _.get(info, 'static_schema_flag', false); - const existingCustomPartition = _.get(info, 'custom_partition', '-').split(','); - const [partitionFields] = useStreamStore((store) => store.fieldNames); - const [value, setValue] = useState([]); - const [updating, setUpdating] = useState(false); - const [showEditField, setShowEditField] = useState(false); - const [error, setError] = useState(null); - const { updateLogStreamMutation } = useLogStream(); - const { getStreamInfoRefetch } = useGetStreamInfo(props.currentStream, props.currentStream !== null); - - useEffect(() => { - const customPartition: string = _.get(info, 'custom_partition', 'EMPTY_VALUE'); - setValue(customPartition !== 'EMPTY_VALUE' ? customPartition.split(',') : []); - }, [props.currentStream, info]); - - const onChangeValue = useCallback( - (value: string[]) => { - setValue(value); - - if (isStaticSchema) { - value?.forEach((el) => { - if (!partitionFields.includes(el)) { - setError('Unknown Field Included'); - } else { - setError(null); - } - }); - } - if (Array.isArray(value) && value.length === 0) { - setError(null); - } - }, - [setValue], - ); - - const updateLogStreamSuccess = useCallback(() => { - getStreamInfoRefetch().then(() => { - setUpdating(false); - setShowEditField(false); - }); - }, [getStreamInfoRefetch]); - - const updateLogStream = useCallback( - (updatedValue: string) => { - updateLogStreamMutation({ - streamName: props.currentStream, - header: { 'x-p-custom-partition': updatedValue }, - onSuccess: updateLogStreamSuccess, - onError: () => { - setUpdating(false), setValue(existingCustomPartition); - }, - }); - }, - [props.currentStream, updateLogStreamMutation], - ); - - const updateCustomPartition = useCallback(() => { - const valuesFlattened = value?.join(','); - - if (valuesFlattened === undefined) return; - if (error !== null) return; - - setUpdating(true); - updateLogStream(valuesFlattened); - }, [value, updateLogStream]); - - return ( - - - - Custom Partition Field - - - - setShowEditField((prev) => !prev)} - /> - - - {showEditField ? ( - - onChangeValue(value)} - maxTags={3} - value={value?.length === 1 && value?.[0] === '' ? undefined : value} - error={error} - /> - setShowEditField(false)} - isUpdating={updating} - /> - - ) : ( - - {existingCustomPartition.join(',')} - - )} - - ); -} diff --git a/src/pages/Stream/Views/Manage/UpdateTimePartitionLimit.tsx b/src/pages/Stream/Views/Manage/UpdateTimePartitionLimit.tsx deleted file mode 100644 index ed868125..00000000 --- a/src/pages/Stream/Views/Manage/UpdateTimePartitionLimit.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import _ from 'lodash'; -import { useStreamStore } from '../../providers/StreamProvider'; -import { ChangeEvent, useCallback, useState, useEffect } from 'react'; -import { useLogStream } from '@/hooks/useLogStream'; -import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; -import { Box, Loader, Stack, TextInput, Tooltip, Text, Group } from '@mantine/core'; -import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; -import classes from '../../styles/Management.module.css'; - -const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => void; isUpdating: boolean }) => { - return ( - - {!props.isUpdating ? ( - - - props.onUpdateClick()} stroke={1.6} size={16} /> - - - - props.onClose()} /> - - - ) : ( - - )} - - ); -}; - -function UpdateTimePartitionLimit(props: { timePartition: string; currentStream: string }) { - const [info] = useStreamStore((store) => store.info); - const timePartitonLimit = _.get(info, 'time_partition_limit'); - const [value, setValue] = useState(timePartitonLimit); - const [updating, setUpdating] = useState(false); - const [error, setError] = useState(null); - const [showEditField, setShowEditField] = useState(false); - const { updateLogStreamMutation } = useLogStream(); - const { getStreamInfoRefetch } = useGetStreamInfo(props.currentStream, props.currentStream !== null); - - useEffect(() => { - setValue(timePartitonLimit); - }, [props.currentStream, info]); - - const onChange = useCallback( - (e: ChangeEvent) => { - const inputTime = e.target.value; - const numberRegex = /^\d*$/; - if (numberRegex.test(inputTime)) { - if (parseInt(inputTime) > 0) { - setValue(parseInt(inputTime)); - setError(null); - } else { - setValue(0); - setError('Number should be higher than zero'); - } - } - }, - [setValue], - ); - - const updateLogStreamSuccess = useCallback(() => { - getStreamInfoRefetch().then(() => { - setUpdating(false); - setShowEditField(false); - }); - }, [getStreamInfoRefetch]); - - const updateLogStream = useCallback( - (updatedValue: number) => { - updateLogStreamMutation({ - streamName: props.currentStream, - header: { 'x-p-time-partition-limit': `${updatedValue}d` }, - onSuccess: updateLogStreamSuccess, - onError: () => setUpdating(false), - }); - }, - [updateLogStreamMutation, props.currentStream], - ); - - const updateTimePartitionLimit = useCallback(() => { - if (value === undefined) return; - if (error !== null) return; - - setUpdating(true); - updateLogStream(value); - }, [value, updateLogStream]); - - return ( - - - - Max Historical Difference - - - {props.timePartition !== '-' && ( - - setShowEditField((prev) => !prev)} - /> - - )} - - {showEditField ? ( - - onChange(e)} - error={error} - /> - setShowEditField(false)} - isUpdating={updating} - /> - - ) : ( - - {timePartitonLimit !== undefined ? `${timePartitonLimit} day(s)` : '-'} - - )} - - ); -} - -export default UpdateTimePartitionLimit; From 0fbaab4fc702aa5835c4b5b21c7661652972f3af Mon Sep 17 00:00:00 2001 From: Praveen K B Date: Sat, 9 Nov 2024 10:53:04 +0530 Subject: [PATCH 2/5] Refactor: New component PartitionLimit --- .../Stream/Views/Manage/PartitionLimit.tsx | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/pages/Stream/Views/Manage/PartitionLimit.tsx diff --git a/src/pages/Stream/Views/Manage/PartitionLimit.tsx b/src/pages/Stream/Views/Manage/PartitionLimit.tsx new file mode 100644 index 00000000..a245b060 --- /dev/null +++ b/src/pages/Stream/Views/Manage/PartitionLimit.tsx @@ -0,0 +1,216 @@ +import { Box, Group, Loader, Stack, TagsInput, Tooltip, Text, TextInput } from '@mantine/core'; +import classes from '../../styles/Management.module.css'; +import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; +import { useStreamStore } from '../../providers/StreamProvider'; +import _ from 'lodash'; +import { ChangeEvent, FC, useCallback, useEffect, useState } from 'react'; +import { useLogStream } from '@/hooks/useLogStream'; +import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; + +interface UpdateFieldButtonsProps { + onClose: () => void; + onUpdateClick: () => void; + isUpdating: boolean; +} + +interface PartitionLimitProps { + timePartition: string; + currentStream: string; +} + +type PartitionValue = string[] | number | undefined; + +const UpdateFieldButtons: FC = ({ onClose, onUpdateClick, isUpdating }) => { + return ( + + {!isUpdating ? ( + + + onUpdateClick()} stroke={1.6} size={16} /> + + + + onClose()} /> + + + ) : ( + + )} + + ); +}; + +const PartitionLimit: FC = ({ timePartition, currentStream }) => { + const [info] = useStreamStore((store) => store.info); + const [partitionFields] = useStreamStore((store) => store.fieldNames); + + const isStaticSchema = _.get(info, 'static_schema_flag', false); + const initialPartitionValue = isStaticSchema + ? _.get(info, 'custom_partition', '-').split(',') + : _.get(info, 'time_partition_limit'); + + const [value, setValue] = useState(initialPartitionValue); + const [updating, setUpdating] = useState(false); + const [error, setError] = useState(null); + const [showEditField, setShowEditField] = useState(false); + + const { updateLogStreamMutation } = useLogStream(); + const { getStreamInfoRefetch } = useGetStreamInfo(currentStream, currentStream !== null); + + useEffect(() => { + setValue(initialPartitionValue); + }, [currentStream, info, initialPartitionValue]); + + const handleCustomPartitionChange = useCallback( + (value: string[]) => { + setValue(value); + + if (isStaticSchema) { + value?.forEach((el) => { + if (!partitionFields.includes(el)) { + setError('Unknown Field Included'); + } else { + setError(null); + } + }); + } + if (Array.isArray(value) && value.length === 0) { + setError(null); + } + }, + [setValue], + ); + + const handleTimePartitionChange = useCallback( + (e: ChangeEvent) => { + const inputTime = e.target.value; + const numberRegex = /^\d*$/; + if (numberRegex.test(inputTime)) { + const parsedValue = parseInt(inputTime); + if (parsedValue > 0) { + setValue(parsedValue); + setError(null); + } else { + setValue(0); + setError('Number should be higher than zero'); + } + } + }, + [setValue], + ); + + const updateLogStreamSuccess = useCallback(() => { + getStreamInfoRefetch().then(() => { + setUpdating(false); + setShowEditField(false); + }); + }, [getStreamInfoRefetch]); + + const updateLogStream = useCallback( + (updatedValue: string | number) => { + updateLogStreamMutation({ + streamName: currentStream, + header: isStaticSchema + ? { 'x-p-custom-partition': String(updatedValue) } + : { 'x-p-time-partition-limit': `${updatedValue}d` }, + onSuccess: updateLogStreamSuccess, + onError: () => setUpdating(false), + }); + }, + [updateLogStreamMutation, currentStream, isStaticSchema], + ); + + const updatePartitionLimit = useCallback(() => { + if (error) return; + if (isStaticSchema) { + if (!Array.isArray(value) || value.length === 0) return; + setUpdating(true); + updateLogStream(value.join(',')); + } else { + if (typeof value !== 'number') return; + setUpdating(true); + updateLogStream(value); + } + }, [value, updateLogStream]); + + return ( + + + + {isStaticSchema ? 'Custom Partition Field' : 'Max Historical Difference'} + + + {timePartition !== '-' && !isStaticSchema && ( + + setShowEditField((prev) => !prev)} + /> + + )} + {isStaticSchema && !showEditField && ( + + setShowEditField((prev) => !prev)} + /> + + )} + + + {showEditField ? ( + + {isStaticSchema ? ( + + ) : ( + + )} + + setShowEditField(false)} + isUpdating={updating} + /> + + ) : ( + + {isStaticSchema + ? Array.isArray(value) + ? value.join(',') + : '-' + : typeof value === 'number' + ? `${value} day(s)` + : '-'} + + )} + + ); +}; + +export default PartitionLimit; From adfdd141c703e4a8b8dc55bac21556f0e335aec4 Mon Sep 17 00:00:00 2001 From: Praveen K B Date: Mon, 11 Nov 2024 16:59:27 +0530 Subject: [PATCH 3/5] Renamed the component name --- src/pages/Stream/Views/Manage/Info.tsx | 6 +- .../Stream/Views/Manage/PartitionLimit.tsx | 216 ------------------ 2 files changed, 3 insertions(+), 219 deletions(-) delete mode 100644 src/pages/Stream/Views/Manage/PartitionLimit.tsx diff --git a/src/pages/Stream/Views/Manage/Info.tsx b/src/pages/Stream/Views/Manage/Info.tsx index d00cfa4c..d2fec7f4 100644 --- a/src/pages/Stream/Views/Manage/Info.tsx +++ b/src/pages/Stream/Views/Manage/Info.tsx @@ -5,7 +5,7 @@ import _ from 'lodash'; import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider'; import timeRangeUtils from '@/utils/timeRangeUtils'; import ErrorView from './ErrorView'; -import PartitionLimit from './PartitionLimit'; +import UpdateStreamInfo from './UpdateStreamInfo'; const { formatDateWithTimezone } = timeRangeUtils; @@ -75,10 +75,10 @@ const InfoData = (props: { isLoading: boolean }) => { - + - + )} diff --git a/src/pages/Stream/Views/Manage/PartitionLimit.tsx b/src/pages/Stream/Views/Manage/PartitionLimit.tsx deleted file mode 100644 index a245b060..00000000 --- a/src/pages/Stream/Views/Manage/PartitionLimit.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { Box, Group, Loader, Stack, TagsInput, Tooltip, Text, TextInput } from '@mantine/core'; -import classes from '../../styles/Management.module.css'; -import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; -import { useStreamStore } from '../../providers/StreamProvider'; -import _ from 'lodash'; -import { ChangeEvent, FC, useCallback, useEffect, useState } from 'react'; -import { useLogStream } from '@/hooks/useLogStream'; -import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; - -interface UpdateFieldButtonsProps { - onClose: () => void; - onUpdateClick: () => void; - isUpdating: boolean; -} - -interface PartitionLimitProps { - timePartition: string; - currentStream: string; -} - -type PartitionValue = string[] | number | undefined; - -const UpdateFieldButtons: FC = ({ onClose, onUpdateClick, isUpdating }) => { - return ( - - {!isUpdating ? ( - - - onUpdateClick()} stroke={1.6} size={16} /> - - - - onClose()} /> - - - ) : ( - - )} - - ); -}; - -const PartitionLimit: FC = ({ timePartition, currentStream }) => { - const [info] = useStreamStore((store) => store.info); - const [partitionFields] = useStreamStore((store) => store.fieldNames); - - const isStaticSchema = _.get(info, 'static_schema_flag', false); - const initialPartitionValue = isStaticSchema - ? _.get(info, 'custom_partition', '-').split(',') - : _.get(info, 'time_partition_limit'); - - const [value, setValue] = useState(initialPartitionValue); - const [updating, setUpdating] = useState(false); - const [error, setError] = useState(null); - const [showEditField, setShowEditField] = useState(false); - - const { updateLogStreamMutation } = useLogStream(); - const { getStreamInfoRefetch } = useGetStreamInfo(currentStream, currentStream !== null); - - useEffect(() => { - setValue(initialPartitionValue); - }, [currentStream, info, initialPartitionValue]); - - const handleCustomPartitionChange = useCallback( - (value: string[]) => { - setValue(value); - - if (isStaticSchema) { - value?.forEach((el) => { - if (!partitionFields.includes(el)) { - setError('Unknown Field Included'); - } else { - setError(null); - } - }); - } - if (Array.isArray(value) && value.length === 0) { - setError(null); - } - }, - [setValue], - ); - - const handleTimePartitionChange = useCallback( - (e: ChangeEvent) => { - const inputTime = e.target.value; - const numberRegex = /^\d*$/; - if (numberRegex.test(inputTime)) { - const parsedValue = parseInt(inputTime); - if (parsedValue > 0) { - setValue(parsedValue); - setError(null); - } else { - setValue(0); - setError('Number should be higher than zero'); - } - } - }, - [setValue], - ); - - const updateLogStreamSuccess = useCallback(() => { - getStreamInfoRefetch().then(() => { - setUpdating(false); - setShowEditField(false); - }); - }, [getStreamInfoRefetch]); - - const updateLogStream = useCallback( - (updatedValue: string | number) => { - updateLogStreamMutation({ - streamName: currentStream, - header: isStaticSchema - ? { 'x-p-custom-partition': String(updatedValue) } - : { 'x-p-time-partition-limit': `${updatedValue}d` }, - onSuccess: updateLogStreamSuccess, - onError: () => setUpdating(false), - }); - }, - [updateLogStreamMutation, currentStream, isStaticSchema], - ); - - const updatePartitionLimit = useCallback(() => { - if (error) return; - if (isStaticSchema) { - if (!Array.isArray(value) || value.length === 0) return; - setUpdating(true); - updateLogStream(value.join(',')); - } else { - if (typeof value !== 'number') return; - setUpdating(true); - updateLogStream(value); - } - }, [value, updateLogStream]); - - return ( - - - - {isStaticSchema ? 'Custom Partition Field' : 'Max Historical Difference'} - - - {timePartition !== '-' && !isStaticSchema && ( - - setShowEditField((prev) => !prev)} - /> - - )} - {isStaticSchema && !showEditField && ( - - setShowEditField((prev) => !prev)} - /> - - )} - - - {showEditField ? ( - - {isStaticSchema ? ( - - ) : ( - - )} - - setShowEditField(false)} - isUpdating={updating} - /> - - ) : ( - - {isStaticSchema - ? Array.isArray(value) - ? value.join(',') - : '-' - : typeof value === 'number' - ? `${value} day(s)` - : '-'} - - )} - - ); -}; - -export default PartitionLimit; From 8410f3ac1e3dcd3438b3421e7a6d3f5394fa8a56 Mon Sep 17 00:00:00 2001 From: Praveen K B Date: Tue, 12 Nov 2024 10:33:29 +0530 Subject: [PATCH 4/5] Added the new UpdateStreamInfo file --- .../Stream/Views/Manage/UpdateStreamInfo.tsx | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx diff --git a/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx b/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx new file mode 100644 index 00000000..8869ad66 --- /dev/null +++ b/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx @@ -0,0 +1,138 @@ +import _ from 'lodash'; +import { useStreamStore } from '../../providers/StreamProvider'; +import { ChangeEvent, useCallback, useState, useEffect } from 'react'; +import { useLogStream } from '@/hooks/useLogStream'; +import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; +import { Box, Loader, Stack, TextInput, Tooltip, Text, Group } from '@mantine/core'; +import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; +import classes from '../../styles/Management.module.css'; + +const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => void; isUpdating: boolean }) => { + return ( + + {!props.isUpdating ? ( + + + props.onUpdateClick()} stroke={1.6} size={16} /> + + + + props.onClose()} /> + + + ) : ( + + )} + + ); +}; + +function UpdateStreamInfo(props: { timePartition: string; currentStream: string }) { + const [info] = useStreamStore((store) => store.info); + const timePartitonLimit = _.get(info, 'time_partition_limit'); + const [value, setValue] = useState(timePartitonLimit); + const [updating, setUpdating] = useState(false); + const [error, setError] = useState(null); + const [showEditField, setShowEditField] = useState(false); + const { updateLogStreamMutation } = useLogStream(); + const { getStreamInfoRefetch } = useGetStreamInfo(props.currentStream, props.currentStream !== null); + + useEffect(() => { + setValue(timePartitonLimit); + }, [props.currentStream, info]); + + const onChange = useCallback( + (e: ChangeEvent) => { + const inputTime = e.target.value; + const numberRegex = /^\d*$/; + if (numberRegex.test(inputTime)) { + if (parseInt(inputTime) > 0) { + setValue(parseInt(inputTime)); + setError(null); + } else { + setValue(0); + setError('Number should be higher than zero'); + } + } + }, + [setValue], + ); + + const updateLogStreamSuccess = useCallback(() => { + getStreamInfoRefetch().then(() => { + setUpdating(false); + setShowEditField(false); + }); + }, [getStreamInfoRefetch]); + + const updateLogStream = useCallback( + (updatedValue: number) => { + updateLogStreamMutation({ + streamName: props.currentStream, + header: { 'x-p-time-partition-limit': `${updatedValue}d` }, + onSuccess: updateLogStreamSuccess, + onError: () => setUpdating(false), + }); + }, + [updateLogStreamMutation, props.currentStream], + ); + + const updateTimePartitionLimit = useCallback(() => { + if (value === undefined) return; + if (error !== null) return; + + setUpdating(true); + updateLogStream(value); + }, [value, updateLogStream]); + + return ( + + + + Max Historical Difference + + + {props.timePartition !== '-' && ( + + setShowEditField((prev) => !prev)} + /> + + )} + + {showEditField ? ( + + onChange(e)} + error={error} + /> + setShowEditField(false)} + isUpdating={updating} + /> + + ) : ( + + {timePartitonLimit !== undefined ? `${timePartitonLimit} day(s)` : '-'} + + )} + + ); +} + +export default UpdateStreamInfo; From f172f661a2c9abf7f3a55167bd5baec9ce282f8d Mon Sep 17 00:00:00 2001 From: Praveen K B Date: Tue, 12 Nov 2024 10:35:14 +0530 Subject: [PATCH 5/5] Added the new UpdateStreamInfo file --- .../Stream/Views/Manage/UpdateStreamInfo.tsx | 162 +++++++++++++----- 1 file changed, 120 insertions(+), 42 deletions(-) diff --git a/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx b/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx index 8869ad66..11c0f9cd 100644 --- a/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx +++ b/src/pages/Stream/Views/Manage/UpdateStreamInfo.tsx @@ -1,23 +1,36 @@ -import _ from 'lodash'; +import { Box, Group, Loader, Stack, TagsInput, Tooltip, Text, TextInput } from '@mantine/core'; +import classes from '../../styles/Management.module.css'; +import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; import { useStreamStore } from '../../providers/StreamProvider'; -import { ChangeEvent, useCallback, useState, useEffect } from 'react'; +import _ from 'lodash'; +import { ChangeEvent, FC, useCallback, useEffect, useState } from 'react'; import { useLogStream } from '@/hooks/useLogStream'; import { useGetStreamInfo } from '@/hooks/useGetStreamInfo'; -import { Box, Loader, Stack, TextInput, Tooltip, Text, Group } from '@mantine/core'; -import { IconCheck, IconX, IconEdit } from '@tabler/icons-react'; -import classes from '../../styles/Management.module.css'; -const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => void; isUpdating: boolean }) => { +interface UpdateFieldButtonsProps { + onClose: () => void; + onUpdateClick: () => void; + isUpdating: boolean; +} + +interface PartitionLimitProps { + timePartition: string; + currentStream: string; +} + +type PartitionValue = string[] | number | undefined; + +const UpdateFieldButtons: FC = ({ onClose, onUpdateClick, isUpdating }) => { return ( - {!props.isUpdating ? ( + {!isUpdating ? ( - props.onUpdateClick()} stroke={1.6} size={16} /> + onUpdateClick()} stroke={1.6} size={16} /> - props.onClose()} /> + onClose()} /> ) : ( @@ -27,27 +40,55 @@ const UpdateFieldButtons = (props: { onClose: () => void; onUpdateClick: () => v ); }; -function UpdateStreamInfo(props: { timePartition: string; currentStream: string }) { +const UpdateStreamInfo: FC = ({ timePartition, currentStream }) => { const [info] = useStreamStore((store) => store.info); - const timePartitonLimit = _.get(info, 'time_partition_limit'); - const [value, setValue] = useState(timePartitonLimit); - const [updating, setUpdating] = useState(false); + const [partitionFields] = useStreamStore((store) => store.fieldNames); + + const isStaticSchema = _.get(info, 'static_schema_flag', false); + const initialPartitionValue = isStaticSchema + ? _.get(info, 'custom_partition', '-').split(',') + : _.get(info, 'time_partition_limit'); + + const [value, setValue] = useState(initialPartitionValue); + const [updating, setUpdating] = useState(false); const [error, setError] = useState(null); - const [showEditField, setShowEditField] = useState(false); + const [showEditField, setShowEditField] = useState(false); + const { updateLogStreamMutation } = useLogStream(); - const { getStreamInfoRefetch } = useGetStreamInfo(props.currentStream, props.currentStream !== null); + const { getStreamInfoRefetch } = useGetStreamInfo(currentStream, currentStream !== null); useEffect(() => { - setValue(timePartitonLimit); - }, [props.currentStream, info]); + setValue(initialPartitionValue); + }, [currentStream, info, initialPartitionValue]); + + const handleCustomPartitionChange = useCallback( + (value: string[]) => { + setValue(value); + + if (isStaticSchema) { + value?.forEach((el) => { + if (!partitionFields.includes(el)) { + setError('Unknown Field Included'); + } else { + setError(null); + } + }); + } + if (Array.isArray(value) && value.length === 0) { + setError(null); + } + }, + [setValue], + ); - const onChange = useCallback( + const handleTimePartitionChange = useCallback( (e: ChangeEvent) => { const inputTime = e.target.value; const numberRegex = /^\d*$/; if (numberRegex.test(inputTime)) { - if (parseInt(inputTime) > 0) { - setValue(parseInt(inputTime)); + const parsedValue = parseInt(inputTime); + if (parsedValue > 0) { + setValue(parsedValue); setError(null); } else { setValue(0); @@ -66,35 +107,52 @@ function UpdateStreamInfo(props: { timePartition: string; currentStream: string }, [getStreamInfoRefetch]); const updateLogStream = useCallback( - (updatedValue: number) => { + (updatedValue: string | number) => { updateLogStreamMutation({ - streamName: props.currentStream, - header: { 'x-p-time-partition-limit': `${updatedValue}d` }, + streamName: currentStream, + header: isStaticSchema + ? { 'x-p-custom-partition': String(updatedValue) } + : { 'x-p-time-partition-limit': `${updatedValue}d` }, onSuccess: updateLogStreamSuccess, onError: () => setUpdating(false), }); }, - [updateLogStreamMutation, props.currentStream], + [updateLogStreamMutation, currentStream, isStaticSchema], ); - const updateTimePartitionLimit = useCallback(() => { - if (value === undefined) return; - if (error !== null) return; - - setUpdating(true); - updateLogStream(value); + const updatePartitionLimit = useCallback(() => { + if (error) return; + if (isStaticSchema) { + if (!Array.isArray(value) || value.length === 0) return; + setUpdating(true); + updateLogStream(value.join(',')); + } else { + if (typeof value !== 'number') return; + setUpdating(true); + updateLogStream(value); + } }, [value, updateLogStream]); return ( - + - Max Historical Difference + {isStaticSchema ? 'Custom Partition Field' : 'Max Historical Difference'} - {props.timePartition !== '-' && ( + {timePartition !== '-' && !isStaticSchema && ( + + setShowEditField((prev) => !prev)} + /> + + )} + {isStaticSchema && !showEditField && ( )} + {showEditField ? ( - onChange(e)} - error={error} - /> + {isStaticSchema ? ( + + ) : ( + + )} + setShowEditField(false)} isUpdating={updating} /> @@ -128,11 +200,17 @@ function UpdateStreamInfo(props: { timePartition: string; currentStream: string overflow: 'hidden', fontWeight: 400, }}> - {timePartitonLimit !== undefined ? `${timePartitonLimit} day(s)` : '-'} + {isStaticSchema + ? Array.isArray(value) + ? value.join(',') + : '-' + : typeof value === 'number' + ? `${value} day(s)` + : '-'} )} ); -} +}; export default UpdateStreamInfo;