Skip to content

Commit f24cd02

Browse files
authored
fix: Reset layout after click on Navigation item (kyma-project#3726)
* small cleanup of code * temporary fix for layout state * add my thoughts * potential fix * revert changes * improve routing * fix flickering in custom resources * fix extensibility routes * use navigate
1 parent 9afbf46 commit f24cd02

File tree

19 files changed

+169
-210
lines changed

19 files changed

+169
-210
lines changed

src/components/App/ExtensibilityRoutes.js

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,7 @@ const Details = React.lazy(() =>
2020
);
2121
const Create = React.lazy(() => import('../Extensibility/ExtensibilityCreate'));
2222

23-
const ColumnWrapper = ({
24-
defaultColumn = 'list',
25-
resourceType,
26-
extension,
27-
urlPath,
28-
}) => {
23+
const ColumnWrapper = ({ resourceType, extension, urlPath }) => {
2924
const [layoutState, setLayoutColumn] = useRecoilState(columnLayoutState);
3025
const [searchParams] = useSearchParams();
3126
const layout = searchParams.get('layout');
@@ -34,6 +29,7 @@ const ColumnWrapper = ({
3429
const { t } = useTranslation();
3530

3631
const { namespaceId, resourceName } = useParams();
32+
const defaultColumn = resourceName ? 'details' : 'list';
3733
const initialLayoutState = layout
3834
? {
3935
layout: layout,
@@ -171,7 +167,7 @@ export const createExtensibilityRoutes = (extension, language, ...props) => {
171167
return (
172168
<React.Fragment key={urlPath}>
173169
<Route
174-
path={urlPath}
170+
path={`${urlPath}/:resourceName?`}
175171
exact
176172
element={
177173
<Suspense fallback={<Spinner />}>
@@ -183,21 +179,6 @@ export const createExtensibilityRoutes = (extension, language, ...props) => {
183179
</Suspense>
184180
}
185181
/>
186-
{extension.details && (
187-
<Route
188-
path={`${urlPath}/:resourceName`}
189-
exact
190-
element={
191-
<Suspense fallback={<Spinner />}>
192-
<ColumnWrapper
193-
defaultColumn="details"
194-
resourceType={resourceType}
195-
urlPath={urlPath}
196-
/>
197-
</Suspense>
198-
}
199-
/>
200-
)}
201182
</React.Fragment>
202183
);
203184
};

src/components/CustomResources/CustomResources.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function CustomResources({
1919
}) {
2020
const { group, names } = crd.spec;
2121
const name = names.plural;
22-
const customUrl = useCustomResourceUrl(crd, true);
22+
const customUrl = useCustomResourceUrl(crd);
2323
const { namespace } = useUrl();
2424
const resourceUrl =
2525
namespace && namespace !== '-all-'
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useParams } from 'react-router-dom';
2+
import EventDetails from 'resources/Events/EventDetails';
3+
import { pathSegment } from 'resources/ClusterEvents/index';
4+
import { useUrl } from 'hooks/useUrl';
5+
6+
export type ClusterEventDetailsProps = {
7+
resourceName: string;
8+
resourceUrl: string | undefined;
9+
namespace: string | undefined;
10+
};
11+
12+
export default function ClusterEventDetails({
13+
resourceName,
14+
resourceUrl,
15+
namespace,
16+
...props
17+
}: ClusterEventDetailsProps) {
18+
const params = useParams();
19+
const overriddenNamespace = params.namespace ?? namespace;
20+
const overriddenResourceUrl = resourceUrl
21+
? `/api/v1/namespaces/${overriddenNamespace}/events/${resourceName}`
22+
: undefined;
23+
const { clusterUrl } = useUrl();
24+
return (
25+
<EventDetails
26+
{...props}
27+
layoutCloseCreateUrl={clusterUrl(pathSegment)}
28+
resourceName={resourceName}
29+
namespace={overriddenNamespace}
30+
resourceUrl={overriddenResourceUrl}
31+
/>
32+
);
33+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import EventsList from 'resources/Events/EventList';
2+
import { ReactNode } from 'react';
3+
4+
export default function ClusterEventList(props: any): ReactNode {
5+
return <EventsList {...props} isClusterView={true} />;
6+
}
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
export { List, Details, resourceType } from 'resources/Events';
1+
import React from 'react';
2+
3+
export { resourceType, ResourceDescription } from 'resources/Events';
24
export const namespaced = false;
35
export const apiGroup = '';
46
export const apiVersion = 'v1';
5-
67
export const category = '';
7-
export const topLevelNode = true;
88
export const icon = 'warning2';
9+
export const topLevelNode = true;
10+
11+
export const pathSegment = 'clusterevents';
12+
export const customPath = `${pathSegment}/:namespace?/:resourceName?`;
13+
14+
export const List = React.lazy(() => import('./ClusterEventList'));
15+
export const Details = React.lazy(() => import('./ClusterEventDetails'));

src/resources/CustomResourceDefinitions/CRCreate.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,11 @@ function CRCreate({
2828
const [initialResource] = useState(
2929
initialCustomResource || createTemplate(crd),
3030
);
31-
const currUrl = window.location.href;
3231

33-
const customUrl = useCustomResourceUrl(
34-
crd,
35-
currUrl.includes('customresources/'),
36-
);
32+
const customUrl = useCustomResourceUrl(crd);
3733

3834
const navigate = useNavigate();
39-
const { nextQuery, currentQuery } = usePrepareLayout(layoutNumber);
40-
const goToLayoutQuery = customUrl(cr).includes('customresources/')
41-
? nextQuery
42-
: currentQuery;
35+
const { nextQuery } = usePrepareLayout(layoutNumber);
4336

4437
const currentVersion = crd.spec.versions?.find(ver => ver.storage).name;
4538
const namespace =
@@ -75,7 +68,7 @@ function CRCreate({
7568
resourceType: crd.spec.names.kind,
7669
}),
7770
});
78-
navigate(`${customUrl(cr)}${goToLayoutQuery}`);
71+
navigate(`${customUrl(cr)}${nextQuery}`);
7972
}}
8073
/>
8174
);
Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,21 @@
1-
import { useRecoilValue } from 'recoil';
2-
3-
import { allNodesSelector } from 'state/navigation/allNodesSelector';
41
import { useUrl } from 'hooks/useUrl';
52

6-
export function useCustomResourceUrl(crd, columnLayout = false) {
7-
const { resourceUrl, clusterUrl, namespaceUrl } = useUrl();
8-
const clusterNodes = useRecoilValue(allNodesSelector).filter(
9-
node => !node.namespaced,
10-
);
11-
const namespaceNodes = useRecoilValue(allNodesSelector).filter(
12-
node => node.namespaced,
13-
);
14-
3+
export function useCustomResourceUrl(crd) {
4+
const { clusterUrl, namespaceUrl } = useUrl();
155
return cr => {
16-
const crdNamePlural = crd.spec.names.plural;
17-
const clusterNode = clusterNodes.find(
18-
res => res.resourceType === crdNamePlural,
6+
const crClusterURL = clusterUrl(
7+
`customresources/${crd.metadata.name}/${cr.metadata.name}`,
198
);
20-
const namespaceNode = namespaceNodes.find(
21-
res => res.resourceType === crdNamePlural,
9+
10+
const crNamespaceURL = namespaceUrl(
11+
`customresources/${crd.metadata.name}/${cr.metadata.name}`,
12+
{ namespace: cr.metadata.namespace },
2213
);
2314

24-
if (clusterNode) {
25-
return resourceUrl(cr, { resourceType: clusterNode.pathSegment });
26-
} else if (namespaceNode && !columnLayout) {
27-
return resourceUrl(cr, { resourceType: namespaceNode.pathSegment });
28-
} else if (crd.spec.scope === 'Cluster') {
29-
return clusterUrl(
30-
`customresources/${crd.metadata.name}/${cr.metadata.name}`,
31-
);
15+
if (crd.spec.scope === 'Cluster') {
16+
return crClusterURL;
3217
} else {
33-
return namespaceUrl(
34-
`customresources/${crd.metadata.name}/${cr.metadata.name}`,
35-
{ namespace: cr.metadata.namespace },
36-
);
18+
return crNamespaceURL;
3719
}
3820
};
3921
}

src/resources/Events/EventDetails.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ export default function EventDetails(props) {
8787
value: event => (
8888
<Link
8989
data-testid="details-link"
90-
url={clusterUrl(`namespaces/${event.metadata.namespace}`)}
90+
url={clusterUrl(
91+
`namespaces/${event.metadata.namespace}/events/${props.resourceName}`,
92+
)}
9193
>
9294
{event.metadata.namespace}
9395
</Link>
@@ -103,6 +105,7 @@ export default function EventDetails(props) {
103105

104106
return (
105107
<ResourceDetails
108+
{...props}
106109
customComponents={[Specification]}
107110
customColumns={customColumns}
108111
description={ResourceDescription}
@@ -112,7 +115,6 @@ export default function EventDetails(props) {
112115
hideLabels
113116
hideAnnotations
114117
hideLastUpdate
115-
{...props}
116118
/>
117119
);
118120
}

src/resources/Events/EventList.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,41 @@ import { ResourcesList } from 'shared/components/ResourcesList/ResourcesList';
88
import { useUrl } from 'hooks/useUrl';
99
import { Icon, ObjectStatus, Text } from '@ui5/webcomponents-react';
1010
import {
11-
ResourceDescription,
1211
docsURL,
1312
i18nDescriptionKey,
13+
ResourceDescription,
1414
} from 'resources/Events';
15+
import { pathSegment } from 'resources/ClusterEvents';
16+
17+
function useEventUrl(resourceType, clusterView) {
18+
const { namespaceUrl, clusterUrl } = useUrl();
19+
20+
if (clusterView) {
21+
return resource => {
22+
return clusterUrl(
23+
`${pathSegment}/${resource.metadata.namespace}/${resource.metadata.name}`,
24+
);
25+
};
26+
}
27+
return resource => {
28+
return namespaceUrl(`${resourceType}/${resource.metadata.name}`, {
29+
namespace: resource.metadata.namespace,
30+
});
31+
};
32+
}
1533

1634
export function EventList({
1735
defaultType,
1836
hideInvolvedObjects,
1937
filter,
2038
isCompact,
39+
isClusterView = false,
2140
...props
2241
}) {
2342
const { t } = useTranslation();
24-
const { namespaceUrl, namespace } = useUrl();
43+
const { namespace } = useUrl();
2544
const resourceType = props.resourceType.toLowerCase();
45+
const customUrl = useEventUrl(resourceType, isClusterView);
2646
const {
2747
EVENT_MESSAGE_TYPE,
2848
displayType,
@@ -149,11 +169,7 @@ export function EventList({
149169
searchSettings={{
150170
textSearchProperties,
151171
}}
152-
customUrl={event =>
153-
namespaceUrl(`${resourceType}/${event.metadata.name}`, {
154-
namespace: event.metadata.namespace,
155-
})
156-
}
172+
customUrl={customUrl}
157173
emptyListProps={{
158174
showButton: false,
159175
subtitleText: i18nDescriptionKey,

src/resources/createResourceRoutes.js

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,12 @@ export const createPath = (
2424
) => {
2525
const { detailsView = false, pathSegment = '' } = config;
2626

27-
const details = detailsView ? '/:resourceName' : '';
27+
const details = detailsView ? '/:resourceName?' : '';
2828

2929
return `${pathSegment}${details}`;
3030
};
3131

32-
const ColumnWrapper = ({
33-
defaultColumn = 'list',
34-
list,
35-
details,
36-
create,
37-
...props
38-
}) => {
32+
const ColumnWrapper = ({ list, details, create, ...props }) => {
3933
const [layoutState, setLayoutColumn] = useRecoilState(columnLayoutState);
4034
const [searchParams] = useSearchParams();
4135
const layout = searchParams.get('layout');
@@ -57,6 +51,8 @@ const ColumnWrapper = ({
5751
[props.namespaceId, namespaceIdFromParams],
5852
);
5953

54+
const defaultColumn = resourceName ? 'details' : 'list';
55+
6056
const initialLayoutState = layout
6157
? {
6258
layout: layout,
@@ -210,22 +206,19 @@ export const createResourceRoutes = ({
210206
List = null,
211207
Details = null,
212208
Create = null,
213-
namespaced = true,
214209
resourceType = '',
215210
resourceI18Key = '',
211+
customPath = null,
216212
...props
217213
}) => {
218214
const pathSegment = resourceType.toLowerCase();
219215

220-
const listPath = createPath({ pathSegment });
221-
const detailsPath = Details
222-
? createPath({ pathSegment, detailsView: true })
223-
: '';
216+
const path = customPath || createPath({ pathSegment, detailsView: true });
224217

225218
return (
226-
<React.Fragment key={listPath}>
219+
<React.Fragment key={path}>
227220
<Route
228-
path={listPath}
221+
path={path}
229222
exact
230223
element={
231224
<Suspense fallback={<Spinner />}>
@@ -243,27 +236,6 @@ export const createResourceRoutes = ({
243236
</Suspense>
244237
}
245238
/>
246-
{detailsPath ? (
247-
<Route
248-
path={detailsPath}
249-
element={
250-
<Suspense fallback={<Spinner />}>
251-
<ColumnWrapper
252-
resourceType={resourceType}
253-
resourceI18Key={resourceI18Key}
254-
hasDetailsView={true}
255-
list={<List />}
256-
details={<Details />}
257-
create={Create ? <Create /> : null}
258-
defaultColumn="details"
259-
{...props}
260-
>
261-
<Details />
262-
</ColumnWrapper>
263-
</Suspense>
264-
}
265-
/>
266-
) : null}
267239
</React.Fragment>
268240
);
269241
};

0 commit comments

Comments
 (0)