mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
feat: add support for single step funnels while creating from span details (#8492)
* feat: add support for single step funnels while creating from span details * fix: fix the UI for loading state
This commit is contained in:
parent
24d6d83575
commit
b91407416b
@ -1,5 +1,12 @@
|
|||||||
// Modal base styles
|
// Modal base styles
|
||||||
.add-span-to-funnel-modal-container {
|
.add-span-to-funnel-modal {
|
||||||
|
&__loading-spinner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
&-container {
|
||||||
.ant-modal {
|
.ant-modal {
|
||||||
&-content,
|
&-content,
|
||||||
&-header {
|
&-header {
|
||||||
@ -64,6 +71,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Main modal styles
|
// Main modal styles
|
||||||
.add-span-to-funnel-modal {
|
.add-span-to-funnel-modal {
|
||||||
@ -89,7 +97,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.steps-content {
|
.steps-content {
|
||||||
height: 500px;
|
max-height: 500px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,6 +99,7 @@ function AddSpanToFunnelModal({
|
|||||||
const [triggerSave, setTriggerSave] = useState<boolean>(false);
|
const [triggerSave, setTriggerSave] = useState<boolean>(false);
|
||||||
const [isUnsavedChanges, setIsUnsavedChanges] = useState<boolean>(false);
|
const [isUnsavedChanges, setIsUnsavedChanges] = useState<boolean>(false);
|
||||||
const [triggerDiscard, setTriggerDiscard] = useState<boolean>(false);
|
const [triggerDiscard, setTriggerDiscard] = useState<boolean>(false);
|
||||||
|
const [isCreatedFromSpan, setIsCreatedFromSpan] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleSearch = (e: ChangeEvent<HTMLInputElement>): void => {
|
const handleSearch = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||||
setSearchQuery(e.target.value);
|
setSearchQuery(e.target.value);
|
||||||
@ -126,6 +127,7 @@ function AddSpanToFunnelModal({
|
|||||||
const handleFunnelClick = (funnel: FunnelData): void => {
|
const handleFunnelClick = (funnel: FunnelData): void => {
|
||||||
setSelectedFunnelId(funnel.funnel_id);
|
setSelectedFunnelId(funnel.funnel_id);
|
||||||
setActiveView(ModalView.DETAILS);
|
setActiveView(ModalView.DETAILS);
|
||||||
|
setIsCreatedFromSpan(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBack = (): void => {
|
const handleBack = (): void => {
|
||||||
@ -133,6 +135,7 @@ function AddSpanToFunnelModal({
|
|||||||
setSelectedFunnelId(undefined);
|
setSelectedFunnelId(undefined);
|
||||||
setIsUnsavedChanges(false);
|
setIsUnsavedChanges(false);
|
||||||
setTriggerSave(false);
|
setTriggerSave(false);
|
||||||
|
setIsCreatedFromSpan(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateNewClick = (): void => {
|
const handleCreateNewClick = (): void => {
|
||||||
@ -188,6 +191,7 @@ function AddSpanToFunnelModal({
|
|||||||
if (funnelId) {
|
if (funnelId) {
|
||||||
setSelectedFunnelId(funnelId);
|
setSelectedFunnelId(funnelId);
|
||||||
setActiveView(ModalView.DETAILS);
|
setActiveView(ModalView.DETAILS);
|
||||||
|
setIsCreatedFromSpan(true);
|
||||||
}
|
}
|
||||||
setIsCreateModalOpen(false);
|
setIsCreateModalOpen(false);
|
||||||
}}
|
}}
|
||||||
@ -206,15 +210,18 @@ function AddSpanToFunnelModal({
|
|||||||
<ArrowLeft size={14} />
|
<ArrowLeft size={14} />
|
||||||
All funnels
|
All funnels
|
||||||
</Button>
|
</Button>
|
||||||
|
<div className="traces-funnel-details">
|
||||||
|
<div className="traces-funnel-details__steps-config">
|
||||||
<Spin
|
<Spin
|
||||||
style={{ height: 400 }}
|
className="add-span-to-funnel-modal__loading-spinner"
|
||||||
spinning={isFunnelDetailsLoading || isFunnelDetailsFetching}
|
spinning={isFunnelDetailsLoading || isFunnelDetailsFetching}
|
||||||
indicator={<LoadingOutlined spin />}
|
indicator={<LoadingOutlined spin />}
|
||||||
>
|
>
|
||||||
<div className="traces-funnel-details">
|
|
||||||
<div className="traces-funnel-details__steps-config">
|
|
||||||
{selectedFunnelId && funnelDetails?.payload && (
|
{selectedFunnelId && funnelDetails?.payload && (
|
||||||
<FunnelProvider funnelId={selectedFunnelId}>
|
<FunnelProvider
|
||||||
|
funnelId={selectedFunnelId}
|
||||||
|
hasSingleStep={isCreatedFromSpan}
|
||||||
|
>
|
||||||
<FunnelDetailsView
|
<FunnelDetailsView
|
||||||
funnel={funnelDetails.payload}
|
funnel={funnelDetails.payload}
|
||||||
span={span}
|
span={span}
|
||||||
@ -225,10 +232,10 @@ function AddSpanToFunnelModal({
|
|||||||
/>
|
/>
|
||||||
</FunnelProvider>
|
</FunnelProvider>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { FunnelStepData, LatencyOptions } from 'types/api/traceFunnels';
|
import { FunnelStepData, LatencyOptions } from 'types/api/traceFunnels';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
export const initialStepsData: FunnelStepData[] = [
|
export const createInitialStepsData = (): FunnelStepData[] => [
|
||||||
{
|
{
|
||||||
id: v4(),
|
id: v4(),
|
||||||
step_order: 1,
|
step_order: 1,
|
||||||
@ -12,7 +12,6 @@ export const initialStepsData: FunnelStepData[] = [
|
|||||||
op: 'and',
|
op: 'and',
|
||||||
},
|
},
|
||||||
latency_pointer: 'start',
|
latency_pointer: 'start',
|
||||||
latency_type: undefined,
|
|
||||||
has_errors: false,
|
has_errors: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -30,6 +29,21 @@ export const initialStepsData: FunnelStepData[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const createSingleStepData = (): FunnelStepData[] => [
|
||||||
|
{
|
||||||
|
id: v4(),
|
||||||
|
step_order: 1,
|
||||||
|
service_name: '',
|
||||||
|
span_name: '',
|
||||||
|
filters: {
|
||||||
|
items: [],
|
||||||
|
op: 'and',
|
||||||
|
},
|
||||||
|
latency_pointer: 'start',
|
||||||
|
has_errors: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const LatencyPointers: {
|
export const LatencyPointers: {
|
||||||
value: FunnelStepData['latency_pointer'];
|
value: FunnelStepData['latency_pointer'];
|
||||||
key: string;
|
key: string;
|
||||||
|
|||||||
@ -10,7 +10,10 @@ import { normalizeSteps } from 'hooks/TracesFunnels/useFunnelConfiguration';
|
|||||||
import { useValidateFunnelSteps } from 'hooks/TracesFunnels/useFunnels';
|
import { useValidateFunnelSteps } from 'hooks/TracesFunnels/useFunnels';
|
||||||
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
|
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { initialStepsData } from 'pages/TracesFunnelDetails/constants';
|
import {
|
||||||
|
createInitialStepsData,
|
||||||
|
createSingleStepData,
|
||||||
|
} from 'pages/TracesFunnelDetails/constants';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
Dispatch,
|
Dispatch,
|
||||||
@ -68,9 +71,11 @@ const FunnelContext = createContext<FunnelContextType | undefined>(undefined);
|
|||||||
export function FunnelProvider({
|
export function FunnelProvider({
|
||||||
children,
|
children,
|
||||||
funnelId,
|
funnelId,
|
||||||
|
hasSingleStep = false,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
funnelId: string;
|
funnelId: string;
|
||||||
|
hasSingleStep?: boolean;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { selectedTime } = useSelector<AppState, GlobalReducer>(
|
const { selectedTime } = useSelector<AppState, GlobalReducer>(
|
||||||
(state) => state.globalTime,
|
(state) => state.globalTime,
|
||||||
@ -89,7 +94,13 @@ export function FunnelProvider({
|
|||||||
funnelId,
|
funnelId,
|
||||||
]);
|
]);
|
||||||
const funnel = data?.payload;
|
const funnel = data?.payload;
|
||||||
const initialSteps = funnel?.steps?.length ? funnel.steps : initialStepsData;
|
|
||||||
|
const defaultSteps = useMemo(
|
||||||
|
() => (hasSingleStep ? createSingleStepData() : createInitialStepsData()),
|
||||||
|
[hasSingleStep],
|
||||||
|
);
|
||||||
|
|
||||||
|
const initialSteps = funnel?.steps?.length ? funnel.steps : defaultSteps;
|
||||||
const [steps, setSteps] = useState<FunnelStepData[]>(initialSteps);
|
const [steps, setSteps] = useState<FunnelStepData[]>(initialSteps);
|
||||||
const [triggerSave, setTriggerSave] = useState<boolean>(false);
|
const [triggerSave, setTriggerSave] = useState<boolean>(false);
|
||||||
const [isUpdatingFunnel, setIsUpdatingFunnel] = useState<boolean>(false);
|
const [isUpdatingFunnel, setIsUpdatingFunnel] = useState<boolean>(false);
|
||||||
@ -155,7 +166,7 @@ export function FunnelProvider({
|
|||||||
setSteps((prev) => [
|
setSteps((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
...initialStepsData[0],
|
...createInitialStepsData()[0],
|
||||||
id: v4(),
|
id: v4(),
|
||||||
step_order: prev.length + 1,
|
step_order: prev.length + 1,
|
||||||
},
|
},
|
||||||
@ -296,6 +307,10 @@ export function FunnelProvider({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunnelProvider.defaultProps = {
|
||||||
|
hasSingleStep: false,
|
||||||
|
};
|
||||||
|
|
||||||
export function useFunnelContext(): FunnelContextType {
|
export function useFunnelContext(): FunnelContextType {
|
||||||
const context = useContext(FunnelContext);
|
const context = useContext(FunnelContext);
|
||||||
if (context === undefined) {
|
if (context === undefined) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user