argo-cd

Форк
0
317 строк · 21.4 Кб
1
import {DataLoader, Tooltip} from 'argo-ui';
2
import * as classNames from 'classnames';
3
import * as React from 'react';
4
import {Key, KeybindingContext, NumKey, NumKeyToNumber, NumPadKey, useNav} from 'argo-ui/v2';
5
import {Cluster} from '../../../shared/components';
6
import {Consumer, Context, AuthSettingsCtx} from '../../../shared/context';
7
import * as models from '../../../shared/models';
8
import {ApplicationURLs} from '../application-urls';
9
import * as AppUtils from '../utils';
10
import {getAppDefaultSource, OperationState} from '../utils';
11
import {services} from '../../../shared/services';
12

13
import './applications-tiles.scss';
14

15
export interface ApplicationTilesProps {
16
    applications: models.Application[];
17
    syncApplication: (appName: string, appNamespace: string) => any;
18
    refreshApplication: (appName: string, appNamespace: string) => any;
19
    deleteApplication: (appName: string, appNamespace: string) => any;
20
}
21

22
const useItemsPerContainer = (itemRef: any, containerRef: any): number => {
23
    const [itemsPer, setItemsPer] = React.useState(0);
24

25
    React.useEffect(() => {
26
        const handleResize = () => {
27
            let timeoutId: any;
28
            clearTimeout(timeoutId);
29
            timeoutId = setTimeout(() => {
30
                timeoutId = null;
31
                const itemWidth = itemRef.current ? itemRef.current.offsetWidth : -1;
32
                const containerWidth = containerRef.current ? containerRef.current.offsetWidth : -1;
33
                const curItemsPer = containerWidth > 0 && itemWidth > 0 ? Math.floor(containerWidth / itemWidth) : 1;
34
                if (curItemsPer !== itemsPer) {
35
                    setItemsPer(curItemsPer);
36
                }
37
            }, 1000);
38
        };
39
        window.addEventListener('resize', handleResize);
40
        handleResize();
41
        return () => {
42
            window.removeEventListener('resize', handleResize);
43
        };
44
    }, []);
45

46
    return itemsPer || 1;
47
};
48

