Skip to content
Snippets Groups Projects
Select Git revision
  • ecf41425e8f761127795b1a57afe7124d93c8daf
  • master default protected
  • add-frequency-to-form
  • dev protected
  • ckan-2.11.0
  • add-package-custom-fields
  • fix-adding-datasets-for-users-and-editors
  • add-auth-subroute
  • 71-migrate-custom-fields-to-ckanext-scheming
  • add-author-maintainer-information
  • fix-inline-flex-btns
  • fix-known-spatial-uri-validation
  • py3
  • 47-aktuelle-resource-einer-collection-wird-nicht-mehr-gefunden
  • 10-eingabe-der-dct-accrualperiodicity-in-weboberflache
  • v1.3
  • 2.5.3
  • 2.5.2
  • 2.5.1
  • 2.5.0
  • 2.4.7
  • 2.4.6
  • 2.4.5
  • 2.4.4
  • 2.4.3
  • 2.4.2
  • 2.4.1
  • 2.4.0
  • 2.3.1
  • 2.3.0
  • 2.2.0
  • 2.1.0
  • 2.0.0
  • 1.4.3
  • 1.4.2
  • 1.4.1
36 results

test_env.py

Blame
  • resource.service.ts 6.08 KiB
    import {
      BehaviorSubject,
      Observable,
      catchError,
      combineLatest,
      filter,
      map,
      mergeMap,
      of,
      startWith,
      tap,
      throwError,
    } from 'rxjs';
    import { ResourceServiceConfig } from './resource.model';
    import {
      StateResource,
      createEmptyStateResource,
      createErrorStateResource,
      createStateResource,
      isLoadingRequired,
      throwErrorOn,
    } from './resource.util';
    import { Resource, getUrl, hasLink } from '@ngxp/rest';
    import { ResourceRepository } from './resource.repository';
    import { isEqual, isNull } from 'lodash-es';
    import { isNotNull } from '../tech.util';
    import { HttpErrorResponse } from '@angular/common/http';
    import { isUnprocessableEntity } from '../http.util';
    import { HttpError, ProblemDetail } from '../tech.model';
    import { isDevMode } from '@angular/core';
    
    /**
     * B = Type of baseresource
     * T = Type of the resource which is working on
     */
    export class ResourceService<B extends Resource, T extends Resource> {
      readonly stateResource: BehaviorSubject<StateResource<T>> = new BehaviorSubject(
        createEmptyStateResource(),
      );
    
      configResource: B;
    
      constructor(
        private config: ResourceServiceConfig<B>,
        private repository: ResourceRepository,
      ) {}
    
      public get(): Observable<StateResource<T>> {
        return combineLatest([this.stateResource.asObservable(), this.getConfigResource()]).pipe(
          tap(([, configResource]) => this.handleConfigResourceChanged(configResource)),
          tap(([, configResource]) => this.handleNullConfigResource(configResource)),
          tap(([stateResource, configResource]) =>
            this.handleConfigResource(stateResource, configResource),
          ),
          filter(([stateResource]) => !this.shouldFilter(stateResource)),
          map(([stateResource]) => stateResource),
          startWith(createEmptyStateResource<T>(true)),
        );
      }
    
      private getConfigResource(): Observable<B> {
        return this.config.resource.pipe(
          filter((stateResource) => stateResource.loaded && !stateResource.loading),
          map((stateResource) => stateResource.resource),
        );
      }
    
      handleConfigResourceChanged(configResource: B): void {
        if (!isEqual(this.configResource, configResource)) {
          this.configResource = configResource;
          this.stateResource.next({ ...this.stateResource.value, reload: true });
        }
      }
    
      handleNullConfigResource(configResource: B): void {
        if (this.shouldClearStateResource(configResource)) {
          this.stateResource.next(createEmptyStateResource());
        }
      }
    
      shouldClearStateResource(configResource: B): boolean {
        return isNull(configResource) && !isEqual(this.stateResource.value, createEmptyStateResource());
      }
    
      handleConfigResource(stateResource: StateResource<T>, configResource: B): void {
        if (this.shouldLoadResource(stateResource, configResource)) {
          this.loadResource(configResource);
        }
      }
    
      shouldLoadResource(stateResource: StateResource<T>, configResource: B): boolean {
        return isNotNull(configResource) && isLoadingRequired(stateResource);
      }
    
      loadResource(configResource: B): void {
        this.verifyGetLink(configResource);
        this.setStateResourceLoading();
        this.doLoadResource(configResource);
      }
    
      handleError(errorResponse: HttpErrorResponse): Observable<StateResource<HttpError>> {
        if (isUnprocessableEntity(errorResponse.status)) {
          return of(createErrorStateResource((<any>errorResponse) as ProblemDetail));
        }
        return throwError(() => errorResponse);
      }
    
      private verifyGetLink(configResource: B): void {
        throwErrorOn(
          !hasLink(configResource, this.config.getLinkRel),
          'No get link exists on configresource.',
        );
      }
    
      setStateResourceLoading(): void {
        this.stateResource.next({ ...createEmptyStateResource(true), reload: false });
      }
    
      doLoadResource(configResource: B): void {
        this.repository
          .getResource(getUrl(configResource, this.config.getLinkRel))
          .pipe()
          .subscribe((loadedResource: T) => this.updateStateResource(loadedResource));
      }
    
      updateStateResource(resource: T): void {
        this.stateResource.next(createStateResource(resource));
      }
    
      shouldFilter(stateResource: StateResource<Resource>): boolean {
        return (
          stateResource.reload || this.isInvalidResourceCombination(stateResource, this.configResource)
        );
      }
    
      isInvalidResourceCombination(
        stateResource: StateResource<Resource>,
        baseResource: Resource,
      ): boolean {
        return (
          !stateResource.loading &&
          ((!stateResource.loaded && isNotNull(baseResource)) ||
            (stateResource.loaded && isNull(baseResource)))
        );
      }
    
      public save(toSave: unknown): Observable<StateResource<T | HttpError>> {
        this.verifyEditLinkRel();
        return this.stateResource.asObservable().pipe(
          mergeMap((selectedResource: StateResource<T>) =>
            this.doSave(selectedResource.resource, toSave),
          ),
          map((loadedResource: T) => createStateResource(loadedResource)),
          catchError((errorResponse: HttpErrorResponse) => this.handleError(errorResponse)),
        );
      }
    
      private verifyEditLinkRel(): void {
        throwErrorOn(
          !this.hasLinkRel(this.config.editLinkRel),
          'No edit link exists on current stateresource.',
        );
      }
    
      private doSave(resource: T, toSave: unknown): Observable<T> {
        return <Observable<T>>this.repository.save({
          resource,
          linkRel: this.config.editLinkRel,
          toSave,
        });
      }
    
      public refresh(): void {
        this.stateResource.next({ ...this.stateResource.value, reload: true });
      }
    
      public canEdit(): boolean {
        return this.hasLinkRel(this.config.editLinkRel);
      }
    
      public canDelete(): boolean {
        return this.hasLinkRel(this.config.deleteLinkRel);
      }
    
      private hasLinkRel(linkRel: string): boolean {
        return hasLink(this.getStateResource(), linkRel);
      }
    
      private getStateResource(): T {
        return this.stateResource.value.resource;
      }
    
      public delete(): Observable<Resource> {
        this.verifyDeleteLinkRel();
        return this.repository.delete(this.getStateResource(), this.config.deleteLinkRel);
      }
    
      private verifyDeleteLinkRel(): void {
        throwErrorOn(
          !this.hasLinkRel(this.config.deleteLinkRel),
          'No delete link exists on current stateresource.',
        );
      }
    }