argo-cd
159 строк · 10.5 Кб
1import {DataLoader, DropDownMenu, Tooltip} from 'argo-ui';
2import * as React from 'react';
3import Moment from 'react-moment';
4import {Key, KeybindingContext, useNav} from 'argo-ui/v2';
5import {Cluster} from '../../../shared/components';
6import {Consumer, Context} from '../../../shared/context';
7import * as models from '../../../shared/models';
8import {ApplicationURLs} from '../application-urls';
9import * as AppUtils from '../utils';
10import {getAppDefaultSource, OperationState} from '../utils';
11import {ApplicationsLabels} from './applications-labels';
12import {ApplicationsSource} from './applications-source';
13import {services} from '../../../shared/services';
14import './applications-table.scss';
15
16export const ApplicationsTable = (props: {
17applications: models.Application[];
18syncApplication: (appName: string, appNamespace: string) => any;
19refreshApplication: (appName: string, appNamespace: string) => any;
20deleteApplication: (appName: string, appNamespace: string) => any;
21}) => {
22const [selectedApp, navApp, reset] = useNav(props.applications.length);
23const ctxh = React.useContext(Context);
24
25const {useKeybinding} = React.useContext(KeybindingContext);
26
27useKeybinding({keys: Key.DOWN, action: () => navApp(1)});
28useKeybinding({keys: Key.UP, action: () => navApp(-1)});
29useKeybinding({
30keys: Key.ESCAPE,
31action: () => {
32reset();
33return selectedApp > -1 ? true : false;
34}
35});
36useKeybinding({
37keys: Key.ENTER,
38action: () => {
39if (selectedApp > -1) {
40ctxh.navigation.goto(`/applications/${props.applications[selectedApp].metadata.name}`);
41return true;
42}
43return false;
44}
45});
46
47return (
48<Consumer>
49{ctx => (
50<DataLoader load={() => services.viewPreferences.getPreferences()}>
51{pref => {
52const favList = pref.appList.favoritesAppList || [];
53return (
54<div className='applications-table argo-table-list argo-table-list--clickable'>
55{props.applications.map((app, i) => (
56<div
57key={AppUtils.appInstanceName(app)}
58className={`argo-table-list__row
59applications-list__entry applications-list__entry--health-${app.status.health.status} ${selectedApp === i ? 'applications-tiles__selected' : ''}`}>
60<div
61className={`row applications-list__table-row`}
62onClick={e => ctx.navigation.goto(`/applications/${app.metadata.namespace}/${app.metadata.name}`, {}, {event: e})}>
63<div className='columns small-4'>
64<div className='row'>
65<div className=' columns small-2'>
66<div>
67<Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
68<button
69onClick={e => {
70e.stopPropagation();
71favList?.includes(app.metadata.name)
72? favList.splice(favList.indexOf(app.metadata.name), 1)
73: favList.push(app.metadata.name);
74services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
75}}>
76<i
77className={favList?.includes(app.metadata.name) ? 'fas fa-star' : 'far fa-star'}
78style={{
79cursor: 'pointer',
80marginRight: '7px',
81color: favList?.includes(app.metadata.name) ? '#FFCE25' : '#8fa4b1'
82}}
83/>
84</button>
85</Tooltip>
86<ApplicationURLs urls={app.status.summary.externalURLs} />
87</div>
88</div>
89<div className='show-for-xxlarge columns small-4'>Project:</div>
90<div className='columns small-12 xxlarge-6'>{app.spec.project}</div>
91</div>
92<div className='row'>
93<div className=' columns small-2' />
94<div className='show-for-xxlarge columns small-4'>Name:</div>
95<div className='columns small-12 xxlarge-6'>
96<Tooltip
97content={
98<>
99{app.metadata.name}
100<br />
101<Moment fromNow={true} ago={true}>
102{app.metadata.creationTimestamp}
103</Moment>
104</>
105}>
106<span>{app.metadata.name}</span>
107</Tooltip>
108</div>
109</div>
110</div>
111
112<div className='columns small-6'>
113<div className='row'>
114<div className='show-for-xxlarge columns small-2'>Source:</div>
115<div className='columns small-12 xxlarge-10 applications-table-source' style={{position: 'relative'}}>
116<div className='applications-table-source__link'>
117<ApplicationsSource source={getAppDefaultSource(app)} />
118</div>
119<div className='applications-table-source__labels'>
120<ApplicationsLabels app={app} />
121</div>
122</div>
123</div>
124<div className='row'>
125<div className='show-for-xxlarge columns small-2'>Destination:</div>
126<div className='columns small-12 xxlarge-10'>
127<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />/{app.spec.destination.namespace}
128</div>
129</div>
130</div>
131
132<div className='columns small-2'>
133<AppUtils.HealthStatusIcon state={app.status.health} /> <span>{app.status.health.status}</span> <br />
134<AppUtils.ComparisonStatusIcon status={app.status.sync.status} />
135<span>{app.status.sync.status}</span> <OperationState app={app} quiet={true} />
136<DropDownMenu
137anchor={() => (
138<button className='argo-button argo-button--light argo-button--lg argo-button--short'>
139<i className='fa fa-ellipsis-v' />
140</button>
141)}
142items={[
143{title: 'Sync', action: () => props.syncApplication(app.metadata.name, app.metadata.namespace)},
144{title: 'Refresh', action: () => props.refreshApplication(app.metadata.name, app.metadata.namespace)},
145{title: 'Delete', action: () => props.deleteApplication(app.metadata.name, app.metadata.namespace)}
146]}
147/>
148</div>
149</div>
150</div>
151))}
152</div>
153);
154}}
155</DataLoader>
156)}
157</Consumer>
158);
159};
160