{"version":3,"file":"myrmidon-cadmus-api.mjs","names":[],"sources":["../../../../projects/myrmidon/cadmus-api/src/lib/services/editor-guard.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/editor-settings.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/facet.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/flag.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/graph.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/item-browser.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/item.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/messaging.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/operator-guard.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/preview.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/stats.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/thesaurus.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/upload.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/user-level.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/services/user.service.ts","../../../../projects/myrmidon/cadmus-api/src/lib/guards/editor-guard.ts","../../../../projects/myrmidon/cadmus-api/src/lib/guards/operator-guard.ts"],"sourcesContent":["// https://angular.io/docs/ts/latest/guide/router.html\r\nimport { Injectable } from '@angular/core';\r\nimport {\r\n  Router,\r\n  ActivatedRouteSnapshot,\r\n  RouterStateSnapshot,\r\n} from '@angular/router';\r\nimport { AuthJwtService } from '@myrmidon/auth-jwt-login';\r\n\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class EditorGuardService {\r\n  constructor(private _router: Router, private _authService: AuthJwtService) {}\r\n\r\n  private redirectToLogin(url: string): void {\r\n    this._router.navigate(['/login'], {\r\n      queryParams: {\r\n        returnUrl: url,\r\n      },\r\n    });\r\n  }\r\n\r\n  canActivate(\r\n    route: ActivatedRouteSnapshot,\r\n    state: RouterStateSnapshot\r\n  ): boolean {\r\n    // if not authenticated, redirect to login\r\n    if (!this._authService.isAuthenticated(false)) {\r\n      this.redirectToLogin(state.url);\r\n      return false;\r\n    }\r\n    // if authenticated but not verified, redirect to login\r\n    if (!this._authService.currentUserValue?.emailConfirmed) {\r\n      this._router.navigate(['/login']);\r\n      console.warn('User not verified');\r\n      return false;\r\n    }\r\n    // else activate only if admin/editor\r\n    const user = this._authService.currentUserValue;\r\n    const ok = user && user.roles.some((r) => r === 'admin' || r === 'editor');\r\n    if (!ok) {\r\n      console.warn('Unauthorized user');\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n}\r\n","import { HttpClient } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\n\r\nimport { ErrorService, EnvService } from '@myrmidon/ngx-tools';\r\nimport { catchError, Observable, retry } from 'rxjs';\r\n\r\n/**\r\n * Editor settings service. These settings are stored server-side.\r\n */\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class EditorSettingsService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n  ) {}\r\n\r\n  /**\r\n   * Get the setting with the specified ID. If the setting is not found,\r\n   * an empty object is returned.\r\n   * @param id The setting's ID.\r\n   */\r\n  public getSetting<T>(id: string): Observable<T> {\r\n    return this._http\r\n      .get<T>(`${this._env.get('apiUrl')}settings/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the setting with the specified ID.\r\n   * @param id The setting's ID.\r\n   * @param setting The setting object to add.\r\n   */\r\n  public addSetting<T>(id: string, setting: T): Observable<T> {\r\n    return this._http\r\n      .post<T>(`${this._env.get('apiUrl')}settings/${id}`, setting)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the setting with the specified ID.\r\n   * @param id The setting's ID.\r\n   */\r\n  public deleteSetting(id: string): Observable<any> {\r\n    return this._http\r\n      .delete<any>(`${this._env.get('apiUrl')}settings/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\n\r\nimport { Observable, of } from 'rxjs';\r\nimport { catchError, map, retry, switchMap } from 'rxjs/operators';\r\n\r\nimport { FacetDefinition, PartDefinition } from '@myrmidon/cadmus-core';\r\nimport { EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\n\r\nimport { EditorSettingsService } from './editor-settings.service';\r\n\r\n/**\r\n * An entry in the facet model settings. The key is the part or fragment\r\n * type ID, and the value is metadata about whether the part is a base text\r\n * part (applicable to parts only) and the list of thesauri IDs to use\r\n * for the part or fragment. Required thesauri are prefixed by an asterisk.\r\n */\r\nexport interface FacetModelSettingsEntry {\r\n  [key: string]: {\r\n    baseText?: boolean;\r\n    thesauriIds?: string[];\r\n  };\r\n}\r\n\r\n/**\r\n * The facet model settings, which is a map of part and fragment type IDs to\r\n * their metadata for the purpose of facet editing.\r\n */\r\nexport interface FacetModelSettings {\r\n  parts: FacetModelSettingsEntry;\r\n  fragments?: FacetModelSettingsEntry;\r\n}\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FacetService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n    private _settings: EditorSettingsService,\r\n  ) {}\r\n\r\n  /**\r\n   * Get a list of facets.\r\n   * @returns Observable with facets array.\r\n   */\r\n  public getFacets(): Observable<FacetDefinition[]> {\r\n    return this._http\r\n      .get<FacetDefinition[]>(`${this._env.get('apiUrl')}facets`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the facet with the specified ID.\r\n   *\r\n   * @param id The facet's ID.\r\n   */\r\n  public getFacet(id: string): Observable<FacetDefinition> {\r\n    return this._http\r\n      .get<FacetDefinition>(`${this._env.get('apiUrl')}facets/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the facet assigned to the item with the specified ID.\r\n   *\r\n   * @param id The item's ID.\r\n   */\r\n  public getFacetFromItemId(id: string): Observable<FacetDefinition> {\r\n    return this._http\r\n      .get<FacetDefinition>(`${this._env.get('apiUrl')}facets/items/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get a list of all the parts defined in the specified facet.\r\n   *\r\n   * @param id The facet ID.\r\n   * @param idIsItem True if the received ID refers to an item's ID rather\r\n   * than to the facet ID. In this case, the item's facet will be retrieved\r\n   * first, and then used to get the requested result.\r\n   * @param noRoles True to ignore the roles when collecting parts from\r\n   *  facets. In this case, you will get just 1 part for each part type.\r\n   * @returns Observable with part definitions array.\r\n   */\r\n  public getFacetParts(\r\n    id: string,\r\n    idIsItem: boolean,\r\n    noRoles = false,\r\n  ): Observable<PartDefinition[]> {\r\n    let url = idIsItem\r\n      ? this._env.get('apiUrl')! + `item-facets/${id}/parts`\r\n      : this._env.get('apiUrl')! + `facets/${id}/parts`;\r\n    if (noRoles) {\r\n      url += '?noRoles=true';\r\n    }\r\n\r\n    return this._http\r\n      .get<PartDefinition[]>(url)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the text layer part type ID if any.\r\n   * @returns Observable of an object with property typeId=result or null.\r\n   */\r\n  public getTextLayerPartTypeId(): Observable<{ typeId: string }> {\r\n    return this._http\r\n      .get<{ typeId: string }>(`${this._env.get('apiUrl')}facets/layer-type-id`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the color of the part with the specified type and role IDs, inside\r\n   * the specified facet (if any).\r\n   *\r\n   * @param typeId The part's type ID.\r\n   * @param roleId The part's optional role ID.\r\n   * @param facet The facet definition including the part being requested.\r\n   */\r\n  public getPartColor(\r\n    typeId: string,\r\n    roleId: string | undefined,\r\n    facet: FacetDefinition | undefined,\r\n  ): string {\r\n    let def: PartDefinition | undefined;\r\n    if (facet) {\r\n      def = facet.partDefinitions.find((d) => {\r\n        return d.typeId === typeId && (!roleId || roleId === d.roleId);\r\n      });\r\n      if (!def) {\r\n        def = facet.partDefinitions.find((d) => {\r\n          return d.typeId === typeId;\r\n        });\r\n      }\r\n    }\r\n    return def ? '#' + def.colorKey : '#f0f0f0';\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified facet.\r\n   * @param facet The facet to add or update.\r\n   */\r\n  public addFacet(facet: FacetDefinition): Observable<FacetDefinition> {\r\n    return this._http\r\n      .post<FacetDefinition>(`${this._env.get('apiUrl')}facets`, facet)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the facet with the specified ID.\r\n   * @param id The facet ID.\r\n   */\r\n  public deleteFacet(id: string): Observable<void> {\r\n    return this._http\r\n      .delete<void>(`${this._env.get('apiUrl')}facets/${id}`)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Build a baseline FacetModelSettings from the facet definitions alone,\r\n   * without any server-side settings. This is used as a fallback when no\r\n   * \"models\" setting is stored on the server.\r\n   *\r\n   * For each unique typeId found across all facets' part definitions:\r\n   * - an entry is added to `parts`, keyed by typeId;\r\n   * - if any part with that typeId has a roleId starting with \"fr.\", the part\r\n   *   entry gets `baseText: true`, and the roleId is also added to `fragments`.\r\n   * No `thesauriIds` are included because that information cannot be derived\r\n   * from FacetDefinition alone.\r\n   */\r\n  private buildDefaultSettings(facets: FacetDefinition[]): FacetModelSettings {\r\n    const parts: FacetModelSettingsEntry = {};\r\n    const fragments: FacetModelSettingsEntry = {};\r\n\r\n    for (const facet of facets) {\r\n      for (const pd of facet.partDefinitions) {\r\n        const { typeId, roleId } = pd;\r\n        if (roleId?.startsWith('fr.')) {\r\n          // layer host: mark as base-text and register the fragment type\r\n          parts[typeId] = { ...parts[typeId], baseText: true };\r\n          if (!fragments[roleId]) {\r\n            fragments[roleId] = {};\r\n          }\r\n        } else {\r\n          // plain part: register if not yet seen\r\n          if (!parts[typeId]) {\r\n            parts[typeId] = {};\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    const result: FacetModelSettings = { parts };\r\n    if (Object.keys(fragments).length) {\r\n      result.fragments = fragments;\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Merge server-loaded settings on top of the pre-built defaults.\r\n   * Entries present in `loaded` override or extend those in `defaults`;\r\n   * entries only in `defaults` are kept as-is.\r\n   */\r\n  private mergeSettings(\r\n    defaults: FacetModelSettings,\r\n    loaded: FacetModelSettings,\r\n  ): FacetModelSettings {\r\n    const parts: FacetModelSettingsEntry = { ...defaults.parts };\r\n    if (loaded?.parts) {\r\n      for (const key of Object.keys(loaded.parts)) {\r\n        parts[key] = { ...parts[key], ...loaded.parts[key] };\r\n      }\r\n    }\r\n\r\n    const fragments: FacetModelSettingsEntry = {\r\n      ...(defaults.fragments ?? {}),\r\n    };\r\n    if (loaded?.fragments) {\r\n      for (const key of Object.keys(loaded.fragments)) {\r\n        fragments[key] = { ...fragments[key], ...loaded.fragments[key] };\r\n      }\r\n    }\r\n\r\n    return {\r\n      parts,\r\n      ...(Object.keys(fragments).length ? { fragments } : {}),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Get the facet model settings, merging server-stored settings with a\r\n   * baseline derived from the facet definitions.\r\n   *\r\n   * Strategy:\r\n   * 1. Load all facets and build a minimal but valid FacetModelSettings from\r\n   *    their part definitions (see buildDefaultSettings). This guarantees\r\n   *    that every part/fragment known to the profile is represented, even when\r\n   *    the server has no \"models\" setting stored yet.\r\n   * 2. Load the \"models\" setting from the server and deep-merge it on top of\r\n   *    the defaults (server values win). When no setting has been configured\r\n   *    the server returns an empty object, so the merge leaves the defaults\r\n   *    intact. A catchError guards against genuine network failures and also\r\n   *    returns the defaults in that case.\r\n   */\r\n  public getFacetModelSettings(): Observable<FacetModelSettings> {\r\n    return this.getFacets().pipe(\r\n      map((facets) => this.buildDefaultSettings(facets)),\r\n      switchMap((defaults) =>\r\n        this._settings.getSetting<FacetModelSettings>('models').pipe(\r\n          map((loaded) => this.mergeSettings(defaults, loaded)),\r\n          catchError(() => of(defaults)),\r\n        ),\r\n      ),\r\n    );\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { retry, catchError } from 'rxjs/operators';\r\n\r\nimport { FlagDefinition } from '@myrmidon/cadmus-core';\r\nimport { EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FlagService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService\r\n  ) {}\r\n\r\n  public getFlags(): Observable<FlagDefinition[]> {\r\n    return this._http\r\n      .get<FlagDefinition[]>(`${this._env.get('apiUrl')}flags`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  public addFlags(flags: FlagDefinition[]): Observable<void> {\r\n    return this._http\r\n      .post<void>(`${this._env.get('apiUrl')}flags`, flags)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { HttpClient, HttpParams } from '@angular/common/http';\r\nimport { Injectable, Inject, Optional } from '@angular/core';\r\n\r\nimport { Observable } from 'rxjs';\r\nimport { catchError, retry } from 'rxjs/operators';\r\n\r\nimport { DataPage, EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\n\r\nimport { InjectionToken } from '@angular/core';\r\n\r\n// the GRAPH_API_PATH token allows overriding the default API path\r\n// for the graph service, useful for demos or specific configurations.\r\n// If you don't define this token, the service will just fallback\r\n// to the default 'graph' path.\r\nexport const GRAPH_API_PATH = new InjectionToken<string>('GRAPH_API_PATH');\r\n\r\n//#region Models\r\nexport enum NodeSourceType {\r\n  User = 0,\r\n  Item,\r\n  Part,\r\n  Thesaurus,\r\n  Implicit,\r\n}\r\n\r\nexport interface Node {\r\n  id: number;\r\n  isClass?: boolean;\r\n  label: string;\r\n  sourceType: NodeSourceType;\r\n  tag?: string;\r\n  sid?: string;\r\n}\r\n\r\nexport interface UriNode extends Node {\r\n  uri: string;\r\n}\r\n\r\ninterface NodeFilterBase {\r\n  uid?: string;\r\n  isClass?: boolean;\r\n  tag?: string;\r\n  label?: string;\r\n  sourceType?: NodeSourceType;\r\n  sid?: string;\r\n  isSidPrefix?: boolean;\r\n  classIds?: number[];\r\n}\r\n\r\nexport interface NodeFilter extends NodeFilterBase {\r\n  linkedNodeId?: number;\r\n  linkedNodeRole?: 'S' | 'O';\r\n}\r\n\r\nexport interface Triple {\r\n  id: number;\r\n  subjectId: number;\r\n  predicateId: number;\r\n  objectId?: number;\r\n  objectLiteral?: string;\r\n  objectLiteralIx?: string;\r\n  literalType?: string;\r\n  literalLanguage?: string;\r\n  literalNumber?: number;\r\n  sid?: string;\r\n  tag?: string;\r\n}\r\n\r\nexport interface UriTriple extends Triple {\r\n  subjectUri: string;\r\n  predicateUri: string;\r\n  objectUri?: string;\r\n}\r\n\r\nexport interface TripleGroup {\r\n  predicateId: number;\r\n  predicateUri: string;\r\n  count: number;\r\n}\r\n\r\nexport interface LiteralFilter {\r\n  literalPattern?: string;\r\n  literalType?: string;\r\n  literalLanguage?: string;\r\n  minLiteralNumber?: number;\r\n  maxLiteralNumber?: number;\r\n}\r\n\r\nexport interface TripleFilter extends LiteralFilter {\r\n  subjectId?: number;\r\n  predicateIds?: number[];\r\n  notPredicateIds?: number[];\r\n  hasLiteralObject?: boolean;\r\n  objectId?: number;\r\n  sid?: string;\r\n  isSidPrefix?: boolean;\r\n  tag?: string;\r\n}\r\n\r\nexport interface LinkedNodeFilter extends NodeFilterBase {\r\n  /**\r\n   * The other node identifier, which is the subject node\r\n   * ID when isObject is true, otherwise the object node ID.\r\n   */\r\n  otherNodeId: number;\r\n  predicateId: number;\r\n  /**\r\n   * Whether the node to match is the object (true) or\r\n   * the subject (false) of the triple having predicate\r\n   * predicateId.\r\n   */\r\n  isObject?: boolean;\r\n}\r\n\r\nexport interface LinkedLiteralFilter extends LiteralFilter {\r\n  subjectId?: number;\r\n  predicateId?: number;\r\n}\r\n//#endregion\r\n\r\n/**\r\n * Cadmus semantic graph service.\r\n */\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class GraphService {\r\n  private readonly _apiPath: string;\r\n\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n    @Optional() @Inject(GRAPH_API_PATH) apiPath?: string\r\n  ) {\r\n    // use injected path if provided, otherwise fallback to 'graph'\r\n    this._apiPath = apiPath || 'graph';\r\n    console.log(`GraphService API path: ${this._apiPath}`);\r\n  }\r\n\r\n  /**\r\n   * Get the specified page of graph nodes.\r\n   *\r\n   * @param filter The nodes filter.\r\n   * @returns A page of nodes.\r\n   */\r\n  public getNodes(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: NodeFilter\r\n  ): Observable<DataPage<UriNode>> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes`;\r\n\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    if (filter.uid) {\r\n      httpParams = httpParams.set('uid', filter.uid);\r\n    }\r\n    if (filter.isClass !== null && filter.isClass !== undefined) {\r\n      httpParams = httpParams.set('isClass', filter.isClass ? 'true' : 'false');\r\n    }\r\n    if (filter.tag) {\r\n      httpParams = httpParams.set('tag', filter.tag);\r\n    }\r\n    if (filter.label) {\r\n      httpParams = httpParams.set('label', filter.label);\r\n    }\r\n    if (filter.sourceType !== null && filter.sourceType !== undefined) {\r\n      httpParams = httpParams.set('sourceType', filter.sourceType.toString());\r\n    }\r\n    if (filter.sid) {\r\n      httpParams = httpParams.set('sid', filter.sid);\r\n    }\r\n    if (filter.isSidPrefix) {\r\n      httpParams = httpParams.set('isSidPrefix', 'true');\r\n    }\r\n    if (filter.linkedNodeId) {\r\n      httpParams = httpParams.set(\r\n        'linkedNodeId',\r\n        filter.linkedNodeId.toString()\r\n      );\r\n    }\r\n    if (filter.linkedNodeRole) {\r\n      httpParams = httpParams.set('linkedNodeRole', filter.linkedNodeRole);\r\n    }\r\n    if (filter.classIds?.length) {\r\n      for (let i = 0; i < filter.classIds.length; i++) {\r\n        httpParams = httpParams.set('classIds', filter.classIds[i]);\r\n      }\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<UriNode>>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the specified set of nodes.\r\n   *\r\n   * @param ids The nodes IDs.\r\n   * @returns List of nodes/nulls.\r\n   */\r\n  public getNodeSet(ids: number[]): Observable<(UriNode | null)[]> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes-set/`;\r\n    let httpParams = new HttpParams();\r\n    for (let i = 0; i < ids.length; i++) {\r\n      httpParams = httpParams.append('id', ids[i].toString());\r\n    }\r\n\r\n    return this._http\r\n      .get<(UriNode | null)[]>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the node with the specified ID.\r\n   *\r\n   * @param id The node's ID.\r\n   * @returns The node.\r\n   */\r\n  public getNode(id: number): Observable<UriNode> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes/` + id.toString();\r\n    return this._http\r\n      .get<UriNode>(url)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the node with the specified URI.\r\n   *\r\n   * @param uri The node's URI.\r\n   * @returns The node.\r\n   */\r\n  public getNodeByUri(uri: string): Observable<UriNode> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes-by-uri`;\r\n    console.log(`Fetching URL: ${url}`);\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('uri', uri);\r\n\r\n    return this._http\r\n      .get<UriNode>(url, { params: httpParams })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified node. A new node has id=0 and uri set;\r\n   * an existing node has its id.\r\n   *\r\n   * @param node The node to add.\r\n   * @returns The added node.\r\n   */\r\n  public addNode(node: UriNode): Observable<UriNode> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes/`;\r\n    return this._http\r\n      .post<UriNode>(url, node)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the node with the specified ID.\r\n   *\r\n   * @param id The node's ID.\r\n   */\r\n  public deleteNode(id: number): Observable<any> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/nodes/` + id.toString();\r\n    return this._http.delete(url).pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  private applyTripleFilter(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: TripleFilter,\r\n    httpParams: HttpParams\r\n  ): HttpParams {\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    if (filter.subjectId) {\r\n      httpParams = httpParams.set('subjectId', filter.subjectId.toString());\r\n    }\r\n    if (filter.predicateIds?.length) {\r\n      filter.predicateIds!.forEach((p) => {\r\n        httpParams = httpParams.set('predicateIds', p);\r\n      });\r\n    }\r\n    if (filter.notPredicateIds?.length) {\r\n      filter.notPredicateIds!.forEach((p) => {\r\n        httpParams = httpParams.set('notPredicateIds', p);\r\n      });\r\n    }\r\n    if (\r\n      filter.hasLiteralObject !== null &&\r\n      filter.hasLiteralObject !== undefined\r\n    ) {\r\n      httpParams = httpParams.set(\r\n        'hasLiteralObject',\r\n        filter.hasLiteralObject.toString()\r\n      );\r\n    }\r\n    if (filter.objectId) {\r\n      httpParams = httpParams.set('objectId', filter.objectId.toString());\r\n    }\r\n    if (filter.sid) {\r\n      httpParams = httpParams.set('sid', filter.sid);\r\n    }\r\n    if (filter.isSidPrefix) {\r\n      httpParams = httpParams.set('isSidPrefix', 'true');\r\n    }\r\n    if (filter.tag) {\r\n      httpParams = httpParams.set('tag', filter.tag);\r\n    }\r\n\r\n    return httpParams;\r\n  }\r\n\r\n  /**\r\n   * Get the specified page of triples.\r\n   *\r\n   * @param filter The filter.\r\n   * @returns The page.\r\n   */\r\n  public getTriples(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: TripleFilter\r\n  ): Observable<DataPage<UriTriple>> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/triples`;\r\n\r\n    const httpParams = this.applyTripleFilter(\r\n      pageNumber,\r\n      pageSize,\r\n      filter,\r\n      new HttpParams()\r\n    );\r\n\r\n    return this._http\r\n      .get<DataPage<UriTriple>>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the triple with the specified ID.\r\n   *\r\n   * @param id The triple's ID.\r\n   * @returns The triple.\r\n   */\r\n  public getTriple(id: number): Observable<UriTriple> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/triples/` + id.toString();\r\n    return this._http\r\n      .get<UriTriple>(url)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified triple.\r\n   *\r\n   * @param triple The triple to add.\r\n   * @returns The added triple.\r\n   */\r\n  public addTriple(triple: Triple): Observable<Triple> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/triples`;\r\n    return this._http\r\n      .post<Triple>(url, triple)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the triple with the specified ID.\r\n   *\r\n   * @param id The triple's ID.\r\n   */\r\n  public deleteTriple(id: number): Observable<any> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/triples/` + id.toString();\r\n    return this._http.delete(url).pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  private applyLiteralFilter(\r\n    filter: LiteralFilter,\r\n    httpParams: HttpParams\r\n  ): HttpParams {\r\n    if (filter.literalPattern) {\r\n      httpParams = httpParams.set('literalPattern', filter.literalPattern);\r\n    }\r\n    if (filter.literalType) {\r\n      httpParams = httpParams.set('literalType', filter.literalType);\r\n    }\r\n    if (filter.literalLanguage) {\r\n      httpParams = httpParams.set('literalLanguage', filter.literalLanguage);\r\n    }\r\n    if (\r\n      filter.minLiteralNumber !== null &&\r\n      filter.minLiteralNumber !== undefined\r\n    ) {\r\n      httpParams = httpParams.set(\r\n        'minLiteralNumber',\r\n        filter.minLiteralNumber.toString()\r\n      );\r\n    }\r\n    if (\r\n      filter.maxLiteralNumber !== null &&\r\n      filter.maxLiteralNumber !== undefined\r\n    ) {\r\n      httpParams = httpParams.set(\r\n        'maxLiteralNumber',\r\n        filter.maxLiteralNumber.toString()\r\n      );\r\n    }\r\n    return httpParams;\r\n  }\r\n\r\n  /**\r\n   * Get the specified page of triples grouped by their property.\r\n   *\r\n   * @param filter The filter.\r\n   * @returns The page of triples.\r\n   */\r\n  public getTripleGroups(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: TripleFilter\r\n  ): Observable<DataPage<TripleGroup>> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/walk/triples`;\r\n    const httpParams = this.applyTripleFilter(\r\n      pageNumber,\r\n      pageSize,\r\n      filter,\r\n      new HttpParams()\r\n    );\r\n\r\n    return this._http\r\n      .get<DataPage<TripleGroup>>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get linked nodes.\r\n   * @param filter The filter.\r\n   * @returns Observable with data page.\r\n   */\r\n  public getLinkedNodes(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: LinkedNodeFilter\r\n  ): Observable<DataPage<UriNode>> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/walk/nodes`;\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    // NodeFilterBase\r\n    if (filter.uid) {\r\n      httpParams = httpParams.set('uid', filter.uid);\r\n    }\r\n    if (filter.isClass !== null && filter.isClass !== undefined) {\r\n      httpParams = httpParams.set('isClass', filter.isClass);\r\n    }\r\n    if (filter.tag) {\r\n      httpParams = httpParams.set('tag', filter.tag);\r\n    }\r\n    if (filter.label) {\r\n      httpParams = httpParams.set('label', filter.label);\r\n    }\r\n    if (filter.sourceType !== null && filter.sourceType !== undefined) {\r\n      httpParams = httpParams.set('sourceType', +filter.sourceType);\r\n    }\r\n    if (filter.sid) {\r\n      httpParams = httpParams.set('sid', filter.sid);\r\n    }\r\n    if (filter.isSidPrefix !== null && filter.isSidPrefix !== undefined) {\r\n      httpParams = httpParams.set('isSidPrefix', filter.isSidPrefix);\r\n    }\r\n    if (filter.classIds?.length) {\r\n      for (let i = 0; i < filter.classIds.length; i++) {\r\n        httpParams = httpParams.set('classIds', filter.classIds[i]);\r\n      }\r\n    }\r\n\r\n    // LinkedNodeFilter\r\n    if (filter.otherNodeId) {\r\n      httpParams = httpParams.set('otherNodeId', filter.otherNodeId);\r\n    }\r\n    if (filter.predicateId) {\r\n      httpParams = httpParams.set('predicateId', filter.predicateId);\r\n    }\r\n    if (filter.isObject !== null && filter.isObject !== undefined) {\r\n      httpParams = httpParams.set('isObject', filter.isObject);\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<UriNode>>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get linked literals.\r\n   * @param filter The filter.\r\n   * @returns Observable with data page.\r\n   */\r\n  public getLinkedLiterals(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter: LinkedLiteralFilter\r\n  ): Observable<DataPage<UriTriple>> {\r\n    const url = this._env.get('apiUrl') + `${this._apiPath}/walk/nodes/literal`;\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    // LiteralFilter\r\n    httpParams = this.applyLiteralFilter(filter, httpParams);\r\n\r\n    // LinkedLiteralFilter\r\n    if (filter.subjectId) {\r\n      httpParams = httpParams.set('subjectId', filter.subjectId.toString());\r\n    }\r\n    if (filter.predicateId) {\r\n      httpParams = httpParams.set('predicateId', filter.predicateId.toString());\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<UriTriple>>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpParams } from '@angular/common/http';\r\n\r\nimport { Observable } from 'rxjs';\r\nimport { retry, catchError } from 'rxjs/operators';\r\n\r\nimport { ItemInfo } from '@myrmidon/cadmus-core';\r\nimport { DataPage, EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\n\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class ItemBrowserService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService\r\n  ) {}\r\n\r\n  /**\r\n   * Get the array of items browser IDs registered in the server.\r\n   *\r\n   * @returns Observable with strings array.\r\n   */\r\n  public getBrowserIds(): Observable<string[]> {\r\n    return this._http\r\n      .get<string[]>(`${this._env.get('apiUrl')}item-browsers/ids`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the specified page of items from the specified items browser.\r\n   *\r\n   * @param browserId The items browser ID.\r\n   * @param pageNumber The items page number.\r\n   * @param pageSize The items page size.\r\n   * @param filters The filters object.\r\n   */\r\n  public getItems(\r\n    browserId: string,\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filters: any\r\n  ): Observable<DataPage<ItemInfo>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    for (const key in filters) {\r\n      if (filters.hasOwnProperty(key)) {\r\n        httpParams = httpParams.set(key, filters[key]);\r\n      }\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<ItemInfo>>(\r\n        `${this._env.get('apiUrl')}item-browsers/${browserId}/items`,\r\n        {\r\n          params: httpParams,\r\n        }\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport {\r\n  HttpClient,\r\n  HttpErrorResponse,\r\n  HttpParams,\r\n} from '@angular/common/http';\r\n\r\nimport { Observable, of, throwError } from 'rxjs';\r\nimport { retry, catchError, map } from 'rxjs/operators';\r\n\r\nimport {\r\n  ItemFilter,\r\n  ItemInfo,\r\n  Item,\r\n  Part,\r\n  PartDefinition,\r\n  PartGroup,\r\n  LayerPartInfo,\r\n  LayerHint,\r\n  DataPinInfo,\r\n  DataPinDefinition,\r\n} from '@myrmidon/cadmus-core';\r\n\r\nimport {\r\n  DataPage,\r\n  EnvService,\r\n  ErrorService,\r\n  ErrorWrapper,\r\n} from '@myrmidon/ngx-tools';\r\n\r\nexport interface RolePartId {\r\n  roleId: string;\r\n  partId: string;\r\n}\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ItemService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n  ) {}\r\n\r\n  /**\r\n   * Get a page of items matching the specified filters.\r\n   *\r\n   * @param filter The items filter.\r\n   * @returns Observable with paged result.\r\n   */\r\n  public getItems(\r\n    filter: ItemFilter,\r\n    pageNumber = 1,\r\n    pageSize = 20,\r\n  ): Observable<DataPage<ItemInfo>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n    if (filter.title) {\r\n      httpParams = httpParams.set('title', filter.title);\r\n    }\r\n    if (filter.description) {\r\n      httpParams = httpParams.set('description', filter.description);\r\n    }\r\n    if (filter.facetId) {\r\n      httpParams = httpParams.set('facetId', filter.facetId);\r\n    }\r\n    if (filter.groupId) {\r\n      httpParams = httpParams.set('groupId', filter.groupId);\r\n    }\r\n    if (filter.flagMatching !== undefined && +filter.flagMatching > -1) {\r\n      httpParams = httpParams.set(\r\n        'flags',\r\n        filter.flags ? filter.flags.toString() : '0',\r\n      );\r\n      httpParams = httpParams.set(\r\n        'flagMatching',\r\n        filter.flagMatching ? filter.flagMatching.toString() : '0',\r\n      );\r\n    }\r\n    if (filter.userId) {\r\n      httpParams = httpParams.set('userId', filter.userId);\r\n    }\r\n    if (filter.minModified) {\r\n      httpParams = httpParams.set(\r\n        'minModified',\r\n        filter.minModified.toISOString(),\r\n      );\r\n    }\r\n    if (filter.maxModified) {\r\n      httpParams = httpParams.set(\r\n        'maxModified',\r\n        filter.maxModified.toISOString(),\r\n      );\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<ItemInfo>>(`${this._env.get('apiUrl')}items`, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Search the items using the specified query.\r\n   *\r\n   * @param query The query text.\r\n   * @param pageNumber The page number.\r\n   * @param pageSize The page size.\r\n   */\r\n  public searchItems(\r\n    query: string,\r\n    pageNumber: number,\r\n    pageSize: number,\r\n  ): Observable<ErrorWrapper<DataPage<ItemInfo>>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    return this._http\r\n      .post<ErrorWrapper<DataPage<ItemInfo>>>(\r\n        `${this._env.get('apiUrl')}search/items`,\r\n        {\r\n          query,\r\n          pageNumber,\r\n          pageSize,\r\n        },\r\n        {\r\n          params: httpParams,\r\n        },\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Search the item's parts pins using the specified query.\r\n   *\r\n   * @param query The query text.\r\n   * @param pageNumber The page number.\r\n   * @param pageSize The page size.\r\n   */\r\n  public searchPins(\r\n    query: string,\r\n    pageNumber: number,\r\n    pageSize: number,\r\n  ): Observable<ErrorWrapper<DataPage<DataPinInfo>>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n\r\n    return this._http\r\n      .post<ErrorWrapper<DataPage<DataPinInfo>>>(\r\n        `${this._env.get('apiUrl')}search/pins`,\r\n        {\r\n          query,\r\n          pageNumber,\r\n          pageSize,\r\n        },\r\n        {\r\n          params: httpParams,\r\n        },\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the item with the specified ID.\r\n   * @param id Items filter.\r\n   * @param parts True to get also item's parts.\r\n   * @param noErrIfNotFound True to return null if the item is not found.\r\n   * @returns Observable with paged result.\r\n   */\r\n  public getItem(\r\n    id: string,\r\n    parts: boolean,\r\n    noErrIfNotFound = false,\r\n  ): Observable<Item | null> {\r\n    let url = `${this._env.get('apiUrl')}items/${id}`;\r\n    if (parts) {\r\n      url += '?parts=true';\r\n    }\r\n    return this._http.get<Item>(url).pipe(\r\n      retry(3),\r\n      catchError((error) => {\r\n        if (noErrIfNotFound && error?.status === 404) {\r\n          return of(null);\r\n        }\r\n        return this._error.handleError(error);\r\n      }),\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Delete the item with the specified ID.\r\n   * @param id The item's ID.\r\n   * @returns Observable with result.\r\n   */\r\n  public deleteItem(id: string): Observable<any> {\r\n    return this._http\r\n      .delete(`${this._env.get('apiUrl')}items/${id}`)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified item.\r\n   * @param item The item.\r\n   * @returns Observable with result.\r\n   */\r\n  public addItem(item: Item): Observable<Item> {\r\n    return this._http\r\n      .post<Item>(`${this._env.get('apiUrl')}items`, item)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Generate the specified count of items using the specified item as a template.\r\n   *\r\n   * @param count The count of items to generate.\r\n   * @param itemId The ID of the item to be used as a template.\r\n   * @param title The title template for the new item. It can contain\r\n   * a placeholder like {0} for the item number. This can use any\r\n   * formatting supported by the backend (C# `string.Format`).\r\n   * @param flags The flag(s) to be set for each new item.\r\n   */\r\n  public generateItems(\r\n    count: number,\r\n    itemId: string,\r\n    title: string,\r\n    flags = 0,\r\n  ): Observable<any> {\r\n    return this._http\r\n      .post<any>(`${this._env.get('apiUrl')}items/generate`, {\r\n        count,\r\n        itemId,\r\n        title,\r\n        flags,\r\n      })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get a user-facing message from an HTTP error response, using the\r\n   * details of the problem returned by the server when available.\r\n   * @param error The error response.\r\n   * @returns The message.\r\n   */\r\n  private static getErrorMessage(error: HttpErrorResponse): string {\r\n    const problem = error.error;\r\n    const message =\r\n      typeof problem === 'string' ? problem : problem?.detail || problem?.title;\r\n    if (typeof message === 'string' && message) {\r\n      return message;\r\n    }\r\n    return error.status\r\n      ? `Server error ${error.status}: ${error.statusText}`\r\n      : 'Network error';\r\n  }\r\n\r\n  /**\r\n   * Download the item with the specified ID as a JSON file, which can\r\n   * later be uploaded via uploadItem.\r\n   * @param id The item's ID.\r\n   * @param parts True to include the item's parts (default).\r\n   * @returns Observable with the JSON file content. On error, the\r\n   * observable fails with a user-facing message.\r\n   */\r\n  public downloadItem(id: string, parts = true): Observable<Blob> {\r\n    return this._http\r\n      .get(`${this._env.get('apiUrl')}items/${id}/download`, {\r\n        params: new HttpParams().set('parts', parts.toString()),\r\n        responseType: 'blob',\r\n      })\r\n      .pipe(\r\n        catchError((error: HttpErrorResponse) =>\r\n          throwError(() => ItemService.getErrorMessage(error)),\r\n        ),\r\n      );\r\n  }\r\n\r\n  /**\r\n   * Upload the specified JSON file, as generated by downloadItem, to add\r\n   * a new item with its parts. The upload fails if an item with the same\r\n   * ID already exists; if the item or any of its parts were deleted, they\r\n   * get a new ID.\r\n   * @param file The JSON file.\r\n   * @returns Observable with the imported item, including its parts with\r\n   * their final IDs. On error, the observable fails with a user-facing\r\n   * message.\r\n   */\r\n  public uploadItem(file: File): Observable<Item> {\r\n    const data = new FormData();\r\n    data.append('file', file, file.name);\r\n\r\n    return this._http\r\n      .post<Item>(`${this._env.get('apiUrl')}items/upload`, data)\r\n      .pipe(\r\n        catchError((error: HttpErrorResponse) =>\r\n          throwError(() => ItemService.getErrorMessage(error)),\r\n        ),\r\n      );\r\n  }\r\n\r\n  /**\r\n   * Get the item's part with the specified ID.\r\n   * @param id The part ID.\r\n   * @returns Observable with result. If the part ID is null,\r\n   * a null part will be returned.\r\n   */\r\n  public getPart(id: string): Observable<Part | null> {\r\n    if (!id) {\r\n      return of(null);\r\n    }\r\n    return this._http\r\n      .get<Part>(`${this._env.get('apiUrl')}parts/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * From the item with the specified ID, get the first (and normally unique)\r\n   * part matching the specified type and/or role.\r\n   * @param id The item ID.\r\n   * @param type The part type or \"any\".\r\n   * @param role The part role or \"default\".\r\n   * @param noErrIfNotFound If true, no error will be thrown if the part is not found.\r\n   * Rather, null will be returned.\r\n   * @returns Observable with result.\r\n   */\r\n  public getPartFromTypeAndRole(\r\n    id: string,\r\n    type: string,\r\n    role = 'default',\r\n    noErrIfNotFound = false,\r\n  ): Observable<Part | null> {\r\n    if (!type) {\r\n      type = 'any';\r\n    }\r\n    if (!role) {\r\n      role = 'default';\r\n    }\r\n    return this._http\r\n      .get<Part>(`${this._env.get('apiUrl')}items/${id}/parts/${type}/${role}`)\r\n      .pipe(\r\n        retry(3),\r\n        catchError((error) => {\r\n          if (noErrIfNotFound && error?.status === 404) {\r\n            return of(null);\r\n          }\r\n          return this._error.handleError(error);\r\n        }),\r\n      );\r\n  }\r\n\r\n  /**\r\n   * Check if the item with the specified ID has a part of the specified type\r\n   * and role.\r\n   * @param id The item ID.\r\n   * @param type The part type of \"any\".\r\n   * @param role The part role or \"default\".\r\n   * @returns Observable with result.\r\n   */\r\n  public partWithTypeAndRoleExists(\r\n    id: string,\r\n    type: string,\r\n    role = 'default',\r\n  ): Observable<boolean> {\r\n    if (!type) {\r\n      type = 'any';\r\n    }\r\n    if (!role) {\r\n      role = 'default';\r\n    }\r\n    return this._http\r\n      .get<{\r\n        exists: boolean;\r\n      }>(`${this._env.get('apiUrl')}items/${id}/parts/${type}/${role}/exists`)\r\n      .pipe(\r\n        retry(3),\r\n        catchError(this._error.handleError),\r\n        map((r) => r.exists),\r\n      );\r\n  }\r\n\r\n  /**\r\n   * Get the base text (if any) of the item with the specified ID.\r\n   * @param id The item's ID.\r\n   * @returns An observable of an object with a \"text\" property.\r\n   */\r\n  public getBaseTextPart(id: string): Observable<{ part: Part; text: string }> {\r\n    return this._http\r\n      .get<{\r\n        part: Part;\r\n        text: string;\r\n      }>(`${this._env.get('apiUrl')}items/${id}/base-text`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the information about all the layer parts in the item with\r\n   * the specified ID. If parameter \"absent\" is true, the layer parts are added\r\n   * also from the item's facet, even if absent from the database. This produces\r\n   * the full list of all the possible layer parts which could be connected\r\n   * to the given item.\r\n   * Remember that you can have multiple parts of the same type in an item,\r\n   * provided that you specify different roles for them.\r\n   * This happens for the layer part: it is a unique type, but it differs\r\n   * according to its role. Thus, the role here identifies the layer, and\r\n   * in fact it is equal to the layer fragment type ID.\r\n   * Should you need to have several layers of the same type (e.g. 2 comment\r\n   * layers), you can add a layer-specific role to the fragment type ID,\r\n   * by appending it preceded by a colon. For instance, the fragment type ID\r\n   * \"fr.it.vedph.comment:scholarly\" has the ID proper followed by \":\"\r\n   * and its role (\"scholarly\").\r\n   * Thus, the role IDs (=layer type) for layer parts may just be equal\r\n   * to the fragment type ID (e.g. \"fr.it.vedph.comment\"), or include\r\n   * this + colon + role ID proper (e.g.\"fr.it.vedph.comment:scholarly\").\r\n   * @param id The item's ID.\r\n   * @returns Observable with array of RolePartId's.\r\n   */\r\n  public getItemLayerInfo(\r\n    id: string,\r\n    absent: boolean,\r\n  ): Observable<LayerPartInfo[]> {\r\n    let url = `${this._env.get('apiUrl')}items/${id}/layers`;\r\n    if (absent) {\r\n      url += '?absent=true';\r\n    }\r\n    return this._http\r\n      .get<LayerPartInfo[]>(url)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the data pins of the part with the specified ID.\r\n   * @param id The part ID.\r\n   * @returns Observable with array of IDataPin's.\r\n   */\r\n  public getPartPins(id: string): Observable<RolePartId[]> {\r\n    return this._http\r\n      .get<RolePartId[]>(`${this._env.get('apiUrl')}parts/${id}/pins`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the data pin definitions for the part or fragment\r\n   * with the specified type ID.\r\n   * @param typeId The type ID (e.g. \"it.vedph.token-text\" or\r\n   * \"fr.it.vedph.comment\").\r\n   * @returns Observable with array of definitions.\r\n   */\r\n  public getDataPinDefinitions(\r\n    typeId: string,\r\n  ): Observable<DataPinDefinition[]> {\r\n    return this._http\r\n      .get<DataPinDefinition[]>(`${this._env.get('apiUrl')}pin-defs/${typeId}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the layer part break chance, a number indicating whether the layer part\r\n   * with the specified ID might potentially be broken because of changes in its\r\n   * base text.\r\n   * @param id The layer part's ID.\r\n   * @returns An object with a chance property equal to 0=not broken, 1=potentially\r\n   * broken, or 2=surely broken.\r\n   */\r\n  public getLayerPartBreakChance(id: string): Observable<{ chance: number }> {\r\n    return this._http\r\n      .get<{\r\n        chance: number;\r\n      }>(`${this._env.get('apiUrl')}parts/${id}/break-chance`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the layer part reconciliation hints, one for each fragment.\r\n   * @param id The layer part's ID.\r\n   * @returns A list of layer hints, one per fragment.\r\n   */\r\n  public getLayerPartHints(id: string): Observable<LayerHint[]> {\r\n    return this._http\r\n      .get<LayerHint[]>(`${this._env.get('apiUrl')}parts/${id}/layer-hints`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Apply a set of patches to the specified layer part.\r\n   *\r\n   * @param id The layer part ID.\r\n   * @param patches The array of patch instructions.\r\n   */\r\n  public applyLayerPatches(id: string, patches: string[]): Observable<Part> {\r\n    return this._http\r\n      .post<Part>(`${this._env.get('apiUrl')}parts/${id}/layer-patches`, {\r\n        patches,\r\n      })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the part with the specified ID.\r\n   * @param id The part's ID.\r\n   * @returns Observable with result.\r\n   */\r\n  public deletePart(id: string): Observable<any> {\r\n    return this._http\r\n      .delete(`${this._env.get('apiUrl')}parts/${id}`)\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified part.\r\n   * @param part The part.\r\n   * @returns Observable with result.\r\n   */\r\n  public addPart(part: Part): Observable<Part> {\r\n    return this._http\r\n      .post<Part>(`${this._env.get('apiUrl')}parts`, {\r\n        raw: JSON.stringify(part),\r\n      })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Set the flags value for all the specified items.\r\n   *\r\n   * @param ids The item IDs.\r\n   * @param flags The flags value to be set.\r\n   */\r\n  public setItemFlags(ids: string[], flags: number): Observable<any> {\r\n    return this._http\r\n      .post<any>(`${this._env.get('apiUrl')}items/flags`, { ids, flags })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the specified page of item group IDs.\r\n   * @param pageNumber The page number.\r\n   * @param pageSize The page size.\r\n   * @param filter The optional ID filter. If specified, it should be included\r\n   * in each group ID returned.\r\n   * @returns Page.\r\n   */\r\n  public getItemGroupIds(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter?: string,\r\n  ): Observable<DataPage<string>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n    if (filter) {\r\n      httpParams = httpParams.set('filter', filter);\r\n    }\r\n    return this._http\r\n      .get<DataPage<string>>(`${this._env.get('apiUrl')}items/groups`, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Set the group ID value for all the specified items.\r\n   *\r\n   * @param ids The item IDs.\r\n   * @param groupId The group ID value to be set.\r\n   */\r\n  public setItemGroupId(ids: string[], groupId: string): Observable<any> {\r\n    return this._http\r\n      .post<any>(`${this._env.get('apiUrl')}items/group-id`, { ids, groupId })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Set the thesaurus scope for all the specified parts.\r\n   *\r\n   * @param ids The part IDs.\r\n   * @param scope The scope to be set.\r\n   */\r\n  public setPartThesaurusScope(ids: string[], scope: string): Observable<any> {\r\n    return this._http\r\n      .post<any>(`${this._env.get('apiUrl')}parts/thes-scope`, { ids, scope })\r\n      .pipe(catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Group the specified item's parts according to the specified part\r\n   * definitions. This is used to list item's parts in editing it.\r\n   * Each part is grouped under a specific group according to its groupKey,\r\n   * and the parts of each group are sorted according to their sortyKey.\r\n   *\r\n   * @param parts The parts to group.\r\n   * @param partDefs The part definitions to use for grouping.\r\n   * @return The groups.\r\n   */\r\n  public groupParts(parts: Part[], partDefs: PartDefinition[]): PartGroup[] {\r\n    // group the part definitions by their groupKey sorting by sortKey\r\n    const groupedDefs = this.groupBy(\r\n      partDefs.slice().sort((a, b) => {\r\n        return (a.sortKey || '').localeCompare(b.sortKey || '');\r\n      }),\r\n      'groupKey',\r\n    );\r\n\r\n    const groups: PartGroup[] = [];\r\n\r\n    // each group of definitions is a property of groupedDefs, whose value\r\n    // is an array of PartDefinition's: now scan each group\r\n    for (const key in groupedDefs) {\r\n      if (!groupedDefs.hasOwnProperty(key)) {\r\n        continue;\r\n      }\r\n      // create a new parts group to be filled\r\n      const group: PartGroup = {\r\n        key,\r\n        label: key, // TODO get label from key\r\n        parts: [],\r\n      };\r\n\r\n      // for each PartDefinition in the group\r\n      groupedDefs[key].forEach((def: PartDefinition) => {\r\n        // get all the item's parts belonging to this parts group\r\n        const filteredParts: Part[] = parts\r\n          .filter((p) => {\r\n            return (\r\n              p.typeId === def.typeId &&\r\n              ((!p.roleId && !def.roleId) || p.roleId === def.roleId)\r\n            );\r\n          })\r\n          .sort((a, b) => {\r\n            return (a.roleId || '').localeCompare(b.roleId || '');\r\n          });\r\n\r\n        // add each of these parts to the group's parts\r\n        filteredParts.forEach((p: Part) => {\r\n          group.parts.push(p);\r\n        });\r\n      });\r\n      // add the group unless it's empty\r\n      if (group.parts.length > 0) {\r\n        groups.push(group);\r\n      }\r\n    }\r\n    return groups;\r\n  }\r\n\r\n  /**\r\n   * Vanilla groupBy function.\r\n   * See https://gomakethings.com/a-vanilla-js-equivalent-of-lodashs-groupby-method.\r\n   *\r\n   * @param array The array.\r\n   * @param criteria The grouping criteria (either a function receiving the\r\n   * item and returning a key, or a property name).\r\n   * @returns Grouped array.\r\n   */\r\n  private groupBy(array: any[], criteria: any): any[] {\r\n    return array.reduce((obj, item) => {\r\n      // check if the criteria is a function to run on the item or a property of it\r\n      const key =\r\n        typeof criteria === 'function' ? criteria(item) : item[criteria];\r\n\r\n      // if the key doesn't exist yet, create it\r\n      if (!obj.hasOwnProperty(key)) {\r\n        obj[key] = [];\r\n      }\r\n\r\n      // push the value to the object\r\n      obj[key].push(item);\r\n\r\n      // return the object to the next item in the loop\r\n      return obj;\r\n    }, {});\r\n  }\r\n\r\n  /**\r\n   * Let the server build metadata for the target item looking at its parts\r\n   * and return it. This is used when users request to autogenerate the title\r\n   * and/or description of an item.\r\n   *\r\n   * @param id The item's ID.\r\n   * @param targets The target metadata in item: T=title, D=description.\r\n   * @returns Object with requested target keys when found, else empty.\r\n   */\r\n  public getItemMetadata(\r\n    id: string,\r\n    targets = 'TD',\r\n  ): Observable<{ [key: string]: string }> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('targets', targets);\r\n\r\n    return this._http\r\n      .get<{ [key: string]: string }>(\r\n        `${this._env.get('apiUrl')}items/${id}/metadata`,\r\n        {\r\n          params: httpParams,\r\n        },\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\n\r\n/**\r\n * A message payload, with an ID and optional data.\r\n */\r\nexport interface MessagePayload<T> {\r\n  id: string;\r\n  data?: T;\r\n}\r\n\r\n/**\r\n * A simple messaging service, allowing to send messages to subscribers.\r\n * This is typically used to send messages between components.\r\n */\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class MessagingService {\r\n  private _subject = new Subject<MessagePayload<any>>();\r\n\r\n  /**\r\n   * Observable of messages.\r\n   */\r\n  public get messages$() {\r\n    return this._subject.asObservable();\r\n  }\r\n\r\n  /**\r\n   * Send a message to subscribers.\r\n   *\r\n   * @param id The message ID.\r\n   * @param data The optional data to send.\r\n   */\r\n  public sendMessage<T>(id: string, data?: T): void {\r\n    this._subject.next({ id, data });\r\n  }\r\n}\r\n","// https://angular.io/docs/ts/latest/guide/router.html\r\nimport { Injectable } from '@angular/core';\r\nimport {\r\n  Router,\r\n  ActivatedRouteSnapshot,\r\n  RouterStateSnapshot,\r\n} from '@angular/router';\r\nimport { AuthJwtService } from '@myrmidon/auth-jwt-login';\r\n\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class OperatorGuardService {\r\n  constructor(private _router: Router, private _authService: AuthJwtService) {}\r\n\r\n  private redirectToLogin(url: string): void {\r\n    this._router.navigate(['/login'], {\r\n      queryParams: {\r\n        returnUrl: url,\r\n      },\r\n    });\r\n  }\r\n\r\n  canActivate(\r\n    route: ActivatedRouteSnapshot,\r\n    state: RouterStateSnapshot\r\n  ): boolean {\r\n    // if not authenticated, redirect to login\r\n    if (!this._authService.isAuthenticated(false)) {\r\n      this.redirectToLogin(state.url);\r\n      return false;\r\n    }\r\n    // if authenticated but not verified, redirect to login\r\n    if (!this._authService.currentUserValue?.emailConfirmed) {\r\n      this._router.navigate(['/login']);\r\n      console.warn('User not verified');\r\n      return false;\r\n    }\r\n    // else activate only if admin/editor\r\n    const user = this._authService.currentUserValue;\r\n    const ok =\r\n      user &&\r\n      user.roles.some(\r\n        (r) => r === 'admin' || r === 'editor' || r === 'operator'\r\n      );\r\n    if (!ok) {\r\n      console.warn('Unauthorized user');\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n}\r\n","import { HttpClient, HttpParams } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\n\r\nimport { Observable } from 'rxjs';\r\nimport { catchError, retry } from 'rxjs/operators';\r\n\r\nimport { ErrorService, EnvService } from '@myrmidon/ngx-tools';\r\n\r\n/**\r\n * Result of an object rendition.\r\n */\r\nexport interface RenditionResult {\r\n  result: string;\r\n}\r\n\r\nexport interface AnnotatedTextRange {\r\n  start: number;\r\n  end: number;\r\n  fragmentIds?: string[];\r\n  text?: string;\r\n}\r\n\r\n/**\r\n * A text span used in rendering.\r\n */\r\n// export interface TextSpan {\r\n//   range?: AnnotatedTextRange;\r\n//   type?: string;\r\n//   isBeforeEol?: boolean;\r\n//   text?: string;\r\n//   features?: { [key: string]: string };\r\n// }\r\n\r\nexport interface StringPair {\r\n  name: string;\r\n  value?: string;\r\n}\r\n\r\n/**\r\n * A segment of a text used in export/preview.\r\n */\r\nexport interface ExportedSegment {\r\n  sourceId: number;\r\n  type?: string;\r\n  text?: string;\r\n  features?: StringPair[];\r\n  tags?: string[];\r\n  payloads?: any[];\r\n}\r\n\r\n/**\r\n * Cadmus preview API service.\r\n */\r\n@Injectable({\r\n  providedIn: 'root',\r\n})\r\nexport class PreviewService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService\r\n  ) {}\r\n\r\n  // preview/keys\r\n  /**\r\n   * Gets all the Cadmus objects keys registered for preview.\r\n   *\r\n   * @param type A character: J=JSON renderer keys, F=text flattener keys,\r\n   * C=item composer keys. The default is J.\r\n   * @returns List of unique keys.\r\n   */\r\n  public getKeys(type: string): Observable<string[]> {\r\n    const url = this._env.get('apiUrl') + 'preview/keys';\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('type', type || 'J');\r\n    return this._http\r\n      .get<string[]>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  // preview/items/{itemId}/parts/{partId}\r\n  /**\r\n   * Render the part with the specified ID.\r\n   *\r\n   * @param itemId The item's ID.\r\n   * @param partId The part's ID.\r\n   * @returns Rendition.\r\n   */\r\n  public renderPart(\r\n    itemId: string,\r\n    partId: string\r\n  ): Observable<RenditionResult> {\r\n    return this._http\r\n      .get<RenditionResult>(\r\n        this._env.get('apiUrl') + `preview/items/${itemId}/parts/${partId}`\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  // preview/items/{itemId}parts/{partId}/{frIndex}\r\n  /**\r\n   * Render the fragment at the specified index in the part with the specified\r\n   * ID.\r\n   *\r\n   * @param itemId The item's ID.\r\n   * @param partId The part's ID.\r\n   * @param frIndex The fragment's index (0-N).\r\n   * @returns Rendition.\r\n   */\r\n  public renderFragment(\r\n    itemId: string,\r\n    partId: string,\r\n    frIndex: number\r\n  ): Observable<RenditionResult> {\r\n    return this._http\r\n      .get<RenditionResult>(\r\n        this._env.get('apiUrl') +\r\n          `preview/items/${itemId}/parts/${partId}/${frIndex}`\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  // preview/text-parts/{id}\r\n  /**\r\n   * Gets the text segments built by flattening the text part with the\r\n   * specified ID with all the layers specified.\r\n   *\r\n   * @param textPartId The base text part's ID.\r\n   * @param layerPartIds The layer parts IDs.\r\n   */\r\n  public getTextSegments(\r\n    textPartId: string,\r\n    layerPartIds: string[]\r\n  ): Observable<ExportedSegment[]> {\r\n    let httpParams = new HttpParams();\r\n\r\n    if (layerPartIds.length) {\r\n      for (let i = 0; i < layerPartIds.length; i++) {\r\n        let id = layerPartIds[i];\r\n        httpParams = httpParams.append('layerPartId', id);\r\n      }\r\n    }\r\n\r\n    return this._http\r\n      .get<ExportedSegment[]>(\r\n        this._env.get('apiUrl') + `preview/text-parts/${textPartId}`,\r\n        {\r\n          params: httpParams,\r\n        }\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { HttpClient } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { catchError, Observable, retry } from 'rxjs';\r\n\r\nimport { ErrorService, EnvService } from '@myrmidon/ngx-tools';\r\n\r\nexport interface ItemEditFrameStats {\r\n  start?: Date;\r\n  end?: Date;\r\n  createdCount: number;\r\n  updatedCount: number;\r\n  deletedCount: number;\r\n}\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class StatsService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService\r\n  ) {}\r\n\r\n  public getEditFrameStats(\r\n    start: Date | string,\r\n    end: Date | string,\r\n    interval: string,\r\n    frameLimit = 0\r\n  ): Observable<ItemEditFrameStats[]> {\r\n    // ensure we have proper Date objects for ISO string conversion\r\n    const startDate = start instanceof Date ? start : new Date(start);\r\n    const endDate = end instanceof Date ? end : new Date(end);\r\n\r\n    // construct the URL with query parameters\r\n    // - start and end are dates, so we need to format them\r\n    // - interval is N + unit (e.g., \"1d\", \"1h\", \"1m\")\r\n    const url =\r\n      `${this._env.get('apiUrl')}stats/edit-frames` +\r\n      `?start=${startDate.toISOString()}&end=${endDate.toISOString()}` +\r\n      `&interval=${interval}&frameLimit=${frameLimit}`;\r\n\r\n    return this._http\r\n      .get<ItemEditFrameStats[]>(url)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpParams } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { retry, catchError, take } from 'rxjs/operators';\r\n\r\nimport { Thesaurus, ThesauriSet, ThesaurusFilter } from '@myrmidon/cadmus-core';\r\nimport { DataPage, EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ThesaurusService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n  ) {}\r\n\r\n  private getFilterParams(\r\n    pageNumber: number,\r\n    pageSize: number,\r\n    filter?: ThesaurusFilter,\r\n  ): HttpParams {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n    if (filter?.id) {\r\n      httpParams = httpParams.set('id', filter.id);\r\n    }\r\n    if (filter?.language) {\r\n      httpParams = httpParams.set('language', filter.language);\r\n    }\r\n    if (filter?.isAlias === false || filter?.isAlias === true) {\r\n      httpParams = httpParams.set(\r\n        'isAlias',\r\n        filter.isAlias === true ? 'true' : 'false',\r\n      );\r\n    }\r\n    return httpParams;\r\n  }\r\n\r\n  /**\r\n   * Get the list of all thesauri IDs or of the subset of them matching the filter.\r\n   * @param filter The optional filter to use.\r\n   * @returns Array of IDs.\r\n   */\r\n  public getThesaurusIds(\r\n    filter?: ThesaurusFilter,\r\n  ): Observable<string[]> {\r\n    const url = `${this._env.get('apiUrl')}thesauri-ids`;\r\n\r\n    if (!filter) {\r\n      return this._http\r\n        .get<string[]>(url)\r\n        .pipe(retry(3), catchError(this._error.handleError));\r\n    } else {\r\n      let httpParams = new HttpParams();\r\n      if (filter.id) {\r\n        httpParams = httpParams.set('id', filter.id);\r\n      }\r\n      if (filter.language) {\r\n        httpParams = httpParams.set('language', filter.language);\r\n      }\r\n      if (filter.isAlias === false || filter.isAlias === true) {\r\n        httpParams = httpParams.set(\r\n          'isAlias',\r\n          filter.isAlias === true ? 'true' : 'false',\r\n        );\r\n      }\r\n      return this._http\r\n        .get<string[]>(url, {\r\n          params: httpParams,\r\n        })\r\n        .pipe(retry(3), catchError(this._error.handleError));\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Check whether a thesaurus with the specified ID exists.\r\n   *\r\n   * @param id The ID of the thesaurus to check for.\r\n   * @returns Promise having true/false on resolution.\r\n   */\r\n  public thesaurusExists(id: string): Promise<boolean> {\r\n    return new Promise((resolve, reject) => {\r\n      let httpParams = new HttpParams();\r\n      httpParams = httpParams.set('pageNumber', '1');\r\n      httpParams = httpParams.set('pageSize', '1');\r\n      httpParams = httpParams.set('id', id);\r\n\r\n      this._http\r\n        .get<string[]>(`${this._env.get('apiUrl')}thesauri-ids`, {\r\n          params: httpParams,\r\n        })\r\n        .pipe(retry(3), take(1), catchError(this._error.handleError))\r\n        .subscribe({\r\n          next: (ids) => {\r\n            resolve(ids.length > 0);\r\n          },\r\n          error: (_) => {\r\n            console.error('Error checking for existence of thesaurus ' + id);\r\n            reject(false);\r\n          },\r\n        });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the tags set with the specified ID.\r\n   * @param id string The tag set ID.\r\n   * @param emptyIfNotFound True to return an empty thesaurus when the requested\r\n   * thesaurus ID is not found, rather than getting a 404.\r\n   * @returns Tag set.\r\n   */\r\n  public getThesaurus(\r\n    id: string,\r\n    emptyIfNotFound = false,\r\n  ): Observable<Thesaurus> {\r\n    let httpParams = new HttpParams();\r\n    if (emptyIfNotFound) {\r\n      httpParams = httpParams.set('emptyIfNotFound', true.toString());\r\n    }\r\n    const url = `${this._env.get('apiUrl')}thesauri/${encodeURIComponent(id)}`;\r\n    return this._http\r\n      .get<Thesaurus>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get a list of thesauri IDs whose target ID is the specified one.\r\n   * @param targetId The target ID of the thesaurus.\r\n   * @returns An ordered list of thesauri IDs whose target ID is targetId.\r\n   */\r\n  public getThesaurusAliases(targetId: string): Observable<string[]> {\r\n    let httpParams = new HttpParams();\r\n    const url = `${this._env.get('apiUrl')}thesauri/${encodeURIComponent(targetId)}/aliases`;\r\n    return this._http\r\n      .get<string[]>(url, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the requested thesauri in a batch.\r\n   * @param ids The IDs of the requested thesauri.\r\n   * @returns An object where each key is the purged thesaurus ID with value\r\n   * equal to the thesaurus model.\r\n   */\r\n  public getThesauriSet(ids: string[]): Observable<ThesauriSet> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('purgeIds', 'true');\r\n    httpParams = httpParams.set('ids', ids.join(','));\r\n    return this._http\r\n      .get<ThesauriSet>(`${this._env.get('apiUrl')}thesauri-set`, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get a page of thesauri.\r\n   *\r\n   * @param filter The filter.\r\n   */\r\n  public getThesauri(\r\n    filter: ThesaurusFilter,\r\n    pageNumber = 1,\r\n    pageSize = 20,\r\n  ): Observable<DataPage<Thesaurus>> {\r\n    let httpParams = this.getFilterParams(pageNumber, pageSize, filter);\r\n\r\n    return this._http\r\n      .get<DataPage<Thesaurus>>(`${this._env.get('apiUrl')}thesauri`, {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Add or update the specified thesaurus.\r\n   *\r\n   * @param thesaurus The thesaurus.\r\n   */\r\n  public addThesaurus(thesaurus: Thesaurus): Observable<any> {\r\n    return this._http\r\n      .post(`${this._env.get('apiUrl')}thesauri`, thesaurus)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Delete the specified thesaurus.\r\n   *\r\n   * @param id The thesaurus ID.\r\n   */\r\n  public deleteThesaurus(id: string): Observable<any> {\r\n    return this._http\r\n      .delete<Thesaurus>(`${this._env.get('apiUrl')}thesauri/${id}`)\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the thesaurus scoped ID from the corresponding non-scoped thesaurus ID\r\n   * and the specified scope ID. This just suffixes the thesaurus ID with\r\n   * the scope ID prefixed by a dot, before the language ID. For instance,\r\n   * a thesaurus ID \"witnesses@en\" with a scope ID \"lucr\" would become\r\n   * \"witnesses.lucr@en\". If the thesaurus ID starts with an exclamation mark,\r\n   * which means that it must not be scoped, this function will return it\r\n   * without the leading mark.\r\n   *\r\n   * @param id The thesaurus ID.\r\n   * @param scopeId The scope ID, or undefined when you just want to strip off\r\n   * the leading exclamation mark if any.\r\n   */\r\n  public getScopedId(id: string, scopeId?: string): string {\r\n    // an ID starting with ! should not be scoped\r\n    if (id.startsWith('!')) {\r\n      return id.substring(1);\r\n    }\r\n    // just ret the ID if we were just requested to strip the initial !\r\n    if (!scopeId) {\r\n      return id;\r\n    }\r\n\r\n    const i = id.lastIndexOf('@');\r\n    if (i === -1) {\r\n      return id + '.' + scopeId;\r\n    }\r\n    return id.substring(0, i) + '.' + scopeId + id.substring(i);\r\n  }\r\n\r\n  /**\r\n   * Get the unscoped thesaurus ID from the specified ID, also stripping\r\n   * any language suffix off and any leading \"!\". For instance, an ID like\r\n   * \"apparatus-witnesses.verg-eclo@en\" becomes \"apparatus-witnesses\".\r\n   *\r\n   * @param id The thesaurus ID.\r\n   */\r\n  public getUnscopedId(id: string): string {\r\n    if (id.startsWith('!')) {\r\n      id = id.substring(1);\r\n    }\r\n    let i = id.lastIndexOf('.');\r\n    if (i > 0) {\r\n      id = id.substring(0, i);\r\n    }\r\n\r\n    i = id.lastIndexOf('@');\r\n    if (i > -1) {\r\n      id = id.substring(0, i);\r\n    }\r\n    return id;\r\n  }\r\n}\r\n","import { Injectable } from '@angular/core';\nimport { HttpClient, HttpRequest } from '@angular/common/http';\nimport { Observable } from 'rxjs';\n\n/**\n * Generic upload service.\n */\n@Injectable({\n  providedIn: 'root',\n})\nexport class UploadService {\n  constructor(private http: HttpClient) {}\n\n  /**\n   * Upload the specified file to the specified URL.\n   * @param file The file to upload.\n   * @param url The upload URL.\n   * @param options The options. For instance, you can pass { reportProgress: true}\n   * to get upload progress events.\n   * @returns Observable.\n   */\n  uploadFile(file: File, url: string, options?: any): Observable<any> {\n    const fd = new FormData();\n    fd.append('file', file, file.name);\n\n    const uploadRequest = new HttpRequest('POST', url, fd, {\n      reportProgress: true,\n      ...options,\n    });\n\n    return this.http.request(uploadRequest);\n  }\n}\n","import { Injectable } from '@angular/core';\nimport { AuthJwtService } from '@myrmidon/auth-jwt-login';\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class UserLevelService {\n  constructor(private _authService: AuthJwtService) {}\n\n  /**\n   * Get the authorization level of the current user if any.\n   * @returns 4-1 for admin, editor, operator, visitor; else 0.\n   */\n  public getCurrentUserLevel(): number {\n    const user = this._authService.currentUserValue;\n    if (!user || !user.roles) {\n      return 0;\n    }\n    if (user.roles.indexOf('admin') > -1) {\n      return 4;\n    }\n    if (user.roles.indexOf('editor') > -1) {\n      return 3;\n    }\n    if (user.roles.indexOf('operator') > -1) {\n      return 2;\n    }\n    if (user.roles.indexOf('visitor') > -1) {\n      return 1;\n    }\n    return 0;\n  }\n}\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpParams } from '@angular/common/http';\r\n\r\nimport { Observable } from 'rxjs';\r\nimport { retry, catchError } from 'rxjs/operators';\r\n\r\nimport { DataPage, EnvService, ErrorService } from '@myrmidon/ngx-tools';\r\nimport { UserFilter } from '@myrmidon/auth-jwt-admin';\r\n\r\n/**\r\n * A Cadmus user with his roles.\r\n */\r\nexport interface UserWithRoles {\r\n  user: {\r\n    id: string;\r\n    firstName: string;\r\n    lastName: string;\r\n    userName: string;\r\n    email: string;\r\n  };\r\n  roles: string[];\r\n}\r\n\r\n/**\r\n * Cadmus users service.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class UserService {\r\n  constructor(\r\n    private _http: HttpClient,\r\n    private _error: ErrorService,\r\n    private _env: EnvService,\r\n  ) {}\r\n\r\n  public getAllUsers(): Observable<DataPage<UserWithRoles>> {\r\n    return this._http\r\n      .get<DataPage<UserWithRoles>>(this._env.get('apiUrl') + 'users', {\r\n        params: new HttpParams().set('pageNumber', '1'),\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  public getUsers(\r\n    filter: UserFilter,\r\n    pageNumber = 1,\r\n    pageSize = 20,\r\n  ): Observable<DataPage<UserWithRoles>> {\r\n    let httpParams = new HttpParams();\r\n    httpParams = httpParams.set('pageNumber', pageNumber.toString());\r\n    httpParams = httpParams.set('pageSize', pageSize.toString());\r\n    if (filter.name) {\r\n      httpParams = httpParams.set('name', filter.name);\r\n    }\r\n\r\n    return this._http\r\n      .get<DataPage<UserWithRoles>>(this._env.get('apiUrl') + 'users', {\r\n        params: httpParams,\r\n      })\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n\r\n  /**\r\n   * Get the user with the specified name.\r\n   *\r\n   * @param name The user name.\r\n   * @returns Observable with the user, or undefined if not found.\r\n   */\r\n  public getUser(name: string): Observable<UserWithRoles | undefined> {\r\n    return this._http\r\n      .get<UserWithRoles>(\r\n        this._env.get('apiUrl') + 'users/' + encodeURIComponent(name),\r\n      )\r\n      .pipe(retry(3), catchError(this._error.handleError));\r\n  }\r\n}\r\n","import { inject } from '@angular/core';\r\nimport {\r\n  Router,\r\n  ActivatedRouteSnapshot,\r\n  RouterStateSnapshot,\r\n} from '@angular/router';\r\nimport { AuthJwtService } from '@myrmidon/auth-jwt-login';\r\n\r\nexport function editorGuard(\r\n  route: ActivatedRouteSnapshot,\r\n  state: RouterStateSnapshot\r\n): boolean {\r\n  const router = inject(Router);\r\n  const authService = inject(AuthJwtService);\r\n\r\n  const redirectToLogin = (url: string): void => {\r\n    router.navigate(['/login'], {\r\n      queryParams: {\r\n        returnUrl: url,\r\n      },\r\n    });\r\n  };\r\n\r\n  // if not authenticated, redirect to login\r\n  if (!authService.isAuthenticated(false)) {\r\n    redirectToLogin(state.url);\r\n    return false;\r\n  }\r\n  // if authenticated but not verified, redirect to login\r\n  if (!authService.currentUserValue?.emailConfirmed) {\r\n    router.navigate(['/login']);\r\n    console.warn('User not verified');\r\n    return false;\r\n  }\r\n  // else activate only if admin/editor\r\n  const user = authService.currentUserValue;\r\n  const ok = user && user.roles.some((r) => r === 'admin' || r === 'editor');\r\n  if (!ok) {\r\n    console.warn('Unauthorized user');\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n","import { inject } from '@angular/core';\r\nimport {\r\n  Router,\r\n  ActivatedRouteSnapshot,\r\n  RouterStateSnapshot,\r\n} from '@angular/router';\r\nimport { AuthJwtService } from '@myrmidon/auth-jwt-login';\r\n\r\nexport function operatorGuard(\r\n  route: ActivatedRouteSnapshot,\r\n  state: RouterStateSnapshot\r\n): boolean {\r\n  const router = inject(Router);\r\n  const authService = inject(AuthJwtService);\r\n\r\n  const redirectToLogin = (url: string): void => {\r\n    router.navigate(['/login'], {\r\n      queryParams: {\r\n        returnUrl: url,\r\n      },\r\n    });\r\n  };\r\n\r\n  // if not authenticated, redirect to login\r\n  if (!authService.isAuthenticated(false)) {\r\n    redirectToLogin(state.url);\r\n    return false;\r\n  }\r\n  // if authenticated but not verified, redirect to login\r\n  if (!authService.currentUserValue?.emailConfirmed) {\r\n    router.navigate(['/login']);\r\n    console.warn('User not verified');\r\n    return false;\r\n  }\r\n  // else activate only if admin/editor\r\n  const user = authService.currentUserValue;\r\n  const ok =\r\n    user &&\r\n    user.roles.some((r) => r === 'admin' || r === 'editor' || r === 'operator');\r\n  if (!ok) {\r\n    console.warn('Unauthorized user');\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n"],"mappings":"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"}