@c8y/ngx-components 1017.0.511 → 1017.0.514

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.
@@ -6964,7 +6964,7 @@ class CookieBannerService {
6964
6964
  return JSON.parse(localStorage.getItem(this.STORAGE_KEY));
6965
6965
  }
6966
6966
  /**
6967
- * Verifies that cookie preferences configuration is defined.
6967
+ * Verifies that cookie preferences configuration is defined in the application options.
6968
6968
  * @returns {boolean} Returns if the cookie preferences configuration is defined.
6969
6969
  */
6970
6970
  isConfigCookiePreferencesDefined() {
@@ -7031,8 +7031,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
7031
7031
  * tag and
7032
7032
  */
7033
7033
  class GainsightService {
7034
- constructor(document, appState, options, cookieBannerService, userPreferencesService, translateService) {
7035
- this.document = document;
7034
+ constructor(appState, options, cookieBannerService, userPreferencesService, translateService) {
7036
7035
  this.appState = appState;
7037
7036
  this.options = options;
7038
7037
  this.cookieBannerService = cookieBannerService;
@@ -7042,6 +7041,11 @@ class GainsightService {
7042
7041
  * A subject that emits the tag function as soon as a new tag is set.
7043
7042
  */
7044
7043
  this.tagFunction$ = new BehaviorSubject(null);
7044
+ this.trackingLoaded$ = new Subject();
7045
+ /**
7046
+ * Gainsight is activated only when the cookie banner is present. If functional cookies are enabled, both personally identifiable information (PII) and required data are sent.
7047
+ * Otherwise, only the required data is transmitted during the identity step execution.
7048
+ */
7045
7049
  this.USER_PREFERENCES_GAINSIGHT_KEY = 'gainsightEnabled';
7046
7050
  /**
7047
7051
  * The name of the key remained unchanged, but applies to all engagements.
@@ -7053,15 +7057,23 @@ class GainsightService {
7053
7057
  this.SCRIPT_EXECUTION_WAIT_TIME = 500;
7054
7058
  this.OPTIONS_KEY_CATEGORY = 'gainsight';
7055
7059
  this.OPTIONS_KEY_NAME = 'api.key';
7056
- this.ENGAGEMENTS = 'engagements';
7057
7060
  this.isScriptLoaded = false;
7058
7061
  }
7062
+ /**
7063
+ * Checks if the specified Gainsight preference is disabled in user preferences.
7064
+ * @param preferenceName - Name of the Gainsight preference.
7065
+ * @returns A promise that resolves to `true` if the preference is disabled, otherwise `false`.
7066
+ */
7059
7067
  isGainsightPreferenceDisabledInUserPreferences(preferenceName) {
7060
7068
  return __awaiter(this, void 0, void 0, function* () {
7061
7069
  const userGainsightPref = yield this.userPreferencesService.get(preferenceName).toPromise();
7062
7070
  return userGainsightPref === false;
7063
7071
  });
7064
7072
  }
7073
+ /**
7074
+ * Sets the state of the functional cookie.
7075
+ * @param value - A boolean value to indicate whether the functional cookie should be enabled (`true`) or disabled (`false`).
7076
+ */
7065
7077
  setFunctionalCookie(value) {
7066
7078
  const cookies = this.cookieBannerService.getUserCookiePreferences();
7067
7079
  if (cookies) {
@@ -7092,58 +7104,110 @@ class GainsightService {
7092
7104
  /**
7093
7105
  * Load the script tag and calls the identify function to start the tracking.
7094
7106
  * @param currentTenant The current tenant.
7095
- * @param identify If set to false, only the tag is loaded.
7107
+ * @param sendPiiData Flag for sending personally identifiable information (PII) during identification in Gainsight.
7096
7108
  */
7097
- loadTag(currentTenant, identify = true) {
7109
+ loadTag(currentTenant, sendPiiData) {
7098
7110
  return __awaiter(this, void 0, void 0, function* () {
7099
7111
  const scriptTag = document.createElement('script');
7100
7112
  const key = yield this.getGainsightKey();
7101
7113
  if (key && !this.isScriptLoaded) {
7102
7114
  this.loadScriptTag(scriptTag, key);
7103
- combineLatest(this.appState.currentUser, fromEvent(scriptTag, 'load'), this.appState.state$.pipe(filter(({ versions }) => versions.backend), map(({ versions }) => versions), take(1)))
7115
+ const currentUserStream = this.appState.currentUser;
7116
+ const scriptLoadStream = fromEvent(scriptTag, 'load');
7117
+ const versionStream = this.appState.state$.pipe(filter(({ versions }) => versions.backend), map(({ versions }) => versions), take(1));
7118
+ const sourceStreams = sendPiiData
7119
+ ? [currentUserStream, scriptLoadStream, versionStream]
7120
+ : [currentUserStream, scriptLoadStream];
7121
+ combineLatest(sourceStreams)
7104
7122
  .pipe(delay(this.SCRIPT_EXECUTION_WAIT_TIME), filter(([user, scriptEvent]) => !!(scriptEvent && user)))
7105
- .subscribe(([user, , versions]) => {
7123
+ .subscribe(args => {
7124
+ const [user, , versions] = args;
7125
+ this.setGlobalContext();
7106
7126
  const instanceId = this.getInstanceIdFromUrl();
7107
- if (identify) {
7108
- this.setGlobalContext();
7109
- this.identify(user, currentTenant, instanceId, versions.ui.ngx, versions.backend);
7127
+ if (sendPiiData) {
7128
+ const versionUI = versions.ui.ngx;
7129
+ const versionBE = versions.backend;
7130
+ const extendedIdentifyData = {
7131
+ user,
7132
+ currentTenant,
7133
+ instanceId,
7134
+ versionUI,
7135
+ versionBE
7136
+ };
7137
+ this.identify(sendPiiData, extendedIdentifyData);
7138
+ }
7139
+ else {
7140
+ const requiredIdentifyData = { user, currentTenant, instanceId };
7141
+ this.identify(sendPiiData, requiredIdentifyData);
7110
7142
  }
7111
7143
  this.isScriptLoaded = true;
7112
7144
  this.tagFunction$.next(this.tagFunction);
7145
+ this.trackingLoaded$.next(true);
7113
7146
  });
7114
7147
  }
7115
7148
  });
7116
7149
  }
7117
7150
  /**
7118
7151
  * Identifies the user/account at Gainsight.
7119
- * @param user The user which is given to Gainsight.
7120
- * @param tenant The tenant which is given to Gainsight.
7121
- * @param versionUI The UI version used.
7122
- * @param versionBE The BE version used.
7152
+ * @param sendPiiData Flag for sending personally identifiable information.
7153
+ * @param identifyData Object containing identification data.
7123
7154
  */
7124
- identify(user, tenant, instanceId, versionUI, versionBE) {
7155
+ identify(sendPiiData, identifyData) {
7125
7156
  const windowRef = window;
7126
- const { id: userId, email, userName, firstName, lastName, roles } = user;
7127
- const { name, customProperties, domainName } = tenant;
7128
- const { externalReference } = customProperties || {};
7129
- windowRef[this.GAINSIGHT_GLOBAL_SCOPE]('identify', {
7130
- id: `${userId}_${name}_${instanceId}`,
7131
- email,
7132
- userName,
7133
- firstName,
7134
- lastName,
7157
+ const { id: userId, email, roles } = identifyData.user;
7158
+ const { name: tenantID, customProperties, domainName } = identifyData.currentTenant;
7159
+ const { instanceId, versionUI, versionBE } = identifyData;
7160
+ /**
7161
+ * Passing ID is a minimum required data to make an identify call to Gainsight.
7162
+ * isUserCreatedAfterAnonymizationWasActivated parameter is passed to later distinguish between users created before and after data anonymization done by Gainsight.
7163
+ * tenantID Used to distinguish between tenants when same email is used for different tenants.
7164
+ *
7165
+ * Due to GS limitations (GS does not allow clearing user attr/preferences via the GS tag!),
7166
+ * we always need to initialize fields related to PII to prevent leaking this data to GS when the user has disabled functional cookies.
7167
+ */
7168
+ const requiredIdentify = {
7169
+ /**
7170
+ * Email was not mandatory form field until 10.14
7171
+ */
7172
+ id: email ? email : `${userId}_${tenantID}_${instanceId}`,
7173
+ isUserCreatedAfterAnonymizationWasActivated: true,
7174
+ tenantID: tenantID,
7175
+ email: '--',
7176
+ userName: '--',
7177
+ firstName: '--',
7178
+ lastName: '--',
7135
7179
  domainName,
7136
7180
  versionUI,
7137
7181
  versionBE,
7138
7182
  userLanguage: this.translateService.currentLang,
7183
+ browserLanguage: this.translateService.getBrowserLang(),
7139
7184
  instanceId,
7140
- externalReference,
7141
- userRoles: this.transformUserRolesToStr(roles === null || roles === void 0 ? void 0 : roles.references)
7142
- }, {
7143
- id: `${name}_${instanceId}`,
7144
- instanceId
7145
- });
7185
+ externalReference: customProperties === null || customProperties === void 0 ? void 0 : customProperties.externalReference,
7186
+ userRoles: this.transformUserRolesToStr(roles === null || roles === void 0 ? void 0 : roles.references),
7187
+ customBranding: this.isCustomBranding(),
7188
+ fullTracking: sendPiiData
7189
+ };
7190
+ if (sendPiiData) {
7191
+ const { userName, firstName, lastName } = identifyData.user;
7192
+ const extendedIdentify = Object.assign(Object.assign({}, requiredIdentify), { email,
7193
+ userName,
7194
+ firstName,
7195
+ lastName });
7196
+ windowRef[this.GAINSIGHT_GLOBAL_SCOPE]('identify', extendedIdentify, {
7197
+ id: `${tenantID}_${instanceId}`,
7198
+ instanceId
7199
+ });
7200
+ return;
7201
+ }
7202
+ windowRef[this.GAINSIGHT_GLOBAL_SCOPE]('identify', requiredIdentify);
7146
7203
  }
7204
+ /**
7205
+ * Triggers an event to be recorded by Gainsight PX.
7206
+ * This method calls the Gainsight PX's tracking mechanism to log a specific event
7207
+ * along with its associated properties.
7208
+ * @param eventName - Name of the event to be triggered.
7209
+ * @param props - Optional properties associated with the event.
7210
+ */
7147
7211
  triggerEvent(eventName, props) {
7148
7212
  if (this.tagFunction && eventName) {
7149
7213
  eventName = this.prepareEventName(eventName);
@@ -7165,41 +7229,56 @@ class GainsightService {
7165
7229
  return this.getEnTranslation(textToTranslate, this.cachedRevertedTranslations);
7166
7230
  }
7167
7231
  /**
7168
- * Checks if the Gainsight's tag should be loaded.
7169
- * The decision to load Gainsight will depend on custom properties and functional cookies.
7170
- * @param customProperties Tenant's customProperties.
7232
+ * Determines whether personally identifiable information (PII) should be sent while loading a tag.
7233
+ * The decision to activate Gainsight and send PII relies on whether the cookiePreferences option is defined in the application settings,
7234
+ * if the functional cookie is enabled, and if the user grants permission.
7171
7235
  */
7172
- shouldLoadGainsightTag(customProperties) {
7173
- return (this.cookieBannerService.isConfigCookiePreferencesDefined() &&
7174
- this.cookieBannerService.isFunctionalCookieEnabled() &&
7175
- !this.isGainsightDisabled(customProperties) &&
7176
- !this.isCustomBranding());
7236
+ shouldSendPiiData() {
7237
+ return __awaiter(this, void 0, void 0, function* () {
7238
+ return (this.cookieBannerService.isConfigCookiePreferencesDefined() &&
7239
+ this.cookieBannerService.isFunctionalCookieEnabled() &&
7240
+ !(yield this.isGainsightPreferenceDisabledInUserPreferences(this.USER_PREFERENCES_GAINSIGHT_KEY)));
7241
+ });
7177
7242
  }
7243
+ /**
7244
+ * Updates a specific user attribute in the Gainsight global scope.
7245
+ * This method interfaces with the Gainsight global object to set a user's specific attribute with a provided value.
7246
+ * @param name - Name of the user attribute to be updated.
7247
+ * @param value - Value to set for the specified user attribute.
7248
+ */
7178
7249
  updateUserAttribute(name, value) {
7179
7250
  var _a;
7180
7251
  (_a = window[this.GAINSIGHT_GLOBAL_SCOPE]) === null || _a === void 0 ? void 0 : _a.call(window, 'set', 'user', { [name]: value });
7181
7252
  }
7253
+ /**
7254
+ * Determines if the current user has the capability to modify Gainsight PX settings.
7255
+ *
7256
+ * This method checks multiple conditions:
7257
+ * 1. Whether tracking has been disabled globally via application options.
7258
+ * 2. Whether Gainsight is disabled at the tenant level through custom properties.
7259
+ * 3. Whether a Gainsight key is available, either currently loaded or fetched asynchronously.
7260
+ * 4. Whether cookie preferences are defined and available for the user.
7261
+ *
7262
+ * @returns Promise that resolves to a boolean. True indicates the user can edit product experience settings, and false otherwise.
7263
+ */
7182
7264
  canEditProductExperienceSettings() {
7183
7265
  return __awaiter(this, void 0, void 0, function* () {
7184
7266
  const currentTenant = this.appState.currentTenant.value;
7185
7267
  const { customProperties } = currentTenant;
7268
+ if (this.isTrackingDisabled() ||
7269
+ this.isGainsightDisabledAtTenantCustomProperties(customProperties)) {
7270
+ return false;
7271
+ }
7186
7272
  const gainsightKey = !!this.gainsightKey || !!(yield this.getGainsightKey());
7187
7273
  return (gainsightKey &&
7188
7274
  this.cookieBannerService.isConfigCookiePreferencesDefined() &&
7189
- !this.isGainsightDisabled(customProperties) &&
7190
- !!this.cookieBannerService.getUserCookiePreferences() &&
7191
- !this.isCustomBranding());
7275
+ !!this.cookieBannerService.getUserCookiePreferences());
7192
7276
  });
7193
7277
  }
7194
- switchGainsightEngagementsVisibility(showGainsightEngagements) {
7195
- if (showGainsightEngagements) {
7196
- this.removeHidingStyle(this.HIDE_GAINSIGHT_BOT_STYLE_ID);
7197
- this.updateUserAttribute(this.ENGAGEMENTS, true);
7198
- return;
7199
- }
7200
- this.addHidingStyle(this.HIDE_GAINSIGHT_BOT_STYLE_ID, '#apt-widget { display:none }');
7201
- this.updateUserAttribute(this.ENGAGEMENTS, false);
7202
- }
7278
+ /**
7279
+ * Sets the global context for Gainsight with the current application name.
7280
+ * The global context can be utilized by Gainsight for various purposes, such as segmenting users.
7281
+ */
7203
7282
  setGlobalContext() {
7204
7283
  var _a;
7205
7284
  const currentAppState = this.appState.state$.value;
@@ -7212,18 +7291,31 @@ class GainsightService {
7212
7291
  }
7213
7292
  return flatMap(userRoles, (userRole) => userRole.role.name).join();
7214
7293
  }
7215
- addHidingStyle(styleId, textContent) {
7216
- if (this.document.getElementById(styleId)) {
7217
- return;
7218
- }
7219
- const style = this.document.createElement('style');
7220
- style.id = styleId;
7221
- style.textContent = textContent;
7222
- this.document.head.appendChild(style);
7294
+ /**
7295
+ * Checks if Gainsight is disabled based on tenant custom properties.
7296
+ *
7297
+ * @param customProperties - The custom properties of the tenant.
7298
+ * @returns {boolean} - True if Gainsight is disabled, false otherwise.
7299
+ */
7300
+ isGainsightDisabledAtTenantCustomProperties(customProperties) {
7301
+ const gainsightEnabled = customProperties && customProperties.gainsightEnabled;
7302
+ return gainsightEnabled === false;
7223
7303
  }
7224
- removeHidingStyle(styleId) {
7225
- const style = this.document.getElementById(styleId);
7226
- style === null || style === void 0 ? void 0 : style.remove();
7304
+ /**
7305
+ * Determines if custom branding is enabled based on the presence of a brand logo.
7306
+ *
7307
+ * @returns {boolean} - True if custom branding is applied, false otherwise.
7308
+ */
7309
+ isCustomBranding() {
7310
+ const brandingCssVars = this.options.get('brandingCssVars') || {};
7311
+ return !!brandingCssVars['brand-logo-img'];
7312
+ }
7313
+ /**
7314
+ * Determines if tracking is disabled based on the application options.
7315
+ * @returns `true` if tracking is disabled, otherwise `false`.
7316
+ */
7317
+ isTrackingDisabled() {
7318
+ return this.options.disableTracking === true;
7227
7319
  }
7228
7320
  prepareEventName(baseEventName) {
7229
7321
  return baseEventName
@@ -7234,14 +7326,6 @@ class GainsightService {
7234
7326
  return eventNamePart.replace(/`[\w\W]*`/g, '');
7235
7327
  }
7236
7328
  }
7237
- isGainsightDisabled(customProperties) {
7238
- const gainsightEnabled = customProperties && customProperties.gainsightEnabled;
7239
- return gainsightEnabled === false;
7240
- }
7241
- isCustomBranding() {
7242
- const brandingCssVars = this.options.get('brandingCssVars') || {};
7243
- return !!brandingCssVars['brand-logo-img'];
7244
- }
7245
7329
  loadScriptTag(scriptTag, key) {
7246
7330
  try {
7247
7331
  const windowRef = window;
@@ -7304,19 +7388,14 @@ class GainsightService {
7304
7388
  return enTranslation;
7305
7389
  }
7306
7390
  }
7307
- GainsightService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GainsightService, deps: [{ token: DOCUMENT }, { token: AppStateService }, { token: OptionsService }, { token: CookieBannerService }, { token: UserPreferencesService }, { token: i1$3.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
7391
+ GainsightService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GainsightService, deps: [{ token: AppStateService }, { token: OptionsService }, { token: CookieBannerService }, { token: UserPreferencesService }, { token: i1$3.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
7308
7392
  GainsightService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GainsightService, providedIn: 'root' });
7309
7393
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GainsightService, decorators: [{
7310
7394
  type: Injectable,
7311
7395
  args: [{
7312
7396
  providedIn: 'root'
7313
7397
  }]
7314
- }], ctorParameters: function () {
7315
- return [{ type: DOCUMENT, decorators: [{
7316
- type: Inject,
7317
- args: [DOCUMENT]
7318
- }] }, { type: AppStateService }, { type: OptionsService }, { type: CookieBannerService }, { type: UserPreferencesService }, { type: i1$3.TranslateService }];
7319
- } });
7398
+ }], ctorParameters: function () { return [{ type: AppStateService }, { type: OptionsService }, { type: CookieBannerService }, { type: UserPreferencesService }, { type: i1$3.TranslateService }]; } });
7320
7399
 
7321
7400
  /**
7322
7401
  * This component is used as the outlet to show the action bars.
@@ -12350,6 +12429,173 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
12350
12429
  type: Injectable
12351
12430
  }], ctorParameters: function () { return [{ type: i1$8.BsModalService }]; } });
12352
12431
 
12432
+ class UserEngagementsService {
12433
+ constructor(document, userPreferencesService, gainsightService) {
12434
+ this.document = document;
12435
+ this.userPreferencesService = userPreferencesService;
12436
+ this.gainsightService = gainsightService;
12437
+ this.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY = 'gainsightBotEnabled';
12438
+ this.userEngagementsEnabled$ = new BehaviorSubject(false);
12439
+ this.HIDE_GAINSIGHT_BOT_STYLE_ID = 'hide-gs-bot';
12440
+ this.ENGAGEMENTS = 'engagements';
12441
+ this.handleUserEngagements();
12442
+ }
12443
+ /**
12444
+ * Handles user engagement settings based on various conditions.
12445
+ *
12446
+ * - Waits for the Gainsight tracking to be loaded.
12447
+ * - Retrieves the engagement settings.
12448
+ * - Updates the engagement settings based on the combined observations.
12449
+ * - Finally, toggles the Gainsight engagements based on the latest `userEngagementsEnabled$` value.
12450
+ */
12451
+ handleUserEngagements() {
12452
+ this.gainsightService.trackingLoaded$
12453
+ .pipe(take(1), switchMap(() => this.getEngagementSettingsObservable()), tap((settings) => this.updateUserEngagementSettings(...settings)), switchMap(() => this.userEngagementsEnabled$.pipe(take(1))))
12454
+ .subscribe(isEnabled => this.toggleGainsightEngagements(isEnabled));
12455
+ }
12456
+ /**
12457
+ * Updates the user's preference for Gainsight Engagements.
12458
+ * @param {boolean} isEnabled - The new value for the user's engagement preference.
12459
+ */
12460
+ updateUserEngagementPreference(isEnabled) {
12461
+ this.userEngagementsEnabled$.next(isEnabled);
12462
+ this.userPreferencesService.set(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY, this.userEngagementsEnabled$.value);
12463
+ }
12464
+ /**
12465
+ * Toggles the visibility of Gainsight Engagements based on the provided flag.
12466
+ *
12467
+ * @param isEnabled - A flag indicating whether Gainsight Engagements should be visible.
12468
+ */
12469
+ toggleGainsightEngagements(isEnabled) {
12470
+ isEnabled ? this.showGainsightEngagements() : this.hideGainsightEngagements();
12471
+ }
12472
+ /**
12473
+ * Constructs an observable that emits an array of boolean values representing
12474
+ * the current engagement settings. The observable combines the latest values from:
12475
+ *
12476
+ * 1. User's preferences for Gainsight engagements.
12477
+ * 2. A flag indicating if PII data should be sent.
12478
+ * 3. A flag indicating if the platform uses custom branding.
12479
+ *
12480
+ * @returns An observable emitting an array of boolean values.
12481
+ */
12482
+ getEngagementSettingsObservable() {
12483
+ return combineLatest([
12484
+ this.userPreferencesService.observe(this.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY),
12485
+ from(this.gainsightService.shouldSendPiiData()),
12486
+ of(this.gainsightService.isCustomBranding())
12487
+ ]);
12488
+ }
12489
+ /**
12490
+ * Updates user engagement settings based on provided preferences and settings.
12491
+ *
12492
+ * Based on the received values, the method decides to:
12493
+ * 1. Disable user engagements if PII data should not be shared or certain branding/settings conditions are met.
12494
+ * 2. Update the user engagement preference if the user engagement bot setting is undefined.
12495
+ *
12496
+ * @param userEngagementBotSetting - The user's setting for the engagement bot.
12497
+ * @param shouldSendPiiData - Indicates whether PII data should be shared.
12498
+ * @param hasCustomBranding - Indicates if custom branding is applied.
12499
+ */
12500
+ updateUserEngagementSettings(userEngagementBotSetting, shouldSendPiiData, hasCustomBranding) {
12501
+ if (this.shouldDisableUserEngagementsDueToPIIData(shouldSendPiiData)) {
12502
+ this.userEngagementsEnabled$.next(false);
12503
+ }
12504
+ else if (this.isUserEngagementBotSettingUndefined(userEngagementBotSetting)) {
12505
+ /**
12506
+ * Case where the user is new (freshly created) and has not changed the user engagement settings in the user edit modal (untouched state).
12507
+ * When custom branding is not set, we will set the user engagements in the user preferences to true by default.
12508
+ */
12509
+ this.updateUserEngagementPreference(!hasCustomBranding);
12510
+ }
12511
+ else {
12512
+ this.userEngagementsEnabled$.next(userEngagementBotSetting);
12513
+ }
12514
+ }
12515
+ /**
12516
+ * Determines whether user engagements should be disabled due to PII data settings.
12517
+ *
12518
+ * If the `shouldSendPiiData` parameter is false, this indicates that the user engagements
12519
+ * should be disabled to prevent sharing personally identifiable information.
12520
+ *
12521
+ * @param {boolean} shouldSendPiiData - Indicates whether PII data is allowed to be sent.
12522
+ * @returns {boolean} Returns true if user engagements should be disabled, otherwise false.
12523
+ */
12524
+ shouldDisableUserEngagementsDueToPIIData(shouldSendPiiData) {
12525
+ return !shouldSendPiiData;
12526
+ }
12527
+ /**
12528
+ * Determines if the user engagement bot setting is undefined.
12529
+ *
12530
+ * @param {boolean | undefined} userEngagementBotSetting - The setting value to check.
12531
+ * @returns {boolean} Returns `true` if the setting is undefined; otherwise, `false`.
12532
+ *
12533
+ * This scenario occurs when a user is new and hasn't modified the bot settings in the user details UI yet.
12534
+ */
12535
+ isUserEngagementBotSettingUndefined(userEngagementBotSetting) {
12536
+ return userEngagementBotSetting === undefined;
12537
+ }
12538
+ /**
12539
+ * Enables the visibility of Gainsight engagements.
12540
+ *
12541
+ * This method removes the CSS styles that hide the Gainsight engagements
12542
+ * and updates the relevant user attribute to mark the engagements as visible.
12543
+ */
12544
+ showGainsightEngagements() {
12545
+ this.removeHidingStyle(this.HIDE_GAINSIGHT_BOT_STYLE_ID);
12546
+ this.gainsightService.updateUserAttribute(this.ENGAGEMENTS, true);
12547
+ }
12548
+ /**
12549
+ * Hides the Gainsight engagements.
12550
+ *
12551
+ * This method applies CSS styles to hide the Gainsight engagements
12552
+ * and updates the relevant user attribute to mark the engagements as hidden.
12553
+ */
12554
+ hideGainsightEngagements() {
12555
+ this.addHidingStyle(this.HIDE_GAINSIGHT_BOT_STYLE_ID, '#apt-widget { display:none }');
12556
+ this.gainsightService.updateUserAttribute(this.ENGAGEMENTS, false);
12557
+ }
12558
+ /**
12559
+ * Removes the specified CSS style from the document.
12560
+ *
12561
+ * @param {string} styleId - The ID of the CSS style element to remove.
12562
+ */
12563
+ removeHidingStyle(styleId) {
12564
+ const style = this.document.getElementById(styleId);
12565
+ style === null || style === void 0 ? void 0 : style.remove();
12566
+ }
12567
+ /**
12568
+ * Adds a new CSS style to the document.
12569
+ *
12570
+ * If the style with the specified ID already exists, the method will do nothing.
12571
+ * Otherwise, it creates a new `<style>` element with the given ID and content,
12572
+ * then appends it to the document head.
12573
+ *
12574
+ * @param {string} styleId - The ID to assign to the new style element.
12575
+ * @param {string} textContent - The CSS rules to be included in the style.
12576
+ */
12577
+ addHidingStyle(styleId, textContent) {
12578
+ if (this.document.getElementById(styleId)) {
12579
+ return;
12580
+ }
12581
+ const style = this.document.createElement('style');
12582
+ style.id = styleId;
12583
+ style.textContent = textContent;
12584
+ this.document.head.appendChild(style);
12585
+ }
12586
+ }
12587
+ UserEngagementsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEngagementsService, deps: [{ token: DOCUMENT }, { token: UserPreferencesService }, { token: GainsightService }], target: i0.ɵɵFactoryTarget.Injectable });
12588
+ UserEngagementsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEngagementsService, providedIn: 'root' });
12589
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEngagementsService, decorators: [{
12590
+ type: Injectable,
12591
+ args: [{ providedIn: 'root' }]
12592
+ }], ctorParameters: function () {
12593
+ return [{ type: DOCUMENT, decorators: [{
12594
+ type: Inject,
12595
+ args: [DOCUMENT]
12596
+ }] }, { type: UserPreferencesService }, { type: GainsightService }];
12597
+ } });
12598
+
12353
12599
  class TotpChallengeComponent {
12354
12600
  constructor(loginService, users, alert) {
12355
12601
  this.loginService = loginService;
@@ -12748,7 +12994,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
12748
12994
  }] } });
12749
12995
 
12750
12996
  class UserEditComponent {
12751
- constructor(state, translate, bsModalService, alert, userService, tenantLoginOptionsService, tenantService, userPreferencesService, gainsightService) {
12997
+ constructor(state, translate, bsModalService, alert, userService, tenantLoginOptionsService, tenantService) {
12752
12998
  this.state = state;
12753
12999
  this.translate = translate;
12754
13000
  this.bsModalService = bsModalService;
@@ -12756,17 +13002,15 @@ class UserEditComponent {
12756
13002
  this.userService = userService;
12757
13003
  this.tenantLoginOptionsService = tenantLoginOptionsService;
12758
13004
  this.tenantService = tenantService;
12759
- this.userPreferencesService = userPreferencesService;
12760
- this.gainsightService = gainsightService;
12761
13005
  this.loading = false;
12762
- this.showProductUsageSetting = false;
13006
+ this.showProductExperienceOptions = false;
12763
13007
  this.isUsageTrackingEnabled = true;
12764
- this.isGainsightEngagementsEnabled = true;
13008
+ this.isUserEngagementPreferenceEnabled = true;
12765
13009
  this.onUser = new EventEmitter();
12766
- this.onLanguage = new EventEmitter();
12767
- this.onProductExperience = new EventEmitter();
12768
- this.onGainsightEngagements = new EventEmitter();
13010
+ this.onUsageTrackingChange = new EventEmitter();
13011
+ this.onUserEngagementPreferenceChange = new EventEmitter();
12769
13012
  this.onCancel = new EventEmitter();
13013
+ this.onLanguage = new EventEmitter();
12770
13014
  this.userHasActiveTotp = false;
12771
13015
  this.userCanSetupTotp = false;
12772
13016
  this.isPhoneRequired = false;
@@ -12792,18 +13036,6 @@ class UserEditComponent {
12792
13036
  }
12793
13037
  });
12794
13038
  }
12795
- onEnablingProductUsageTracking(isUsageTrackingEnabled) {
12796
- return __awaiter(this, void 0, void 0, function* () {
12797
- if (isUsageTrackingEnabled && this.isGainsightEngagementsEnabled === undefined) {
12798
- this.isGainsightEngagementsEnabled = yield this.userPreferencesService
12799
- .get(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY)
12800
- .toPromise();
12801
- }
12802
- });
12803
- }
12804
- get langs() {
12805
- return this.state.state.langs;
12806
- }
12807
13039
  setupTotp() {
12808
13040
  this.bsModalService.show(UserTotpSetupComponent, {
12809
13041
  class: 'modal-sm',
@@ -12820,9 +13052,13 @@ class UserEditComponent {
12820
13052
  if (this.loading) {
12821
13053
  return;
12822
13054
  }
12823
- if (this.showProductUsageSetting) {
12824
- this.onProductExperience.emit(this.isUsageTrackingEnabled);
12825
- this.onGainsightEngagements.emit(this.isGainsightEngagementsEnabled);
13055
+ if (this.showProductExperienceOptions) {
13056
+ this.onUsageTrackingChange.emit(this.isUsageTrackingEnabled);
13057
+ /**
13058
+ * Emits a user engagement preference change event.
13059
+ * If usage tracking is disabled, it emits `false`. Otherwise, it emits the current state of the user engagement preference.
13060
+ */
13061
+ this.onUserEngagementPreferenceChange.emit(this.isUsageTrackingEnabled === false ? false : this.isUserEngagementPreferenceEnabled);
12826
13062
  }
12827
13063
  this.onUser.emit(this._user);
12828
13064
  });
@@ -12830,6 +13066,9 @@ class UserEditComponent {
12830
13066
  onNewPasswordChanged(newPassword) {
12831
13067
  this._user.password = newPassword.password;
12832
13068
  }
13069
+ get langs() {
13070
+ return this.state.state.langs;
13071
+ }
12833
13072
  initializeTotpSettings() {
12834
13073
  return __awaiter(this, void 0, void 0, function* () {
12835
13074
  try {
@@ -12852,37 +13091,37 @@ class UserEditComponent {
12852
13091
  });
12853
13092
  }
12854
13093
  }
12855
- UserEditComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditComponent, deps: [{ token: AppStateService }, { token: TranslateService }, { token: i1$8.BsModalService }, { token: AlertService }, { token: i1$2.UserService }, { token: i1$2.TenantLoginOptionsService }, { token: i1$2.TenantService }, { token: UserPreferencesService }, { token: GainsightService }], target: i0.ɵɵFactoryTarget.Component });
12856
- UserEditComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: UserEditComponent, selector: "c8y-user-edit", inputs: { lang: "lang", loading: "loading", user: "user", showProductUsageSetting: "showProductUsageSetting", isUsageTrackingEnabled: "isUsageTrackingEnabled", isGainsightEngagementsEnabled: "isGainsightEngagementsEnabled" }, outputs: { onUser: "onUser", onLanguage: "onLanguage", onProductExperience: "onProductExperience", onGainsightEngagements: "onGainsightEngagements", onCancel: "onCancel" }, ngImport: i0, template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"d-block p-24 p-b-0\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n Some of the user settings are not editable here because they are managed via your\n authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (for example, email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"true\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n id=\"userLastName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n [required]=\"isPhoneRequired\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">\n {{ translate.getNativeLanguage(lang) }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <c8y-form-group class=\"p-t-16 separator-top\" *ngIf=\"showProductUsageSetting\">\n <label translate>Product experience</label>\n <label class=\"c8y-switch\" for=\"productUsageTracking\">\n <input\n id=\"productUsageTracking\"\n name=\"productUsageTracking\"\n type=\"checkbox\"\n (change)=\"onEnablingProductUsageTracking(isUsageTrackingEnabled)\"\n [(ngModel)]=\"isUsageTrackingEnabled\"\n />\n <span></span>\n {{ 'Enable tracking to enhance the product experience' | translate }}\n </label>\n <ng-container *ngIf=\"isUsageTrackingEnabled\">\n <label class=\"c8y-switch m-l-0\" for=\"gainsightEngagements\">\n <input\n id=\"gainsightEngagements\"\n name=\"gainsightEngagements\"\n type=\"checkbox\"\n [(ngModel)]=\"isGainsightEngagementsEnabled\"\n />\n <span></span>\n {{ 'Enable in-product information & communication' | translate }}\n </label>\n </ng-container>\n </c8y-form-group>\n\n <div class=\"form-group p-t-16 separator-top\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp && isTfaEnabled\"\n >\n {{ 'Set up two-factor authentication' | translate }}\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label\n title=\"{{ 'Send me information about outages, maintenance or updates.' | translate }}\"\n class=\"c8y-checkbox\"\n >\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n <span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </div>\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: PhoneValidationDirective, selector: "[c8yPhoneValidation]" }, { kind: "directive", type: DefaultValidationDirective, selector: "[c8yDefaultValidation]", inputs: ["c8yDefaultValidation"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.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$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2$2.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NewPasswordComponent, selector: "c8y-new-password", outputs: ["password"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
13094
+ UserEditComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditComponent, deps: [{ token: AppStateService }, { token: TranslateService }, { token: i1$8.BsModalService }, { token: AlertService }, { token: i1$2.UserService }, { token: i1$2.TenantLoginOptionsService }, { token: i1$2.TenantService }], target: i0.ɵɵFactoryTarget.Component });
13095
+ UserEditComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: UserEditComponent, selector: "c8y-user-edit", inputs: { lang: "lang", loading: "loading", user: "user", showProductExperienceOptions: "showProductExperienceOptions", isUsageTrackingEnabled: "isUsageTrackingEnabled", isUserEngagementPreferenceEnabled: "isUserEngagementPreferenceEnabled" }, outputs: { onUser: "onUser", onUsageTrackingChange: "onUsageTrackingChange", onUserEngagementPreferenceChange: "onUserEngagementPreferenceChange", onCancel: "onCancel", onLanguage: "onLanguage" }, ngImport: i0, template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"d-block p-24 p-b-0\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n Some of the user settings are not editable here because they are managed via your\n authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (for example, email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"true\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n id=\"userLastName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n [required]=\"isPhoneRequired\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">\n {{ translate.getNativeLanguage(lang) }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <c8y-form-group class=\"p-t-16 separator-top\" *ngIf=\"showProductExperienceOptions\">\n <label translate>Product experience</label>\n <label class=\"c8y-switch\" for=\"productUsageTracking\">\n <input\n id=\"productUsageTracking\"\n name=\"productUsageTracking\"\n type=\"checkbox\"\n [(ngModel)]=\"isUsageTrackingEnabled\"\n />\n <span></span>\n {{ 'Enable personalized product experience tracking' | translate }}\n </label>\n <ng-container *ngIf=\"isUsageTrackingEnabled\">\n <label class=\"c8y-switch m-l-0\" for=\"userEngagementPreference\">\n <input\n id=\"userEngagementPreference\"\n name=\"userEngagementPreference\"\n type=\"checkbox\"\n [(ngModel)]=\"isUserEngagementPreferenceEnabled\"\n />\n <span></span>\n {{ 'Enable in-product information & communication' | translate }}\n </label>\n </ng-container>\n </c8y-form-group>\n\n <div class=\"form-group p-t-16 separator-top\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp && isTfaEnabled\"\n >\n {{ 'Set up two-factor authentication' | translate }}\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label\n title=\"{{ 'Send me information about outages, maintenance or updates.' | translate }}\"\n class=\"c8y-checkbox\"\n >\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n <span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </div>\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: PhoneValidationDirective, selector: "[c8yPhoneValidation]" }, { kind: "directive", type: DefaultValidationDirective, selector: "[c8yDefaultValidation]", inputs: ["c8yDefaultValidation"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.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$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2$2.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NewPasswordComponent, selector: "c8y-new-password", outputs: ["password"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
12857
13096
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditComponent, decorators: [{
12858
13097
  type: Component,
12859
- args: [{ selector: 'c8y-user-edit', template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"d-block p-24 p-b-0\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n Some of the user settings are not editable here because they are managed via your\n authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (for example, email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"true\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n id=\"userLastName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n [required]=\"isPhoneRequired\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">\n {{ translate.getNativeLanguage(lang) }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <c8y-form-group class=\"p-t-16 separator-top\" *ngIf=\"showProductUsageSetting\">\n <label translate>Product experience</label>\n <label class=\"c8y-switch\" for=\"productUsageTracking\">\n <input\n id=\"productUsageTracking\"\n name=\"productUsageTracking\"\n type=\"checkbox\"\n (change)=\"onEnablingProductUsageTracking(isUsageTrackingEnabled)\"\n [(ngModel)]=\"isUsageTrackingEnabled\"\n />\n <span></span>\n {{ 'Enable tracking to enhance the product experience' | translate }}\n </label>\n <ng-container *ngIf=\"isUsageTrackingEnabled\">\n <label class=\"c8y-switch m-l-0\" for=\"gainsightEngagements\">\n <input\n id=\"gainsightEngagements\"\n name=\"gainsightEngagements\"\n type=\"checkbox\"\n [(ngModel)]=\"isGainsightEngagementsEnabled\"\n />\n <span></span>\n {{ 'Enable in-product information & communication' | translate }}\n </label>\n </ng-container>\n </c8y-form-group>\n\n <div class=\"form-group p-t-16 separator-top\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp && isTfaEnabled\"\n >\n {{ 'Set up two-factor authentication' | translate }}\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label\n title=\"{{ 'Send me information about outages, maintenance or updates.' | translate }}\"\n class=\"c8y-checkbox\"\n >\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n <span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </div>\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n" }]
12860
- }], ctorParameters: function () { return [{ type: AppStateService }, { type: TranslateService }, { type: i1$8.BsModalService }, { type: AlertService }, { type: i1$2.UserService }, { type: i1$2.TenantLoginOptionsService }, { type: i1$2.TenantService }, { type: UserPreferencesService }, { type: GainsightService }]; }, propDecorators: { lang: [{
13098
+ args: [{ selector: 'c8y-user-edit', template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"d-block p-24 p-b-0\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n Some of the user settings are not editable here because they are managed via your\n authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (for example, email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"true\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n id=\"userLastName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n [required]=\"isPhoneRequired\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">\n {{ translate.getNativeLanguage(lang) }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <c8y-form-group class=\"p-t-16 separator-top\" *ngIf=\"showProductExperienceOptions\">\n <label translate>Product experience</label>\n <label class=\"c8y-switch\" for=\"productUsageTracking\">\n <input\n id=\"productUsageTracking\"\n name=\"productUsageTracking\"\n type=\"checkbox\"\n [(ngModel)]=\"isUsageTrackingEnabled\"\n />\n <span></span>\n {{ 'Enable personalized product experience tracking' | translate }}\n </label>\n <ng-container *ngIf=\"isUsageTrackingEnabled\">\n <label class=\"c8y-switch m-l-0\" for=\"userEngagementPreference\">\n <input\n id=\"userEngagementPreference\"\n name=\"userEngagementPreference\"\n type=\"checkbox\"\n [(ngModel)]=\"isUserEngagementPreferenceEnabled\"\n />\n <span></span>\n {{ 'Enable in-product information & communication' | translate }}\n </label>\n </ng-container>\n </c8y-form-group>\n\n <div class=\"form-group p-t-16 separator-top\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp && isTfaEnabled\"\n >\n {{ 'Set up two-factor authentication' | translate }}\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label\n title=\"{{ 'Send me information about outages, maintenance or updates.' | translate }}\"\n class=\"c8y-checkbox\"\n >\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n <span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </div>\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n" }]
13099
+ }], ctorParameters: function () { return [{ type: AppStateService }, { type: TranslateService }, { type: i1$8.BsModalService }, { type: AlertService }, { type: i1$2.UserService }, { type: i1$2.TenantLoginOptionsService }, { type: i1$2.TenantService }]; }, propDecorators: { lang: [{
12861
13100
  type: Input
12862
13101
  }], loading: [{
12863
13102
  type: Input
12864
13103
  }], user: [{
12865
13104
  type: Input
12866
- }], showProductUsageSetting: [{
13105
+ }], showProductExperienceOptions: [{
12867
13106
  type: Input
12868
13107
  }], isUsageTrackingEnabled: [{
12869
13108
  type: Input
12870
- }], isGainsightEngagementsEnabled: [{
13109
+ }], isUserEngagementPreferenceEnabled: [{
12871
13110
  type: Input
12872
13111
  }], onUser: [{
12873
13112
  type: Output
12874
- }], onLanguage: [{
12875
- type: Output
12876
- }], onProductExperience: [{
13113
+ }], onUsageTrackingChange: [{
12877
13114
  type: Output
12878
- }], onGainsightEngagements: [{
13115
+ }], onUserEngagementPreferenceChange: [{
12879
13116
  type: Output
12880
13117
  }], onCancel: [{
12881
13118
  type: Output
13119
+ }], onLanguage: [{
13120
+ type: Output
12882
13121
  }] } });
12883
13122
 
12884
13123
  class UserEditModalComponent {
12885
- constructor(modal, user, ui, auth, client, alert, translate, userPreferences, c8yModalService, gainsightService, cookieBannerService, loginService, passwordService) {
13124
+ constructor(modal, user, ui, auth, client, alert, translate, userPreferences, c8yModalService, gainsightService, cookieBannerService, loginService, passwordService, userEngagementsService) {
12886
13125
  this.modal = modal;
12887
13126
  this.user = user;
12888
13127
  this.ui = ui;
@@ -12896,21 +13135,37 @@ class UserEditModalComponent {
12896
13135
  this.cookieBannerService = cookieBannerService;
12897
13136
  this.loginService = loginService;
12898
13137
  this.passwordService = passwordService;
13138
+ this.userEngagementsService = userEngagementsService;
12899
13139
  this.loading = false;
12900
- this.showProductUsageSetting = false;
13140
+ this.showProductExperienceOptions = false;
12901
13141
  this.lang = this.ui.state.lang;
12902
13142
  }
12903
13143
  ngOnInit() {
12904
13144
  return __awaiter(this, void 0, void 0, function* () {
12905
13145
  this.updateUserInAppState();
12906
- this.showProductUsageSetting = yield this.gainsightService.canEditProductExperienceSettings();
12907
- if (this.showProductUsageSetting) {
12908
- if (this.cookieBannerService.isFunctionalCookieEnabled()) {
12909
- this.currentUsageTrackingState =
12910
- !(yield this.gainsightService.isGainsightPreferenceDisabledInUserPreferences(this.gainsightService.USER_PREFERENCES_GAINSIGHT_KEY));
12911
- this.currentGainsightEngagementsState =
12912
- !(yield this.gainsightService.isGainsightPreferenceDisabledInUserPreferences(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY));
12913
- }
13146
+ yield this.setInitialProductExperienceOptions();
13147
+ });
13148
+ }
13149
+ /**
13150
+ * Initializes product experience options for the user.
13151
+ *
13152
+ * This function performs the following operations:
13153
+ * - Determines if the user has the permission to edit product experience options.
13154
+ * - If the user has the permission and functional cookies are enabled:
13155
+ * - Checks whether personalized product experience tracking is active.
13156
+ * - Checks whether in-product information and communication is active.
13157
+ */
13158
+ setInitialProductExperienceOptions() {
13159
+ return __awaiter(this, void 0, void 0, function* () {
13160
+ this.showProductExperienceOptions =
13161
+ yield this.gainsightService.canEditProductExperienceSettings();
13162
+ if (this.showProductExperienceOptions && this.cookieBannerService.isFunctionalCookieEnabled()) {
13163
+ // Enable personalized product experience tracking option
13164
+ this.currentUsageTrackingState =
13165
+ !(yield this.gainsightService.isGainsightPreferenceDisabledInUserPreferences(this.gainsightService.USER_PREFERENCES_GAINSIGHT_KEY));
13166
+ // Enable in-product information & communication option
13167
+ this.currentUserEngagementPreferenceInitialState =
13168
+ this.userEngagementsService.userEngagementsEnabled$.value;
12914
13169
  }
12915
13170
  });
12916
13171
  }
@@ -12928,11 +13183,11 @@ class UserEditModalComponent {
12928
13183
  yield this.translate.switchToLanguage(this.changedLang);
12929
13184
  });
12930
13185
  }
12931
- onProductExperience(option) {
12932
- this.usageTrackingState = option;
13186
+ onUsageTrackingChange(isEnabled) {
13187
+ this.usageTrackingState = isEnabled;
12933
13188
  }
12934
- onGainsightEngagements(option) {
12935
- this.gainsightEngagementsState = option;
13189
+ onUserEngagementPreferenceChange(isEnabled) {
13190
+ this.userEngagementPreferenceNewState = isEnabled;
12936
13191
  }
12937
13192
  updateAndClose(user) {
12938
13193
  return __awaiter(this, void 0, void 0, function* () {
@@ -12955,16 +13210,7 @@ class UserEditModalComponent {
12955
13210
  if (this.changedLang && this.changedLang !== this.lang) {
12956
13211
  reloadRequired = yield this.persistLanguage(this.changedLang);
12957
13212
  }
12958
- if (this.currentGainsightEngagementsState !== this.gainsightEngagementsState) {
12959
- yield this.userPreferences.set(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY, this.gainsightEngagementsState);
12960
- }
12961
- if (this.currentUsageTrackingState !== this.usageTrackingState) {
12962
- yield this.userPreferences.set(this.gainsightService.USER_PREFERENCES_GAINSIGHT_KEY, this.usageTrackingState);
12963
- this.gainsightService.setFunctionalCookie(this.usageTrackingState);
12964
- this.usageTrackingState
12965
- ? yield this.gainsightService.loadTag(this.client.tenant)
12966
- : yield this.gainsightTrackingAppReload();
12967
- }
13213
+ yield this.updateProductExperienceOptions();
12968
13214
  if (user.customProperties.userOrigin !== 'OAUTH2') {
12969
13215
  yield this.user.updateCurrent(omit(user, 'password'));
12970
13216
  yield this.updateUserInAppState();
@@ -13021,6 +13267,38 @@ class UserEditModalComponent {
13021
13267
  }
13022
13268
  });
13023
13269
  }
13270
+ updateProductExperienceOptions() {
13271
+ return __awaiter(this, void 0, void 0, function* () {
13272
+ this.updateUserEngagementsPreference();
13273
+ yield this.updateTrackingOption();
13274
+ });
13275
+ }
13276
+ /**
13277
+ * Updates the user engagement preference if it has changed from the initial state.
13278
+ * Calls the user engagements service to update the preference.
13279
+ *
13280
+ * The update only occurs if the current preference differs from the new state.
13281
+ */
13282
+ updateUserEngagementsPreference() {
13283
+ if (this.currentUserEngagementPreferenceInitialState !== this.userEngagementPreferenceNewState) {
13284
+ this.userEngagementsService.updateUserEngagementPreference(this.userEngagementPreferenceNewState);
13285
+ }
13286
+ }
13287
+ /**
13288
+ * Asynchronously updates the tracking option for user preferences.
13289
+ * If the current usage tracking state differs from the new state,
13290
+ * it updates the Gainsight preferences and sets a functional cookie
13291
+ * before triggering a reload of the application.
13292
+ */
13293
+ updateTrackingOption() {
13294
+ return __awaiter(this, void 0, void 0, function* () {
13295
+ if (this.currentUsageTrackingState !== this.usageTrackingState) {
13296
+ yield this.userPreferences.set(this.gainsightService.USER_PREFERENCES_GAINSIGHT_KEY, this.usageTrackingState);
13297
+ this.gainsightService.setFunctionalCookie(this.usageTrackingState);
13298
+ yield this.gainsightTrackingAppReload();
13299
+ }
13300
+ });
13301
+ }
13024
13302
  updateUserInAppState() {
13025
13303
  return __awaiter(this, void 0, void 0, function* () {
13026
13304
  const currentUserResult = yield this.user.current();
@@ -13036,12 +13314,12 @@ class UserEditModalComponent {
13036
13314
  this.auth.updateCredentials(newCredentials);
13037
13315
  }
13038
13316
  }
13039
- UserEditModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditModalComponent, deps: [{ token: i1$8.BsModalRef }, { token: i1$2.UserService }, { token: AppStateService }, { token: i1$2.BasicAuth }, { token: i1$2.FetchClient }, { token: AlertService }, { token: TranslateService }, { token: UserPreferencesService }, { token: ModalService }, { token: GainsightService }, { token: CookieBannerService }, { token: LoginService }, { token: PasswordService }], target: i0.ɵɵFactoryTarget.Component });
13040
- UserEditModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: UserEditModalComponent, selector: "c8y-user-edit-modal", ngImport: i0, template: "<c8y-modal [customFooter]=\"true\" [title]=\"'Edit user' | translate\" (onDismiss)=\"onDismiss()\">\n <c8y-user-edit\n [lang]=\"lang\"\n [user]=\"ui.currentUser | async\"\n [loading]=\"loading\"\n [isUsageTrackingEnabled]=\"currentUsageTrackingState\"\n [isGainsightEngagementsEnabled]=\"currentGainsightEngagementsState\"\n [showProductUsageSetting]=\"showProductUsageSetting\"\n (onLanguage)=\"onLanguage($event)\"\n (onProductExperience)=\"onProductExperience($event)\"\n (onGainsightEngagements)=\"onGainsightEngagements($event)\"\n (onUser)=\"updateAndClose($event)\"\n (onCancel)=\"onDismiss()\"\n >\n </c8y-user-edit>\n</c8y-modal>\n", dependencies: [{ kind: "component", type: ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: UserEditComponent, selector: "c8y-user-edit", inputs: ["lang", "loading", "user", "showProductUsageSetting", "isUsageTrackingEnabled", "isGainsightEngagementsEnabled"], outputs: ["onUser", "onLanguage", "onProductExperience", "onGainsightEngagements", "onCancel"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
13317
+ UserEditModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditModalComponent, deps: [{ token: i1$8.BsModalRef }, { token: i1$2.UserService }, { token: AppStateService }, { token: i1$2.BasicAuth }, { token: i1$2.FetchClient }, { token: AlertService }, { token: TranslateService }, { token: UserPreferencesService }, { token: ModalService }, { token: GainsightService }, { token: CookieBannerService }, { token: LoginService }, { token: PasswordService }, { token: UserEngagementsService }], target: i0.ɵɵFactoryTarget.Component });
13318
+ UserEditModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: UserEditModalComponent, selector: "c8y-user-edit-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"'Edit user' | translate\"\n [customFooter]=\"true\"\n (onDismiss)=\"onDismiss()\"\n>\n <c8y-user-edit\n [lang]=\"lang\"\n [user]=\"ui.currentUser | async\"\n [loading]=\"loading\"\n [isUsageTrackingEnabled]=\"currentUsageTrackingState\"\n [isUserEngagementPreferenceEnabled]=\"currentUserEngagementPreferenceInitialState\"\n [showProductExperienceOptions]=\"showProductExperienceOptions\"\n (onUsageTrackingChange)=\"onUsageTrackingChange($event)\"\n (onUserEngagementPreferenceChange)=\"onUserEngagementPreferenceChange($event)\"\n (onUser)=\"updateAndClose($event)\"\n (onCancel)=\"onDismiss()\"\n (onLanguage)=\"onLanguage($event)\"\n ></c8y-user-edit>\n</c8y-modal>\n", dependencies: [{ kind: "component", type: ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: UserEditComponent, selector: "c8y-user-edit", inputs: ["lang", "loading", "user", "showProductExperienceOptions", "isUsageTrackingEnabled", "isUserEngagementPreferenceEnabled"], outputs: ["onUser", "onUsageTrackingChange", "onUserEngagementPreferenceChange", "onCancel", "onLanguage"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
13041
13319
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: UserEditModalComponent, decorators: [{
13042
13320
  type: Component,
13043
- args: [{ selector: 'c8y-user-edit-modal', template: "<c8y-modal [customFooter]=\"true\" [title]=\"'Edit user' | translate\" (onDismiss)=\"onDismiss()\">\n <c8y-user-edit\n [lang]=\"lang\"\n [user]=\"ui.currentUser | async\"\n [loading]=\"loading\"\n [isUsageTrackingEnabled]=\"currentUsageTrackingState\"\n [isGainsightEngagementsEnabled]=\"currentGainsightEngagementsState\"\n [showProductUsageSetting]=\"showProductUsageSetting\"\n (onLanguage)=\"onLanguage($event)\"\n (onProductExperience)=\"onProductExperience($event)\"\n (onGainsightEngagements)=\"onGainsightEngagements($event)\"\n (onUser)=\"updateAndClose($event)\"\n (onCancel)=\"onDismiss()\"\n >\n </c8y-user-edit>\n</c8y-modal>\n" }]
13044
- }], ctorParameters: function () { return [{ type: i1$8.BsModalRef }, { type: i1$2.UserService }, { type: AppStateService }, { type: i1$2.BasicAuth }, { type: i1$2.FetchClient }, { type: AlertService }, { type: TranslateService }, { type: UserPreferencesService }, { type: ModalService }, { type: GainsightService }, { type: CookieBannerService }, { type: LoginService }, { type: PasswordService }]; } });
13321
+ args: [{ selector: 'c8y-user-edit-modal', template: "<c8y-modal\n [title]=\"'Edit user' | translate\"\n [customFooter]=\"true\"\n (onDismiss)=\"onDismiss()\"\n>\n <c8y-user-edit\n [lang]=\"lang\"\n [user]=\"ui.currentUser | async\"\n [loading]=\"loading\"\n [isUsageTrackingEnabled]=\"currentUsageTrackingState\"\n [isUserEngagementPreferenceEnabled]=\"currentUserEngagementPreferenceInitialState\"\n [showProductExperienceOptions]=\"showProductExperienceOptions\"\n (onUsageTrackingChange)=\"onUsageTrackingChange($event)\"\n (onUserEngagementPreferenceChange)=\"onUserEngagementPreferenceChange($event)\"\n (onUser)=\"updateAndClose($event)\"\n (onCancel)=\"onDismiss()\"\n (onLanguage)=\"onLanguage($event)\"\n ></c8y-user-edit>\n</c8y-modal>\n" }]
13322
+ }], ctorParameters: function () { return [{ type: i1$8.BsModalRef }, { type: i1$2.UserService }, { type: AppStateService }, { type: i1$2.BasicAuth }, { type: i1$2.FetchClient }, { type: AlertService }, { type: TranslateService }, { type: UserPreferencesService }, { type: ModalService }, { type: GainsightService }, { type: CookieBannerService }, { type: LoginService }, { type: PasswordService }, { type: UserEngagementsService }]; } });
13045
13323
 
13046
13324
  class UserMenuItemComponent {
13047
13325
  constructor(userService) {
@@ -16754,50 +17032,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
16754
17032
  /**
16755
17033
  * This module enables an tenant to activate the product experience
16756
17034
  * software [Gainsight](https://www.gainsight.com/product-experience/) to help
16757
- * and track user actions. Gainsight is only activated, if the tenant custom
16758
- * property `gainsightEnabled` is set to true.
17035
+ * and track user actions.
16759
17036
  */
16760
17037
  class ProductExperienceModule {
16761
- constructor(appState, gainsightService, cookieBannerService, userPreferencesService) {
17038
+ constructor(appState, gainsightService, cookieBannerService,
17039
+ // Don't remove it, otherwise UserEngagementsService won't be initialized.
17040
+ userEngagementsService) {
16762
17041
  this.appState = appState;
16763
17042
  this.gainsightService = gainsightService;
16764
17043
  this.cookieBannerService = cookieBannerService;
16765
- this.userPreferencesService = userPreferencesService;
17044
+ this.userEngagementsService = userEngagementsService;
17045
+ /**
17046
+ * Check if the Gainsight tracking is disabled in the application apptions. If so, exit early without processing further.
17047
+ */
17048
+ if (this.gainsightService.isTrackingDisabled()) {
17049
+ return;
17050
+ }
17051
+ this.toggleUserTrackingObservable();
17052
+ }
17053
+ /**
17054
+ * Observes several factors to determine the state of user tracking and manages the visibility of Gainsight engagements.
17055
+ * It watches for changes in the current tenant, the state of the cookie banner, and user's preferences for Gainsight engagements.
17056
+ *
17057
+ * 1. If the cookie banner is being displayed, it returns without making any changes.
17058
+ * 2. If Gainsight is disabled at the tenant level via custom properties, it returns without making any changes.
17059
+ * 3. If the conditions are met for loading the Gainsight tag, it loads the tag.
17060
+ */
17061
+ toggleUserTrackingObservable() {
16766
17062
  combineLatest([
16767
17063
  this.appState.currentTenant.pipe(filter(Boolean)),
16768
- this.cookieBannerService.isCookieBannerShowed$,
16769
- this.userPreferencesService.observe(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY)
16770
- ]).subscribe(([currentTenant, isCookieBannerShowed, showGainsightEngagements]) => __awaiter(this, void 0, void 0, function* () {
17064
+ this.cookieBannerService.isCookieBannerShowed$
17065
+ ]).subscribe(([currentTenant, isCookieBannerShowed]) => __awaiter(this, void 0, void 0, function* () {
16771
17066
  if (isCookieBannerShowed) {
16772
17067
  return;
16773
17068
  }
16774
17069
  const { customProperties } = currentTenant;
16775
- if (this.gainsightService.shouldLoadGainsightTag(customProperties) &&
16776
- !(yield this.gainsightService.isGainsightPreferenceDisabledInUserPreferences(this.gainsightService.USER_PREFERENCES_GAINSIGHT_KEY))) {
16777
- this.gainsightService.loadTag(currentTenant);
17070
+ if (this.gainsightService.isGainsightDisabledAtTenantCustomProperties(customProperties)) {
17071
+ return;
16778
17072
  }
16779
- /**
16780
- * In case the user preference for Gainsight bot does not exist the default value is set to true and saved in user preferences
16781
- */
16782
- if (showGainsightEngagements === undefined) {
16783
- showGainsightEngagements = true;
16784
- userPreferencesService.set(this.gainsightService.USER_PREFERENCES_GAINSIGHT_ENGAGEMENTS_KEY, showGainsightEngagements);
17073
+ if (this.shouldLoadTag()) {
17074
+ yield this.gainsightService.loadTag(currentTenant, yield this.gainsightService.shouldSendPiiData());
16785
17075
  }
16786
- this.gainsightService.switchGainsightEngagementsVisibility(showGainsightEngagements);
16787
17076
  }));
16788
17077
  }
17078
+ /**
17079
+ * Determines if a tracking tag should be loaded based on cookie preferences.
17080
+ * @returns `true` if user cookie preferences exist, otherwise `false`.
17081
+ */
17082
+ shouldLoadTag() {
17083
+ return !!this.cookieBannerService.getUserCookiePreferences();
17084
+ }
16789
17085
  }
16790
- ProductExperienceModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, deps: [{ token: AppStateService }, { token: GainsightService }, { token: CookieBannerService }, { token: UserPreferencesService }], target: i0.ɵɵFactoryTarget.NgModule });
17086
+ ProductExperienceModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, deps: [{ token: AppStateService }, { token: GainsightService }, { token: CookieBannerService }, { token: UserEngagementsService }], target: i0.ɵɵFactoryTarget.NgModule });
16791
17087
  ProductExperienceModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, declarations: [ProductExperienceDirective], exports: [ProductExperienceDirective] });
16792
- ProductExperienceModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, providers: [GainsightService] });
17088
+ ProductExperienceModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, providers: [GainsightService, UserEngagementsService] });
16793
17089
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ProductExperienceModule, decorators: [{
16794
17090
  type: NgModule,
16795
17091
  args: [{
16796
17092
  declarations: [ProductExperienceDirective],
16797
17093
  exports: [ProductExperienceDirective],
16798
- providers: [GainsightService]
17094
+ providers: [GainsightService, UserEngagementsService]
16799
17095
  }]
16800
- }], ctorParameters: function () { return [{ type: AppStateService }, { type: GainsightService }, { type: CookieBannerService }, { type: UserPreferencesService }]; } });
17096
+ }], ctorParameters: function () { return [{ type: AppStateService }, { type: GainsightService }, { type: CookieBannerService }, { type: UserEngagementsService }]; } });
16801
17097
 
16802
17098
  class SearchComponent {
16803
17099
  constructor(searchService) {
@@ -25901,7 +26197,7 @@ class RangeDisplayComponent {
25901
26197
  if (!this.config.min) {
25902
26198
  this.config.min = 0;
25903
26199
  }
25904
- if (!this.config.max) {
26200
+ if (!this.config.max && this.config.max !== 0) {
25905
26201
  this.config.max = 100;
25906
26202
  }
25907
26203
  if (this.config.fractionSize !== undefined) {
@@ -26022,10 +26318,10 @@ class RangeDisplayComponent {
26022
26318
  }
26023
26319
  }
26024
26320
  RangeDisplayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RangeDisplayComponent, deps: [{ token: i1$5.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
26025
- RangeDisplayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: RangeDisplayComponent, selector: "c8y-range-display", inputs: { config: "config", display: "display" }, host: { properties: { "attr.style": "this.inlineStyle" } }, viewQueries: [{ propertyName: "rangeDisplay", first: true, predicate: ["rangeDisplay"], descendants: true }, { propertyName: "currentRangeElement", first: true, predicate: ["currentRangeElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max || 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.DecimalPipe, name: "number" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] });
26321
+ RangeDisplayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: RangeDisplayComponent, selector: "c8y-range-display", inputs: { config: "config", display: "display" }, host: { properties: { "attr.style": "this.inlineStyle" } }, viewQueries: [{ propertyName: "rangeDisplay", first: true, predicate: ["rangeDisplay"], descendants: true }, { propertyName: "currentRangeElement", first: true, predicate: ["currentRangeElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max ?? 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.DecimalPipe, name: "number" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] });
26026
26322
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RangeDisplayComponent, decorators: [{
26027
26323
  type: Component,
26028
- args: [{ selector: 'c8y-range-display', template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max || 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n" }]
26324
+ args: [{ selector: 'c8y-range-display', template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max ?? 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n" }]
26029
26325
  }], ctorParameters: function () { return [{ type: i1$5.DomSanitizer }]; }, propDecorators: { config: [{
26030
26326
  type: Input
26031
26327
  }], display: [{
@@ -27716,5 +28012,5 @@ class RealtimeMessage {
27716
28012
  * Generated bundle index. Do not edit.
27717
28013
  */
27718
28014
 
27719
- export { ACTIONS, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionModule, ActionOutletComponent, ActionService, AlarmRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherService, ApplicationOptions, ApplicationPluginStatus, AssetTypesModule, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BootstrapComponent, BootstrapModule, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BytesPipe, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yValidators, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangePasswordComponent, ClipboardModule, ClipboardService, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CoreModule, CredentialsComponent, CurrentPasswordModalComponent, CustomColumn, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EventRealtimeService, FilePickerComponent, FilePickerModule, FilesService, FilterInputComponent, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GainsightService, GetGroupIconPipe, GridDataSource, GroupFragment, GroupService, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_ROUTE, HOOK_SEARCH, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, I18nModule$1 as I18nModule, ICONS, ICON_LIST, IconDirective, IfAllowedDirective, InjectionType, InputGroupListComponent, InputGroupListContainerDirective, InventorySearchService, IpRangeInputListComponent, IsControlVisiblePipe, JsonValidationPrettifierDirective, LANGUAGES, LOCALE_PATH, LegacyGridConfigMapperService, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, LoginComponent, LoginModule, LoginService, LoginViews, MAX_PAGE_SIZE, MESSAGES, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NUMBER_FORMAT_REGEXP, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthValidatorDirective, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, ProvidePhoneNumberComponent, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QuickLinkComponent, QuickLinkModule, RESOLVING_COMPONENT_WAIT_TIME, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RecoverPasswordComponent, RequiredInputPlaceholderDirective, RightDrawerComponent, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SearchComponent, SearchFilters, SearchInputComponent, SearchModule, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent$1 as SelectComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SendStatus, SendStatusLabels, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SkipLinkDirective, SmsChallengeComponent, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StrengthValidatorService, StringifyObjectPipe, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, TitleComponent, TitleOutletComponent, TotpAuthComponent, TotpChallengeComponent, TotpSetupComponent, TranslateCustomLoader, TranslateParserCustom, TranslateService, TypeaheadComponent, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionDetailsModalComponent, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, WebSDKVersionFactory, WidgetTimeContextComponent, WidgetsDashboardComponent, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _, _virtualScrollWindowStrategyFactory, allEntriesAreEqual, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getInjectedHooks, gettext, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookDocs, hookDynamicProviderConfig, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookRoute, hookSearch, hookStepper, hookTab, hookVersion, hookWizard, initializeServices, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, ratiosByColumnTypes, resolveInjectedFactories, retryWithDelay, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, translateLoaderFactory, trimTranslationKey, uniqueInCollectionByPathValidator };
28015
+ export { ACTIONS, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionModule, ActionOutletComponent, ActionService, AlarmRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherService, ApplicationOptions, ApplicationPluginStatus, AssetTypesModule, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BootstrapComponent, BootstrapModule, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BytesPipe, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yValidators, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangePasswordComponent, ClipboardModule, ClipboardService, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CoreModule, CredentialsComponent, CurrentPasswordModalComponent, CustomColumn, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EventRealtimeService, FilePickerComponent, FilePickerModule, FilesService, FilterInputComponent, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GainsightService, GetGroupIconPipe, GridDataSource, GroupFragment, GroupService, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_ROUTE, HOOK_SEARCH, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, I18nModule$1 as I18nModule, ICONS, ICON_LIST, IconDirective, IfAllowedDirective, InjectionType, InputGroupListComponent, InputGroupListContainerDirective, InventorySearchService, IpRangeInputListComponent, IsControlVisiblePipe, JsonValidationPrettifierDirective, LANGUAGES, LOCALE_PATH, LegacyGridConfigMapperService, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, LoginComponent, LoginModule, LoginService, LoginViews, MAX_PAGE_SIZE, MESSAGES, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NUMBER_FORMAT_REGEXP, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthValidatorDirective, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, ProvidePhoneNumberComponent, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QuickLinkComponent, QuickLinkModule, RESOLVING_COMPONENT_WAIT_TIME, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RecoverPasswordComponent, RequiredInputPlaceholderDirective, RightDrawerComponent, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SearchComponent, SearchFilters, SearchInputComponent, SearchModule, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent$1 as SelectComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SendStatus, SendStatusLabels, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SkipLinkDirective, SmsChallengeComponent, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StrengthValidatorService, StringifyObjectPipe, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, TitleComponent, TitleOutletComponent, TotpAuthComponent, TotpChallengeComponent, TotpSetupComponent, TranslateCustomLoader, TranslateParserCustom, TranslateService, TypeaheadComponent, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserEngagementsService, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionDetailsModalComponent, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, WebSDKVersionFactory, WidgetTimeContextComponent, WidgetsDashboardComponent, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _, _virtualScrollWindowStrategyFactory, allEntriesAreEqual, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getInjectedHooks, gettext, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookDocs, hookDynamicProviderConfig, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookRoute, hookSearch, hookStepper, hookTab, hookVersion, hookWizard, initializeServices, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, ratiosByColumnTypes, resolveInjectedFactories, retryWithDelay, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, translateLoaderFactory, trimTranslationKey, uniqueInCollectionByPathValidator };
27720
28016
  //# sourceMappingURL=c8y-ngx-components.mjs.map