ng-configcat-publicapi-ui 3.0.8 → 4.0.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 (136) hide show
  1. package/esm2022/lib/_directives/input-display-normalizer.directive.mjs +38 -0
  2. package/esm2022/lib/_models/flag-state.mjs +2 -0
  3. package/esm2022/lib/_models/setting-value-formgroup.mjs +2 -0
  4. package/esm2022/lib/_models/user-comparator.mjs +100 -0
  5. package/esm2022/lib/_services/app-data-adapter.mjs +18 -0
  6. package/esm2022/lib/_services/comparison-value-list-helper.mjs +72 -0
  7. package/esm2022/lib/_services/date-helper.mjs +56 -0
  8. package/esm2022/lib/_services/form-generator.mjs +359 -0
  9. package/esm2022/lib/_services/form-helper.mjs +107 -0
  10. package/esm2022/lib/_services/messaging.service.mjs +26 -0
  11. package/esm2022/lib/_services/public-api.service.mjs +77 -0
  12. package/esm2022/lib/_services/setting-list-form-helper.mjs +171 -0
  13. package/esm2022/lib/_services/tracking.directive.mjs +16 -0
  14. package/esm2022/lib/ace-editor/ace-editor.component.mjs +137 -0
  15. package/esm2022/lib/authorization/authorization.component.mjs +62 -0
  16. package/{esm2020 → esm2022}/lib/base/base-select.component.mjs +4 -4
  17. package/esm2022/lib/base/base.component.mjs +48 -0
  18. package/esm2022/lib/bootstrap.mjs +10 -0
  19. package/{esm2020 → esm2022}/lib/configuration.mjs +4 -4
  20. package/esm2022/lib/dialogs/confirmation-dialog/confirmation-dialog.mjs +28 -0
  21. package/{esm2020 → esm2022}/lib/dialogs/delete-setting-dialog/delete-setting-dialog.component.mjs +6 -6
  22. package/esm2022/lib/dialogs/expand-dialog/expand-dialog.component.mjs +80 -0
  23. package/esm2022/lib/dialogs/info-dialog/info-dialog.mjs +29 -0
  24. package/esm2022/lib/dialogs/reason-dialog/reason-dialog.component.mjs +36 -0
  25. package/{esm2020 → esm2022}/lib/dialogs/save-snackbar/save-snackbar.component.mjs +5 -5
  26. package/esm2022/lib/ng-configcat-publicapi-ui.module.mjs +285 -0
  27. package/esm2022/lib/selects/config-select/config-select.component.mjs +60 -0
  28. package/esm2022/lib/selects/environment-select/environment-select.component.mjs +47 -0
  29. package/esm2022/lib/selects/product-select/product-select.component.mjs +40 -0
  30. package/esm2022/lib/selects/setting-select/setting-select.component.mjs +47 -0
  31. package/esm2022/lib/setting-item/setting-item.component.mjs +118 -0
  32. package/esm2022/lib/setting-list/setting/rollout-percentage-items/rollout-percentage-items.component.mjs +81 -0
  33. package/esm2022/lib/setting-list/setting/rollout-rules/rollout-rules.component.mjs +293 -0
  34. package/{esm2020 → esm2022}/lib/setting-list/setting/setting.component.mjs +5 -5
  35. package/esm2022/lib/setting-list/setting/value/value.component.mjs +37 -0
  36. package/esm2022/lib/setting-list/setting-list.component.mjs +194 -0
  37. package/esm2022/lib/v2/feature-flag/date-time-picker/date-time-picker.component.mjs +123 -0
  38. package/esm2022/lib/v2/feature-flag/dependees-dialog/dependees-dialog.component.mjs +30 -0
  39. package/esm2022/lib/v2/feature-flag/evaluation-formula/evaluation-formula.component.mjs +220 -0
  40. package/esm2022/lib/v2/feature-flag/evaluation-formula/feature-flag-value/feature-flag-value.component.mjs +61 -0
  41. package/esm2022/lib/v2/feature-flag/evaluation-formula/popout-text-editor-dialog/popout-text-editor-dialog.component.mjs +72 -0
  42. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/condition-chip/condition-chip.component.mjs +25 -0
  43. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/conditions.component.mjs +105 -0
  44. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/prerequisite-flag-condition/prerequisite-flag-condition.component.mjs +75 -0
  45. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/segment-condition/segment-condition.component.mjs +48 -0
  46. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/comparator-dialog/comparator-dialog.component.mjs +113 -0
  47. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/popout-list-editor-dialog/popout-list-editor-dialog.component.mjs +251 -0
  48. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/user-condition.component.mjs +444 -0
  49. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/percentage-options/percentage-options.component.mjs +84 -0
  50. package/esm2022/lib/v2/feature-flag/evaluation-formula/targeting-rule/targeting-rule.component.mjs +129 -0
  51. package/esm2022/lib/v2/feature-flag/feature-flag.component.mjs +190 -0
  52. package/esm2022/lib/v2/feature-flag/percentage-evaluation-attribute-dialog/percentage-evaluation-attribute-dialog.component.mjs +65 -0
  53. package/esm2022/lib/v2/feature-flag-item.component.mjs +319 -0
  54. package/{esm2020 → esm2022}/public-api.mjs +2 -1
  55. package/fesm2022/ng-configcat-publicapi-ui.mjs +4790 -0
  56. package/fesm2022/ng-configcat-publicapi-ui.mjs.map +1 -0
  57. package/lib/_models/flag-state.d.ts +20 -0
  58. package/lib/_models/setting-value-formgroup.d.ts +69 -0
  59. package/lib/_models/user-comparator.d.ts +84 -0
  60. package/lib/_services/app-data-adapter.d.ts +7 -0
  61. package/lib/_services/comparison-value-list-helper.d.ts +17 -0
  62. package/lib/_services/date-helper.d.ts +6 -0
  63. package/lib/_services/form-generator.d.ts +59 -0
  64. package/lib/_services/form-helper.d.ts +4 -1
  65. package/lib/_services/messaging.service.d.ts +12 -0
  66. package/lib/_services/public-api.service.d.ts +2 -1
  67. package/lib/_services/setting-list-form-helper.d.ts +1 -1
  68. package/lib/_services/tracking.directive.d.ts +6 -0
  69. package/lib/ace-editor/ace-editor.component.d.ts +32 -0
  70. package/lib/authorization/authorization.component.d.ts +2 -2
  71. package/lib/base/base-select.component.d.ts +1 -1
  72. package/lib/base/base.component.d.ts +2 -1
  73. package/lib/bootstrap.d.ts +12 -0
  74. package/lib/dialogs/confirmation-dialog/confirmation-dialog.d.ts +19 -0
  75. package/lib/dialogs/info-dialog/info-dialog.d.ts +17 -0
  76. package/lib/ng-configcat-publicapi-ui.module.d.ts +47 -19
  77. package/lib/selects/config-select/config-select.component.d.ts +1 -1
  78. package/lib/selects/environment-select/environment-select.component.d.ts +1 -1
  79. package/lib/selects/product-select/product-select.component.d.ts +1 -1
  80. package/lib/selects/setting-select/setting-select.component.d.ts +1 -1
  81. package/lib/setting-item/setting-item.component.d.ts +4 -2
  82. package/lib/setting-list/setting/rollout-percentage-items/rollout-percentage-items.component.d.ts +1 -1
  83. package/lib/setting-list/setting/rollout-rules/rollout-rules.component.d.ts +4 -4
  84. package/lib/setting-list/setting/setting.component.d.ts +1 -1
  85. package/lib/setting-list/setting/value/value.component.d.ts +1 -1
  86. package/lib/setting-list/setting-list.component.d.ts +1 -1
  87. package/lib/v2/feature-flag/date-time-picker/date-time-picker.component.d.ts +25 -0
  88. package/lib/v2/feature-flag/dependees-dialog/dependees-dialog.component.d.ts +27 -0
  89. package/lib/v2/feature-flag/evaluation-formula/evaluation-formula.component.d.ts +41 -0
  90. package/lib/v2/feature-flag/evaluation-formula/feature-flag-value/feature-flag-value.component.d.ts +18 -0
  91. package/lib/v2/feature-flag/evaluation-formula/popout-text-editor-dialog/popout-text-editor-dialog.component.d.ts +30 -0
  92. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/condition-chip/condition-chip.component.d.ts +10 -0
  93. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/conditions.component.d.ts +27 -0
  94. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/prerequisite-flag-condition/prerequisite-flag-condition.component.d.ts +36 -0
  95. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/segment-condition/segment-condition.component.d.ts +21 -0
  96. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/comparator-dialog/comparator-dialog.component.d.ts +79 -0
  97. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/popout-list-editor-dialog/popout-list-editor-dialog.component.d.ts +63 -0
  98. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/conditions/user-condition/user-condition.component.d.ts +94 -0
  99. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/percentage-options/percentage-options.component.d.ts +31 -0
  100. package/lib/v2/feature-flag/evaluation-formula/targeting-rule/targeting-rule.component.d.ts +33 -0
  101. package/lib/v2/feature-flag/feature-flag.component.d.ts +49 -0
  102. package/lib/v2/feature-flag/percentage-evaluation-attribute-dialog/percentage-evaluation-attribute-dialog.component.d.ts +28 -0
  103. package/lib/v2/feature-flag-item.component.d.ts +66 -0
  104. package/package.json +12 -16
  105. package/public-api.d.ts +1 -0
  106. package/public-api.scss +205 -3
  107. package/esm2020/lib/_directives/input-display-normalizer.directive.mjs +0 -38
  108. package/esm2020/lib/_services/form-helper.mjs +0 -104
  109. package/esm2020/lib/_services/public-api.service.mjs +0 -71
  110. package/esm2020/lib/_services/setting-list-form-helper.mjs +0 -171
  111. package/esm2020/lib/authorization/authorization.component.mjs +0 -62
  112. package/esm2020/lib/base/base.component.mjs +0 -45
  113. package/esm2020/lib/dialogs/expand-dialog/expand-dialog.component.mjs +0 -80
  114. package/esm2020/lib/dialogs/reason-dialog/reason-dialog.component.mjs +0 -36
  115. package/esm2020/lib/ng-configcat-publicapi-ui.module.mjs +0 -179
  116. package/esm2020/lib/selects/config-select/config-select.component.mjs +0 -60
  117. package/esm2020/lib/selects/environment-select/environment-select.component.mjs +0 -47
  118. package/esm2020/lib/selects/product-select/product-select.component.mjs +0 -40
  119. package/esm2020/lib/selects/setting-select/setting-select.component.mjs +0 -47
  120. package/esm2020/lib/setting-item/setting-item.component.mjs +0 -116
  121. package/esm2020/lib/setting-list/setting/rollout-percentage-items/rollout-percentage-items.component.mjs +0 -81
  122. package/esm2020/lib/setting-list/setting/rollout-rules/rollout-rules.component.mjs +0 -293
  123. package/esm2020/lib/setting-list/setting/value/value.component.mjs +0 -37
  124. package/esm2020/lib/setting-list/setting-list.component.mjs +0 -194
  125. package/fesm2015/ng-configcat-publicapi-ui.mjs +0 -1786
  126. package/fesm2015/ng-configcat-publicapi-ui.mjs.map +0 -1
  127. package/fesm2020/ng-configcat-publicapi-ui.mjs +0 -1763
  128. package/fesm2020/ng-configcat-publicapi-ui.mjs.map +0 -1
  129. /package/{esm2020 → esm2022}/lib/_directives/index.mjs +0 -0
  130. /package/{esm2020 → esm2022}/lib/_models/deleteSettingModel.mjs +0 -0
  131. /package/{esm2020 → esm2022}/lib/_models/index.mjs +0 -0
  132. /package/{esm2020 → esm2022}/lib/_models/settingValuesModel.mjs +0 -0
  133. /package/{esm2020 → esm2022}/lib/_models/updateSettingValuesModel.mjs +0 -0
  134. /package/{esm2020 → esm2022}/lib/_services/index.mjs +0 -0
  135. /package/{esm2020 → esm2022}/lib/_services/platform-helper.mjs +0 -0
  136. /package/{esm2020 → esm2022}/ng-configcat-publicapi-ui.mjs +0 -0
