Skip to content

Commit 7be21a4

Browse files
committed
fix: show single no-access alert instead of one per section in app details
1 parent 76d1faa commit 7be21a4

4 files changed

Lines changed: 108 additions & 45 deletions

File tree

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StudioHeading } from '@studio/components';
1+
import { StudioAlert, StudioHeading } from '@studio/components';
22
import { AppMetrics } from './components/AppMetrics';
33
import { useQueryParamState } from 'admin/features/apps/hooks/useQueryParamState';
44
import classes from './AppDetails.module.css';
@@ -7,8 +7,14 @@ import { AppInfo } from './components/AppInfo';
77
import { Breadcrumbs } from 'admin/features/apps/components/Breadcrumbs/Breadcrumbs';
88
import { DEFAULT_SEARCH_PARAMS } from 'admin/constants/constants';
99
import { useRequiredRoutePathsParams } from 'admin/hooks/useRequiredRoutePathsParams';
10+
import { useAppHealthMetricsQuery } from 'admin/features/apps/hooks/queries/useAppHealthMetricsQuery';
11+
import { isAxiosError } from 'axios';
12+
import { useCurrentOrg } from 'admin/contexts/OrgContext';
13+
import { useEnvironmentTitle } from 'admin/features/apps/hooks/useEnvironmentTitle';
14+
import { useTranslation } from 'react-i18next';
1015

