argo-cd

Форк
0
/
edit-notification-subscriptions.tsx 
220 строк · 10.1 Кб
1
import {Autocomplete} from 'argo-ui';
2
import * as React from 'react';
3
import {DataLoader} from '../../../shared/components';
4
import * as models from '../../../shared/models';
5
import {services} from '../../../shared/services';
6

7
import {ApplicationSummaryProps} from './application-summary';
8

9
import './edit-notification-subscriptions.scss';
10

11
export const NOTIFICATION_SUBSCRIPTION_ANNOTATION_PREFIX = 'notifications.argoproj.io/subscribe';
12

13
export const NOTIFICATION_SUBSCRIPTION_ANNOTATION_REGEX = new RegExp(`^notifications\.argoproj\.io\/subscribe\.[a-zA-Z-]{1,100}\.[a-zA-Z-]{1,100}$`);
14

15
export type TNotificationSubscription = {
16
    trigger: string;
17
    // notification service name
18
    service: string;
19
    // a semicolon separated list of recipients
20
    value: string;
21
};
22

23
export const notificationSubscriptionsParser = {
24
    annotationsToSubscriptions: (annotations: models.Application['metadata']['annotations']): TNotificationSubscription[] => {
25
        const subscriptions: TNotificationSubscription[] = [];
26

27
        for (const [key, value] of Object.entries(annotations || {})) {
28
            if (NOTIFICATION_SUBSCRIPTION_ANNOTATION_REGEX.test(key)) {
29
                try {
30
                    const [trigger, service] = key.slice(NOTIFICATION_SUBSCRIPTION_ANNOTATION_PREFIX.length + 1 /* for dot "." */).split('.');
31

32
                    subscriptions.push({trigger, service, value});
33
                } catch (e) {
34
                    // console.error(`annotationsToSubscriptions parsing issue for ${key}`);
35
                    throw new Error(e);
36
                }
37
            }
38
        }
39

40
        return subscriptions;
41
    },
42
    subscriptionsToAnnotations: (subscriptions: TNotificationSubscription[]): models.Application['metadata']['annotations'] => {
43
        const annotations: models.Application['metadata']['annotations'] = {};
44

45
        for (const subscription of subscriptions || []) {
46
            annotations[notificationSubscriptionsParser.subscriptionToAnnotationKey(subscription)] = subscription.value;
47
        }
48

49
        return annotations;
50
    },
51
    subscriptionToAnnotationKey: (subscription: TNotificationSubscription): string =>
52
        `${NOTIFICATION_SUBSCRIPTION_ANNOTATION_PREFIX}.${subscription.trigger}.${subscription.service}`
53
};
54

55
/**
56
 * split the notification subscription related annotation to have it in seperate edit field
57
 * this hook will emit notification subscription state, controller & merge utility to core annotations helpful when final submit
58
 */
59
export const useEditNotificationSubscriptions = (annotations: models.Application['metadata']['annotations']) => {
60
    const [subscriptions, setSubscriptions] = React.useState(notificationSubscriptionsParser.annotationsToSubscriptions(annotations));
61

62
    const onAddNewSubscription = () => {
63
        const lastSubscription = subscriptions[subscriptions.length - 1];
64

65
        if (subscriptions.length === 0 || lastSubscription.trigger || lastSubscription.service || lastSubscription.value) {
66
            setSubscriptions([
67
                ...subscriptions,
68
                {
69
                    trigger: '',
70
                    service: '',
71
                    value: ''
72
                }
73
            ]);
74
        }
75
    };
76

77
    const onEditSubscription = (idx: number, subscription: TNotificationSubscription) => {
78
        const existingSubscription = subscriptions.findIndex((sub, toFindIdx) => toFindIdx !== idx && sub.service === subscription.service && sub.trigger === subscription.trigger);
79
        let newSubscriptions = [...subscriptions];
80

81
        if (existingSubscription !== -1) {
82
            // remove existing subscription
83
            newSubscriptions = newSubscriptions.filter((_, newSubscriptionIdx) => newSubscriptionIdx !== existingSubscription);
84
            // decrement index because one value is removed
85
            idx--;
86
        }
87

88
        if (idx === -1) {
89
            newSubscriptions = [subscription];
90
        } else {
91
            newSubscriptions = newSubscriptions.map((oldSubscription, oldSubscriptionIdx) => (oldSubscriptionIdx === idx ? subscription : oldSubscription));
92
        }
93

94
        setSubscriptions(newSubscriptions);
95
    };
96

97
    const onRemoveSubscription = (idx: number) => idx >= 0 && setSubscriptions(subscriptions.filter((_, i) => i !== idx));
98

99
    const withNotificationSubscriptions = (updateApp: ApplicationSummaryProps['updateApp']) => (...args: Parameters<ApplicationSummaryProps['updateApp']>) => {
100
        const app = args[0];
101

102
        const notificationSubscriptionsRaw = notificationSubscriptionsParser.subscriptionsToAnnotations(subscriptions);
103

104
        if (Object.keys(notificationSubscriptionsRaw)?.length) {
105
            app.metadata.annotations = {
106
                ...notificationSubscriptionsRaw,
107
                ...(app.metadata.annotations || {})
108
            };
109
        }
110

111
        return updateApp(app, args[1]);
112
    };
113

114
    const onResetNotificationSubscriptions = () => setSubscriptions(notificationSubscriptionsParser.annotationsToSubscriptions(annotations));
115

116
    return {
117
        /**
118
         * abstraction of notification subscription annotations in edit view
119
         */
120
        subscriptions,
121
        onAddNewSubscription,
122
        onEditSubscription,
123
        onRemoveSubscription,
124
        /**
125
         * merge abstracted 'subscriptions' into core 'metadata.annotations' in form submit
126
         */
127
        withNotificationSubscriptions,
128
        onResetNotificationSubscriptions
129
    };
130
};
131

