@spinnaker/core 2026.1.1 → 2026.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/apitoken/ApiTokenService.d.ts +34 -0
  2. package/dist/apitoken/ApiTokensPage.d.ts +15 -0
  3. package/dist/apitoken/ApiTokensPageContainer.d.ts +2 -0
  4. package/dist/apitoken/CreateApiTokenModal.d.ts +20 -0
  5. package/dist/apitoken/RevokeApiTokenButton.d.ts +7 -0
  6. package/dist/apitoken/apitoken.module.d.ts +1 -0
  7. package/dist/apitoken/apitoken.states.d.ts +1 -0
  8. package/dist/apitoken/index.d.ts +6 -0
  9. package/dist/application/application.initializers.d.ts +7 -0
  10. package/dist/application/index.d.ts +2 -0
  11. package/dist/authentication/AuthenticationService.d.ts +1 -0
  12. package/dist/config/settings.d.ts +0 -3
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.js +36 -36
  15. package/dist/index.js.map +1 -1
  16. package/dist/notification/selector/types/index.d.ts +0 -1
  17. package/package.json +12 -7
  18. package/rollup.config.js +16 -0
  19. package/src/apitoken/ApiTokenService.spec.ts +199 -0
  20. package/src/apitoken/ApiTokenService.ts +65 -0
  21. package/src/apitoken/ApiTokensPage.less +81 -0
  22. package/src/apitoken/ApiTokensPage.tsx +370 -0
  23. package/src/apitoken/ApiTokensPageContainer.tsx +85 -0
  24. package/src/apitoken/CreateApiTokenModal.tsx +228 -0
  25. package/src/apitoken/RevokeApiTokenButton.tsx +79 -0
  26. package/src/apitoken/apitoken.module.ts +20 -0
  27. package/src/apitoken/apitoken.states.ts +43 -0
  28. package/src/apitoken/index.ts +20 -0
  29. package/src/application/application.initializers.spec.ts +34 -0
  30. package/src/application/application.initializers.ts +40 -0
  31. package/src/application/application.module.ts +2 -0
  32. package/src/application/index.ts +6 -0
  33. package/src/authentication/AuthenticationInitializer.spec.ts +16 -0
  34. package/src/authentication/AuthenticationInitializer.ts +4 -0
  35. package/src/authentication/AuthenticationService.spec.ts +18 -0
  36. package/src/authentication/AuthenticationService.ts +3 -0
  37. package/src/authentication/userMenu/UserMenu.tsx +17 -3
  38. package/src/config/settings.ts +0 -1
  39. package/src/core.module.ts +2 -0
  40. package/src/index.ts +1 -0
  41. package/src/notification/notification.types.ts +0 -2
  42. package/src/notification/selector/types/index.ts +0 -1
  43. package/src/notification/selector/types/microsoftteams/MicrosoftTeamsNotificationType.tsx +1 -1
  44. package/dist/notification/selector/types/bearychat/BearychatNotificationType.d.ts +0 -5
  45. package/dist/notification/selector/types/bearychat/beary.notification.d.ts +0 -2
  46. package/src/notification/selector/types/bearychat/BearychatNotificationType.tsx +0 -19
  47. package/src/notification/selector/types/bearychat/beary.notification.ts +0 -8
