File

projects/core/src/anonymous-consents/facade/anonymous-consents.service.ts

Index

Methods

Constructor

constructor(store: Store, authService: AuthService)
Parameters :
Name Type Optional
store Store<StateWithAnonymousConsents> No
authService AuthService No

Methods

Private checkConsentVersions
checkConsentVersions()

Dispatches an action to trigger the check whether the anonymous consent version have been updated

Returns : void
consentsUpdated
consentsUpdated(newConsents: AnonymousConsent[], previousConsents: AnonymousConsent[])

Compares the given newConsents and previousConsents and returns true if there are differences (the newConsents are updates). Otherwise it returns false.

Parameters :
Name Type Optional Description
newConsents AnonymousConsent[] No

new consents to compare

previousConsents AnonymousConsent[] No

old consents to compare

Returns : boolean
decodeAndDeserialize
decodeAndDeserialize(rawConsents: string)

Decodes using decodeURIComponent() and deserializes using JSON.parse()

Parameters :
Name Type Optional Description
rawConsents string No

to decode an deserialize

Returns : AnonymousConsent[]
detectUpdatedTemplates
detectUpdatedTemplates(currentTemplates: ConsentTemplate[], newTemplates: ConsentTemplate[])

Returns true if there's a mismatch in template versions between the provided currentTemplates and newTemplates

Parameters :
Name Type Optional Description
currentTemplates ConsentTemplate[] No

current templates to check

newTemplates ConsentTemplate[] No

new templates to check

Returns : boolean
getConsent
getConsent(templateId: string)

Returns the anonymous consent for the given template ID.

As a side-effect, the method will call getTemplates(true) to load the templates if those are not present.

Parameters :
Name Type Optional Description
templateId string No

a template ID by which to filter anonymous consent templates.

Returns : Observable<AnonymousConsent>
getConsents
getConsents()

Returns all the anonymous consents.

Returns : Observable<AnonymousConsent[]>
getLoadTemplatesError
getLoadTemplatesError()

Returns an indicator for the error status for the anonymous consent templates.

Returns : Observable<boolean>
getLoadTemplatesLoading
getLoadTemplatesLoading()

Returns an indicator for the loading status for the anonymous consent templates.

Returns : Observable<boolean>
getLoadTemplatesSuccess
getLoadTemplatesSuccess()

Returns an indicator for the success status for the anonymous consent templates.

Returns : Observable<boolean>
getTemplate
getTemplate(templateCode: string)

Returns the anonymous consent templates with the given template code.

Parameters :
Name Type Optional Description
templateCode string No

a template code by which to filter anonymous consent templates.

Returns : Observable<ConsentTemplate>
getTemplates
getTemplates(loadIfMissing)

Conditionally triggers the load of the anonymous consent templates if:

  • loadIfMissing parameter is set to true
  • the templates in the store are undefined

Otherwise it just returns the value from the store.

Parameters :
Name Optional Default value Description
loadIfMissing No false

setting to true will trigger the load of the templates if the currently stored templates are undefined

Returns : Observable<ConsentTemplate[]>
getTemplatesUpdated
getTemplatesUpdated()

Returns true if the consent templates were updated on the back-end. If the templates are not present in the store, it triggers the load.

Returns : Observable<boolean>
giveAllConsents
giveAllConsents()

Sets all the anonymous consents' state to given.

Returns : Observable<ConsentTemplate[]>
giveConsent
giveConsent(templateCode: string)

Give a consent for the given templateCode

Parameters :
Name Type Optional Description
templateCode string No

for which to give the consent

Returns : void
isBannerDismissed
isBannerDismissed()

Returns true if the banner was dismissed, false otherwise.

Returns : Observable<boolean>
isBannerVisible
isBannerVisible()

Returns true if either the banner is not dismissed or if the templates were updated on the back-end. Otherwise, it returns false.

Returns : Observable<boolean>
isConsentGiven
isConsentGiven(consent: AnonymousConsent)

Returns true if the provided consent is given.

