Skip to content

Commit 847cb1e

Browse files
author
Marc Monchablon
committed
fix(pci-project): fix redirection on malformed projectId
ref: #MANAGER-19363 Signed-off-by: Marc Monchablon <[email protected]>
1 parent c9166f4 commit 847cb1e

File tree

4 files changed

+160
-117
lines changed

4 files changed

+160
-117
lines changed

packages/manager/apps/pci-project/src/index.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,16 @@ ods-text.disabled::part(text) {
6565
flex-grow: 1;
6666
max-width: 33.3333%;
6767
}
68+
69+
@media (max-width: 35rem) {
70+
.contacts-card .row {
71+
flex-direction: column;
72+
gap: 0.5em;
73+
}
74+
.contacts-card .contacts-card-info {
75+
max-width: 100%;
76+
&:first-child {
77+
align-self: flex-end;
78+
}
79+
}
80+
}

packages/manager/apps/pci-project/src/pages/contacts/Contacts.page.tsx

Lines changed: 97 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
BaseLayout,
1515
Notifications,
1616
ChangelogButton,
17+
RedirectionGuard,
1718
PciGuidesHeader,
1819
Datagrid,
1920
useProjectUrl,
@@ -65,7 +66,11 @@ export default function ContactsPage() {
6566
const context = useContext(ShellContext);
6667
const user = context.environment.getUser();
6768
const projectId = useParam('projectId');
68-
const { data: project } = useProject();
69+
const {
70+
data: project,
71+
isLoading: isProjectLoading,
72+
isError: isProjectError,
73+
} = useProject();
6974
const { data: serviceInfo } = useProjectService(projectId);
7075
const { data: aclAccountIds } = useProjectAcl(projectId);
7176
const userAcls = useProjectAclAccountsInfo(projectId, aclAccountIds || []);
@@ -78,96 +83,111 @@ export default function ContactsPage() {
7883
const openAddContactModal = () => {
7984
navigate(`./${urls.contactAndRightsAdd}`);
8085
};
86+
const isUsRegion = context.environment.getRegion() === 'US';
8187
const isEuRegion = context.environment.getRegion() === 'EU';
8288
const discoveryProject = isDiscoveryProject(project);
8389
const canChangeContacts = isEuRegion && !discoveryProject;
8490
const contactsPageHref = useGetContactsPageHref(context, serviceInfo);
91+
const redirectToProjects = isProjectError || isUsRegion;
8592

8693
if (!project || !serviceInfo || !userAcls) {
87-
return <OdsSpinner size="md" />;
94+
return (
95+
<RedirectionGuard
96+
condition={redirectToProjects}
97+
isLoading={isProjectLoading}
98+
route={urls.root}
99+
>
100+
<OdsSpinner size="md" />
101+
</RedirectionGuard>
102+
);
88103
}
89104

90105
return (
91-
<BaseLayout
92-
header={{
93-
title: t('pci_projects_project_contacts_title'),
94-
changelogButton: <ChangelogButton links={ROADMAP_CHANGELOG_LINKS} />,
95-
headerButton: <PciGuidesHeader category="instances" />,
96-
}}
97-
breadcrumb={
98-
<OdsBreadcrumb>
99-
<OdsBreadcrumbItem href={hrefProject} label={project.description} />
100-
<OdsBreadcrumbItem
101-
href={'#'}
102-
label={t('pci_projects_project_contacts_title')}
103-
/>
104-
</OdsBreadcrumb>
105-
}
106+
<RedirectionGuard
107+
condition={redirectToProjects}
108+
isLoading={isProjectLoading}
109+
route={urls.root}
106110
>
107-
<div className="flex flex-col gap-4 mb-8">
108-
<PciDiscoveryBanner project={project} />
109-
<Notifications />
110-
<div className="contacts-card">
111-
<div className="row">
112-
<OdsText className="contacts-card-info text-right">
113-
{t('cpb_rights_owner')}
114-
</OdsText>
115-
<OdsText className="contacts-card-info text-left">
116-
{serviceInfo.contactAdmin}
117-
</OdsText>
118-
<div className="contacts-card-info">
119-
{canChangeContacts && (
120-
<OdsLink
121-
href={contactsPageHref}
122-
label={t('cpb_rights_modify')}
123-
icon={ODS_ICON_NAME.externalLink}
124-
target="_blank"
125-
/>
126-
)}
111+
<BaseLayout
112+
header={{
113+
title: t('pci_projects_project_contacts_title'),
114+
changelogButton: <ChangelogButton links={ROADMAP_CHANGELOG_LINKS} />,
115+
headerButton: <PciGuidesHeader category="instances" />,
116+
}}
117+
breadcrumb={
118+
<OdsBreadcrumb>
119+
<OdsBreadcrumbItem href={hrefProject} label={project.description} />
120+
<OdsBreadcrumbItem
121+
href={'#'}
122+
label={t('pci_projects_project_contacts_title')}
123+
/>
124+
</OdsBreadcrumb>
125+
}
126+
>
127+
<div className="flex flex-col gap-4 mb-8">
128+
<PciDiscoveryBanner project={project} />
129+
<Notifications />
130+
<div className="contacts-card">
131+
<div className="row">
132+
<OdsText className="contacts-card-info text-right">
133+
{t('cpb_rights_owner')}
134+
</OdsText>
135+
<OdsText className="contacts-card-info text-left">
136+
{serviceInfo.contactAdmin}
137+
</OdsText>
138+
<div className="contacts-card-info">
139+
{canChangeContacts && (
140+
<OdsLink
141+
href={contactsPageHref}
142+
label={t('cpb_rights_modify')}
143+
icon={ODS_ICON_NAME.externalLink}
144+
target="_blank"
145+
/>
146+
)}
147+
</div>
127148
</div>
128-
</div>
129-
<div className="row mt-4">
130-
<OdsText className="contacts-card-info text-right">
131-
{t('cpb_rights_billing_contact')}
132-
</OdsText>
133-
<OdsText className="contacts-card-info text-left">
134-
{serviceInfo.contactBilling}
135-
</OdsText>
136-
<div className="contacts-card-info">
137-
{canChangeContacts && (
138-
<OdsLink
139-
href={contactsPageHref}
140-
label={t('cpb_rights_modify')}
141-
icon={ODS_ICON_NAME.externalLink}
142-
target="_blank"
143-
/>
144-
)}
149+
<div className="row mt-4">
150+
<OdsText className="contacts-card-info text-right">
151+
{t('cpb_rights_billing_contact')}
152+
</OdsText>
153+
<OdsText className="contacts-card-info text-left">
154+
{serviceInfo.contactBilling}
155+
</OdsText>
156+
<div className="contacts-card-info">
157+
{canChangeContacts && (
158+
<OdsLink
159+
href={contactsPageHref}
160+
label={t('cpb_rights_modify')}
161+
icon={ODS_ICON_NAME.externalLink}
162+
target="_blank"
163+
/>
164+
)}
165+
</div>
145166
</div>
146167
</div>
147-
</div>
148-
<OdsText>{t('cpb_rights_expl2')}</OdsText>
149-
<OdsText>{t('cpb_rights_note')}</OdsText>
168+
<OdsText>{t('cpb_rights_expl2')}</OdsText>
169+
<OdsText>{t('cpb_rights_note')}</OdsText>
150170

151-
{isAdmin && (
152-
<OdsButton
153-
className="my-8 size-fit"
154-
label={t('common_add')}
155-
variant={ODS_BUTTON_VARIANT.outline}
156-
onClick={openAddContactModal}
157-
isDisabled={discoveryProject}
158-
/>
159-
)}
171+
{isAdmin && (
172+
<OdsButton
173+
className="my-8 size-fit"
174+
label={t('common_add')}
175+
variant={ODS_BUTTON_VARIANT.outline}
176+
onClick={openAddContactModal}
177+
isDisabled={discoveryProject}
178+
/>
179+
)}
160180

161-
<Datagrid
162-
columns={columns}
163-
items={flattenData as AccountAcl[]}
164-
totalItems={userAcls.length}
165-
hasNextPage={hasNextPage}
166-
onFetchNextPage={fetchNextPage}
167-
/>
168-
</div>
169-
170-
<Outlet />
171-
</BaseLayout>
181+
<Datagrid
182+
columns={columns}
183+
items={flattenData as AccountAcl[]}
184+
totalItems={userAcls.length}
185+
hasNextPage={hasNextPage}
186+
onFetchNextPage={fetchNextPage}
187+
/>
188+
</div>
189+
<Outlet />
190+
</BaseLayout>
191+
</RedirectionGuard>
172192
);
173193
}

packages/manager/apps/pci-project/src/pages/contacts/components/AddAccountAcl.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export default function AddAccountAcl() {
2929
const [accountRights, setAccountRights] = useState<AclRight>('readOnly');
3030
const [isAccountInputTouched, setIsAccountInputTouched] = useState(false);
3131
const handleClose = () => navigate('..');
32-
const isUSorCA = ['US', 'CA'].includes(user.country.toUpperCase());
3332
const normalizedAccountId = normalizeAccountId(accountToAdd);
3433

3534
const { addAccountAclToProject, isPending } = useAddAccountAclToProject({
@@ -76,9 +75,7 @@ export default function AddAccountAcl() {
7675
}
7776
>
7877
<label htmlFor="contactInput" slot="label">
79-
{isUSorCA
80-
? t('cpb_rights_table_email')
81-
: t('cpb_rights_table_nichandle')}
78+
{t('cpb_rights_table_nichandle')}
8279
</label>
8380
<OdsInput
8481
type={ODS_INPUT_TYPE.text}

packages/manager/apps/pci-project/src/pages/home/Header.page.tsx

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
useProject,
88
usePciUrl,
99
} from '@ovh-ux/manager-pci-common';
10-
import { BaseLayout, ChangelogButton } from '@ovh-ux/manager-react-components';
10+
import {
11+
BaseLayout,
12+
ChangelogButton,
13+
RedirectionGuard,
14+
} from '@ovh-ux/manager-react-components';
1115
import { ODS_BADGE_COLOR, ODS_BADGE_SIZE } from '@ovhcloud/ods-components';
1216
import {
1317
OdsBreadcrumb,
@@ -18,51 +22,60 @@ import {
1822
import { ROADMAP_CHANGELOG_LINKS } from '@/constants';
1923
import { useProjectTabs } from '@/hooks/useProjectTabs';
2024
import QuotaAlert from './components/QuotaAlert.component';
25+
import { urls } from '@/routes/routes.constant';
2126

2227
export default function ProjectHeader() {
2328
const { t } = useTranslation('project');
2429

2530
const hrefProject = usePciUrl();
26-
const { data: project, isLoading, error } = useProject();
31+
const {
32+
data: project,
33+
isLoading: isProjectLoading,
34+
isError: isProjectError,
35+
} = useProject();
2736
const tabs = useProjectTabs();
2837

2938
const isDiscovery = isDiscoveryProject(project);
3039

31-
if (error) throw error;
32-
3340
return (
34-
<BaseLayout
35-
breadcrumb={
36-
isLoading ? (
37-
<OdsSkeleton className="w-48 h-6" />
38-
) : (
39-
<OdsBreadcrumb>
40-
<OdsBreadcrumbItem
41-
href={hrefProject}
42-
label={project?.description}
43-
/>
44-
</OdsBreadcrumb>
45-
)
46-
}
47-
header={{
48-
title: project?.description,
49-
badge: isDiscovery
50-
? {
51-
color: ODS_BADGE_COLOR.information,
52-
size: ODS_BADGE_SIZE.md,
53-
label: t('pci_projects_project_label_discovery'),
54-
}
55-
: undefined,
56-
changelogButton: <ChangelogButton links={ROADMAP_CHANGELOG_LINKS} />,
57-
}}
58-
tabs={
59-
<nav aria-label={t('pci_projects_project_main_navigation')}>
60-
<TabsPanel tabs={tabs} />
61-
</nav>
62-
}
41+
<RedirectionGuard
42+
condition={isProjectError}
43+
isLoading={isProjectLoading}
44+
route={urls.root}
6345
>
64-
<QuotaAlert />
65-
<Outlet />
66-
</BaseLayout>
46+
<BaseLayout
47+
breadcrumb={
48+
isProjectLoading ? (
49+
<OdsSkeleton className="w-48 h-6" />
50+
) : (
51+
<OdsBreadcrumb>
52+
<OdsBreadcrumbItem
53+
href={hrefProject}
54+
label={project?.description}
55+
/>
56+
</OdsBreadcrumb>
57+
)
58+
}
59+
header={{
60+
title: project?.description,
61+
badge: isDiscovery
62+
? {
63+
color: ODS_BADGE_COLOR.information,
64+
size: ODS_BADGE_SIZE.md,
65+
label: t('pci_projects_project_label_discovery'),
66+
}
67+
: undefined,
68+
changelogButton: <ChangelogButton links={ROADMAP_CHANGELOG_LINKS} />,
69+
}}
70+
tabs={
71+
<nav aria-label={t('pci_projects_project_main_navigation')}>
72+
<TabsPanel tabs={tabs} />
73+
</nav>
74+
}
75+
>
76+
<QuotaAlert />
77+
<Outlet />
78+
</BaseLayout>
79+
</RedirectionGuard>
6780
);
6881
}

0 commit comments

Comments
 (0)