@@ -1,1763 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Injectable, Optional, Component, Input, Inject, Directive, HostListener, EventEmitter, Output, forwardRef, NgModule } from '@angular/core';
3
- import { MeService, Configuration as Configuration$1, ProductsService, ConfigsService, EnvironmentsService, FeatureFlagsSettingsService, FeatureFlagSettingValuesService, IntegrationLinksService, SegmentsService, SettingType, RolloutRuleComparator, SegmentComparator, ApiModule } from 'ng-configcat-publicapi';
4
- import * as i1 from '@angular/common/http';
5
- import { HttpErrorResponse } from '@angular/common/http';
6
- import { forkJoin, throwError, of } from 'rxjs';
7
- import { map, catchError } from 'rxjs/operators';
8
- import * as i2 from '@angular/forms';
9
- import { Validators, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
10
- import * as i1$1 from '@angular/material/dialog';
11
- import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
12
- import * as i2$1 from '@angular/common';
13
- import { CommonModule } from '@angular/common';
14
- import * as i4 from '@angular/material/form-field';
15
- import { MatFormFieldModule } from '@angular/material/form-field';
16
- import * as i5 from '@angular/material/button';
17
- import { MatButtonModule } from '@angular/material/button';
18
- import * as i6 from '@angular/material/input';
19
- import { MatInputModule } from '@angular/material/input';
20
- import * as i2$2 from '@angular/material/snack-bar';
21
- import { MatSnackBarModule } from '@angular/material/snack-bar';
22
- import * as i7 from '@angular/material/icon';
23
- import { MatIconModule } from '@angular/material/icon';
24
- import * as i7$1 from '@angular/material/tooltip';
25
- import { MatTooltipModule, MAT_TOOLTIP_DEFAULT_OPTIONS } from '@angular/material/tooltip';
26
- import * as i5$1 from '@angular/material/chips';
27
- import { MatChipsModule } from '@angular/material/chips';
28
- import * as i11 from '@angular/cdk/drag-drop';
29
- import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
30
- import { valid } from 'semver';
31
- import * as i5$2 from '@angular/material/core';
32
- import { MatOptionModule } from '@angular/material/core';
33
- import * as i10 from '@angular/material/autocomplete';
34
- import { MatAutocompleteModule } from '@angular/material/autocomplete';
35
- import * as i6$1 from '@angular/material/select';
36
- import { MatSelectModule } from '@angular/material/select';
37
- import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
38
- import { RouterModule } from '@angular/router';
39
- import { MatMenuModule } from '@angular/material/menu';
40
-
41
- class Configuration {
42
- constructor() {
43
- this.basePath = 'https://api.configcat.com';
44
- this.dashboardBasePath = 'https://app.configcat.com';
45
- }
46
- }
47
- Configuration.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: Configuration, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
48
- Configuration.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: Configuration });
49
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: Configuration, decorators: [{
50
- type: Injectable
51
- }] });
52
-
53
- class PublicApiService {
54
- constructor(httpClient, configuration) {
55
- this.httpClient = httpClient;
56
- this.configuration = configuration;
57
- }
58
- createMeService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
59
- return new MeService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
60
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
61
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
62
- }));
63
- }
64
- createProductsService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
65
- return new ProductsService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
66
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
67
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
68
- }));
69
- }
70
- createConfigsService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
71
- return new ConfigsService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
72
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
73
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
74
- }));
75
- }
76
- createEnvironmentsService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
77
- return new EnvironmentsService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
78
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
79
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
80
- }));
81
- }
82
- createSettingsService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
83
- return new FeatureFlagsSettingsService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
84
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
85
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
86
- }));
87
- }
88
- createSettingValuesService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
89
- return new FeatureFlagSettingValuesService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
90
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
91
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
92
- }));
93
- }
94
- createIntegrationLinksService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
95
- return new IntegrationLinksService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
96
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
97
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
98
- }));
99
- }
100
- createSegmentsService(basicAuthUsername = null, basicAuthPassword = null, basePath = null) {
101
- return new SegmentsService(this.httpClient, basePath ?? this.configuration?.basePath, new Configuration$1({
102
- username: basicAuthUsername ?? this.configuration?.basicAuthUsername,
103
- password: basicAuthPassword ?? this.configuration?.basicAuthPassword
104
- }));
105
- }
106
- getDashboardBasePath() {
107
- return this.configuration?.dashboardBasePath ?? 'https://app.configcat.com';
108
- }
109
- }
110
- PublicApiService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PublicApiService, deps: [{ token: i1.HttpClient }, { token: Configuration, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
111
- PublicApiService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PublicApiService, providedIn: 'root' });
112
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: PublicApiService, decorators: [{
113
- type: Injectable,
114
- args: [{ providedIn: 'root' }]
115
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: Configuration, decorators: [{
116
- type: Optional
117
- }] }]; } });
118
-
119
- class BaseComponent {
120
- constructor(publicApiService) {
121
- this.publicApiService = publicApiService;
122
- this.basePath = null;
123
- this.basicAuthUsername = null;
124
- this.basicAuthPassword = null;
125
- }
126
- createProductsService() {
127
- return this.publicApiService.createProductsService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
128
- }
129
- createConfigsService() {
130
- return this.publicApiService.createConfigsService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
131
- }
132
- createEnvironmentsService() {
133
- return this.publicApiService.createEnvironmentsService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
134
- }
135
- createSettingsService() {
136
- return this.publicApiService.createSettingsService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
137
- }
138
- createSettingValuesService() {
139
- return this.publicApiService.createSettingValuesService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
140
- }
141
- createSegmentsService() {
142
- return this.publicApiService.createSegmentsService(this.basicAuthUsername, this.basicAuthPassword, this.basePath);
143
- }
144
- }
145
- BaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: BaseComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
146
- BaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: BaseComponent, selector: "base", inputs: { basePath: "basePath", basicAuthUsername: "basicAuthUsername", basicAuthPassword: "basicAuthPassword" }, ngImport: i0, template: '<div></div>', isInline: true });
147
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: BaseComponent, decorators: [{
148
- type: Component,
149
- args: [{
150
- selector: 'base',
151
- template: '<div></div>'
152
- }]
153
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { basePath: [{
154
- type: Input
155
- }], basicAuthUsername: [{
156
- type: Input
157
- }], basicAuthPassword: [{
158
- type: Input
159
- }] } });
160
-
161
- class PlatformHelper {
162
- static isChromium() {
163
- // https://stackoverflow.com/a/62797156/8656352
164
- return !!window.chrome;
165
- }
166
- }
167
-
168
- class FormHelper {
169
- static getErrorMessage(control, hint = '') {
170
- if (!control || control.valid) {
171
- return;
172
- }
173
- if (control.hasError('required')) {
174
- return `${hint} The field is required.`;
175
- }
176
- if (control.hasError('pattern')) {
177
- return 'Not a valid e-mail address.';
178
- }
179
- if (control.hasError('minlength')) {
180
- return 'The field must be at least ' + control.getError('minlength').requiredLength + ' characters long';
181
- }
182
- if (control.hasError('maxlength')) {
183
- return 'The field must be at max ' + control.getError('maxlength').requiredLength + ' characters long';
184
- }
185
- return;
186
- }
187
- static handleErrors(formGroup, error) {
188
- if (error instanceof HttpErrorResponse) {
189
- const response = error;
190
- switch (response.status) {
191
- case 400:
192
- let unknownFieldName = false;
193
- for (const fieldName in error.error) {
194
- if (error.error.hasOwnProperty(fieldName) && error.error[fieldName] &&
195
- (error.error[fieldName]?.length > 0 || error.error[fieldName]?.Errors?.length > 0)) {
196
- let jsonFieldName = fieldName;
197
- if (jsonFieldName.length > 0) {
198
- jsonFieldName = jsonFieldName[0].toLowerCase() + jsonFieldName.slice(1);
199
- }
200
- const errorMessage = error.error[fieldName]?.Errors?.length > 0 ?
201
- (error.error[fieldName]?.Errors.map((e) => e.ErrorMessage)).join(', ')
202
- : error.error[fieldName];
203
- if (formGroup.controls.hasOwnProperty(jsonFieldName)) {
204
- formGroup.controls[jsonFieldName].setErrors({ serverSide: errorMessage });
205
- }
206
- else {
207
- unknownFieldName = true;
208
- }
209
- }
210
- }
211
- if (unknownFieldName) {
212
- formGroup.setErrors({ serverSide: 'Something went wrong.' });
213
- }
214
- break;
215
- // in these cases we do not show errors on the form, they're handled by the http
216
- // interceptor in src\app\_interceptors\httpstatuscode.interceptor.ts
217
- case 402:
218
- case 429:
219
- return;
220
- }
221
- }
222
- else {
223
- formGroup.setErrors({ serverSide: 'Something went wrong on our side. This is not your fault. Please try again.' });
224
- }
225
- }
226
- /**
227
- * Converts a value representing a number to a `number` value.
228
- * Returns `NaN` in the case of non-numerical values.
229
- */
230
- static normalizeNumber(value) {
231
- switch (typeof value) {
232
- case "number":
233
- return value;
234
- case "string":
235
- // NOTE: `Number()` converts whitespace strings to 0.
236
- return value.trim() === '' ? NaN : Number(value);
237
- case "bigint":
238
- return Number(value);
239
- default:
240
- return NaN;
241
- }
242
- }
243
- /**
244
- * Converts a value representing a number to the normalized `string`
245
- * representation of the number. (e.g. `.1` --> `'0.1'`, `3.14e2` --> `'314'`).
246
- * Returns `''` in the case of non-numerical values or non-finite numerical values.
247
- */
248
- static normalizeNumberStoredAsString(value) {
249
- value = FormHelper.normalizeNumber(value);
250
- // NOTE: `NaN` is not considered finite.
251
- return isFinite(value) ? value + '' : '';
252
- }
253
- static formatNumberForDisplay(value) {
254
- if (!isFinite(value)) {
255
- return '';
256
- }
257
- // Chromium-based browsers don't respect the `lang` attribute,
258
- // they use a display format corresponding to the browser's language setting.
259
- if (PlatformHelper.isChromium()) {
260
- return value.toLocaleString();
261
- }
262
- // Firefox (and probably other browsers) respect the `lang` attribute,
263
- // which is currently set to the fixed value of "en" (see index.html),
264
- // so in these cases dot should be used as the decimal separator.
265
- // (In case localization is implemented in the application, this logic should be revised!)
266
- return value + '';
267
- }
268
- }
269
-
270
- class ReasonDialogComponent {
271
- constructor(dialogRef, formBuilder) {
272
- this.dialogRef = dialogRef;
273
- this.formBuilder = formBuilder;
274
- }
275
- ngOnInit() {
276
- this.formGroup = this.formBuilder.group({
277
- reason: ['', [Validators.required, Validators.maxLength(1000)]]
278
- });
279
- }
280
- handleSaveButton() {
281
- if (!this.formGroup.valid) {
282
- return;
283
- }
284
- this.dialogRef.close({ button: 'save', reason: this.formGroup.controls.reason.value });
285
- }
286
- cancel() {
287
- this.dialogRef.close({ button: 'cancel' });
288
- }
289
- }
290
- ReasonDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ReasonDialogComponent, deps: [{ token: i1$1.MatDialogRef }, { token: i2.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Component });
291
- ReasonDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ReasonDialogComponent, selector: "configcat-reason-dialog", ngImport: i0, template: "<h1 mat-dialog-title>Add notes</h1>\n<form [formGroup]=\"formGroup\" (ngSubmit)=\"handleSaveButton()\">\n <div mat-dialog-content class=\"container\">\n <p>This will appear in the Why column of the Audit Log.</p>\n <mat-form-field appearance=\"outline\">\n <mat-label></mat-label>\n <textarea matInput formControlName=\"reason\" name=\"reason\" placeholder=\"I'm changing settings because...\"\n rows=\"3\"></textarea>\n <mat-error *ngIf=\"formGroup.controls.reason.invalid\">The field is required.</mat-error>\n </mat-form-field>\n </div>\n <div mat-dialog-actions>\n <button type=\"submit\" style=\"margin-right: 10px;\" mat-flat-button color=\"primary\">Add notes & Save</button>\n <button type=\"button\" mat-stroked-button (click)=\"cancel()\">Cancel</button>\n </div>\n</form>", styles: [".container>*{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
292
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ReasonDialogComponent, decorators: [{
293
- type: Component,
294
- args: [{ selector: 'configcat-reason-dialog', template: "<h1 mat-dialog-title>Add notes</h1>\n<form [formGroup]=\"formGroup\" (ngSubmit)=\"handleSaveButton()\">\n <div mat-dialog-content class=\"container\">\n <p>This will appear in the Why column of the Audit Log.</p>\n <mat-form-field appearance=\"outline\">\n <mat-label></mat-label>\n <textarea matInput formControlName=\"reason\" name=\"reason\" placeholder=\"I'm changing settings because...\"\n rows=\"3\"></textarea>\n <mat-error *ngIf=\"formGroup.controls.reason.invalid\">The field is required.</mat-error>\n </mat-form-field>\n </div>\n <div mat-dialog-actions>\n <button type=\"submit\" style=\"margin-right: 10px;\" mat-flat-button color=\"primary\">Add notes & Save</button>\n <button type=\"button\" mat-stroked-button (click)=\"cancel()\">Cancel</button>\n </div>\n</form>", styles: [".container>*{width:100%}\n"] }]
295
- }], ctorParameters: function () { return [{ type: i1$1.MatDialogRef }, { type: i2.UntypedFormBuilder }]; } });
296
-
297
- class SaveSnackbarComponent {
298
- constructor() { }
299
- ngOnInit() {
300
- }
301
- }
302
- SaveSnackbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SaveSnackbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
303
- SaveSnackbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SaveSnackbarComponent, selector: "configcat-save-snackbar", ngImport: i0, template: "<p class=\"header\">Settings saved successfully.</p>", styles: ["p{text-align:center;font-weight:700}.header{font-size:1.2em}\n"] });
304
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SaveSnackbarComponent, decorators: [{
305
- type: Component,
306
- args: [{ selector: 'configcat-save-snackbar', template: "<p class=\"header\">Settings saved successfully.</p>", styles: ["p{text-align:center;font-weight:700}.header{font-size:1.2em}\n"] }]
307
- }], ctorParameters: function () { return []; } });
308
-
309
- class SettingListFormHelper {
310
- constructor(formBuilder) {
311
- this.formBuilder = formBuilder;
312
- }
313
- createSettingValuesFormGroup(settingValuesModel) {
314
- const formGroup = this.formBuilder.group({
315
- settingValues: this.formBuilder.array(settingValuesModel.settingValues.map(sv => {
316
- return this.createSettingValueFormGroup(sv, settingValuesModel.readOnly);
317
- })),
318
- // Decorator
319
- environment: this.formBuilder.group({
320
- environmentId: [{ value: settingValuesModel.environment.environmentId, disabled: true }],
321
- name: [{ value: settingValuesModel.environment.name, disabled: true }],
322
- }),
323
- comparisonAttributes: [[]]
324
- });
325
- const rolloutRules = this.getAllRolloutRules(formGroup);
326
- const comparisonAttributes = this.getComparisonAttributes(rolloutRules);
327
- formGroup.patchValue({ comparisonAttributes: comparisonAttributes });
328
- return formGroup;
329
- }
330
- createSettingValueFormGroup(settingValueModel, readOnly) {
331
- if (!settingValueModel.setting) {
332
- return this.formBuilder.group({});
333
- }
334
- return this.formBuilder.group({
335
- settingId: [settingValueModel.setting.settingId],
336
- value: [
337
- { value: settingValueModel.value, disabled: readOnly },
338
- this.getValidatorsForSettingType(settingValueModel.setting.settingType)
339
- ],
340
- rolloutPercentageItems: settingValueModel.rolloutPercentageItems
341
- ? this.formBuilder.array(settingValueModel.rolloutPercentageItems.map(p => {
342
- // @ts-ignore()
343
- return this.createRolloutPercentageItemFormGroup(p, readOnly, settingValueModel.setting.settingType);
344
- }))
345
- : this.formBuilder.array([]), rolloutRules: settingValueModel.rolloutRules
346
- ? this.formBuilder.array(settingValueModel.rolloutRules.map(r => {
347
- // @ts-ignore()
348
- return this.createRolloutRuleFormGroup(r, readOnly, settingValueModel.setting.settingType);
349
- }))
350
- : this.formBuilder.array([]),
351
- updatedAt: [{ value: settingValueModel.updatedAt, disabled: true }],
352
- lastUpdaterUserEmail: [{ value: settingValueModel.lastUpdaterUserEmail, disabled: true }],
353
- lastUpdaterUserFullName: [{ value: settingValueModel.lastUpdaterUserFullName, disabled: true }],
354
- rolloutPercentageItemsSum: [{ value: 100, disabled: false }, [Validators.min(100), Validators.max(100)]],
355
- // Decoration
356
- setting: this.formBuilder.group({
357
- settingId: [{ value: settingValueModel.setting.settingId, disabled: true }],
358
- key: [{ value: settingValueModel.setting.key, disabled: true }],
359
- name: [{ value: settingValueModel.setting.name, disabled: true }],
360
- hint: [{ value: settingValueModel.setting.hint, disabled: true }],
361
- settingType: [{ value: settingValueModel.setting.settingType, disabled: true }],
362
- creatorEmail: [{ value: settingValueModel.setting.creatorEmail, disabled: true }],
363
- creatorFullName: [{ value: settingValueModel.setting.creatorFullName, disabled: true }],
364
- createdAt: [{ value: settingValueModel.setting.createdAt, disabled: true }]
365
- }),
366
- integrationLinks: settingValueModel.integrationLinks ? this.formBuilder.array(settingValueModel.integrationLinks.map(il => {
367
- return this.formBuilder.group({
368
- key: [{ value: il.key, disabled: true }],
369
- description: [{ value: il.description, disabled: true }],
370
- integrationLinkType: [{ value: il.integrationLinkType, disabled: true }],
371
- url: [{ value: il.url, disabled: true }],
372
- });
373
- })) : this.formBuilder.array([])
374
- });
375
- }
376
- createRolloutPercentageItemFormGroup(p, readOnly, settingType) {
377
- return this.formBuilder.group({
378
- percentage: [{ value: p.percentage, disabled: readOnly }, [Validators.required, Validators.min(0), Validators.max(100)]],
379
- value: [
380
- { value: p.value, disabled: readOnly },
381
- this.getValidatorsForSettingType(settingType)
382
- ],
383
- valueDisabled: [
384
- { value: p.value, disabled: true }, // For percentage item value
385
- ]
386
- });
387
- }
388
- createRolloutRuleFormGroup(r, readOnly, settingType) {
389
- if (r.comparator) {
390
- return this.formBuilder.group({
391
- type: [{ value: 0, disabled: true }],
392
- comparisonAttribute: [{ value: r.comparisonAttribute, disabled: readOnly }, [Validators.required]],
393
- comparator: [{ value: r.comparator, disabled: readOnly }, [Validators.required]],
394
- comparisonValue: [{ value: r.comparisonValue, disabled: readOnly }, [Validators.required]],
395
- value: [
396
- { value: r.value, disabled: readOnly },
397
- this.getValidatorsForSettingType(settingType)
398
- ],
399
- });
400
- }
401
- else if (r.segmentComparator) {
402
- return this.formBuilder.group({
403
- type: [{ value: 1, disabled: true }],
404
- segmentComparator: [{ value: r.segmentComparator, disabled: readOnly }, [Validators.required]],
405
- segmentId: [{ value: r.segmentId, disabled: readOnly }, [Validators.required]],
406
- value: [
407
- { value: r.value, disabled: readOnly },
408
- this.getValidatorsForSettingType(settingType)
409
- ],
410
- });
411
- }
412
- else {
413
- throw new Error('Invalid rollout rule');
414
- }
415
- }
416
- getValidatorsForSettingType(settingType) {
417
- switch (settingType) {
418
- case SettingType.Int:
419
- return [Validators.required,
420
- Validators.min(-2147483648), Validators.max(2147483647), Validators.pattern('^[-+]?[0-9]\\d*$')];
421
- case SettingType.Double:
422
- return [Validators.required, Validators.min(-1.79769313486232E+308), Validators.max(1.79769313486232E+308)];
423
- case SettingType.String:
424
- case SettingType.Boolean:
425
- return [Validators.required];
426
- default:
427
- return [];
428
- }
429
- }
430
- getAllRolloutRules(formGroup) {
431
- const settingValues = formGroup.get('settingValues');
432
- const rolloutRules = settingValues.controls.map(cv => cv.get('rolloutRules').value);
433
- return rolloutRules.length === 0 ? rolloutRules : rolloutRules.reduce((a, b) => a.concat(b));
434
- }
435
- getComparisonAttributes(rolloutRules) {
436
- if (rolloutRules.length > 0) {
437
- const currentComparisonAttributes = rolloutRules.map(r => r.comparisonAttribute);
438
- const defaultComparisonAttributes = ['Identifier', 'Email', 'Country'];
439
- const comparisonAttributes = currentComparisonAttributes.filter(c => defaultComparisonAttributes.indexOf(c) === -1);
440
- return Array.from(new Set(comparisonAttributes));
441
- }
442
- else {
443
- return [];
444
- }
445
- }
446
- getComparisonValueType(comparator) {
447
- switch (comparator) {
448
- case RolloutRuleComparator.NumberEquals:
449
- case RolloutRuleComparator.NumberDoesNotEqual:
450
- case RolloutRuleComparator.NumberLess:
451
- case RolloutRuleComparator.NumberLessOrEquals:
452
- case RolloutRuleComparator.NumberGreater:
453
- case RolloutRuleComparator.NumberGreaterOrEquals:
454
- return 'number';
455
- default:
456
- return 'text';
457
- }
458
- }
459
- normalizeComparisonValue(comparator, comparisonValue) {
460
- // In the case of number inputs value is a number but API expects
461
- // a string, so we need to make sure that it's converted to string.
462
- return comparator && this.getComparisonValueType(comparator) === "number"
463
- ? FormHelper.normalizeNumberStoredAsString(comparisonValue)
464
- : comparisonValue;
465
- }
466
- }
467
- SettingListFormHelper.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingListFormHelper, deps: [{ token: i2.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Injectable });
468
- SettingListFormHelper.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingListFormHelper, providedIn: 'root' });
469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingListFormHelper, decorators: [{
470
- type: Injectable,
471
- args: [{ providedIn: 'root' }]
472
- }], ctorParameters: function () { return [{ type: i2.UntypedFormBuilder }]; } });
473
-
474
- class ExpandDialogComponent {
475
- constructor(dialogRef, formBuilder, data) {
476
- this.dialogRef = dialogRef;
477
- this.formBuilder = formBuilder;
478
- this.data = data;
479
- this.readOnly = false;
480
- }
481
- ngOnInit() {
482
- this.readOnly = this.data.control.disabled;
483
- if (this.data.multiline) {
484
- this.buildFormGroup();
485
- }
486
- else {
487
- this.formControlSubscription = this.data.control.valueChanges.subscribe((value) => {
488
- this.data.control.setValue(value, { onlySelf: true, emitEvent: false, emitModelToViewChange: true });
489
- this.data.control.markAsDirty();
490
- }, () => { }, () => { });
491
- }
492
- }
493
- values() {
494
- return this.formGroup.get('values');
495
- }
496
- getValueControls() {
497
- return this.values().controls.map(c => c);
498
- }
499
- buildFormGroup() {
500
- const value = this.data.control.value ? this.data.control.value : '';
501
- const list = value.split(',').map((v) => v.trim()).filter((v) => !!v);
502
- this.formGroup = this.formBuilder.group({
503
- values: this.formBuilder.array(list.map((v) => this.formBuilder.control({ value: v, disabled: this.data.control.disabled })))
504
- });
505
- this.formGroupSubscription = this.formGroup.valueChanges.subscribe((formGroupValue) => {
506
- this.data.control.setValue(formGroupValue.values
507
- .filter((v) => !!v)
508
- .join(','), { onlySelf: true, emitEvent: false, emitModelToViewChange: true });
509
- this.data.control.updateValueAndValidity();
510
- this.data.control.markAsDirty();
511
- });
512
- }
513
- add() {
514
- this.formGroup.controls.values.push(this.formBuilder.control(''));
515
- }
516
- remove(index) {
517
- this.formGroup.controls.values.removeAt(index);
518
- }
519
- ngOnDestroy() {
520
- if (this.formControlSubscription) {
521
- this.formControlSubscription.unsubscribe();
522
- this.formControlSubscription = null;
523
- }
524
- if (this.formGroupSubscription) {
525
- this.formGroupSubscription.unsubscribe();
526
- this.formGroupSubscription = null;
527
- }
528
- }
529
- close() {
530
- this.dialogRef.close();
531
- }
532
- }
533
- ExpandDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ExpandDialogComponent, deps: [{ token: i1$1.MatDialogRef }, { token: i2.UntypedFormBuilder }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
534
- ExpandDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ExpandDialogComponent, selector: "configcat-expand-dialog", ngImport: i0, template: "<div mat-dialog-content class=\"container\">\n <mat-form-field appearance=\"outline\" *ngIf=\"!data.multiline\" subscriptSizing=\"dynamic\">\n <mat-label></mat-label>\n <textarea matInput [formControl]=\"data.control\" rows=\"10\"></textarea>\n </mat-form-field>\n <div [formGroup]=\"formGroup\" *ngIf=\"data.multiline\">\n <div *ngFor=\"let valueControl of getValueControls(); let i = index;\" class=\"value-field\">\n <mat-form-field appearance=\"outline\">\n <input matInput [formControl]=\"valueControl\" />\n </mat-form-field>\n <button (click)=\"remove(i)\" mat-icon-button type=\"button\" class=\"no-density-mat-icon-button\"\n matTooltip=\"Remove item\" *ngIf=\"!readOnly\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n <button (click)=\"add()\" mat-stroked-button type=\"button\" *ngIf=\"!readOnly\">\n <mat-icon>add</mat-icon>Add item\n </button>\n </div>\n</div>\n<div mat-dialog-actions>\n <button type=\"button\" mat-flat-button color=\"primary\" (click)=\"close()\">Done</button>\n</div>", styles: [".container>*{width:100%}.container>* .value-field{display:flex;font-size:12px;flex-wrap:nowrap}.container>* .value-field mat-form-field{flex-grow:1}.container>* .no-density-mat-icon-button{width:48px;height:48px;padding:12px}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
535
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ExpandDialogComponent, decorators: [{
536
- type: Component,
537
- args: [{ selector: 'configcat-expand-dialog', template: "<div mat-dialog-content class=\"container\">\n <mat-form-field appearance=\"outline\" *ngIf=\"!data.multiline\" subscriptSizing=\"dynamic\">\n <mat-label></mat-label>\n <textarea matInput [formControl]=\"data.control\" rows=\"10\"></textarea>\n </mat-form-field>\n <div [formGroup]=\"formGroup\" *ngIf=\"data.multiline\">\n <div *ngFor=\"let valueControl of getValueControls(); let i = index;\" class=\"value-field\">\n <mat-form-field appearance=\"outline\">\n <input matInput [formControl]=\"valueControl\" />\n </mat-form-field>\n <button (click)=\"remove(i)\" mat-icon-button type=\"button\" class=\"no-density-mat-icon-button\"\n matTooltip=\"Remove item\" *ngIf=\"!readOnly\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n <button (click)=\"add()\" mat-stroked-button type=\"button\" *ngIf=\"!readOnly\">\n <mat-icon>add</mat-icon>Add item\n </button>\n </div>\n</div>\n<div mat-dialog-actions>\n <button type=\"button\" mat-flat-button color=\"primary\" (click)=\"close()\">Done</button>\n</div>", styles: [".container>*{width:100%}.container>* .value-field{display:flex;font-size:12px;flex-wrap:nowrap}.container>* .value-field mat-form-field{flex-grow:1}.container>* .no-density-mat-icon-button{width:48px;height:48px;padding:12px}\n"] }]
538
- }], ctorParameters: function () { return [{ type: i1$1.MatDialogRef }, { type: i2.UntypedFormBuilder }, { type: undefined, decorators: [{
539
- type: Inject,
540
- args: [MAT_DIALOG_DATA]
541
- }] }]; } });
542
-
543
- /**
544
- * Makes sure that values entered into HTML input fields are displayed in the correct format,
545
- * where correct means normalized (e.g. `'.10'` --> `'0.1'`) and corresponding to the locale setting.
546
- *
547
- * The format is adjusted on the blur event. Only the format of number inputs is adjusted currently.
548
- */
549
- class InputDisplayNormalizerDirective {
550
- constructor() { }
551
- onChange($event) {
552
- const target = $event.target;
553
- if (target.type === 'number') {
554
- let value = target.value;
555
- value = value.trim() !== '' ? Number(value) : NaN;
556
- if (isFinite(value)) {
557
- // The string returned by the `value` property and the string displayed in the input field are not necessarily equal.
558
- // HACK: When the returned and the displayed value differs only in the decimal separator,
559
- // Chrome won't update the displayed value unless the value is changed first...
560
- target.value = '';
561
- target.value = value;
562
- }
563
- }
564
- }
565
- }
566
- InputDisplayNormalizerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InputDisplayNormalizerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
567
- InputDisplayNormalizerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: InputDisplayNormalizerDirective, selector: "input[inputDisplayNormalizer]", host: { listeners: { "blur": "onChange($event)" } }, ngImport: i0 });
568
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InputDisplayNormalizerDirective, decorators: [{
569
- type: Directive,
570
- args: [{
571
- // eslint-disable-next-line @angular-eslint/directive-selector
572
- selector: 'input[inputDisplayNormalizer]'
573
- }]
574
- }], ctorParameters: function () { return []; }, propDecorators: { onChange: [{
575
- type: HostListener,
576
- args: ['blur', ['$event']]
577
- }] } });
578
-
579
- class ValueComponent {
580
- constructor(dialog) {
581
- this.dialog = dialog;
582
- this.SettingType = SettingType;
583
- }
584
- popOut() {
585
- this.dialog.open(ExpandDialogComponent, {
586
- width: '640px',
587
- data: { control: this.valueFormControl }
588
- });
589
- }
590
- formatDecimalNumber(value) {
591
- return FormHelper.formatNumberForDisplay(value);
592
- }
593
- }
594
- ValueComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ValueComponent, deps: [{ token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
595
- ValueComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ValueComponent, selector: "configcat-value", inputs: { valueFormControl: "valueFormControl", setting: "setting" }, ngImport: i0, template: "<div class=\"flex\">\n <div class=\"container\" [ngSwitch]=\"setting.settingType\">\n <div *ngSwitchCase=\"SettingType.String\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"text\"\n [formControl]=\"valueFormControl\" placeholder=\"my value\" name=\"value\">\n <div class=\"expand\" (click)=\"popOut()\" matTooltip=\"Pop-out Editor\">\n <mat-icon>height</mat-icon>\n </div>\n </div>\n <div *ngSwitchCase=\"SettingType.Int\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"number\" [formControl]=\"valueFormControl\"\n placeholder=\"42\" name=\"value\" />\n </div>\n <div *ngSwitchCase=\"SettingType.Double\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"number\" [formControl]=\"valueFormControl\"\n placeholder=\"{{ formatDecimalNumber(3.14) }}\" name=\"value\" inputDisplayNormalizer>\n </div>\n <div *ngSwitchCase=\"SettingType.Boolean\" class=\"toggle\">\n <label class=\"switch\">\n <input type=\"checkbox\" [formControl]=\"valueFormControl\" name=\"value\" />\n <span class=\"slider round\"></span>\n </label>\n </div>\n </div>\n <div *ngIf=\"setting.settingType === SettingType.Boolean\" class=\"spacer\"></div>\n\n</div>\n", styles: [".switch{position:relative;width:66px;height:30px;margin-left:4px;margin-top:0;margin-bottom:0}.switch input{display:none}.slider{position:absolute;cursor:pointer;inset:0;background-color:#ff5252;transition:.4s;width:66px;height:30px}.slider:before{position:absolute;content:\"\";height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;transition:.4s}input:checked+.slider{background-color:#9acd32}input:focus+.slider{box-shadow:0 0 1px #9acd32}input:checked+.slider:before{transform:translate(36px)}.slider.round{border-radius:34px}.slider.round:before{border-radius:50%}.slider:after{content:\"Off\";color:#fff;display:block;position:absolute;transform:translate(-14%,-50%);top:50%;left:50%;font-size:10px;font-family:Verdana,sans-serif}input:checked+.slider:after{content:\"On\";transform:translate(-91%,-50%)}\n", ".flex{display:flex;margin-right:10px;align-items:center}.flex .spacer{min-width:15px}.flex .container .with-validation{display:flex;flex-wrap:nowrap}.flex .container .toggle{width:66px;height:30px}.flex .container input{background-color:#fff;border:1px solid #e5e5e5;min-height:28px;padding:0 30px 0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300;min-width:150px;margin:0 3px}.flex .container input[type=number]{padding:0 2px 0 5px}.flex .container .invalid{border:1px solid #ff5252}.flex .container .error{color:#ff5252;margin-right:5px}.flex .variationId{margin:0 4px 0 5px;cursor:pointer;color:#888;display:flex;align-items:center}.flex .expand{position:relative;top:2px;height:24px;cursor:pointer;margin-left:-28px;z-index:1;color:#b3b3b3;background-color:#fff}.flex .expand mat-icon{transform:rotate(45deg)}@media (max-width: 920px){.flex{margin-right:0!important}.flex .spacer{min-width:5px}}@media (max-width: 510px){.flex .container .error{display:none}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: InputDisplayNormalizerDirective, selector: "input[inputDisplayNormalizer]" }] });
596
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ValueComponent, decorators: [{
597
- type: Component,
598
- args: [{ selector: 'configcat-value', template: "<div class=\"flex\">\n <div class=\"container\" [ngSwitch]=\"setting.settingType\">\n <div *ngSwitchCase=\"SettingType.String\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"text\"\n [formControl]=\"valueFormControl\" placeholder=\"my value\" name=\"value\">\n <div class=\"expand\" (click)=\"popOut()\" matTooltip=\"Pop-out Editor\">\n <mat-icon>height</mat-icon>\n </div>\n </div>\n <div *ngSwitchCase=\"SettingType.Int\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"number\" [formControl]=\"valueFormControl\"\n placeholder=\"42\" name=\"value\" />\n </div>\n <div *ngSwitchCase=\"SettingType.Double\" class=\"with-validation\">\n <span *ngIf=\"valueFormControl.invalid\" class=\"error\">*</span>\n <input [ngClass]=\"{'invalid': valueFormControl.invalid}\" type=\"number\" [formControl]=\"valueFormControl\"\n placeholder=\"{{ formatDecimalNumber(3.14) }}\" name=\"value\" inputDisplayNormalizer>\n </div>\n <div *ngSwitchCase=\"SettingType.Boolean\" class=\"toggle\">\n <label class=\"switch\">\n <input type=\"checkbox\" [formControl]=\"valueFormControl\" name=\"value\" />\n <span class=\"slider round\"></span>\n </label>\n </div>\n </div>\n <div *ngIf=\"setting.settingType === SettingType.Boolean\" class=\"spacer\"></div>\n\n</div>\n", styles: [".switch{position:relative;width:66px;height:30px;margin-left:4px;margin-top:0;margin-bottom:0}.switch input{display:none}.slider{position:absolute;cursor:pointer;inset:0;background-color:#ff5252;transition:.4s;width:66px;height:30px}.slider:before{position:absolute;content:\"\";height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;transition:.4s}input:checked+.slider{background-color:#9acd32}input:focus+.slider{box-shadow:0 0 1px #9acd32}input:checked+.slider:before{transform:translate(36px)}.slider.round{border-radius:34px}.slider.round:before{border-radius:50%}.slider:after{content:\"Off\";color:#fff;display:block;position:absolute;transform:translate(-14%,-50%);top:50%;left:50%;font-size:10px;font-family:Verdana,sans-serif}input:checked+.slider:after{content:\"On\";transform:translate(-91%,-50%)}\n", ".flex{display:flex;margin-right:10px;align-items:center}.flex .spacer{min-width:15px}.flex .container .with-validation{display:flex;flex-wrap:nowrap}.flex .container .toggle{width:66px;height:30px}.flex .container input{background-color:#fff;border:1px solid #e5e5e5;min-height:28px;padding:0 30px 0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300;min-width:150px;margin:0 3px}.flex .container input[type=number]{padding:0 2px 0 5px}.flex .container .invalid{border:1px solid #ff5252}.flex .container .error{color:#ff5252;margin-right:5px}.flex .variationId{margin:0 4px 0 5px;cursor:pointer;color:#888;display:flex;align-items:center}.flex .expand{position:relative;top:2px;height:24px;cursor:pointer;margin-left:-28px;z-index:1;color:#b3b3b3;background-color:#fff}.flex .expand mat-icon{transform:rotate(45deg)}@media (max-width: 920px){.flex{margin-right:0!important}.flex .spacer{min-width:5px}}@media (max-width: 510px){.flex .container .error{display:none}}\n"] }]
599
- }], ctorParameters: function () { return [{ type: i1$1.MatDialog }]; }, propDecorators: { valueFormControl: [{
600
- type: Input
601
- }], setting: [{
602
- type: Input
603
- }] } });
604
-
605
- class RolloutPercentageItemsComponent {
606
- setting() {
607
- return this.formGroup.get('setting')?.value;
608
- }
609
- rolloutRules() {
610
- return this.formGroup.get('rolloutRules');
611
- }
612
- rolloutPercentageItems() {
613
- return this.formGroup.get('rolloutPercentageItems');
614
- }
615
- rolloutPercentageItemsSum() {
616
- return this.formGroup.get('rolloutPercentageItemsSum');
617
- }
618
- value(rolloutPercentageItem) {
619
- return this.setting().settingType === SettingType.Boolean ?
620
- rolloutPercentageItem.get('valueDisabled') :
621
- rolloutPercentageItem.get('value');
622
- }
623
- constructor() {
624
- this.readOnly = false;
625
- this.SettingType = SettingType;
626
- }
627
- percentageChanged(index) {
628
- if (this.rolloutPercentageItems().controls[index].value.percentage < 0) {
629
- this.rolloutPercentageItems().controls[index].controls.percentage.setValue(0);
630
- }
631
- if (this.rolloutPercentageItems().controls[index].value.percentage > 100) {
632
- this.rolloutPercentageItems().controls[index].controls.percentage.setValue(100);
633
- }
634
- if (this.rolloutPercentageItems().controls.length === 2) {
635
- this.rolloutPercentageItems().controls[1 - index].controls.percentage
636
- .setValue(100 - this.rolloutPercentageItems().controls[index].value.percentage);
637
- }
638
- this.updateSum();
639
- }
640
- updateSum() {
641
- if (this.rolloutPercentageItems().controls.length === 0) {
642
- this.rolloutPercentageItemsSum().setValue(100);
643
- }
644
- else {
645
- this.rolloutPercentageItemsSum().setValue(this.rolloutPercentageItems().controls.map(v => v.value.percentage)
646
- .reduce((a, b) => a + b));
647
- }
648
- }
649
- removeRolloutPercentageItem(index) {
650
- this.rolloutPercentageItems().removeAt(index);
651
- this.rolloutPercentageItems().markAsDirty();
652
- this.updateSum();
653
- }
654
- removeAll() {
655
- this.rolloutPercentageItems().clear();
656
- this.rolloutPercentageItems().markAsDirty();
657
- this.updateSum();
658
- }
659
- getRolloutPercentageItemFormGroups() {
660
- return this.rolloutPercentageItems()?.controls?.map(c => c);
661
- }
662
- getPercentageFormControl(rolloutPercentageItem) {
663
- return rolloutPercentageItem.controls.percentage;
664
- }
665
- }
666
- RolloutPercentageItemsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RolloutPercentageItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
667
- RolloutPercentageItemsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RolloutPercentageItemsComponent, selector: "configcat-rollout-percentage-items", inputs: { formGroup: "formGroup", readOnly: "readOnly" }, ngImport: i0, template: "<div class=\"percentage-wrapper\" [formGroup]=\"formGroup\">\n\n <div class=\"if\" *ngIf=\"rolloutRules().controls.length > 0\">\n <mat-chip-set>\n <mat-chip class=\"chip\">ELSE IF</mat-chip>\n </mat-chip-set>\n </div>\n <div class=\"grow\">\n <div class=\"percentage-row flex\"\n *ngFor=\"let rolloutPercentageItem of getRolloutPercentageItemFormGroups(); let i = index\">\n <div class=\"flex\">\n <input type=\"number\" [formControl]=\"getPercentageFormControl(rolloutPercentageItem)\"\n (input)=\"percentageChanged(i)\">%\n <span class=\"users\">of <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">users</a>\n </span>\n </div>\n\n <div class=\"delete-option\" matTooltip=\"Remove this % option\"\n *ngIf=\"!readOnly && rolloutPercentageItems().controls.length > 2\"\n (click)=\"removeRolloutPercentageItem(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n\n <span matTooltip=\"The sum of percentages must be equal to 100.\" matTooltipPosition=\"above\"\n *ngIf=\"(i === rolloutPercentageItems().controls.length -1) && (rolloutPercentageItemsSum().invalid)\">\n <mat-icon color=\"warn\">\n error_outline\n </mat-icon>\n </span>\n\n <div class=\"value flex\">\n <span class=\"value-name\" *ngIf=\"setting().settingType !== SettingType.Boolean\">Served value:</span>\n <configcat-value class=\"served-value\" [valueFormControl]=\"value(rolloutPercentageItem)\"\n [setting]=\"setting()\">\n </configcat-value>\n </div>\n <div class=\"delete\" matTooltip=\"Remove % options\" (click)=\"removeAll()\" *ngIf=\"!readOnly\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n </div>\n</div>", styles: [".percentage-wrapper{border:1px solid #d5d5d5;background-color:#fff;margin:.5em 1em;position:relative;padding:.5em 0;display:flex;flex-wrap:wrap}.percentage-wrapper .delete{position:absolute;cursor:pointer;top:-9px;right:-10px;z-index:999;border-radius:50%;background-color:#fff;height:20px;width:20px;color:#ed5251}.percentage-wrapper .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.percentage-wrapper .delete:hover mat-icon{opacity:1}.percentage-wrapper .delete-option{color:#ed5251;cursor:pointer;margin-left:1rem;margin-top:4px}.percentage-wrapper .delete-option:hover mat-icon{opacity:1}.percentage-wrapper .delete-option mat-icon{opacity:.5;font-size:20px}.if{display:flex;align-items:center}.if>*{margin:0 .5em}.if .spacing{margin-right:44px}.if .chip{font-size:12px;background-color:#67b1fc3d}.grow{flex-grow:1}.percentage-row{min-height:40px;margin-left:.5em}.flex{display:flex;flex-wrap:wrap;align-items:center}.value{margin-left:auto}.value .value-name{display:none}input{background-color:#fff;border:1px solid #e5e5e5;min-height:28px;width:40px;margin-top:3px;margin-right:5px;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}input:focus{outline-color:#e5e5e5;outline-offset:-1px}.users{margin-left:20px}@media (max-width: 920px){.value{min-width:0!important}.value .served-value{margin:3px 7px 3px 0}}@media (max-width: 650px){.users{margin-left:5px}}@media (max-width: 540px){.users{font-size:12px}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i5$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disabled", "disableRipple", "tabIndex", "role", "id", "aria-label", "aria-description", "value", "removable", "highlighted"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i5$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role"] }, { kind: "component", type: ValueComponent, selector: "configcat-value", inputs: ["valueFormControl", "setting"] }] });
668
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RolloutPercentageItemsComponent, decorators: [{
669
- type: Component,
670
- args: [{ selector: 'configcat-rollout-percentage-items', template: "<div class=\"percentage-wrapper\" [formGroup]=\"formGroup\">\n\n <div class=\"if\" *ngIf=\"rolloutRules().controls.length > 0\">\n <mat-chip-set>\n <mat-chip class=\"chip\">ELSE IF</mat-chip>\n </mat-chip-set>\n </div>\n <div class=\"grow\">\n <div class=\"percentage-row flex\"\n *ngFor=\"let rolloutPercentageItem of getRolloutPercentageItemFormGroups(); let i = index\">\n <div class=\"flex\">\n <input type=\"number\" [formControl]=\"getPercentageFormControl(rolloutPercentageItem)\"\n (input)=\"percentageChanged(i)\">%\n <span class=\"users\">of <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">users</a>\n </span>\n </div>\n\n <div class=\"delete-option\" matTooltip=\"Remove this % option\"\n *ngIf=\"!readOnly && rolloutPercentageItems().controls.length > 2\"\n (click)=\"removeRolloutPercentageItem(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n\n <span matTooltip=\"The sum of percentages must be equal to 100.\" matTooltipPosition=\"above\"\n *ngIf=\"(i === rolloutPercentageItems().controls.length -1) && (rolloutPercentageItemsSum().invalid)\">\n <mat-icon color=\"warn\">\n error_outline\n </mat-icon>\n </span>\n\n <div class=\"value flex\">\n <span class=\"value-name\" *ngIf=\"setting().settingType !== SettingType.Boolean\">Served value:</span>\n <configcat-value class=\"served-value\" [valueFormControl]=\"value(rolloutPercentageItem)\"\n [setting]=\"setting()\">\n </configcat-value>\n </div>\n <div class=\"delete\" matTooltip=\"Remove % options\" (click)=\"removeAll()\" *ngIf=\"!readOnly\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n </div>\n</div>", styles: [".percentage-wrapper{border:1px solid #d5d5d5;background-color:#fff;margin:.5em 1em;position:relative;padding:.5em 0;display:flex;flex-wrap:wrap}.percentage-wrapper .delete{position:absolute;cursor:pointer;top:-9px;right:-10px;z-index:999;border-radius:50%;background-color:#fff;height:20px;width:20px;color:#ed5251}.percentage-wrapper .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.percentage-wrapper .delete:hover mat-icon{opacity:1}.percentage-wrapper .delete-option{color:#ed5251;cursor:pointer;margin-left:1rem;margin-top:4px}.percentage-wrapper .delete-option:hover mat-icon{opacity:1}.percentage-wrapper .delete-option mat-icon{opacity:.5;font-size:20px}.if{display:flex;align-items:center}.if>*{margin:0 .5em}.if .spacing{margin-right:44px}.if .chip{font-size:12px;background-color:#67b1fc3d}.grow{flex-grow:1}.percentage-row{min-height:40px;margin-left:.5em}.flex{display:flex;flex-wrap:wrap;align-items:center}.value{margin-left:auto}.value .value-name{display:none}input{background-color:#fff;border:1px solid #e5e5e5;min-height:28px;width:40px;margin-top:3px;margin-right:5px;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}input:focus{outline-color:#e5e5e5;outline-offset:-1px}.users{margin-left:20px}@media (max-width: 920px){.value{min-width:0!important}.value .served-value{margin:3px 7px 3px 0}}@media (max-width: 650px){.users{margin-left:5px}}@media (max-width: 540px){.users{font-size:12px}}\n"] }]
671
- }], ctorParameters: function () { return []; }, propDecorators: { formGroup: [{
672
- type: Input
673
- }], readOnly: [{
674
- type: Input
675
- }] } });
676
-
677
- class RolloutRulesComponent {
678
- constructor(dialog, settingListFormHelper) {
679
- this.dialog = dialog;
680
- this.settingListFormHelper = settingListFormHelper;
681
- this.readOnly = false;
682
- this.SettingType = SettingType;
683
- this.defaultComparisonAttributes = ['Identifier', 'Email', 'Country'];
684
- this.rolloutRuleComparators = [
685
- { value: RolloutRuleComparator.IsOneOf, label: 'IS ONE OF (cleartext)' },
686
- { value: RolloutRuleComparator.IsNotOneOf, label: 'IS NOT ONE OF (cleartext)' },
687
- { value: RolloutRuleComparator.Contains, label: 'CONTAINS (cleartext)' },
688
- { value: RolloutRuleComparator.DoesNotContain, label: 'DOES NOT CONTAIN (cleartext)' },
689
- { value: RolloutRuleComparator.SemVerIsOneOf, label: 'IS ONE OF (SemVer)' },
690
- { value: RolloutRuleComparator.SemVerIsNotOneOf, label: 'IS NOT ONE OF (SemVer)' },
691
- { value: RolloutRuleComparator.SemVerLess, label: '< (SemVer)' },
692
- { value: RolloutRuleComparator.SemVerLessOrEquals, label: '<= (SemVer)' },
693
- { value: RolloutRuleComparator.SemVerGreater, label: '> (SemVer)' },
694
- { value: RolloutRuleComparator.SemVerGreaterOrEquals, label: '>= (SemVer)' },
695
- { value: RolloutRuleComparator.NumberEquals, label: '= (Number)' },
696
- { value: RolloutRuleComparator.NumberDoesNotEqual, label: '!= (Number)' },
697
- { value: RolloutRuleComparator.NumberLess, label: '< (Number)' },
698
- { value: RolloutRuleComparator.NumberLessOrEquals, label: '<= (Number)' },
699
- { value: RolloutRuleComparator.NumberGreater, label: '> (Number)' },
700
- { value: RolloutRuleComparator.NumberGreaterOrEquals, label: '>= (Number)' },
701
- { value: RolloutRuleComparator.SensitiveIsOneOf, label: 'IS ONE OF (hashed)' },
702
- { value: RolloutRuleComparator.SensitiveIsNotOneOf, label: 'IS NOT ONE OF (hashed)' },
703
- ];
704
- this.segmentComparators = [
705
- { value: SegmentComparator.IsIn, label: 'IS IN SEGMENT' },
706
- { value: SegmentComparator.IsNotIn, label: 'IS NOT IN SEGMENT' },
707
- ];
708
- }
709
- setting() {
710
- return this.formGroup.get('setting')?.value;
711
- }
712
- rolloutRules() {
713
- return this.formGroup.get('rolloutRules');
714
- }
715
- comparisonAttributes() {
716
- return this.formGroup.root.get('comparisonAttributes')?.value;
717
- }
718
- removeRule(index) {
719
- this.rolloutRules().removeAt(index);
720
- this.rolloutRules().markAsDirty();
721
- }
722
- onDrop(event) {
723
- const rolloutRules = this.rolloutRules().controls;
724
- moveItemInArray(rolloutRules, event.previousIndex, event.currentIndex);
725
- this.formGroup.markAsDirty();
726
- }
727
- attributeChanged(event, comparisonAttribute) {
728
- if (this.defaultComparisonAttributes.indexOf(event.value) !== -1) {
729
- if (comparisonAttribute.value !== event.value) {
730
- comparisonAttribute.setValue(event.value);
731
- this.formGroup.markAsDirty();
732
- }
733
- }
734
- else {
735
- if (comparisonAttribute.value !== '') {
736
- comparisonAttribute.setValue('');
737
- this.formGroup.markAsDirty();
738
- }
739
- }
740
- }
741
- getPlaceHolder(rolloutRule) {
742
- if (!rolloutRule.controls.comparisonAttribute.value) {
743
- return '';
744
- }
745
- switch (rolloutRule.controls.comparator.value) {
746
- case RolloutRuleComparator.IsOneOf:
747
- case RolloutRuleComparator.IsNotOneOf:
748
- case RolloutRuleComparator.SensitiveIsOneOf:
749
- case RolloutRuleComparator.SensitiveIsNotOneOf:
750
- switch (rolloutRule.controls.comparisonAttribute.value.toLowerCase()) {
751
- case 'identifier':
752
- return 'e.g: user_id1, user_id2, user_id3';
753
- case 'email':
754
- return 'e.g: jane@example.com, john@example.com';
755
- case 'country':
756
- return 'e.g: France, Brazil';
757
- default:
758
- return 'e.g: value1, value2, value3';
759
- }
760
- case RolloutRuleComparator.Contains:
761
- case RolloutRuleComparator.DoesNotContain:
762
- switch (rolloutRule.controls.comparisonAttribute.value.toLowerCase()) {
763
- case 'identifier':
764
- return 'part-of-id';
765
- case 'email':
766
- return 'e.g: @example.com';
767
- case 'country':
768
- return 'e.g: United';
769
- default:
770
- return 'e.g: any-part-of-your-value-string';
771
- }
772
- case RolloutRuleComparator.SemVerIsOneOf:
773
- case RolloutRuleComparator.SemVerIsNotOneOf:
774
- return 'e.g: 1.0.0, 2.0.1';
775
- case RolloutRuleComparator.SemVerLessOrEquals:
776
- case RolloutRuleComparator.SemVerLess:
777
- case RolloutRuleComparator.SemVerGreater:
778
- case RolloutRuleComparator.SemVerGreaterOrEquals:
779
- return 'e.g: 1.0.0';
780
- case RolloutRuleComparator.NumberEquals:
781
- case RolloutRuleComparator.NumberDoesNotEqual:
782
- case RolloutRuleComparator.NumberLess:
783
- case RolloutRuleComparator.NumberLessOrEquals:
784
- case RolloutRuleComparator.NumberGreater:
785
- case RolloutRuleComparator.NumberGreaterOrEquals:
786
- return 'e.g: 42';
787
- }
788
- return '';
789
- }
790
- getComparisonValueType(rolloutRule) {
791
- return this.settingListFormHelper.getComparisonValueType(rolloutRule.controls.comparator.value);
792
- }
793
- getInfoClass(rolloutRule) {
794
- if (!rolloutRule.controls.comparisonAttribute.value) {
795
- return 'info';
796
- }
797
- switch (rolloutRule.controls.comparator.value) {
798
- case RolloutRuleComparator.IsOneOf:
799
- case RolloutRuleComparator.IsNotOneOf:
800
- case RolloutRuleComparator.Contains:
801
- case RolloutRuleComparator.DoesNotContain:
802
- return 'warn';
803
- default:
804
- return 'info';
805
- }
806
- }
807
- getInfoTooltip(rolloutRule) {
808
- if (!rolloutRule.controls.comparisonAttribute.value) {
809
- return 'Learn more about comparators';
810
- }
811
- switch (rolloutRule.controls.comparator.value) {
812
- case RolloutRuleComparator.IsOneOf:
813
- case RolloutRuleComparator.IsNotOneOf:
814
- case RolloutRuleComparator.Contains:
815
- case RolloutRuleComparator.DoesNotContain:
816
- return 'Consider using sensitive text comparators. Click to learn more.';
817
- default:
818
- return 'Click to learn more about comparators';
819
- }
820
- }
821
- comparatorChanged(rolloutRule) {
822
- let validators = [];
823
- switch (rolloutRule.controls.comparator.value) {
824
- case RolloutRuleComparator.IsOneOf:
825
- case RolloutRuleComparator.IsNotOneOf:
826
- case RolloutRuleComparator.SensitiveIsOneOf:
827
- case RolloutRuleComparator.SensitiveIsNotOneOf:
828
- case RolloutRuleComparator.Contains:
829
- case RolloutRuleComparator.DoesNotContain:
830
- validators = [Validators.required, Validators.maxLength(65535)];
831
- break;
832
- case RolloutRuleComparator.SemVerIsOneOf:
833
- case RolloutRuleComparator.SemVerIsNotOneOf:
834
- validators = [Validators.required, this.validateSemVerList];
835
- break;
836
- case RolloutRuleComparator.SemVerLessOrEquals:
837
- case RolloutRuleComparator.SemVerLess:
838
- case RolloutRuleComparator.SemVerGreater:
839
- case RolloutRuleComparator.SemVerGreaterOrEquals:
840
- validators = [Validators.required, this.validateSemVer];
841
- break;
842
- case RolloutRuleComparator.NumberEquals:
843
- case RolloutRuleComparator.NumberDoesNotEqual:
844
- case RolloutRuleComparator.NumberLess:
845
- case RolloutRuleComparator.NumberLessOrEquals:
846
- case RolloutRuleComparator.NumberGreater:
847
- case RolloutRuleComparator.NumberGreaterOrEquals:
848
- validators = [Validators.required, Validators.min(-1.79769313486232E+308), Validators.max(1.79769313486232E+308)];
849
- break;
850
- }
851
- rolloutRule.controls.comparisonValue.setValidators(validators);
852
- if (this.getComparisonValueType(rolloutRule) === "number") {
853
- const oldValue = rolloutRule.controls.comparisonValue.value;
854
- rolloutRule.controls.comparisonValue.setValue(FormHelper.normalizeNumberStoredAsString(rolloutRule.controls.comparisonValue.value));
855
- if (oldValue !== rolloutRule.controls.comparisonValue.value) {
856
- rolloutRule.controls.comparisonValue.markAsTouched();
857
- }
858
- }
859
- rolloutRule.controls.comparisonValue.updateValueAndValidity();
860
- }
861
- isListType(rolloutRule) {
862
- switch (rolloutRule.controls.comparator.value) {
863
- case RolloutRuleComparator.IsOneOf:
864
- case RolloutRuleComparator.IsNotOneOf:
865
- case RolloutRuleComparator.SensitiveIsOneOf:
866
- case RolloutRuleComparator.SensitiveIsNotOneOf:
867
- case RolloutRuleComparator.SemVerIsOneOf:
868
- case RolloutRuleComparator.SemVerIsNotOneOf:
869
- return true;
870
- default:
871
- return false;
872
- }
873
- }
874
- validateSemVer(c) {
875
- if (valid(c.value) === null) {
876
- return {
877
- validateSemVer: {
878
- valid: false
879
- }
880
- };
881
- }
882
- return null;
883
- }
884
- validateSemVerList(c) {
885
- if (!c.value) {
886
- return {
887
- validateSemVerList: {
888
- valid: false
889
- }
890
- };
891
- }
892
- const semvers = c.value.split(',').map((s) => s.trim());
893
- if (semvers.find((s) => s && s !== '' && valid(s) === null)) {
894
- return {
895
- validateSemVerList: {
896
- valid: false
897
- }
898
- };
899
- }
900
- return null;
901
- }
902
- popOut(rolloutRule) {
903
- this.dialog.open(ExpandDialogComponent, {
904
- width: '640px',
905
- data: {
906
- control: rolloutRule.controls.comparisonValue,
907
- multiline: this.isListType(rolloutRule)
908
- }
909
- });
910
- }
911
- trackByIndex(index) {
912
- return index;
913
- }
914
- getRolloutRuleValueFormControl(rolloutRule) {
915
- return rolloutRule.controls.value;
916
- }
917
- getRolloutRuleComparisonValueFormControl(rolloutRule) {
918
- return rolloutRule.controls.comparisonValue;
919
- }
920
- getRolloutRuleComparisonAttributeFormControl(rolloutRule) {
921
- return rolloutRule.controls.comparisonAttribute;
922
- }
923
- getRolloutRuleTypeFormControl(rolloutRule) {
924
- return rolloutRule.controls.type;
925
- }
926
- getRolloutRuleComparatorFormControl(rolloutRule) {
927
- return rolloutRule.controls.comparator;
928
- }
929
- getRolloutRuleSegmentComparatorFormControl(rolloutRule) {
930
- return rolloutRule.controls.segmentComparator;
931
- }
932
- getRolloutRuleSegmentIdFormControl(rolloutRule) {
933
- return rolloutRule.controls.segmentId;
934
- }
935
- }
936
- RolloutRulesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RolloutRulesComponent, deps: [{ token: i1$1.MatDialog }, { token: SettingListFormHelper }], target: i0.ɵɵFactoryTarget.Component });
937
- RolloutRulesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RolloutRulesComponent, selector: "configcat-rollout-rules", inputs: { formGroup: "formGroup", readOnly: "readOnly", segments: "segments" }, ngImport: i0, template: "<div [formGroup]=\"formGroup\">\n <div cdkDropList (cdkDropListDropped)=\"onDrop($event)\" [cdkDropListDisabled]=\"readOnly\"\n [cdkDropListData]=\"rolloutRules().controls\">\n <div *ngFor=\"let rolloutRule of rolloutRules().controls; trackBy: trackByIndex; let i = index\" cdkDrag>\n <div class=\"targeting-row\">\n <div class=\"fields flex\" *ngIf=\"getRolloutRuleTypeFormControl(rolloutRule).value === 0\">\n <div class=\"drag-handle\" cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\"\n *ngIf=\"!readOnly\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"if\">\n <mat-chip-set [class.spacing]=\"i === 0\">\n <mat-chip class=\"chip\">{{ i === 0 ? 'IF' : 'ELSE IF' }}</mat-chip>\n </mat-chip-set>\n <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">user's</a>\n </div>\n\n <select class=\"custom-select attribute-select\" matTooltip=\"Comparison attribute\"\n matTooltipPosition=\"above\"\n (change)=\"attributeChanged($event.target, getRolloutRuleComparisonAttributeFormControl(rolloutRule))\"\n [disabled]=\"readOnly\">\n <option *ngFor=\"let comparisonAttribute of defaultComparisonAttributes\"\n [selected]=\"comparisonAttribute === getRolloutRuleComparisonAttributeFormControl(rolloutRule).value\">\n {{comparisonAttribute}}</option>\n <option\n [selected]=\"defaultComparisonAttributes.indexOf(getRolloutRuleComparisonAttributeFormControl(rolloutRule).value) === -1\">\n Custom\n </option>\n </select>\n\n\n <span class=\"attribute-span\" matTooltip=\"Custom user attribute\" matTooltipPosition=\"above\"\n [hidden]=\"defaultComparisonAttributes.indexOf(getRolloutRuleComparisonAttributeFormControl(rolloutRule).value) !== -1\">\n <span class=\"attribute-error\"\n *ngIf=\"getRolloutRuleComparisonAttributeFormControl(rolloutRule).invalid\">*</span>\n <input\n [ngClass]=\"{'invalid': getRolloutRuleComparisonAttributeFormControl(rolloutRule).invalid}\"\n type=\"text\" matInput [matAutocomplete]=\"auto\"\n [formControl]=\"getRolloutRuleComparisonAttributeFormControl(rolloutRule)\" class=\"attribute\"\n placeholder=\"e.g. Eye color\">\n </span>\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let option of comparisonAttributes()\" [value]=\"option\">\n {{option}}\n </mat-option>\n </mat-autocomplete>\n\n <div class=\"select-wrapper\">\n <select class=\"custom-select\" [formControl]=\"getRolloutRuleComparatorFormControl(rolloutRule)\"\n matTooltip=\"Comparator\" matTooltipPosition=\"above\"\n (change)=\"comparatorChanged(rolloutRule)\">\n <optgroup label=\"CONFIDENTIAL TEXT\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(16, 18)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"TEXT\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(0, 4)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"SEMANTIC VERSION\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(4, 10)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"NUMBER\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(10, 16)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n </select>\n <div [class]=\"getInfoClass(rolloutRule)\" [matTooltip]=\"getInfoTooltip(rolloutRule)\">\n <a href=\"https://configcat.com/docs/advanced/targeting/#comparator\" target=\"_blank\"\n rel=\"noopener noreferrer\">\n <mat-icon>info</mat-icon>\n </a>\n </div>\n </div>\n\n <div class=\"comparison-value\">\n <span class=\"error\"\n *ngIf=\"getRolloutRuleComparisonValueFormControl(rolloutRule).invalid\">*</span>\n\n <input [ngClass]=\"{'invalid': getRolloutRuleComparisonValueFormControl(rolloutRule).invalid}\"\n [formControl]=\"getRolloutRuleComparisonValueFormControl(rolloutRule)\"\n [type]=\"getComparisonValueType(rolloutRule)\" [placeholder]=\"getPlaceHolder(rolloutRule)\"\n matTooltip=\"Comparison value\" matTooltipPosition=\"above\" inputDisplayNormalizer>\n <div class=\"expand\" matTooltip=\"Pop-out Editor\" matTooltipPosition=\"above\"\n (click)=\"popOut(rolloutRule)\" *ngIf=\"getComparisonValueType(rolloutRule)==='text'\">\n <mat-icon>height</mat-icon>\n </div>\n </div>\n\n <div class=\"delete\" matTooltip=\"Remove targeting rule\" *ngIf=\"!readOnly\" (click)=\"removeRule(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n\n <div class=\"fields flex\" *ngIf=\"getRolloutRuleTypeFormControl(rolloutRule).value === 1\">\n <div class=\"drag-handle\" cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\"\n *ngIf=\"!readOnly\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"if\">\n <mat-chip-set [class.spacing]=\"i === 0\">\n <mat-chip class=\"chip\">{{ i === 0 ? 'IF' : 'ELSE IF' }}</mat-chip>\n </mat-chip-set>\n <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">user</a>\n </div>\n\n\n <div class=\"select-wrapper\">\n <select class=\"custom-select segment-comparator\"\n [formControl]=\"getRolloutRuleSegmentComparatorFormControl(rolloutRule)\"\n matTooltip=\"Segment comparator\" matTooltipPosition=\"above\">\n <option *ngFor=\"let comparator of segmentComparators\" [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </select>\n </div>\n\n <div class=\"select-wrapper\">\n <span class=\"attribute-error\"\n *ngIf=\"getRolloutRuleSegmentIdFormControl(rolloutRule).invalid\">*</span>\n <select class=\"custom-select segment-select\"\n [formControl]=\"getRolloutRuleSegmentIdFormControl(rolloutRule)\" matTooltip=\"Segment\"\n matTooltipPosition=\"above\"\n [ngClass]=\"{'invalid': getRolloutRuleSegmentIdFormControl(rolloutRule).invalid}\">\n <option *ngFor=\"let segment of segments\" [ngValue]=\"segment.segmentId\">\n {{segment.name}}\n </option>\n </select>\n </div>\n\n\n <div class=\"delete\" matTooltip=\"Remove targeting rule\" *ngIf=\"!readOnly\" (click)=\"removeRule(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n\n\n <div class=\"value flex\">\n <div class=\"serve\" *ngIf=\"setting().settingType !== SettingType.Boolean\">\n <mat-chip-set>\n <mat-chip class=\"chip\">Serve:</mat-chip>\n </mat-chip-set>\n </div>\n\n <configcat-value class=\"served-value\"\n [valueFormControl]=\"getRolloutRuleValueFormControl(rolloutRule)\" [setting]=\"setting()\">\n </configcat-value>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [".cdk-drop-list-dragging .cdk-drag{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .3s cubic-bezier(0,0,.2,1)}.targeting-row{border:1px solid #d5d5d5;background-color:#fff;margin:1em;display:flex;position:relative;padding:.5em 0}.targeting-row:hover{background-color:#dbedff}.targeting-row .select-wrapper{position:relative}.targeting-row .info{position:absolute;cursor:pointer;top:-8px;left:166px;border-radius:50%;background-color:#fff;height:18px;width:18px}.targeting-row .info a{color:#0068f0;opacity:.5}.targeting-row .info a:hover{opacity:1}.targeting-row .info mat-icon{font-size:18px;height:18px;width:18px}.targeting-row .warn{position:absolute;cursor:pointer;top:-8px;left:166px;height:18px;width:18px;border-radius:50%;background-color:#fff}.targeting-row .warn a{color:#fdc67f}.targeting-row .warn a:hover{color:#ff9200}.targeting-row .warn mat-icon{font-size:18px;height:18px;width:18px}.custom-select{margin-left:.5em;width:170px;background-color:#fff;border:1px solid #e5e5e5;height:30px;min-height:30px;line-height:30px;min-width:170px;font-size:.8em;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}.custom-select:focus{outline-color:#e5e5e5;outline-offset:-1px}.fields{justify-content:left;max-width:1060px;flex-grow:100}.fields .if{display:flex;align-items:center}.fields .if>*{margin:0 .5em}.fields .if .spacing{margin-right:41px}.fields .if .user-link{width:40px}.fields .if .chip{font-size:12px;background-color:#67b1fc3d}.fields .attribute-span{margin-left:.5em;display:flex;align-items:center}.fields .attribute-span[hidden]{display:none}.fields .attribute{width:170px;background-color:#fff;border:1px solid #e5e5e5;margin:3px 0;min-height:28px;flex-grow:100;min-width:170px;padding:0 30px 0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300;font-size:13.3px}.fields .invalid{border:1px solid #ff5252}.fields .attribute-error{color:#ff5252;margin:0 5px}.fields .delete{position:absolute;cursor:pointer;top:-9px;right:-10px;z-index:999;border-radius:50%;background-color:#fff;height:20px;width:20px;color:#ed5251}.fields .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.fields .delete:hover mat-icon{opacity:1}.fields .drag-handle{position:absolute;cursor:-moz-grab;left:-20px;top:14px}.fields .drag-handle mat-icon{font-size:20px}.fields .attribute-select{min-width:100px;width:100px;margin-left:0}.fields .segment-comparator,.fields .segment-select{margin-left:0;margin-right:.5em}.fields .segment-more mat-icon{position:relative;top:3px;cursor:pointer;font-size:16px;height:16px;width:16px;color:#797979;margin-top:3px}.fields .comparison-value{flex-grow:100;min-width:150px;display:flex;align-items:center;margin-left:.5em;margin-right:.5em}.fields .comparison-value .error{color:#ff5252;margin:0 5px}.fields .comparison-value input{background-color:#fff;border:1px solid #e5e5e5;margin:3px 0;min-height:28px;min-width:150px;flex-grow:100;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}.fields .comparison-value input[type=text]{padding-right:30px}.fields .comparison-value input:focus{outline-color:#e5e5e5;outline-offset:-1px}.fields .comparison-value .invalid{border:1px solid #ff5252}.fields .comparison-value .expand{position:relative;height:24px;cursor:pointer;margin-left:-28px;z-index:1;color:#b3b3b3;background-color:#fff}.fields .comparison-value .expand mat-icon{transform:rotate(45deg)}.value{margin-left:auto;flex-wrap:nowrap}.value .serve{margin:0 2px 0 5px}.value .serve .chip{font-size:12px;background-color:#67b1fc3d}.value .served-value{margin:3px 0}.flex{display:flex;flex-wrap:wrap;align-items:center}@media (max-width: 1200px){.targeting-row{flex-wrap:wrap}.targeting-row .fields{max-width:500px}}@media (max-width: 920px){.value .served-value{margin:3px 7px 3px 0}.targeting-row .fields .drag-handle{left:-18px}}@media (max-width: 410px){.value .served-value{margin:7px 7px 3px 4px}}@media (max-width: 510px){.fields .comparison-value .error{display:none}}@media (max-width: 650px){.targeting-row{flex-direction:column}.targeting-row .help{left:161px}.targeting-row .fields{flex-direction:column;align-items:stretch}.targeting-row .fields .custom-select{margin:7px 7px 0}.targeting-row .fields .comparison-value{margin:7px}.targeting-row .fields .comparison-value input{margin:0 4px 0 0}.targeting-row .fields .attribute-span{margin:7px 7px 0}.targeting-row .fields .if{font-size:12px}.targeting-row .fields .if .spacing{margin-right:3px}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i5$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disabled", "disableRipple", "tabIndex", "role", "id", "aria-label", "aria-description", "value", "removable", "highlighted"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i5$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role"] }, { kind: "component", type: i10.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple", "hideSingleSelectionIndicator"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i10.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i11.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: ValueComponent, selector: "configcat-value", inputs: ["valueFormControl", "setting"] }, { kind: "directive", type: InputDisplayNormalizerDirective, selector: "input[inputDisplayNormalizer]" }] });
938
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RolloutRulesComponent, decorators: [{
939
- type: Component,
940
- args: [{ selector: 'configcat-rollout-rules', template: "<div [formGroup]=\"formGroup\">\n <div cdkDropList (cdkDropListDropped)=\"onDrop($event)\" [cdkDropListDisabled]=\"readOnly\"\n [cdkDropListData]=\"rolloutRules().controls\">\n <div *ngFor=\"let rolloutRule of rolloutRules().controls; trackBy: trackByIndex; let i = index\" cdkDrag>\n <div class=\"targeting-row\">\n <div class=\"fields flex\" *ngIf=\"getRolloutRuleTypeFormControl(rolloutRule).value === 0\">\n <div class=\"drag-handle\" cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\"\n *ngIf=\"!readOnly\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"if\">\n <mat-chip-set [class.spacing]=\"i === 0\">\n <mat-chip class=\"chip\">{{ i === 0 ? 'IF' : 'ELSE IF' }}</mat-chip>\n </mat-chip-set>\n <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">user's</a>\n </div>\n\n <select class=\"custom-select attribute-select\" matTooltip=\"Comparison attribute\"\n matTooltipPosition=\"above\"\n (change)=\"attributeChanged($event.target, getRolloutRuleComparisonAttributeFormControl(rolloutRule))\"\n [disabled]=\"readOnly\">\n <option *ngFor=\"let comparisonAttribute of defaultComparisonAttributes\"\n [selected]=\"comparisonAttribute === getRolloutRuleComparisonAttributeFormControl(rolloutRule).value\">\n {{comparisonAttribute}}</option>\n <option\n [selected]=\"defaultComparisonAttributes.indexOf(getRolloutRuleComparisonAttributeFormControl(rolloutRule).value) === -1\">\n Custom\n </option>\n </select>\n\n\n <span class=\"attribute-span\" matTooltip=\"Custom user attribute\" matTooltipPosition=\"above\"\n [hidden]=\"defaultComparisonAttributes.indexOf(getRolloutRuleComparisonAttributeFormControl(rolloutRule).value) !== -1\">\n <span class=\"attribute-error\"\n *ngIf=\"getRolloutRuleComparisonAttributeFormControl(rolloutRule).invalid\">*</span>\n <input\n [ngClass]=\"{'invalid': getRolloutRuleComparisonAttributeFormControl(rolloutRule).invalid}\"\n type=\"text\" matInput [matAutocomplete]=\"auto\"\n [formControl]=\"getRolloutRuleComparisonAttributeFormControl(rolloutRule)\" class=\"attribute\"\n placeholder=\"e.g. Eye color\">\n </span>\n\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let option of comparisonAttributes()\" [value]=\"option\">\n {{option}}\n </mat-option>\n </mat-autocomplete>\n\n <div class=\"select-wrapper\">\n <select class=\"custom-select\" [formControl]=\"getRolloutRuleComparatorFormControl(rolloutRule)\"\n matTooltip=\"Comparator\" matTooltipPosition=\"above\"\n (change)=\"comparatorChanged(rolloutRule)\">\n <optgroup label=\"CONFIDENTIAL TEXT\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(16, 18)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"TEXT\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(0, 4)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"SEMANTIC VERSION\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(4, 10)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n <optgroup label=\"NUMBER\">\n <option *ngFor=\"let comparator of rolloutRuleComparators.slice(10, 16)\"\n [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </optgroup>\n </select>\n <div [class]=\"getInfoClass(rolloutRule)\" [matTooltip]=\"getInfoTooltip(rolloutRule)\">\n <a href=\"https://configcat.com/docs/advanced/targeting/#comparator\" target=\"_blank\"\n rel=\"noopener noreferrer\">\n <mat-icon>info</mat-icon>\n </a>\n </div>\n </div>\n\n <div class=\"comparison-value\">\n <span class=\"error\"\n *ngIf=\"getRolloutRuleComparisonValueFormControl(rolloutRule).invalid\">*</span>\n\n <input [ngClass]=\"{'invalid': getRolloutRuleComparisonValueFormControl(rolloutRule).invalid}\"\n [formControl]=\"getRolloutRuleComparisonValueFormControl(rolloutRule)\"\n [type]=\"getComparisonValueType(rolloutRule)\" [placeholder]=\"getPlaceHolder(rolloutRule)\"\n matTooltip=\"Comparison value\" matTooltipPosition=\"above\" inputDisplayNormalizer>\n <div class=\"expand\" matTooltip=\"Pop-out Editor\" matTooltipPosition=\"above\"\n (click)=\"popOut(rolloutRule)\" *ngIf=\"getComparisonValueType(rolloutRule)==='text'\">\n <mat-icon>height</mat-icon>\n </div>\n </div>\n\n <div class=\"delete\" matTooltip=\"Remove targeting rule\" *ngIf=\"!readOnly\" (click)=\"removeRule(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n\n <div class=\"fields flex\" *ngIf=\"getRolloutRuleTypeFormControl(rolloutRule).value === 1\">\n <div class=\"drag-handle\" cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\"\n *ngIf=\"!readOnly\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"if\">\n <mat-chip-set [class.spacing]=\"i === 0\">\n <mat-chip class=\"chip\">{{ i === 0 ? 'IF' : 'ELSE IF' }}</mat-chip>\n </mat-chip-set>\n <a href=\"https://configcat.com/docs/advanced/user-object\" target=\"_blank\"\n rel=\"noopener noreferrer\">user</a>\n </div>\n\n\n <div class=\"select-wrapper\">\n <select class=\"custom-select segment-comparator\"\n [formControl]=\"getRolloutRuleSegmentComparatorFormControl(rolloutRule)\"\n matTooltip=\"Segment comparator\" matTooltipPosition=\"above\">\n <option *ngFor=\"let comparator of segmentComparators\" [ngValue]=\"comparator.value\">\n {{comparator.label}}\n </option>\n </select>\n </div>\n\n <div class=\"select-wrapper\">\n <span class=\"attribute-error\"\n *ngIf=\"getRolloutRuleSegmentIdFormControl(rolloutRule).invalid\">*</span>\n <select class=\"custom-select segment-select\"\n [formControl]=\"getRolloutRuleSegmentIdFormControl(rolloutRule)\" matTooltip=\"Segment\"\n matTooltipPosition=\"above\"\n [ngClass]=\"{'invalid': getRolloutRuleSegmentIdFormControl(rolloutRule).invalid}\">\n <option *ngFor=\"let segment of segments\" [ngValue]=\"segment.segmentId\">\n {{segment.name}}\n </option>\n </select>\n </div>\n\n\n <div class=\"delete\" matTooltip=\"Remove targeting rule\" *ngIf=\"!readOnly\" (click)=\"removeRule(i)\">\n <mat-icon>cancel</mat-icon>\n </div>\n </div>\n\n\n <div class=\"value flex\">\n <div class=\"serve\" *ngIf=\"setting().settingType !== SettingType.Boolean\">\n <mat-chip-set>\n <mat-chip class=\"chip\">Serve:</mat-chip>\n </mat-chip-set>\n </div>\n\n <configcat-value class=\"served-value\"\n [valueFormControl]=\"getRolloutRuleValueFormControl(rolloutRule)\" [setting]=\"setting()\">\n </configcat-value>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [".cdk-drop-list-dragging .cdk-drag{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .3s cubic-bezier(0,0,.2,1)}.targeting-row{border:1px solid #d5d5d5;background-color:#fff;margin:1em;display:flex;position:relative;padding:.5em 0}.targeting-row:hover{background-color:#dbedff}.targeting-row .select-wrapper{position:relative}.targeting-row .info{position:absolute;cursor:pointer;top:-8px;left:166px;border-radius:50%;background-color:#fff;height:18px;width:18px}.targeting-row .info a{color:#0068f0;opacity:.5}.targeting-row .info a:hover{opacity:1}.targeting-row .info mat-icon{font-size:18px;height:18px;width:18px}.targeting-row .warn{position:absolute;cursor:pointer;top:-8px;left:166px;height:18px;width:18px;border-radius:50%;background-color:#fff}.targeting-row .warn a{color:#fdc67f}.targeting-row .warn a:hover{color:#ff9200}.targeting-row .warn mat-icon{font-size:18px;height:18px;width:18px}.custom-select{margin-left:.5em;width:170px;background-color:#fff;border:1px solid #e5e5e5;height:30px;min-height:30px;line-height:30px;min-width:170px;font-size:.8em;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}.custom-select:focus{outline-color:#e5e5e5;outline-offset:-1px}.fields{justify-content:left;max-width:1060px;flex-grow:100}.fields .if{display:flex;align-items:center}.fields .if>*{margin:0 .5em}.fields .if .spacing{margin-right:41px}.fields .if .user-link{width:40px}.fields .if .chip{font-size:12px;background-color:#67b1fc3d}.fields .attribute-span{margin-left:.5em;display:flex;align-items:center}.fields .attribute-span[hidden]{display:none}.fields .attribute{width:170px;background-color:#fff;border:1px solid #e5e5e5;margin:3px 0;min-height:28px;flex-grow:100;min-width:170px;padding:0 30px 0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300;font-size:13.3px}.fields .invalid{border:1px solid #ff5252}.fields .attribute-error{color:#ff5252;margin:0 5px}.fields .delete{position:absolute;cursor:pointer;top:-9px;right:-10px;z-index:999;border-radius:50%;background-color:#fff;height:20px;width:20px;color:#ed5251}.fields .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.fields .delete:hover mat-icon{opacity:1}.fields .drag-handle{position:absolute;cursor:-moz-grab;left:-20px;top:14px}.fields .drag-handle mat-icon{font-size:20px}.fields .attribute-select{min-width:100px;width:100px;margin-left:0}.fields .segment-comparator,.fields .segment-select{margin-left:0;margin-right:.5em}.fields .segment-more mat-icon{position:relative;top:3px;cursor:pointer;font-size:16px;height:16px;width:16px;color:#797979;margin-top:3px}.fields .comparison-value{flex-grow:100;min-width:150px;display:flex;align-items:center;margin-left:.5em;margin-right:.5em}.fields .comparison-value .error{color:#ff5252;margin:0 5px}.fields .comparison-value input{background-color:#fff;border:1px solid #e5e5e5;margin:3px 0;min-height:28px;min-width:150px;flex-grow:100;padding:0 5px;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;font-weight:300}.fields .comparison-value input[type=text]{padding-right:30px}.fields .comparison-value input:focus{outline-color:#e5e5e5;outline-offset:-1px}.fields .comparison-value .invalid{border:1px solid #ff5252}.fields .comparison-value .expand{position:relative;height:24px;cursor:pointer;margin-left:-28px;z-index:1;color:#b3b3b3;background-color:#fff}.fields .comparison-value .expand mat-icon{transform:rotate(45deg)}.value{margin-left:auto;flex-wrap:nowrap}.value .serve{margin:0 2px 0 5px}.value .serve .chip{font-size:12px;background-color:#67b1fc3d}.value .served-value{margin:3px 0}.flex{display:flex;flex-wrap:wrap;align-items:center}@media (max-width: 1200px){.targeting-row{flex-wrap:wrap}.targeting-row .fields{max-width:500px}}@media (max-width: 920px){.value .served-value{margin:3px 7px 3px 0}.targeting-row .fields .drag-handle{left:-18px}}@media (max-width: 410px){.value .served-value{margin:7px 7px 3px 4px}}@media (max-width: 510px){.fields .comparison-value .error{display:none}}@media (max-width: 650px){.targeting-row{flex-direction:column}.targeting-row .help{left:161px}.targeting-row .fields{flex-direction:column;align-items:stretch}.targeting-row .fields .custom-select{margin:7px 7px 0}.targeting-row .fields .comparison-value{margin:7px}.targeting-row .fields .comparison-value input{margin:0 4px 0 0}.targeting-row .fields .attribute-span{margin:7px 7px 0}.targeting-row .fields .if{font-size:12px}.targeting-row .fields .if .spacing{margin-right:3px}}\n"] }]
941
- }], ctorParameters: function () { return [{ type: i1$1.MatDialog }, { type: SettingListFormHelper }]; }, propDecorators: { formGroup: [{
942
- type: Input
943
- }], readOnly: [{
944
- type: Input
945
- }], segments: [{
946
- type: Input
947
- }] } });
948
-
949
- class SettingComponent {
950
- constructor(formHelper) {
951
- this.formHelper = formHelper;
952
- this.dashboardBasePath = 'https://app.configcat.com';
953
- this.readOnly = false;
954
- this.canDeleteSetting = false;
955
- this.deleteSettingText = 'Delete setting';
956
- this.showEnvironmentName = false;
957
- this.deleteSettingRequested = new EventEmitter();
958
- this.rulesBeingRendered = false;
959
- this.SettingType = SettingType;
960
- }
961
- ngOnInit() { }
962
- environment() {
963
- return this.formGroup.root.get('environment')?.value;
964
- }
965
- setting() {
966
- return this.formGroup.get('setting')?.value;
967
- }
968
- integrationLinks() {
969
- return this.formGroup.get('integrationLinks');
970
- }
971
- rolloutRules() {
972
- return this.formGroup.get('rolloutRules');
973
- }
974
- rolloutPercentageItems() {
975
- return this.formGroup.get('rolloutPercentageItems');
976
- }
977
- value() {
978
- return this.formGroup.get('value');
979
- }
980
- addRolloutRule() {
981
- this.rolloutRules().push(this.formHelper.createRolloutRuleFormGroup({
982
- comparisonAttribute: 'Identifier',
983
- comparator: RolloutRuleComparator.SensitiveIsOneOf,
984
- comparisonValue: '',
985
- value: this.setting().settingType === SettingType.Boolean ? false : null
986
- }, this.readOnly, this.setting().settingType));
987
- this.rolloutRules().markAsDirty();
988
- }
989
- addSegmentRolloutRule() {
990
- this.rolloutRules().push(this.formHelper.createRolloutRuleFormGroup({
991
- segmentComparator: SegmentComparator.IsIn,
992
- value: this.setting().settingType === SettingType.Boolean ? false : null
993
- }, this.readOnly, this.setting().settingType));
994
- this.rolloutRules().markAsDirty();
995
- }
996
- removeRolloutRules() {
997
- this.rolloutRules().clear();
998
- this.rolloutRules().markAsDirty();
999
- }
1000
- addRolloutPercentageItem() {
1001
- if (this.rolloutPercentageItems().length === 0) {
1002
- switch (this.setting().settingType) {
1003
- case SettingType.Boolean:
1004
- this.rolloutPercentageItems().push(this.formHelper.createRolloutPercentageItemFormGroup({
1005
- percentage: 0,
1006
- value: true
1007
- }, this.readOnly, this.setting().settingType));
1008
- this.rolloutPercentageItems().push(this.formHelper.createRolloutPercentageItemFormGroup({
1009
- percentage: 100,
1010
- value: false
1011
- }, this.readOnly, this.setting().settingType));
1012
- break;
1013
- case SettingType.String:
1014
- case SettingType.Int:
1015
- case SettingType.Double:
1016
- for (let i = 0; i < 4; i++) {
1017
- this.rolloutPercentageItems().push(this.formHelper.createRolloutPercentageItemFormGroup({
1018
- percentage: 25,
1019
- value: null
1020
- }, this.readOnly, this.setting().settingType));
1021
- }
1022
- break;
1023
- }
1024
- }
1025
- else if (this.setting().settingType !== SettingType.Boolean) {
1026
- this.rolloutPercentageItems().push(this.formHelper.createRolloutPercentageItemFormGroup({
1027
- percentage: 0,
1028
- value: null
1029
- }, this.readOnly, this.setting().settingType));
1030
- }
1031
- this.rolloutPercentageItems().markAsDirty();
1032
- }
1033
- removeRolloutPercentageItems() {
1034
- this.rolloutPercentageItems().clear();
1035
- this.rolloutPercentageItems().markAsDirty();
1036
- }
1037
- deleteSetting() {
1038
- this.deleteSettingRequested.emit({ setting: this.setting() });
1039
- }
1040
- getDashboardUrl() {
1041
- return this.dashboardBasePath + '/' + this.productId + '/' + this.configId + '/' + this.environmentId + '?settingId=' + this.setting().settingId;
1042
- }
1043
- }
1044
- SettingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingComponent, deps: [{ token: SettingListFormHelper }], target: i0.ɵɵFactoryTarget.Component });
1045
- SettingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SettingComponent, selector: "setting", inputs: { dashboardBasePath: "dashboardBasePath", productId: "productId", environmentId: "environmentId", configId: "configId", formGroup: "formGroup", readOnly: "readOnly", canDeleteSetting: "canDeleteSetting", deleteSettingText: "deleteSettingText", showEnvironmentName: "showEnvironmentName", segments: "segments" }, outputs: { deleteSettingRequested: "deleteSettingRequested" }, ngImport: i0, template: "<div class=\"setting-full\" [formGroup]=\"formGroup\">\n <div class=\"delete\" (click)=\"deleteSetting()\" *ngIf=\"canDeleteSetting\" [matTooltip]=\"deleteSettingText\"\n data-robot=\"deleteSetting\">\n <mat-icon>cancel</mat-icon>\n </div>\n <div class=\"setting-header\">\n <div class=\"setting-name\">\n <div class=\"name\" data-robot=\"settingName\">\n {{setting().name}}\n <span *ngIf=\"showEnvironmentName\"> ({{environment().name}})</span>\n </div>\n </div>\n </div>\n <div class=\"setting-content\">\n <div class=\"setting-details\">\n <div class=\"setting-key\"><code data-robot=\"settingKey\">{{setting().key}}</code></div>\n <span *ngIf=\"setting().hint\" class=\"description\">{{setting().hint}}</span>\n <div class=\"open\"><a [href]=\"getDashboardUrl()\" target=\"_blank\" rel=\"noopener noreferrer\">Open in ConfigCat</a>\n </div>\n </div>\n\n <div class=\"rules-list\">\n <div>\n <configcat-rollout-rules *ngIf=\"rolloutRules().controls.length !== 0\" [formGroup]=\"formGroup\"\n [segments]=\"segments\" [readOnly]=\"readOnly\">\n </configcat-rollout-rules>\n </div>\n\n <configcat-rollout-percentage-items *ngIf=\"rolloutPercentageItems().controls.length !== 0\" [formGroup]=\"formGroup\"\n [readOnly]=\"readOnly\">\n </configcat-rollout-percentage-items>\n\n <div class=\"all-other flex\">\n <div *ngIf=\"rolloutPercentageItems().length === 0 && rolloutRules().length !== 0\"\n matTooltip=\"This value will be served to all users who the above rules don't apply.\"\n matTooltipPosition=\"above\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To all other users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <div *ngIf=\"rolloutPercentageItems().length !== 0\"\n matTooltip=\"This fallback value will be served in case the user can't be identified.\"\n matTooltipPosition=\"above\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To unidentified users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <div *ngIf=\"rolloutPercentageItems().length === 0 && rolloutRules().length === 0\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To all users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <configcat-value class=\"served-value\" [valueFormControl]=\"value()\" [setting]=\"setting()\">\n </configcat-value>\n </div>\n <div class=\"buttons\">\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addRolloutRule()\" *ngIf=\"!readOnly\">\n {{rolloutRules().length === 0 ? 'Target specific users' : 'Add new targeting rule'}}\n </button>\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addSegmentRolloutRule()\" *ngIf=\"!readOnly\">\n {{rolloutRules().length === 0 ? 'Target segment' : 'Target new segment'}}\n </button>\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addRolloutPercentageItem()\"\n *ngIf=\"!readOnly\"\n [disabled]=\"setting().settingType === SettingType.Boolean && rolloutPercentageItems().length !== 0\">\n {{rolloutPercentageItems().length === 0 ? 'Target % of users' : 'Add new % option'}}\n </button>\n </div>\n </div>\n </div>\n</div>", styles: [".setting-full{position:relative;display:flex;flex-wrap:nowrap;flex-direction:column}.setting-full .delete{position:absolute;right:-10px;top:-10px;color:#ed5251;background-color:#fff;border-radius:50%;height:20px;width:20px;cursor:pointer}.setting-full .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.setting-full .delete:hover mat-icon{opacity:1}.setting-full .setting-header{padding:1.5em .8em 0 1em}.setting-full .setting-header .setting-name{flex-direction:row}.setting-full .setting-header .setting-name:hover>.edit{visibility:visible}.setting-full .setting-header .setting-name .name{font-weight:700;word-wrap:break-word;max-width:100%}.setting-full .setting-header .setting-name .edit{margin:5px 0 0 5px;cursor:pointer;visibility:hidden;color:gray}.setting-full .setting-header .setting-name .edit:hover{visibility:visible}.setting-full .setting-header .setting-name .edit mat-icon{font-size:18px}.setting-full .setting-header .setting-meta{margin-left:auto;margin-right:14px;font-size:.7em;color:gray}.setting-full .setting-content{display:flex}.setting-full .setting-content .setting-details{display:flex;flex-direction:column;width:400px;padding:0 0 .5em .5em}.setting-full .setting-content .setting-details>*{margin:.5em}.setting-full .setting-content .setting-details .open{font-size:14px}.setting-full .setting-content .setting-details .integrations{font-size:.8rem}.setting-full .setting-content .setting-details .integrations>div{margin:3px}.setting-full .setting-content .setting-details .integrations>div>a:hover{text-decoration:underline}.setting-full .setting-content .setting-details .setting-key{word-wrap:break-word}.setting-full .setting-content .setting-details .description{font-size:.8em;white-space:pre-wrap;word-wrap:break-word;max-width:300px}.setting-full .setting-content .setting-details code{background-color:#d3d3d3;padding:3px 6px}.setting-full .setting-content .rules-list{width:100%;padding:0 .3em .3em 1em}.setting-full .setting-content .targeting-button{margin-left:.5rem;margin-right:.5rem;margin-bottom:1.5em;text-transform:uppercase}.all-other{min-height:40px;justify-content:flex-start;border:1px solid #d5d5d5;background-color:#fff;margin:.5em 1em;padding:4px 0 4px .5em}.all-other .chip{font-size:12px;background-color:#67b1fc3d}.all-other .served-value{margin-left:auto;margin-top:3px;margin-bottom:3px}.end{margin-left:auto}.buttons{display:flex;margin-left:.5rem;margin-right:.5rem}.buttons .updated-date{font-size:.7em;margin-left:auto;margin-right:22px;color:gray}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}.show-hide-toggle a{font-size:.8rem}.sige-button{background-color:#d9eadc;color:#363636;cursor:pointer;justify-content:center;padding:.375em .75em;text-align:center;white-space:nowrap;font-size:.75rem;border:1px solid #dbdbdb;box-shadow:none;display:inline-flex;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif}.sige-button:hover{background-color:#bad0be}.sige-button:disabled{background-color:#fff;color:#b3b3b3}@media (max-width: 1200px){.setting-details{width:300px!important}}@media (max-width: 920px){.setting-full .setting-content{flex-wrap:wrap}.setting-full .setting-content .rules-list{padding:0}.setting-full .setting-content .targeting-button{margin-bottom:.5em;margin-top:.5em;padding:.6em 0}.colorbar{min-width:5px}.buttons{flex-direction:column;margin-bottom:.5em;margin-left:.4em;margin-right:.4em}.created-date,.updated-date{display:none}.setting-details{width:100%!important;padding:.2em 0 .2em .2em}.setting-details .description{max-width:none!important}.rollout-rules{margin-bottom:1em}.all-other{margin:1em;padding:7px 0 7px .5em}.all-other .served-value{margin:7px 7px 4px auto}}@media (max-width: 380px){.mat-mdc-standard-chip{min-height:auto!important;height:auto!important}.mat-chip-list-wrapper{padding-right:7px}.sige-button{font-size:.65rem}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i5$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disabled", "disableRipple", "tabIndex", "role", "id", "aria-label", "aria-description", "value", "removable", "highlighted"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i5$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role"] }, { kind: "component", type: RolloutPercentageItemsComponent, selector: "configcat-rollout-percentage-items", inputs: ["formGroup", "readOnly"] }, { kind: "component", type: RolloutRulesComponent, selector: "configcat-rollout-rules", inputs: ["formGroup", "readOnly", "segments"] }, { kind: "component", type: ValueComponent, selector: "configcat-value", inputs: ["valueFormControl", "setting"] }] });
1046
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingComponent, decorators: [{
1047
- type: Component,
1048
- args: [{ selector: 'setting', template: "<div class=\"setting-full\" [formGroup]=\"formGroup\">\n <div class=\"delete\" (click)=\"deleteSetting()\" *ngIf=\"canDeleteSetting\" [matTooltip]=\"deleteSettingText\"\n data-robot=\"deleteSetting\">\n <mat-icon>cancel</mat-icon>\n </div>\n <div class=\"setting-header\">\n <div class=\"setting-name\">\n <div class=\"name\" data-robot=\"settingName\">\n {{setting().name}}\n <span *ngIf=\"showEnvironmentName\"> ({{environment().name}})</span>\n </div>\n </div>\n </div>\n <div class=\"setting-content\">\n <div class=\"setting-details\">\n <div class=\"setting-key\"><code data-robot=\"settingKey\">{{setting().key}}</code></div>\n <span *ngIf=\"setting().hint\" class=\"description\">{{setting().hint}}</span>\n <div class=\"open\"><a [href]=\"getDashboardUrl()\" target=\"_blank\" rel=\"noopener noreferrer\">Open in ConfigCat</a>\n </div>\n </div>\n\n <div class=\"rules-list\">\n <div>\n <configcat-rollout-rules *ngIf=\"rolloutRules().controls.length !== 0\" [formGroup]=\"formGroup\"\n [segments]=\"segments\" [readOnly]=\"readOnly\">\n </configcat-rollout-rules>\n </div>\n\n <configcat-rollout-percentage-items *ngIf=\"rolloutPercentageItems().controls.length !== 0\" [formGroup]=\"formGroup\"\n [readOnly]=\"readOnly\">\n </configcat-rollout-percentage-items>\n\n <div class=\"all-other flex\">\n <div *ngIf=\"rolloutPercentageItems().length === 0 && rolloutRules().length !== 0\"\n matTooltip=\"This value will be served to all users who the above rules don't apply.\"\n matTooltipPosition=\"above\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To all other users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <div *ngIf=\"rolloutPercentageItems().length !== 0\"\n matTooltip=\"This fallback value will be served in case the user can't be identified.\"\n matTooltipPosition=\"above\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To unidentified users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <div *ngIf=\"rolloutPercentageItems().length === 0 && rolloutRules().length === 0\">\n <mat-chip-set>\n <mat-chip class=\"chip\">To all users, serve:</mat-chip>\n </mat-chip-set>\n </div>\n <configcat-value class=\"served-value\" [valueFormControl]=\"value()\" [setting]=\"setting()\">\n </configcat-value>\n </div>\n <div class=\"buttons\">\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addRolloutRule()\" *ngIf=\"!readOnly\">\n {{rolloutRules().length === 0 ? 'Target specific users' : 'Add new targeting rule'}}\n </button>\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addSegmentRolloutRule()\" *ngIf=\"!readOnly\">\n {{rolloutRules().length === 0 ? 'Target segment' : 'Target new segment'}}\n </button>\n <button type=\"button\" class=\"sige-button targeting-button\" (click)=\"addRolloutPercentageItem()\"\n *ngIf=\"!readOnly\"\n [disabled]=\"setting().settingType === SettingType.Boolean && rolloutPercentageItems().length !== 0\">\n {{rolloutPercentageItems().length === 0 ? 'Target % of users' : 'Add new % option'}}\n </button>\n </div>\n </div>\n </div>\n</div>", styles: [".setting-full{position:relative;display:flex;flex-wrap:nowrap;flex-direction:column}.setting-full .delete{position:absolute;right:-10px;top:-10px;color:#ed5251;background-color:#fff;border-radius:50%;height:20px;width:20px;cursor:pointer}.setting-full .delete mat-icon{font-size:20px;height:20px;width:20px;opacity:.5}.setting-full .delete:hover mat-icon{opacity:1}.setting-full .setting-header{padding:1.5em .8em 0 1em}.setting-full .setting-header .setting-name{flex-direction:row}.setting-full .setting-header .setting-name:hover>.edit{visibility:visible}.setting-full .setting-header .setting-name .name{font-weight:700;word-wrap:break-word;max-width:100%}.setting-full .setting-header .setting-name .edit{margin:5px 0 0 5px;cursor:pointer;visibility:hidden;color:gray}.setting-full .setting-header .setting-name .edit:hover{visibility:visible}.setting-full .setting-header .setting-name .edit mat-icon{font-size:18px}.setting-full .setting-header .setting-meta{margin-left:auto;margin-right:14px;font-size:.7em;color:gray}.setting-full .setting-content{display:flex}.setting-full .setting-content .setting-details{display:flex;flex-direction:column;width:400px;padding:0 0 .5em .5em}.setting-full .setting-content .setting-details>*{margin:.5em}.setting-full .setting-content .setting-details .open{font-size:14px}.setting-full .setting-content .setting-details .integrations{font-size:.8rem}.setting-full .setting-content .setting-details .integrations>div{margin:3px}.setting-full .setting-content .setting-details .integrations>div>a:hover{text-decoration:underline}.setting-full .setting-content .setting-details .setting-key{word-wrap:break-word}.setting-full .setting-content .setting-details .description{font-size:.8em;white-space:pre-wrap;word-wrap:break-word;max-width:300px}.setting-full .setting-content .setting-details code{background-color:#d3d3d3;padding:3px 6px}.setting-full .setting-content .rules-list{width:100%;padding:0 .3em .3em 1em}.setting-full .setting-content .targeting-button{margin-left:.5rem;margin-right:.5rem;margin-bottom:1.5em;text-transform:uppercase}.all-other{min-height:40px;justify-content:flex-start;border:1px solid #d5d5d5;background-color:#fff;margin:.5em 1em;padding:4px 0 4px .5em}.all-other .chip{font-size:12px;background-color:#67b1fc3d}.all-other .served-value{margin-left:auto;margin-top:3px;margin-bottom:3px}.end{margin-left:auto}.buttons{display:flex;margin-left:.5rem;margin-right:.5rem}.buttons .updated-date{font-size:.7em;margin-left:auto;margin-right:22px;color:gray}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}.show-hide-toggle a{font-size:.8rem}.sige-button{background-color:#d9eadc;color:#363636;cursor:pointer;justify-content:center;padding:.375em .75em;text-align:center;white-space:nowrap;font-size:.75rem;border:1px solid #dbdbdb;box-shadow:none;display:inline-flex;font-family:Montserrat,Roboto,Helvetica Neue,sans-serif}.sige-button:hover{background-color:#bad0be}.sige-button:disabled{background-color:#fff;color:#b3b3b3}@media (max-width: 1200px){.setting-details{width:300px!important}}@media (max-width: 920px){.setting-full .setting-content{flex-wrap:wrap}.setting-full .setting-content .rules-list{padding:0}.setting-full .setting-content .targeting-button{margin-bottom:.5em;margin-top:.5em;padding:.6em 0}.colorbar{min-width:5px}.buttons{flex-direction:column;margin-bottom:.5em;margin-left:.4em;margin-right:.4em}.created-date,.updated-date{display:none}.setting-details{width:100%!important;padding:.2em 0 .2em .2em}.setting-details .description{max-width:none!important}.rollout-rules{margin-bottom:1em}.all-other{margin:1em;padding:7px 0 7px .5em}.all-other .served-value{margin:7px 7px 4px auto}}@media (max-width: 380px){.mat-mdc-standard-chip{min-height:auto!important;height:auto!important}.mat-chip-list-wrapper{padding-right:7px}.sige-button{font-size:.65rem}}\n"] }]
1049
- }], ctorParameters: function () { return [{ type: SettingListFormHelper }]; }, propDecorators: { dashboardBasePath: [{
1050
- type: Input
1051
- }], productId: [{
1052
- type: Input
1053
- }], environmentId: [{
1054
- type: Input
1055
- }], configId: [{
1056
- type: Input
1057
- }], formGroup: [{
1058
- type: Input
1059
- }], readOnly: [{
1060
- type: Input
1061
- }], canDeleteSetting: [{
1062
- type: Input
1063
- }], deleteSettingText: [{
1064
- type: Input
1065
- }], showEnvironmentName: [{
1066
- type: Input
1067
- }], segments: [{
1068
- type: Input
1069
- }], deleteSettingRequested: [{
1070
- type: Output
1071
- }] } });
1072
-
1073
- class SettingListComponent {
1074
- constructor(formHelper, snackBar, dialog) {
1075
- this.formHelper = formHelper;
1076
- this.snackBar = snackBar;
1077
- this.dialog = dialog;
1078
- this.dashboardBasePath = 'https://app.configcat.com';
1079
- this.canDeleteSetting = false;
1080
- this.deleteSettingText = 'Delete setting';
1081
- this.showEnvironmentName = false;
1082
- this.loadSucceeded = new EventEmitter();
1083
- this.deleteSettingRequested = new EventEmitter();
1084
- this.formValuesChanged = new EventEmitter();
1085
- this.loading = true;
1086
- this.submitting = false;
1087
- this.showRevertQuestion = false;
1088
- this.showFeedBackMessage = false;
1089
- this.readOnly = false;
1090
- }
1091
- ngOnChanges() {
1092
- this.reloadSettingValues();
1093
- }
1094
- ngOnDestroy() {
1095
- if (this.formValuesChangedSubscription) {
1096
- this.formValuesChangedSubscription.unsubscribe();
1097
- this.formValuesChangedSubscription = null;
1098
- }
1099
- }
1100
- reloadSettingValues() {
1101
- this.showFeedBackMessage = false;
1102
- this.loading = true;
1103
- forkJoin({
1104
- segments: this.loadSegments(),
1105
- settingValues: this.loadSettingValues()
1106
- }).subscribe(result => {
1107
- this.readOnly = result.settingValues.readOnly;
1108
- this.settingValues = result.settingValues;
1109
- this.segments = result.segments;
1110
- this.createFormGroup();
1111
- this.loading = false;
1112
- this.loadSucceeded.emit(true);
1113
- }, () => {
1114
- this.snackBar.open('Ooops. We could not load your Feature Flags and Settings. Please try again or contact us.', 'Dismiss', { duration: 60000, panelClass: 'red-snackbar' });
1115
- });
1116
- }
1117
- createFormGroup() {
1118
- this.formGroup = this.formHelper.createSettingValuesFormGroup(this.settingValues);
1119
- this.formValuesChangedSubscription = this.formGroup.valueChanges.subscribe(() => {
1120
- this.formValuesChanged.emit();
1121
- });
1122
- }
1123
- settingValuesFormArray() {
1124
- return this.formGroup.get('settingValues');
1125
- }
1126
- getSettingValueFormGroups() {
1127
- return this.settingValuesFormArray().controls.map(c => c);
1128
- }
1129
- buildUpdateSettingValuesModel(settingValuesVM) {
1130
- return settingValuesVM.map(settingValueVM => {
1131
- return {
1132
- rolloutRules: settingValueVM.rolloutRules?.map(rolloutRuleVM => ({
1133
- comparisonAttribute: rolloutRuleVM.comparisonAttribute,
1134
- comparator: rolloutRuleVM.comparator,
1135
- comparisonValue: this.formHelper.normalizeComparisonValue(rolloutRuleVM.comparator, rolloutRuleVM.comparisonValue),
1136
- segmentComparator: rolloutRuleVM.segmentComparator,
1137
- segmentId: rolloutRuleVM.segmentId,
1138
- value: rolloutRuleVM.value
1139
- })),
1140
- rolloutPercentageItems: settingValueVM.rolloutPercentageItems?.map(rolloutPercentageItemVM => ({
1141
- percentage: rolloutPercentageItemVM.percentage,
1142
- value: rolloutPercentageItemVM.value
1143
- })),
1144
- value: settingValueVM.value
1145
- };
1146
- });
1147
- }
1148
- submit() {
1149
- if (!this.formGroup || !this.formGroup.valid) {
1150
- this.showFeedBackMessage = true;
1151
- this.formGroup.markAsTouched();
1152
- return;
1153
- }
1154
- this.showFeedBackMessage = false;
1155
- this.submitting = true;
1156
- const updateSettingValuesModel = {
1157
- settingValues: this.buildUpdateSettingValuesModel(this.formGroup.controls.settingValues.value),
1158
- knownLastUpdatedAt: this.settingValues.lastUpdatedAt,
1159
- forced: false
1160
- };
1161
- if (this.settingValues.reasonRequired) {
1162
- const dialogRef = this.dialog.open(ReasonDialogComponent, {
1163
- width: '450px'
1164
- });
1165
- dialogRef.afterClosed()
1166
- .subscribe(result => {
1167
- if (result && result.button === 'save' && result.reason) {
1168
- updateSettingValuesModel.reason = result.reason;
1169
- this.updateSettingValues(updateSettingValuesModel);
1170
- }
1171
- else {
1172
- this.submitting = false;
1173
- }
1174
- });
1175
- return;
1176
- }
1177
- this.updateSettingValues(updateSettingValuesModel);
1178
- }
1179
- updateSettingValues(updateSettingValuesModel) {
1180
- this.onSave(updateSettingValuesModel).subscribe(settingValues => {
1181
- this.settingValues = settingValues;
1182
- this.createFormGroup();
1183
- this.submitting = false;
1184
- this.snackBar.openFromComponent(SaveSnackbarComponent, { duration: 5000, panelClass: 'green-snackbar' });
1185
- }, (error) => {
1186
- if (error.status === 400 && error.error && error.error.Reason && error.error.Reason[0] === 'Reason required') {
1187
- const dialogRef = this.dialog.open(ReasonDialogComponent, {
1188
- width: '450px'
1189
- });
1190
- dialogRef.afterClosed()
1191
- .subscribe(result => {
1192
- if (result && result.button === 'save' && result.reason) {
1193
- updateSettingValuesModel.reason = result.reason;
1194
- this.updateSettingValues(updateSettingValuesModel);
1195
- }
1196
- else {
1197
- this.submitting = false;
1198
- }
1199
- });
1200
- return;
1201
- }
1202
- this.formGroup.setErrors({ internalServerError: 'Internal server error' });
1203
- this.showFeedBackMessage = true;
1204
- });
1205
- }
1206
- handleRevertYes() {
1207
- this.showRevertQuestion = false;
1208
- this.reloadSettingValues();
1209
- }
1210
- handleRevertCancel() {
1211
- this.showRevertQuestion = false;
1212
- }
1213
- onDeleteSettingRequested(setting) {
1214
- this.deleteSettingRequested.emit({
1215
- setting: setting.setting,
1216
- environment: this.settingValues.environment,
1217
- config: this.settingValues.config
1218
- });
1219
- }
1220
- }
1221
- SettingListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingListComponent, deps: [{ token: SettingListFormHelper }, { token: i2$2.MatSnackBar }, { token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1222
- SettingListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SettingListComponent, selector: "configcat-setting-list", inputs: { productId: "productId", environmentId: "environmentId", configId: "configId", dashboardBasePath: "dashboardBasePath", canDeleteSetting: "canDeleteSetting", onSave: "onSave", loadSettingValues: "loadSettingValues", loadSegments: "loadSegments", deleteSettingText: "deleteSettingText", showEnvironmentName: "showEnvironmentName" }, outputs: { loadSucceeded: "loadSucceeded", deleteSettingRequested: "deleteSettingRequested", formValuesChanged: "formValuesChanged" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\" *ngIf=\"!loading\">\n <div class=\"wrapper\" *ngFor=\"let settingValueFromGroup of getSettingValueFormGroups(); let i = index\">\n <setting [formGroup]=\"settingValueFromGroup\" [readOnly]=\"readOnly\" [canDeleteSetting]=\"canDeleteSetting\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" [deleteSettingText]=\"deleteSettingText\"\n [showEnvironmentName]=\"showEnvironmentName\" [segments]=\"segments\" [productId]=\"productId\" [configId]=\"configId\"\n [environmentId]=\"environmentId\" [dashboardBasePath]=\"dashboardBasePath\">\n </setting>\n </div>\n\n <div class=\"save\" *ngIf=\"!readOnly && !submitting && formGroup.dirty\">\n <div class=\"feedback\" *ngIf=\"formGroup.touched && formGroup.invalid && showFeedBackMessage\">\n <div class=\"error\" *ngIf=\"formGroup.errors && formGroup.errors.internalServerError\">\n <span>Something went wrong and we could not save your settings. You can try again or <a\n href=\"https://configcat.com/support\" target=\"_blank\" rel=\"noopener noreferrer\">contact us.</a></span>\n </div>\n <div class=\"error\" *ngIf=\"!formGroup.errors || !formGroup.errors.internalServerError\">\n <span>Oh no! A feature flag has invalid or missing data.</span>\n </div>\n </div>\n <button type=\"button\" mat-stroked-button *ngIf=\"!showRevertQuestion\" (click)=\"showRevertQuestion = true\">\n <mat-icon>history</mat-icon><span>Revert changes</span>\n </button>\n <div *ngIf=\"showRevertQuestion\">\n <span class=\"revert\">Revert to last saved state?</span>\n <button type=\"button\" class=\"yes\" mat-stroked-button (click)=\"handleRevertYes()\">Yes</button>\n <button type=\"button\" mat-stroked-button (click)=\"handleRevertCancel()\">No</button>\n </div>\n <button class=\"save-button\" mat-flat-button color=\"warn\" type=\"submit\" [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon> <span> Save & publish changes</span>\n </button>\n </div>\n</form>", styles: [".wrapper{background-color:#f3f3f3;border:1px solid rgba(0,0,0,.12);margin:1em 0}.show-hide a{cursor:pointer;font-size:.8rem}.save{position:sticky;bottom:0;min-height:38px;padding:.5rem .5rem .5rem 0;background-color:#fff;display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-end;z-index:1000}.save .save-button{animation:shadow-pulse 1s 3;margin-left:1rem}.save>*{margin:.3em}.save .revert{margin:0 16px;font-size:14px}.save .yes{margin:0 5px}.error{background-color:#a32b2d;color:#fff;padding:5px;font-size:.9em}.error a{color:#fff;text-decoration:underline}@media (max-width: 700px){.save{padding:.5rem 0}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SettingComponent, selector: "setting", inputs: ["dashboardBasePath", "productId", "environmentId", "configId", "formGroup", "readOnly", "canDeleteSetting", "deleteSettingText", "showEnvironmentName", "segments"], outputs: ["deleteSettingRequested"] }] });
1223
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingListComponent, decorators: [{
1224
- type: Component,
1225
- args: [{ selector: 'configcat-setting-list', template: "<form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\" *ngIf=\"!loading\">\n <div class=\"wrapper\" *ngFor=\"let settingValueFromGroup of getSettingValueFormGroups(); let i = index\">\n <setting [formGroup]=\"settingValueFromGroup\" [readOnly]=\"readOnly\" [canDeleteSetting]=\"canDeleteSetting\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" [deleteSettingText]=\"deleteSettingText\"\n [showEnvironmentName]=\"showEnvironmentName\" [segments]=\"segments\" [productId]=\"productId\" [configId]=\"configId\"\n [environmentId]=\"environmentId\" [dashboardBasePath]=\"dashboardBasePath\">\n </setting>\n </div>\n\n <div class=\"save\" *ngIf=\"!readOnly && !submitting && formGroup.dirty\">\n <div class=\"feedback\" *ngIf=\"formGroup.touched && formGroup.invalid && showFeedBackMessage\">\n <div class=\"error\" *ngIf=\"formGroup.errors && formGroup.errors.internalServerError\">\n <span>Something went wrong and we could not save your settings. You can try again or <a\n href=\"https://configcat.com/support\" target=\"_blank\" rel=\"noopener noreferrer\">contact us.</a></span>\n </div>\n <div class=\"error\" *ngIf=\"!formGroup.errors || !formGroup.errors.internalServerError\">\n <span>Oh no! A feature flag has invalid or missing data.</span>\n </div>\n </div>\n <button type=\"button\" mat-stroked-button *ngIf=\"!showRevertQuestion\" (click)=\"showRevertQuestion = true\">\n <mat-icon>history</mat-icon><span>Revert changes</span>\n </button>\n <div *ngIf=\"showRevertQuestion\">\n <span class=\"revert\">Revert to last saved state?</span>\n <button type=\"button\" class=\"yes\" mat-stroked-button (click)=\"handleRevertYes()\">Yes</button>\n <button type=\"button\" mat-stroked-button (click)=\"handleRevertCancel()\">No</button>\n </div>\n <button class=\"save-button\" mat-flat-button color=\"warn\" type=\"submit\" [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon> <span> Save & publish changes</span>\n </button>\n </div>\n</form>", styles: [".wrapper{background-color:#f3f3f3;border:1px solid rgba(0,0,0,.12);margin:1em 0}.show-hide a{cursor:pointer;font-size:.8rem}.save{position:sticky;bottom:0;min-height:38px;padding:.5rem .5rem .5rem 0;background-color:#fff;display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-end;z-index:1000}.save .save-button{animation:shadow-pulse 1s 3;margin-left:1rem}.save>*{margin:.3em}.save .revert{margin:0 16px;font-size:14px}.save .yes{margin:0 5px}.error{background-color:#a32b2d;color:#fff;padding:5px;font-size:.9em}.error a{color:#fff;text-decoration:underline}@media (max-width: 700px){.save{padding:.5rem 0}}\n"] }]
1226
- }], ctorParameters: function () { return [{ type: SettingListFormHelper }, { type: i2$2.MatSnackBar }, { type: i1$1.MatDialog }]; }, propDecorators: { productId: [{
1227
- type: Input
1228
- }], environmentId: [{
1229
- type: Input
1230
- }], configId: [{
1231
- type: Input
1232
- }], dashboardBasePath: [{
1233
- type: Input
1234
- }], canDeleteSetting: [{
1235
- type: Input
1236
- }], onSave: [{
1237
- type: Input
1238
- }], loadSettingValues: [{
1239
- type: Input
1240
- }], loadSegments: [{
1241
- type: Input
1242
- }], deleteSettingText: [{
1243
- type: Input
1244
- }], showEnvironmentName: [{
1245
- type: Input
1246
- }], loadSucceeded: [{
1247
- type: Output
1248
- }], deleteSettingRequested: [{
1249
- type: Output
1250
- }], formValuesChanged: [{
1251
- type: Output
1252
- }] } });
1253
-
1254
- class SettingItemComponent extends BaseComponent {
1255
- constructor(publicApiService) {
1256
- super(publicApiService);
1257
- this.canDeleteSetting = true;
1258
- this.deleteSettingText = 'Delete setting';
1259
- this.showEnvironmentName = true;
1260
- this.deleteSettingRequested = new EventEmitter();
1261
- this.loadSucceeded = new EventEmitter();
1262
- this.loadFailed = new EventEmitter();
1263
- this.saveSucceeded = new EventEmitter();
1264
- this.saveFailed = new EventEmitter();
1265
- this.formValuesChanged = new EventEmitter();
1266
- this.loadSettingValues = () => {
1267
- return this.createSettingValuesService().getSettingValue(this.environmentId, this.settingId)
1268
- .pipe(map(settingValue => {
1269
- this.settingValue = settingValue;
1270
- const settingValues = {
1271
- settingValues: [settingValue],
1272
- readOnly: settingValue.readOnly,
1273
- config: settingValue.config,
1274
- environment: settingValue.environment
1275
- };
1276
- return settingValues;
1277
- }), catchError(error => {
1278
- this.loadFailed.emit(error);
1279
- return throwError(error);
1280
- }));
1281
- };
1282
- this.loadSegments = () => {
1283
- return this.createSegmentsService().getSegments(this.productId)
1284
- .pipe(map(segments => {
1285
- this.segments = segments;
1286
- return segments;
1287
- }), catchError(error => {
1288
- return throwError(error);
1289
- }));
1290
- };
1291
- this.handleSave = (model) => {
1292
- if (model.settingValues.length === 0) {
1293
- return of();
1294
- }
1295
- const updateModel = model.settingValues[0];
1296
- return this.createSettingValuesService().replaceSettingValue(this.environmentId, this.settingId, updateModel, model.reason)
1297
- .pipe(map(settingValue => {
1298
- this.settingValue = settingValue;
1299
- const settingValues = {
1300
- settingValues: [settingValue],
1301
- readOnly: settingValue.readOnly,
1302
- config: settingValue.config,
1303
- environment: settingValue.environment
1304
- };
1305
- this.saveSucceeded.emit(settingValues);
1306
- return settingValues;
1307
- }), catchError(error => {
1308
- this.saveFailed.emit(error);
1309
- return throwError(error);
1310
- }));
1311
- };
1312
- this.dashboardBasePath = publicApiService.getDashboardBasePath();
1313
- }
1314
- ngOnInit() {
1315
- }
1316
- itemLoadSucceeded() {
1317
- this.loadSucceeded.emit(true);
1318
- }
1319
- onDeleteSettingRequested(setting) {
1320
- this.deleteSettingRequested.emit({
1321
- setting: setting.setting,
1322
- environment: this.settingValue.environment,
1323
- config: this.settingValue.config
1324
- });
1325
- }
1326
- onFormValuesChanged() {
1327
- this.formValuesChanged.emit();
1328
- }
1329
- }
1330
- SettingItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingItemComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1331
- SettingItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SettingItemComponent, selector: "configcat-setting-item", inputs: { productId: "productId", environmentId: "environmentId", configId: "configId", settingId: "settingId", canDeleteSetting: "canDeleteSetting", deleteSettingText: "deleteSettingText", showEnvironmentName: "showEnvironmentName" }, outputs: { deleteSettingRequested: "deleteSettingRequested", loadSucceeded: "loadSucceeded", loadFailed: "loadFailed", saveSucceeded: "saveSucceeded", saveFailed: "saveFailed", formValuesChanged: "formValuesChanged" }, usesInheritance: true, ngImport: i0, template: "<configcat-setting-list [canDeleteSetting]=\"canDeleteSetting\" [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\" [loadSegments]=\"loadSegments\" (loadSucceeded)=\"itemLoadSucceeded()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" [deleteSettingText]=\"deleteSettingText\"\n [showEnvironmentName]=\"showEnvironmentName\" (formValuesChanged)=\"onFormValuesChanged()\" [productId]=\"productId\"\n [configId]=\"configId\" [environmentId]=\"environmentId\" [dashboardBasePath]=\"dashboardBasePath\">\n</configcat-setting-list>", styles: [".container{font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;background-color:#f3f3f3;border:1px solid rgba(0,0,0,.12);border-radius:4px;margin:1em 0}.container .setting-full{position:relative;display:flex;flex-wrap:nowrap}.container .setting-full .setting-details{display:flex;flex-direction:column;width:400px;padding:1em 0 1em 1em}.container .setting-full .setting-details>*{margin:.5em}.container .setting-full .setting-details .setting-name{flex-direction:row}.container .setting-full .setting-details .setting-name .name{font-weight:700;word-wrap:break-word;max-width:100%}.container .setting-full .setting-details .setting-key{word-wrap:break-word}.container .setting-full .setting-details .description{font-size:.8em}.container .setting-full .setting-details code{background-color:#d3d3d3;padding:3px 6px}.container .setting-full .rules-list{width:100%;padding:1em}.container .setting-full .targeting-button{margin-left:1rem;margin-bottom:1em}.all-other{min-height:40px;justify-content:flex-start;border:1px solid #d5d5d5;border-radius:4px;background-color:#fff;margin:.5em 1em;padding:4px 0 4px .5em}.all-other .chip{background-color:#67b1fc3d}.all-other .served-value{margin-left:auto;min-width:100px}.end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media (max-width: 1200px){.setting-full .setting-details{width:300px}}@media (max-width: 700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"], dependencies: [{ kind: "component", type: SettingListComponent, selector: "configcat-setting-list", inputs: ["productId", "environmentId", "configId", "dashboardBasePath", "canDeleteSetting", "onSave", "loadSettingValues", "loadSegments", "deleteSettingText", "showEnvironmentName"], outputs: ["loadSucceeded", "deleteSettingRequested", "formValuesChanged"] }] });
1332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingItemComponent, decorators: [{
1333
- type: Component,
1334
- args: [{ selector: 'configcat-setting-item', template: "<configcat-setting-list [canDeleteSetting]=\"canDeleteSetting\" [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\" [loadSegments]=\"loadSegments\" (loadSucceeded)=\"itemLoadSucceeded()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" [deleteSettingText]=\"deleteSettingText\"\n [showEnvironmentName]=\"showEnvironmentName\" (formValuesChanged)=\"onFormValuesChanged()\" [productId]=\"productId\"\n [configId]=\"configId\" [environmentId]=\"environmentId\" [dashboardBasePath]=\"dashboardBasePath\">\n</configcat-setting-list>", styles: [".container{font-family:Montserrat,Roboto,Helvetica Neue,sans-serif;background-color:#f3f3f3;border:1px solid rgba(0,0,0,.12);border-radius:4px;margin:1em 0}.container .setting-full{position:relative;display:flex;flex-wrap:nowrap}.container .setting-full .setting-details{display:flex;flex-direction:column;width:400px;padding:1em 0 1em 1em}.container .setting-full .setting-details>*{margin:.5em}.container .setting-full .setting-details .setting-name{flex-direction:row}.container .setting-full .setting-details .setting-name .name{font-weight:700;word-wrap:break-word;max-width:100%}.container .setting-full .setting-details .setting-key{word-wrap:break-word}.container .setting-full .setting-details .description{font-size:.8em}.container .setting-full .setting-details code{background-color:#d3d3d3;padding:3px 6px}.container .setting-full .rules-list{width:100%;padding:1em}.container .setting-full .targeting-button{margin-left:1rem;margin-bottom:1em}.all-other{min-height:40px;justify-content:flex-start;border:1px solid #d5d5d5;border-radius:4px;background-color:#fff;margin:.5em 1em;padding:4px 0 4px .5em}.all-other .chip{background-color:#67b1fc3d}.all-other .served-value{margin-left:auto;min-width:100px}.end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media (max-width: 1200px){.setting-full .setting-details{width:300px}}@media (max-width: 700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"] }]
1335
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { productId: [{
1336
- type: Input
1337
- }], environmentId: [{
1338
- type: Input
1339
- }], configId: [{
1340
- type: Input
1341
- }], settingId: [{
1342
- type: Input
1343
- }], canDeleteSetting: [{
1344
- type: Input
1345
- }], deleteSettingText: [{
1346
- type: Input
1347
- }], showEnvironmentName: [{
1348
- type: Input
1349
- }], deleteSettingRequested: [{
1350
- type: Output
1351
- }], loadSucceeded: [{
1352
- type: Output
1353
- }], loadFailed: [{
1354
- type: Output
1355
- }], saveSucceeded: [{
1356
- type: Output
1357
- }], saveFailed: [{
1358
- type: Output
1359
- }], formValuesChanged: [{
1360
- type: Output
1361
- }] } });
1362
-
1363
- class BaseSelectComponent extends BaseComponent {
1364
- constructor() {
1365
- super(...arguments);
1366
- this.customDropdown = false;
1367
- this.dropdownOpened = new EventEmitter();
1368
- }
1369
- openChanged(event) {
1370
- this.dropdownOpened.emit(event);
1371
- }
1372
- }
1373
- BaseSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: BaseSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1374
- BaseSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: BaseSelectComponent, selector: "base-select", inputs: { customDropdown: "customDropdown" }, outputs: { dropdownOpened: "dropdownOpened" }, usesInheritance: true, ngImport: i0, template: '<div></div>', isInline: true });
1375
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: BaseSelectComponent, decorators: [{
1376
- type: Component,
1377
- args: [{
1378
- selector: 'base-select',
1379
- template: '<div></div>'
1380
- }]
1381
- }], propDecorators: { customDropdown: [{
1382
- type: Input
1383
- }], dropdownOpened: [{
1384
- type: Output
1385
- }] } });
1386
-
1387
- class SettingSelectComponent extends BaseSelectComponent {
1388
- constructor(publicApiService) {
1389
- super(publicApiService);
1390
- this.settings = [];
1391
- }
1392
- ngOnInit() {
1393
- this.settings = [];
1394
- this.reloadSettings();
1395
- }
1396
- ngOnChanges() {
1397
- this.reloadSettings();
1398
- }
1399
- reloadSettings() {
1400
- if (this.configId) {
1401
- this.createSettingsService().getSettings(this.configId).subscribe(settings => {
1402
- this.settings = settings;
1403
- if (this.settings.length > 0) {
1404
- this.valueFormControl.setValue(this.settings[0].settingId);
1405
- }
1406
- else {
1407
- this.valueFormControl.setValue("");
1408
- }
1409
- });
1410
- }
1411
- }
1412
- }
1413
- SettingSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingSelectComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1414
- SettingSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SettingSelectComponent, selector: "configcat-setting-select", inputs: { valueFormControl: "valueFormControl", configId: "configId" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"settings\">\n <mat-label>Feature flag or setting</mat-label>\n <mat-select placeholder=\"Feature flag or setting\" [formControl]=\"valueFormControl\" name=\"value\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let setting of settings\" [value]=\"setting.settingId\" matTooltip=\"{{setting.name}}\"\n [matTooltipShowDelay]=\"1000\">{{setting.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
1415
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SettingSelectComponent, decorators: [{
1416
- type: Component,
1417
- args: [{ selector: 'configcat-setting-select', template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"settings\">\n <mat-label>Feature flag or setting</mat-label>\n <mat-select placeholder=\"Feature flag or setting\" [formControl]=\"valueFormControl\" name=\"value\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let setting of settings\" [value]=\"setting.settingId\" matTooltip=\"{{setting.name}}\"\n [matTooltipShowDelay]=\"1000\">{{setting.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"] }]
1418
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { valueFormControl: [{
1419
- type: Input
1420
- }], configId: [{
1421
- type: Input
1422
- }] } });
1423
-
1424
- class ProductSelectComponent extends BaseSelectComponent {
1425
- constructor(publicApiService) {
1426
- super(publicApiService);
1427
- this.products = [];
1428
- }
1429
- ngOnInit() {
1430
- this.products = [];
1431
- this.createProductsService().getProducts().subscribe(products => {
1432
- this.products = products;
1433
- if (this.products.length > 0) {
1434
- this.valueFormControl.setValue(this.products[0].productId, {
1435
- emitEvent: true,
1436
- emitModelToViewChange: true, emitViewToModelChange: true
1437
- });
1438
- }
1439
- else {
1440
- this.valueFormControl.setValue("");
1441
- }
1442
- });
1443
- }
1444
- }
1445
- ProductSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ProductSelectComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1446
- ProductSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ProductSelectComponent, selector: "configcat-product-select", inputs: { valueFormControl: "valueFormControl" }, usesInheritance: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Product</mat-label>\n <mat-select placeholder=\"Product\" [formControl]=\"valueFormControl\" name=\"productValue\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let product of products\" [value]=\"product.productId\" matTooltip=\"{{product.name}}\"\n [matTooltipShowDelay]=\"1000\">{{product.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
1447
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ProductSelectComponent, decorators: [{
1448
- type: Component,
1449
- args: [{ selector: 'configcat-product-select', template: "<mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Product</mat-label>\n <mat-select placeholder=\"Product\" [formControl]=\"valueFormControl\" name=\"productValue\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let product of products\" [value]=\"product.productId\" matTooltip=\"{{product.name}}\"\n [matTooltipShowDelay]=\"1000\">{{product.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"] }]
1450
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { valueFormControl: [{
1451
- type: Input
1452
- }] } });
1453
-
1454
- class ConfigSelectComponent extends BaseSelectComponent {
1455
- constructor(publicApiService) {
1456
- super(publicApiService);
1457
- this.configs = [];
1458
- }
1459
- ngOnInit() {
1460
- this.configs = [];
1461
- this.reloadConfigs();
1462
- }
1463
- ngOnChanges() {
1464
- this.reloadConfigs();
1465
- }
1466
- reloadConfigs() {
1467
- if (this.productId) {
1468
- this.createConfigsService().getConfigs(this.productId).subscribe(configs => {
1469
- this.configs = configs;
1470
- if (this.configs.length > 0) {
1471
- this.valueFormControl.setValue(this.configs[0].configId);
1472
- }
1473
- else {
1474
- this.valueFormControl.setValue("");
1475
- }
1476
- });
1477
- }
1478
- }
1479
- }
1480
- ConfigSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ConfigSelectComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1481
- ConfigSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ConfigSelectComponent, selector: "configcat-config-select", inputs: { valueFormControl: "valueFormControl", productId: "productId" }, providers: [
1482
- {
1483
- provide: NG_VALUE_ACCESSOR,
1484
- useExisting: forwardRef(() => ConfigSelectComponent),
1485
- multi: true
1486
- }
1487
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"configs\">\n <mat-label>Config</mat-label>\n <mat-select placeholder=\"Config\" [formControl]=\"valueFormControl\" name=\"value\" disableOptionCentering\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let config of configs\" [value]=\"config.configId\" matTooltip=\"{{config.name}}\"\n [matTooltipShowDelay]=\"1000\">{{config.name}}</mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
1488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ConfigSelectComponent, decorators: [{
1489
- type: Component,
1490
- args: [{ selector: 'configcat-config-select', providers: [
1491
- {
1492
- provide: NG_VALUE_ACCESSOR,
1493
- useExisting: forwardRef(() => ConfigSelectComponent),
1494
- multi: true
1495
- }
1496
- ], template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"configs\">\n <mat-label>Config</mat-label>\n <mat-select placeholder=\"Config\" [formControl]=\"valueFormControl\" name=\"value\" disableOptionCentering\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let config of configs\" [value]=\"config.configId\" matTooltip=\"{{config.name}}\"\n [matTooltipShowDelay]=\"1000\">{{config.name}}</mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"] }]
1497
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { valueFormControl: [{
1498
- type: Input
1499
- }], productId: [{
1500
- type: Input
1501
- }] } });
1502
-
1503
- class EnvironmentSelectComponent extends BaseSelectComponent {
1504
- constructor(publicApiService) {
1505
- super(publicApiService);
1506
- this.environments = [];
1507
- }
1508
- ngOnInit() {
1509
- this.environments = [];
1510
- this.reloadEnvironments();
1511
- }
1512
- ngOnChanges() {
1513
- this.reloadEnvironments();
1514
- }
1515
- reloadEnvironments() {
1516
- if (this.productId) {
1517
- this.createEnvironmentsService().getEnvironments(this.productId).subscribe(environments => {
1518
- this.environments = environments;
1519
- if (this.environments.length > 0) {
1520
- this.valueFormControl.setValue(this.environments[0].environmentId);
1521
- }
1522
- else {
1523
- this.valueFormControl.setValue("");
1524
- }
1525
- });
1526
- }
1527
- }
1528
- }
1529
- EnvironmentSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EnvironmentSelectComponent, deps: [{ token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1530
- EnvironmentSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EnvironmentSelectComponent, selector: "configcat-environment-select", inputs: { valueFormControl: "valueFormControl", productId: "productId" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"environments\">\n <mat-label>Environment</mat-label>\n <mat-select placeholder=\"Environment\" [formControl]=\"valueFormControl\" name=\"value\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let environment of environments\" [value]=\"environment.environmentId\"\n matTooltip=\"{{environment.name}}\" [matTooltipShowDelay]=\"1000\">{{environment.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i5$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i7$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
1531
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EnvironmentSelectComponent, decorators: [{
1532
- type: Component,
1533
- args: [{ selector: 'configcat-environment-select', template: "<mat-form-field class=\"form-field\" appearance=\"outline\" *ngIf=\"environments\">\n <mat-label>Environment</mat-label>\n <mat-select placeholder=\"Environment\" [formControl]=\"valueFormControl\" name=\"value\"\n (openedChange)=\"openChanged($event)\" [panelClass]=\"customDropdown ? 'custom-dropdown-below' : ''\">\n <mat-option *ngFor=\"let environment of environments\" [value]=\"environment.environmentId\"\n matTooltip=\"{{environment.name}}\" [matTooltipShowDelay]=\"1000\">{{environment.name}}\n </mat-option>\n </mat-select>\n</mat-form-field>", styles: [".form-field{width:100%}\n"] }]
1534
- }], ctorParameters: function () { return [{ type: PublicApiService }]; }, propDecorators: { valueFormControl: [{
1535
- type: Input
1536
- }], productId: [{
1537
- type: Input
1538
- }] } });
1539
-
1540
- class AuthorizationComponent {
1541
- constructor(formBuilder, publicApiService) {
1542
- this.formBuilder = formBuilder;
1543
- this.publicApiService = publicApiService;
1544
- this.basePath = null;
1545
- this.integrationName = 'ConfigCat Feature Flags';
1546
- this.authorized = new EventEmitter();
1547
- this.error = new EventEmitter();
1548
- this.FormHelper = FormHelper;
1549
- }
1550
- ngOnInit() {
1551
- this.formGroup = this.formBuilder.group({
1552
- basicAuthUsername: ['', Validators.required],
1553
- basicAuthPassword: ['', Validators.required],
1554
- });
1555
- }
1556
- onSubmit() {
1557
- if (!this.formGroup.valid) {
1558
- return;
1559
- }
1560
- const meService = this.publicApiService.createMeService(this.formGroup.controls.basicAuthUsername.value, this.formGroup.controls.basicAuthPassword.value, this.basePath);
1561
- meService.getMe().subscribe(me => {
1562
- this.authorized.emit({
1563
- basicAuthUsername: this.formGroup.controls.basicAuthUsername.value,
1564
- basicAuthPassword: this.formGroup.controls.basicAuthPassword.value,
1565
- email: me.email,
1566
- fullName: me.fullName
1567
- });
1568
- }, () => {
1569
- this.formGroup.setErrors({ invalidAuthorization: 'Invalid Basic auth user name or password' });
1570
- this.error.emit();
1571
- });
1572
- }
1573
- getPublicApiUrl() {
1574
- return this.publicApiService.getDashboardBasePath() + '/my-account/public-api-credentials';
1575
- }
1576
- }
1577
- AuthorizationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AuthorizationComponent, deps: [{ token: i2.UntypedFormBuilder }, { token: PublicApiService }], target: i0.ɵɵFactoryTarget.Component });
1578
- AuthorizationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: AuthorizationComponent, selector: "configcat-authorization", inputs: { basePath: "basePath", integrationName: "integrationName" }, outputs: { authorized: "authorized", error: "error" }, ngImport: i0, template: "<form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <div class=\"container\">\n <div class=\"form\">\n <p>\n In order to use {{integrationName}} you have to authorize first with your ConfigCat Public API\n credentials.\n </p>\n <ul>\n <li>\n <a [href]=\"getPublicApiUrl()\" target=\"_blank\">\n Get your Basic Auth user name and password</a> to access ConfigCat Public API.\n <br />\n <b>Note!</b> Your ConfigCat account's email address and password will not work here.\n </li>\n <li>\n Type your credentials here and click the Authorize button.\n </li>\n </ul>\n\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Basic auth user name</mat-label>\n <input matInput placeholder=\"Basic auth user name\" formControlName=\"basicAuthUsername\">\n <mat-error *ngIf=\"formGroup.controls.basicAuthUsername.invalid\">\n {{FormHelper.getErrorMessage(formGroup.controls.basicAuthUsername)}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Basic auth password</mat-label>\n <input matInput placeholder=\"Basic auth password\" formControlName=\"basicAuthPassword\" type=\"password\"\n autocomplete=\"current-password\">\n <mat-error *ngIf=\"formGroup.controls.basicAuthPassword.invalid\">\n {{FormHelper.getErrorMessage(formGroup.controls.basicAuthPassword)}}\n </mat-error>\n </mat-form-field>\n <div>\n <button mat-flat-button color=\"primary\" type=\"submit\" class=\"submit\">Authorize</button>\n <mat-error *ngIf=\"formGroup.invalid && formGroup.errors && formGroup.errors.invalidAuthorization\">\n {{formGroup.errors.invalidAuthorization}}</mat-error>\n </div>\n </div>\n </div>\n</form>", styles: [".container{display:flex;margin:8px}.form{width:100%}.form-field{width:100%;margin-bottom:8px}.submit{margin-top:8px;margin-bottom:8px}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }] });
1579
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: AuthorizationComponent, decorators: [{
1580
- type: Component,
1581
- args: [{ selector: 'configcat-authorization', template: "<form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <div class=\"container\">\n <div class=\"form\">\n <p>\n In order to use {{integrationName}} you have to authorize first with your ConfigCat Public API\n credentials.\n </p>\n <ul>\n <li>\n <a [href]=\"getPublicApiUrl()\" target=\"_blank\">\n Get your Basic Auth user name and password</a> to access ConfigCat Public API.\n <br />\n <b>Note!</b> Your ConfigCat account's email address and password will not work here.\n </li>\n <li>\n Type your credentials here and click the Authorize button.\n </li>\n </ul>\n\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Basic auth user name</mat-label>\n <input matInput placeholder=\"Basic auth user name\" formControlName=\"basicAuthUsername\">\n <mat-error *ngIf=\"formGroup.controls.basicAuthUsername.invalid\">\n {{FormHelper.getErrorMessage(formGroup.controls.basicAuthUsername)}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Basic auth password</mat-label>\n <input matInput placeholder=\"Basic auth password\" formControlName=\"basicAuthPassword\" type=\"password\"\n autocomplete=\"current-password\">\n <mat-error *ngIf=\"formGroup.controls.basicAuthPassword.invalid\">\n {{FormHelper.getErrorMessage(formGroup.controls.basicAuthPassword)}}\n </mat-error>\n </mat-form-field>\n <div>\n <button mat-flat-button color=\"primary\" type=\"submit\" class=\"submit\">Authorize</button>\n <mat-error *ngIf=\"formGroup.invalid && formGroup.errors && formGroup.errors.invalidAuthorization\">\n {{formGroup.errors.invalidAuthorization}}</mat-error>\n </div>\n </div>\n </div>\n</form>", styles: [".container{display:flex;margin:8px}.form{width:100%}.form-field{width:100%;margin-bottom:8px}.submit{margin-top:8px;margin-bottom:8px}\n"] }]
1582
- }], ctorParameters: function () { return [{ type: i2.UntypedFormBuilder }, { type: PublicApiService }]; }, propDecorators: { basePath: [{
1583
- type: Input
1584
- }], integrationName: [{
1585
- type: Input
1586
- }], authorized: [{
1587
- type: Output
1588
- }], error: [{
1589
- type: Output
1590
- }] } });
1591
-
1592
- class DeleteSettingDialogComponent {
1593
- constructor(dialogRef, data) {
1594
- this.dialogRef = dialogRef;
1595
- this.data = data;
1596
- }
1597
- remove() {
1598
- this.dialogRef.close({ button: 'remove' });
1599
- }
1600
- cancel() {
1601
- this.dialogRef.close({ button: 'cancel' });
1602
- }
1603
- }
1604
- DeleteSettingDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DeleteSettingDialogComponent, deps: [{ token: i1$1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1605
- DeleteSettingDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DeleteSettingDialogComponent, selector: "app-delete-setting-dialog", ngImport: i0, template: "<h1 mat-dialog-title>Remove Feature Flag or Setting from {{data.system}}</h1>\n<div mat-dialog-actions class=\"container\">\n <button type=\"button\" mat-raised-button color=\"primary\" (click)=\"remove()\">Remove from {{data.ticketType}}</button>\n <button type=\"button\" mat-raised-button (click)=\"cancel()\">Cancel</button>\n</div>", styles: [""], dependencies: [{ kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
1606
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DeleteSettingDialogComponent, decorators: [{
1607
- type: Component,
1608
- args: [{ selector: 'app-delete-setting-dialog', template: "<h1 mat-dialog-title>Remove Feature Flag or Setting from {{data.system}}</h1>\n<div mat-dialog-actions class=\"container\">\n <button type=\"button\" mat-raised-button color=\"primary\" (click)=\"remove()\">Remove from {{data.ticketType}}</button>\n <button type=\"button\" mat-raised-button (click)=\"cancel()\">Cancel</button>\n</div>" }]
1609
- }], ctorParameters: function () { return [{ type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
1610
- type: Inject,
1611
- args: [MAT_DIALOG_DATA]
1612
- }] }]; } });
1613
-
1614
- class NgConfigCatPublicApiUIModule {
1615
- static forRoot(configurationFactory) {
1616
- return {
1617
- ngModule: NgConfigCatPublicApiUIModule,
1618
- providers: [{ provide: Configuration, useFactory: configurationFactory }]
1619
- };
1620
- }
1621
- constructor() { }
1622
- }
1623
- NgConfigCatPublicApiUIModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgConfigCatPublicApiUIModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1624
- NgConfigCatPublicApiUIModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgConfigCatPublicApiUIModule, declarations: [BaseComponent,
1625
- BaseSelectComponent,
1626
- ProductSelectComponent,
1627
- ConfigSelectComponent,
1628
- EnvironmentSelectComponent,
1629
- SettingSelectComponent,
1630
- SettingItemComponent,
1631
- AuthorizationComponent,
1632
- SettingListComponent,
1633
- SettingComponent,
1634
- RolloutPercentageItemsComponent,
1635
- RolloutRulesComponent,
1636
- ValueComponent,
1637
- ReasonDialogComponent,
1638
- SaveSnackbarComponent,
1639
- ExpandDialogComponent,
1640
- DeleteSettingDialogComponent,
1641
- InputDisplayNormalizerDirective], imports: [CommonModule,
1642
- FormsModule,
1643
- ReactiveFormsModule,
1644
- BrowserAnimationsModule,
1645
- MatFormFieldModule,
1646
- MatOptionModule,
1647
- MatSelectModule,
1648
- MatButtonModule,
1649
- MatInputModule,
1650
- MatIconModule,
1651
- MatTooltipModule,
1652
- MatChipsModule,
1653
- MatAutocompleteModule,
1654
- DragDropModule,
1655
- RouterModule,
1656
- MatSnackBarModule,
1657
- MatDialogModule,
1658
- MatMenuModule,
1659
- ApiModule], exports: [AuthorizationComponent,
1660
- ProductSelectComponent,
1661
- ConfigSelectComponent,
1662
- EnvironmentSelectComponent,
1663
- SettingSelectComponent,
1664
- SettingItemComponent,
1665
- InputDisplayNormalizerDirective,
1666
- DeleteSettingDialogComponent] });
1667
- NgConfigCatPublicApiUIModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgConfigCatPublicApiUIModule, providers: [
1668
- {
1669
- provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
1670
- useValue: { disableTooltipInteractivity: true },
1671
- },
1672
- ], imports: [CommonModule,
1673
- FormsModule,
1674
- ReactiveFormsModule,
1675
- BrowserAnimationsModule,
1676
- MatFormFieldModule,
1677
- MatOptionModule,
1678
- MatSelectModule,
1679
- MatButtonModule,
1680
- MatInputModule,
1681
- MatIconModule,
1682
- MatTooltipModule,
1683
- MatChipsModule,
1684
- MatAutocompleteModule,
1685
- DragDropModule,
1686
- RouterModule,
1687
- MatSnackBarModule,
1688
- MatDialogModule,
1689
- MatMenuModule,
1690
- ApiModule] });
1691
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgConfigCatPublicApiUIModule, decorators: [{
1692
- type: NgModule,
1693
- args: [{
1694
- declarations: [
1695
- BaseComponent,
1696
- BaseSelectComponent,
1697
- ProductSelectComponent,
1698
- ConfigSelectComponent,
1699
- EnvironmentSelectComponent,
1700
- SettingSelectComponent,
1701
- SettingItemComponent,
1702
- AuthorizationComponent,
1703
- SettingListComponent,
1704
- SettingComponent,
1705
- RolloutPercentageItemsComponent,
1706
- RolloutRulesComponent,
1707
- ValueComponent,
1708
- ReasonDialogComponent,
1709
- SaveSnackbarComponent,
1710
- ExpandDialogComponent,
1711
- DeleteSettingDialogComponent,
1712
- InputDisplayNormalizerDirective
1713
- ],
1714
- imports: [
1715
- CommonModule,
1716
- FormsModule,
1717
- ReactiveFormsModule,
1718
- BrowserAnimationsModule,
1719
- MatFormFieldModule,
1720
- MatOptionModule,
1721
- MatSelectModule,
1722
- MatButtonModule,
1723
- MatInputModule,
1724
- MatIconModule,
1725
- MatTooltipModule,
1726
- MatChipsModule,
1727
- MatAutocompleteModule,
1728
- DragDropModule,
1729
- RouterModule,
1730
- MatSnackBarModule,
1731
- MatDialogModule,
1732
- MatMenuModule,
1733
- ApiModule
1734
- ],
1735
- exports: [
1736
- AuthorizationComponent,
1737
- ProductSelectComponent,
1738
- ConfigSelectComponent,
1739
- EnvironmentSelectComponent,
1740
- SettingSelectComponent,
1741
- SettingItemComponent,
1742
- InputDisplayNormalizerDirective,
1743
- DeleteSettingDialogComponent
1744
- ],
1745
- providers: [
1746
- {
1747
- provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
1748
- useValue: { disableTooltipInteractivity: true },
1749
- },
1750
- ]
1751
- }]
1752
- }], ctorParameters: function () { return []; } });
1753
-
1754
- /*
1755
- * Public API Surface of ng-configcat-publicapi-ui
1756
- */
1757
-
1758
- /**
1759
- * Generated bundle index. Do not edit.
1760
- */
1761
-
1762
- export { AuthorizationComponent, ConfigSelectComponent, DeleteSettingDialogComponent, EnvironmentSelectComponent, FormHelper, InputDisplayNormalizerDirective, NgConfigCatPublicApiUIModule, ProductSelectComponent, PublicApiService, SettingItemComponent, SettingSelectComponent };
1763
- //# sourceMappingURL=ng-configcat-publicapi-ui.mjs.map