Parameters :
Name Type Optional Description
consent AnonymousConsent No

a consent to test

Returns : boolean
isConsentWithdrawn
isConsentWithdrawn(consent: AnonymousConsent)

Returns true if the provided consent is withdrawn.

Parameters :
Name Type Optional Description
consent AnonymousConsent No

a consent to test

Returns : boolean
loadTemplates
loadTemplates()

Retrieves the anonymous consent templates.

Returns : void
resetLoadTemplatesState
resetLoadTemplatesState()

Resets the loading, success and error indicators for the anonymous consent templates.

Returns : void
serializeAndEncode
serializeAndEncode(consents: AnonymousConsent[])

Serializes using JSON.stringify() and encodes using encodeURIComponent() methods

Parameters :
Name Type Optional Description
consents AnonymousConsent[] No

to serialize and encode

Returns : string
setConsents
setConsents(consents: AnonymousConsent[])

Puts the provided anonymous consents into the store.

Parameters :
Name Type Optional
consents AnonymousConsent[] No
Returns : void
toggleBannerDismissed
toggleBannerDismissed(dismissed: boolean)

Toggles the dismissed state of the anonymous consents banner.

Parameters :
Name Type Optional Description
dismissed boolean No

the banner will be dismissed if true is passed, otherwise it will be visible.

Returns : void
toggleTemplatesUpdated
toggleTemplatesUpdated(updated: boolean)

Toggles the updated slice of the state

Parameters :
Name Type Optional
updated boolean No
Returns : void
withdrawAllConsents
withdrawAllConsents()

Sets all the anonymous consents' state to withdrawn.

Returns : Observable<ConsentTemplate[]>
withdrawConsent
withdrawConsent(templateCode: string)

Withdraw a consent for the given templateCode

Parameters :
Name Type Optional Description
templateCode string No

for which to withdraw the consent

