-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathApplication.tsx
148 lines (136 loc) · 5.14 KB
/
Application.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import {
Alert,
AlertActionLink,
AlertVariant,
Button,
ButtonVariant,
Drawer,
DrawerContent,
DrawerContentBody,
List,
ListItem,
ListVariant,
PageSection,
PageSectionVariants,
Spinner,
} from '@patternfly/react-core';
import { Link, useHistory, useParams } from 'react-router-dom';
import { QueryObserverResult, useQuery } from 'react-query';
import React, { useState } from 'react';
import { UsersIcon } from '@patternfly/react-icons';
import { ExternalLink, IApplication, Title } from '@kobsio/plugin-core';
import { DashboardsWrapper } from '@kobsio/plugin-dashboards';
interface IApplicationsParams {
cluster: string;
namespace: string;
name: string;
}
// The Application component is used to display a single application. The application which should be shown is
// determined by the cluster, namespace and name paramter. These parameters are passed to the API as query parameters.
// The API is called everytime the cluster, namespace or name parameter changes and returns the application.
const Application: React.FunctionComponent = () => {
const history = useHistory();
const params = useParams<IApplicationsParams>();
const [details, setDetails] = useState<React.ReactNode>(undefined);
const { isError, isLoading, error, data, refetch } = useQuery<IApplication, Error>(
['applications/application', params.cluster, params.namespace, params.name],
async () => {
try {
const response = await fetch(
`/api/plugins/applications/application?cluster=${params.cluster}&namespace=${params.namespace}&name=${params.name}`,
{ method: 'get' },
);
const json = await response.json();
if (response.status >= 200 && response.status < 300) {
return json;
} else {
if (json.error) {
throw new Error(json.error);
} else {
throw new Error('An unknown error occured');
}
}
} catch (err) {
throw err;
}
},
);
// During the API call we display a Spinner at the center of the page.
if (isLoading) {
return <Spinner style={{ left: '50%', position: 'fixed', top: '50%', transform: 'translate(-50%, -50%)' }} />;
}
// When an error occured during the API call we show this error. The user has then the option to go to the home page,
// the applications page or to retry the API call.
if (isError) {
return (
<Alert
style={{ left: '50%', position: 'fixed', top: '50%', transform: 'translate(-50%, -50%)' }}
variant={AlertVariant.danger}
title="Could not get application"
actionLinks={
<React.Fragment>
<AlertActionLink onClick={(): void => history.push('/')}>Home</AlertActionLink>
<AlertActionLink onClick={(): void => history.push('/applications')}>Applications</AlertActionLink>
<AlertActionLink onClick={(): Promise<QueryObserverResult<IApplication, Error>> => refetch()}>
Retry
</AlertActionLink>
</React.Fragment>
}
>
<p>{error?.message}</p>
</Alert>
);
}
// As long as the data is undefined we do not display anything. This can happen during the first rendering of the
// component. After this the data should be defined or the data is loading or an error occured.
if (!data) {
return null;
}
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Title title={data.name} subtitle={`${data.namespace} (${data.cluster})`} size="xl" />
<div>
<p>{data.description}</p>
{(data.teams && data.teams.length > 0) || (data.links && data.links.length > 0) ? (
<List variant={ListVariant.inline}>
{data.teams &&
data.teams.map((team, index) => (
<ListItem key={index}>
<Link
key={index}
to={`/teams/${team.cluster ? team.cluster : data.cluster}/${
team.namespace ? team.namespace : data.namespace
}/${team.name}`}
>
<Button variant={ButtonVariant.link} isInline={true} icon={<UsersIcon />}>
{team.name}
</Button>
</Link>
</ListItem>
))}
{data.links &&
data.links.map((link, index) => (
<ListItem key={index}>
<ExternalLink title={link.title} link={link.link} />
</ListItem>
))}
</List>
) : null}
</div>
</PageSection>
<Drawer isExpanded={details !== undefined}>
<DrawerContent panelContent={details}>
<DrawerContentBody>
{data.dashboards ? (
<DashboardsWrapper defaults={data} references={data.dashboards} setDetails={setDetails} />
) : (
<PageSection style={{ minHeight: '100%' }} variant={PageSectionVariants.default}></PageSection>
)}
</DrawerContentBody>
</DrawerContent>
</Drawer>
</React.Fragment>
);
};
export default Application;