diff --git a/pkg/services/publicdashboards/database/database.go b/pkg/services/publicdashboards/database/database.go index bb99e1a7331..a76bca44ccb 100644 --- a/pkg/services/publicdashboards/database/database.go +++ b/pkg/services/publicdashboards/database/database.go @@ -163,10 +163,13 @@ func (d *PublicDashboardStoreImpl) FindByDashboardUid(ctx context.Context, orgId pdRes := &PublicDashboard{OrgId: orgId, DashboardUid: dashboardUid} err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error { // publicDashboard - _, err := sess.Get(pdRes) + exists, err := sess.Get(pdRes) if err != nil { return err } + if !exists { + return ErrPublicDashboardNotFound + } return nil }) diff --git a/pkg/services/publicdashboards/database/database_test.go b/pkg/services/publicdashboards/database/database_test.go index 8f8e9c41855..df5a8462dae 100644 --- a/pkg/services/publicdashboards/database/database_test.go +++ b/pkg/services/publicdashboards/database/database_test.go @@ -300,9 +300,10 @@ func TestIntegrationFindByDashboardUid(t *testing.T) { t.Run("returns isPublic and set dashboardUid and orgId", func(t *testing.T) { setup() + savedPubdash := insertPublicDashboard(t, publicdashboardStore, savedDashboard.Uid, savedDashboard.OrgId, false) pubdash, err := publicdashboardStore.FindByDashboardUid(context.Background(), savedDashboard.OrgId, savedDashboard.Uid) require.NoError(t, err) - assert.Equal(t, &PublicDashboard{IsEnabled: false, DashboardUid: savedDashboard.Uid, OrgId: savedDashboard.OrgId}, pubdash) + assert.Equal(t, savedPubdash, pubdash) }) t.Run("returns dashboard errDashboardIdentifierNotSet", func(t *testing.T) { @@ -335,6 +336,14 @@ func TestIntegrationFindByDashboardUid(t *testing.T) { assert.True(t, assert.ObjectsAreEqualValues(&cmd.PublicDashboard, pubdash)) }) + + t.Run("returns error when public dashboard doesn't exist", func(t *testing.T) { + setup() + pubdash, err := publicdashboardStore.FindByDashboardUid(context.Background(), 9, "fake-dashboard-uid") + require.Error(t, err) + require.Nil(t, pubdash) + assert.Equal(t, ErrPublicDashboardNotFound, err) + }) } func TestIntegrationSavePublicDashboard(t *testing.T) { @@ -351,6 +360,7 @@ func TestIntegrationSavePublicDashboard(t *testing.T) { publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) savedDashboard2 = insertTestDashboard(t, dashboardStore, "testDashie2", 1, 0, true) + insertPublicDashboard(t, publicdashboardStore, savedDashboard2.Uid, savedDashboard2.OrgId, false) } t.Run("saves new public dashboard", func(t *testing.T) { diff --git a/public/app/features/dashboard/api/publicDashboardApi.ts b/public/app/features/dashboard/api/publicDashboardApi.ts index c61ccdf7695..63c8da66ce6 100644 --- a/public/app/features/dashboard/api/publicDashboardApi.ts +++ b/public/app/features/dashboard/api/publicDashboardApi.ts @@ -3,23 +3,34 @@ import { lastValueFrom } from 'rxjs'; import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime/src'; import { notifyApp } from 'app/core/actions'; -import { createSuccessNotification } from 'app/core/copy/appNotification'; +import { createErrorNotification, createSuccessNotification } from 'app/core/copy/appNotification'; import { PublicDashboard } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; import { DashboardModel } from 'app/features/dashboard/state'; +type ReqOptions = { + manageError?: (err: unknown) => { error: unknown }; + showErrorAlert?: boolean; +}; + const backendSrvBaseQuery = - ({ baseUrl }: { baseUrl: string } = { baseUrl: '' }): BaseQueryFn => + ({ baseUrl }: { baseUrl: string }): BaseQueryFn => async (requestOptions) => { try { const { data: responseData, ...meta } = await lastValueFrom( - getBackendSrv().fetch({ ...requestOptions, url: baseUrl + requestOptions.url }) + getBackendSrv().fetch({ + ...requestOptions, + url: baseUrl + requestOptions.url, + showErrorAlert: requestOptions.showErrorAlert, + }) ); return { data: responseData, meta }; } catch (error) { - return { error }; + return requestOptions.manageError ? requestOptions.manageError(error) : { error }; } }; +const getConfigError = (err: { status: number }) => ({ error: err.status !== 404 ? err : null }); + export const publicDashboardApi = createApi({ reducerPath: 'publicDashboardApi', baseQuery: retry(backendSrvBaseQuery({ baseUrl: '/api/dashboards' }), { maxRetries: 3 }), @@ -29,7 +40,18 @@ export const publicDashboardApi = createApi({ getConfig: builder.query({ query: (dashboardUid) => ({ url: `/uid/${dashboardUid}/public-config`, + manageError: getConfigError, + showErrorAlert: false, }), + async onQueryStarted(_, { dispatch, queryFulfilled }) { + try { + await queryFulfilled; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + const customError = e as { error: { data: { message: string } } }; + dispatch(notifyApp(createErrorNotification(customError?.error?.data?.message))); + } + }, providesTags: ['Config'], }), saveConfig: builder.mutation({