diff --git a/projects/ng-core-tester/src/app/app-config.service.ts b/projects/ng-core-tester/src/app/app-config.service.ts index 5211f843..62939a76 100644 --- a/projects/ng-core-tester/src/app/app-config.service.ts +++ b/projects/ng-core-tester/src/app/app-config.service.ts @@ -18,10 +18,16 @@ import { Injectable } from '@angular/core'; import { CoreConfigService } from '@rero/ng-core'; import { environment } from '../environments/environment'; +/** + * Service for configuring the application. + */ @Injectable({ providedIn: 'root' }) export class AppConfigService extends CoreConfigService { + /** + * Constructor. + */ constructor() { super(); this.production = false; diff --git a/projects/ng-core-tester/src/app/app-routing.module.ts b/projects/ng-core-tester/src/app/app-routing.module.ts index 142a09d6..aff3d728 100644 --- a/projects/ng-core-tester/src/app/app-routing.module.ts +++ b/projects/ng-core-tester/src/app/app-routing.module.ts @@ -25,6 +25,9 @@ import { DetailComponent } from './record/document/detail/detail.component'; import { DocumentComponent } from './record/document/document.component'; import { RouteService } from './routes/route.service'; +/** + * Disallows access to admin functionalities. + */ const adminModeCanNot = (): Observable => { return of({ can: false, @@ -32,6 +35,9 @@ const adminModeCanNot = (): Observable => { }); }; +/** + * Allows access to admin functionalities. + */ const adminModeCan = (): Observable => { return of({ can: true, @@ -39,6 +45,9 @@ const adminModeCan = (): Observable => { }); }; +/** + * Whether user can add a record. + */ const canAdd = (record: any): Observable => { return of({ can: Math.random() >= 0.5, @@ -46,6 +55,9 @@ const canAdd = (record: any): Observable => { }); }; +/** + * Whether user can update a record. + */ const canUpdate = (record: any): Observable => { return of({ can: Math.random() >= 0.5, @@ -53,6 +65,9 @@ const canUpdate = (record: any): Observable => { }); }; +/** + * Whether user can delete a record. + */ const canDelete = (record: any): Observable => { return of({ can: Math.random() >= 0.5, @@ -60,6 +75,9 @@ const canDelete = (record: any): Observable => { }); }; +/** + * Whether user can read a record. + */ const canRead = (record: any): Observable => { return of({ can: Math.random() >= 0.5, @@ -67,6 +85,9 @@ const canRead = (record: any): Observable => { }); }; +/** + * Custom configuration for form editor. + */ const formFieldMap = (field: FormlyFieldConfig, jsonSchema: JSONSchema7): FormlyFieldConfig => { // Populates "type" field with custom options const formOptions = jsonSchema.form; @@ -82,10 +103,19 @@ const formFieldMap = (field: FormlyFieldConfig, jsonSchema: JSONSchema7): Formly return field; }; +/** + * Custom treatment for aggregations. + */ const aggregations = (agg: object) => { return of(agg); }; +/** + * Returned matched URL. + * + * @param url List of URL segments. + * @return Object representing the matched URL. + */ export function matchedUrl(url: UrlSegment[]) { const segments = [new UrlSegment(url[0].path, {})]; @@ -95,6 +125,12 @@ export function matchedUrl(url: UrlSegment[]) { }; } +/** + * URL matchs document resource. + * + * @param url List of URL segments. + * @return Object representing the matched URL. + */ export function documentsMatcher(url: Array) { if (url[0].path === 'records' && url[1].path === 'documents') { return matchedUrl(url); @@ -102,6 +138,12 @@ export function documentsMatcher(url: Array) { return null; } +/** + * URL matchs organisation resource. + * + * @param url List of URL segments. + * @return Object representing the matched URL. + */ export function institutionsMatcher(url: Array) { if (url[0].path === 'records' && url[1].path === 'institutions') { return matchedUrl(url); @@ -109,6 +151,9 @@ export function institutionsMatcher(url: Array) { return null; } +/** + * List of routes for application. + */ const routes: Routes = [ { path: '', @@ -196,12 +241,22 @@ const routes: Routes = [ } ]; +/** + * Routing module for application. + */ @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { - constructor(private routeService: RouteService) { - this.routeService.initializeRoutes(); + /** + * Constructor + * + * Intializes routes. + * + * @param _routeService Route service + */ + constructor(private _routeService: RouteService) { + this._routeService.initializeRoutes(); } } diff --git a/projects/ng-core-tester/src/app/app.component.ts b/projects/ng-core-tester/src/app/app.component.ts index 6341954d..a6f993b5 100644 --- a/projects/ng-core-tester/src/app/app.component.ts +++ b/projects/ng-core-tester/src/app/app.component.ts @@ -20,16 +20,25 @@ import { CoreConfigService, RecordEvent, RecordService, TitleMetaService } from import { BsLocaleService } from 'ngx-bootstrap'; import { ToastrService } from 'ngx-toastr'; +/** + * Main component of the application. + */ @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { + // Current lang of the application lang: string = document.documentElement.lang; + + // Available languages languages: string[]; + + // If navigation is collapsed or not. isCollapsed = true; - public linksMenu = { + // List of links in the navigation. + linksMenu = { navCssClass: 'navbar-nav', entries: [ { @@ -69,63 +78,88 @@ export class AppComponent implements OnInit { ] }; + // List of languages in the navigation. languagesMenu = { navCssClass: 'navbar-nav', entries: [] }; - private activeLanguagesMenuItem; + // Active language. + private _activeLanguagesMenuItem: any; + /** + * Constructor. + * @param _translateService Translate service. + * @param _configService Configuration service. + * @param _titleMetaService Meta service. + * @param _recordService Record service. + * @param _toastrService Toast service. + * @param _bsLocaleService Locale service for bootstrap. + */ constructor( - private translateService: TranslateService, - private configService: CoreConfigService, - private titleMetaService: TitleMetaService, - private recordService: RecordService, - private toastrService: ToastrService, - private bsLocaleService: BsLocaleService - ) { - } + private _translateService: TranslateService, + private _configService: CoreConfigService, + private _titleMetaService: TitleMetaService, + private _recordService: RecordService, + private _toastrService: ToastrService, + private _bsLocaleService: BsLocaleService + ) { + } - ngOnInit() { - this.initializeEvents(); - this.translateService.use(this.lang); - this.languages = this.configService.languages; - for (const lang of this.languages) { - const data: any = {name: lang}; - if (lang === this.lang) { - data.active = true; - this.activeLanguagesMenuItem = data; - } - this.languagesMenu.entries.push(data); - } - // Set default title window when application start - const prefix = this.configService.prefixWindow; - if (prefix) { - this.titleMetaService.setPrefix(prefix); + /** + * Component initialization. + * + * - Initializes listener to record changes. + * - Initializes languages and current language. + * - Sets title metadata. + */ + ngOnInit() { + this.initializeEvents(); + this._translateService.use(this.lang); + this.languages = this._configService.languages; + for (const lang of this.languages) { + const data: any = { name: lang }; + if (lang === this.lang) { + data.active = true; + this._activeLanguagesMenuItem = data; } - this.titleMetaService.setTitle('Welcome'); + this.languagesMenu.entries.push(data); } - - changeLang(item: any) { - this.translateService.use(item.name); - this.bsLocaleService.use(item.name); - delete(this.activeLanguagesMenuItem.active); - item.active = true; - this.activeLanguagesMenuItem = item; + // Set default title window when application start + const prefix = this._configService.prefixWindow; + if (prefix) { + this._titleMetaService.setPrefix(prefix); } + this._titleMetaService.setTitle('Welcome'); + } - private initializeEvents() { - this.recordService.onCreate$.subscribe((recordEvent: RecordEvent) => { - const pid = recordEvent.data.record.pid; - this.toastrService.info(`Call Record Event on create (Record Pid: ${pid})`); - }); - this.recordService.onUpdate$.subscribe((recordEvent: RecordEvent) => { - const pid = recordEvent.data.record.pid; - this.toastrService.info(`Call Record Event on update (Record Pid: ${pid})`); - }); - this.recordService.onDelete$.subscribe((recordEvent: RecordEvent) => { - const pid = recordEvent.data.pid; - this.toastrService.info(`Call Record Event on delete (Record Pid: ${pid})`); - }); - } + /** + * Changes the languages. + * @param item Menu item representing a language. + */ + changeLang(item: any) { + this._translateService.use(item.name); + this._bsLocaleService.use(item.name); + delete (this._activeLanguagesMenuItem.active); + item.active = true; + this._activeLanguagesMenuItem = item; + } + + /** + * Initializes listening of events when a record is changed. + */ + private initializeEvents() { + this._recordService.onCreate$.subscribe((recordEvent: RecordEvent) => { + const pid = recordEvent.data.record.pid; + this._toastrService.info(`Call Record Event on create (Record Pid: ${pid})`); + }); + this._recordService.onUpdate$.subscribe((recordEvent: RecordEvent) => { + const pid = recordEvent.data.record.pid; + this._toastrService.info(`Call Record Event on update (Record Pid: ${pid})`); + }); + this._recordService.onDelete$.subscribe((recordEvent: RecordEvent) => { + const pid = recordEvent.data.pid; + this._toastrService.info(`Call Record Event on delete (Record Pid: ${pid})`); + }); } +} diff --git a/projects/ng-core-tester/src/app/home/home.component.ts b/projects/ng-core-tester/src/app/home/home.component.ts index c57e625f..412c67dc 100644 --- a/projects/ng-core-tester/src/app/home/home.component.ts +++ b/projects/ng-core-tester/src/app/home/home.component.ts @@ -24,10 +24,14 @@ import { DocumentComponent } from '../record/document/document.component'; templateUrl: './home.component.html' }) export class HomeComponent { - title = 'app-ng-core'; - apiData: object; + // Object containing API paths. + apiData: any; + + // Contains the full translated language of a language code. testLanguageTranslation: string; - recordConfig: object[] = [ + + // Configuration for resources. + recordConfig: Array = [ { key: 'documents', label: 'Documents', @@ -39,7 +43,8 @@ export class HomeComponent { } ]; - demoMenu = { + // Menu links for demo. + demoMenu: any = { entries: [ { routerLink: '/', @@ -59,24 +64,40 @@ export class HomeComponent { ] }; + /** + * Constructor. + * + * - Initializes API object paths. + * - Stores translated language. + * - Empties aggregations filters. + * + * @param _dialogService Dialog service. + * @param _apiService API service. + * @param _translateLanguageService Translate language service. + * @param _toastrService Toastr service. + * @param _recordSearchService Record search service. + */ constructor( - private dialogService: DialogService, - private apiService: ApiService, - private translateLanguageService: TranslateLanguageService, - private toastrService: ToastrService, + private _dialogService: DialogService, + private _apiService: ApiService, + private _translateLanguageService: TranslateLanguageService, + private _toastrService: ToastrService, private _recordSearchService: RecordSearchService ) { this.apiData = { - relative: this.apiService.getEndpointByType('documents'), - absolute: this.apiService.getEndpointByType('documents', true), + relative: this._apiService.getEndpointByType('documents'), + absolute: this._apiService.getEndpointByType('documents', true), }; - this.testLanguageTranslation = this.translateLanguageService.translate('fr', 'fr'); + this.testLanguageTranslation = this._translateLanguageService.translate('fr', 'fr'); // Initializes aggregations filters to launch the first search. this._recordSearchService.setAggregationsFilters([]); } + /** + * Show a confirmation dialog box. + */ showDialog() { const config = { ignoreBackdropClick: true, @@ -87,42 +108,61 @@ export class HomeComponent { } }; - this.dialogService.show(config).subscribe((confirm: boolean) => { + this._dialogService.show(config).subscribe((confirm: boolean) => { if (confirm) { console.log('Confirmed !'); } }); } + /** + * Simulates a search by only log infos. + * + * @param searchText String to search. + */ doSearch(searchText: string) { console.log(`You search for: ${searchText}`); } + /** + * Shows an alert message with toastr. + */ addAlert() { const type = (document.getElementById('alert-type')) as HTMLSelectElement; const message = (document.getElementById('alert-message')) as HTMLInputElement; switch (type.value) { // Checkbox controls case 'success': - this.toastrService.success(message.value); + this._toastrService.success(message.value); break; case 'info': - this.toastrService.info(message.value); + this._toastrService.info(message.value); break; case 'warning': - this.toastrService.warning(message.value); + this._toastrService.warning(message.value); break; case 'danger': - this.toastrService.error(message.value); + this._toastrService.error(message.value); break; } } - clickLinkItemMenu(item) { - this.toastrService.success(`menu ${item.name} clicked`); + /** + * Show a message when item menu is clicked. + * + * @param item Menu item. + */ + clickLinkItemMenu(item: any) { + this._toastrService.success(`menu ${item.name} clicked`); } - isItemMenuVisible(itemMenu) { + /** + * Whether a menu item is visible or not. + * + * @param itemMenu Menu item. + * @return True if the menu is visible. + */ + isItemMenuVisible(itemMenu: any) { if (itemMenu.name === 'Hidden') { return false; } diff --git a/projects/ng-core-tester/src/app/record-wrapper/record-wrapper.module.ts b/projects/ng-core-tester/src/app/record-wrapper/record-wrapper.module.ts index ac3d4947..11fa5258 100644 --- a/projects/ng-core-tester/src/app/record-wrapper/record-wrapper.module.ts +++ b/projects/ng-core-tester/src/app/record-wrapper/record-wrapper.module.ts @@ -18,6 +18,10 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RecordModule } from '@rero/ng-core'; +/** + * Module used to wrap record module of ng-core for using it in routes lazy + * loading. + */ @NgModule({ declarations: [], imports: [ diff --git a/projects/ng-core-tester/src/app/record/document/detail/detail.component.ts b/projects/ng-core-tester/src/app/record/document/detail/detail.component.ts index 6c78dcb3..5c5d5d79 100644 --- a/projects/ng-core-tester/src/app/record/document/detail/detail.component.ts +++ b/projects/ng-core-tester/src/app/record/document/detail/detail.component.ts @@ -19,24 +19,39 @@ import { TitleMetaService } from '@rero/ng-core'; import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record'; import { Observable } from 'rxjs'; +/** + * Component for displaying the detail of a document. + */ @Component({ selector: 'app-detail', templateUrl: './detail.component.html' }) export class DetailComponent implements DetailRecord, OnInit { - /** Observable resolving record data */ + // Observable resolving record data record$: Observable; - /** Resource type */ + // Resource type type: string; - /** Record data */ + // Record data record: any; - constructor(private titleMetaService: TitleMetaService) { } + /** + * Constructor + * + * @param _titleMetaService Title meta service. + */ + constructor(private _titleMetaService: TitleMetaService) { } + /** + * Component initialization. + * + * Set meta title. + * Subscribe to record observable. + */ ngOnInit(): void { - this.titleMetaService.setTitle('Detail of ' + this.type); + this._titleMetaService.setTitle('Detail of ' + this.type); + this.record$.subscribe((record) => { this.record = record; }); diff --git a/projects/ng-core-tester/src/app/record/document/document.component.html b/projects/ng-core-tester/src/app/record/document/document.component.html index 70bad5fd..7867923a 100644 --- a/projects/ng-core-tester/src/app/record/document/document.component.html +++ b/projects/ng-core-tester/src/app/record/document/document.component.html @@ -15,21 +15,21 @@  along with this program. If not, see . -->
- - - {{ record.metadata.title[0].mainTitle[0].value }} - - - - {{ record.metadata.title[0].mainTitle[0].value }} - - - - + + {{ record.metadata.title[0].mainTitle[0].value }} + + + + {{ record.metadata.title[0].mainTitle[0].value }} + + + + {{ record.metadata.title[0].mainTitle[0].value }} +

- {{ author.name }} + {{ author.name }}

{{ record.metadata.abstracts[0].value | truncateText:30 }}
diff --git a/projects/ng-core-tester/src/app/record/document/document.component.ts b/projects/ng-core-tester/src/app/record/document/document.component.ts index d7a54a73..06727f1a 100644 --- a/projects/ng-core-tester/src/app/record/document/document.component.ts +++ b/projects/ng-core-tester/src/app/record/document/document.component.ts @@ -17,31 +17,38 @@ import { Component, Input, OnInit } from '@angular/core'; import { ResultItem, TitleMetaService } from '@rero/ng-core'; +/** + * Component for displaying a document brief view. + */ @Component({ templateUrl: './document.component.html' }) - export class DocumentComponent implements OnInit, ResultItem { - + // Record data. @Input() record: any; + // Type of resource. @Input() type: string; + // Object containing link to detail. @Input() detailUrl: { link: string, external: boolean }; /** * Constructor - * @param titleMetaService - TitleMetaService + * + * @param _titleMetaService TitleMetaService */ - constructor(private titleMetaService: TitleMetaService) { } + constructor(private _titleMetaService: TitleMetaService) { } /** - * On Init + * Component initialization. + * + * Set meta title. */ - ngOnInit(): void { - this.titleMetaService.setTitle(this.type); + ngOnInit() { + this._titleMetaService.setTitle(this.type); } } diff --git a/projects/ng-core-tester/src/app/routes/documents-route.ts b/projects/ng-core-tester/src/app/routes/documents-route.ts index 3863555c..d24fc0bb 100644 --- a/projects/ng-core-tester/src/app/routes/documents-route.ts +++ b/projects/ng-core-tester/src/app/routes/documents-route.ts @@ -28,14 +28,17 @@ import { Observable, of } from 'rxjs'; import { DetailComponent } from '../record/document/detail/detail.component'; import { DocumentComponent } from '../record/document/document.component'; +/** + * Routes for document resources + */ export class DocumentsRoute implements RouteInterface { - - /** Route name */ + // Route name readonly name = 'documents'; /** - * Get Configuration - * @return Object + * Get Configuration. + * + * @return Configuration object. */ getConfiguration() { return { @@ -88,7 +91,7 @@ export class DocumentsRoute implements RouteInterface { formFieldMap: (field: FormlyFieldConfig, jsonSchema: JSONSchema7): FormlyFieldConfig => { // Populates each select with custom options if (field.type === 'enum') { - field.templateOptions.options = [ { label: 'Option 1', value: '1' }, { label: 'Option 2', value: '2' } ]; + field.templateOptions.options = [{ label: 'Option 1', value: '1' }, { label: 'Option 2', value: '2' }]; } return field; }, diff --git a/projects/ng-core-tester/src/app/routes/route.service.ts b/projects/ng-core-tester/src/app/routes/route.service.ts index 729f46e6..cb425544 100644 --- a/projects/ng-core-tester/src/app/routes/route.service.ts +++ b/projects/ng-core-tester/src/app/routes/route.service.ts @@ -19,31 +19,33 @@ import { Router } from '@angular/router'; import { RouteCollectionService } from '@rero/ng-core'; import { DocumentsRoute } from './documents-route'; +/** + * Service for managing routes. + */ @Injectable({ providedIn: 'root' }) export class RouteService { - /** - * Constructor - * @param routeCollectionService - RouteCollectionService - * @param router - Router - * @param routeToolService - RouteToolService + * Constructor. + * + * @param _routeCollectionService RouteCollectionService. + * @param _router Router. */ constructor( - private routeCollectionService: RouteCollectionService, - private router: Router + private _routeCollectionService: RouteCollectionService, + private _router: Router ) { } /** - * Initialize routes + * Initialize routes. */ initializeRoutes() { - this.routeCollectionService + this._routeCollectionService .addRoute(new DocumentsRoute()); - this.routeCollectionService.getRoutes().map((route: any) => { - this.router.config.push(route); + this._routeCollectionService.getRoutes().map((route: any) => { + this._router.config.push(route); }); } } diff --git a/projects/ng-core-tester/src/app/search-bar/search-bar.component.ts b/projects/ng-core-tester/src/app/search-bar/search-bar.component.ts index b45ea519..455cb1e2 100644 --- a/projects/ng-core-tester/src/app/search-bar/search-bar.component.ts +++ b/projects/ng-core-tester/src/app/search-bar/search-bar.component.ts @@ -17,24 +17,33 @@ import { Component, Input, OnInit } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; +/** + * Component showing the search bar for searching records. + */ @Component({ selector: 'app-search-bar', templateUrl: './search-bar.component.html' }) export class SearchBarComponent implements OnInit { - + // Code of the organisation. @Input() viewcode: string; - @Input() size: string = undefined; - @Input() maxLengthSuggestion = 100; + // Size. + @Input() size: string = undefined; - get action() { - return `/records/documents`; - } + // Suggestions max length. + @Input() maxLengthSuggestion = 100; + // List of resource type recordTypes = []; - static getPersonName(metadata) { + /** + * Returns person name for given metadata. + * + * @param metadata Metadata. + * @return Person name. + */ + static getPersonName(metadata: string) { for (const source of ['rero', 'bnf', 'gnd']) { if (metadata[source] && metadata[source].preferred_name_for_person) { return metadata[source].preferred_name_for_person; @@ -42,34 +51,59 @@ export class SearchBarComponent implements OnInit { } } - constructor(private translateService: TranslateService) { - } + /** + * Constructor. + * + * @param _translateService Translate service. + */ + constructor(private _translateService: TranslateService) { } + /** + * Component initialization. + * + * Initializes record types. + */ ngOnInit() { this.recordTypes = [{ type: 'documents', field: 'title', - getSuggestions: (query, persons) => this.getDocumentsSuggestions(query, persons), - preFilters: this.viewcode ? {view: this.viewcode} : {} + getSuggestions: (query: string, persons: any) => this.getDocumentsSuggestions(query, persons), + preFilters: this.viewcode ? { view: this.viewcode } : {} }, { type: 'institutions', field: 'name', - getSuggestions: (query, persons) => this.getInstitutionsSuggestions(query, persons), + getSuggestions: (query: string, persons: any) => this.getInstitutionsSuggestions(query, persons), component: this, - preFilters: this.viewcode ? {view: this.viewcode} : {} + preFilters: this.viewcode ? { view: this.viewcode } : {} }]; } - getInstitutionsSuggestions(query, institutions) { + /** + * Link to record search. + * + * @return Link to record search. + */ + get action(): string { + return `/records/documents`; + } + + /** + * Return a list of suggestions for organisations. + * + * @param query String query. + * @param institutions List of institutions. + * @return List of suggestions. + */ + getInstitutionsSuggestions(query: string, institutions: any): Array { const values = []; - institutions.hits.hits.map(hit => { + institutions.hits.hits.map((hit: any) => { let text = hit.metadata.name; text = text.replace(new RegExp(query, 'gi'), `${query}`); values.push({ text, query: '', index: 'institutions', - category: this.translateService.instant('direct links'), + category: this._translateService.instant('direct links'), href: `/records/institutions/detail/${hit.metadata.pid}`, iconCssClass: 'fa fa-bank' }); @@ -77,9 +111,16 @@ export class SearchBarComponent implements OnInit { return values; } - getDocumentsSuggestions(query, documents) { + /** + * Return a list of suggestions for documents. + * + * @param query String query. + * @param institutions List of documents. + * @return List of suggestions. + */ + getDocumentsSuggestions(query: string, documents: any): Array { const values = []; - documents.hits.hits.map(hit => { + documents.hits.hits.map((hit: any) => { let text = hit.metadata.title; let truncate = false; if (text.length > this.maxLengthSuggestion) { @@ -94,7 +135,7 @@ export class SearchBarComponent implements OnInit { text, query: hit.metadata.title.replace(/[:\-\[\]()/"]/g, ' ').replace(/\s\s+/g, ' '), index: 'documents', - category: this.translateService.instant('documents') + category: this._translateService.instant('documents') // href: `/${this.viewcode}/documents/${hit.metadata.pid}` }); }); diff --git a/projects/rero/ng-core/src/lib/api/api.service.ts b/projects/rero/ng-core/src/lib/api/api.service.ts index 5edd4b82..02a04b9d 100644 --- a/projects/rero/ng-core/src/lib/api/api.service.ts +++ b/projects/rero/ng-core/src/lib/api/api.service.ts @@ -26,35 +26,32 @@ import { CoreConfigService } from '../core-config.service'; } ) export class ApiService { - /** - * API base URL. - * - * Ex: https://localhost:5000 - */ - public baseUrl = ''; + // API base URL. Ex: https://localhost:5000. + baseUrl = ''; - /** - * API prefix - * - * Ex: /api - */ - public endpointPrefix = '/'; + // API prefix. Ex: /api + endpointPrefix = '/'; /** - * Constructor - * @param config - Config, global configuration + * Constructor. + * + * Initializes base URL and endpoint API prefix. + * + * @param _configService Configuration service. */ - constructor(private configService: CoreConfigService) { - this.baseUrl = this.configService.apiBaseUrl; - this.endpointPrefix = this.configService.apiEndpointPrefix; + constructor(private _configService: CoreConfigService) { + this.baseUrl = this._configService.apiBaseUrl; + this.endpointPrefix = this._configService.apiEndpointPrefix; } /** - * Return invenio API Endpoint corresponding to type. - * @param type - string, type of the resource - * @param absolute - boolean, if absolute or relative url must be returned. + * Returns invenio API Endpoint corresponding to type. + * + * @param type Type of the resource. + * @param absolute If absolute or relative url must be returned. + * @return Endpoint as string. */ - public getEndpointByType(type: string, absolute: boolean = false) { + getEndpointByType(type: string, absolute: boolean = false): string { let endpoint = this.endpointPrefix + '/' + type; if (absolute === true) { @@ -65,27 +62,30 @@ export class ApiService { } /** - * Returne $ref endpoint to resource - * @param type - string, type of resource - * @param id - string id of the record + * Returns $ref endpoint to resource. + * + * @param type Type of resource. + * @param id Id of the record. + * @return Ref endpoint as string. */ - getRefEndpoint(type: string, id: string) { - return `${this.configService.$refPrefix}${this.endpointPrefix}/${type}/${id}`; + getRefEndpoint(type: string, id: string): string { + return `${this._configService.$refPrefix}${this.endpointPrefix}/${type}/${id}`; } /** - * Return invenio API FormOption Endpoint corresponding to type. - * @param type - string, type of the resource - * @param absolute - boolean, if absolute or relative url must be returned. + * Returns invenio API FormOption Endpoint corresponding to type. + * + * @param type Type of the resource + * @param absolute If absolute or relative url must be returned. + * @return Schema form endpoint. */ - public getSchemaFormEndpoint(type: string, absolute: boolean = false) { - let endpoint = this.configService.schemaFormEndpoint + '/' + type; + getSchemaFormEndpoint(type: string, absolute: boolean = false): string { + let endpoint = this._configService.schemaFormEndpoint + '/' + type; if (absolute === true) { endpoint = this.baseUrl + endpoint; } return endpoint; - } } diff --git a/projects/rero/ng-core/src/lib/core-config.service.ts b/projects/rero/ng-core/src/lib/core-config.service.ts index 393cb598..4485494d 100644 --- a/projects/rero/ng-core/src/lib/core-config.service.ts +++ b/projects/rero/ng-core/src/lib/core-config.service.ts @@ -16,6 +16,9 @@ */ import { Injectable } from '@angular/core'; +/** + * Interface for configuration. + */ export interface Config { production?: boolean; prefixWindow?: string; @@ -34,6 +37,9 @@ export interface Config { }; } +/** + * Service for managing configuration of the application. + */ @Injectable({ providedIn: 'root' }) diff --git a/projects/rero/ng-core/src/lib/dialog/dialog.component.ts b/projects/rero/ng-core/src/lib/dialog/dialog.component.ts index 299f8181..2b9b4c45 100644 --- a/projects/rero/ng-core/src/lib/dialog/dialog.component.ts +++ b/projects/rero/ng-core/src/lib/dialog/dialog.component.ts @@ -18,43 +18,31 @@ import { Component, OnInit } from '@angular/core'; import { BsModalRef } from 'ngx-bootstrap/modal'; import { Subject } from 'rxjs'; +/** + * Show dialog modal + */ @Component({ selector: 'ng-core-dialog', templateUrl: './dialog.component.html' }) -/** - * Show dialog modal - */ export class DialogComponent implements OnInit { - /** - * Title of the modal. - */ - public title: string; + // Title of the modal. + title: string; - /** - * Content of the modal, can be html. - */ - public body: string; + // Content of the modal, can be html. + body: string; - /** - * Show button to confirm action. - */ - public confirmButton = true; + // Show button to confirm action. + confirmButton = true; - /** - * Label of cancel button - */ - public cancelTitleButton: string; + // Label of cancel button. + cancelTitleButton: string; - /** - * Label of confirmation button - */ - public confirmTitleButton: string; + // Label of confirmation button. + confirmTitleButton: string; - /** - * Event triggered when modal is closed. - */ - public onClose: Subject; + // Event triggered when modal is closed. + onClose: Subject; /** * Constructor @@ -64,6 +52,8 @@ export class DialogComponent implements OnInit { /** * Component init + * + * Initializes subject when the dialog is closed. */ ngOnInit() { this.onClose = new Subject(); @@ -72,7 +62,7 @@ export class DialogComponent implements OnInit { /** * Confirm action. */ - confirm(): void { + confirm() { this.onClose.next(true); this._bsModalRef.hide(); } @@ -80,7 +70,7 @@ export class DialogComponent implements OnInit { /** * Cancel action */ - decline(): void { + decline() { this.onClose.next(false); this._bsModalRef.hide(); } diff --git a/projects/rero/ng-core/src/lib/dialog/dialog.service.ts b/projects/rero/ng-core/src/lib/dialog/dialog.service.ts index c016bde3..1461965c 100644 --- a/projects/rero/ng-core/src/lib/dialog/dialog.service.ts +++ b/projects/rero/ng-core/src/lib/dialog/dialog.service.ts @@ -18,15 +18,26 @@ import { Injectable } from '@angular/core'; import { BsModalService } from 'ngx-bootstrap'; import { DialogComponent } from './dialog.component'; +/** + * Service for displaying a dialog box. + */ @Injectable({ providedIn: 'root' }) export class DialogService { + /** + * + * @param _modalService Bootstrap modal service. + */ + constructor(private _modalService: BsModalService) { } - constructor(private modalService: BsModalService) { } - - public show(config: any) { - const bsModalRef = this.modalService.show(DialogComponent, config); + /** + * Show the dialog box configured by the given config. + * + * @param config Configuration object. + */ + show(config: any) { + const bsModalRef = this._modalService.show(DialogComponent, config); return bsModalRef.content.onClose; } } diff --git a/projects/rero/ng-core/src/lib/pipe/callback-array-filter.pipe.ts b/projects/rero/ng-core/src/lib/pipe/callback-array-filter.pipe.ts index a0749c43..9ede2fd1 100644 --- a/projects/rero/ng-core/src/lib/pipe/callback-array-filter.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/callback-array-filter.pipe.ts @@ -16,16 +16,24 @@ */ import { Pipe, PipeTransform } from '@angular/core'; +/** + * Pipe for applying a callback function to filter array items. + */ @Pipe({ name: 'callbackArrayFilter' }) export class CallbackArrayFilterPipe implements PipeTransform { - - transform(items: any[], callback: (item: any) => boolean): any { + /** + * Filter array items with the given callback function. + * + * @param items List of items. + * @param callback Callback function to apply. + * @return List of filtered values. + */ + transform(items: any[], callback: (item: any) => boolean): Array { if (!items || !callback) { return items; } return items.filter(item => callback(item)); } - } diff --git a/projects/rero/ng-core/src/lib/pipe/default.pipe.ts b/projects/rero/ng-core/src/lib/pipe/default.pipe.ts index 5b8bd012..3c670658 100644 --- a/projects/rero/ng-core/src/lib/pipe/default.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/default.pipe.ts @@ -16,8 +16,18 @@ */ import { Pipe, PipeTransform } from '@angular/core'; +/** + * Pipe for returning a default value if the given value is null or undefined. + */ @Pipe({name: 'default', pure: true}) export class DefaultPipe implements PipeTransform { + /** + * Returns a default value. + * + * @param value Value to check. + * @param defaultValue Value to return if value is null. + * @return Value or default value. + */ transform(value: any, defaultValue: any): any { return value || defaultValue; } diff --git a/projects/rero/ng-core/src/lib/pipe/get-record.pipe.ts b/projects/rero/ng-core/src/lib/pipe/get-record.pipe.ts index 11dbe732..814713ba 100644 --- a/projects/rero/ng-core/src/lib/pipe/get-record.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/get-record.pipe.ts @@ -19,13 +19,29 @@ import { map } from 'rxjs/operators'; import { RecordService } from '../record/record.service'; import { extractIdOnRef } from '../utils/utils'; +/** + * Get a record by its PID. + */ @Pipe({ name: 'getRecord' }) export class GetRecordPipe implements PipeTransform { + /** + * Constructor. + * + * @param _recordService Record service. + */ + constructor(private _recordService: RecordService) { } - constructor(private recordService: RecordService) {} - + /** + * Return record data corresponding to PID. + * + * @param pid Record PID. + * @param type Type of the resource. + * @param returnType Type of data to return. + * @param field Field to return. + * @return Record or field record corresponding to PID. + */ transform(pid: any, type: string, returnType = 'object', field?: string): any { // process $ref entrypoint if (pid.startsWith('http')) { @@ -36,7 +52,7 @@ export class GetRecordPipe implements PipeTransform { returnType = 'field'; } - return this.recordService.getRecord(type, pid, 1).pipe(map(data => { + return this._recordService.getRecord(type, pid, 1).pipe(map(data => { if (!data) { return null; } diff --git a/projects/rero/ng-core/src/lib/pipe/nl2br.pipe.ts b/projects/rero/ng-core/src/lib/pipe/nl2br.pipe.ts index 95eb626d..a140a71e 100644 --- a/projects/rero/ng-core/src/lib/pipe/nl2br.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/nl2br.pipe.ts @@ -17,16 +17,29 @@ import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; +/** + * Pipe for converting carriage returns to
html entities. + */ @Pipe({ name: 'nl2br' }) export class Nl2brPipe implements PipeTransform { + /** + * Constructor. + * + * @param _sanitizer Dom sanitizer. + */ + constructor(private _sanitizer: DomSanitizer) { } - public constructor(public sanitizer: DomSanitizer) { } - + /** + * Returns transformed value containing
entities. + * + * @param value Value to transform. + * @return Transformed value. + */ transform(value: string): any { if (!value) { - return this.sanitizer.bypassSecurityTrustHtml(''); + return this._sanitizer.bypassSecurityTrustHtml(''); } - return this.sanitizer.bypassSecurityTrustHtml( + return this._sanitizer.bypassSecurityTrustHtml( value.replace(/\r\n?|\n/g, '
\n') ); } diff --git a/projects/rero/ng-core/src/lib/pipe/truncate-text.pipe.ts b/projects/rero/ng-core/src/lib/pipe/truncate-text.pipe.ts index 40645c5d..4bd76fcc 100644 --- a/projects/rero/ng-core/src/lib/pipe/truncate-text.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/truncate-text.pipe.ts @@ -16,11 +16,21 @@ */ import { Pipe, PipeTransform } from '@angular/core'; +/** + * Pipe for truncating text. + */ @Pipe({ name: 'truncateText' }) export class TruncateTextPipe implements PipeTransform { - + /** + * Truncate text. + * + * @param value Text to truncate. + * @param limit Limit after which the text is truncated. + * @param trail Trailing chars + * @return Truncated string + */ transform(value: string, limit: number = 40, trail: string = '…'): string { let result = value || ''; diff --git a/projects/rero/ng-core/src/lib/pipe/ucfirst.pipe.ts b/projects/rero/ng-core/src/lib/pipe/ucfirst.pipe.ts index 2e847a17..d17f9da1 100644 --- a/projects/rero/ng-core/src/lib/pipe/ucfirst.pipe.ts +++ b/projects/rero/ng-core/src/lib/pipe/ucfirst.pipe.ts @@ -20,14 +20,20 @@ import { Pipe, PipeTransform } from '@angular/core'; * Uppercase the first letter of the string. */ @Pipe({ - name: 'ucfirst' + name: 'ucfirst' }) export class UpperCaseFirstPipe implements PipeTransform { - transform(value: string): string { - if (value === null) { - return value; - } - - return value.charAt(0).toUpperCase() + value.slice(1); + /** + * Uppercase the first letter of the given value. + * + * @param value Value to transform. + * @return Transformed value. + */ + transform(value: string): string { + if (value === null) { + return value; } + + return value.charAt(0).toUpperCase() + value.slice(1); + } } diff --git a/projects/rero/ng-core/src/lib/record/action-status.ts b/projects/rero/ng-core/src/lib/record/action-status.ts index 9288e9c3..b9d33715 100644 --- a/projects/rero/ng-core/src/lib/record/action-status.ts +++ b/projects/rero/ng-core/src/lib/record/action-status.ts @@ -14,6 +14,10 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + +/** + * Interface representing an action status for permission check. + */ export interface ActionStatus { can: boolean; message: string; diff --git a/projects/rero/ng-core/src/lib/record/autocomplete/autocomplete.component.ts b/projects/rero/ng-core/src/lib/record/autocomplete/autocomplete.component.ts index b8dabd96..30dcd42f 100644 --- a/projects/rero/ng-core/src/lib/record/autocomplete/autocomplete.component.ts +++ b/projects/rero/ng-core/src/lib/record/autocomplete/autocomplete.component.ts @@ -26,79 +26,82 @@ import { RecordService } from '../record.service'; templateUrl: './autocomplete.component.html' }) export class AutocompleteComponent implements OnInit { - /** The current form object from the template. */ - @ViewChild('form', { static: false }) form; - - /** The current selected suggestion. */ - asyncSelected = { - text: undefined, - query: undefined, - index: undefined, - category: undefined, - href: undefined - }; - - /** The submit button css class. */ - @Input() buttonCssClass = 'btn btn-light'; + // The submit button css class. + @Input() + buttonCssClass = 'btn btn-light'; - /** The remote suggestions loading status. */ - typeaheadLoading: boolean; + // The form action i.e. '/search' + @Input() + action: string; - /** The remote suggestions list. */ - dataSource: Observable; + // The autocomplete record type configuration. + @Input() + recordTypes: Array = []; - /** The form action i.e. '/search' */ - @Input() action: string; + // The search input field size: small or large + @Input() + size: string; - /** The autocomplete record type configuration. */ + // The search input field placeholder. @Input() - recordTypes: Array = []; + placeholder: string; - /** The search input field size: small or large */ - @Input() size: string; + // The routing mode, angular for internal or href for external. + @Input() + internalRouting = true; - /** The search input field placeholder. */ - @Input() placeholder: string; + // The minimal number of characters that needs to be entered before typeahead kicks-in. + @Input() + typeaheadMinLength = 3; - /** The routing mode, angular for internal or href for external. */ - @Input() internalRouting = true; + // The minimal wait time after last character typed before typeahead kicks-in. + @Input() + typeaheadWaitMs = 300; - // debug information - // @Input() displayScore = undefined; + // The maximum length of options items list. The default value is 20. + @Input() typeaheadOptionsLimit = 10; - /** The minimal number of characters that needs to be entered before typeahead kicks-in. */ - @Input() typeaheadMinLength = 3; + // The current selected suggestion. + asyncSelected = { + text: undefined, + query: undefined, + index: undefined, + category: undefined, + href: undefined + }; - /** The minimal wait time after last character typed before typeahead kicks-in. */ - @Input() typeaheadWaitMs = 300; + // The remote suggestions loading status. + typeaheadLoading: boolean; - /** The maximum length of options items list. The default value is 20. */ - @Input() typeaheadOptionsLimit = 10; + // The remote suggestions list. + dataSource: Observable; // store a current URL redirection - private redirect = false; + private _redirect = false; + + // The current form object from the template. + @ViewChild('form', { static: false }) + form: any; /** - * Constructor - * @param recordService - REST API record service - * @param route - Angular current route - * @param router - Angular router for navigation + * Constructor. + * + * @param _recordService - REST API record service + * @param _route - Angular current route + * @param _router - Angular router for navigation */ constructor( - private recordService: RecordService, - private route: ActivatedRoute, - private router: Router - ) {} + private _recordService: RecordService, + private _route: ActivatedRoute, + private _router: Router + ) { } /** * On init hook */ ngOnInit() { - this.route.queryParamMap.subscribe((params: any) => { - // if (params.get('display_score')) { - // this.displayScore = params.get('display_score'); - // } - if (this.action === this.router.url.split('?')[0]) { + this._route.queryParamMap.subscribe((params: any) => { + if (this.action === this._router.url.split('?')[0]) { // get the query form the URL const query = params.get('q'); if (query) { @@ -126,11 +129,11 @@ export class AutocompleteComponent implements OnInit { * Apply search action * @param event - Event, DOM event */ - doSearch(event) { + doSearch(event: any) { event.preventDefault(); - if (!this.redirect) { + if (!this._redirect) { if (this.internalRouting) { - this.router.navigate([this.action], { + this._router.navigate([this.action], { queryParams: { q: this.asyncSelected.query, page: '1', size: '10' } }); } else { @@ -152,7 +155,7 @@ export class AutocompleteComponent implements OnInit { const recordTypesKeys = this.recordTypes.map(recordType => recordType.type); this.recordTypes.forEach(recordType => { combineGetRecords.push( - this.recordService.getRecords( + this._recordService.getRecords( recordType.type, `${recordType.field}:${query}`, 1, @@ -196,11 +199,11 @@ export class AutocompleteComponent implements OnInit { typeaheadOnSelect(e: TypeaheadMatch): void { if (e.item.href) { if (this.internalRouting) { - this.router.navigate([e.item.href]); + this._router.navigate([e.item.href]); } else { window.location.href = e.item.href; } - this.redirect = true; + this._redirect = true; } } } diff --git a/projects/rero/ng-core/src/lib/record/detail/detail.component.ts b/projects/rero/ng-core/src/lib/record/detail/detail.component.ts index 5e41253e..5eb25add 100644 --- a/projects/rero/ng-core/src/lib/record/detail/detail.component.ts +++ b/projects/rero/ng-core/src/lib/record/detail/detail.component.ts @@ -79,17 +79,18 @@ export class DetailComponent implements OnInit { /** * Directive for displaying record */ - @ViewChild(RecordDetailDirective, { static: true }) recordDetail: RecordDetailDirective; + @ViewChild(RecordDetailDirective, { static: true }) + recordDetail: RecordDetailDirective; constructor( - private route: ActivatedRoute, - private router: Router, - private location: Location, - private componentFactoryResolver: ComponentFactoryResolver, - private recordService: RecordService, - private recordUiService: RecordUiService, - private toastrService: ToastrService, - private translate: TranslateService + private _route: ActivatedRoute, + private _router: Router, + private _location: Location, + private _componentFactoryResolver: ComponentFactoryResolver, + private _recordService: RecordService, + private _recordUiService: RecordUiService, + private _toastrService: ToastrService, + private _translate: TranslateService ) { } /** @@ -98,37 +99,37 @@ export class DetailComponent implements OnInit { ngOnInit() { this.loadViewComponentRef(); - const pid = this.route.snapshot.paramMap.get('pid'); - const type = this.route.snapshot.paramMap.get('type'); + const pid = this._route.snapshot.paramMap.get('pid'); + const type = this._route.snapshot.paramMap.get('type'); - this.recordUiService.types = this.route.snapshot.data.types; - const config = this.recordUiService.getResourceConfig(type); + this._recordUiService.types = this._route.snapshot.data.types; + const config = this._recordUiService.getResourceConfig(type); - this.record$ = this.recordService.getRecord(type, pid, 1, config.itemHeaders || null); + this.record$ = this._recordService.getRecord(type, pid, 1, config.itemHeaders || null); this.record$.subscribe( (record) => { this.record = record; - this.recordUiService.canReadRecord$(this.record, type).subscribe(result => { + this._recordUiService.canReadRecord$(this.record, type).subscribe(result => { if (result.can === false) { - this.toastrService.error( - this.translate.instant('You cannot read this record'), - this.translate.instant(type) + this._toastrService.error( + this._translate.instant('You cannot read this record'), + this._translate.instant(type) ); - this.location.back(); + this._location.back(); } }); - this.recordUiService.canDeleteRecord$(this.record, type).subscribe(result => { + this._recordUiService.canDeleteRecord$(this.record, type).subscribe(result => { this.deleteStatus = result; }); - this.recordUiService.canUpdateRecord$(this.record, type).subscribe(result => { + this._recordUiService.canUpdateRecord$(this.record, type).subscribe(result => { this.updateStatus = result; }); - if (this.route.snapshot.data.adminMode) { - this.route.snapshot.data.adminMode().subscribe((am: ActionStatus) => this.adminMode = am); + if (this._route.snapshot.data.adminMode) { + this._route.snapshot.data.adminMode().subscribe((am: ActionStatus) => this.adminMode = am); } }, (error) => { @@ -142,8 +143,8 @@ export class DetailComponent implements OnInit { /** * Go back to previous page */ - public goBack() { - this.location.back(); + goBack() { + this._location.back(); } /** @@ -151,10 +152,10 @@ export class DetailComponent implements OnInit { * @param event - DOM event * @param pid - string, PID to remove */ - public deleteRecord(pid: string) { - this.recordUiService.deleteRecord(this.route.snapshot.paramMap.get('type'), pid).subscribe((result: any) => { + deleteRecord(pid: string) { + this._recordUiService.deleteRecord(this._route.snapshot.paramMap.get('type'), pid).subscribe((result: any) => { if (result === true) { - this.router.navigate(['../..'], {relativeTo: this.route}); + this._router.navigate(['../..'], {relativeTo: this._route}); } }); } @@ -164,34 +165,34 @@ export class DetailComponent implements OnInit { * @param event - DOM event * @param message - message to display into modal */ - public showDeleteMessage(message: string) { - this.recordUiService.showDeleteMessage(message); + showDeleteMessage(message: string) { + this._recordUiService.showDeleteMessage(message); } /** * Dynamically load component depending on selected resource type. */ private loadRecordView() { - const componentFactory = this.componentFactoryResolver + const componentFactory = this._componentFactoryResolver .resolveComponentFactory(this.viewComponent ? this.viewComponent : JsonComponent); const viewContainerRef = this.recordDetail.viewContainerRef; viewContainerRef.clear(); const componentRef = viewContainerRef.createComponent(componentFactory); (componentRef.instance as JsonComponent).record$ = this.record$; - (componentRef.instance as JsonComponent).type = this.route.snapshot.paramMap.get('type'); + (componentRef.instance as JsonComponent).type = this._route.snapshot.paramMap.get('type'); } /** * Load component view corresponding to type */ private loadViewComponentRef() { - if (!this.route.snapshot.data.types || this.route.snapshot.data.types.length === 0) { + if (!this._route.snapshot.data.types || this._route.snapshot.data.types.length === 0) { throw new Error('Configuration types not passed to component'); } - const type = this.route.snapshot.paramMap.get('type'); - const types = this.route.snapshot.data.types; + const type = this._route.snapshot.paramMap.get('type'); + const types = this._route.snapshot.data.types; const index = types.findIndex((item: any) => item.key === type); diff --git a/projects/rero/ng-core/src/lib/record/detail/detail.directive.ts b/projects/rero/ng-core/src/lib/record/detail/detail.directive.ts index a94ecb4c..9fb511cc 100644 --- a/projects/rero/ng-core/src/lib/record/detail/detail.directive.ts +++ b/projects/rero/ng-core/src/lib/record/detail/detail.directive.ts @@ -16,6 +16,9 @@ */ import { Directive, Input, ViewContainerRef } from '@angular/core'; +/** + * Directive for displaying a record detail. + */ @Directive({ selector: '[ngCoreRecordDetail]', }) @@ -32,5 +35,17 @@ export class RecordDetailDirective { @Input() type: string; - constructor(public viewContainerRef: ViewContainerRef) { } + /** + * Constructor. + * + * @param _viewContainerRef View container reference + */ + constructor(private _viewContainerRef: ViewContainerRef) { } + + /** + * Returns view container reference. + */ + get viewContainerRef(): ViewContainerRef { + return this._viewContainerRef; + } } diff --git a/projects/rero/ng-core/src/lib/record/detail/view/detail-record.ts b/projects/rero/ng-core/src/lib/record/detail/view/detail-record.ts index b93073fa..e60aac9a 100644 --- a/projects/rero/ng-core/src/lib/record/detail/view/detail-record.ts +++ b/projects/rero/ng-core/src/lib/record/detail/view/detail-record.ts @@ -16,10 +16,13 @@ */ import { Observable } from 'rxjs'; +/** + * Interface represneting a record detail. + */ export interface DetailRecord { - /** Observable resolving record data */ + // Observable resolving record data record$: Observable; - /** Resource type */ + // Resource type type: string; } diff --git a/projects/rero/ng-core/src/lib/record/detail/view/json.component.ts b/projects/rero/ng-core/src/lib/record/detail/view/json.component.ts index 6a601865..989b652a 100644 --- a/projects/rero/ng-core/src/lib/record/detail/view/json.component.ts +++ b/projects/rero/ng-core/src/lib/record/detail/view/json.component.ts @@ -18,6 +18,9 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { DetailRecord } from './detail-record'; +/** + * Component to display a record by dumping its data to JSON. + */ @Component({ template: ` @@ -27,21 +30,20 @@ import { DetailRecord } from './detail-record'; ` }) export class JsonComponent implements DetailRecord, OnInit { - /** - * Observable resolving record data - */ + // Observable resolving record data record$: Observable; - /** - * Resource type - */ + // Resource type type: string; - /** - * Record data - */ + // Record data record: any; + /** + * Component initialization. + * + * Subscribes to observable for getting the record. + */ ngOnInit(): void { this.record$.subscribe((record) => { this.record = record; diff --git a/projects/rero/ng-core/src/lib/record/editor/add-field-editor/add-field-editor.component.ts b/projects/rero/ng-core/src/lib/record/editor/add-field-editor/add-field-editor.component.ts index 48c6c7df..21832220 100644 --- a/projects/rero/ng-core/src/lib/record/editor/add-field-editor/add-field-editor.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/add-field-editor/add-field-editor.component.ts @@ -49,10 +49,10 @@ export class AddFieldEditorComponent implements OnInit { /*** * Constructor - * @param editorService - EditorService, that keep the list of hidden fields + * @param _editorService - EditorService, that keep the list of hidden fields */ constructor( - private editorService: EditorService + private _editorService: EditorService ) {} /*** @@ -60,8 +60,8 @@ export class AddFieldEditorComponent implements OnInit { */ ngOnInit() { // avoid duplicate when switching between page - this.editorService.clearHiddenFields(); - this.typeaheadFields$ = this.editorService.hiddenFields$.pipe( + this._editorService.clearHiddenFields(); + this.typeaheadFields$ = this._editorService.hiddenFields$.pipe( map( (fields: FormlyFieldConfig[]) => { const value = fields.map(field => { return {name: field.templateOptions.label, field}; @@ -84,19 +84,19 @@ export class AddFieldEditorComponent implements OnInit { * Shows the selected field when it is selected * @param match - TyepeaheadMath, the selected element */ - showSelectedField(field) { + showSelectedField(field: any) { // show the field in the form field.hide = false; // reset the input value this.value = undefined; // remove the the element from the list of hidden fields - this.editorService.removeHiddenField(field); + this._editorService.removeHiddenField(field); // scroll at the right position // to avoid: Expression has changed after it was checked // See: https://blog.angular-university.io/angular-debugging/ // wait that the component is present in the DOM - setTimeout(() => this.editorService.setFocus(field, true)); + setTimeout(() => this._editorService.setFocus(field, true)); } /** diff --git a/projects/rero/ng-core/src/lib/record/editor/array-type/array-type.component.ts b/projects/rero/ng-core/src/lib/record/editor/array-type/array-type.component.ts index 73203513..f05ca962 100644 --- a/projects/rero/ng-core/src/lib/record/editor/array-type/array-type.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/array-type/array-type.component.ts @@ -17,6 +17,9 @@ import { Component, OnInit } from '@angular/core'; import { FieldArrayType, FormlyFieldConfig } from '@ngx-formly/core'; +/** + * Component for displaying array fields in editor. + */ @Component({ selector: 'ng-core-editor-formly-array-type', templateUrl: 'array-type.component.html' diff --git a/projects/rero/ng-core/src/lib/record/editor/dropdown-label-editor/dropdown-label-editor.component.ts b/projects/rero/ng-core/src/lib/record/editor/dropdown-label-editor/dropdown-label-editor.component.ts index 14905e4c..9e145bb2 100644 --- a/projects/rero/ng-core/src/lib/record/editor/dropdown-label-editor/dropdown-label-editor.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/dropdown-label-editor/dropdown-label-editor.component.ts @@ -17,6 +17,9 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { FormlyFieldConfig } from '@ngx-formly/core'; +/** + * Component for displaying a label with dropdown in editor. + */ @Component({ selector: 'ng-core-editor-dropdown-label-editor', templateUrl: './dropdown-label-editor.component.html' @@ -37,7 +40,7 @@ export class DropdownLabelEditorComponent { * Emit a new Ouput event when the add button is clicked * @param event - Event, the click event. */ - addClick(event) { + addClick(event: any) { this.addClicked.emit(event); } } diff --git a/projects/rero/ng-core/src/lib/record/editor/editor.component.spec.ts b/projects/rero/ng-core/src/lib/record/editor/editor.component.spec.ts index ef3b7129..9205b99f 100644 --- a/projects/rero/ng-core/src/lib/record/editor/editor.component.spec.ts +++ b/projects/rero/ng-core/src/lib/record/editor/editor.component.spec.ts @@ -55,7 +55,7 @@ const route = { } ], showSearchInput: true, - adminMode: true + adminMode: of({ message: '', can: true }) } }, queryParams: of({}) diff --git a/projects/rero/ng-core/src/lib/record/editor/editor.component.ts b/projects/rero/ng-core/src/lib/record/editor/editor.component.ts index 35f93395..e55ee35c 100644 --- a/projects/rero/ng-core/src/lib/record/editor/editor.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/editor.component.ts @@ -73,10 +73,10 @@ export class EditorComponent implements OnInit, OnDestroy { longMode = false; // current record type from the url - public recordType = null; + recordType = null; // store pid on edit mode - public pid = null; + pid = null; // subscribers private _subscribers: Subscription[] = []; @@ -85,19 +85,27 @@ export class EditorComponent implements OnInit, OnDestroy { private _resourceConfig: any; /** - * Constructor - * @param formlyJsonschema - FormlyJsonschema, the ngx-fomly jsonschema service + * Constructor. + * @param _formlyJsonschema Formly JSON schema. + * @param _recordService Record service. + * @param _apiService API service. + * @param _route Route. + * @param _editorService Editor service. + * @param _recordUiService Record UI service. + * @param _translateService Translate service. + * @param _toastrService Toast service. + * @param _location Location. */ constructor( - private formlyJsonschema: FormlyJsonschema, - private recordService: RecordService, - private apiService: ApiService, - private route: ActivatedRoute, - private editorService: EditorService, - private recordUiService: RecordUiService, - private translateService: TranslateService, - private toastrService: ToastrService, - private location: Location + private _formlyJsonschema: FormlyJsonschema, + private _recordService: RecordService, + private _apiService: ApiService, + private _route: ActivatedRoute, + private _editorService: EditorService, + private _recordUiService: RecordUiService, + private _translateService: TranslateService, + private _toastrService: ToastrService, + private _location: Location ) { this.form = new FormGroup({}); } @@ -106,7 +114,7 @@ export class EditorComponent implements OnInit, OnDestroy { * Component initialisation */ ngOnInit() { - combineLatest([this.route.params, this.route.queryParams]) + combineLatest([this._route.params, this._route.queryParams]) .subscribe(([params, queryParams]) => { // uncomment for debug // this.form.valueChanges.subscribe(v => @@ -114,38 +122,38 @@ export class EditorComponent implements OnInit, OnDestroy { // ); this.recordType = params.type; - this.recordUiService.types = this.route.snapshot.data.types; - this._resourceConfig = this.recordUiService.getResourceConfig(this.recordType); + this._recordUiService.types = this._route.snapshot.data.types; + this._resourceConfig = this._recordUiService.getResourceConfig(this.recordType); if (this._resourceConfig.editorLongMode === true) { this.longMode = true; this._subscribers.push( - this.editorService.hiddenFields$.subscribe(() => + this._editorService.hiddenFields$.subscribe(() => this.getTocFields() ) ); } this.pid = params.pid; - this.recordService + this._recordService .getSchemaForm(this.recordType) .subscribe(schemaform => { this.setSchema(schemaform.schema); }); // edition if (this.pid) { - this.recordService + this._recordService .getRecord(this.recordType, this.pid) .subscribe(record => { - this.recordUiService + this._recordUiService .canUpdateRecord$(record, this.recordType) .subscribe(result => { if (result.can === false) { - this.toastrService.error( - this.translateService.instant( + this._toastrService.error( + this._translateService.instant( 'You cannot update this record' ), - this.translateService.instant(this.recordType) + this._translateService.instant(this.recordType) ); - this.location.back(); + this._location.back(); } else { this._model = record.metadata; this.modelChange.emit(this._model); @@ -165,8 +173,12 @@ export class EditorComponent implements OnInit, OnDestroy { } } - - modelChanged(modelValue) { + /** + * Emit value when model is changed. + * + * @param modelValue Model. + */ + modelChanged(modelValue: any) { this.modelChange.emit(modelValue); } @@ -174,8 +186,8 @@ export class EditorComponent implements OnInit, OnDestroy { * Preprocess the record before passing it to the editor * @param record - Record object to preprocess */ - private preprocessRecord(record) { - const config = this.recordUiService.getResourceConfig(this.recordType); + private preprocessRecord(record: any) { + const config = this._recordUiService.getResourceConfig(this.recordType); if (config.preprocessRecordEditor) { return config.preprocessRecordEditor(record); @@ -188,7 +200,7 @@ export class EditorComponent implements OnInit, OnDestroy { * @param record - Record object to postprocess */ private postprocessRecord(record: any) { - const config = this.recordUiService.getResourceConfig(this.recordType); + const config = this._recordUiService.getResourceConfig(this.recordType); if (config.postprocessRecordEditor) { return config.postprocessRecordEditor(record); @@ -201,7 +213,7 @@ export class EditorComponent implements OnInit, OnDestroy { * @param record - Record object */ private preCreateRecord(record: any) { - const config = this.recordUiService.getResourceConfig(this.recordType); + const config = this._recordUiService.getResourceConfig(this.recordType); if (config.preCreateRecord) { return config.preCreateRecord(record); @@ -214,7 +226,7 @@ export class EditorComponent implements OnInit, OnDestroy { * @param record - Record object */ private preUpdateRecord(record: any) { - const config = this.recordUiService.getResourceConfig(this.recordType); + const config = this._recordUiService.getResourceConfig(this.recordType); if (config.preUpdateRecord) { return config.preUpdateRecord(record); @@ -226,14 +238,14 @@ export class EditorComponent implements OnInit, OnDestroy { * Preprocess the record before passing it to the editor * @param schema - object, JOSNSchemag */ - setSchema(schema) { + setSchema(schema: any) { // reorder all object properties this.schema = orderedJsonSchema(schema); this.options = {}; // form configuration const fields = [ - this.formlyJsonschema.toFieldConfig(this.schema, { + this._formlyJsonschema.toFieldConfig(this.schema, { // post process JSONSChema7 to FormlyFieldConfig conversion map: (field: FormlyFieldConfig, jsonSchema: JSONSchema7) => { /**** additionnal JSONSchema configurations *******/ @@ -252,7 +264,7 @@ export class EditorComponent implements OnInit, OnDestroy { // show the field if the model contains a value usefull for edition field.hooks = { ...field.hooks, - onPopulate: (f) => { + onPopulate: (f: any) => { this.hideShowEmptyField(f); } }; @@ -296,13 +308,13 @@ export class EditorComponent implements OnInit, OnDestroy { if (!modelEmpty && (field.hide !== false)) { setTimeout(() => { field.hide = false; - this.editorService.removeHiddenField(field); + this._editorService.removeHiddenField(field); }); } if (modelEmpty && (field.templateOptions.hide === true && field.hide === undefined)) { setTimeout(() => { field.hide = true; - this.editorService.addHiddenField(field); + this._editorService.addHiddenField(field); }); } } @@ -315,35 +327,35 @@ export class EditorComponent implements OnInit, OnDestroy { let data = removeEmptyValues(this.model); data = this.postprocessRecord(data); if (data.pid != null) { - this.recordService + this._recordService .update(this.recordType, this.preUpdateRecord(data)) .subscribe(record => { - this.toastrService.success( - this.translateService.instant('Record Updated!'), - this.translateService.instant(this.recordType) + this._toastrService.success( + this._translateService.instant('Record Updated!'), + this._translateService.instant(this.recordType) ); - this.recordUiService.redirectAfterSave( + this._recordUiService.redirectAfterSave( this.pid, record, this.recordType, 'update', - this.route + this._route ); }); } else { - this.recordService + this._recordService .create(this.recordType, this.preCreateRecord(data)) .subscribe(record => { - this.toastrService.success( - this.translateService.instant('Resource created'), - this.translateService.instant(this.recordType) + this._toastrService.success( + this._translateService.instant('Resource created'), + this._translateService.instant(this.recordType) ); - this.recordUiService.redirectAfterSave( + this._recordUiService.redirectAfterSave( record.metadata.pid, record, this.recordType, 'create', - this.route + this._route ); }); } @@ -354,9 +366,9 @@ export class EditorComponent implements OnInit, OnDestroy { * @param event - click DOM event * @param field - FormlyFieldConfig, the form config corresponding to the DOM element to jump to. */ - setFocus(event, field: FormlyFieldConfig) { + setFocus(event: any, field: FormlyFieldConfig) { event.preventDefault(); - this.editorService.setFocus(field, true); + this._editorService.setFocus(field, true); } /** @@ -373,8 +385,8 @@ export class EditorComponent implements OnInit, OnDestroy { /** * Cancel editing and back to previous page */ - public cancel() { - this.location.back(); + cancel() { + this._location.back(); } /********************* Private ***************************************/ @@ -395,16 +407,16 @@ export class EditorComponent implements OnInit, OnDestroy { afterContentInit: (f: FormlyFieldConfig) => { const recordType = formOptions.remoteOptions.type; const query = formOptions.remoteOptions.query ? formOptions.remoteOptions.query : ''; - f.templateOptions.options = this.recordService + f.templateOptions.options = this._recordService .getRecords(recordType, query, 1, RecordService.MAX_REST_RESULTS_SIZE) .pipe( map(data => - data.hits.hits.map(record => { + data.hits.hits.map((record: any) => { return { label: formOptions.remoteOptions.labelField && formOptions.remoteOptions.labelField in record.metadata ? record.metadata[formOptions.remoteOptions.labelField] : record.metadata.name, - value: this.apiService.getRefEndpoint( + value: this._apiService.getRefEndpoint( recordType, record.metadata.pid ) @@ -452,7 +464,7 @@ export class EditorComponent implements OnInit, OnDestroy { field.asyncValidators = { validation: [ (control: FormControl) => { - return this.recordService.uniqueValue( + return this._recordService.uniqueValue( field, remoteRecordType ? remoteRecordType : this.recordType, this.pid ? this.pid : null, diff --git a/projects/rero/ng-core/src/lib/record/editor/editor.service.ts b/projects/rero/ng-core/src/lib/record/editor/editor.service.ts index e33de7f5..8132b1cc 100644 --- a/projects/rero/ng-core/src/lib/record/editor/editor.service.ts +++ b/projects/rero/ng-core/src/lib/record/editor/editor.service.ts @@ -18,6 +18,9 @@ import { Injectable } from '@angular/core'; import { FormlyFieldConfig } from '@ngx-formly/core'; import { BehaviorSubject, Observable } from 'rxjs'; +/** + * Service for managing the editor. + */ @Injectable({ providedIn: 'root' }) diff --git a/projects/rero/ng-core/src/lib/record/editor/object-type/object-type.component.ts b/projects/rero/ng-core/src/lib/record/editor/object-type/object-type.component.ts index aa511bd1..160ef9e4 100644 --- a/projects/rero/ng-core/src/lib/record/editor/object-type/object-type.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/object-type/object-type.component.ts @@ -18,6 +18,9 @@ import { Component } from '@angular/core'; import { FieldType, FormlyFieldConfig } from '@ngx-formly/core'; import { EditorService } from '../editor.service'; +/** + * Component for displaying an object in editor. + */ @Component({ selector: 'ng-core-editor-formly-object-type', templateUrl: './object-type.component.html' @@ -32,7 +35,7 @@ export class ObjectTypeComponent extends FieldType { * Constructor * @param editorService - EditorService, that keep the list of hidden fields */ - constructor(private editorService: EditorService) { + constructor(private _editorService: EditorService) { super(); } @@ -45,7 +48,7 @@ export class ObjectTypeComponent extends FieldType { } for (const f of this.field.fieldGroup) { if (f.hide) { - this.editorService.addHiddenField(f); + this._editorService.addHiddenField(f); } } } @@ -67,8 +70,8 @@ export class ObjectTypeComponent extends FieldType { * @param fieldGroup - FormlyFieldConfig[], the fieldGroup to filter * @returns FormlyFieldConfig[], the filtered list */ - hiddenFieldGroup(fieldGroup) { - return fieldGroup.filter(f => f.hide && f.hideExpression == null); + hiddenFieldGroup(fieldGroup: any) { + return fieldGroup.filter((f: any) => f.hide && f.hideExpression == null); } /** @@ -95,7 +98,7 @@ export class ObjectTypeComponent extends FieldType { field.formControl.reset(); field.hide = true; if (this.isRoot()) { - this.editorService.addHiddenField(field); + this._editorService.addHiddenField(field); } } diff --git a/projects/rero/ng-core/src/lib/record/editor/switch/switch.component.ts b/projects/rero/ng-core/src/lib/record/editor/switch/switch.component.ts index 511380eb..f5134d54 100644 --- a/projects/rero/ng-core/src/lib/record/editor/switch/switch.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/switch/switch.component.ts @@ -17,6 +17,9 @@ import { Component } from '@angular/core'; import { FieldType } from '@ngx-formly/core'; +/** + * Component for displaying a switcher in editor. + */ @Component({ selector: 'ng-core-editor-formly-field-switch', template: ` diff --git a/projects/rero/ng-core/src/lib/record/editor/type/datepicker-type.component.ts b/projects/rero/ng-core/src/lib/record/editor/type/datepicker-type.component.ts index 90b61445..258200ae 100644 --- a/projects/rero/ng-core/src/lib/record/editor/type/datepicker-type.component.ts +++ b/projects/rero/ng-core/src/lib/record/editor/type/datepicker-type.component.ts @@ -18,6 +18,9 @@ import { formatDate } from '@angular/common'; import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; import { FieldType } from '@ngx-formly/core'; +/** + * Component for displaying a datepicker field in editor. + */ @Component({ selector: 'ng-core-editor-datepicker-type', template: ` @@ -45,12 +48,11 @@ import { FieldType } from '@ngx-formly/core'; ` }) export class DatepickerTypeComponent extends FieldType implements OnInit { - /** * constructor - * @param locale - string + * @param _locale - string */ - constructor(@Inject(LOCALE_ID) private locale: string) { + constructor(@Inject(LOCALE_ID) private _locale: string) { super(); } @@ -102,7 +104,7 @@ export class DatepickerTypeComponent extends FieldType implements OnInit { patchDate = formatDate( date, this.field.templateOptions.outputDateFormat, - this.locale + this._locale ); } catch { patchDate = undefined; diff --git a/projects/rero/ng-core/src/lib/record/editor/utils.ts b/projects/rero/ng-core/src/lib/record/editor/utils.ts index 967b0c4b..1cbf6dbf 100644 --- a/projects/rero/ng-core/src/lib/record/editor/utils.ts +++ b/projects/rero/ng-core/src/lib/record/editor/utils.ts @@ -23,7 +23,7 @@ import { extractIdOnRef } from '../../utils/utils'; * @param schema - object, the JSONSchema * @returns object, a fresh copy of the ordred JSONSchema */ -export function orderedJsonSchema(schema) { +export function orderedJsonSchema(schema: any) { if (schema.properties) { if (schema.propertiesOrder) { // copy the data @@ -72,7 +72,7 @@ export function orderedJsonSchema(schema) { * @param data - object, the data to be cleaned * @returns object, a fresh copy of the data with replacements */ -export function resolveRefs(data) { +export function resolveRefs(data: any) { // array? if (data instanceof Array) { for (const d of data) { @@ -103,7 +103,7 @@ export function resolveRefs(data) { * @param value - any, the value to check * @returns boolean, true if the value is empty */ -export function isEmpty(value) { +export function isEmpty(value: any) { return ( // null or undefined value == null || @@ -119,7 +119,7 @@ export function isEmpty(value) { * @param data - object, the data to be cleaned * @returns object, a fresh copy of the clean data */ -export function removeEmptyValues(data) { +export function removeEmptyValues(data: any) { // array? if (data instanceof Array) { // new array with non empty values diff --git a/projects/rero/ng-core/src/lib/record/record-ui.service.ts b/projects/rero/ng-core/src/lib/record/record-ui.service.ts index d10a106f..abb0062a 100644 --- a/projects/rero/ng-core/src/lib/record/record-ui.service.ts +++ b/projects/rero/ng-core/src/lib/record/record-ui.service.ts @@ -31,13 +31,21 @@ export class RecordUiService { /** Configuration for all resources. */ types = []; + /** + * Constructor. + * + * @param _dialogService Dialog service. + * @param _toastService Toast service. + * @param _translateService Translate service. + * @param _recordService Record service. + * @param _router Router. + */ constructor( - private dialogService: DialogService, - private toastService: ToastrService, - private translate: TranslateService, - private recordService: RecordService, - private router: Router, - private route: ActivatedRoute + private _dialogService: DialogService, + private _toastService: ToastrService, + private _translateService: TranslateService, + private _recordService: RecordService, + private _router: Router ) { } /** @@ -47,14 +55,14 @@ export class RecordUiService { * @returns Observable resolving as a boolean */ deleteRecord(type: string, pid: string): Observable { - const observable = this.dialogService.show({ + const observable = this._dialogService.show({ ignoreBackdropClick: true, initialState: { - title: this.translate.instant('Confirmation'), - body: this.translate.instant('Do you really want to delete this record?'), + title: this._translateService.instant('Confirmation'), + body: this._translateService.instant('Do you really want to delete this record?'), confirmButton: true, - confirmTitleButton: this.translate.instant('Delete'), - cancelTitleButton: this.translate.instant('Cancel') + confirmTitleButton: this._translateService.instant('Delete'), + cancelTitleButton: this._translateService.instant('Cancel') } }).pipe( // return a new observable depending on confirm dialog result. @@ -63,9 +71,9 @@ export class RecordUiService { return of(false); } - return this.recordService.delete(type, pid).pipe( + return this._recordService.delete(type, pid).pipe( map(() => { - this.toastService.success(this.translate.instant('Record deleted.')); + this._toastService.success(this._translateService.instant('Record deleted.')); return true; }), // delay before doing anything else, otherwise records may be not refreshed. @@ -82,12 +90,12 @@ export class RecordUiService { * @param message Message to display */ showDeleteMessage(message: string) { - this.dialogService.show({ + this._dialogService.show({ initialState: { - title: this.translate.instant('Information'), + title: this._translateService.instant('Information'), body: message, confirmButton: false, - cancelTitleButton: this.translate.instant('OK') + cancelTitleButton: this._translateService.instant('OK') } }).subscribe(); } @@ -186,17 +194,17 @@ export class RecordUiService { if (config.redirectUrl) { config.redirectUrl(record).subscribe((result: string) => { if (result !== null) { - this.router.navigate([result]); + this._router.navigate([result]); return; } }); } else { // Default behaviour if (action === 'update') { - this.router.navigate(['../../detail', pid], {relativeTo: route, replaceUrl: true}); + this._router.navigate(['../../detail', pid], {relativeTo: route, replaceUrl: true}); return; } - this.router.navigate(['../detail', pid], {relativeTo: route, replaceUrl: true}); + this._router.navigate(['../detail', pid], {relativeTo: route, replaceUrl: true}); } } } diff --git a/projects/rero/ng-core/src/lib/record/record.service.ts b/projects/rero/ng-core/src/lib/record/record.service.ts index 34a134e2..5c79bb5e 100644 --- a/projects/rero/ng-core/src/lib/record/record.service.ts +++ b/projects/rero/ng-core/src/lib/record/record.service.ts @@ -24,12 +24,11 @@ import { resolveRefs } from './editor/utils'; import { Record } from './record'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class RecordService { - - public static readonly DEFAULT_REST_RESULTS_SIZE = 10; - public static readonly MAX_REST_RESULTS_SIZE = 9999; + static readonly DEFAULT_REST_RESULTS_SIZE = 10; + static readonly MAX_REST_RESULTS_SIZE = 9999; /** * Event for record created @@ -72,13 +71,10 @@ export class RecordService { /** * Constructor - * @param http - HttpClient - * @param apiService - ApiService + * @param _http HttpClient + * @param _apiService ApiService */ - constructor( - private http: HttpClient, - private apiService: ApiService - ) { } + constructor(private _http: HttpClient, private _apiService: ApiService) { } /** * Get records filtered by given parameters. @@ -89,7 +85,7 @@ export class RecordService { * @param aggregationsFilters - number, option list of filters * @param sort - parameter for sorting records (eg. 'mostrecent' or '-mostrecent') */ - public getRecords( + getRecords( type: string, query: string = '', page = 1, @@ -118,13 +114,12 @@ export class RecordService { httpParams = httpParams.append(key, preFilters[key]); } - return this.http.get(this.apiService.getEndpointByType(type, true) + '/', { - params: httpParams, - headers: this.createRequestHeaders(headers) - }) - .pipe( - catchError(this.handleError) - ); + return this._http + .get(this._apiService.getEndpointByType(type, true) + '/', { + params: httpParams, + headers: this.createRequestHeaders(headers), + }) + .pipe(catchError(this.handleError)); } /** @@ -132,8 +127,9 @@ export class RecordService { * @param type - string, type of record * @param pid - string, PID to remove */ - public delete(type: string, pid: string): Observable { - return this.http.delete(this.apiService.getEndpointByType(type, true) + '/' + pid) + delete(type: string, pid: string): Observable { + return this._http + .delete(this._apiService.getEndpointByType(type, true) + '/' + pid) .pipe( tap(() => this.onDelete.next(this.createEvent(type, { pid }))), catchError(this.handleError) @@ -145,30 +141,40 @@ export class RecordService { * @param type - string, type of resource * @param pid - string, record PID */ - public getRecord(type: string, pid: string, resolve = 0, headers: any = {}): Observable { - return this.http.get(`${this.apiService.getEndpointByType(type, true)}/${pid}?resolve=${resolve}`, { - headers: this.createRequestHeaders(headers) - }) - .pipe( - catchError(this.handleError) - ); + getRecord( + type: string, + pid: string, + resolve = 0, + headers: any = {} + ): Observable { + return this._http + .get( + `${this._apiService.getEndpointByType( + type, + true + )}/${pid}?resolve=${resolve}`, + { + headers: this.createRequestHeaders(headers), + } + ) + .pipe(catchError(this.handleError)); } /** * Return the schema form to generate the form based on the resource given. * @param recordType - string, type of the resource */ - public getSchemaForm(recordType: string) { + getSchemaForm(recordType: string) { let recType = recordType.replace(/ies$/, 'y'); recType = recType.replace(/s$/, ''); - const url = this.apiService.getSchemaFormEndpoint(recordType, true); - return this.http.get(url).pipe( - catchError(e => { + const url = this._apiService.getSchemaFormEndpoint(recordType, true); + return this._http.get(url).pipe( + catchError((e) => { if (e.status === 404) { return of(null); } }), - map(data => { + map((data) => { return data; }) ); @@ -179,11 +185,12 @@ export class RecordService { * @param recordType - string, type of resource * @param record - object, record to create */ - public create(recordType: string, record: object): Observable { - return this.http.post(this.apiService.getEndpointByType(recordType, true) + '/', record) - .pipe( - tap(() => this.onCreate.next(this.createEvent(recordType, { record }))) - ); + create(recordType: string, record: object): Observable { + return this._http + .post(this._apiService.getEndpointByType(recordType, true) + '/', record) + .pipe( + tap(() => this.onCreate.next(this.createEvent(recordType, { record }))) + ); } /** @@ -192,9 +199,12 @@ export class RecordService { * @param record - object, record to create * @param pid - string, record PID */ - public update(recordType: string, record: { pid: string }) { - const url = `${this.apiService.getEndpointByType(recordType, true)}/${record.pid}`; - return this.http.put(url, record) + update(recordType: string, record: { pid: string }) { + const url = `${this._apiService.getEndpointByType(recordType, true)}/${ + record.pid + }`; + return this._http + .put(url, record) .pipe( tap(() => this.onUpdate.next(this.createEvent(recordType, { record }))) ); @@ -207,14 +217,19 @@ export class RecordService { * @param value - string, value to check * @param excludePid - string, PID to ignore (normally the current record we are checking) */ - public valueAlreadyExists(recordType: string, field: string, value: string, excludePid: string) { + valueAlreadyExists( + recordType: string, + field: string, + value: string, + excludePid: string + ) { let query = `${field}:"${value}"`; if (excludePid) { query += ` NOT pid:${excludePid}`; } return this.getRecords(recordType, query, 1, 0).pipe( - map(res => res.hits.total), - map(total => total ? { alreadyTakenMessage: value } : null), + map((res) => res.hits.total), + map((total) => (total ? { alreadyTakenMessage: value } : null)), debounceTime(1000) ); } @@ -228,8 +243,14 @@ export class RecordService { * @param limitToValues - string[], limit the test to a given list of values * @param filter - string, additionnal es query filters */ - public uniqueValue(field: FormlyFieldConfig, recordType: string, excludePid: string = null, - term = null, limitToValues: string[] = [], filter: string = null) { + uniqueValue( + field: FormlyFieldConfig, + recordType: string, + excludePid: string = null, + term = null, + limitToValues: string[] = [], + filter: string = null + ) { let key = field.key; if (term != null) { key = term; @@ -239,11 +260,11 @@ export class RecordService { if (value == null) { return of(false); } - if (limitToValues.length > 0 && !limitToValues.some(v => v === value)) { + if (limitToValues.length > 0 && !limitToValues.some((v) => v === value)) { return of(true); } let query = `${key}:${value}`; - if (typeof(value) === 'string') { + if (typeof value === 'string') { query = `${key}:"${value}"`; } if (filter) { @@ -254,8 +275,8 @@ export class RecordService { query += ` NOT pid:${excludePid}`; } return this.getRecords(recordType, query, 1, 0).pipe( - map(res => res.hits.total), - map(total => total ? { alreadyTakenMessage: value } : null), + map((res) => res.hits.total), + map((total) => (total ? { alreadyTakenMessage: value } : null)), debounceTime(500) ); } @@ -272,12 +293,11 @@ export class RecordService { // The backend returned an unsuccessful response code. // The response body may contain clues as to what went wrong, console.error( - `Backend returned code ${error.status}, ` + - `body was: ${error.error}`); + `Backend returned code ${error.status}, ` + `body was: ${error.error}` + ); } // return an observable with a user-facing error message - return throwError( - 'Something bad happened; please try again later.'); + return throwError('Something bad happened; please try again later.'); } /** @@ -285,7 +305,9 @@ export class RecordService { * @param headers Object containing http headers to send to request. */ private createRequestHeaders(headers: any = {}) { - return headers ? new HttpHeaders(headers) : new HttpHeaders({ 'Content-Type': 'application/json' }); + return headers + ? new HttpHeaders(headers) + : new HttpHeaders({ 'Content-Type': 'application/json' }); } /** diff --git a/projects/rero/ng-core/src/lib/record/record.ts b/projects/rero/ng-core/src/lib/record/record.ts index e89d5c13..c7a0e639 100644 --- a/projects/rero/ng-core/src/lib/record/record.ts +++ b/projects/rero/ng-core/src/lib/record/record.ts @@ -14,6 +14,10 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + +/** + * Class representing a record set retured by API. + */ export class Record { aggregations: any; hits: any; diff --git a/projects/rero/ng-core/src/lib/record/search/aggregation/buckets/buckets.component.ts b/projects/rero/ng-core/src/lib/record/search/aggregation/buckets/buckets.component.ts index 2163b731..62a286d7 100644 --- a/projects/rero/ng-core/src/lib/record/search/aggregation/buckets/buckets.component.ts +++ b/projects/rero/ng-core/src/lib/record/search/aggregation/buckets/buckets.component.ts @@ -62,9 +62,10 @@ export class BucketsComponent implements OnInit, OnDestroy { * Constructor * @param translate Translate service * @param _recordSearchService Record search service + * @param _translateLanguage TranslateLanguageService */ constructor( - private translate: TranslateService, + private _translateService: TranslateService, private _recordSearchService: RecordSearchService, private _translateLanguage: TranslateLanguageService ) { } @@ -109,7 +110,7 @@ export class BucketsComponent implements OnInit, OnDestroy { * @return Current language */ get language(): string { - return this.translate.currentLang; + return this._translateService.currentLang; } /** @@ -207,6 +208,6 @@ export class BucketsComponent implements OnInit, OnDestroy { } // Simply translate the bucket key. - return this.translate.instant(bucket.key); + return this._translateService.instant(bucket.key); } } diff --git a/projects/rero/ng-core/src/lib/record/search/record-search-page.component.ts b/projects/rero/ng-core/src/lib/record/search/record-search-page.component.ts index f46dab7c..888b661d 100644 --- a/projects/rero/ng-core/src/lib/record/search/record-search-page.component.ts +++ b/projects/rero/ng-core/src/lib/record/search/record-search-page.component.ts @@ -103,13 +103,15 @@ export class RecordSearchComponent implements OnInit, OnDestroy { private _routeParametersSubscription: Subscription; /** - * Constructor - * @param route - Angular current route - * @param router - Angular router + * Constructor. + * + * @param _route Angular current route. + * @param _router Angular router. + * @param _recordSearchService Record search service. */ constructor( - private route: ActivatedRoute, - protected router: Router, + private _route: ActivatedRoute, + private _router: Router, private _recordSearchService: RecordSearchService ) { } @@ -121,7 +123,7 @@ export class RecordSearchComponent implements OnInit, OnDestroy { * (RecordSearchComponent). */ ngOnInit() { - this._routeParametersSubscription = combineLatest([this.route.paramMap, this.route.queryParamMap]).subscribe( + this._routeParametersSubscription = combineLatest([this._route.paramMap, this._route.queryParamMap]).subscribe( ([paramMap, queryParams]) => { // store current type of resource this.currentType = paramMap.get('type'); @@ -160,7 +162,7 @@ export class RecordSearchComponent implements OnInit, OnDestroy { ); // Store configuration data - const data = this.route.snapshot.data; + const data = this._route.snapshot.data; if (data.types) { this.types = data.types; } @@ -209,7 +211,7 @@ export class RecordSearchComponent implements OnInit, OnDestroy { } } - this.router.navigate([this.getCurrentUrl(parameters.currentType)], { queryParams, relativeTo: this.route }); + this._router.navigate([this.getCurrentUrl(parameters.currentType)], { queryParams, relativeTo: this._route }); } /** @@ -218,7 +220,7 @@ export class RecordSearchComponent implements OnInit, OnDestroy { * @returns Updated url without query string */ private getCurrentUrl(type: string): string { - const segments = this.router.parseUrl(this.router.url).root.children.primary.segments.map(it => it.path); + const segments = this._router.parseUrl(this._router.url).root.children.primary.segments.map(it => it.path); segments[segments.length - 1] = type; return '/' + segments.join('/'); diff --git a/projects/rero/ng-core/src/lib/record/search/record-search.component.ts b/projects/rero/ng-core/src/lib/record/search/record-search.component.ts index 08956b1a..da13e263 100644 --- a/projects/rero/ng-core/src/lib/record/search/record-search.component.ts +++ b/projects/rero/ng-core/src/lib/record/search/record-search.component.ts @@ -167,14 +167,15 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { @Output() parametersChanged = new EventEmitter(); /** - * Constructor - * @param dialogService - Modal component - * @param recordService - Service for managing records - * @param toastService - Toast message + * Constructor. + * + * @param _recordService Record service. + * @param _recordUiService Record UI service. + * @param _recordSearchService Record search service. */ constructor( - private recordService: RecordService, - private recordUiService: RecordUiService, + private _recordService: RecordService, + private _recordUiService: RecordUiService, private _recordSearchService: RecordSearchService ) { } @@ -211,7 +212,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { // Load totals for each resource type for (const type of this.types) { - this.recordService.getRecords( + this._recordService.getRecords( type.key, '', 1, 1, [], this._config.preFilters || {}, this._config.listHeaders || null).subscribe(records => { @@ -249,7 +250,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { if (changes.currentType) { if (changes.currentType.firstChange) { // Load all configuration types, only during the first change - this.recordUiService.types = this.types; + this._recordUiService.types = this.types; } // if the "type" property is changed in input, but the change is not @@ -387,7 +388,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { * @param pid - string, PID to delete */ deleteRecord(pid: string) { - this.recordUiService.deleteRecord(this.currentType, pid).subscribe((result) => { + this._recordUiService.deleteRecord(this.currentType, pid).subscribe((result) => { if (result === true) { // refresh records this._getRecords(true, false); @@ -452,7 +453,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { * @return Observable */ canUpdateRecord$(record: object): Observable { - return this.recordUiService.canUpdateRecord$(record, this.currentType); + return this._recordUiService.canUpdateRecord$(record, this.currentType); } /** @@ -461,7 +462,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { * @return Observable */ canDeleteRecord$(record: object): Observable { - return this.recordUiService.canDeleteRecord$(record, this.currentType); + return this._recordUiService.canDeleteRecord$(record, this.currentType); } /** @@ -496,7 +497,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { return of(url); } - return this.recordUiService.canReadRecord$(record, this.currentType).pipe( + return this._recordUiService.canReadRecord$(record, this.currentType).pipe( map((status: ActionStatus) => { if (status.can === false) { return null; @@ -521,7 +522,7 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { this.isLoading = true; - this.recordService.getRecords( + this._recordService.getRecords( this.currentType, this.q, this.page, @@ -571,8 +572,8 @@ export class RecordSearchComponent implements OnInit, OnChanges, OnDestroy { * @param type Type of resource */ private loadConfigurationForType(type: string) { - this._config = this.recordUiService.getResourceConfig(type); - this.recordUiService.canAddRecord$(type).subscribe((result: ActionStatus) => { + this._config = this._recordUiService.getResourceConfig(type); + this._recordUiService.canAddRecord$(type).subscribe((result: ActionStatus) => { this.addStatus = result; }); } diff --git a/projects/rero/ng-core/src/lib/record/search/record-search.service.ts b/projects/rero/ng-core/src/lib/record/search/record-search.service.ts index 94ecf8d1..2fb52851 100644 --- a/projects/rero/ng-core/src/lib/record/search/record-search.service.ts +++ b/projects/rero/ng-core/src/lib/record/search/record-search.service.ts @@ -19,11 +19,17 @@ import { cloneDeep } from 'lodash-es'; import { BehaviorSubject, Observable } from 'rxjs'; import { first, map } from 'rxjs/operators'; +/** + * Interface representing aggregations filters + */ export interface AggregationsFilter { key: string; values: Array; } +/** + * Service for managing records search. + */ @Injectable( { providedIn: 'root' diff --git a/projects/rero/ng-core/src/lib/record/search/result/item/json.component.ts b/projects/rero/ng-core/src/lib/record/search/result/item/json.component.ts index edf12358..9f8e1503 100644 --- a/projects/rero/ng-core/src/lib/record/search/result/item/json.component.ts +++ b/projects/rero/ng-core/src/lib/record/search/result/item/json.component.ts @@ -17,6 +17,9 @@ import { Component, Input } from '@angular/core'; import { ResultItem } from './result-item'; +/** + * Component for displaying record as JSON in brief views. + */ @Component({ template: ` {{ record|json }} @@ -33,12 +36,15 @@ import { ResultItem } from './result-item'; ` }) export class JsonComponent implements ResultItem { + // Record data. @Input() - record: object; + record: any; + // Type of resource. @Input() type: string; + // Info for detail URL link. @Input() detailUrl: { link: string, external: boolean }; } diff --git a/projects/rero/ng-core/src/lib/record/search/result/item/result-item.ts b/projects/rero/ng-core/src/lib/record/search/result/item/result-item.ts index b71d201d..dd37e486 100644 --- a/projects/rero/ng-core/src/lib/record/search/result/item/result-item.ts +++ b/projects/rero/ng-core/src/lib/record/search/result/item/result-item.ts @@ -14,8 +14,17 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + +/** + * Interface representing a result item in search. + */ export interface ResultItem { - record: any; - type: string; - detailUrl: { link: string, external: boolean }; + // Record data. + record: any; + + // Type of resource. + type: string; + + // Object containing info about the link to detail. + detailUrl: { link: string, external: boolean }; } diff --git a/projects/rero/ng-core/src/lib/record/search/result/record-search-result.component.ts b/projects/rero/ng-core/src/lib/record/search/result/record-search-result.component.ts index 5face52f..6d4ac043 100644 --- a/projects/rero/ng-core/src/lib/record/search/result/record-search-result.component.ts +++ b/projects/rero/ng-core/src/lib/record/search/result/record-search-result.component.ts @@ -109,11 +109,14 @@ export class RecordSearchResultComponent implements OnInit { @ViewChild(RecordSearchResultDirective, { static: true }) searchResultItem: RecordSearchResultDirective; /** - * Constructor + * Constructor. + * + * @param _componentFactoryResolver Component factory resolver. + * @param _recordUiService Record UI service. */ constructor( - private componentFactoryResolver: ComponentFactoryResolver, - private recordUiService: RecordUiService + private _componentFactoryResolver: ComponentFactoryResolver, + private _recordUiService: RecordUiService ) { this.currentUrl = window.location.href; } @@ -146,8 +149,8 @@ export class RecordSearchResultComponent implements OnInit { /** * Dynamically load component depending on selected resource type. */ - public loadItemView() { - const componentFactory = this.componentFactoryResolver + loadItemView() { + const componentFactory = this._componentFactoryResolver .resolveComponentFactory(this.itemViewComponent ? this.itemViewComponent : JsonComponent); const viewContainerRef = this.searchResultItem.viewContainerRef; viewContainerRef.clear(); @@ -163,7 +166,7 @@ export class RecordSearchResultComponent implements OnInit { * @param event - Event, dom event fired * @param pid - string, pid to delete */ - public deleteRecord(pid: string) { + deleteRecord(pid: string) { return this.deletedRecord.emit(pid); } @@ -172,7 +175,7 @@ export class RecordSearchResultComponent implements OnInit { * @param event - Event * @param message - string, message to display */ - public showDeleteMessage(message: string) { - this.recordUiService.showDeleteMessage(message); + showDeleteMessage(message: string) { + this._recordUiService.showDeleteMessage(message); } } diff --git a/projects/rero/ng-core/src/lib/record/search/result/record-search-result.directive.ts b/projects/rero/ng-core/src/lib/record/search/result/record-search-result.directive.ts index 8df357e7..2aae72d1 100644 --- a/projects/rero/ng-core/src/lib/record/search/result/record-search-result.directive.ts +++ b/projects/rero/ng-core/src/lib/record/search/result/record-search-result.directive.ts @@ -16,9 +16,24 @@ */ import { Directive, ViewContainerRef } from '@angular/core'; +/** + * Directive for displaying record search result. + */ @Directive({ - selector: '[ngCoreRecordSearchResult]', + selector: '[ngCoreRecordSearchResult]', }) export class RecordSearchResultDirective { - constructor(public viewContainerRef: ViewContainerRef) { } + /** + * Constructor. + * + * @param _viewContainerRef View container reference. + */ + constructor(private _viewContainerRef: ViewContainerRef) { } + + /** + * Returns view container reference. + */ + get viewContainerRef(): ViewContainerRef { + return this._viewContainerRef; + } } diff --git a/projects/rero/ng-core/src/lib/route/route-collection.service.ts b/projects/rero/ng-core/src/lib/route/route-collection.service.ts index f5d4551e..ddca48a4 100644 --- a/projects/rero/ng-core/src/lib/route/route-collection.service.ts +++ b/projects/rero/ng-core/src/lib/route/route-collection.service.ts @@ -25,7 +25,7 @@ export class RouteCollectionService { /** * Collection of routes */ - private collection = new Map(); + private _collection = new Map(); /** * Add route on collection @@ -35,7 +35,7 @@ export class RouteCollectionService { addRoute(route: RouteInterface): RouteCollectionService { const routeName = route.name; if (!this.hasRoute(routeName)) { - this.collection.set(routeName, route); + this._collection.set(routeName, route); } return this; } @@ -47,7 +47,7 @@ export class RouteCollectionService { */ deleteRoute(name: string): boolean { if (this.hasRoute(name)) { - this.collection.delete(name); + this._collection.delete(name); return true; } return false; @@ -59,7 +59,7 @@ export class RouteCollectionService { * @return boolean */ hasRoute(name: string): boolean { - return this.collection.has(name); + return this._collection.has(name); } /** @@ -69,7 +69,7 @@ export class RouteCollectionService { */ getRoute(name: string): RouteInterface | null { if (this.hasRoute(name)) { - return this.collection.get(name); + return this._collection.get(name); } return null; } @@ -80,7 +80,7 @@ export class RouteCollectionService { */ getRoutes() { const routes = []; - for (const value of this.collection.values()) { + for (const value of this._collection.values()) { routes.push(value.getConfiguration()); } return routes; @@ -92,7 +92,7 @@ export class RouteCollectionService { */ availableRoutesName() { const routesName = []; - for (const route of this.collection.keys()) { + for (const route of this._collection.keys()) { routesName.push(route); } return routesName; @@ -103,6 +103,6 @@ export class RouteCollectionService { * @return number; */ size() { - return this.collection.size; + return this._collection.size; } } diff --git a/projects/rero/ng-core/src/lib/search-input/search-input.component.ts b/projects/rero/ng-core/src/lib/search-input/search-input.component.ts index 2ea606fd..44e1e543 100644 --- a/projects/rero/ng-core/src/lib/search-input/search-input.component.ts +++ b/projects/rero/ng-core/src/lib/search-input/search-input.component.ts @@ -16,36 +16,46 @@ */ import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +/** + * Component for displaying a search input. + */ @Component({ selector: 'ng-core-search-input', templateUrl: './search-input.component.html' }) export class SearchInputComponent { - /** The current search input object from the template. */ - @ViewChild('searchinput', { static: false }) input: any; - - /** Search output event emitter */ - @Output() search = new EventEmitter(); - /** Display label */ - @Input() displayLabel = true; + @Input() + displayLabel = true; /** Placeholder */ - @Input() placeholder = 'search'; + @Input() + placeholder = 'search'; /** Value to search */ - @Input() searchText = ''; + @Input() + searchText = ''; + + /** Remove trailing and leading spaces if true */ + @Input() + trimQueryString = true; + + /** The current search input object from the template. */ + @ViewChild('searchinput', { static: false }) + input: any; + + /** Search output event emitter */ + @Output() + search = new EventEmitter(); /** Set the focus on the input element */ - @Input() set focus(value: boolean) { + @Input() + set focus(value: boolean) { if (value === true) { setTimeout(() => this.input.nativeElement.focus()); } } - /** Remove trailing and leading spaces if true */ - @Input() trimQueryString = true; - doSearch(searchText: string) { if (this.trimQueryString) { this.search.emit(searchText.trim()); diff --git a/projects/rero/ng-core/src/lib/service/crypto-js.service.ts b/projects/rero/ng-core/src/lib/service/crypto-js.service.ts index b11f61b6..caf1bcc7 100644 --- a/projects/rero/ng-core/src/lib/service/crypto-js.service.ts +++ b/projects/rero/ng-core/src/lib/service/crypto-js.service.ts @@ -22,8 +22,12 @@ import { CoreConfigService } from '../core-config.service'; providedIn: 'root' }) export class CryptoJsService { - - constructor(private coreConfigService: CoreConfigService) { } + /** + * Constructor. + * + * @param _coreConfigService Configuration service. + */ + constructor(private _coreConfigService: CoreConfigService) { } encrypt(value: string) { const _key = this.secretPassphrase(); @@ -36,6 +40,6 @@ export class CryptoJsService { } private secretPassphrase() { - return CryptoJS.enc.Utf8.parse(this.coreConfigService.secretPassphrase); + return CryptoJS.enc.Utf8.parse(this._coreConfigService.secretPassphrase); } } diff --git a/projects/rero/ng-core/src/lib/service/local-storage.service.ts b/projects/rero/ng-core/src/lib/service/local-storage.service.ts index f697dca8..20100635 100644 --- a/projects/rero/ng-core/src/lib/service/local-storage.service.ts +++ b/projects/rero/ng-core/src/lib/service/local-storage.service.ts @@ -18,32 +18,34 @@ import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { CryptoJsService } from './crypto-js.service'; +/** + * Service for managing data saved into local storage. + */ @Injectable({ providedIn: 'root' }) export class LocalStorageService { - /** * Event for set data on local storage */ - private onSet: Subject = new Subject(); + private _onSet: Subject = new Subject(); /** * Event for remove data on local storage */ - private onRemove: Subject = new Subject(); + private _onRemove: Subject = new Subject(); /** * Event for clear on local storage */ - private onClear: Subject = new Subject(); + private _onClear: Subject = new Subject(); /** * On set observable * @return onSet subject observable */ get onSet$() { - return this.onSet.asObservable(); + return this._onSet.asObservable(); } /** @@ -51,7 +53,7 @@ export class LocalStorageService { * @return onRemove subject observable */ get onRemove$() { - return this.onRemove.asObservable(); + return this._onRemove.asObservable(); } /** @@ -59,13 +61,15 @@ export class LocalStorageService { * @return onClear subject observable */ get onClear$() { - return this.onClear.asObservable(); + return this._onClear.asObservable(); } /** - * Constructor + * Constructor. + * + * @param _cryptoService Crypto service. */ - constructor(private cryptoService: CryptoJsService) {} + constructor(private _cryptoService: CryptoJsService) {} /** * Set a new key on LocalStorage @@ -75,10 +79,10 @@ export class LocalStorageService { */ set(key: string, value: any) { const data = { date: new Date(), data: value }; - localStorage.setItem(key, this.cryptoService.encrypt( + localStorage.setItem(key, this._cryptoService.encrypt( JSON.stringify(data) )); - this.onSet.next({ key, data }); + this._onSet.next({ key, data }); return this; } @@ -91,7 +95,7 @@ export class LocalStorageService { updateDate(key: string) { const local = this.getItem(key); local.date = new Date(); - localStorage.setItem(key, this.cryptoService.encrypt( + localStorage.setItem(key, this._cryptoService.encrypt( JSON.stringify(local) )); @@ -131,7 +135,7 @@ export class LocalStorageService { */ remove(key: string) { localStorage.removeItem(key); - this.onRemove.next(null); + this._onRemove.next(null); return this; } @@ -142,7 +146,7 @@ export class LocalStorageService { */ clear() { localStorage.clear(); - this.onClear.next(null); + this._onClear.next(null); return this; } @@ -161,7 +165,7 @@ export class LocalStorageService { * @param key - string */ private getItem(key: string) { - return JSON.parse(this.cryptoService.decrypt( + return JSON.parse(this._cryptoService.decrypt( localStorage.getItem(key) )); } diff --git a/projects/rero/ng-core/src/lib/service/title-meta.service.ts b/projects/rero/ng-core/src/lib/service/title-meta.service.ts index 4347c1ce..ed15f48e 100644 --- a/projects/rero/ng-core/src/lib/service/title-meta.service.ts +++ b/projects/rero/ng-core/src/lib/service/title-meta.service.ts @@ -18,11 +18,14 @@ import { Injectable } from '@angular/core'; import { Meta, Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; +/** + * Service for managin HTML meta and title. + */ @Injectable({ providedIn: 'root' }) export class TitleMetaService { - + // Prefix. private _prefix = null; /** @@ -32,9 +35,9 @@ export class TitleMetaService { * @param translateService - TranslateService */ constructor( - private titleService: Title, - private metaService: Meta, - private translateService: TranslateService + private _titleService: Title, + private _metaService: Meta, + private _translateService: TranslateService ) { } /** @@ -43,7 +46,7 @@ export class TitleMetaService { * @return this */ setPrefix(prefix?: string) { - this._prefix = this.translateService.instant(prefix); + this._prefix = this._translateService.instant(prefix); return this; } @@ -58,8 +61,8 @@ export class TitleMetaService { if (this._prefix !== null) { pageTitle += this._prefix + ': '; } - pageTitle += this.translateService.instant(title); - this.titleService.setTitle(pageTitle); + pageTitle += this._translateService.instant(title); + this._titleService.setTitle(pageTitle); return this; } @@ -69,7 +72,7 @@ export class TitleMetaService { * @return string */ getTitle() { - return this.titleService.getTitle(); + return this._titleService.getTitle(); } /** @@ -79,7 +82,7 @@ export class TitleMetaService { * @return this */ setMeta(name: string, content: string) { - this.metaService.updateTag({name, content}); + this._metaService.updateTag({name, content}); return this; } @@ -90,6 +93,6 @@ export class TitleMetaService { * @return string */ getMeta(name: string) { - return this.metaService.getTag(name); + return this._metaService.getTag(name); } } diff --git a/projects/rero/ng-core/src/lib/text-read-more/text-read-more.component.ts b/projects/rero/ng-core/src/lib/text-read-more/text-read-more.component.ts index 6b5ad7ec..4f9edd22 100644 --- a/projects/rero/ng-core/src/lib/text-read-more/text-read-more.component.ts +++ b/projects/rero/ng-core/src/lib/text-read-more/text-read-more.component.ts @@ -16,31 +16,41 @@ */ import { Component, Input, OnInit } from '@angular/core'; +/** + * Component for displaying a "read more" link after a text. + */ @Component({ selector: 'ng-core-text-read-more', templateUrl: './text-read-more.component.html' }) export class TextReadMoreComponent implements OnInit { - /** Initial text */ @Input() text: string; + /** Number of parts to display (depending of the unit) */ @Input() limit = 50; + /** "Show more" label to display */ @Input() showMoreLabel = 'Show more'; + /** "Show less" label to display */ @Input() showLessLabel = 'Show less'; + /** Splitting unit [ word | character] */ @Input() unit = 'word'; + /** trailing string */ @Input() trailing = '…'; /** The text that will be display */ textToDisplay: string; + /** boolean to know if initial text is expanded */ isExpanded = false; + /** boolean to know if limit is reached */ isLimitReached = true; + /** The truncated text */ private _sTruncateText: string; diff --git a/projects/rero/ng-core/src/lib/translate/date-translate-pipe.spec.ts b/projects/rero/ng-core/src/lib/translate/date-translate-pipe.spec.ts index 3956344b..31a70760 100644 --- a/projects/rero/ng-core/src/lib/translate/date-translate-pipe.spec.ts +++ b/projects/rero/ng-core/src/lib/translate/date-translate-pipe.spec.ts @@ -16,6 +16,7 @@ */ import { EventEmitter } from '@angular/core'; import { DateTranslatePipe } from './date-translate-pipe'; +import { TranslateService } from '@ngx-translate/core'; let dateTranslateService: DateTranslatePipe; @@ -36,7 +37,7 @@ class TranslateServiceMock { describe('DateTranslatePipePipe', () => { beforeEach(() => { dateTranslateService = new DateTranslatePipe( - new TranslateServiceMock() + new TranslateServiceMock() as unknown as TranslateService ); }); diff --git a/projects/rero/ng-core/src/lib/translate/date-translate-pipe.ts b/projects/rero/ng-core/src/lib/translate/date-translate-pipe.ts index fa18a720..2caaca09 100644 --- a/projects/rero/ng-core/src/lib/translate/date-translate-pipe.ts +++ b/projects/rero/ng-core/src/lib/translate/date-translate-pipe.ts @@ -23,15 +23,19 @@ import { TranslateService } from '@ngx-translate/core'; pure: false // required to update the value when the promise is resolved }) export class DateTranslatePipe extends DatePipe implements PipeTransform { - - constructor(@Inject(TranslateService) private translateService) { - super(translateService.currentLang); + /** + * Constructor. + * + * @param _translateService Translate service. + */ + constructor(@Inject(TranslateService) private _translateService: TranslateService) { + super(_translateService.currentLang); } transform(value: any, format = 'mediumDate', timezone?: string, locale?: string): string { - let tlocale = (locale) ? locale : this.translateService.currentLang; - this.translateService.onLangChange.subscribe(() => { - tlocale = (locale) ? locale : this.translateService.currentLang; + let tlocale = (locale) ? locale : this._translateService.currentLang; + this._translateService.onLangChange.subscribe(() => { + tlocale = (locale) ? locale : this._translateService.currentLang; return super.transform(value, format, timezone, tlocale); }); diff --git a/projects/rero/ng-core/src/lib/translate/translate-language.pipe.ts b/projects/rero/ng-core/src/lib/translate/translate-language.pipe.ts index 5ffdf30c..cdb68f4f 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-language.pipe.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-language.pipe.ts @@ -23,10 +23,11 @@ import { TranslateLanguageService } from './translate-language.service'; export class TranslateLanguagePipe implements PipeTransform { /** - * Constructor - * @param translateLanguage - TranslateLanguageService + * Constructor. + * + * @param _translateLanguage TranslateLanguageService */ - constructor(private translateLanguage: TranslateLanguageService) { } + constructor(private _translateLanguage: TranslateLanguageService) { } /** * transform language code to human language @@ -34,6 +35,6 @@ export class TranslateLanguagePipe implements PipeTransform { * @param language - ISO 639-1 (2 characters) */ transform(langCode: string, language?: string): string { - return this.translateLanguage.translate(langCode, language); + return this._translateLanguage.translate(langCode, language); } } diff --git a/projects/rero/ng-core/src/lib/translate/translate-language.service.ts b/projects/rero/ng-core/src/lib/translate/translate-language.service.ts index addb7b7f..69da83c7 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-language.service.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-language.service.ts @@ -32,7 +32,7 @@ export class TranslateLanguageService implements OnDestroy { static PREFERRED_LANGUAGES = ['eng', 'fre', 'ger', 'ita']; // Available languages (import) - private availableLanguages = { de, en, fr, it }; + private _availableLanguages = { de, en, fr, it }; // List of options for populating the select box. The options are stored to // avoid a repetitive treatment, as the language select box may appear several @@ -48,11 +48,11 @@ export class TranslateLanguageService implements OnDestroy { * Subscribes to language changes and resets the stored options after a * change. * - * @param translateService - TranslateService + * @param _translateService - TranslateService */ - constructor(private translateService: TranslateService) { + constructor(private _translateService: TranslateService) { // When language is changed, we reset the stored select options. - this._changeLanguageSubscription = this.translateService.onLangChange.subscribe(() => { + this._changeLanguageSubscription = this._translateService.onLangChange.subscribe(() => { this._selectOptions = null; }); } @@ -72,16 +72,16 @@ export class TranslateLanguageService implements OnDestroy { * @return human language - string */ translate(langCode: string, language?: string) { - const lang = language ? language : this.translateService.currentLang; - if (!(lang in this.availableLanguages)) { + const lang = language ? language : this._translateService.currentLang; + if (!(lang in this._availableLanguages)) { return langCode; } - if (!(langCode in this.availableLanguages[lang])) { + if (!(langCode in this._availableLanguages[lang])) { return langCode; } - return this.availableLanguages[lang][langCode]; + return this._availableLanguages[lang][langCode]; } /** diff --git a/projects/rero/ng-core/src/lib/translate/translate-loader.spec.ts b/projects/rero/ng-core/src/lib/translate/translate-loader.spec.ts index 189fe181..1adf324d 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-loader.spec.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-loader.spec.ts @@ -15,6 +15,7 @@ * along with this program. If not, see . */ import { TestBed } from '@angular/core/testing'; +import { CoreConfigService } from '../core-config.service'; import { TranslateLoader } from './translate-loader'; describe('TranslateLoader', () => { @@ -23,7 +24,7 @@ describe('TranslateLoader', () => { }); it('should be created', () => { - const translateLoader = new TranslateLoader({}); + const translateLoader = new TranslateLoader(new CoreConfigService()); expect(translateLoader).toBeTruthy(); }); @@ -38,7 +39,7 @@ describe('TranslateLoader', () => { } }; - const translateLoader = new TranslateLoader(config); + const translateLoader = new TranslateLoader(config as CoreConfigService); translateLoader.getTranslation('fr').subscribe(translations => { expect(translations['your query']).toBe(config.customTranslations.fr['your query']); }); @@ -49,7 +50,7 @@ describe('TranslateLoader', () => { languages: ['fr'] }; - const translateLoader = new TranslateLoader(config); + const translateLoader = new TranslateLoader(config as CoreConfigService); expect(() => translateLoader.getTranslation('pt')).toThrowError('Translations not found for lang "pt"'); }); @@ -63,7 +64,7 @@ describe('TranslateLoader', () => { } }; - const translateLoader = new TranslateLoader(config); + const translateLoader = new TranslateLoader(config as CoreConfigService); translateLoader.getTranslation('en').subscribe(translations => { expect(translations['Record deleted.']).toBe('Record deleted.'); }); diff --git a/projects/rero/ng-core/src/lib/translate/translate-loader.ts b/projects/rero/ng-core/src/lib/translate/translate-loader.ts index ebf041d2..bbaf728a 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-loader.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-loader.ts @@ -27,42 +27,43 @@ import it from './i18n/it.json'; * Loader for translations used in ngx-translate library. */ export class TranslateLoader implements BaseTranslateLoader { - /** - * Store translations in available languages. - */ - public translations: object = { fr, de, en, it }; + /** + * Store translations in available languages. + */ + translations: object = { fr, de, en, it }; - /** - * Constructor - * @param config - ConfigService, invenio core configuration - */ - constructor(@Inject(CoreConfigService) private configService) { - this.loadCustomTranslations(); - } + /** + * Constructor. + * + * @param _coreConfigService Configuration service. + */ + constructor(@Inject(CoreConfigService) private _coreConfigService: CoreConfigService) { + this.loadCustomTranslations(); + } - /** - * Load custom translations - */ - private loadCustomTranslations() { - if (!this.configService.customTranslations) { - return; - } + /** + * Load custom translations + */ + private loadCustomTranslations() { + if (!this._coreConfigService.customTranslations) { + return; + } - for (const lang of this.configService.languages) { - if (this.translations[lang] && this.configService.customTranslations[lang]) { - this.translations[lang] = { ...this.translations[lang], ...this.configService.customTranslations[lang] }; - } - } + for (const lang of this._coreConfigService.languages) { + if (this.translations[lang] && this._coreConfigService.customTranslations[lang]) { + this.translations[lang] = { ...this.translations[lang], ...this._coreConfigService.customTranslations[lang] }; + } } + } - /** - * Return observable used by ngx-translate to get translations. - * @param lang - string, language to rerieve translations from. - */ - getTranslation(lang: string): Observable { - if (!this.translations[lang]) { - throw new Error(`Translations not found for lang "${lang}"`); - } - return of(this.translations[lang]); + /** + * Return observable used by ngx-translate to get translations. + * @param lang - string, language to rerieve translations from. + */ + getTranslation(lang: string): Observable { + if (!this.translations[lang]) { + throw new Error(`Translations not found for lang "${lang}"`); } + return of(this.translations[lang]); + } } diff --git a/projects/rero/ng-core/src/lib/translate/translate-service.spec.ts b/projects/rero/ng-core/src/lib/translate/translate-service.spec.ts index 430c75a5..2d25df6f 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-service.spec.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-service.spec.ts @@ -16,6 +16,8 @@ */ import { CoreConfigService } from '../core-config.service'; import { TranslateService } from './translate-service'; +import { TranslateService as NgxTranslateService } from '@ngx-translate/core'; +import { BsLocaleService } from 'ngx-bootstrap'; class TranslateServiceMock { private language; @@ -45,9 +47,9 @@ let appTranslateService; describe('AppTranslateService', () => { beforeEach(() => { appTranslateService = new TranslateService( - new TranslateServiceMock(), + new TranslateServiceMock() as unknown as NgxTranslateService, new CoreConfigService(), - new BsLocaleServiceMock() + new BsLocaleServiceMock() as unknown as BsLocaleService ); }); it('should create an instance', () => { diff --git a/projects/rero/ng-core/src/lib/translate/translate-service.ts b/projects/rero/ng-core/src/lib/translate/translate-service.ts index 7f36c701..145ef67b 100644 --- a/projects/rero/ng-core/src/lib/translate/translate-service.ts +++ b/projects/rero/ng-core/src/lib/translate/translate-service.ts @@ -31,24 +31,31 @@ import { SelectOption } from '../record/editor/interfaces'; }) export class TranslateService { languages = { - de: { ngx: deLocale, angular: localeDe }, - en: { ngx: enGbLocale, angular: localeEn }, - fr: { ngx: frLocale, angular: localeFr }, - it: { ngx: itLocale, angular: localeIt } + de: { ngx: deLocale, angular: localeDe }, + en: { ngx: enGbLocale, angular: localeEn }, + fr: { ngx: frLocale, angular: localeFr }, + it: { ngx: itLocale, angular: localeIt } }; + /** + * Constructor. + * + * @param _translateService Translate service. + * @param _coreConfigService Configuration service. + * @param _bsLocaleService Bootstrap locale service. + */ constructor( - @Inject(NgxTranslateService) private translateService, - @Inject(CoreConfigService) private coreConfigService, - @Inject(BsLocaleService) private bsLocaleService + @Inject(NgxTranslateService) private _translateService: NgxTranslateService, + @Inject(CoreConfigService) private _coreConfigService: CoreConfigService, + @Inject(BsLocaleService) private _bsLocaleService: BsLocaleService ) { this.init(); } setLanguage(language: string) { - this.translateService.use(language); + this._translateService.use(language); moment.locale(language); - this.bsLocaleService.use(language); + this._bsLocaleService.use(language); return this; } @@ -60,17 +67,17 @@ export class TranslateService { * @return Translated value as string. */ translate(key: string | Array, interpolateParams: any = null): string { - return this.translateService.instant(key, interpolateParams); + return this._translateService.instant(key, interpolateParams); } getBrowserLang() { - return this.translateService.getBrowserLang(); + return this._translateService.getBrowserLang(); } get currentLanguage(): string { - return this.translateService.currentLang - || this.coreConfigService.defaultLanguage - || 'en'; + return this._translateService.currentLang + || this._coreConfigService.defaultLanguage + || 'en'; } /** @@ -83,7 +90,7 @@ export class TranslateService { getSelectOptions(values: Array, prefix: string = null, sort = true): Array { const options = values.map((value: string) => { return { - label: this.translateService.instant((prefix || '') + value), + label: this._translateService.instant((prefix || '') + value), value }; }); @@ -102,9 +109,9 @@ export class TranslateService { defineLocale(key, value.ngx); registerLocaleData(value.angular, key); } - const languages: Array = this.coreConfigService.languages; - this.translateService.addLangs(languages); - this.translateService.setDefaultLang(this.coreConfigService.defaultLanguage); - this.setLanguage(this.coreConfigService.defaultLanguage); + const languages: Array = this._coreConfigService.languages; + this._translateService.addLangs(languages); + this._translateService.setDefaultLang(this._coreConfigService.defaultLanguage); + this.setLanguage(this._coreConfigService.defaultLanguage); } } diff --git a/projects/rero/ng-core/src/lib/widget/menu/menu.component.ts b/projects/rero/ng-core/src/lib/widget/menu/menu.component.ts index e429ca9a..f72e23df 100644 --- a/projects/rero/ng-core/src/lib/widget/menu/menu.component.ts +++ b/projects/rero/ng-core/src/lib/widget/menu/menu.component.ts @@ -21,16 +21,16 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; templateUrl: './menu.component.html' }) export class MenuComponent { - @Input() - menu; + menu: any; @Input() - isItemMenuVisible: (menuItem) => true; + isItemMenuVisible: (menuItem: any) => true; - @Output() clickItem = new EventEmitter(); + @Output() + clickItem = new EventEmitter(); - itemType(item) { + itemType(item: any) { if (item.routerLink) { return 'routerLink'; } @@ -40,7 +40,7 @@ export class MenuComponent { return 'action'; } - itemClass(item) { + itemClass(item: any) { const itemClasses = [ this.menu.hasOwnProperty('itemCssClass') ? this.menu.itemCssClass : 'nav-item' ]; @@ -50,7 +50,7 @@ export class MenuComponent { return itemClasses.join(' '); } - doClickItem(event, item) { + doClickItem(event: any, item: any) { event.preventDefault(); this.clickItem.emit(item); }