mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 05:55:59 +08:00
chore: add logs pipelines nav and update logs pipelines title and routes (#3858)
* chore: update logs pipelines title and routes * chore: add nav for logs pipelines * feat: debounced pipelines sarch on change, navigation text changes * fix: get lint passing * fix: update snapshots for tests --------- Co-authored-by: Yunus A M <myounis.ar@live.com>
This commit is contained in:
parent
ec3eba612c
commit
ed3017d247
@ -32,6 +32,7 @@
|
|||||||
"LOGS": "SigNoz | Logs",
|
"LOGS": "SigNoz | Logs",
|
||||||
"LOGS_EXPLORER": "SigNoz | Logs Explorer",
|
"LOGS_EXPLORER": "SigNoz | Logs Explorer",
|
||||||
"LIVE_LOGS": "SigNoz | Live Logs",
|
"LIVE_LOGS": "SigNoz | Live Logs",
|
||||||
|
"LOGS_PIPELINES": "SigNoz | Logs Pipelines",
|
||||||
"HOME_PAGE": "Open source Observability Platform | SigNoz",
|
"HOME_PAGE": "Open source Observability Platform | SigNoz",
|
||||||
"PASSWORD_RESET": "SigNoz | Password Reset",
|
"PASSWORD_RESET": "SigNoz | Password Reset",
|
||||||
"LIST_LICENSES": "SigNoz | List of Licenses",
|
"LIST_LICENSES": "SigNoz | List of Licenses",
|
||||||
|
@ -282,10 +282,10 @@ const routes: AppRoutes[] = [
|
|||||||
isPrivate: false,
|
isPrivate: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ROUTES.PIPELINES,
|
path: ROUTES.LOGS_PIPELINES,
|
||||||
exact: true,
|
exact: true,
|
||||||
component: PipelinePage,
|
component: PipelinePage,
|
||||||
key: 'PIPELINES',
|
key: 'LOGS_PIPELINES',
|
||||||
isPrivate: true,
|
isPrivate: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -31,13 +31,12 @@ const ROUTES = {
|
|||||||
LOGS: '/logs',
|
LOGS: '/logs',
|
||||||
LOGS_EXPLORER: '/logs-explorer',
|
LOGS_EXPLORER: '/logs-explorer',
|
||||||
LIVE_LOGS: '/logs-explorer/live',
|
LIVE_LOGS: '/logs-explorer/live',
|
||||||
|
LOGS_PIPELINES: '/pipelines',
|
||||||
HOME_PAGE: '/',
|
HOME_PAGE: '/',
|
||||||
PASSWORD_RESET: '/password-reset',
|
PASSWORD_RESET: '/password-reset',
|
||||||
LIST_LICENSES: '/licenses',
|
LIST_LICENSES: '/licenses',
|
||||||
LOGS_INDEX_FIELDS: '/logs-explorer/index-fields',
|
LOGS_INDEX_FIELDS: '/logs-explorer/index-fields',
|
||||||
LOGS_PIPELINE: '/logs-explorer/pipeline',
|
|
||||||
TRACE_EXPLORER: '/trace-explorer',
|
TRACE_EXPLORER: '/trace-explorer',
|
||||||
PIPELINES: '/pipelines',
|
|
||||||
BILLING: '/billing',
|
BILLING: '/billing',
|
||||||
SUPPORT: '/support',
|
SUPPORT: '/support',
|
||||||
WORKSPACE_LOCKED: '/workspace-locked',
|
WORKSPACE_LOCKED: '/workspace-locked',
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Input } from 'antd';
|
import { Input } from 'antd';
|
||||||
import React, { Dispatch, SetStateAction, useCallback } from 'react';
|
import { debounce } from 'lodash-es';
|
||||||
|
import { BaseSyntheticEvent, Dispatch, SetStateAction } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
function PipelinesSearchSection({
|
function PipelinesSearchSection({
|
||||||
@ -7,18 +8,18 @@ function PipelinesSearchSection({
|
|||||||
}: PipelinesSearchSectionProps): JSX.Element {
|
}: PipelinesSearchSectionProps): JSX.Element {
|
||||||
const { t } = useTranslation(['pipeline']);
|
const { t } = useTranslation(['pipeline']);
|
||||||
|
|
||||||
const onSeachHandler = useCallback(
|
const handleSearch = (searchEv: BaseSyntheticEvent): void => {
|
||||||
(event: React.SetStateAction<string>) => {
|
setPipelineSearchValue(searchEv?.target?.value || '');
|
||||||
setPipelineSearchValue(event);
|
};
|
||||||
},
|
|
||||||
[setPipelineSearchValue],
|
const debouncedHandleSearch = debounce(handleSearch, 300);
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input.Search
|
<Input
|
||||||
|
type="text"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder={t('search_pipeline_placeholder')}
|
placeholder={t('search_pipeline_placeholder')}
|
||||||
onSearch={onSeachHandler}
|
onChange={debouncedHandleSearch}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,8 @@ import {
|
|||||||
|
|
||||||
import { tableComponents } from '../config';
|
import { tableComponents } from '../config';
|
||||||
import { ModalFooterTitle } from '../styles';
|
import { ModalFooterTitle } from '../styles';
|
||||||
import { AlertMessage } from '.';
|
|
||||||
import { processorColumns } from './config';
|
import { processorColumns } from './config';
|
||||||
|
import { AlertMessage } from './PipelineListsView';
|
||||||
import { FooterButton, StyledTable } from './styles';
|
import { FooterButton, StyledTable } from './styles';
|
||||||
import DragAction from './TableComponents/DragAction';
|
import DragAction from './TableComponents/DragAction';
|
||||||
import ProcessorActions from './TableComponents/ProcessorActions';
|
import ProcessorActions from './TableComponents/ProcessorActions';
|
||||||
|
@ -0,0 +1,489 @@
|
|||||||
|
import { ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { Modal, Table } from 'antd';
|
||||||
|
import { ExpandableConfig } from 'antd/es/table/interface';
|
||||||
|
import savePipeline from 'api/pipeline/post';
|
||||||
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
|
import cloneDeep from 'lodash-es/cloneDeep';
|
||||||
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { DndProvider } from 'react-dnd';
|
||||||
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
ActionMode,
|
||||||
|
ActionType,
|
||||||
|
Pipeline,
|
||||||
|
PipelineData,
|
||||||
|
ProcessorData,
|
||||||
|
} from 'types/api/pipeline/def';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { tableComponents } from '../config';
|
||||||
|
import AddNewPipeline from './AddNewPipeline';
|
||||||
|
import AddNewProcessor from './AddNewProcessor';
|
||||||
|
import { pipelineColumns } from './config';
|
||||||
|
import ModeAndConfiguration from './ModeAndConfiguration';
|
||||||
|
import PipelineExpanView from './PipelineExpandView';
|
||||||
|
import SaveConfigButton from './SaveConfigButton';
|
||||||
|
import {
|
||||||
|
AlertContentWrapper,
|
||||||
|
AlertModalTitle,
|
||||||
|
Container,
|
||||||
|
FooterButton,
|
||||||
|
} from './styles';
|
||||||
|
import DragAction from './TableComponents/DragAction';
|
||||||
|
import PipelineActions from './TableComponents/PipelineActions';
|
||||||
|
import PreviewAction from './TableComponents/PipelineActions/components/PreviewAction';
|
||||||
|
import TableExpandIcon from './TableComponents/TableExpandIcon';
|
||||||
|
import {
|
||||||
|
getDataOnSearch,
|
||||||
|
getEditedDataSource,
|
||||||
|
getElementFromArray,
|
||||||
|
getRecordIndex,
|
||||||
|
getTableColumn,
|
||||||
|
getUpdatedRow,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
|
function PipelineListsView({
|
||||||
|
isActionType,
|
||||||
|
setActionType,
|
||||||
|
isActionMode,
|
||||||
|
setActionMode,
|
||||||
|
pipelineData,
|
||||||
|
refetchPipelineLists,
|
||||||
|
pipelineSearchValue,
|
||||||
|
}: PipelineListsViewProps): JSX.Element {
|
||||||
|
const { t } = useTranslation(['pipeline', 'common']);
|
||||||
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
|
const { notifications } = useNotifications();
|
||||||
|
const [prevPipelineData, setPrevPipelineData] = useState<Array<PipelineData>>(
|
||||||
|
cloneDeep(pipelineData?.pipelines || []),
|
||||||
|
);
|
||||||
|
const [currPipelineData, setCurrPipelineData] = useState<Array<PipelineData>>(
|
||||||
|
cloneDeep(pipelineData?.pipelines || []),
|
||||||
|
);
|
||||||
|
|
||||||
|
const [expandedPipelineId, setExpandedPipelineId] = useState<
|
||||||
|
string | undefined
|
||||||
|
>(undefined);
|
||||||
|
const expandedPipelineData = useCallback(
|
||||||
|
() => currPipelineData?.find((p) => p.id === expandedPipelineId),
|
||||||
|
[currPipelineData, expandedPipelineId],
|
||||||
|
);
|
||||||
|
const setExpandedPipelineData = useCallback(
|
||||||
|
(newData: PipelineData): void => {
|
||||||
|
if (expandedPipelineId) {
|
||||||
|
const pipelineIdx = currPipelineData?.findIndex(
|
||||||
|
(p) => p.id === expandedPipelineId,
|
||||||
|
);
|
||||||
|
if (pipelineIdx >= 0) {
|
||||||
|
const newPipelineData = [...currPipelineData];
|
||||||
|
newPipelineData[pipelineIdx] = newData;
|
||||||
|
setCurrPipelineData(newPipelineData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[expandedPipelineId, currPipelineData],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [
|
||||||
|
selectedProcessorData,
|
||||||
|
setSelectedProcessorData,
|
||||||
|
] = useState<ProcessorData>();
|
||||||
|
|
||||||
|
const [
|
||||||
|
selectedPipelineData,
|
||||||
|
setSelectedPipelineData,
|
||||||
|
] = useState<PipelineData>();
|
||||||
|
|
||||||
|
const [expandedRowKeys, setExpandedRowKeys] = useState<Array<string>>();
|
||||||
|
const [showSaveButton, setShowSaveButton] = useState<string>();
|
||||||
|
const isEditingActionMode = isActionMode === ActionMode.Editing;
|
||||||
|
|
||||||
|
const visibleCurrPipelines = useMemo((): Array<PipelineData> => {
|
||||||
|
if (pipelineSearchValue === '') {
|
||||||
|
return currPipelineData;
|
||||||
|
}
|
||||||
|
return currPipelineData.filter((data) =>
|
||||||
|
getDataOnSearch(data as never, pipelineSearchValue),
|
||||||
|
);
|
||||||
|
}, [currPipelineData, pipelineSearchValue]);
|
||||||
|
|
||||||
|
const handleAlert = useCallback(
|
||||||
|
({ title, descrition, buttontext, onCancel, onOk }: AlertMessage) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: <AlertModalTitle>{title}</AlertModalTitle>,
|
||||||
|
icon: <ExclamationCircleOutlined />,
|
||||||
|
content: <AlertContentWrapper>{descrition}</AlertContentWrapper>,
|
||||||
|
okText: <span>{buttontext}</span>,
|
||||||
|
cancelText: <span>{t('cancel')}</span>,
|
||||||
|
onOk,
|
||||||
|
onCancel,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[modal, t],
|
||||||
|
);
|
||||||
|
|
||||||
|
const pipelineEditAction = useCallback(
|
||||||
|
(record: PipelineData) => (): void => {
|
||||||
|
setActionType(ActionType.EditPipeline);
|
||||||
|
setSelectedPipelineData(record);
|
||||||
|
},
|
||||||
|
[setActionType],
|
||||||
|
);
|
||||||
|
|
||||||
|
const pipelineDeleteHandler = useCallback(
|
||||||
|
(record: PipelineData) => (): void => {
|
||||||
|
setShowSaveButton(ActionMode.Editing);
|
||||||
|
const filteredData = getElementFromArray(currPipelineData, record, 'id');
|
||||||
|
filteredData.forEach((item, index) => {
|
||||||
|
const obj = item;
|
||||||
|
obj.orderId = index + 1;
|
||||||
|
});
|
||||||
|
setCurrPipelineData(filteredData);
|
||||||
|
},
|
||||||
|
[currPipelineData],
|
||||||
|
);
|
||||||
|
|
||||||
|
const pipelineDeleteAction = useCallback(
|
||||||
|
(record: PipelineData) => (): void => {
|
||||||
|
handleAlert({
|
||||||
|
title: `${t('delete_pipeline')} : ${record.name}?`,
|
||||||
|
descrition: t('delete_pipeline_description'),
|
||||||
|
buttontext: t('delete'),
|
||||||
|
onOk: pipelineDeleteHandler(record),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[handleAlert, pipelineDeleteHandler, t],
|
||||||
|
);
|
||||||
|
|
||||||
|
const processorEditAction = useCallback(
|
||||||
|
(record: ProcessorData) => (): void => {
|
||||||
|
setActionType(ActionType.EditProcessor);
|
||||||
|
setSelectedProcessorData(record);
|
||||||
|
},
|
||||||
|
[setActionType],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSwitchPipelineChange = useCallback(
|
||||||
|
(checked: boolean, record: PipelineData): void => {
|
||||||
|
setShowSaveButton(ActionMode.Editing);
|
||||||
|
const findRecordIndex = getRecordIndex(currPipelineData, record, 'id');
|
||||||
|
const updateSwitch = {
|
||||||
|
...currPipelineData[findRecordIndex],
|
||||||
|
enabled: checked,
|
||||||
|
};
|
||||||
|
const editedPipelineData = getEditedDataSource(
|
||||||
|
currPipelineData,
|
||||||
|
record,
|
||||||
|
'id',
|
||||||
|
updateSwitch,
|
||||||
|
);
|
||||||
|
setCurrPipelineData(editedPipelineData);
|
||||||
|
},
|
||||||
|
[currPipelineData],
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns = useMemo(() => {
|
||||||
|
const fieldColumns = getTableColumn(pipelineColumns);
|
||||||
|
if (isEditingActionMode) {
|
||||||
|
fieldColumns.push(
|
||||||
|
{
|
||||||
|
title: 'Actions',
|
||||||
|
dataIndex: 'smartAction',
|
||||||
|
key: 'smartAction',
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, record): JSX.Element => (
|
||||||
|
<PipelineActions
|
||||||
|
pipeline={record}
|
||||||
|
editAction={pipelineEditAction(record)}
|
||||||
|
deleteAction={pipelineDeleteAction(record)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
dataIndex: 'enabled',
|
||||||
|
key: 'enabled',
|
||||||
|
render: (value, record) => (
|
||||||
|
<DragAction
|
||||||
|
isEnabled={value}
|
||||||
|
onChange={(checked: boolean): void =>
|
||||||
|
onSwitchPipelineChange(checked, record)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fieldColumns.push({
|
||||||
|
title: 'Actions',
|
||||||
|
dataIndex: 'smartAction',
|
||||||
|
key: 'smartAction',
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, record): JSX.Element => (
|
||||||
|
<PreviewAction pipeline={record} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return fieldColumns;
|
||||||
|
}, [
|
||||||
|
isEditingActionMode,
|
||||||
|
pipelineEditAction,
|
||||||
|
pipelineDeleteAction,
|
||||||
|
onSwitchPipelineChange,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const updatePipelineSequence = useCallback(
|
||||||
|
(updatedRow: PipelineData[]) => (): void => {
|
||||||
|
setShowSaveButton(ActionMode.Editing);
|
||||||
|
setCurrPipelineData(updatedRow);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onCancelPipelineSequence = useCallback(
|
||||||
|
(rawData: PipelineData[]) => (): void => {
|
||||||
|
setCurrPipelineData(rawData);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const movePipelineRow = useCallback(
|
||||||
|
(dragIndex: number, hoverIndex: number) => {
|
||||||
|
if (currPipelineData && isEditingActionMode) {
|
||||||
|
const rawData = currPipelineData;
|
||||||
|
|
||||||
|
const updatedRows = getUpdatedRow(
|
||||||
|
currPipelineData,
|
||||||
|
visibleCurrPipelines[dragIndex].orderId - 1,
|
||||||
|
visibleCurrPipelines[hoverIndex].orderId - 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
updatedRows.forEach((item, index) => {
|
||||||
|
const obj = item;
|
||||||
|
obj.orderId = index + 1;
|
||||||
|
});
|
||||||
|
handleAlert({
|
||||||
|
title: t('reorder_pipeline'),
|
||||||
|
descrition: t('reorder_pipeline_description'),
|
||||||
|
buttontext: t('reorder'),
|
||||||
|
onOk: updatePipelineSequence(updatedRows),
|
||||||
|
onCancel: onCancelPipelineSequence(rawData),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
currPipelineData,
|
||||||
|
isEditingActionMode,
|
||||||
|
visibleCurrPipelines,
|
||||||
|
handleAlert,
|
||||||
|
t,
|
||||||
|
updatePipelineSequence,
|
||||||
|
onCancelPipelineSequence,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
const expandedRowView = useCallback(
|
||||||
|
(): JSX.Element => (
|
||||||
|
<PipelineExpanView
|
||||||
|
handleAlert={handleAlert}
|
||||||
|
isActionMode={isActionMode}
|
||||||
|
setActionType={setActionType}
|
||||||
|
processorEditAction={processorEditAction}
|
||||||
|
setShowSaveButton={setShowSaveButton}
|
||||||
|
expandedPipelineData={expandedPipelineData()}
|
||||||
|
setExpandedPipelineData={setExpandedPipelineData}
|
||||||
|
prevPipelineData={prevPipelineData}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[
|
||||||
|
handleAlert,
|
||||||
|
processorEditAction,
|
||||||
|
isActionMode,
|
||||||
|
expandedPipelineData,
|
||||||
|
setActionType,
|
||||||
|
prevPipelineData,
|
||||||
|
setExpandedPipelineData,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onExpand = useCallback(
|
||||||
|
(expanded: boolean, record: PipelineData): void => {
|
||||||
|
const keys = [];
|
||||||
|
if (expanded && record.id) {
|
||||||
|
keys.push(record?.id);
|
||||||
|
}
|
||||||
|
setExpandedRowKeys(keys);
|
||||||
|
setExpandedPipelineId(record.id);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const getExpandIcon = (
|
||||||
|
expanded: boolean,
|
||||||
|
onExpand: (record: PipelineData, e: React.MouseEvent<HTMLElement>) => void,
|
||||||
|
record: PipelineData,
|
||||||
|
): JSX.Element => (
|
||||||
|
<TableExpandIcon expanded={expanded} onExpand={onExpand} record={record} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const addNewPipelineHandler = useCallback((): void => {
|
||||||
|
setActionType(ActionType.AddPipeline);
|
||||||
|
}, [setActionType]);
|
||||||
|
|
||||||
|
const footer = useCallback((): JSX.Element | undefined => {
|
||||||
|
if (isEditingActionMode) {
|
||||||
|
return (
|
||||||
|
<FooterButton
|
||||||
|
type="link"
|
||||||
|
onClick={addNewPipelineHandler}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
>
|
||||||
|
{t('add_new_pipeline')}
|
||||||
|
</FooterButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [isEditingActionMode, addNewPipelineHandler, t]);
|
||||||
|
|
||||||
|
const onSaveConfigurationHandler = useCallback(async () => {
|
||||||
|
const modifiedPipelineData = currPipelineData.map((item: PipelineData) => {
|
||||||
|
const pipelineData = { ...item };
|
||||||
|
delete pipelineData?.id;
|
||||||
|
return pipelineData;
|
||||||
|
});
|
||||||
|
const response = await savePipeline({
|
||||||
|
data: { pipelines: modifiedPipelineData },
|
||||||
|
});
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
refetchPipelineLists();
|
||||||
|
setActionMode(ActionMode.Viewing);
|
||||||
|
setShowSaveButton(undefined);
|
||||||
|
setCurrPipelineData(response.payload?.pipelines || []);
|
||||||
|
setPrevPipelineData(response.payload?.pipelines || []);
|
||||||
|
} else {
|
||||||
|
modifiedPipelineData.forEach((item: PipelineData) => {
|
||||||
|
const pipelineData = item;
|
||||||
|
pipelineData.id = v4();
|
||||||
|
return pipelineData;
|
||||||
|
});
|
||||||
|
setActionMode(ActionMode.Editing);
|
||||||
|
setShowSaveButton(ActionMode.Editing);
|
||||||
|
notifications.error({
|
||||||
|
message: 'Error',
|
||||||
|
description: response.error || t('something_went_wrong'),
|
||||||
|
});
|
||||||
|
setCurrPipelineData(modifiedPipelineData);
|
||||||
|
setPrevPipelineData(modifiedPipelineData);
|
||||||
|
}
|
||||||
|
}, [currPipelineData, notifications, refetchPipelineLists, setActionMode, t]);
|
||||||
|
|
||||||
|
const onCancelConfigurationHandler = useCallback((): void => {
|
||||||
|
setActionMode(ActionMode.Viewing);
|
||||||
|
setShowSaveButton(undefined);
|
||||||
|
prevPipelineData.forEach((item, index) => {
|
||||||
|
const obj = item;
|
||||||
|
obj.orderId = index + 1;
|
||||||
|
if (obj.config) {
|
||||||
|
obj.config?.forEach((configItem, index) => {
|
||||||
|
const config = configItem;
|
||||||
|
config.orderId = index + 1;
|
||||||
|
});
|
||||||
|
for (let i = 0; i < obj.config.length - 1; i += 1) {
|
||||||
|
obj.config[i].output = obj.config[i + 1].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setCurrPipelineData(prevPipelineData);
|
||||||
|
setExpandedRowKeys([]);
|
||||||
|
}, [prevPipelineData, setActionMode]);
|
||||||
|
|
||||||
|
const onRowHandler = (
|
||||||
|
_data: PipelineData,
|
||||||
|
index?: number,
|
||||||
|
): React.HTMLAttributes<unknown> =>
|
||||||
|
({
|
||||||
|
index,
|
||||||
|
moveRow: movePipelineRow,
|
||||||
|
} as React.HTMLAttributes<unknown>);
|
||||||
|
|
||||||
|
const expandableConfig: ExpandableConfig<PipelineData> = {
|
||||||
|
expandedRowKeys,
|
||||||
|
onExpand,
|
||||||
|
expandIcon: ({ expanded, onExpand, record }: ExpandRowConfig) =>
|
||||||
|
getExpandIcon(expanded, onExpand, record),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{contextHolder}
|
||||||
|
<AddNewPipeline
|
||||||
|
isActionType={isActionType}
|
||||||
|
setActionType={setActionType}
|
||||||
|
selectedPipelineData={selectedPipelineData}
|
||||||
|
setShowSaveButton={setShowSaveButton}
|
||||||
|
setCurrPipelineData={setCurrPipelineData}
|
||||||
|
currPipelineData={currPipelineData}
|
||||||
|
/>
|
||||||
|
<AddNewProcessor
|
||||||
|
isActionType={isActionType}
|
||||||
|
setActionType={setActionType}
|
||||||
|
selectedProcessorData={selectedProcessorData}
|
||||||
|
setShowSaveButton={setShowSaveButton}
|
||||||
|
expandedPipelineData={expandedPipelineData()}
|
||||||
|
setExpandedPipelineData={setExpandedPipelineData}
|
||||||
|
/>
|
||||||
|
<Container>
|
||||||
|
<ModeAndConfiguration
|
||||||
|
isActionMode={isActionMode}
|
||||||
|
version={pipelineData?.version}
|
||||||
|
/>
|
||||||
|
<DndProvider backend={HTML5Backend}>
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
columns={columns}
|
||||||
|
expandedRowRender={expandedRowView}
|
||||||
|
expandable={expandableConfig}
|
||||||
|
components={tableComponents}
|
||||||
|
dataSource={visibleCurrPipelines}
|
||||||
|
onRow={onRowHandler}
|
||||||
|
footer={footer}
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
</DndProvider>
|
||||||
|
{showSaveButton && (
|
||||||
|
<SaveConfigButton
|
||||||
|
onSaveConfigurationHandler={onSaveConfigurationHandler}
|
||||||
|
onCancelConfigurationHandler={onCancelConfigurationHandler}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PipelineListsViewProps {
|
||||||
|
isActionType: string;
|
||||||
|
setActionType: (actionType?: ActionType) => void;
|
||||||
|
isActionMode: string;
|
||||||
|
setActionMode: (actionMode: ActionMode) => void;
|
||||||
|
pipelineData: Pipeline;
|
||||||
|
refetchPipelineLists: VoidFunction;
|
||||||
|
pipelineSearchValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExpandRowConfig {
|
||||||
|
expanded: boolean;
|
||||||
|
onExpand: (record: PipelineData, e: React.MouseEvent<HTMLElement>) => void;
|
||||||
|
record: PipelineData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlertMessage {
|
||||||
|
title: string;
|
||||||
|
descrition: string;
|
||||||
|
buttontext: string;
|
||||||
|
onOk: VoidFunction;
|
||||||
|
onCancel?: VoidFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PipelineListsView;
|
@ -1,489 +1,3 @@
|
|||||||
import { ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
import PipelineListsView from './PipelineListsView';
|
||||||
import { Modal, Table } from 'antd';
|
|
||||||
import { ExpandableConfig } from 'antd/es/table/interface';
|
|
||||||
import savePipeline from 'api/pipeline/post';
|
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
|
||||||
import cloneDeep from 'lodash-es/cloneDeep';
|
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
|
||||||
import { DndProvider } from 'react-dnd';
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import {
|
|
||||||
ActionMode,
|
|
||||||
ActionType,
|
|
||||||
Pipeline,
|
|
||||||
PipelineData,
|
|
||||||
ProcessorData,
|
|
||||||
} from 'types/api/pipeline/def';
|
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { tableComponents } from '../config';
|
|
||||||
import AddNewPipeline from './AddNewPipeline';
|
|
||||||
import AddNewProcessor from './AddNewProcessor';
|
|
||||||
import { pipelineColumns } from './config';
|
|
||||||
import ModeAndConfiguration from './ModeAndConfiguration';
|
|
||||||
import PipelineExpanView from './PipelineExpandView';
|
|
||||||
import SaveConfigButton from './SaveConfigButton';
|
|
||||||
import {
|
|
||||||
AlertContentWrapper,
|
|
||||||
AlertModalTitle,
|
|
||||||
Container,
|
|
||||||
FooterButton,
|
|
||||||
} from './styles';
|
|
||||||
import DragAction from './TableComponents/DragAction';
|
|
||||||
import PipelineActions from './TableComponents/PipelineActions';
|
|
||||||
import PreviewAction from './TableComponents/PipelineActions/components/PreviewAction';
|
|
||||||
import TableExpandIcon from './TableComponents/TableExpandIcon';
|
|
||||||
import {
|
|
||||||
getDataOnSearch,
|
|
||||||
getEditedDataSource,
|
|
||||||
getElementFromArray,
|
|
||||||
getRecordIndex,
|
|
||||||
getTableColumn,
|
|
||||||
getUpdatedRow,
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
function PipelineListsView({
|
|
||||||
isActionType,
|
|
||||||
setActionType,
|
|
||||||
isActionMode,
|
|
||||||
setActionMode,
|
|
||||||
pipelineData,
|
|
||||||
refetchPipelineLists,
|
|
||||||
pipelineSearchValue,
|
|
||||||
}: PipelineListsViewProps): JSX.Element {
|
|
||||||
const { t } = useTranslation(['pipeline', 'common']);
|
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
|
||||||
const { notifications } = useNotifications();
|
|
||||||
const [prevPipelineData, setPrevPipelineData] = useState<Array<PipelineData>>(
|
|
||||||
cloneDeep(pipelineData?.pipelines || []),
|
|
||||||
);
|
|
||||||
const [currPipelineData, setCurrPipelineData] = useState<Array<PipelineData>>(
|
|
||||||
cloneDeep(pipelineData?.pipelines || []),
|
|
||||||
);
|
|
||||||
|
|
||||||
const [expandedPipelineId, setExpandedPipelineId] = useState<
|
|
||||||
string | undefined
|
|
||||||
>(undefined);
|
|
||||||
const expandedPipelineData = useCallback(
|
|
||||||
() => currPipelineData?.find((p) => p.id === expandedPipelineId),
|
|
||||||
[currPipelineData, expandedPipelineId],
|
|
||||||
);
|
|
||||||
const setExpandedPipelineData = useCallback(
|
|
||||||
(newData: PipelineData): void => {
|
|
||||||
if (expandedPipelineId) {
|
|
||||||
const pipelineIdx = currPipelineData?.findIndex(
|
|
||||||
(p) => p.id === expandedPipelineId,
|
|
||||||
);
|
|
||||||
if (pipelineIdx >= 0) {
|
|
||||||
const newPipelineData = [...currPipelineData];
|
|
||||||
newPipelineData[pipelineIdx] = newData;
|
|
||||||
setCurrPipelineData(newPipelineData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[expandedPipelineId, currPipelineData],
|
|
||||||
);
|
|
||||||
|
|
||||||
const [
|
|
||||||
selectedProcessorData,
|
|
||||||
setSelectedProcessorData,
|
|
||||||
] = useState<ProcessorData>();
|
|
||||||
|
|
||||||
const [
|
|
||||||
selectedPipelineData,
|
|
||||||
setSelectedPipelineData,
|
|
||||||
] = useState<PipelineData>();
|
|
||||||
|
|
||||||
const [expandedRowKeys, setExpandedRowKeys] = useState<Array<string>>();
|
|
||||||
const [showSaveButton, setShowSaveButton] = useState<string>();
|
|
||||||
const isEditingActionMode = isActionMode === ActionMode.Editing;
|
|
||||||
|
|
||||||
const visibleCurrPipelines = useMemo((): Array<PipelineData> => {
|
|
||||||
if (pipelineSearchValue === '') {
|
|
||||||
return currPipelineData;
|
|
||||||
}
|
|
||||||
return currPipelineData.filter((data) =>
|
|
||||||
getDataOnSearch(data as never, pipelineSearchValue),
|
|
||||||
);
|
|
||||||
}, [currPipelineData, pipelineSearchValue]);
|
|
||||||
|
|
||||||
const handleAlert = useCallback(
|
|
||||||
({ title, descrition, buttontext, onCancel, onOk }: AlertMessage) => {
|
|
||||||
modal.confirm({
|
|
||||||
title: <AlertModalTitle>{title}</AlertModalTitle>,
|
|
||||||
icon: <ExclamationCircleOutlined />,
|
|
||||||
content: <AlertContentWrapper>{descrition}</AlertContentWrapper>,
|
|
||||||
okText: <span>{buttontext}</span>,
|
|
||||||
cancelText: <span>{t('cancel')}</span>,
|
|
||||||
onOk,
|
|
||||||
onCancel,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[modal, t],
|
|
||||||
);
|
|
||||||
|
|
||||||
const pipelineEditAction = useCallback(
|
|
||||||
(record: PipelineData) => (): void => {
|
|
||||||
setActionType(ActionType.EditPipeline);
|
|
||||||
setSelectedPipelineData(record);
|
|
||||||
},
|
|
||||||
[setActionType],
|
|
||||||
);
|
|
||||||
|
|
||||||
const pipelineDeleteHandler = useCallback(
|
|
||||||
(record: PipelineData) => (): void => {
|
|
||||||
setShowSaveButton(ActionMode.Editing);
|
|
||||||
const filteredData = getElementFromArray(currPipelineData, record, 'id');
|
|
||||||
filteredData.forEach((item, index) => {
|
|
||||||
const obj = item;
|
|
||||||
obj.orderId = index + 1;
|
|
||||||
});
|
|
||||||
setCurrPipelineData(filteredData);
|
|
||||||
},
|
|
||||||
[currPipelineData],
|
|
||||||
);
|
|
||||||
|
|
||||||
const pipelineDeleteAction = useCallback(
|
|
||||||
(record: PipelineData) => (): void => {
|
|
||||||
handleAlert({
|
|
||||||
title: `${t('delete_pipeline')} : ${record.name}?`,
|
|
||||||
descrition: t('delete_pipeline_description'),
|
|
||||||
buttontext: t('delete'),
|
|
||||||
onOk: pipelineDeleteHandler(record),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[handleAlert, pipelineDeleteHandler, t],
|
|
||||||
);
|
|
||||||
|
|
||||||
const processorEditAction = useCallback(
|
|
||||||
(record: ProcessorData) => (): void => {
|
|
||||||
setActionType(ActionType.EditProcessor);
|
|
||||||
setSelectedProcessorData(record);
|
|
||||||
},
|
|
||||||
[setActionType],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onSwitchPipelineChange = useCallback(
|
|
||||||
(checked: boolean, record: PipelineData): void => {
|
|
||||||
setShowSaveButton(ActionMode.Editing);
|
|
||||||
const findRecordIndex = getRecordIndex(currPipelineData, record, 'id');
|
|
||||||
const updateSwitch = {
|
|
||||||
...currPipelineData[findRecordIndex],
|
|
||||||
enabled: checked,
|
|
||||||
};
|
|
||||||
const editedPipelineData = getEditedDataSource(
|
|
||||||
currPipelineData,
|
|
||||||
record,
|
|
||||||
'id',
|
|
||||||
updateSwitch,
|
|
||||||
);
|
|
||||||
setCurrPipelineData(editedPipelineData);
|
|
||||||
},
|
|
||||||
[currPipelineData],
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = useMemo(() => {
|
|
||||||
const fieldColumns = getTableColumn(pipelineColumns);
|
|
||||||
if (isEditingActionMode) {
|
|
||||||
fieldColumns.push(
|
|
||||||
{
|
|
||||||
title: 'Actions',
|
|
||||||
dataIndex: 'smartAction',
|
|
||||||
key: 'smartAction',
|
|
||||||
align: 'center',
|
|
||||||
render: (_value, record): JSX.Element => (
|
|
||||||
<PipelineActions
|
|
||||||
pipeline={record}
|
|
||||||
editAction={pipelineEditAction(record)}
|
|
||||||
deleteAction={pipelineDeleteAction(record)}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '',
|
|
||||||
dataIndex: 'enabled',
|
|
||||||
key: 'enabled',
|
|
||||||
render: (value, record) => (
|
|
||||||
<DragAction
|
|
||||||
isEnabled={value}
|
|
||||||
onChange={(checked: boolean): void =>
|
|
||||||
onSwitchPipelineChange(checked, record)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fieldColumns.push({
|
|
||||||
title: 'Actions',
|
|
||||||
dataIndex: 'smartAction',
|
|
||||||
key: 'smartAction',
|
|
||||||
align: 'center',
|
|
||||||
render: (_value, record): JSX.Element => (
|
|
||||||
<PreviewAction pipeline={record} />
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return fieldColumns;
|
|
||||||
}, [
|
|
||||||
isEditingActionMode,
|
|
||||||
pipelineEditAction,
|
|
||||||
pipelineDeleteAction,
|
|
||||||
onSwitchPipelineChange,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const updatePipelineSequence = useCallback(
|
|
||||||
(updatedRow: PipelineData[]) => (): void => {
|
|
||||||
setShowSaveButton(ActionMode.Editing);
|
|
||||||
setCurrPipelineData(updatedRow);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onCancelPipelineSequence = useCallback(
|
|
||||||
(rawData: PipelineData[]) => (): void => {
|
|
||||||
setCurrPipelineData(rawData);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const movePipelineRow = useCallback(
|
|
||||||
(dragIndex: number, hoverIndex: number) => {
|
|
||||||
if (currPipelineData && isEditingActionMode) {
|
|
||||||
const rawData = currPipelineData;
|
|
||||||
|
|
||||||
const updatedRows = getUpdatedRow(
|
|
||||||
currPipelineData,
|
|
||||||
visibleCurrPipelines[dragIndex].orderId - 1,
|
|
||||||
visibleCurrPipelines[hoverIndex].orderId - 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedRows.forEach((item, index) => {
|
|
||||||
const obj = item;
|
|
||||||
obj.orderId = index + 1;
|
|
||||||
});
|
|
||||||
handleAlert({
|
|
||||||
title: t('reorder_pipeline'),
|
|
||||||
descrition: t('reorder_pipeline_description'),
|
|
||||||
buttontext: t('reorder'),
|
|
||||||
onOk: updatePipelineSequence(updatedRows),
|
|
||||||
onCancel: onCancelPipelineSequence(rawData),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[
|
|
||||||
currPipelineData,
|
|
||||||
isEditingActionMode,
|
|
||||||
visibleCurrPipelines,
|
|
||||||
handleAlert,
|
|
||||||
t,
|
|
||||||
updatePipelineSequence,
|
|
||||||
onCancelPipelineSequence,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
const expandedRowView = useCallback(
|
|
||||||
(): JSX.Element => (
|
|
||||||
<PipelineExpanView
|
|
||||||
handleAlert={handleAlert}
|
|
||||||
isActionMode={isActionMode}
|
|
||||||
setActionType={setActionType}
|
|
||||||
processorEditAction={processorEditAction}
|
|
||||||
setShowSaveButton={setShowSaveButton}
|
|
||||||
expandedPipelineData={expandedPipelineData()}
|
|
||||||
setExpandedPipelineData={setExpandedPipelineData}
|
|
||||||
prevPipelineData={prevPipelineData}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[
|
|
||||||
handleAlert,
|
|
||||||
processorEditAction,
|
|
||||||
isActionMode,
|
|
||||||
expandedPipelineData,
|
|
||||||
setActionType,
|
|
||||||
prevPipelineData,
|
|
||||||
setExpandedPipelineData,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onExpand = useCallback(
|
|
||||||
(expanded: boolean, record: PipelineData): void => {
|
|
||||||
const keys = [];
|
|
||||||
if (expanded && record.id) {
|
|
||||||
keys.push(record?.id);
|
|
||||||
}
|
|
||||||
setExpandedRowKeys(keys);
|
|
||||||
setExpandedPipelineId(record.id);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const getExpandIcon = (
|
|
||||||
expanded: boolean,
|
|
||||||
onExpand: (record: PipelineData, e: React.MouseEvent<HTMLElement>) => void,
|
|
||||||
record: PipelineData,
|
|
||||||
): JSX.Element => (
|
|
||||||
<TableExpandIcon expanded={expanded} onExpand={onExpand} record={record} />
|
|
||||||
);
|
|
||||||
|
|
||||||
const addNewPipelineHandler = useCallback((): void => {
|
|
||||||
setActionType(ActionType.AddPipeline);
|
|
||||||
}, [setActionType]);
|
|
||||||
|
|
||||||
const footer = useCallback((): JSX.Element | undefined => {
|
|
||||||
if (isEditingActionMode) {
|
|
||||||
return (
|
|
||||||
<FooterButton
|
|
||||||
type="link"
|
|
||||||
onClick={addNewPipelineHandler}
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
>
|
|
||||||
{t('add_new_pipeline')}
|
|
||||||
</FooterButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}, [isEditingActionMode, addNewPipelineHandler, t]);
|
|
||||||
|
|
||||||
const onSaveConfigurationHandler = useCallback(async () => {
|
|
||||||
const modifiedPipelineData = currPipelineData.map((item: PipelineData) => {
|
|
||||||
const pipelineData = { ...item };
|
|
||||||
delete pipelineData?.id;
|
|
||||||
return pipelineData;
|
|
||||||
});
|
|
||||||
const response = await savePipeline({
|
|
||||||
data: { pipelines: modifiedPipelineData },
|
|
||||||
});
|
|
||||||
if (response.statusCode === 200) {
|
|
||||||
refetchPipelineLists();
|
|
||||||
setActionMode(ActionMode.Viewing);
|
|
||||||
setShowSaveButton(undefined);
|
|
||||||
setCurrPipelineData(response.payload?.pipelines || []);
|
|
||||||
setPrevPipelineData(response.payload?.pipelines || []);
|
|
||||||
} else {
|
|
||||||
modifiedPipelineData.forEach((item: PipelineData) => {
|
|
||||||
const pipelineData = item;
|
|
||||||
pipelineData.id = v4();
|
|
||||||
return pipelineData;
|
|
||||||
});
|
|
||||||
setActionMode(ActionMode.Editing);
|
|
||||||
setShowSaveButton(ActionMode.Editing);
|
|
||||||
notifications.error({
|
|
||||||
message: 'Error',
|
|
||||||
description: response.error || t('something_went_wrong'),
|
|
||||||
});
|
|
||||||
setCurrPipelineData(modifiedPipelineData);
|
|
||||||
setPrevPipelineData(modifiedPipelineData);
|
|
||||||
}
|
|
||||||
}, [currPipelineData, notifications, refetchPipelineLists, setActionMode, t]);
|
|
||||||
|
|
||||||
const onCancelConfigurationHandler = useCallback((): void => {
|
|
||||||
setActionMode(ActionMode.Viewing);
|
|
||||||
setShowSaveButton(undefined);
|
|
||||||
prevPipelineData.forEach((item, index) => {
|
|
||||||
const obj = item;
|
|
||||||
obj.orderId = index + 1;
|
|
||||||
if (obj.config) {
|
|
||||||
obj.config?.forEach((configItem, index) => {
|
|
||||||
const config = configItem;
|
|
||||||
config.orderId = index + 1;
|
|
||||||
});
|
|
||||||
for (let i = 0; i < obj.config.length - 1; i += 1) {
|
|
||||||
obj.config[i].output = obj.config[i + 1].id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setCurrPipelineData(prevPipelineData);
|
|
||||||
setExpandedRowKeys([]);
|
|
||||||
}, [prevPipelineData, setActionMode]);
|
|
||||||
|
|
||||||
const onRowHandler = (
|
|
||||||
_data: PipelineData,
|
|
||||||
index?: number,
|
|
||||||
): React.HTMLAttributes<unknown> =>
|
|
||||||
({
|
|
||||||
index,
|
|
||||||
moveRow: movePipelineRow,
|
|
||||||
} as React.HTMLAttributes<unknown>);
|
|
||||||
|
|
||||||
const expandableConfig: ExpandableConfig<PipelineData> = {
|
|
||||||
expandedRowKeys,
|
|
||||||
onExpand,
|
|
||||||
expandIcon: ({ expanded, onExpand, record }: ExpandRowConfig) =>
|
|
||||||
getExpandIcon(expanded, onExpand, record),
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{contextHolder}
|
|
||||||
<AddNewPipeline
|
|
||||||
isActionType={isActionType}
|
|
||||||
setActionType={setActionType}
|
|
||||||
selectedPipelineData={selectedPipelineData}
|
|
||||||
setShowSaveButton={setShowSaveButton}
|
|
||||||
setCurrPipelineData={setCurrPipelineData}
|
|
||||||
currPipelineData={currPipelineData}
|
|
||||||
/>
|
|
||||||
<AddNewProcessor
|
|
||||||
isActionType={isActionType}
|
|
||||||
setActionType={setActionType}
|
|
||||||
selectedProcessorData={selectedProcessorData}
|
|
||||||
setShowSaveButton={setShowSaveButton}
|
|
||||||
expandedPipelineData={expandedPipelineData()}
|
|
||||||
setExpandedPipelineData={setExpandedPipelineData}
|
|
||||||
/>
|
|
||||||
<Container>
|
|
||||||
<ModeAndConfiguration
|
|
||||||
isActionMode={isActionMode}
|
|
||||||
version={pipelineData?.version}
|
|
||||||
/>
|
|
||||||
<DndProvider backend={HTML5Backend}>
|
|
||||||
<Table
|
|
||||||
rowKey="id"
|
|
||||||
columns={columns}
|
|
||||||
expandedRowRender={expandedRowView}
|
|
||||||
expandable={expandableConfig}
|
|
||||||
components={tableComponents}
|
|
||||||
dataSource={visibleCurrPipelines}
|
|
||||||
onRow={onRowHandler}
|
|
||||||
footer={footer}
|
|
||||||
pagination={false}
|
|
||||||
/>
|
|
||||||
</DndProvider>
|
|
||||||
{showSaveButton && (
|
|
||||||
<SaveConfigButton
|
|
||||||
onSaveConfigurationHandler={onSaveConfigurationHandler}
|
|
||||||
onCancelConfigurationHandler={onCancelConfigurationHandler}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Container>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PipelineListsViewProps {
|
|
||||||
isActionType: string;
|
|
||||||
setActionType: (actionType?: ActionType) => void;
|
|
||||||
isActionMode: string;
|
|
||||||
setActionMode: (actionMode: ActionMode) => void;
|
|
||||||
pipelineData: Pipeline;
|
|
||||||
refetchPipelineLists: VoidFunction;
|
|
||||||
pipelineSearchValue: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ExpandRowConfig {
|
|
||||||
expanded: boolean;
|
|
||||||
onExpand: (record: PipelineData, e: React.MouseEvent<HTMLElement>) => void;
|
|
||||||
record: PipelineData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlertMessage {
|
|
||||||
title: string;
|
|
||||||
descrition: string;
|
|
||||||
buttontext: string;
|
|
||||||
onOk: VoidFunction;
|
|
||||||
onCancel?: VoidFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PipelineListsView;
|
export default PipelineListsView;
|
||||||
|
@ -82,78 +82,42 @@ exports[`PipelinePage container test should render PipelinePageLayout section 1`
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="ant-input-group-wrapper ant-input-search css-dev-only-do-not-override-1i536d8"
|
class="ant-input-affix-wrapper css-dev-only-do-not-override-1i536d8"
|
||||||
>
|
>
|
||||||
|
<input
|
||||||
|
class="ant-input css-dev-only-do-not-override-1i536d8"
|
||||||
|
placeholder="search_pipeline_placeholder"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
class="ant-input-wrapper ant-input-group css-dev-only-do-not-override-1i536d8"
|
class="ant-input-suffix"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="ant-input-affix-wrapper css-dev-only-do-not-override-1i536d8"
|
class="ant-input-clear-icon ant-input-clear-icon-hidden"
|
||||||
|
role="button"
|
||||||
|
tabindex="-1"
|
||||||
>
|
>
|
||||||
<input
|
|
||||||
class="ant-input css-dev-only-do-not-override-1i536d8"
|
|
||||||
placeholder="search_pipeline_placeholder"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
class="ant-input-suffix"
|
aria-label="close-circle"
|
||||||
|
class="anticon anticon-close-circle"
|
||||||
|
role="img"
|
||||||
>
|
>
|
||||||
<span
|
<svg
|
||||||
class="ant-input-clear-icon ant-input-clear-icon-hidden"
|
aria-hidden="true"
|
||||||
role="button"
|
data-icon="close-circle"
|
||||||
tabindex="-1"
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
>
|
>
|
||||||
<span
|
<path
|
||||||
aria-label="close-circle"
|
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
||||||
class="anticon anticon-close-circle"
|
/>
|
||||||
role="img"
|
</svg>
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="close-circle"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
|
||||||
class="ant-input-group-addon"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-btn css-dev-only-do-not-override-1i536d8 ant-btn-default ant-btn-icon-only ant-input-search-button"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="search"
|
|
||||||
class="anticon anticon-search"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="search"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
.c0 {
|
.c0 {
|
||||||
|
@ -3,78 +3,42 @@
|
|||||||
exports[`PipelinePage container test should render PipelinesSearchSection section 1`] = `
|
exports[`PipelinePage container test should render PipelinesSearchSection section 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<span
|
<span
|
||||||
class="ant-input-group-wrapper ant-input-search css-dev-only-do-not-override-1i536d8"
|
class="ant-input-affix-wrapper css-dev-only-do-not-override-1i536d8"
|
||||||
>
|
>
|
||||||
|
<input
|
||||||
|
class="ant-input css-dev-only-do-not-override-1i536d8"
|
||||||
|
placeholder="search_pipeline_placeholder"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
class="ant-input-wrapper ant-input-group css-dev-only-do-not-override-1i536d8"
|
class="ant-input-suffix"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="ant-input-affix-wrapper css-dev-only-do-not-override-1i536d8"
|
class="ant-input-clear-icon ant-input-clear-icon-hidden"
|
||||||
|
role="button"
|
||||||
|
tabindex="-1"
|
||||||
>
|
>
|
||||||
<input
|
|
||||||
class="ant-input css-dev-only-do-not-override-1i536d8"
|
|
||||||
placeholder="search_pipeline_placeholder"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
class="ant-input-suffix"
|
aria-label="close-circle"
|
||||||
|
class="anticon anticon-close-circle"
|
||||||
|
role="img"
|
||||||
>
|
>
|
||||||
<span
|
<svg
|
||||||
class="ant-input-clear-icon ant-input-clear-icon-hidden"
|
aria-hidden="true"
|
||||||
role="button"
|
data-icon="close-circle"
|
||||||
tabindex="-1"
|
fill="currentColor"
|
||||||
|
focusable="false"
|
||||||
|
height="1em"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
width="1em"
|
||||||
>
|
>
|
||||||
<span
|
<path
|
||||||
aria-label="close-circle"
|
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
||||||
class="anticon anticon-close-circle"
|
/>
|
||||||
role="img"
|
</svg>
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="close-circle"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
|
||||||
class="ant-input-group-addon"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-btn css-dev-only-do-not-override-1i536d8 ant-btn-default ant-btn-icon-only ant-input-search-button"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="search"
|
|
||||||
class="anticon anticon-search"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="search"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
|
@ -45,6 +45,6 @@ export const routeConfig: Record<string, QueryParams[]> = {
|
|||||||
[ROUTES.USAGE_EXPLORER]: [QueryParams.resourceAttributes],
|
[ROUTES.USAGE_EXPLORER]: [QueryParams.resourceAttributes],
|
||||||
[ROUTES.VERSION]: [QueryParams.resourceAttributes],
|
[ROUTES.VERSION]: [QueryParams.resourceAttributes],
|
||||||
[ROUTES.TRACE_EXPLORER]: [QueryParams.resourceAttributes],
|
[ROUTES.TRACE_EXPLORER]: [QueryParams.resourceAttributes],
|
||||||
[ROUTES.PIPELINES]: [QueryParams.resourceAttributes],
|
[ROUTES.LOGS_PIPELINES]: [QueryParams.resourceAttributes],
|
||||||
[ROUTES.WORKSPACE_LOCKED]: [QueryParams.resourceAttributes],
|
[ROUTES.WORKSPACE_LOCKED]: [QueryParams.resourceAttributes],
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
LineChartOutlined,
|
LineChartOutlined,
|
||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
RocketOutlined,
|
RocketOutlined,
|
||||||
|
SearchOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
@ -35,6 +36,18 @@ const menuItems: SidebarMenu[] = [
|
|||||||
key: ROUTES.LOGS_EXPLORER,
|
key: ROUTES.LOGS_EXPLORER,
|
||||||
label: 'Logs',
|
label: 'Logs',
|
||||||
icon: <AlignLeftOutlined />,
|
icon: <AlignLeftOutlined />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: ROUTES.LOGS_EXPLORER,
|
||||||
|
icon: <SearchOutlined />,
|
||||||
|
label: 'Logs Explorer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: ROUTES.LOGS_PIPELINES,
|
||||||
|
icon: <DeploymentUnitOutlined />,
|
||||||
|
label: 'Logs Pipelines',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: ROUTES.ALL_DASHBOARD,
|
key: ROUTES.ALL_DASHBOARD,
|
||||||
|
@ -23,7 +23,7 @@ const breadcrumbNameMap = {
|
|||||||
[ROUTES.LOGS]: 'Logs',
|
[ROUTES.LOGS]: 'Logs',
|
||||||
[ROUTES.LOGS_EXPLORER]: 'Logs Explorer',
|
[ROUTES.LOGS_EXPLORER]: 'Logs Explorer',
|
||||||
[ROUTES.LIVE_LOGS]: 'Live View',
|
[ROUTES.LIVE_LOGS]: 'Live View',
|
||||||
[ROUTES.PIPELINES]: 'Pipelines',
|
[ROUTES.LOGS_PIPELINES]: 'Logs Pipelines',
|
||||||
[ROUTES.BILLING]: 'Billing',
|
[ROUTES.BILLING]: 'Billing',
|
||||||
[ROUTES.SUPPORT]: 'Support',
|
[ROUTES.SUPPORT]: 'Support',
|
||||||
[ROUTES.WORKSPACE_LOCKED]: 'Workspace Locked',
|
[ROUTES.WORKSPACE_LOCKED]: 'Workspace Locked',
|
||||||
|
@ -83,7 +83,7 @@ export const routesToSkip = [
|
|||||||
ROUTES.ALERTS_NEW,
|
ROUTES.ALERTS_NEW,
|
||||||
ROUTES.EDIT_ALERTS,
|
ROUTES.EDIT_ALERTS,
|
||||||
ROUTES.LIST_ALL_ALERT,
|
ROUTES.LIST_ALL_ALERT,
|
||||||
ROUTES.PIPELINES,
|
ROUTES.LOGS_PIPELINES,
|
||||||
ROUTES.BILLING,
|
ROUTES.BILLING,
|
||||||
ROUTES.SUPPORT,
|
ROUTES.SUPPORT,
|
||||||
ROUTES.WORKSPACE_LOCKED,
|
ROUTES.WORKSPACE_LOCKED,
|
||||||
|
@ -75,9 +75,8 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
|||||||
LIVE_LOGS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
LIVE_LOGS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
LIST_LICENSES: ['ADMIN'],
|
LIST_LICENSES: ['ADMIN'],
|
||||||
LOGS_INDEX_FIELDS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
LOGS_INDEX_FIELDS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
LOGS_PIPELINE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
LOGS_PIPELINES: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
TRACE_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
TRACE_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
PIPELINES: ['ADMIN', 'EDITOR', 'VIEWER'],
|
|
||||||
GET_STARTED: ['ADMIN', 'EDITOR', 'VIEWER'],
|
GET_STARTED: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
WORKSPACE_LOCKED: ['ADMIN', 'EDITOR', 'VIEWER'],
|
WORKSPACE_LOCKED: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
BILLING: ['ADMIN', 'EDITOR', 'VIEWER'],
|
BILLING: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user