feat: ingestion limits - add toggle feature (#6430)

This commit is contained in:
Yunus M 2024-11-15 14:02:31 +05:30 committed by GitHub
parent 2faa0c6d4f
commit 504bc0d541
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 251 additions and 118 deletions

View File

@ -18,8 +18,13 @@
font-style: normal; font-style: normal;
font-weight: var(--font-weight-normal); font-weight: var(--font-weight-normal);
line-height: 28px; line-height: 28px;
/* 155.556% */
letter-spacing: -0.09px; letter-spacing: -0.09px;
width: 72%; // arbitrary number to match input width
display: flex;
align-items: center;
gap: 8px;
justify-content: space-between;
} }
.subtitle { .subtitle {
@ -356,6 +361,8 @@
flex: 1; flex: 1;
.heading { .heading {
margin-bottom: 8px;
.title { .title {
font-size: 12px; font-size: 12px;
} }
@ -370,6 +377,18 @@
.ant-input-number { .ant-input-number {
width: 80%; width: 80%;
} }
.no-limit {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 24px;
font-weight: 700;
font-size: 12px;
color: var(--bg-forest-400);
}
} }
.signal-limit-view-mode { .signal-limit-view-mode {

View File

@ -12,6 +12,7 @@ import {
Modal, Modal,
Row, Row,
Select, Select,
Switch,
Table, Table,
TablePaginationConfig, TablePaginationConfig,
TableProps as AntDTableProps, TableProps as AntDTableProps,
@ -34,7 +35,7 @@ import dayjs, { Dayjs } from 'dayjs';
import { useGetAllIngestionsKeys } from 'hooks/IngestionKeys/useGetAllIngestionKeys'; import { useGetAllIngestionsKeys } from 'hooks/IngestionKeys/useGetAllIngestionKeys';
import useDebouncedFn from 'hooks/useDebouncedFunction'; import useDebouncedFn from 'hooks/useDebouncedFunction';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { isNil } from 'lodash-es'; import { isNil, isUndefined } from 'lodash-es';
import { import {
ArrowUpRight, ArrowUpRight,
CalendarClock, CalendarClock,
@ -395,84 +396,6 @@ function MultiIngestionSettings(): JSX.Element {
const getFormattedTime = (date: string): string => const getFormattedTime = (date: string): string =>
dayjs(date).format('MMM DD,YYYY, hh:mm a'); dayjs(date).format('MMM DD,YYYY, hh:mm a');
const handleAddLimit = (
APIKey: IngestionKeyProps,
signalName: string,
): void => {
setActiveSignal({
id: signalName,
signal: signalName,
config: {},
});
const { dailyLimit, secondsLimit } = addEditLimitForm.getFieldsValue();
const payload = {
keyID: APIKey.id,
signal: signalName,
config: {
day: {
size: gbToBytes(dailyLimit),
},
second: {
size: gbToBytes(secondsLimit),
},
},
};
createLimitForIngestionKey(payload);
};
const handleUpdateLimit = (
APIKey: IngestionKeyProps,
signal: LimitProps,
): void => {
setActiveSignal(signal);
const { dailyLimit, secondsLimit } = addEditLimitForm.getFieldsValue();
const payload = {
limitID: signal.id,
signal: signal.signal,
config: {
day: {
size: gbToBytes(dailyLimit),
},
second: {
size: gbToBytes(secondsLimit),
},
},
};
updateLimitForIngestionKey(payload);
};
const bytesToGb = (size: number | undefined): number => {
if (!size) {
return 0;
}
return size / BYTES;
};
const enableEditLimitMode = (
APIKey: IngestionKeyProps,
signal: LimitProps,
): void => {
setActiveAPIKey(APIKey);
setActiveSignal(signal);
addEditLimitForm.setFieldsValue({
dailyLimit: bytesToGb(signal?.config?.day?.size || 0),
secondsLimit: bytesToGb(signal?.config?.second?.size || 0),
});
setIsEditAddLimitOpen(true);
};
const onDeleteLimitHandler = (): void => {
if (activeSignal && activeSignal?.id) {
deleteLimitForKey(activeSignal.id);
}
};
const showDeleteLimitModal = ( const showDeleteLimitModal = (
APIKey: IngestionKeyProps, APIKey: IngestionKeyProps,
limit: LimitProps, limit: LimitProps,
@ -496,6 +419,131 @@ function MultiIngestionSettings(): JSX.Element {
addEditLimitForm.resetFields(); addEditLimitForm.resetFields();
}; };
const handleAddLimit = (
APIKey: IngestionKeyProps,
signalName: string,
): void => {
const { dailyLimit, secondsLimit } = addEditLimitForm.getFieldsValue();
const payload = {
keyID: APIKey.id,
signal: signalName,
config: {},
};
if (!isUndefined(dailyLimit)) {
payload.config = {
day: {
size: gbToBytes(dailyLimit),
},
};
}
if (!isUndefined(secondsLimit)) {
payload.config = {
...payload.config,
second: {
size: gbToBytes(secondsLimit),
},
};
}
if (isUndefined(dailyLimit) && isUndefined(secondsLimit)) {
// No need to save as no limit is provided, close the edit view and reset active signal and api key
setActiveSignal(null);
setActiveAPIKey(null);
setIsEditAddLimitOpen(false);
setUpdatedTags([]);
hideAddViewModal();
setHasCreateLimitForIngestionKeyError(false);
return;
}
createLimitForIngestionKey(payload);
};
const handleUpdateLimit = (
APIKey: IngestionKeyProps,
signal: LimitProps,
): void => {
const { dailyLimit, secondsLimit } = addEditLimitForm.getFieldsValue();
const payload = {
limitID: signal.id,
signal: signal.signal,
config: {},
};
if (isUndefined(dailyLimit) && isUndefined(secondsLimit)) {
showDeleteLimitModal(APIKey, signal);
return;
}
if (!isUndefined(dailyLimit)) {
payload.config = {
day: {
size: gbToBytes(dailyLimit),
},
};
}
if (!isUndefined(secondsLimit)) {
payload.config = {
...payload.config,
second: {
size: gbToBytes(secondsLimit),
},
};
}
updateLimitForIngestionKey(payload);
};
const bytesToGb = (size: number | undefined): number => {
if (!size) {
return 0;
}
return size / BYTES;
};
const enableEditLimitMode = (
APIKey: IngestionKeyProps,
signal: LimitProps,
): void => {
setActiveAPIKey(APIKey);
setActiveSignal({
...signal,
config: {
...signal.config,
day: {
...signal.config?.day,
enabled: !isNil(signal?.config?.day?.size),
},
second: {
...signal.config?.second,
enabled: !isNil(signal?.config?.second?.size),
},
},
});
addEditLimitForm.setFieldsValue({
dailyLimit: bytesToGb(signal?.config?.day?.size || 0),
secondsLimit: bytesToGb(signal?.config?.second?.size || 0),
enableDailyLimit: !isNil(signal?.config?.day?.size),
enableSecondLimit: !isNil(signal?.config?.second?.size),
});
setIsEditAddLimitOpen(true);
};
const onDeleteLimitHandler = (): void => {
if (activeSignal && activeSignal?.id) {
deleteLimitForKey(activeSignal.id);
}
};
const columns: AntDTableProps<IngestionKeyProps>['columns'] = [ const columns: AntDTableProps<IngestionKeyProps>['columns'] = [
{ {
title: 'Ingestion Key', title: 'Ingestion Key',
@ -684,15 +732,39 @@ function MultiIngestionSettings(): JSX.Element {
<div className="signal-limit-edit-mode"> <div className="signal-limit-edit-mode">
<div className="daily-limit"> <div className="daily-limit">
<div className="heading"> <div className="heading">
<div className="title"> Daily limit </div> <div className="title">
Daily limit
<div className="limit-enable-disable-toggle">
<Form.Item name="enableDailyLimit">
<Switch
size="small"
checked={activeSignal?.config?.day?.enabled}
onChange={(value): void => {
setActiveSignal({
...activeSignal,
config: {
...activeSignal.config,
day: {
...activeSignal.config?.day,
enabled: value,
},
},
});
}}
/>
</Form.Item>
</div>
</div>
<div className="subtitle"> <div className="subtitle">
Add a limit for data ingested daily{' '} Add a limit for data ingested daily
</div> </div>
</div> </div>
<div className="size"> <div className="size">
<Form.Item name="dailyLimit"> {activeSignal?.config?.day?.enabled ? (
<Form.Item name="dailyLimit" key="dailyLimit">
<InputNumber <InputNumber
disabled={!activeSignal?.config?.day?.enabled}
key="dailyLimit"
addonAfter={ addonAfter={
<Select defaultValue="GiB" disabled> <Select defaultValue="GiB" disabled>
<Option value="TiB"> TiB</Option> <Option value="TiB"> TiB</Option>
@ -703,21 +775,50 @@ function MultiIngestionSettings(): JSX.Element {
} }
/> />
</Form.Item> </Form.Item>
) : (
<div className="no-limit">
<Infinity size={16} /> NO LIMIT
</div>
)}
</div> </div>
</div> </div>
<div className="second-limit"> <div className="second-limit">
<div className="heading"> <div className="heading">
<div className="title"> Per Second limit </div> <div className="title">
Per Second limit{' '}
<div className="limit-enable-disable-toggle">
<Form.Item name="enableSecondLimit">
<Switch
size="small"
checked={activeSignal?.config?.second?.enabled}
onChange={(value): void => {
setActiveSignal({
...activeSignal,
config: {
...activeSignal.config,
second: {
...activeSignal.config?.second,
enabled: value,
},
},
});
}}
/>
</Form.Item>
</div>
</div>
<div className="subtitle"> <div className="subtitle">
{' '} Add a limit for data ingested every second
Add a limit for data ingested every second{' '}
</div> </div>
</div> </div>
<div className="size"> <div className="size">
<Form.Item name="secondsLimit"> {activeSignal?.config?.second?.enabled ? (
<Form.Item name="secondsLimit" key="secondsLimit">
<InputNumber <InputNumber
key="secondsLimit"
disabled={!activeSignal?.config?.second?.enabled}
addonAfter={ addonAfter={
<Select defaultValue="GiB" disabled> <Select defaultValue="GiB" disabled>
<Option value="TiB"> TiB</Option> <Option value="TiB"> TiB</Option>
@ -728,6 +829,11 @@ function MultiIngestionSettings(): JSX.Element {
} }
/> />
</Form.Item> </Form.Item>
) : (
<div className="no-limit">
<Infinity size={16} /> NO LIMIT
</div>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@ -8,17 +8,21 @@ export interface LimitProps {
config?: { config?: {
day?: { day?: {
size?: number; size?: number;
enabled?: boolean;
}; };
second?: { second?: {
size?: number; size?: number;
enabled?: boolean;
}; };
}; };
metric?: { metric?: {
day?: { day?: {
size?: number; size?: number;
enabled?: boolean;
}; };
second?: { second?: {
size?: number; size?: number;
enabled?: boolean;
}; };
}; };
} }
@ -27,11 +31,13 @@ export interface AddLimitProps {
keyID: string; keyID: string;
signal: string; signal: string;
config: { config: {
day: { day?: {
size: number; size?: number;
enabled?: boolean;
}; };
second: { second?: {
size: number; size?: number;
enabled?: boolean;
}; };
}; };
} }
@ -40,11 +46,13 @@ export interface UpdateLimitProps {
limitID: string; limitID: string;
signal: string; signal: string;
config: { config: {
day: { day?: {
size: number; size?: number;
enabled?: boolean;
}; };
second: { second?: {
size: number; size?: number;
enabled?: boolean;
}; };
}; };
} }