diff --git a/src/app/+login-page/login-page.component.ts b/src/app/+login-page/login-page.component.ts index 1f1cf7cf04..6a8508eb45 100644 --- a/src/app/+login-page/login-page.component.ts +++ b/src/app/+login-page/login-page.component.ts @@ -1,7 +1,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; +import { combineLatest as observableCombineLatest, Subscription } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; @@ -16,17 +16,34 @@ import { hasValue, isNotEmpty } from '../shared/empty.util'; import { AuthTokenInfo } from '../core/auth/models/auth-token-info.model'; import { isAuthenticated } from '../core/auth/selectors'; +/** + * This component represents the login page + */ @Component({ selector: 'ds-login-page', styleUrls: ['./login-page.component.scss'], templateUrl: './login-page.component.html' }) export class LoginPageComponent implements OnDestroy, OnInit { + + /** + * Subscription to unsubscribe onDestroy + * @type {Subscription} + */ sub: Subscription; + /** + * Initialize instance variables + * + * @param {ActivatedRoute} route + * @param {Store} store + */ constructor(private route: ActivatedRoute, private store: Store) {} + /** + * Initialize instance variables + */ ngOnInit() { const queryParamsObs = this.route.queryParams; const authenticated = this.store.select(isAuthenticated); @@ -52,6 +69,9 @@ export class LoginPageComponent implements OnDestroy, OnInit { }) } + /** + * Unsubscribe from subscription + */ ngOnDestroy() { if (hasValue(this.sub)) { this.sub.unsubscribe(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 984495078b..4e66c7673e 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -53,6 +53,14 @@ export abstract class DataService { public abstract getBrowseEndpoint(options: FindAllOptions, linkPath?: string): Observable + /** + * Create the HREF with given options object + * + * @param options The [[FindAllOptions]] object + * @param linkPath The link path for the object + * @return {Observable} + * Return an observable that emits created HREF + */ protected getFindAllHref(options: FindAllOptions = {}, linkPath?: string): Observable { let result: Observable; const args = []; @@ -62,6 +70,14 @@ export abstract class DataService { return this.buildHrefFromFindOptions(result, args, options); } + /** + * Create the HREF for a specific object's search method with given options object + * + * @param searchMethod The search method for the object + * @param options The [[FindAllOptions]] object + * @return {Observable} + * Return an observable that emits created HREF + */ protected getSearchByHref(searchMethod: string, options: FindAllOptions = {}): Observable { let result: Observable; const args = []; @@ -77,6 +93,15 @@ export abstract class DataService { return this.buildHrefFromFindOptions(result, args, options); } + /** + * Turn an options object into a query string and combine it with the given HREF + * + * @param href$ The HREF to which the query string should be appended + * @param args Array with additional params to combine with query string + * @param options The [[FindAllOptions]] object + * @return {Observable} + * Return an observable that emits created HREF + */ protected buildHrefFromFindOptions(href$: Observable, args: string[], options: FindAllOptions): Observable { if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { @@ -146,6 +171,14 @@ export abstract class DataService { map((href: string) => `${href}/${searchMethod}`)); } + /** + * Make a new FindAllRequest with given search method + * + * @param searchMethod The search method for the object + * @param options The [[FindAllOptions]] object + * @return {Observable>} + * Return an observable that emits response from the server + */ protected searchBy(searchMethod: string, options: FindAllOptions = {}): Observable>> { const hrefObs = this.getSearchByHref(searchMethod, options); diff --git a/src/app/core/submission/models/normalized-workflowitem.model.ts b/src/app/core/submission/models/normalized-workflowitem.model.ts index 0ea4ff6150..a3fa8992a2 100644 --- a/src/app/core/submission/models/normalized-workflowitem.model.ts +++ b/src/app/core/submission/models/normalized-workflowitem.model.ts @@ -5,22 +5,37 @@ import { Workflowitem } from './workflowitem.model'; import { NormalizedSubmissionObject } from './normalized-submission-object.model'; import { ResourceType } from '../../shared/resource-type'; +/** + * An model class for a NormalizedWorkflowItem. + */ @mapsTo(Workflowitem) @inheritSerialization(NormalizedSubmissionObject) export class NormalizedWorkflowItem extends NormalizedSubmissionObject { + /** + * The collection this workflowitem belonging to + */ @autoserialize @relationship(ResourceType.Collection, false) collection: string; + /** + * The item created with this workflowitem + */ @autoserialize @relationship(ResourceType.Item, false) item: string; + /** + * The configuration object that define this workflowitem + */ @autoserialize @relationship(ResourceType.SubmissionDefinition, false) submissionDefinition: string; + /** + * The EPerson who submit this workflowitem + */ @autoserialize @relationship(ResourceType.EPerson, false) submitter: string; diff --git a/src/app/core/submission/models/normalized-workspaceitem.model.ts b/src/app/core/submission/models/normalized-workspaceitem.model.ts index 7ec40d6524..7c15925c98 100644 --- a/src/app/core/submission/models/normalized-workspaceitem.model.ts +++ b/src/app/core/submission/models/normalized-workspaceitem.model.ts @@ -7,23 +7,38 @@ import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-obj import { ResourceType } from '../../shared/resource-type'; import { Workflowitem } from './workflowitem.model'; +/** + * An model class for a NormalizedWorkspaceItem. + */ @mapsTo(Workspaceitem) @inheritSerialization(NormalizedDSpaceObject) @inheritSerialization(NormalizedSubmissionObject) export class NormalizedWorkspaceItem extends NormalizedSubmissionObject { + /** + * The collection this workspaceitem belonging to + */ @autoserialize @relationship(ResourceType.Collection, false) collection: string; + /** + * The item created with this workspaceitem + */ @autoserialize @relationship(ResourceType.Item, false) item: string; + /** + * The configuration object that define this workspaceitem + */ @autoserialize @relationship(ResourceType.SubmissionDefinition, false) submissionDefinition: string; + /** + * The EPerson who submit this workspaceitem + */ @autoserialize @relationship(ResourceType.EPerson, false) submitter: string; diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 7e3b74a6a9..6b2d9a03b9 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -46,7 +46,7 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable sections: WorkspaceitemSectionsObject; /** - * The submission config definition + * The configuration object that define this submission */ submissionDefinition: Observable> | SubmissionDefinitionsModel; diff --git a/src/app/core/submission/models/workspaceitem-section-form.model.ts b/src/app/core/submission/models/workspaceitem-section-form.model.ts index cfae3f5b0f..1462a96d81 100644 --- a/src/app/core/submission/models/workspaceitem-section-form.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-form.model.ts @@ -1,6 +1,10 @@ import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; import { MetadataMapInterface } from '../../shared/metadata.models'; +/** + * An interface to represent submission's form section data. + * A map of metadata keys to an ordered list of FormFieldMetadataValueObject objects. + */ export interface WorkspaceitemSectionFormObject extends MetadataMapInterface { [metadata: string]: FormFieldMetadataValueObject[]; } diff --git a/src/app/core/submission/models/workspaceitem-section-license.model.ts b/src/app/core/submission/models/workspaceitem-section-license.model.ts index 4a86503a04..26f625871e 100644 --- a/src/app/core/submission/models/workspaceitem-section-license.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-license.model.ts @@ -1,5 +1,20 @@ + +/** + * An interface to represent submission's license section data. + */ export interface WorkspaceitemSectionLicenseObject { + /** + * The license url + */ url: string; + + /** + * The acceptance date of the license + */ acceptanceDate: string; + + /** + * A boolean representing if license has been granted + */ granted: boolean; } diff --git a/src/app/core/submission/models/workspaceitem-section-upload-file.model.ts b/src/app/core/submission/models/workspaceitem-section-upload-file.model.ts index a42a334b86..177473b7d5 100644 --- a/src/app/core/submission/models/workspaceitem-section-upload-file.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-upload-file.model.ts @@ -1,15 +1,46 @@ import { SubmissionUploadFileAccessConditionObject } from './submission-upload-file-access-condition.model'; import { WorkspaceitemSectionFormObject } from './workspaceitem-section-form.model'; +/** + * An interface to represent submission's upload section file entry. + */ export class WorkspaceitemSectionUploadFileObject { + + /** + * The file UUID + */ uuid: string; + + /** + * The file metadata + */ metadata: WorkspaceitemSectionFormObject; + + /** + * The file size + */ sizeBytes: number; + + /** + * The file check sum + */ checkSum: { checkSumAlgorithm: string; value: string; }; + + /** + * The file url + */ url: string; + + /** + * The file thumbnail url + */ thumbnail: string; + + /** + * The list of file access conditions + */ accessConditions: SubmissionUploadFileAccessConditionObject[]; } diff --git a/src/app/core/submission/models/workspaceitem-section-upload.model.ts b/src/app/core/submission/models/workspaceitem-section-upload.model.ts index b936b5d4d8..f98e0584eb 100644 --- a/src/app/core/submission/models/workspaceitem-section-upload.model.ts +++ b/src/app/core/submission/models/workspaceitem-section-upload.model.ts @@ -1,5 +1,12 @@ import { WorkspaceitemSectionUploadFileObject } from './workspaceitem-section-upload-file.model'; +/** + * An interface to represent submission's upload section data. + */ export interface WorkspaceitemSectionUploadObject { + + /** + * A list of [[WorkspaceitemSectionUploadFileObject]] + */ files: WorkspaceitemSectionUploadFileObject[]; } diff --git a/src/app/core/submission/models/workspaceitem-sections.model.ts b/src/app/core/submission/models/workspaceitem-sections.model.ts index f0d010cd27..165e69869c 100644 --- a/src/app/core/submission/models/workspaceitem-sections.model.ts +++ b/src/app/core/submission/models/workspaceitem-sections.model.ts @@ -2,10 +2,17 @@ import { WorkspaceitemSectionFormObject } from './workspaceitem-section-form.mod import { WorkspaceitemSectionLicenseObject } from './workspaceitem-section-license.model'; import { WorkspaceitemSectionUploadObject } from './workspaceitem-section-upload.model'; +/** + * An interface to represent submission's section object. + * A map of section keys to an ordered list of WorkspaceitemSectionDataType objects. + */ export class WorkspaceitemSectionsObject { [name: string]: WorkspaceitemSectionDataType; } +/** + * Export a type alias of all sections + */ export type WorkspaceitemSectionDataType = WorkspaceitemSectionUploadObject | WorkspaceitemSectionFormObject diff --git a/src/app/core/submission/submission-json-patch-operations.service.ts b/src/app/core/submission/submission-json-patch-operations.service.ts index f9371100d6..d469f2098f 100644 --- a/src/app/core/submission/submission-json-patch-operations.service.ts +++ b/src/app/core/submission/submission-json-patch-operations.service.ts @@ -9,6 +9,9 @@ import { SubmitDataResponseDefinitionObject } from '../shared/submit-data-respon import { SubmissionPatchRequest } from '../data/request.models'; import { CoreState } from '../core.reducers'; +/** + * A service that provides methods to make JSON Patch requests. + */ @Injectable() export class SubmissionJsonPatchOperationsService extends JsonPatchOperationsService { protected linkPath = ''; diff --git a/src/app/core/submission/submission-response-parsing.service.ts b/src/app/core/submission/submission-response-parsing.service.ts index abce34808e..d793b90e56 100644 --- a/src/app/core/submission/submission-response-parsing.service.ts +++ b/src/app/core/submission/submission-response-parsing.service.ts @@ -18,6 +18,11 @@ import { FormFieldMetadataValueObject } from '../../shared/form/builder/models/f import { SubmissionObject } from './models/submission-object.model'; import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory'; +/** + * Export a function to check if object has same properties of FormFieldMetadataValueObject + * + * @param obj + */ export function isServerFormValue(obj: any): boolean { return (typeof obj === 'object' && obj.hasOwnProperty('value') @@ -27,6 +32,11 @@ export function isServerFormValue(obj: any): boolean { && obj.hasOwnProperty('place')) } +/** + * Export a function to normalize sections object of the server response + * + * @param obj + */ export function normalizeSectionData(obj: any) { let result: any = obj; if (isNotNull(obj)) { @@ -74,6 +84,13 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService super(); } + /** + * Parses data from the workspaceitems/workflowitems endpoints + * + * @param {RestRequest} request + * @param {DSpaceRESTV2Response} data + * @returns {RestResponse} + */ parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) @@ -93,6 +110,13 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService } } + /** + * Parses response and normalize it + * + * @param {DSpaceRESTV2Response} data + * @param {string} requestHref + * @returns {any[]} + */ protected processResponse(data: any, requestHref: string): any[] { const dataDefinition = this.process(data, requestHref); const normalizedDefinition = Array.of(); diff --git a/src/app/core/submission/submission-rest.service.ts b/src/app/core/submission/submission-rest.service.ts index a249f10c6f..e2b8bb01c8 100644 --- a/src/app/core/submission/submission-rest.service.ts +++ b/src/app/core/submission/submission-rest.service.ts @@ -22,7 +22,7 @@ import { ErrorResponse, RestResponse, SubmissionSuccessResponse } from '../cache import { getResponseFromEntry } from '../shared/operators'; /** - * The service handling all submission requests + * The service handling all submission REST requests */ @Injectable() export class SubmissionRestService { diff --git a/src/app/core/submission/workflowitem-data.service.ts b/src/app/core/submission/workflowitem-data.service.ts index 266d2b5411..e739a62e81 100644 --- a/src/app/core/submission/workflowitem-data.service.ts +++ b/src/app/core/submission/workflowitem-data.service.ts @@ -14,6 +14,9 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { ObjectCacheService } from '../cache/object-cache.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; +/** + * A service that provides methods to make REST requests with workflowitems endpoint. + */ @Injectable() export class WorkflowitemDataService extends DataService { protected linkPath = 'workflowitems'; diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 119bfb66cc..3bb3eb1ee8 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -14,6 +14,9 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { ObjectCacheService } from '../cache/object-cache.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; +/** + * A service that provides methods to make REST requests with workspaceitems endpoint. + */ @Injectable() export class WorkspaceitemDataService extends DataService { protected linkPath = 'workspaceitems'; diff --git a/src/app/shared/alerts/alerts.component.ts b/src/app/shared/alerts/alerts.component.ts index c9fc0ec9cc..d5fc2b48c7 100644 --- a/src/app/shared/alerts/alerts.component.ts +++ b/src/app/shared/alerts/alerts.component.ts @@ -4,6 +4,9 @@ import { trigger } from '@angular/animations'; import { AlertType } from './aletrs-type'; import { fadeOutLeave, fadeOutState } from '../animations/fade'; +/** + * This component allow to create div that uses the Bootstrap's Alerts component. + */ @Component({ selector: 'ds-alert', encapsulation: ViewEncapsulation.None, @@ -15,20 +18,49 @@ import { fadeOutLeave, fadeOutState } from '../animations/fade'; templateUrl: './alerts.component.html', styleUrls: ['./alerts.component.scss'] }) - export class AlertsComponent { + /** + * The alert content + */ @Input() content: string; + + /** + * A boolean representing if alert is dismissible + */ @Input() dismissible = false; + + /** + * The alert type + */ @Input() type: AlertType; + + /** + * An event fired when alert is dismissed. + */ @Output() close: EventEmitter = new EventEmitter(); + /** + * The initial animation name + */ public animate = 'fadeIn'; + + /** + * A boolean representing if alert is dismissed or not + */ public dismissed = false; + /** + * Initialize instance variables + * + * @param {ChangeDetectorRef} cdr + */ constructor(private cdr: ChangeDetectorRef) { } + /** + * Dismiss div with animation + */ dismiss() { if (this.dismissible) { this.animate = 'fadeOut'; diff --git a/src/app/shared/authority-confidence/authority-confidence-state.directive.ts b/src/app/shared/authority-confidence/authority-confidence-state.directive.ts index da62204d10..6362daf3c7 100644 --- a/src/app/shared/authority-confidence/authority-confidence-state.directive.ts +++ b/src/app/shared/authority-confidence/authority-confidence-state.directive.ts @@ -19,25 +19,55 @@ import { isNotEmpty, isNull } from '../empty.util'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { ConfidenceIconConfig } from '../../../config/submission-config.interface'; +/** + * Directive to add to the element a bootstrap utility class based on metadata confidence value + */ @Directive({ selector: '[dsAuthorityConfidenceState]' }) export class AuthorityConfidenceStateDirective implements OnChanges { + /** + * The metadata value + */ @Input() authorityValue: AuthorityValue | FormFieldMetadataValueObject | string; + + /** + * A boolean representing if to show html icon if authority value is empty + */ @Input() visibleWhenAuthorityEmpty = true; + /** + * The css class applied before directive changes + */ private previousClass: string = null; + + /** + * The css class applied after directive changes + */ private newClass: string; + /** + * An event fired when click on element that has a confidence value empty or different from CF_ACCEPTED + */ @Output() whenClickOnConfidenceNotAccepted: EventEmitter = new EventEmitter(); + /** + * Listener to click event + */ @HostListener('click') onClick() { if (isNotEmpty(this.authorityValue) && this.getConfidenceByValue(this.authorityValue) !== ConfidenceType.CF_ACCEPTED) { this.whenClickOnConfidenceNotAccepted.emit(this.getConfidenceByValue(this.authorityValue)); } } + /** + * Initialize instance variables + * + * @param {GlobalConfig} EnvConfig + * @param {ElementRef} elem + * @param {Renderer2} renderer + */ constructor( @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, private elem: ElementRef, @@ -45,6 +75,11 @@ export class AuthorityConfidenceStateDirective implements OnChanges { ) { } + /** + * Apply css class to element whenever authority value change + * + * @param {SimpleChanges} changes + */ ngOnChanges(changes: SimpleChanges): void { if (!changes.authorityValue.firstChange) { this.previousClass = this.getClassByConfidence(this.getConfidenceByValue(changes.authorityValue.previousValue)) @@ -59,6 +94,9 @@ export class AuthorityConfidenceStateDirective implements OnChanges { } } + /** + * Apply css class to element after view init + */ ngAfterViewInit() { if (isNull(this.previousClass)) { this.renderer.addClass(this.elem.nativeElement, this.newClass); @@ -68,6 +106,11 @@ export class AuthorityConfidenceStateDirective implements OnChanges { } } + /** + * Return confidence value as ConfidenceType + * + * @param value + */ private getConfidenceByValue(value: any): ConfidenceType { let confidence: ConfidenceType = ConfidenceType.CF_UNSET; @@ -82,6 +125,11 @@ export class AuthorityConfidenceStateDirective implements OnChanges { return confidence; } + /** + * Return the properly css class based on confidence value + * + * @param confidence + */ private getClassByConfidence(confidence: any): string { if (!this.visibleWhenAuthorityEmpty && confidence === ConfidenceType.CF_UNSET) { return 'd-none'; diff --git a/src/app/shared/utils/object-ngfor.pipe.ts b/src/app/shared/utils/object-ngfor.pipe.ts index 4715d5c151..982e3342e0 100644 --- a/src/app/shared/utils/object-ngfor.pipe.ts +++ b/src/app/shared/utils/object-ngfor.pipe.ts @@ -1,5 +1,13 @@ import { Pipe, PipeTransform } from '@angular/core'; +/** + * Pipe that allows to iterate over an object and to access to entry key and value : + * + *
+ * {{obj.key}} - {{obj.value}} + *
+ * + */ @Pipe({ name: 'dsObjNgFor' }) diff --git a/src/app/submission/selectors.ts b/src/app/submission/selectors.ts index b52c44b7b1..51c960b537 100644 --- a/src/app/submission/selectors.ts +++ b/src/app/submission/selectors.ts @@ -4,7 +4,9 @@ import { hasValue } from '../shared/empty.util'; import { submissionSelector, SubmissionState } from './submission.reducers'; import { SubmissionObjectEntry, SubmissionSectionObject } from './objects/submission-objects.reducer'; -// @TODO: Merge with keySelector function present in 'src/app/core/shared/selectors.ts' +/** + * Export a function to return a subset of the state by key + */ export function keySelector(parentSelector: Selector, subState: string, key: string): MemoizedSelector { return createSelector(parentSelector, (state: T) => { if (hasValue(state) && hasValue(state[subState])) { @@ -15,6 +17,9 @@ export function keySelector(parentSelector: Selector, subState: }); } +/** + * Export a function to return a subset of the state + */ export function subStateSelector(parentSelector: Selector, subState: string): MemoizedSelector { return createSelector(parentSelector, (state: T) => { if (hasValue(state) && hasValue(state[subState])) { diff --git a/src/app/submission/submission.reducers.ts b/src/app/submission/submission.reducers.ts index 39069b2917..939c4654ad 100644 --- a/src/app/submission/submission.reducers.ts +++ b/src/app/submission/submission.reducers.ts @@ -5,6 +5,9 @@ import { SubmissionObjectState } from './objects/submission-objects.reducer'; +/** + * The Submission State + */ export interface SubmissionState { 'objects': SubmissionObjectState } diff --git a/src/app/submission/submit/submission-submit.component.ts b/src/app/submission/submit/submission-submit.component.ts index c773093336..dbfd2f5a40 100644 --- a/src/app/submission/submit/submission-submit.component.ts +++ b/src/app/submission/submit/submission-submit.component.ts @@ -15,7 +15,7 @@ import { Collection } from '../../core/shared/collection.model'; * This component allows to submit a new workspaceitem. */ @Component({ - selector: 'ds-submit-page', + selector: 'ds-submission-submit', styleUrls: ['./submission-submit.component.scss'], templateUrl: './submission-submit.component.html' })