132
export interface EditNotificationSubscriptionsProps extends ReturnType<typeof useEditNotificationSubscriptions> {}
133

134
export const EditNotificationSubscriptions = ({subscriptions, onAddNewSubscription, onEditSubscription, onRemoveSubscription}: EditNotificationSubscriptionsProps) => {
135
    return (
136
        <div className='edit-notification-subscriptions argo-field'>
137
            {subscriptions.map((subscription, idx) => (
138
                <div className='edit-notification-subscriptions__subscription' key={idx}>
139
                    <input className='argo-field edit-notification-subscriptions__input-prefix' disabled={true} value={NOTIFICATION_SUBSCRIPTION_ANNOTATION_PREFIX} />
140
                    <b>&nbsp;.&nbsp;</b>
141
                    <DataLoader load={() => services.notification.listTriggers().then(triggers => triggers.map(trigger => trigger.name))}>
142
                        {triggersList => (
143
                            <Autocomplete
144
                                wrapperProps={{
145
                                    className: 'argo-field edit-notification-subscriptions__autocomplete-wrapper'
146
                                }}
147
                                inputProps={{
148
                                    className: 'argo-field',
149
                                    placeholder: 'on-sync-running',
150
                                    title: 'Trigger'
151
                                }}
152
                                value={subscription.trigger}
153
                                onChange={e => {
154
                                    onEditSubscription(idx, {
155
                                        ...subscription,
156
                                        trigger: e.target.value
157
                                    });
158
                                }}
159
                                items={triggersList}
160
                                onSelect={trigger => onEditSubscription(idx, {...subscription, trigger})}
161
                                filterSuggestions={true}
162
                                qeid='application-edit-notification-subscription-trigger'
163
                            />
164
                        )}
165
                    </DataLoader>
166
                    <b>&nbsp;.&nbsp;</b>
167
                    <DataLoader load={() => services.notification.listServices().then(_services => _services.map(service => service.name))}>
168
                        {serviceList => (
169
                            <Autocomplete
170
                                wrapperProps={{
171
                                    className: 'argo-field edit-notification-subscriptions__autocomplete-wrapper'
172
                                }}
173
                                inputProps={{
174
                                    className: 'argo-field',
175
                                    placeholder: 'slack',
176
                                    title: 'Service'
177
                                }}
178
                                value={subscription.service}
179
                                onChange={e => {
180
                                    onEditSubscription(idx, {
181
                                        ...subscription,
182
                                        service: e.target.value
183
                                    });
184
                                }}
185
                                items={serviceList}
186
                                onSelect={service => onEditSubscription(idx, {...subscription, service})}
187
                                filterSuggestions={true}
188
                                qeid='application-edit-notification-subscription-service'
189
                            />
190
                        )}
191
                    </DataLoader>
192
                    &nbsp;=&nbsp;
193
                    <input
194
                        autoComplete='fake'
195
                        className='argo-field'
196
                        placeholder='my-channel1; my-channel2'
197
                        title='Value'
198
                        value={subscription.value}
199
                        onChange={e => {
200
                            onEditSubscription(idx, {
201
                                ...subscription,
202
                                value: e.target.value
203
                            });
204
                        }}
205
                        qe-id='application-edit-notification-subscription-value'
206
                    />
207
                    <button className='button-close'>
208
                        <i className='fa fa-times' style={{cursor: 'pointer'}} onClick={() => onRemoveSubscription(idx)} />
209
                    </button>
210
                </div>
211
            ))}
212
            {subscriptions.length === 0 && <label>No items</label>}
213
            <div>
214
                <button className='argo-button argo-button--base argo-button--short' onClick={() => onAddNewSubscription()}>
215
                    <i className='fa fa-plus' style={{cursor: 'pointer'}} />
216
                </button>
217
            </div>
218
        </div>
219
    );
220
};
221

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

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

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

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