1116
export const AppsDetails = () => {
17+
const { t } = useTranslation();
1218
const {
1319
owner: org,
1420
environment,
@@ -17,6 +23,15 @@ export const AppsDetails = () => {
1723
const defaultRange = DEFAULT_SEARCH_PARAMS.range;
1824
const [range, setRange] = useQueryParamState<number>('range', defaultRange);
1925

26+
const currentOrg = useCurrentOrg();
27+
const orgName = currentOrg.full_name || currentOrg.username;
28+
const envTitle = useEnvironmentTitle(environment);
29+
30+
const { isError: healthIsError, error: healthError } = useAppHealthMetricsQuery(org, environment, app, {
31+
hideDefaultError: true,
32+
});
33+
const hasNoAccess = healthIsError && isAxiosError(healthError) && healthError.response?.status === 403;
34+
2035
return (
2136
<div className={classes.container}>
2237
<Breadcrumbs
@@ -28,12 +43,20 @@ export const AppsDetails = () => {
2843
/>
2944
<StudioHeading data-size='lg'>{app}</StudioHeading>
3045
<AppInfo org={org} environment={environment} app={app} />
31-
<div className={classes.metrics}>
32-
<AppMetrics range={range ?? defaultRange} setRange={setRange} />
33-
</div>
34-
<div>
35-
<Instances />
36-
</div>
46+
{hasNoAccess ? (
47+
<StudioAlert data-color='info'>
48+
{t('admin.app.missing_rights', { envTitle, orgName })}
49+
</StudioAlert>
50+
) : (
51+
<>
52+
<div className={classes.metrics}>
53+
<AppMetrics range={range ?? defaultRange} setRange={setRange} />
54+
</div>
55+
<div>
56+
<Instances />
57+
</div>
58+
</>
59+
)}
3760
</div>
3861
);
3962
};

src/Designer/frontend/admin/features/apps/pages/appDetails/components/AppMetrics.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,17 @@ export const AppMetrics = ({ range, setRange }: AppMetricsProps) => {
163163
));
164164
};
165165

166+
const allMissingRights =
167+
appHealthMetricsIsError &&
168+
isAxiosError(appHealthMetricsError) &&
169+
appHealthMetricsError.response?.status === 403 &&
170+
appErrorMetricsIsError &&
171+
isAxiosError(appErrorMetricsError) &&
172+
appErrorMetricsError.response?.status === 403 &&
173+
appMetricsIsError &&
174+
isAxiosError(appMetricsError) &&
175+
appMetricsError.response?.status === 403;
176+
166177
return (
167178
<StudioCard data-color='neutral' className={classes.container}>
168179
<StudioHeading className={classes.heading} data-size='sm'>
@@ -173,9 +184,17 @@ export const AppMetrics = ({ range, setRange }: AppMetricsProps) => {
173184
/>
174185
</StudioHeading>
175186
<div className={classes.content}>
176-
{renderAppHealthMetrics()}
177-
{renderAppErrorMetrics()}
178-
{renderAppMetrics()}
187+
{allMissingRights ? (
188+
<StudioAlert data-color='info' className={classes.metric}>
189+
{t('admin.metrics.missing_rights', { envTitle, orgName })}
190+
</StudioAlert>
191+
) : (
192+
<>
193+
{renderAppHealthMetrics()}
194+
{renderAppErrorMetrics()}
195+
{renderAppMetrics()}
196+
</>
197+
)}
179198
</div>
180199
</StudioCard>
181200
);

src/Designer/frontend/admin/features/apps/pages/instances/Instances.tsx

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { useQueryParamState } from 'admin/features/apps/hooks/useQueryParamState
77
import { ProcessTaskFilter } from './components/ProcessTaskFilter';
88
import { useTranslation } from 'react-i18next';
99
import { useRequiredRoutePathsParams } from 'admin/hooks/useRequiredRoutePathsParams';
10+
import { useAppInstancesQuery } from 'admin/features/apps/hooks/queries/useAppInstancesQuery';
11+
import { isAxiosError } from 'axios';
1012

1113
const YES_NO_ALL_OPTIONS = [
1214
{ label: 'admin.instances.filter.all', value: undefined },
@@ -52,45 +54,62 @@ export const Instances = () => {
5254
undefined,
5355
);
5456

57+
const createdBefore = getCurrentDateOnlyStringMinusDays(createdBeforeDays);
58+
const { error: instancesError } = useAppInstancesQuery(
59+
org,
60+
environment,
61+
app,
62+
currentTask,
63+
isArchived,
64+
archiveReference,
65+
isConfirmed,
66+
isSoftDeleted,
67+
undefined,
68+
createdBefore,
69+
);
70+
const hasNoAccess = isAxiosError(instancesError) && instancesError.response?.status === 403;
71+
5572
return (
5673
<StudioCard>
5774
<StudioHeading className={classes.heading} data-size='sm'>
5875
{t('admin.instances.title')}
5976
</StudioHeading>
60-
<div className={classes.filterWrapper}>
61-
<ArchiveReferenceSearch value={archiveReference} setValue={setArchiveReference} />
62-
<ProcessTaskFilter
63-
org={org}
64-
environment={environment}
65-
app={app}
66-
value={currentTask}
67-
setValue={setCurrentTask}
68-
/>
69-
<StatusFilter
70-
label='admin.instances.status.completed'
71-
value={isArchived}
72-
setValue={setIsArchived}
73-
options={YES_NO_ALL_OPTIONS}
74-
/>
75-
<StatusFilter
76-
label='admin.instances.status.confirmed'
77-
value={isConfirmed}
78-
setValue={setIsConfirmed}
79-
options={YES_NO_ALL_OPTIONS}
80-
/>
81-
<StatusFilter
82-
label='admin.instances.status.deleted'
83-
value={isSoftDeleted}
84-
setValue={setIsSoftDeleted}
85-
options={YES_NO_ALL_OPTIONS}
86-
/>
87-
<StatusFilter
88-
label='admin.instances.created_before'
89-
value={createdBeforeDays}
90-
setValue={setCreatedBeforeDays}
91-
options={CREATED_BEFORE_OPTIONS}
92-
/>
93-
</div>
77+
{!hasNoAccess && (
78+
<div className={classes.filterWrapper}>
79+
<ArchiveReferenceSearch value={archiveReference} setValue={setArchiveReference} />
80+
<ProcessTaskFilter
81+
org={org}
82+
environment={environment}
83+
app={app}
84+
value={currentTask}
85+
setValue={setCurrentTask}
86+
/>
87+
<StatusFilter
88+
label='admin.instances.status.completed'
89+
value={isArchived}
90+
setValue={setIsArchived}
91+
options={YES_NO_ALL_OPTIONS}
92+
/>
93+
<StatusFilter
94+
label='admin.instances.status.confirmed'
95+
value={isConfirmed}
96+
setValue={setIsConfirmed}
97+
options={YES_NO_ALL_OPTIONS}
98+
/>
99+
<StatusFilter
100+
label='admin.instances.status.deleted'
101+
value={isSoftDeleted}
102+
setValue={setIsSoftDeleted}
103+
options={YES_NO_ALL_OPTIONS}
104+
/>
105+
<StatusFilter
106+
label='admin.instances.created_before'
107+
value={createdBeforeDays}
108+
setValue={setCreatedBeforeDays}
109+
options={CREATED_BEFORE_OPTIONS}
110+
/>
111+
</div>
112+
)}
94113
<InstancesTable
95114
org={org}
96115
environment={environment}
@@ -100,7 +119,7 @@ export const Instances = () => {
100119
archiveReference={archiveReference}
101120
confirmed={isConfirmed}
102121
isSoftDeleted={isSoftDeleted}
103-
createdBefore={getCurrentDateOnlyStringMinusDays(createdBeforeDays)}
122+
createdBefore={createdBefore}
104123
/>
105124
</StudioCard>
106125
);

src/Designer/frontend/language/src/nb.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"admin.app.info.publish_date": "Publiseringsdato",
88
"admin.app.info.published_by": "Publisert av",
99
"admin.app.info.title": "Informasjon om appen",
10+
"admin.app.missing_rights": "Du har ikke rettigheter til å se applikasjonsdata i {{envTitle}}. Be eierne i {{orgName}} om å gi deg tilgang.",
1011
"admin.apps.alert_no_org_selected": "For å vise publiserte apper, må du velge en organisasjon i menyen øverst til høyre.",
1112
"admin.apps.alert_no_org_selected_no_access": "Hvis du ikke har tilgang til noen organisasjoner, må du be om tilgang fra en tjenesteeier.",
1213
"admin.apps.name": "Navn",
@@ -65,6 +66,7 @@
6566
"admin.metrics.app.health.missing_rights": "Du har ikke rettigheter til å se applikasjonenshelse i {{envTitle}}. Be eierne i {{orgName}} om å gi deg tilgang.",
6667
"admin.metrics.app.loading": "Laster inn applikasjonsmetrikker for denne appen...",
6768
"admin.metrics.app.missing_rights": "Du har ikke rettigheter til å se applikasjonsmetrikker i {{envTitle}}. Be eierne i {{orgName}} om å gi deg tilgang.",
69+
"admin.metrics.missing_rights": "Du har ikke rettigheter til å se applikasjonsovervåking i {{envTitle}}. Be eierne i {{orgName}} om å gi deg tilgang.",
6870
"admin.metrics.app.no_data": "Fant ingen statistikk om appen for valgt periode.",
6971
"admin.metrics.app.no_data_link": "Her kan du se hvordan du setter en innstilling i koden for å samle inn statistikk.",
7072
"admin.metrics.errors": "Feil fra siste",

0 commit comments

Comments
 (0)