mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-22 20:00:29 +01:00
Compare commits
4 Commits
feat/cloud
...
v0.120.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3080c3c493 | ||
|
|
b0e9fbe24f | ||
|
|
aeb71469d9 | ||
|
|
1ff9a748ee |
@@ -190,7 +190,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.119.0
|
||||
image: signoz/signoz:v0.120.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
# - "6060:6060" # pprof port
|
||||
@@ -213,7 +213,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.2
|
||||
image: signoz/signoz-otel-collector:v0.144.3
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command:
|
||||
@@ -241,7 +241,7 @@ services:
|
||||
replicas: 3
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.2
|
||||
image: signoz/signoz-otel-collector:v0.144.3
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_CLUSTER=cluster
|
||||
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.119.0
|
||||
image: signoz/signoz:v0.120.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
volumes:
|
||||
@@ -139,7 +139,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.2
|
||||
image: signoz/signoz-otel-collector:v0.144.3
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
command:
|
||||
@@ -167,7 +167,7 @@ services:
|
||||
replicas: 3
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:v0.144.2
|
||||
image: signoz/signoz-otel-collector:v0.144.3
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_CLUSTER=cluster
|
||||
|
||||
@@ -181,7 +181,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.119.0}
|
||||
image: signoz/signoz:${VERSION:-v0.120.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
@@ -204,7 +204,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.2}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.3}
|
||||
container_name: signoz-otel-collector
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
@@ -229,7 +229,7 @@ services:
|
||||
- "4318:4318" # OTLP HTTP receiver
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.2}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.3}
|
||||
container_name: signoz-telemetrystore-migrator
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
|
||||
@@ -109,7 +109,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.119.0}
|
||||
image: signoz/signoz:${VERSION:-v0.120.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
@@ -132,7 +132,7 @@ services:
|
||||
retries: 3
|
||||
otel-collector:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.2}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.3}
|
||||
container_name: signoz-otel-collector
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
@@ -157,7 +157,7 @@ services:
|
||||
- "4318:4318" # OTLP HTTP receiver
|
||||
signoz-telemetrystore-migrator:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.2}
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-v0.144.3}
|
||||
container_name: signoz-telemetrystore-migrator
|
||||
environment:
|
||||
- SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://clickhouse:9000
|
||||
|
||||
@@ -79,7 +79,7 @@ export function useNavigateToExplorer(): (
|
||||
);
|
||||
|
||||
const { getUpdatedQuery } = useUpdatedQuery();
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
return useCallback(
|
||||
@@ -111,7 +111,7 @@ export function useNavigateToExplorer(): (
|
||||
panelTypes: PANEL_TYPES.TIME_SERIES,
|
||||
timePreferance: 'GLOBAL_TIME',
|
||||
},
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
})
|
||||
.then((query) => {
|
||||
preparedQuery = query;
|
||||
@@ -140,7 +140,7 @@ export function useNavigateToExplorer(): (
|
||||
minTime,
|
||||
maxTime,
|
||||
getUpdatedQuery,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
notifications,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -87,8 +87,8 @@ jest.mock('hooks/useDarkMode', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): { selectedDashboard: undefined } => ({
|
||||
selectedDashboard: undefined,
|
||||
useDashboardStore: (): { dashboardData: undefined } => ({
|
||||
dashboardData: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@@ -196,12 +196,12 @@ describe('Dashboard landing page actions header tests', () => {
|
||||
(useLocation as jest.Mock).mockReturnValue(mockLocation);
|
||||
|
||||
useDashboardStore.setState({
|
||||
selectedDashboard: (getDashboardById.data as unknown) as Dashboard,
|
||||
dashboardData: (getDashboardById.data as unknown) as Dashboard,
|
||||
layouts: [],
|
||||
panelMap: {},
|
||||
setPanelMap: jest.fn(),
|
||||
setLayouts: jest.fn(),
|
||||
setSelectedDashboard: jest.fn(),
|
||||
setDashboardData: jest.fn(),
|
||||
columnWidths: {},
|
||||
});
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
(s) => s.setIsPanelTypeSelectionModalOpen,
|
||||
);
|
||||
const {
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
panelMap,
|
||||
setPanelMap,
|
||||
layouts,
|
||||
setLayouts,
|
||||
setSelectedDashboard,
|
||||
setDashboardData,
|
||||
} = useDashboardStore();
|
||||
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
@@ -98,10 +98,10 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
|
||||
const isPublicDashboardEnabled = isCloudUser || isEnterpriseSelfHostedUser;
|
||||
|
||||
const selectedData = selectedDashboard
|
||||
const selectedData = dashboardData
|
||||
? {
|
||||
...selectedDashboard.data,
|
||||
uuid: selectedDashboard.id,
|
||||
...dashboardData.data,
|
||||
uuid: dashboardData.id,
|
||||
}
|
||||
: ({} as DashboardData);
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
@@ -133,8 +133,8 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
|
||||
let isAuthor = false;
|
||||
|
||||
if (selectedDashboard && user && user.email) {
|
||||
isAuthor = selectedDashboard?.createdBy === user?.email;
|
||||
if (dashboardData && user && user.email) {
|
||||
isAuthor = dashboardData?.createdBy === user?.email;
|
||||
}
|
||||
|
||||
let permissions: ComponentTypes[] = ['add_panel'];
|
||||
@@ -146,7 +146,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
const userRole: ROLES | null =
|
||||
selectedDashboard?.createdBy === user?.email
|
||||
dashboardData?.createdBy === user?.email
|
||||
? (USER_ROLES.AUTHOR as ROLES)
|
||||
: user.role;
|
||||
|
||||
@@ -155,9 +155,9 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
const onEmptyWidgetHandler = useCallback(() => {
|
||||
setIsPanelTypeSelectionModalOpen(true);
|
||||
logEvent('Dashboard Detail: Add new panel clicked', {
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardName: selectedDashboard?.data.title,
|
||||
numberOfPanels: selectedDashboard?.data.widgets?.length,
|
||||
dashboardId: dashboardData?.id,
|
||||
dashboardName: dashboardData?.data.title,
|
||||
numberOfPanels: dashboardData?.data.widgets?.length,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setIsPanelTypeSelectionModalOpen]);
|
||||
@@ -168,14 +168,14 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
};
|
||||
|
||||
const onNameChangeHandler = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
const updatedDashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
title: updatedTitle,
|
||||
},
|
||||
};
|
||||
@@ -186,7 +186,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
});
|
||||
setIsRenameDashboardOpen(false);
|
||||
if (updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
@@ -203,10 +203,10 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
// the context value is sometimes not available during the initial render
|
||||
// due to which the updatedTitle is set to some previous value
|
||||
useEffect(() => {
|
||||
if (selectedDashboard) {
|
||||
setUpdatedTitle(selectedDashboard.data.title);
|
||||
if (dashboardData) {
|
||||
setUpdatedTitle(dashboardData.data.title);
|
||||
}
|
||||
}, [selectedDashboard]);
|
||||
}, [dashboardData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (state.error) {
|
||||
@@ -227,7 +227,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
}, [state.error, state.value, t, notifications]);
|
||||
|
||||
function handleAddRow(): void {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
const id = uuid();
|
||||
@@ -246,10 +246,10 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
}
|
||||
|
||||
const updatedDashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
layout: [
|
||||
{
|
||||
i: id,
|
||||
@@ -265,7 +265,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
],
|
||||
panelMap: { ...panelMap, [id]: newRowWidgetMap },
|
||||
widgets: [
|
||||
...(selectedDashboard.data.widgets || []),
|
||||
...(dashboardData.data.widgets || []),
|
||||
{
|
||||
id,
|
||||
title: sectionName,
|
||||
@@ -282,7 +282,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
if (updatedDashboard.data.data.layout) {
|
||||
setLayouts(sortLayout(updatedDashboard.data.data.layout));
|
||||
}
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||
}
|
||||
|
||||
@@ -299,8 +299,8 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
error: errorPublicDashboardData,
|
||||
isError: isErrorPublicDashboardData,
|
||||
} = useGetPublicDashboardMeta(
|
||||
selectedDashboard?.id || '',
|
||||
!!selectedDashboard?.id && isPublicDashboardEnabled,
|
||||
dashboardData?.id || '',
|
||||
!!dashboardData?.id && isPublicDashboardEnabled,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -378,14 +378,14 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
{(isAuthor || user.role === USER_ROLES.ADMIN) && (
|
||||
<Tooltip
|
||||
title={
|
||||
selectedDashboard?.createdBy === 'integration' &&
|
||||
dashboardData?.createdBy === 'integration' &&
|
||||
'Dashboards created by integrations cannot be unlocked'
|
||||
}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<LockKeyhole size={14} />}
|
||||
disabled={selectedDashboard?.createdBy === 'integration'}
|
||||
disabled={dashboardData?.createdBy === 'integration'}
|
||||
onClick={handleLockDashboardToggle}
|
||||
data-testid="lock-unlock-dashboard"
|
||||
>
|
||||
@@ -457,9 +457,9 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
</section>
|
||||
<section className="delete-dashboard">
|
||||
<DeleteButton
|
||||
createdBy={selectedDashboard?.createdBy || ''}
|
||||
name={selectedDashboard?.data.title || ''}
|
||||
id={String(selectedDashboard?.id) || ''}
|
||||
createdBy={dashboardData?.createdBy || ''}
|
||||
name={dashboardData?.data.title || ''}
|
||||
id={String(dashboardData?.id) || ''}
|
||||
isLocked={isDashboardLocked}
|
||||
routeToListPage
|
||||
/>
|
||||
|
||||
@@ -239,7 +239,7 @@ function VariableItem({
|
||||
|
||||
const [selectedWidgets, setSelectedWidgets] = useState<string[]>([]);
|
||||
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const widgetsByDynamicVariableId = useWidgetsByDynamicVariableId();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -248,7 +248,7 @@ function VariableItem({
|
||||
} else if (dynamicVariablesSelectedValue?.name) {
|
||||
const widgets = getWidgetsHavingDynamicVariableAttribute(
|
||||
dynamicVariablesSelectedValue?.name,
|
||||
(selectedDashboard?.data?.widgets?.filter(
|
||||
(dashboardData?.data?.widgets?.filter(
|
||||
(widget) => widget.panelTypes !== PANEL_GROUP_TYPES.ROW,
|
||||
) || []) as Widgets[],
|
||||
variableData.name,
|
||||
@@ -257,7 +257,7 @@ function VariableItem({
|
||||
}
|
||||
}, [
|
||||
dynamicVariablesSelectedValue?.name,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
variableData.id,
|
||||
variableData.name,
|
||||
widgetsByDynamicVariableId,
|
||||
|
||||
@@ -12,17 +12,17 @@ export function WidgetSelector({
|
||||
selectedWidgets: string[];
|
||||
setSelectedWidgets: (widgets: string[]) => void;
|
||||
}): JSX.Element {
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
|
||||
// Get layout IDs for cross-referencing
|
||||
const layoutIds = new Set(
|
||||
(selectedDashboard?.data?.layout || []).map((item) => item.i),
|
||||
(dashboardData?.data?.layout || []).map((item) => item.i),
|
||||
);
|
||||
|
||||
// Filter and deduplicate widgets by ID, keeping only those with layout entries
|
||||
// and excluding row widgets since they are not panels that can have variables
|
||||
const widgets = Object.values(
|
||||
(selectedDashboard?.data?.widgets || []).reduce(
|
||||
(dashboardData?.data?.widgets || []).reduce(
|
||||
(acc: Record<string, WidgetRow | Widgets>, widget: WidgetRow | Widgets) => {
|
||||
if (
|
||||
widget.id &&
|
||||
|
||||
@@ -87,7 +87,7 @@ function VariablesSettings({
|
||||
|
||||
const { t } = useTranslation(['dashboard']);
|
||||
|
||||
const { selectedDashboard, setSelectedDashboard } = useDashboardStore();
|
||||
const { dashboardData, setDashboardData } = useDashboardStore();
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
@@ -173,7 +173,7 @@ function VariablesSettings({
|
||||
widgetIds?: string[],
|
||||
applyToAll?: boolean,
|
||||
): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,16 +181,16 @@ function VariablesSettings({
|
||||
(currentRequestedId &&
|
||||
updatedVariablesData[currentRequestedId || '']?.type === 'DYNAMIC' &&
|
||||
addDynamicVariableToPanels(
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
updatedVariablesData[currentRequestedId || ''],
|
||||
widgetIds,
|
||||
applyToAll,
|
||||
)) ||
|
||||
selectedDashboard;
|
||||
dashboardData;
|
||||
|
||||
updateMutation.mutateAsync(
|
||||
{
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...newDashboard.data,
|
||||
@@ -200,7 +200,7 @@ function VariablesSettings({
|
||||
{
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
notifications.success({
|
||||
message: t('variable_updated_successfully'),
|
||||
});
|
||||
|
||||
@@ -15,11 +15,11 @@ import './GeneralSettings.styles.scss';
|
||||
const { Option } = Select;
|
||||
|
||||
function GeneralDashboardSettings(): JSX.Element {
|
||||
const { selectedDashboard, setSelectedDashboard } = useDashboardStore();
|
||||
const { dashboardData, setDashboardData } = useDashboardStore();
|
||||
|
||||
const updateDashboardMutation = useUpdateDashboard();
|
||||
|
||||
const selectedData = selectedDashboard?.data;
|
||||
const selectedData = dashboardData?.data;
|
||||
|
||||
const { title = '', tags = [], description = '', image = Base64Icons[0] } =
|
||||
selectedData || {};
|
||||
@@ -37,15 +37,15 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
const { t } = useTranslation('common');
|
||||
|
||||
const onSaveHandler = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateDashboardMutation.mutate(
|
||||
{
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
description: updatedDescription,
|
||||
tags: updatedTags,
|
||||
title: updatedTitle,
|
||||
@@ -55,7 +55,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
{
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
},
|
||||
onError: () => {},
|
||||
|
||||
@@ -41,7 +41,7 @@ const DASHBOARD_VARIABLES_WARNING =
|
||||
// Use wildcard pattern to match both relative and absolute URLs in MSW
|
||||
const publicDashboardURL = `*/api/v1/dashboards/${MOCK_DASHBOARD_ID}/public`;
|
||||
|
||||
const mockSelectedDashboard = {
|
||||
const mockDashboardData = {
|
||||
id: MOCK_DASHBOARD_ID,
|
||||
data: {
|
||||
title: 'Test Dashboard',
|
||||
@@ -70,7 +70,7 @@ beforeEach(() => {
|
||||
|
||||
// Mock useDashboardStore
|
||||
mockUseDashboard.mockReturnValue(({
|
||||
selectedDashboard: mockSelectedDashboard,
|
||||
dashboardData: mockDashboardData,
|
||||
} as unknown) as ReturnType<typeof useDashboardStore>);
|
||||
|
||||
// Mock useCopyToClipboard
|
||||
|
||||
@@ -59,7 +59,7 @@ function PublicDashboardSetting(): JSX.Element {
|
||||
const [defaultTimeRange, setDefaultTimeRange] = useState(DEFAULT_TIME_RANGE);
|
||||
const [, setCopyPublicDashboardURL] = useCopyToClipboard();
|
||||
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
|
||||
const { isCloudUser, isEnterpriseSelfHostedUser } = useGetTenantLicense();
|
||||
|
||||
@@ -84,8 +84,8 @@ function PublicDashboardSetting(): JSX.Element {
|
||||
refetch: refetchPublicDashboard,
|
||||
error: errorPublicDashboard,
|
||||
} = useGetPublicDashboardMeta(
|
||||
selectedDashboard?.id || '',
|
||||
!!selectedDashboard?.id && isPublicDashboardEnabled,
|
||||
dashboardData?.id || '',
|
||||
!!dashboardData?.id && isPublicDashboardEnabled,
|
||||
);
|
||||
|
||||
const isPublicDashboard = !!publicDashboardData?.publicPath;
|
||||
@@ -154,36 +154,36 @@ function PublicDashboardSetting(): JSX.Element {
|
||||
});
|
||||
|
||||
const handleCreatePublicDashboard = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
createPublicDashboard({
|
||||
dashboardId: selectedDashboard.id,
|
||||
dashboardId: dashboardData.id,
|
||||
timeRangeEnabled,
|
||||
defaultTimeRange,
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdatePublicDashboard = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
updatePublicDashboard({
|
||||
dashboardId: selectedDashboard.id,
|
||||
dashboardId: dashboardData.id,
|
||||
timeRangeEnabled,
|
||||
defaultTimeRange,
|
||||
});
|
||||
};
|
||||
|
||||
const handleRevokePublicDashboardAccess = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
revokePublicDashboardAccess({
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ import VariableItem from './VariableItem';
|
||||
import './DashboardVariableSelection.styles.scss';
|
||||
|
||||
function DashboardVariableSelection(): JSX.Element | null {
|
||||
const { dashboardId, setSelectedDashboard } = useDashboardStore(
|
||||
const { dashboardId, setDashboardData } = useDashboardStore(
|
||||
useShallow((s) => ({
|
||||
dashboardId: s.selectedDashboard?.id ?? '',
|
||||
setSelectedDashboard: s.setSelectedDashboard,
|
||||
dashboardId: s.dashboardData?.id ?? '',
|
||||
setDashboardData: s.setDashboardData,
|
||||
})),
|
||||
);
|
||||
|
||||
@@ -99,7 +99,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
|
||||
// Synchronously update the external store with the new variable value so that
|
||||
// child variables see the updated parent value when they refetch, rather than
|
||||
// waiting for setSelectedDashboard → useEffect → updateDashboardVariablesStore.
|
||||
// waiting for setDashboardData → useEffect → updateDashboardVariablesStore.
|
||||
const updatedVariables = { ...dashboardVariables };
|
||||
if (updatedVariables[id]) {
|
||||
updatedVariables[id] = {
|
||||
@@ -119,7 +119,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
}
|
||||
updateDashboardVariablesStore({ dashboardId, variables: updatedVariables });
|
||||
|
||||
setSelectedDashboard((prev) => {
|
||||
setDashboardData((prev) => {
|
||||
if (prev) {
|
||||
const oldVariables = { ...prev?.data.variables };
|
||||
// this is added to handle case where we have two different
|
||||
@@ -157,7 +157,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
// Safe to call synchronously now that the store already has the updated value.
|
||||
enqueueDescendantsOfVariable(name);
|
||||
},
|
||||
[dashboardId, dashboardVariables, updateUrlVariable, setSelectedDashboard],
|
||||
[dashboardId, dashboardVariables, updateUrlVariable, setDashboardData],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -30,11 +30,11 @@ const mockVariableItemCallbacks: {
|
||||
} = {};
|
||||
|
||||
// Mock providers/Dashboard/Dashboard
|
||||
const mockSetSelectedDashboard = jest.fn();
|
||||
const mockSetDashboardData = jest.fn();
|
||||
const mockUpdateLocalStorageDashboardVariables = jest.fn();
|
||||
interface MockDashboardStoreState {
|
||||
selectedDashboard?: { id: string };
|
||||
setSelectedDashboard: typeof mockSetSelectedDashboard;
|
||||
dashboardData?: { id: string };
|
||||
setDashboardData: typeof mockSetDashboardData;
|
||||
updateLocalStorageDashboardVariables: typeof mockUpdateLocalStorageDashboardVariables;
|
||||
}
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
@@ -42,8 +42,8 @@ jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
selector?: (s: Record<string, unknown>) => MockDashboardStoreState,
|
||||
): MockDashboardStoreState => {
|
||||
const state = {
|
||||
selectedDashboard: { id: 'dash-1' },
|
||||
setSelectedDashboard: mockSetSelectedDashboard,
|
||||
dashboardData: { id: 'dash-1' },
|
||||
setDashboardData: mockSetDashboardData,
|
||||
updateLocalStorageDashboardVariables: mockUpdateLocalStorageDashboardVariables,
|
||||
};
|
||||
return selector ? selector(state) : state;
|
||||
|
||||
@@ -38,15 +38,11 @@ interface UseDashboardVariableUpdateReturn {
|
||||
}
|
||||
|
||||
export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn => {
|
||||
const {
|
||||
dashboardId,
|
||||
selectedDashboard,
|
||||
setSelectedDashboard,
|
||||
} = useDashboardStore(
|
||||
const { dashboardId, dashboardData, setDashboardData } = useDashboardStore(
|
||||
useShallow((s) => ({
|
||||
dashboardId: s.selectedDashboard?.id ?? '',
|
||||
selectedDashboard: s.selectedDashboard,
|
||||
setSelectedDashboard: s.setSelectedDashboard,
|
||||
dashboardId: s.dashboardData?.id ?? '',
|
||||
dashboardData: s.dashboardData,
|
||||
setDashboardData: s.setDashboardData,
|
||||
})),
|
||||
);
|
||||
const addDynamicVariableToPanels = useAddDynamicVariableToPanels();
|
||||
@@ -74,8 +70,8 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
isDynamic,
|
||||
);
|
||||
|
||||
if (selectedDashboard) {
|
||||
setSelectedDashboard((prev) => {
|
||||
if (dashboardData) {
|
||||
setDashboardData((prev) => {
|
||||
if (prev) {
|
||||
const oldVariables = prev?.data.variables;
|
||||
// this is added to handle case where we have two different
|
||||
@@ -110,7 +106,7 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
}
|
||||
}
|
||||
},
|
||||
[dashboardId, selectedDashboard, setSelectedDashboard],
|
||||
[dashboardId, dashboardData, setDashboardData],
|
||||
);
|
||||
|
||||
const updateVariables = useCallback(
|
||||
@@ -120,23 +116,23 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
widgetIds?: string[],
|
||||
applyToAll?: boolean,
|
||||
): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newDashboard =
|
||||
(currentRequestedId &&
|
||||
addDynamicVariableToPanels(
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
updatedVariablesData[currentRequestedId || ''],
|
||||
widgetIds,
|
||||
applyToAll,
|
||||
)) ||
|
||||
selectedDashboard;
|
||||
dashboardData;
|
||||
|
||||
updateMutation.mutateAsync(
|
||||
{
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...newDashboard.data,
|
||||
@@ -146,7 +142,7 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
{
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
// notifications.success({
|
||||
// message: t('variable_updated_successfully'),
|
||||
// });
|
||||
@@ -155,12 +151,7 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
},
|
||||
);
|
||||
},
|
||||
[
|
||||
selectedDashboard,
|
||||
addDynamicVariableToPanels,
|
||||
updateMutation,
|
||||
setSelectedDashboard,
|
||||
],
|
||||
[dashboardData, addDynamicVariableToPanels, updateMutation, setDashboardData],
|
||||
);
|
||||
|
||||
const createVariable = useCallback(
|
||||
@@ -172,13 +163,13 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
source: 'logs' | 'traces' | 'metrics' | 'all sources' = 'all sources',
|
||||
// widgetId?: string,
|
||||
): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
console.warn('No dashboard selected for variable creation');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current dashboard variables
|
||||
const currentVariables = selectedDashboard.data.variables || {};
|
||||
const currentVariables = dashboardData.data.variables || {};
|
||||
|
||||
// Create tableRowData like Dashboard Settings does
|
||||
const tableRowData = [];
|
||||
@@ -234,7 +225,7 @@ export const useDashboardVariableUpdate = (): UseDashboardVariableUpdateReturn =
|
||||
const updatedVariables = convertVariablesToDbFormat(tableRowData);
|
||||
updateVariables(updatedVariables, newVariable.id, [], false);
|
||||
},
|
||||
[selectedDashboard, updateVariables],
|
||||
[dashboardData, updateVariables],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -47,12 +47,12 @@ const mockDashboard = {
|
||||
};
|
||||
|
||||
// Mock the dashboard provider with stable functions to prevent infinite loops
|
||||
const mockSetSelectedDashboard = jest.fn();
|
||||
const mockSetDashboardData = jest.fn();
|
||||
const mockUpdateLocalStorageDashboardVariables = jest.fn();
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): any => ({
|
||||
selectedDashboard: mockDashboard,
|
||||
setSelectedDashboard: mockSetSelectedDashboard,
|
||||
dashboardData: mockDashboard,
|
||||
setDashboardData: mockSetDashboardData,
|
||||
updateLocalStorageDashboardVariables: mockUpdateLocalStorageDashboardVariables,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -58,7 +58,7 @@ const mockDashboard = {
|
||||
// Mock dependencies
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): any => ({
|
||||
selectedDashboard: mockDashboard,
|
||||
dashboardData: mockDashboard,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -154,7 +154,7 @@ describe('Panel Management Tests', () => {
|
||||
// Temporarily mock the dashboard
|
||||
jest.doMock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): any => ({
|
||||
selectedDashboard: modifiedDashboard,
|
||||
dashboardData: modifiedDashboard,
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ import './DashboardBreadcrumbs.styles.scss';
|
||||
|
||||
function DashboardBreadcrumbs(): JSX.Element {
|
||||
const { safeNavigate } = useSafeNavigate();
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const updatedAtRef = useRef(selectedDashboard?.updatedAt);
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const updatedAtRef = useRef(dashboardData?.updatedAt);
|
||||
|
||||
const selectedData = selectedDashboard
|
||||
const selectedData = dashboardData
|
||||
? {
|
||||
...selectedDashboard.data,
|
||||
uuid: selectedDashboard.id,
|
||||
...dashboardData.data,
|
||||
uuid: dashboardData.id,
|
||||
}
|
||||
: ({} as DashboardData);
|
||||
|
||||
@@ -31,7 +31,7 @@ function DashboardBreadcrumbs(): JSX.Element {
|
||||
);
|
||||
|
||||
const hasDashboardBeenUpdated =
|
||||
selectedDashboard?.updatedAt !== updatedAtRef.current;
|
||||
dashboardData?.updatedAt !== updatedAtRef.current;
|
||||
if (!hasDashboardBeenUpdated && dashboardsListQueryParamsString) {
|
||||
safeNavigate({
|
||||
pathname: ROUTES.ALL_DASHBOARD,
|
||||
@@ -40,7 +40,7 @@ function DashboardBreadcrumbs(): JSX.Element {
|
||||
} else {
|
||||
safeNavigate(ROUTES.ALL_DASHBOARD);
|
||||
}
|
||||
}, [safeNavigate, selectedDashboard?.updatedAt]);
|
||||
}, [safeNavigate, dashboardData?.updatedAt]);
|
||||
|
||||
return (
|
||||
<div className="dashboard-breadcrumbs">
|
||||
|
||||
@@ -35,15 +35,15 @@ jest.mock('lib/uPlotV2/hooks/useLegendsSync', () => ({
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (
|
||||
selector?: (s: {
|
||||
selectedDashboard: { locked: boolean } | undefined;
|
||||
}) => { selectedDashboard: { locked: boolean } },
|
||||
): { selectedDashboard: { locked: boolean } } => {
|
||||
const mockState = { selectedDashboard: { locked: false } };
|
||||
dashboardData: { locked: boolean } | undefined;
|
||||
}) => { dashboardData: { locked: boolean } },
|
||||
): { dashboardData: { locked: boolean } } => {
|
||||
const mockState = { dashboardData: { locked: false } };
|
||||
return selector ? selector(mockState) : mockState;
|
||||
},
|
||||
selectIsDashboardLocked: (s: {
|
||||
selectedDashboard: { locked: boolean } | undefined;
|
||||
}): boolean => s.selectedDashboard?.locked ?? false,
|
||||
dashboardData: { locked: boolean } | undefined;
|
||||
}): boolean => s.dashboardData?.locked ?? false,
|
||||
}));
|
||||
|
||||
jest.mock('hooks/useNotifications', () => ({
|
||||
|
||||
@@ -24,9 +24,7 @@ function ExportPanelContainer({
|
||||
}: ExportPanelProps): JSX.Element {
|
||||
const { t } = useTranslation(['dashboard']);
|
||||
|
||||
const [selectedDashboardId, setSelectedDashboardId] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const [dashboardId, setDashboardId] = useState<string | null>(null);
|
||||
|
||||
const {
|
||||
data,
|
||||
@@ -55,17 +53,17 @@ function ExportPanelContainer({
|
||||
|
||||
const handleExportClick = useCallback((): void => {
|
||||
const currentSelectedDashboard = data?.data?.find(
|
||||
({ id }) => id === selectedDashboardId,
|
||||
({ id }) => id === dashboardId,
|
||||
);
|
||||
|
||||
onExport(currentSelectedDashboard || null, false);
|
||||
}, [data, selectedDashboardId, onExport]);
|
||||
}, [data, dashboardId, onExport]);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(selectedDashboardValue: string): void => {
|
||||
setSelectedDashboardId(selectedDashboardValue);
|
||||
(selectedDashboardId: string): void => {
|
||||
setDashboardId(selectedDashboardId);
|
||||
},
|
||||
[setSelectedDashboardId],
|
||||
[setDashboardId],
|
||||
);
|
||||
|
||||
const handleNewDashboard = useCallback(async () => {
|
||||
@@ -85,10 +83,7 @@ function ExportPanelContainer({
|
||||
const isDashboardLoading = isAllDashboardsLoading || createDashboardLoading;
|
||||
|
||||
const isDisabled =
|
||||
isAllDashboardsLoading ||
|
||||
!options?.length ||
|
||||
!selectedDashboardId ||
|
||||
isLoading;
|
||||
isAllDashboardsLoading || !options?.length || !dashboardId || isLoading;
|
||||
|
||||
return (
|
||||
<Wrapper direction="vertical">
|
||||
@@ -101,7 +96,7 @@ function ExportPanelContainer({
|
||||
showSearch
|
||||
loading={isDashboardLoading}
|
||||
disabled={isDashboardLoading}
|
||||
value={selectedDashboardId}
|
||||
value={dashboardId}
|
||||
onSelect={handleSelect}
|
||||
filterOption={filterOptions}
|
||||
/>
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function DashboardEmptyState(): JSX.Element {
|
||||
(s) => s.setIsPanelTypeSelectionModalOpen,
|
||||
);
|
||||
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
|
||||
const variablesSettingsTabHandle = useRef<VariablesSettingsTab>(null);
|
||||
@@ -43,7 +43,7 @@ export default function DashboardEmptyState(): JSX.Element {
|
||||
}
|
||||
|
||||
const userRole: ROLES | null =
|
||||
selectedDashboard?.createdBy === user?.email
|
||||
dashboardData?.createdBy === user?.email
|
||||
? (USER_ROLES.AUTHOR as ROLES)
|
||||
: user.role;
|
||||
|
||||
@@ -52,9 +52,9 @@ export default function DashboardEmptyState(): JSX.Element {
|
||||
const onEmptyWidgetHandler = useCallback(() => {
|
||||
setIsPanelTypeSelectionModalOpen(true);
|
||||
logEvent('Dashboard Detail: Add new panel clicked', {
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardName: selectedDashboard?.data.title,
|
||||
numberOfPanels: selectedDashboard?.data.widgets?.length,
|
||||
dashboardId: dashboardData?.id,
|
||||
dashboardName: dashboardData?.data.title,
|
||||
numberOfPanels: dashboardData?.data.widgets?.length,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setIsPanelTypeSelectionModalOpen]);
|
||||
|
||||
@@ -91,7 +91,7 @@ function FullView({
|
||||
setCurrentGraphRef(fullViewRef);
|
||||
}, [setCurrentGraphRef]);
|
||||
|
||||
const { selectedDashboard, setColumnWidths } = useDashboardStore();
|
||||
const { dashboardData, setColumnWidths } = useDashboardStore();
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
|
||||
const onColumnWidthsChange = useCallback(
|
||||
@@ -166,7 +166,7 @@ function FullView({
|
||||
enableDrillDown,
|
||||
widget,
|
||||
setRequestData,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
selectedPanelType,
|
||||
});
|
||||
|
||||
@@ -344,7 +344,7 @@ function FullView({
|
||||
<>
|
||||
<QueryBuilderV2
|
||||
panelType={selectedPanelType}
|
||||
version={selectedDashboard?.data?.version || 'v3'}
|
||||
version={dashboardData?.data?.version || 'v3'}
|
||||
isListViewPanel={selectedPanelType === PANEL_TYPES.LIST}
|
||||
signalSourceChangeEnabled
|
||||
// filterConfigs={filterConfigs}
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface DrilldownQueryProps {
|
||||
widget: Widgets;
|
||||
setRequestData: Dispatch<SetStateAction<GetQueryResultsProps>>;
|
||||
enableDrillDown: boolean;
|
||||
selectedDashboard: Dashboard | undefined;
|
||||
dashboardData: Dashboard | undefined;
|
||||
selectedPanelType: PANEL_TYPES;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const useDrilldown = ({
|
||||
enableDrillDown,
|
||||
widget,
|
||||
setRequestData,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
selectedPanelType,
|
||||
}: DrilldownQueryProps): UseDrilldownReturn => {
|
||||
const isMounted = useRef(false);
|
||||
@@ -60,11 +60,11 @@ const useDrilldown = ({
|
||||
isMounted.current = true;
|
||||
}, [widget, enableDrillDown, compositeQuery, redirectWithQueryBuilderData]);
|
||||
|
||||
const dashboardEditView = selectedDashboard?.id
|
||||
const dashboardEditView = dashboardData?.id
|
||||
? generateExportToDashboardLink({
|
||||
query: currentQuery,
|
||||
panelType: selectedPanelType,
|
||||
dashboardId: selectedDashboard?.id || '',
|
||||
dashboardId: dashboardData?.id || '',
|
||||
widgetId: widget.id,
|
||||
})
|
||||
: '';
|
||||
|
||||
@@ -163,13 +163,13 @@ const mockProps: WidgetGraphComponentProps = {
|
||||
// Mock useDashabord hook
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): any => ({
|
||||
selectedDashboard: {
|
||||
dashboardData: {
|
||||
data: {
|
||||
variables: [],
|
||||
},
|
||||
},
|
||||
setLayouts: jest.fn(),
|
||||
setSelectedDashboard: jest.fn(),
|
||||
setDashboardData: jest.fn(),
|
||||
setColumnWidths: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -103,8 +103,8 @@ function WidgetGraphComponent({
|
||||
|
||||
const {
|
||||
setLayouts,
|
||||
selectedDashboard,
|
||||
setSelectedDashboard,
|
||||
dashboardData,
|
||||
setDashboardData,
|
||||
setColumnWidths,
|
||||
} = useDashboardStore();
|
||||
|
||||
@@ -125,33 +125,33 @@ function WidgetGraphComponent({
|
||||
const updateDashboardMutation = useUpdateDashboard();
|
||||
|
||||
const onDeleteHandler = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
|
||||
const updatedWidgets = dashboardData?.data?.widgets?.filter(
|
||||
(e) => e.id !== widget.id,
|
||||
);
|
||||
|
||||
const updatedLayout =
|
||||
selectedDashboard.data.layout?.filter((e) => e.i !== widget.id) || [];
|
||||
dashboardData.data.layout?.filter((e) => e.i !== widget.id) || [];
|
||||
|
||||
const updatedSelectedDashboard: Props = {
|
||||
const updatedDashboardData: Props = {
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
widgets: updatedWidgets,
|
||||
layout: updatedLayout,
|
||||
},
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
};
|
||||
|
||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||
updateDashboardMutation.mutateAsync(updatedDashboardData, {
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (setLayouts) {
|
||||
setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||
}
|
||||
if (setSelectedDashboard && updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
if (setDashboardData && updatedDashboard.data) {
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
setDeleteModal(false);
|
||||
},
|
||||
@@ -159,35 +159,35 @@ function WidgetGraphComponent({
|
||||
};
|
||||
|
||||
const onCloneHandler = async (): Promise<void> => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uuid = v4();
|
||||
|
||||
// this is added to make sure the cloned panel is of the same dimensions as the original one
|
||||
const originalPanelLayout = selectedDashboard.data.layout?.find(
|
||||
const originalPanelLayout = dashboardData.data.layout?.find(
|
||||
(l) => l.i === widget.id,
|
||||
);
|
||||
|
||||
const newLayoutItem = placeWidgetAtBottom(
|
||||
uuid,
|
||||
selectedDashboard?.data.layout || [],
|
||||
dashboardData?.data.layout || [],
|
||||
originalPanelLayout?.w || 6,
|
||||
originalPanelLayout?.h || 6,
|
||||
);
|
||||
|
||||
const layout = [...(selectedDashboard.data.layout || []), newLayoutItem];
|
||||
const layout = [...(dashboardData.data.layout || []), newLayoutItem];
|
||||
|
||||
updateDashboardMutation.mutateAsync(
|
||||
{
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
layout,
|
||||
widgets: [
|
||||
...(selectedDashboard.data.widgets || []),
|
||||
...(dashboardData.data.widgets || []),
|
||||
{
|
||||
...{
|
||||
...widget,
|
||||
@@ -202,8 +202,8 @@ function WidgetGraphComponent({
|
||||
if (setLayouts) {
|
||||
setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||
}
|
||||
if (setSelectedDashboard && updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
if (setDashboardData && updatedDashboard.data) {
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
notifications.success({
|
||||
message: 'Panel cloned successfully, redirecting to new copy.',
|
||||
|
||||
@@ -70,16 +70,16 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
useIsFetching([REACT_QUERY_KEY.DASHBOARD_BY_ID]) > 0;
|
||||
|
||||
const {
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
layouts,
|
||||
setLayouts,
|
||||
panelMap,
|
||||
setPanelMap,
|
||||
setSelectedDashboard,
|
||||
setDashboardData,
|
||||
columnWidths,
|
||||
} = useDashboardStore();
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
const { data } = selectedDashboard || {};
|
||||
const { data } = dashboardData || {};
|
||||
const { pathname } = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -124,7 +124,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
}
|
||||
|
||||
const userRole: ROLES | null =
|
||||
selectedDashboard?.createdBy === user?.email
|
||||
dashboardData?.createdBy === user?.email
|
||||
? (USER_ROLES.AUTHOR as ROLES)
|
||||
: user.role;
|
||||
|
||||
@@ -146,27 +146,27 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (!logEventCalledRef.current && !isUndefined(data)) {
|
||||
logEvent('Dashboard Detail: Opened', {
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardId: dashboardData?.id,
|
||||
dashboardName: data.title,
|
||||
numberOfPanels: data.widgets?.length,
|
||||
numberOfVariables: Object.keys(dashboardVariables).length || 0,
|
||||
});
|
||||
logEventCalledRef.current = true;
|
||||
}
|
||||
}, [dashboardVariables, data, selectedDashboard?.id]);
|
||||
}, [dashboardVariables, data, dashboardData?.id]);
|
||||
|
||||
const onSaveHandler = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedDashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
panelMap: { ...currentPanelMap },
|
||||
layout: dashboardLayout.filter((e) => e.i !== PANEL_TYPES.EMPTY_WIDGET),
|
||||
widgets: selectedDashboard?.data?.widgets?.map((widget) => {
|
||||
widgets: dashboardData?.data?.widgets?.map((widget) => {
|
||||
if (columnWidths?.[widget.id]) {
|
||||
return {
|
||||
...widget,
|
||||
@@ -184,7 +184,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
if (updatedDashboard.data.data.layout) {
|
||||
setLayouts(sortLayout(updatedDashboard.data.data.layout));
|
||||
}
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
setDashboardData(updatedDashboard.data);
|
||||
setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||
}
|
||||
},
|
||||
@@ -243,7 +243,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
dashboardLayout &&
|
||||
Array.isArray(dashboardLayout) &&
|
||||
dashboardLayout.length > 0 &&
|
||||
hasColumnWidthsChanged(columnWidths, selectedDashboard);
|
||||
hasColumnWidthsChanged(columnWidths, dashboardData);
|
||||
|
||||
if (shouldSaveLayout || shouldSaveColumnWidths) {
|
||||
onSaveHandler();
|
||||
@@ -253,7 +253,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
|
||||
const onSettingsModalSubmit = (): void => {
|
||||
const newTitle = form.getFieldValue('title');
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentWidget = selectedDashboard?.data?.widgets?.find(
|
||||
const currentWidget = dashboardData?.data?.widgets?.find(
|
||||
(e) => e.id === currentSelectRowId,
|
||||
);
|
||||
|
||||
@@ -269,25 +269,25 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedWidgets = selectedDashboard?.data?.widgets?.map((e) =>
|
||||
const updatedWidgets = dashboardData?.data?.widgets?.map((e) =>
|
||||
e.id === currentSelectRowId ? { ...e, title: newTitle } : e,
|
||||
);
|
||||
|
||||
const updatedSelectedDashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
const updatedDashboardData: Props = {
|
||||
id: dashboardData.id,
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
widgets: updatedWidgets,
|
||||
},
|
||||
};
|
||||
|
||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||
updateDashboardMutation.mutateAsync(updatedDashboardData, {
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (setLayouts) {
|
||||
setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||
}
|
||||
if (setSelectedDashboard && updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
if (setDashboardData && updatedDashboard.data) {
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
if (setPanelMap) {
|
||||
setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||
@@ -311,7 +311,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
}, [currentSelectRowId, form, widgets]);
|
||||
|
||||
const handleRowCollapse = (id: string): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
const { updatedLayout, updatedPanelMap } = applyRowCollapse(
|
||||
@@ -343,7 +343,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
};
|
||||
|
||||
const handleRowDelete = (): void => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -351,34 +351,33 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
|
||||
const updatedWidgets = dashboardData?.data?.widgets?.filter(
|
||||
(e) => e.id !== currentSelectRowId,
|
||||
);
|
||||
|
||||
const updatedLayout =
|
||||
selectedDashboard.data.layout?.filter((e) => e.i !== currentSelectRowId) ||
|
||||
[];
|
||||
dashboardData.data.layout?.filter((e) => e.i !== currentSelectRowId) || [];
|
||||
|
||||
const updatedPanelMap = { ...currentPanelMap };
|
||||
delete updatedPanelMap[currentSelectRowId];
|
||||
|
||||
const updatedSelectedDashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
const updatedDashboardData: Props = {
|
||||
id: dashboardData.id,
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
widgets: updatedWidgets,
|
||||
layout: updatedLayout,
|
||||
panelMap: updatedPanelMap,
|
||||
},
|
||||
};
|
||||
|
||||
updateDashboardMutation.mutateAsync(updatedSelectedDashboard, {
|
||||
updateDashboardMutation.mutateAsync(updatedDashboardData, {
|
||||
onSuccess: (updatedDashboard) => {
|
||||
if (setLayouts) {
|
||||
setLayouts(updatedDashboard.data?.data?.layout || []);
|
||||
}
|
||||
if (setSelectedDashboard && updatedDashboard.data) {
|
||||
setSelectedDashboard(updatedDashboard.data);
|
||||
if (setDashboardData && updatedDashboard.data) {
|
||||
setDashboardData(updatedDashboard.data);
|
||||
}
|
||||
if (setPanelMap) {
|
||||
setPanelMap(updatedDashboard.data?.data?.panelMap || {});
|
||||
@@ -390,10 +389,8 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
};
|
||||
const isDashboardEmpty = useMemo(
|
||||
() =>
|
||||
selectedDashboard?.data.layout
|
||||
? selectedDashboard?.data.layout?.length === 0
|
||||
: true,
|
||||
[selectedDashboard],
|
||||
dashboardData?.data.layout ? dashboardData?.data.layout?.length === 0 : true,
|
||||
[dashboardData],
|
||||
);
|
||||
|
||||
let isDataAvailableInAnyWidget = false;
|
||||
@@ -512,7 +509,7 @@ function GraphLayout(props: GraphLayoutProps): JSX.Element {
|
||||
widget={(currentWidget as Widgets) || ({ id, query: {} } as Widgets)}
|
||||
headerMenuList={widgetActions}
|
||||
variables={dashboardVariables}
|
||||
// version={selectedDashboard?.data?.version}
|
||||
// version={dashboardData?.data?.version}
|
||||
version={ENTITY_VERSION_V5}
|
||||
onDragSelect={onDragSelect}
|
||||
dataAvailable={checkIfDataExists}
|
||||
|
||||
@@ -42,14 +42,14 @@ export function WidgetRowHeader(props: WidgetRowHeaderProps): JSX.Element {
|
||||
(s) => s.setIsPanelTypeSelectionModalOpen,
|
||||
);
|
||||
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
|
||||
const permissions: ComponentTypes[] = ['add_panel'];
|
||||
const { user } = useAppContext();
|
||||
|
||||
const userRole: ROLES | null =
|
||||
selectedDashboard?.createdBy === user?.email
|
||||
dashboardData?.createdBy === user?.email
|
||||
? (USER_ROLES.AUTHOR as ROLES)
|
||||
: user.role;
|
||||
const [addPanelPermission] = useComponentPermission(permissions, userRole);
|
||||
@@ -87,11 +87,11 @@ export function WidgetRowHeader(props: WidgetRowHeaderProps): JSX.Element {
|
||||
icon={<Plus size={14} />}
|
||||
onClick={(): void => {
|
||||
// TODO: @AshwinBhatkal Simplify this check in cleanup of https://github.com/SigNoz/engineering-pod/issues/3953
|
||||
if (!selectedDashboard?.id) {
|
||||
if (!dashboardData?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedRowWidgetId(selectedDashboard.id, id);
|
||||
setSelectedRowWidgetId(dashboardData.id, id);
|
||||
setIsPanelTypeSelectionModalOpen(true);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -121,7 +121,7 @@ function useNavigateToExplorerPages(): (
|
||||
) => Promise<{
|
||||
[queryName: string]: { filters: TagFilterItem[]; dataSource?: string };
|
||||
}> {
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
return useCallback(
|
||||
@@ -143,7 +143,7 @@ function useNavigateToExplorerPages(): (
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[selectedDashboard, notifications],
|
||||
[dashboardData, notifications],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ interface UseUpdatedQueryOptions {
|
||||
panelTypes: PANEL_TYPES;
|
||||
timePreferance: timePreferenceType;
|
||||
};
|
||||
selectedDashboard?: any;
|
||||
dashboardData?: any;
|
||||
}
|
||||
|
||||
interface UseUpdatedQueryResult {
|
||||
@@ -44,7 +44,7 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
|
||||
const getUpdatedQuery = useCallback(
|
||||
async ({
|
||||
widgetConfig,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
}: UseUpdatedQueryOptions): Promise<Query> => {
|
||||
// Prepare query payload with resolved variables
|
||||
const { queryPayload } = prepareQueryRangePayloadV5({
|
||||
@@ -52,7 +52,7 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
|
||||
graphType: getGraphType(widgetConfig.panelTypes),
|
||||
selectedTime: widgetConfig.timePreferance,
|
||||
globalSelectedInterval,
|
||||
variables: getDashboardVariables(selectedDashboard?.data?.variables),
|
||||
variables: getDashboardVariables(dashboardData?.data?.variables),
|
||||
originalGraphType: widgetConfig.panelTypes,
|
||||
dynamicVariables: dashboardDynamicVariables,
|
||||
});
|
||||
|
||||
@@ -149,16 +149,16 @@ export function extractQueryNamesFromExpression(expression: string): string[] {
|
||||
|
||||
export const hasColumnWidthsChanged = (
|
||||
columnWidths: Record<string, Record<string, number>>,
|
||||
selectedDashboard?: Dashboard,
|
||||
dashboardData?: Dashboard,
|
||||
): boolean => {
|
||||
// If no column widths stored, no changes
|
||||
if (isEmpty(columnWidths) || !selectedDashboard) {
|
||||
if (isEmpty(columnWidths) || !dashboardData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each widget's column widths
|
||||
return Object.keys(columnWidths).some((widgetId) => {
|
||||
const dashboardWidget = selectedDashboard?.data?.widgets?.find(
|
||||
const dashboardWidget = dashboardData?.data?.widgets?.find(
|
||||
(widget) => widget.id === widgetId,
|
||||
) as Widgets;
|
||||
|
||||
|
||||
@@ -93,8 +93,8 @@ jest.mock('hooks/useDarkMode', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): { selectedDashboard: undefined } => ({
|
||||
selectedDashboard: undefined,
|
||||
useDashboardStore: (): { dashboardData: undefined } => ({
|
||||
dashboardData: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('LogsPanelComponent', () => {
|
||||
<PreferenceContextProvider>
|
||||
<NewWidget
|
||||
dashboardId=""
|
||||
selectedDashboard={undefined}
|
||||
dashboardData={undefined}
|
||||
selectedGraph={PANEL_TYPES.LIST}
|
||||
/>
|
||||
</PreferenceContextProvider>
|
||||
|
||||
@@ -30,7 +30,7 @@ function LeftContainer({
|
||||
setRequestData,
|
||||
setQueryResponse,
|
||||
enableDrillDown = false,
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
isNewPanel = false,
|
||||
}: WidgetGraphProps): JSX.Element {
|
||||
const { stagedQuery } = useQueryBuilder();
|
||||
@@ -79,8 +79,8 @@ function LeftContainer({
|
||||
isLoadingQueries={queryResponse.isFetching}
|
||||
selectedWidget={selectedWidget}
|
||||
dashboardVersion={ENTITY_VERSION_V5}
|
||||
dashboardId={selectedDashboard?.id}
|
||||
dashboardName={selectedDashboard?.data.title}
|
||||
dashboardId={dashboardData?.id}
|
||||
dashboardName={dashboardData?.data.title}
|
||||
isNewPanel={isNewPanel}
|
||||
/>
|
||||
{selectedGraph === PANEL_TYPES.LIST && (
|
||||
|
||||
@@ -326,7 +326,7 @@ describe('Stacking bar in new panel', () => {
|
||||
<PreferenceContextProvider>
|
||||
<NewWidget
|
||||
dashboardId=""
|
||||
selectedDashboard={undefined}
|
||||
dashboardData={undefined}
|
||||
selectedGraph={PANEL_TYPES.BAR}
|
||||
/>
|
||||
</PreferenceContextProvider>
|
||||
@@ -378,7 +378,7 @@ describe('when switching to BAR panel type', () => {
|
||||
<DashboardBootstrapWrapper dashboardId="">
|
||||
<NewWidget
|
||||
dashboardId=""
|
||||
selectedDashboard={undefined}
|
||||
dashboardData={undefined}
|
||||
selectedGraph={PANEL_TYPES.BAR}
|
||||
/>
|
||||
</DashboardBootstrapWrapper>,
|
||||
|
||||
@@ -86,7 +86,7 @@ import {
|
||||
import './NewWidget.styles.scss';
|
||||
|
||||
function NewWidget({
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
dashboardId,
|
||||
selectedGraph,
|
||||
enableDrillDown = false,
|
||||
@@ -135,7 +135,7 @@ function NewWidget({
|
||||
[selectedGraph, globalSelectedInterval, isLogsQuery],
|
||||
);
|
||||
|
||||
const { widgets = [] } = selectedDashboard?.data || {};
|
||||
const { widgets = [] } = dashboardData?.data || {};
|
||||
|
||||
const query = useUrlQuery();
|
||||
|
||||
@@ -154,9 +154,9 @@ function NewWidget({
|
||||
if (!logEventCalledRef.current) {
|
||||
logEvent('Panel Edit: Page visited', {
|
||||
panelType: selectedWidget?.panelTypes,
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardId: dashboardData?.id,
|
||||
widgetId: selectedWidget?.id,
|
||||
dashboardName: selectedDashboard?.data.title,
|
||||
dashboardName: dashboardData?.data.title,
|
||||
isNewPanel: !!isWidgetNotPresent,
|
||||
dataSource: currentQuery?.builder?.queryData?.[0]?.dataSource,
|
||||
});
|
||||
@@ -362,7 +362,7 @@ function NewWidget({
|
||||
const updateDashboardMutation = useUpdateDashboard();
|
||||
|
||||
const { afterWidgets, preWidgets } = useMemo(() => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return {
|
||||
selectedWidget: {} as Widgets,
|
||||
preWidgets: [],
|
||||
@@ -372,21 +372,18 @@ function NewWidget({
|
||||
|
||||
const widgetId = query.get('widgetId');
|
||||
|
||||
const selectedWidgetIndex = getSelectedWidgetIndex(
|
||||
selectedDashboard,
|
||||
widgetId,
|
||||
);
|
||||
const selectedWidgetIndex = getSelectedWidgetIndex(dashboardData, widgetId);
|
||||
|
||||
const preWidgets = getPreviousWidgets(selectedDashboard, selectedWidgetIndex);
|
||||
const preWidgets = getPreviousWidgets(dashboardData, selectedWidgetIndex);
|
||||
|
||||
const afterWidgets = getNextWidgets(selectedDashboard, selectedWidgetIndex);
|
||||
const afterWidgets = getNextWidgets(dashboardData, selectedWidgetIndex);
|
||||
|
||||
const selectedWidget = (selectedDashboard.data.widgets || [])[
|
||||
const selectedWidget = (dashboardData.data.widgets || [])[
|
||||
selectedWidgetIndex || 0
|
||||
];
|
||||
|
||||
return { selectedWidget, preWidgets, afterWidgets };
|
||||
}, [selectedDashboard, query]);
|
||||
}, [dashboardData, query]);
|
||||
|
||||
// this loading state is to take care of mismatch in the responses for table and other panels
|
||||
// hence while changing the query contains the older value and the processing logic fails
|
||||
@@ -483,12 +480,12 @@ function NewWidget({
|
||||
}, [dashboardId, query, safeNavigate]);
|
||||
|
||||
const onClickSaveHandler = useCallback(() => {
|
||||
if (!selectedDashboard) {
|
||||
if (!dashboardData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const widgetId = query.get('widgetId') || '';
|
||||
let updatedLayout = selectedDashboard.data.layout || [];
|
||||
let updatedLayout = dashboardData.data.layout || [];
|
||||
|
||||
const selectedRowWidgetId = getSelectedRowWidgetId(dashboardId);
|
||||
|
||||
@@ -522,10 +519,10 @@ function NewWidget({
|
||||
const adjustedQueryForV5 = adjustQueryForV5(currentQuery);
|
||||
|
||||
const dashboard: Props = {
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
|
||||
data: {
|
||||
...selectedDashboard.data,
|
||||
...dashboardData.data,
|
||||
widgets: isNewDashboard
|
||||
? [
|
||||
...afterWidgets,
|
||||
@@ -603,7 +600,7 @@ function NewWidget({
|
||||
},
|
||||
});
|
||||
}, [
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
query,
|
||||
isNewDashboard,
|
||||
afterWidgets,
|
||||
@@ -672,9 +669,9 @@ function NewWidget({
|
||||
const onSaveDashboard = useCallback((): void => {
|
||||
logEvent('Panel Edit: Save changes', {
|
||||
panelType: selectedWidget.panelTypes,
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardId: dashboardData?.id,
|
||||
widgetId: selectedWidget.id,
|
||||
dashboardName: selectedDashboard?.data.title,
|
||||
dashboardName: dashboardData?.data.title,
|
||||
queryType: currentQuery.queryType,
|
||||
isNewPanel,
|
||||
dataSource: currentQuery?.builder?.queryData?.[0]?.dataSource,
|
||||
@@ -869,7 +866,7 @@ function NewWidget({
|
||||
<OverlayScrollbar>
|
||||
{selectedWidget && (
|
||||
<LeftContainer
|
||||
selectedDashboard={selectedDashboard}
|
||||
dashboardData={dashboardData}
|
||||
selectedGraph={graphType}
|
||||
selectedLogFields={selectedLogFields}
|
||||
setSelectedLogFields={setSelectedLogFields}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { timePreferance } from './RightContainer/timeItems';
|
||||
|
||||
export interface NewWidgetProps {
|
||||
dashboardId: string;
|
||||
selectedDashboard: Dashboard | undefined;
|
||||
dashboardData: Dashboard | undefined;
|
||||
selectedGraph: PANEL_TYPES;
|
||||
enableDrillDown?: boolean;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ export interface WidgetGraphProps {
|
||||
>
|
||||
>;
|
||||
enableDrillDown?: boolean;
|
||||
selectedDashboard: Dashboard | undefined;
|
||||
dashboardData: Dashboard | undefined;
|
||||
isNewPanel?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ describe('InviteTeamMembers', () => {
|
||||
|
||||
describe('Validation callout on Complete', () => {
|
||||
it('shows the correct callout message for each combination of email/role validity', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0, delay: null });
|
||||
renderComponent();
|
||||
|
||||
const removeButtons = screen.getAllByRole('button', {
|
||||
@@ -302,10 +302,10 @@ describe('InviteTeamMembers', () => {
|
||||
screen.queryByText(/please enter valid emails and select roles/i),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
}, 15000);
|
||||
|
||||
it('treats whitespace as untouched, clears the callout on fix-and-resubmit, and clears role error on role select', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0, delay: null });
|
||||
renderComponent();
|
||||
|
||||
const removeButtons = screen.getAllByRole('button', {
|
||||
@@ -365,7 +365,7 @@ describe('InviteTeamMembers', () => {
|
||||
await waitFor(() => expect(mockOnNext).toHaveBeenCalledTimes(1), {
|
||||
timeout: 1200,
|
||||
});
|
||||
});
|
||||
}, 15000);
|
||||
|
||||
it('disables the Send Invites button when all rows are untouched (empty)', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
|
||||
@@ -46,18 +46,16 @@ describe('CreateEdit Modal', () => {
|
||||
// Tooltip mouseEnterDelay timers it triggers on the Configure button.
|
||||
fireEvent.click(configureButtons[0]);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/edit google authentication/i)).toBeInTheDocument();
|
||||
});
|
||||
expect(
|
||||
await screen.findByText(/edit google authentication/i),
|
||||
).toBeInTheDocument();
|
||||
|
||||
const backButton = screen.getByRole('button', { name: /back/i });
|
||||
fireEvent.click(backButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByText(/configure authentication method/i),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
expect(
|
||||
await screen.findByText(/configure authentication method/i),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ const useBaseAggregateOptions = ({
|
||||
getUpdatedQuery,
|
||||
isLoading: isResolveQueryLoading,
|
||||
} = useUpdatedQuery();
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (!aggregateData) {
|
||||
@@ -79,7 +79,7 @@ const useBaseAggregateOptions = ({
|
||||
panelTypes: panelType || PANEL_TYPES.TIME_SERIES,
|
||||
timePreferance: 'GLOBAL_TIME',
|
||||
},
|
||||
selectedDashboard,
|
||||
dashboardData,
|
||||
});
|
||||
setResolvedQuery(updatedQuery);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ jest.mock('react-router-dom', () => ({
|
||||
// Mock useDashabord hook
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): any => ({
|
||||
selectedDashboard: {
|
||||
dashboardData: {
|
||||
data: {
|
||||
variables: [],
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@ export function useDashboardBootstrap(
|
||||
);
|
||||
|
||||
const {
|
||||
setSelectedDashboard,
|
||||
setDashboardData,
|
||||
setLayouts,
|
||||
setPanelMap,
|
||||
resetDashboardStore,
|
||||
@@ -65,7 +65,7 @@ export function useDashboardBootstrap(
|
||||
transformDashboardVariables,
|
||||
} = useTransformDashboardVariables(dashboardId);
|
||||
|
||||
// Keep the external variables store in sync with selectedDashboard
|
||||
// Keep the external variables store in sync with dashboardData
|
||||
useDashboardVariablesSync(dashboardId);
|
||||
|
||||
const dashboardQuery = useDashboardQuery(dashboardId);
|
||||
@@ -88,7 +88,7 @@ export function useDashboardBootstrap(
|
||||
if (variables) {
|
||||
initializeDefaultVariables(variables, getUrlVariables, updateUrlVariable);
|
||||
}
|
||||
setSelectedDashboard(updatedDashboardData);
|
||||
setDashboardData(updatedDashboardData);
|
||||
dashboardRef.current = updatedDashboardData;
|
||||
setLayouts(sortLayout(getUpdatedLayout(updatedDashboardData?.data.layout)));
|
||||
setPanelMap(defaultTo(updatedDashboardData?.data?.panelMap, {}));
|
||||
@@ -107,7 +107,7 @@ export function useDashboardBootstrap(
|
||||
title: t('dashboard_has_been_updated'),
|
||||
content: t('do_you_want_to_refresh_the_dashboard'),
|
||||
onOk() {
|
||||
setSelectedDashboard(updatedDashboardData);
|
||||
setDashboardData(updatedDashboardData);
|
||||
|
||||
const { maxTime, minTime } = getMinMaxForSelectedTime(
|
||||
globalTime.selectedTime,
|
||||
|
||||
@@ -13,21 +13,21 @@ import { useDashboardVariablesSelector } from './useDashboardVariables';
|
||||
|
||||
/**
|
||||
* Keeps the external variables store in sync with the zustand dashboard store.
|
||||
* When selectedDashboard changes, propagates variable updates to the variables store.
|
||||
* When dashboardData changes, propagates variable updates to the variables store.
|
||||
*/
|
||||
export function useDashboardVariablesSync(dashboardId: string): void {
|
||||
const dashboardVariables = useDashboardVariablesSelector((s) => s.variables);
|
||||
const savedDashboardId = useDashboardVariablesSelector((s) => s.dashboardId);
|
||||
const selectedDashboard = useDashboardStore(
|
||||
(s: DashboardStore) => s.selectedDashboard,
|
||||
const dashboardData = useDashboardStore(
|
||||
(s: DashboardStore) => s.dashboardData,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const updatedVariables = selectedDashboard?.data.variables || {};
|
||||
const updatedVariables = dashboardData?.data.variables || {};
|
||||
if (savedDashboardId !== dashboardId) {
|
||||
setDashboardVariablesStore({ dashboardId, variables: updatedVariables });
|
||||
} else if (!isEqual(dashboardVariables, updatedVariables)) {
|
||||
updateDashboardVariablesStore({ dashboardId, variables: updatedVariables });
|
||||
}
|
||||
}, [selectedDashboard]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [dashboardData]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMutation } from 'react-query';
|
||||
import locked from 'api/v1/dashboards/id/lock';
|
||||
import {
|
||||
getSelectedDashboard,
|
||||
getDashboardData,
|
||||
useDashboardStore,
|
||||
} from 'providers/Dashboard/store/useDashboardStore';
|
||||
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
@@ -13,13 +13,11 @@ import APIError from 'types/api/error';
|
||||
*/
|
||||
export function useLockDashboard(): (value: boolean) => Promise<void> {
|
||||
const { showErrorModal } = useErrorModal();
|
||||
const { setSelectedDashboard } = useDashboardStore();
|
||||
const { setDashboardData } = useDashboardStore();
|
||||
|
||||
const { mutate: lockDashboard } = useMutation(locked, {
|
||||
onSuccess: (_, props) => {
|
||||
setSelectedDashboard((prev) =>
|
||||
prev ? { ...prev, locked: props.lock } : prev,
|
||||
);
|
||||
setDashboardData((prev) => (prev ? { ...prev, locked: props.lock } : prev));
|
||||
},
|
||||
onError: (error) => {
|
||||
showErrorModal(error as APIError);
|
||||
@@ -27,11 +25,11 @@ export function useLockDashboard(): (value: boolean) => Promise<void> {
|
||||
});
|
||||
|
||||
return async (value: boolean): Promise<void> => {
|
||||
const selectedDashboard = getSelectedDashboard();
|
||||
if (selectedDashboard) {
|
||||
const dashboardData = getDashboardData();
|
||||
if (dashboardData) {
|
||||
try {
|
||||
await lockDashboard({
|
||||
id: selectedDashboard.id,
|
||||
id: dashboardData.id,
|
||||
lock: value,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -12,11 +12,11 @@ import { useDashboardVariablesByType } from './useDashboardVariablesByType';
|
||||
*/
|
||||
export function useWidgetsByDynamicVariableId(): Record<string, string[]> {
|
||||
const dynamicVariables = useDashboardVariablesByType('DYNAMIC', 'values');
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
|
||||
return useMemo(() => {
|
||||
const widgets =
|
||||
selectedDashboard?.data?.widgets?.filter(
|
||||
dashboardData?.data?.widgets?.filter(
|
||||
(widget) => widget.panelTypes !== PANEL_GROUP_TYPES.ROW,
|
||||
) || [];
|
||||
|
||||
@@ -24,5 +24,5 @@ export function useWidgetsByDynamicVariableId(): Record<string, string[]> {
|
||||
dynamicVariables,
|
||||
widgets as Widgets[],
|
||||
);
|
||||
}, [selectedDashboard, dynamicVariables]);
|
||||
}, [dashboardData, dynamicVariables]);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ jest.mock('lib/dashboardVariables/getDashboardVariables', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): unknown => ({ selectedDashboard: undefined }),
|
||||
useDashboardStore: (): unknown => ({ dashboardData: undefined }),
|
||||
}));
|
||||
|
||||
jest.mock('utils/getGraphType', () => ({
|
||||
|
||||
@@ -33,7 +33,7 @@ const useCreateAlerts = (widget?: Widgets, caller?: string): VoidFunction => {
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
const dashboardDynamicVariables = useDashboardVariablesByType(
|
||||
@@ -49,8 +49,8 @@ const useCreateAlerts = (widget?: Widgets, caller?: string): VoidFunction => {
|
||||
if (caller === 'panelView') {
|
||||
logEvent('Panel Edit: Create alert', {
|
||||
panelType: widget.panelTypes,
|
||||
dashboardName: selectedDashboard?.data?.title,
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardName: dashboardData?.data?.title,
|
||||
dashboardId: dashboardData?.id,
|
||||
widgetId: widget.id,
|
||||
queryType: widget.query.queryType,
|
||||
});
|
||||
@@ -58,8 +58,8 @@ const useCreateAlerts = (widget?: Widgets, caller?: string): VoidFunction => {
|
||||
logEvent('Dashboard Detail: Panel action', {
|
||||
action: MenuItemKeys.CreateAlerts,
|
||||
panelType: widget.panelTypes,
|
||||
dashboardName: selectedDashboard?.data?.title,
|
||||
dashboardId: selectedDashboard?.id,
|
||||
dashboardName: dashboardData?.data?.title,
|
||||
dashboardId: dashboardData?.id,
|
||||
widgetId: widget.id,
|
||||
queryType: widget.query.queryType,
|
||||
});
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
|
||||
.legend-marker {
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
min-width: 11px;
|
||||
min-height: 11px;
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
// horizontal offset when the scroller has padding or transform applied.
|
||||
div[data-viewport-type='element'] {
|
||||
left: 0;
|
||||
padding: 4px 8px 4px 16px;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 12px 4px 16px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
|
||||
@@ -21,9 +21,7 @@ function DashboardPage(): JSX.Element {
|
||||
error,
|
||||
} = useDashboardBootstrap(dashboardId, { confirm: onModal.confirm });
|
||||
|
||||
const dashboardTitle = useDashboardStore(
|
||||
(s) => s.selectedDashboard?.data.title,
|
||||
);
|
||||
const dashboardTitle = useDashboardStore((s) => s.dashboardData?.data.title);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = dashboardTitle || document.title;
|
||||
|
||||
@@ -62,9 +62,9 @@ function DashboardWidgetInternal({
|
||||
widgetId: string;
|
||||
graphType: PANEL_TYPES;
|
||||
}): JSX.Element | null {
|
||||
const [selectedDashboard, setSelectedDashboard] = useState<
|
||||
Dashboard | undefined
|
||||
>(undefined);
|
||||
const [dashboardData, setDashboardData] = useState<Dashboard | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
const { transformDashboardVariables } = useTransformDashboardVariables(
|
||||
dashboardId,
|
||||
@@ -83,7 +83,7 @@ function DashboardWidgetInternal({
|
||||
cacheTime: DASHBOARD_CACHE_TIME,
|
||||
onSuccess: (response) => {
|
||||
const updatedDashboardData = transformDashboardVariables(response.data);
|
||||
setSelectedDashboard(updatedDashboardData);
|
||||
setDashboardData(updatedDashboardData);
|
||||
setDashboardVariablesStore({
|
||||
dashboardId,
|
||||
variables: updatedDashboardData.data.variables,
|
||||
@@ -108,7 +108,7 @@ function DashboardWidgetInternal({
|
||||
dashboardId={dashboardId}
|
||||
selectedGraph={graphType}
|
||||
enableDrillDown={isDrilldownEnabled()}
|
||||
selectedDashboard={selectedDashboard}
|
||||
dashboardData={dashboardData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -699,17 +699,17 @@ describe('TracesExplorer - ', () => {
|
||||
});
|
||||
|
||||
it('select a view options - assert and save this view', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const { container } = renderWithTracesExplorerRouter(<TracesExplorer />, [
|
||||
'/traces-explorer/?panelType=list&selectedExplorerView=list',
|
||||
]);
|
||||
|
||||
const viewSearchInput = container.querySelector(
|
||||
'.view-options .ant-select-selection-search-input',
|
||||
) as HTMLElement;
|
||||
|
||||
expect(viewSearchInput).toBeInTheDocument();
|
||||
const viewSearchInput = await waitFor(() => {
|
||||
const el = container.querySelector(
|
||||
'.view-options .ant-select-selection-search-input',
|
||||
) as HTMLElement;
|
||||
expect(el).toBeInTheDocument();
|
||||
return el;
|
||||
});
|
||||
|
||||
fireEvent.mouseDown(viewSearchInput);
|
||||
|
||||
@@ -718,17 +718,18 @@ describe('TracesExplorer - ', () => {
|
||||
).toBeInTheDocument();
|
||||
|
||||
// save this view
|
||||
fireEvent.click(screen.getByText('Save this view'));
|
||||
fireEvent.click(await screen.findByText('Save this view'));
|
||||
|
||||
const saveViewModalInput = await screen.findByPlaceholderText(
|
||||
'e.g. External http method view',
|
||||
);
|
||||
expect(saveViewModalInput).toBeInTheDocument();
|
||||
|
||||
const saveViewModal = document.querySelector(
|
||||
'.ant-modal-content',
|
||||
) as HTMLElement;
|
||||
expect(saveViewModal).toBeInTheDocument();
|
||||
const saveViewModal = await waitFor(() => {
|
||||
const el = document.querySelector('.ant-modal-content') as HTMLElement;
|
||||
expect(el).toBeInTheDocument();
|
||||
return el;
|
||||
});
|
||||
|
||||
await act(async () =>
|
||||
fireEvent.change(saveViewModalInput, { target: { value: 'test view' } }),
|
||||
@@ -739,18 +740,19 @@ describe('TracesExplorer - ', () => {
|
||||
fireEvent.click(within(saveViewModal).getByTestId('save-view-btn'));
|
||||
});
|
||||
|
||||
expect(successNotification).toHaveBeenCalledWith({
|
||||
message: 'View Saved Successfully',
|
||||
await waitFor(() => {
|
||||
expect(successNotification).toHaveBeenCalledWith({
|
||||
message: 'View Saved Successfully',
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 15000);
|
||||
|
||||
it('create a dashboard btn assert', async () => {
|
||||
const { getByText } = renderWithTracesExplorerRouter(<TracesExplorer />, [
|
||||
renderWithTracesExplorerRouter(<TracesExplorer />, [
|
||||
'/traces-explorer/?panelType=list&selectedExplorerView=list',
|
||||
]);
|
||||
await screen.findByText(FILTER_SERVICE_NAME);
|
||||
|
||||
const createDashboardBtn = getByText('Add to Dashboard');
|
||||
const createDashboardBtn = await screen.findByText('Add to Dashboard');
|
||||
expect(createDashboardBtn).toBeInTheDocument();
|
||||
fireEvent.click(createDashboardBtn);
|
||||
|
||||
@@ -771,12 +773,11 @@ describe('TracesExplorer - ', () => {
|
||||
});
|
||||
|
||||
it('create an alert btn assert', async () => {
|
||||
const { getByText } = renderWithTracesExplorerRouter(<TracesExplorer />, [
|
||||
renderWithTracesExplorerRouter(<TracesExplorer />, [
|
||||
'/traces-explorer/?panelType=list&selectedExplorerView=list',
|
||||
]);
|
||||
await screen.findByText(FILTER_SERVICE_NAME);
|
||||
|
||||
const createAlertBtn = getByText('Create an Alert');
|
||||
const createAlertBtn = await screen.findByText('Create an Alert');
|
||||
expect(createAlertBtn).toBeInTheDocument();
|
||||
fireEvent.click(createAlertBtn);
|
||||
|
||||
|
||||
@@ -69,17 +69,17 @@ jest.mock('react-redux', () => ({
|
||||
jest.mock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') }));
|
||||
|
||||
function TestComponent(): JSX.Element {
|
||||
const { selectedDashboard } = useDashboardStore();
|
||||
const { dashboardData } = useDashboardStore();
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="dashboard-id">{selectedDashboard?.id}</div>
|
||||
<div data-testid="dashboard-id">{dashboardData?.id}</div>
|
||||
<div data-testid="dashboard-variables">
|
||||
{dashboardVariables ? JSON.stringify(dashboardVariables) : 'null'}
|
||||
</div>
|
||||
<div data-testid="dashboard-data">
|
||||
{selectedDashboard?.data?.title || 'No Title'}
|
||||
{dashboardData?.data?.title || 'No Title'}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -9,8 +9,8 @@ export type WidgetColumnWidths = {
|
||||
|
||||
export interface DashboardUISlice {
|
||||
//
|
||||
selectedDashboard: Dashboard | undefined;
|
||||
setSelectedDashboard: (
|
||||
dashboardData: Dashboard | undefined;
|
||||
setDashboardData: (
|
||||
updater:
|
||||
| Dashboard
|
||||
| undefined
|
||||
@@ -26,7 +26,7 @@ export interface DashboardUISlice {
|
||||
}
|
||||
|
||||
export const initialDashboardUIState = {
|
||||
selectedDashboard: undefined as Dashboard | undefined,
|
||||
dashboardData: undefined as Dashboard | undefined,
|
||||
columnWidths: {} as WidgetColumnWidths,
|
||||
};
|
||||
|
||||
@@ -38,10 +38,10 @@ export const createDashboardUISlice: StateCreator<
|
||||
> = (set) => ({
|
||||
...initialDashboardUIState,
|
||||
|
||||
setSelectedDashboard: (updater): void =>
|
||||
setDashboardData: (updater): void =>
|
||||
set((state: DashboardUISlice): void => {
|
||||
state.selectedDashboard =
|
||||
typeof updater === 'function' ? updater(state.selectedDashboard) : updater;
|
||||
state.dashboardData =
|
||||
typeof updater === 'function' ? updater(state.dashboardData) : updater;
|
||||
}),
|
||||
|
||||
setColumnWidths: (updater): void =>
|
||||
|
||||
@@ -25,7 +25,7 @@ export type DashboardStore = DashboardUISlice &
|
||||
* In this case, we are selecting the locked state of the selected dashboard.
|
||||
* */
|
||||
export const selectIsDashboardLocked = (s: DashboardStore): boolean =>
|
||||
s.selectedDashboard?.locked ?? false;
|
||||
s.dashboardData?.locked ?? false;
|
||||
|
||||
export const useDashboardStore = create<DashboardStore>()(
|
||||
immer((set, get, api) => ({
|
||||
@@ -40,8 +40,8 @@ export const useDashboardStore = create<DashboardStore>()(
|
||||
);
|
||||
|
||||
// Standalone imperative accessors — use these instead of calling useDashboardStore.getState() at call sites.
|
||||
export const getSelectedDashboard = (): Dashboard | undefined =>
|
||||
useDashboardStore.getState().selectedDashboard;
|
||||
export const getDashboardData = (): Dashboard | undefined =>
|
||||
useDashboardStore.getState().dashboardData;
|
||||
|
||||
export const getDashboardLayouts = (): Layout[] =>
|
||||
useDashboardStore.getState().layouts;
|
||||
|
||||
@@ -2,28 +2,28 @@ import { Layout } from 'react-grid-layout';
|
||||
import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
|
||||
|
||||
export const getPreviousWidgets = (
|
||||
selectedDashboard: Dashboard,
|
||||
dashboardData: Dashboard,
|
||||
selectedWidgetIndex: number,
|
||||
): Widgets[] =>
|
||||
(selectedDashboard.data.widgets?.slice(
|
||||
(dashboardData.data.widgets?.slice(
|
||||
0,
|
||||
selectedWidgetIndex || 0,
|
||||
) as Widgets[]) || [];
|
||||
|
||||
export const getNextWidgets = (
|
||||
selectedDashboard: Dashboard,
|
||||
dashboardData: Dashboard,
|
||||
selectedWidgetIndex: number,
|
||||
): Widgets[] =>
|
||||
(selectedDashboard.data.widgets?.slice(
|
||||
(dashboardData.data.widgets?.slice(
|
||||
(selectedWidgetIndex || 0) + 1, // this is never undefined
|
||||
selectedDashboard.data.widgets?.length,
|
||||
dashboardData.data.widgets?.length,
|
||||
) as Widgets[]) || [];
|
||||
|
||||
export const getSelectedWidgetIndex = (
|
||||
selectedDashboard: Dashboard,
|
||||
dashboardData: Dashboard,
|
||||
widgetId: string | null,
|
||||
): number =>
|
||||
selectedDashboard.data.widgets?.findIndex((e) => e.id === widgetId) || 0;
|
||||
dashboardData.data.widgets?.findIndex((e) => e.id === widgetId) || 0;
|
||||
|
||||
export const sortLayout = (layout: Layout[]): Layout[] =>
|
||||
[...layout].sort((a, b) => {
|
||||
|
||||
Reference in New Issue
Block a user