Returns : void
import { Injectable } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { combineLatest, iif, Observable } from 'rxjs';
import { filter, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { AuthService } from '../../auth/user-auth/facade/auth.service';
import {
  AnonymousConsent,
  ANONYMOUS_CONSENT_STATUS,
  ConsentTemplate,
} from '../../model/index';
import { AnonymousConsentsActions } from '../store/actions/index';
import { StateWithAnonymousConsents } from '../store/anonymous-consents-state';
import { AnonymousConsentsSelectors } from '../store/selectors/index';

@Injectable({ providedIn: 'root' })
export class AnonymousConsentsService {
  constructor(
    protected store: Store<StateWithAnonymousConsents>,
    protected authService: AuthService
  ) {}

  /**
   * Retrieves the anonymous consent templates.
   */
  loadTemplates(): void {
    this.store.dispatch(
      new AnonymousConsentsActions.LoadAnonymousConsentTemplates()
    );
  }

  /**
   * Conditionally triggers the load of the anonymous consent templates if:
   *   - `loadIfMissing` parameter is set to `true`
   *   - the `templates` in the store are `undefined`
   *
   * Otherwise it just returns the value from the store.
   *
   * @param loadIfMissing setting to `true` will trigger the load of the templates if the currently stored templates are `undefined`
   */
  getTemplates(loadIfMissing = false): Observable<ConsentTemplate[]> {
    return iif(
      () => loadIfMissing,
      this.store.pipe(
        select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesValue),
        withLatestFrom(this.getLoadTemplatesLoading()),
        filter(([_templates, loading]) => !loading),
        tap(([templates, _loading]) => {
          if (!Boolean(templates)) {
            this.loadTemplates();
          }
        }),
        filter(([templates, _loading]) => Boolean(templates)),
        map(([templates, _loading]) => templates)
      ),
      this.store.pipe(
        select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesValue)
      )
    );
  }

  /**
   * Returns the anonymous consent templates with the given template code.
   * @param templateCode a template code by which to filter anonymous consent templates.
   */
  getTemplate(templateCode: string): Observable<ConsentTemplate> {
    return this.store.pipe(
      select(
        AnonymousConsentsSelectors.getAnonymousConsentTemplate(templateCode)
      )
    );
  }

  /**
   * Returns an indicator for the loading status for the anonymous consent templates.
   */
  getLoadTemplatesLoading(): Observable<boolean> {
    return this.store.pipe(
      select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesLoading)
    );
  }

  /**
   * Returns an indicator for the success status for the anonymous consent templates.
   */
  getLoadTemplatesSuccess(): Observable<boolean> {
    return this.store.pipe(
      select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesSuccess)
    );
  }

  /**
   * Returns an indicator for the error status for the anonymous consent templates.
   */
  getLoadTemplatesError(): Observable<boolean> {
    return this.store.pipe(
      select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesError)
    );
  }

  /**
   * Resets the loading, success and error indicators for the anonymous consent templates.
   */
  resetLoadTemplatesState(): void {
    this.store.dispatch(
      new AnonymousConsentsActions.ResetLoadAnonymousConsentTemplates()
    );
  }

  /**
   * Returns all the anonymous consents.
   */
  getConsents(): Observable<AnonymousConsent[]> {
    return this.store.pipe(
      select(AnonymousConsentsSelectors.getAnonymousConsents)
    );
  }

  /**
   * Puts the provided anonymous consents into the store.
   */
  setConsents(consents: AnonymousConsent[]): void {
    return this.store.dispatch(
      new AnonymousConsentsActions.SetAnonymousConsents(consents)
    );
  }

  /**
   * Returns the anonymous consent for the given template ID.
   *
   * As a side-effect, the method will call `getTemplates(true)` to load the templates if those are not present.
   *
   * @param templateId a template ID by which to filter anonymous consent templates.
   */
  getConsent(templateId: string): Observable<AnonymousConsent> {
    return this.authService.isUserLoggedIn().pipe(
      filter((authenticated) => !authenticated),
      tap(() => this.getTemplates(true)),
      switchMap(() =>
        this.store.pipe(
          select(
            AnonymousConsentsSelectors.getAnonymousConsentByTemplateCode(
              templateId
            )
          )
        )
      )
    );
  }

  /**
   * Give a consent for the given `templateCode`
   * @param templateCode for which to give the consent
   */
  giveConsent(templateCode: string): void {
    this.store.dispatch(
      new AnonymousConsentsActions.GiveAnonymousConsent(templateCode)
    );
  }

  /**
   * Sets all the anonymous consents' state to given.
   */
  giveAllConsents(): Observable<ConsentTemplate[]> {
    return this.getTemplates(true).pipe(
      tap((templates) =>
        templates.forEach((template) => this.giveConsent(template.id))
      )
    );
  }

  /**
   * Returns `true` if the provided `consent` is given.
   * @param consent a consent to test
   */
  isConsentGiven(consent: AnonymousConsent): boolean {
    return consent && consent.consentState === ANONYMOUS_CONSENT_STATUS.GIVEN;
  }

  /**
   * Withdraw a consent for the given `templateCode`
   * @param templateCode for which to withdraw the consent
   */
  withdrawConsent(templateCode: string): void {
    this.store.dispatch(
      new AnonymousConsentsActions.WithdrawAnonymousConsent(templateCode)
    );
  }

  /**
   * Sets all the anonymous consents' state to withdrawn.
   */
  withdrawAllConsents(): Observable<ConsentTemplate[]> {
    return this.getTemplates(true).pipe(
      tap((templates) =>
        templates.forEach((template) => this.withdrawConsent(template.id))
      )
    );
  }

  /**
   * Returns `true` if the provided `consent` is withdrawn.
   * @param consent a consent to test
   */
  isConsentWithdrawn(consent: AnonymousConsent): boolean {
    return (
      consent && consent.consentState === ANONYMOUS_CONSENT_STATUS.WITHDRAWN
    );
  }

  /**
   * Toggles the dismissed state of the anonymous consents banner.
   * @param dismissed the banner will be dismissed if `true` is passed, otherwise it will be visible.
   */
  toggleBannerDismissed(dismissed: boolean): void {
    this.store.dispatch(
      new AnonymousConsentsActions.ToggleAnonymousConsentsBannerDissmissed(
        dismissed
      )
    );
    if (dismissed) {
      this.toggleTemplatesUpdated(false);
    }
  }

  /**
   * Returns `true` if the banner was dismissed, `false` otherwise.
   */
  isBannerDismissed(): Observable<boolean> {
    return this.store.pipe(
      select(AnonymousConsentsSelectors.getAnonymousConsentsBannerDismissed)
    );
  }

  /**
   * Returns `true` if the consent templates were updated on the back-end.
   * If the templates are not present in the store, it triggers the load.
   */
  getTemplatesUpdated(): Observable<boolean> {
    return this.getTemplates(true).pipe(
      switchMap(() =>
        this.store.pipe(
          select(AnonymousConsentsSelectors.getAnonymousConsentTemplatesUpdate)
        )
      )
    );
  }

  /**
   * Toggles the `updated` slice of the state
   * @param updated
   */
  toggleTemplatesUpdated(updated: boolean): void {
    this.store.dispatch(
      new AnonymousConsentsActions.ToggleAnonymousConsentTemplatesUpdated(
        updated
      )
    );
  }

  /**
   * Returns `true` if either the banner is not dismissed or if the templates were updated on the back-end.
   * Otherwise, it returns `false`.
   */
  isBannerVisible(): Observable<boolean> {
    return combineLatest([
      this.isBannerDismissed(),
      this.getTemplatesUpdated(),
    ]).pipe(
      tap(() => this.checkConsentVersions()),
      map(([dismissed, updated]) => !dismissed || updated)
    );
  }

  /**
   * Dispatches an action to trigger the check
   * whether the anonymous consent version have been updated
   */
  private checkConsentVersions(): void {
    this.store.dispatch(
      new AnonymousConsentsActions.AnonymousConsentCheckUpdatedVersions()
    );
  }

  /**
   * Returns `true` if there's a mismatch in template versions between the provided `currentTemplates` and `newTemplates`
   * @param currentTemplates current templates to check
   * @param newTemplates new templates to check
   */
  detectUpdatedTemplates(
    currentTemplates: ConsentTemplate[],
    newTemplates: ConsentTemplate[]
  ): boolean {
    if (newTemplates.length !== currentTemplates.length) {
      return true;
    }

    for (let i = 0; i < newTemplates.length; i++) {
      const newTemplate = newTemplates[i];
      const currentTemplate = currentTemplates[i];
      if (newTemplate.version !== currentTemplate.version) {
        return true;
      }
    }

    return false;
  }

  /**
   * Serializes using `JSON.stringify()` and encodes using `encodeURIComponent()` methods
   * @param consents to serialize and encode
   */
  serializeAndEncode(consents: AnonymousConsent[]): string {
    if (!consents) {
      return '';
    }
    const serialized = JSON.stringify(consents);
    const encoded = encodeURIComponent(serialized);
    return encoded;
  }

  /**
   * Decodes using `decodeURIComponent()` and deserializes using `JSON.parse()`
   * @param rawConsents to decode an deserialize
   */
  decodeAndDeserialize(rawConsents: string): AnonymousConsent[] {
    const decoded = decodeURIComponent(rawConsents);
    const unserialized = JSON.parse(decoded) as AnonymousConsent[];
    return unserialized;
  }

  /**
   *
   * Compares the given `newConsents` and `previousConsents` and returns `true` if there are differences (the `newConsents` are updates).
   * Otherwise it returns `false`.
   *
   * @param newConsents new consents to compare
   * @param previousConsents old consents to compare
   */
  consentsUpdated(
    newConsents: AnonymousConsent[],
    previousConsents: AnonymousConsent[]
  ): boolean {
    const newRawConsents = this.serializeAndEncode(newConsents);
    const previousRawConsents = this.serializeAndEncode(previousConsents);
    return newRawConsents !== previousRawConsents;
  }
}

result-matching ""

    No results matching ""