49
export const ApplicationTiles = ({applications, syncApplication, refreshApplication, deleteApplication}: ApplicationTilesProps) => {
50
    const [selectedApp, navApp, reset] = useNav(applications.length);
51

52
    const ctxh = React.useContext(Context);
53
    const appRef = {ref: React.useRef(null), set: false};
54
    const appContainerRef = React.useRef(null);
55
    const appsPerRow = useItemsPerContainer(appRef.ref, appContainerRef);
56
    const useAuthSettingsCtx = React.useContext(AuthSettingsCtx);
57

58
    const {useKeybinding} = React.useContext(KeybindingContext);
59

60
    useKeybinding({keys: Key.RIGHT, action: () => navApp(1)});
61
    useKeybinding({keys: Key.LEFT, action: () => navApp(-1)});
62
    useKeybinding({keys: Key.DOWN, action: () => navApp(appsPerRow)});
63
    useKeybinding({keys: Key.UP, action: () => navApp(-1 * appsPerRow)});
64

65
    useKeybinding({
66
        keys: Key.ENTER,
67
        action: () => {
68
            if (selectedApp > -1) {
69
                ctxh.navigation.goto(`/applications/${applications[selectedApp].metadata.name}`);
70
                return true;
71
            }
72
            return false;
73
        }
74
    });
75

76
    useKeybinding({
77
        keys: Key.ESCAPE,
78
        action: () => {
79
            if (selectedApp > -1) {
80
                reset();
81
                return true;
82
            }
83
            return false;
84
        }
85
    });
86

87
    useKeybinding({
88
        keys: Object.values(NumKey) as NumKey[],
89
        action: n => {
90
            reset();
91
            return navApp(NumKeyToNumber(n));
92
        }
93
    });
94
    useKeybinding({
95
        keys: Object.values(NumPadKey) as NumPadKey[],
96
        action: n => {
97
            reset();
98
            return navApp(NumKeyToNumber(n));
99
        }
100
    });
101
    return (
102
        <Consumer>
103
            {ctx => (
104
                <DataLoader load={() => services.viewPreferences.getPreferences()}>
105
                    {pref => {
106
                        const favList = pref.appList.favoritesAppList || [];
107
                        return (
108
                            <div
109
                                className='applications-tiles argo-table-list argo-table-list--clickable row small-up-1 medium-up-2 large-up-3 xxxlarge-up-4'
110
                                ref={appContainerRef}>
111
                                {applications.map((app, i) => {
112
                                    const source = getAppDefaultSource(app);
113
                                    return (
114
                                        <div
115
                                            key={AppUtils.appInstanceName(app)}
116
                                            ref={appRef.set ? null : appRef.ref}
117
                                            className={`argo-table-list__row applications-list__entry applications-list__entry--health-${app.status.health.status} ${
118
                                                selectedApp === i ? 'applications-tiles__selected' : ''
119
                                            }`}>
120
                                            <div
121
                                                className='row applications-tiles__wrapper'
122
                                                onClick={e =>
123
                                                    ctx.navigation.goto(`/applications/${app.metadata.namespace}/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})
124
                                                }>
125
                                                <div
126
                                                    className={`columns small-12 applications-list__info qe-applications-list-${AppUtils.appInstanceName(
127
                                                        app
128
                                                    )} applications-tiles__item`}>
129
                                                    <div className='row '>
130
                                                        <div className={app.status.summary.externalURLs?.length > 0 ? 'columns small-10' : 'columns small-11'}>
131
                                                            <i className={'icon argo-icon-' + (source.chart != null ? 'helm' : 'git')} />
132
                                                            <Tooltip content={AppUtils.appInstanceName(app)}>
133
                                                                <span className='applications-list__title'>
134
                                                                    {AppUtils.appQualifiedName(app, useAuthSettingsCtx?.appsInAnyNamespaceEnabled)}
135
                                                                </span>
136
                                                            </Tooltip>
137
                                                        </div>
138
                                                        <div className={app.status.summary.externalURLs?.length > 0 ? 'columns small-2' : 'columns small-1'}>
139
                                                            <div className='applications-list__external-link'>
140
                                                                <ApplicationURLs urls={app.status.summary.externalURLs} />
141
                                                                <Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
142
                                                                    <button
143
                                                                        className='large-text-height'
144
                                                                        onClick={e => {
145
                                                                            e.stopPropagation();
146
                                                                            favList?.includes(app.metadata.name)
147
                                                                                ? favList.splice(favList.indexOf(app.metadata.name), 1)
148
                                                                                : favList.push(app.metadata.name);
149
                                                                            services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
150
                                                                        }}>
151
                                                                        <i
152
                                                                            className={favList?.includes(app.metadata.name) ? 'fas fa-star fa-lg' : 'far fa-star fa-lg'}
153
                                                                            style={{
154
                                                                                cursor: 'pointer',
155
                                                                                marginLeft: '7px',
156
                                                                                color: favList?.includes(app.metadata.name) ? '#FFCE25' : '#8fa4b1'
157
                                                                            }}
158
                                                                        />
159
                                                                    </button>
160
                                                                </Tooltip>
161
                                                            </div>
162
                                                        </div>
163
                                                    </div>
164
                                                    <div className='row'>
165
                                                        <div className='columns small-3' title='Project:'>
166
                                                            Project:
167
                                                        </div>
168
                                                        <div className='columns small-9'>{app.spec.project}</div>
169
                                                    </div>
170
                                                    <div className='row'>
171
                                                        <div className='columns small-3' title='Labels:'>
172
                                                            Labels:
173
                                                        </div>
174
                                                        <div className='columns small-9'>
175
                                                            <Tooltip
176
                                                                zIndex={4}
177
                                                                content={
178
                                                                    <div>
179
                                                                        {Object.keys(app.metadata.labels || {})
180
                                                                            .map(label => ({label, value: app.metadata.labels[label]}))
181
                                                                            .map(item => (
182
                                                                                <div key={item.label}>
183
                                                                                    {item.label}={item.value}
184
                                                                                </div>
185
                                                                            ))}
186
                                                                    </div>
187
                                                                }>
188
                                                                <span>
189
                                                                    {Object.keys(app.metadata.labels || {})
190
                                                                        .map(label => `${label}=${app.metadata.labels[label]}`)
191
                                                                        .join(', ')}
192
                                                                </span>
193
                                                            </Tooltip>
194
                                                        </div>
195
                                                    </div>
196
                                                    <div className='row'>
197
                                                        <div className='columns small-3' title='Status:'>
198
                                                            Status:
199
                                                        </div>
200
                                                        <div className='columns small-9' qe-id='applications-tiles-health-status'>
201
                                                            <AppUtils.HealthStatusIcon state={app.status.health} /> {app.status.health.status}
202
                                                            &nbsp;
203
                                                            <AppUtils.ComparisonStatusIcon status={app.status.sync.status} /> {app.status.sync.status}
204
                                                            &nbsp;
205
                                                            <OperationState app={app} quiet={true} />
206
                                                        </div>
207
                                                    </div>
208
                                                    <div className='row'>
209
                                                        <div className='columns small-3' title='Repository:'>
210
                                                            Repository:
211
                                                        </div>
212
                                                        <div className='columns small-9'>
213
                                                            <Tooltip content={source.repoURL} zIndex={4}>
214
                                                                <span>{source.repoURL}</span>
215
                                                            </Tooltip>
216
                                                        </div>
217
                                                    </div>
218
                                                    <div className='row'>
219
                                                        <div className='columns small-3' title='Target Revision:'>
220
                                                            Target Revision:
221
                                                        </div>
222
                                                        <div className='columns small-9'>{source.targetRevision || 'HEAD'}</div>
223
                                                    </div>
224
                                                    {source.path && (
225
                                                        <div className='row'>
226
                                                            <div className='columns small-3' title='Path:'>
227
                                                                Path:
228
                                                            </div>
229
                                                            <div className='columns small-9'>{source.path}</div>
230
                                                        </div>
231
                                                    )}
232
                                                    {source.chart && (
233
                                                        <div className='row'>
234
                                                            <div className='columns small-3' title='Chart:'>
235
                                                                Chart:
236
                                                            </div>
237
                                                            <div className='columns small-9'>{source.chart}</div>
238
                                                        </div>
239
                                                    )}
240
                                                    <div className='row'>
241
                                                        <div className='columns small-3' title='Destination:'>
242
                                                            Destination:
243
                                                        </div>
244
                                                        <div className='columns small-9'>
245
                                                            <Cluster server={app.spec.destination.server} name={app.spec.destination.name} />
246
                                                        </div>
247
                                                    </div>
248
                                                    <div className='row'>
249
                                                        <div className='columns small-3' title='Namespace:'>
250
                                                            Namespace:
251
                                                        </div>
252
                                                        <div className='columns small-9'>{app.spec.destination.namespace}</div>
253
                                                    </div>
254
                                                    <div className='row'>
255
                                                        <div className='columns small-3' title='Age:'>
256
                                                            Created At:
257
                                                        </div>
258
                                                        <div className='columns small-9'>{AppUtils.formatCreationTimestamp(app.metadata.creationTimestamp)}</div>
259
                                                    </div>
260
                                                    {app.status.operationState && (
261
                                                        <div className='row'>
262
                                                            <div className='columns small-3' title='Last sync:'>
263
                                                                Last Sync:
264
                                                            </div>
265
                                                            <div className='columns small-9'>
266
                                                                {AppUtils.formatCreationTimestamp(app.status.operationState.finishedAt || app.status.operationState.startedAt)}
267
                                                            </div>
268
                                                        </div>
269
                                                    )}
270
                                                    <div className='row applications-tiles__actions'>
271
                                                        <div className='columns applications-list__entry--actions'>
272
                                                            <a
273
                                                                className='argo-button argo-button--base'
274
                                                                qe-id='applications-tiles-button-sync'
275
                                                                onClick={e => {
276
                                                                    e.stopPropagation();
277
                                                                    syncApplication(app.metadata.name, app.metadata.namespace);
278
                                                                }}>
279
                                                                <i className='fa fa-sync' /> Sync
280
                                                            </a>
281
                                                            &nbsp;
282
                                                            <a
283
                                                                className='argo-button argo-button--base'
284
                                                                qe-id='applications-tiles-button-refresh'
285
                                                                {...AppUtils.refreshLinkAttrs(app)}
286
                                                                onClick={e => {
287
                                                                    e.stopPropagation();
288
                                                                    refreshApplication(app.metadata.name, app.metadata.namespace);
289
                                                                }}>
290
                                                                <i className={classNames('fa fa-redo', {'status-icon--spin': AppUtils.isAppRefreshing(app)})} />{' '}
291
                                                                <span className='show-for-xxlarge'>Refresh</span>
292
                                                            </a>
293
                                                            &nbsp;
294
                                                            <a
295
                                                                className='argo-button argo-button--base'
296
                                                                qe-id='applications-tiles-button-delete'
297
                                                                onClick={e => {
298
                                                                    e.stopPropagation();
299
                                                                    deleteApplication(app.metadata.name, app.metadata.namespace);
300
                                                                }}>
301
                                                                <i className='fa fa-times-circle' /> <span className='show-for-xxlarge'>Delete</span>
302
                                                            </a>
303
                                                        </div>
304
                                                    </div>
305
                                                </div>
306
                                            </div>
307
                                        </div>
308
                                    );
309
                                })}
310
                            </div>
311
                        );
312
                    }}
313
                </DataLoader>
314
            )}
315
        </Consumer>
316
    );
317
};
318

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.