@@ -0,0 +1,79 @@
1
+ // Copyright 2026 DoorDash, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import React, { useState } from 'react';
16
+ import { Modal } from 'react-bootstrap';
17
+
18
+ import { ApiTokenService } from './ApiTokenService';
19
+
20
+ export interface IRevokeApiTokenButtonProps {
21
+ tokenId: string;
22
+ tokenName: string;
23
+ onRevoked: () => void;
24
+ }
25
+
26
+ export function RevokeApiTokenButton({ tokenId, tokenName, onRevoked }: IRevokeApiTokenButtonProps) {
27
+ const [showModal, setShowModal] = useState(false);
28
+ const [revoking, setRevoking] = useState(false);
29
+ const [error, setError] = useState<string | null>(null);
30
+
31
+ const handleRevoke = () => {
32
+ setRevoking(true);
33
+ setError(null);
34
+ ApiTokenService.revokeToken(tokenId)
35
+ .then(() => {
36
+ setShowModal(false);
37
+ onRevoked();
38
+ })
39
+ .catch(() => {
40
+ setRevoking(false);
41
+ setError('Failed to revoke token. Please try again.');
42
+ });
43
+ };
44
+
45
+ return (
46
+ <>
47
+ <button className="btn btn-default btn-xs" onClick={() => setShowModal(true)}>
48
+ Revoke
49
+ </button>
50
+
51
+ <Modal show={showModal} onHide={() => !revoking && setShowModal(false)} bsSize="small">
52
+ <Modal.Header closeButton={!revoking}>
53
+ <Modal.Title>Revoke token</Modal.Title>
54
+ </Modal.Header>
55
+ <Modal.Body>
56
+ {error && (
57
+ <div className="alert alert-danger" role="alert" style={{ marginBottom: 12 }}>
58
+ {error}
59
+ </div>
60
+ )}
61
+ <p>
62
+ Are you sure you want to revoke <strong>{tokenName}</strong>?
63
+ </p>
64
+ <p className="text-muted" style={{ fontSize: 13, marginBottom: 0 }}>
65
+ This cannot be undone. Any automation using this token will stop working immediately.
66
+ </p>
67
+ </Modal.Body>
68
+ <Modal.Footer>
69
+ <button className="btn btn-default" onClick={() => setShowModal(false)} disabled={revoking}>
70
+ Cancel
71
+ </button>
72
+ <button className="btn btn-danger" onClick={handleRevoke} disabled={revoking}>
73
+ {revoking ? 'Revoking…' : 'Revoke token'}
74
+ </button>
75
+ </Modal.Footer>
76
+ </Modal>
77
+ </>
78
+ );
79
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright 2026 DoorDash, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import { module } from 'angular';
16
+
17
+ import { APITOKEN_STATES } from './apitoken.states';
18
+
19
+ export const APITOKEN_MODULE = 'spinnaker.core.apitoken';
20
+ module(APITOKEN_MODULE, [APITOKEN_STATES]);
@@ -0,0 +1,43 @@
1
+ // Copyright 2026 DoorDash, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import { module } from 'angular';
16
+
17
+ import { ApiTokensPageContainer } from './ApiTokensPageContainer';
18
+ import type { INestedState, StateConfigProvider } from '../navigation/state.provider';
19
+ import { STATE_CONFIG_PROVIDER } from '../navigation/state.provider';
20
+
21
+ export const APITOKEN_STATES = 'spinnaker.core.apitoken.states';
22
+ module(APITOKEN_STATES, [STATE_CONFIG_PROVIDER]).config([
23
+ 'stateConfigProvider',
24
+ (stateConfigProvider: StateConfigProvider) => {
25
+ const apiTokens: INestedState = {
26
+ name: 'apiTokens',
27
+ url: '/api-tokens',
28
+ views: {
29
+ 'main@': {
30
+ component: ApiTokensPageContainer,
31
+ $type: 'react',
32
+ },
33
+ },
34
+ data: {
35
+ pageTitleMain: {
36
+ label: 'API Tokens',
37
+ },
38
+ },
39
+ };
40
+
41
+ stateConfigProvider.addToRootState(apiTokens);
42
+ },
43
+ ]);
@@ -0,0 +1,20 @@
1
+ // Copyright 2026 DoorDash, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ export * from './ApiTokenService';
16
+ export * from './ApiTokensPage';
17
+ export * from './ApiTokensPageContainer';
18
+ export * from './CreateApiTokenModal';
19
+ export * from './RevokeApiTokenButton';
20
+ export * from './apitoken.module';
@@ -0,0 +1,34 @@
1
+ import {
2
+ applyApplicationInitializers,
3
+ registerApplicationInitializer,
4
+ resetApplicationInitializersForTests,
5
+ } from './application.initializers';
6
+
7
+ describe('application.initializers', () => {
8
+ beforeEach(() => resetApplicationInitializersForTests());
9
+
10
+ it('applies registered initializers once for the current context', () => {
11
+ const applicationState = {} as any;
12
+ const uiRouter = {} as any;
13
+ const initializer = jasmine.createSpy('initializer');
14
+
15
+ registerApplicationInitializer(initializer);
16
+ applyApplicationInitializers(applicationState, uiRouter);
17
+ applyApplicationInitializers(applicationState, uiRouter);
18
+
19
+ expect(initializer).toHaveBeenCalledTimes(1);
20
+ expect(initializer).toHaveBeenCalledWith(applicationState, uiRouter);
21
+ });
22
+
23
+ it('runs late registrations immediately after the context has been applied', () => {
24
+ const applicationState = {} as any;
25
+ const uiRouter = {} as any;
26
+ const initializer = jasmine.createSpy('initializer');
27
+
28
+ applyApplicationInitializers(applicationState, uiRouter);
29
+ registerApplicationInitializer(initializer);
30
+
31
+ expect(initializer).toHaveBeenCalledTimes(1);
32
+ expect(initializer).toHaveBeenCalledWith(applicationState, uiRouter);
33
+ });
34
+ });
@@ -0,0 +1,40 @@
1
+ import type { UIRouter } from '@uirouter/core';
2
+ import { module } from 'angular';
3
+
4
+ import type { ApplicationStateProvider } from './application.state.provider';
5
+
6
+ export type ApplicationInitializer = (applicationState: ApplicationStateProvider, uiRouter: UIRouter) => void;
7
+
8
+ const initializers: ApplicationInitializer[] = [];
9
+ let appliedContext: { applicationState: ApplicationStateProvider; uiRouter: UIRouter } | null = null;
10
+
11
+ export function registerApplicationInitializer(initializer: ApplicationInitializer): void {
12
+ initializers.push(initializer);
13
+ if (appliedContext) {
14
+ initializer(appliedContext.applicationState, appliedContext.uiRouter);
15
+ }
16
+ }
17
+
18
+ export function applyApplicationInitializers(applicationState: ApplicationStateProvider, uiRouter: UIRouter): void {
19
+ if (appliedContext?.applicationState === applicationState && appliedContext?.uiRouter === uiRouter) {
20
+ return;
21
+ }
22
+
23
+ appliedContext = { applicationState, uiRouter };
24
+ initializers.forEach((initializer) => initializer(applicationState, uiRouter));
25
+ }
26
+
27
+ export function resetApplicationInitializersForTests(): void {
28
+ initializers.length = 0;
29
+ appliedContext = null;
30
+ }
31
+
32
+ export const APPLICATION_INITIALIZERS_MODULE = 'spinnaker.core.application.initializers';
33
+
34
+ module(APPLICATION_INITIALIZERS_MODULE, []).run([
35
+ 'applicationState',
36
+ '$uiRouter',
37
+ (applicationState: ApplicationStateProvider, uiRouter: UIRouter) => {
38
+ applyApplicationInitializers(applicationState, uiRouter);
39
+ },
40
+ ]);
@@ -1,5 +1,6 @@
1
1
  import { module } from 'angular';
2
2
 
3
+ import { APPLICATION_INITIALIZERS_MODULE } from './application.initializers';
3
4
  import { APPLICATION_STATE_PROVIDER } from './application.state.provider';
4
5
  import './applicationSearchResultType';
5
6
  import { APPLICATIONS_STATE_PROVIDER } from './applications.state.provider';
@@ -14,6 +15,7 @@ import './nav/defaultCategories';
14
15
  export const APPLICATION_MODULE = 'spinnaker.core.application';
15
16
  module(APPLICATION_MODULE, [
16
17
  APPLICATION_STATE_PROVIDER,
18
+ APPLICATION_INITIALIZERS_MODULE,
17
19
  APPLICATIONS_STATE_PROVIDER,
18
20
  CORE_APPLICATION_CONFIG_APPLICATIONCONFIG_CONTROLLER,
19
21
  CORE_APPLICATION_MODAL_CREATEAPPLICATION_MODAL_CONTROLLER,
@@ -1,5 +1,11 @@
1
1
  export * from './ApplicationContext';
2
2
  export * from './ApplicationIcon';
3
+ export type { ApplicationInitializer } from './application.initializers';
4
+ export {
5
+ APPLICATION_INITIALIZERS_MODULE,
6
+ applyApplicationInitializers,
7
+ registerApplicationInitializer,
8
+ } from './application.initializers';
3
9
  export * from './application.model';
4
10
  export * from './application.state.provider';
5
11
  export * from './applicationModel.builder';
@@ -46,6 +46,22 @@ describe('authenticationProvider: application startup', function () {
46
46
  expect(AuthenticationService.getAuthenticatedUser().authenticated).toBe(true);
47
47
  });
48
48
 
49
+ it('threads canMintApiTokens from the auth response onto the authenticated user', function () {
50
+ $httpBackend.whenGET(SETTINGS.authEndpoint).respond(200, { username: 'joe!', canMintApiTokens: true });
51
+ $timeout.flush();
52
+ $httpBackend.flush();
53
+
54
+ expect(AuthenticationService.getAuthenticatedUser().canMintApiTokens).toBe(true);
55
+ });
56
+
57
+ it('defaults canMintApiTokens to false when the auth response omits it', function () {
58
+ $httpBackend.whenGET(SETTINGS.authEndpoint).respond(200, { username: 'joe!' });
59
+ $timeout.flush();
60
+ $httpBackend.flush();
61
+
62
+ expect(AuthenticationService.getAuthenticatedUser().canMintApiTokens).toBe(false);
63
+ });
64
+
49
65
  it('requests authentication from gate, then opens modal and redirects on 401', function () {
50
66
  $httpBackend.whenGET(SETTINGS.authEndpoint).respond(401, null, { 'X-AUTH-REDIRECT-URL': '/authUp' });
51
67
  $rootScope.$digest();
@@ -11,6 +11,7 @@ import { ModalInjector } from '../reactShims/modal.injector';
11
11
  interface IAuthResponse {
12
12
  username: string;
13
13
  roles?: string[];
14
+ canMintApiTokens?: boolean;
14
15
  }
15
16
 
16
17
  export class AuthenticationInitializer {
@@ -26,6 +27,7 @@ export class AuthenticationInitializer {
26
27
  name: response.data.username,
27
28
  authenticated: false,
28
29
  roles: response.data.roles,
30
+ canMintApiTokens: response.data.canMintApiTokens,
29
31
  });
30
32
  ModalInjector.modalStackService.dismissAll();
31
33
  this.visibilityWatch.unsubscribe();
@@ -65,6 +67,7 @@ export class AuthenticationInitializer {
65
67
  name: response.data.username,
66
68
  authenticated: false,
67
69
  roles: response.data.roles,
70
+ canMintApiTokens: response.data.canMintApiTokens,
68
71
  });
69
72
  $rootScope.authenticating = false;
70
73
  } else {
@@ -85,6 +88,7 @@ export class AuthenticationInitializer {
85
88
  name: response.data.username,
86
89
  authenticated: false,
87
90
  roles: response.data.roles,
91
+ canMintApiTokens: response.data.canMintApiTokens,
88
92
  });
89
93
  $rootScope.authenticating = false;
90
94
  this.userLoggedOut = false;
@@ -16,6 +16,24 @@ describe('AuthenticationService', function () {
16
16
  expect(user.authenticated).toBe(true);
17
17
  });
18
18
 
19
+ it('defaults canMintApiTokens to false', function () {
20
+ let user: IUser = AuthenticationService.getAuthenticatedUser();
21
+ expect(user.canMintApiTokens).toBe(false);
22
+
23
+ AuthenticationService.setAuthenticatedUser({ name: 'kato@example.com', authenticated: false });
24
+ user = AuthenticationService.getAuthenticatedUser();
25
+ expect(user.canMintApiTokens).toBe(false);
26
+ });
27
+
28
+ it('stores canMintApiTokens when provided', function () {
29
+ AuthenticationService.setAuthenticatedUser({
30
+ name: 'kato@example.com',
31
+ authenticated: false,
32
+ canMintApiTokens: true,
33
+ });
34
+ expect(AuthenticationService.getAuthenticatedUser().canMintApiTokens).toBe(true);
35
+ });
36
+
19
37
  it('disregards falsy values', function () {
20
38
  const user: IUser = AuthenticationService.getAuthenticatedUser();
21
39
 
@@ -3,12 +3,14 @@ export interface IUser {
3
3
  authenticated: boolean;
4
4
  roles?: string[];
5
5
  lastAuthenticated?: number;
6
+ canMintApiTokens?: boolean;
6
7
  }
7
8
 
8
9
  const defaultUser: IUser = {
9
10
  name: '[anonymous]',
10
11
  roles: [],
11
12
  authenticated: false,
13
+ canMintApiTokens: false,
12
14
  };
13
15
 
14
16
  export class AuthenticationService {
@@ -26,6 +28,7 @@ export class AuthenticationService {
26
28
  this.user.authenticated = true;
27
29
  this.user.lastAuthenticated = new Date().getTime();
28
30
  this.user.roles = authenticatedUser.roles;
31
+ this.user.canMintApiTokens = authenticatedUser.canMintApiTokens ?? false;
29
32
  }
30
33
 
31
34
  this.authEvents.forEach((event: Function) => event());
@@ -1,3 +1,4 @@
1
+ import { UISref } from '@uirouter/react';
1
2
  import * as React from 'react';
2
3
  import { Dropdown } from 'react-bootstrap';
3
4
 
@@ -10,6 +11,7 @@ import './userMenu.less';
10
11
  export const UserMenu = () => {
11
12
  const authenticatedUser = AuthenticationService.getAuthenticatedUser();
12
13
  const showLogOutDropdown = authenticatedUser.authenticated;
14
+ const canMintApiTokens = authenticatedUser.canMintApiTokens ?? false;
13
15
 
14
16
  if (!SETTINGS.authEnabled) {
15
17
  return null;
@@ -23,9 +25,21 @@ export const UserMenu = () => {
23
25
  <span className="hidden-xs hidden-sm hidden-md">{authenticatedUser.name}</span>
24
26
  </Dropdown.Toggle>
25
27
  {showLogOutDropdown && (
26
- <Dropdown.Menu>
27
- <li className="sp-padding-xs" onClick={() => AuthenticationInitializer.logOut()}>
28
- Log Out
28
+ <Dropdown.Menu pullRight>
29
+ {canMintApiTokens && (
30
+ <>
31
+ <li role="presentation">
32
+ <UISref to="home.apiTokens">
33
+ <a role="menuitem">API Tokens</a>
34
+ </UISref>
35
+ </li>
36
+ <li role="presentation" className="divider" />
37
+ </>
38
+ )}
39
+ <li role="presentation">
40
+ <a role="menuitem" style={{ cursor: 'pointer' }} onClick={() => AuthenticationInitializer.logOut()}>
41
+ Log Out
42
+ </a>
29
43
  </li>
30
44
  </Dropdown.Menu>
31
45
  )}
@@ -13,7 +13,6 @@ export interface IProviderSettings {
13
13
  }
14
14
 
15
15
  export interface INotificationSettings {
16
- bearychat: { enabled: boolean };
17
16
  email: { enabled: boolean };
18
17
  githubStatus: { enabled: boolean };
19
18
  googlechat: { enabled: boolean };
@@ -26,6 +26,7 @@ import { RECENT_HISTORY_SERVICE } from './history/recentHistory.service';
26
26
  import './analytics/GoogleAnalyticsInitializer';
27
27
  import { UI_ROUTER_REACT_ERROR_BOUNDARY } from './presentation/SpinErrorBoundary';
28
28
  import { ANALYTICS_MODULE } from './analytics/angulartics.module';
29
+ import { APITOKEN_MODULE } from './apitoken/apitoken.module';
29
30
  import { APPLICATION_BOOTSTRAP_MODULE } from './bootstrap';
30
31
  import { APPLICATION_MODULE } from './application/application.module';
31
32
  import { ARTIFACT_MODULE } from './artifact/artifact.module';
@@ -107,6 +108,7 @@ module(CORE_MODULE, [
107
108
  angularSpinner.name,
108
109
 
109
110
  ANALYTICS_MODULE,
111
+ APITOKEN_MODULE,
110
112
  APPLICATION_MODULE,
111
113
  APPLICATION_BOOTSTRAP_MODULE,
112
114
  ARTIFACT_MODULE,
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import './utils/failedToInstantiateModule';
4
4
 
5
5
  export * from './account';
6
6
  export * from './api';
7
+ export * from './apitoken';
7
8
  export * from './application';
8
9
  export * from './artifact';
9
10
  export * from './authentication';
@@ -5,7 +5,6 @@ import { SETTINGS } from '../config';
5
5
  import type { INotificationTypeConfig } from '../domain';
6
6
  import { Registry } from '../registry';
7
7
 
8
- import { bearyChatNotification } from './selector/types/bearychat/beary.notification';
9
8
  import { cdEventsNotification } from './selector/types/cdevents/cdevents.notification';
10
9
  import { emailNotification } from './selector/types/email/email.notification';
11
10
  import { githubstatusNotification } from './selector/types/githubstatus/githubstatus.notification';
@@ -16,7 +15,6 @@ import { slackNotification } from './selector/types/slack/slack.notification';
16
15
  import { smsNotification } from './selector/types/sms/sms.notification';
17
16
 
18
17
  [
19
- bearyChatNotification,
20
18
  emailNotification,
21
19
  githubstatusNotification,
22
20
  googlechatNotification,
@@ -1,4 +1,3 @@
1
- export * from './bearychat/BearychatNotificationType';
2
1
  export * from './email/EmailNotificationType';
3
2
  export * from './googlechat/GooglechatNotificationType';
4
3
  export * from './microsoftteams/MicrosoftTeamsNotificationType';
@@ -14,7 +14,7 @@ export class MicrosoftTeamsNotificationType extends React.Component<INotificatio
14
14
  <TextInput
15
15
  inputClassName={'form-control input-sm'}
16
16
  {...props}
17
- placeholder="URL starts with https://outlook.office.com/webhook/"
17
+ placeholder="URL starts with https://[region].webhook.office.com/webhookb2/"
18
18
  />
19
19
  )}
20
20
  required={true}
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
- import type { INotificationTypeCustomConfig } from '../../../../domain';
3
- export declare class BearychatNotificationType extends React.Component<INotificationTypeCustomConfig> {
4
- render(): JSX.Element;
5
- }
@@ -1,2 +0,0 @@
1
- import type { INotificationTypeConfig } from '../../../../domain';
2
- export declare const bearyChatNotification: INotificationTypeConfig;
@@ -1,19 +0,0 @@
1
- import React from 'react';
2
-
3
- import type { INotificationTypeCustomConfig } from '../../../../domain';
4
- import { FormikFormField, TextInput, Validators } from '../../../../presentation';
5
-
6
- export class BearychatNotificationType extends React.Component<INotificationTypeCustomConfig> {
7
- public render() {
8
- const { fieldName } = this.props;
9
- return (
10
- <FormikFormField
11
- label="Email Address"
12
- name={fieldName ? `${fieldName}.address` : 'address'}
13
- validate={Validators.emailValue('Please enter a valid email address')}
14
- input={(props) => <TextInput inputClassName={'form-control input-sm'} {...props} />}
15
- required={true}
16
- />
17
- );
18
- }
19
- }
@@ -1,8 +0,0 @@
1
- import { BearychatNotificationType } from './BearychatNotificationType';
2
- import type { INotificationTypeConfig } from '../../../../domain';
3
-
4
- export const bearyChatNotification: INotificationTypeConfig = {
5
- component: BearychatNotificationType,
6
- key: 'bearychat',
7
- label: 'Bearychat',
8
- };