diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/model/persist/AnnotationPersist.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/model/persist/AnnotationPersist.java index e2f802a2e..ae931a8f8 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/model/persist/AnnotationPersist.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/model/persist/AnnotationPersist.java @@ -101,6 +101,9 @@ public class AnnotationPersist { .iff(() -> !this.isNull(item.getSubjectId())) .must(() -> this.isValidGuid(item.getSubjectId())) .failOn(AnnotationPersist._subjectId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationPersist._subjectId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isNull(item.getEntityId())) + .failOn(AnnotationPersist._entityId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationPersist._entityId}, LocaleContextHolder.getLocale())), this.spec() .iff(() -> !this.isNull(item.getEntityId())) .must(() -> this.isValidGuid(item.getEntityId())) diff --git a/dmp-frontend/src/annotation-service/core/model/annotation.model.ts b/dmp-frontend/src/annotation-service/core/model/annotation.model.ts new file mode 100644 index 000000000..7974172e5 --- /dev/null +++ b/dmp-frontend/src/annotation-service/core/model/annotation.model.ts @@ -0,0 +1,21 @@ +import { IsActive } from "@app/core/common/enum/is-active.enum"; +import { Guid } from "@common/types/guid"; + +export interface Annotation { + id: Guid; + entityId: Guid; + entityType: string; + anchor?: string; + payload: string; + createdAt: Date; + updatedAt: Date; + isActive: IsActive; +} + +export interface AnnotationPersist { + subjectId: Guid; + entityId: Guid; + entityType: string; + anchor: string; + payload: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/annotation-service/core/query/annotation.lookup.ts b/dmp-frontend/src/annotation-service/core/query/annotation.lookup.ts new file mode 100644 index 000000000..4d764262b --- /dev/null +++ b/dmp-frontend/src/annotation-service/core/query/annotation.lookup.ts @@ -0,0 +1,27 @@ +import { IsActive } from "@app/core/common/enum/is-active.enum"; +import { Lookup } from "@common/model/lookup"; +import { Guid } from "@common/types/guid"; + +export class AnnotationLookup extends Lookup implements AnnotationFilter { + + like: string; + ids: Guid[]; + excludedIds: Guid[]; + isActive: IsActive; + entityIds: Guid[]; + entityTypes: string[]; + + constructor() { + super(); + } + +} + +export interface AnnotationFilter { + like: string; + ids: Guid[]; + excludedIds: Guid[]; + isActive: IsActive; + entityIds: Guid[]; + entityTypes: string[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/annotation-service/services/core-service.module.ts b/dmp-frontend/src/annotation-service/services/core-service.module.ts new file mode 100644 index 000000000..4e967df1c --- /dev/null +++ b/dmp-frontend/src/annotation-service/services/core-service.module.ts @@ -0,0 +1,37 @@ +// +// +// This is shared module that provides all annotation service's services. Its imported only once on the AppModule. +// + +import { ModuleWithProviders, NgModule, Optional, SkipSelf } from "@angular/core"; +import { BaseHttpV2Service } from "@app/core/services/http/base-http-v2.service"; +import { PrincipalService } from "@app/core/services/http/principal.service"; +import { LoggingService } from "@app/core/services/logging/logging-service"; +import { FormService } from "@common/forms/form-service"; +import { HttpErrorHandlingService } from "@common/modules/errors/error-handling/http-error-handling.service"; +import { FilterService } from "@common/modules/text-filter/filter-service"; +import { AnnotationService } from "@annotation-service/services/http/annotation.service"; + +@NgModule({}) +export class CoreAnnotationServiceModule { + constructor(@Optional() @SkipSelf() parentModule: CoreAnnotationServiceModule) { + if (parentModule) { + throw new Error( + 'CoreAnnotationServiceModule is already loaded. Import it in the AppModule only'); + } + } + static forRoot(): ModuleWithProviders { + return { + ngModule: CoreAnnotationServiceModule, + providers: [ + BaseHttpV2Service, + HttpErrorHandlingService, + FilterService, + FormService, + LoggingService, + PrincipalService, + AnnotationService + ], + }; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/annotation-service/services/http/annotation.service.ts b/dmp-frontend/src/annotation-service/services/http/annotation.service.ts new file mode 100644 index 000000000..d89f5d059 --- /dev/null +++ b/dmp-frontend/src/annotation-service/services/http/annotation.service.ts @@ -0,0 +1,52 @@ +import { Injectable } from "@angular/core"; +import { Annotation, AnnotationPersist } from "@annotation-service/core/model/annotation.model"; +import { AnnotationLookup } from "@annotation-service/core/query/annotation.lookup"; +import { ConfigurationService } from "@app/core/services/configuration/configuration.service"; +import { BaseHttpV2Service } from "@app/core/services/http/base-http-v2.service"; +import { QueryResult } from "@common/model/query-result"; +import { Guid } from "@common/types/guid"; +import { Observable, throwError } from "rxjs"; +import { catchError } from "rxjs/operators"; + +@Injectable() +export class AnnotationService { + private get apiBase(): string { return `${this.installationConfiguration.annotationServiceAddress}api/annotation`; } + + constructor( + private installationConfiguration: ConfigurationService, + private http: BaseHttpV2Service + ) { } + + query(q: AnnotationLookup): Observable> { + const url = `${this.apiBase}/query`; + + return this.http + .post>(url, q).pipe( + catchError((error: any) => throwError(error))); + } + + getSingle(id: Guid, reqFields: string[] = []): Observable { + const url = `${this.apiBase}/${id}`; + const options = { params: { f: reqFields } }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + persist(item: AnnotationPersist) { + const url = `${this.apiBase}/persist`; + + return this.http + .post(url, item).pipe( + catchError((error: any) => throwError(error))); + } + + delete(id: Guid, ): Observable { + const url = `${this.apiBase}/${id}`; + return this.http + .delete(url).pipe( + catchError((error: any) => throwError(error))); + } + +} \ No newline at end of file diff --git a/dmp-frontend/src/app/app.module.ts b/dmp-frontend/src/app/app.module.ts index ab4bfef83..f94de1a24 100644 --- a/dmp-frontend/src/app/app.module.ts +++ b/dmp-frontend/src/app/app.module.ts @@ -38,6 +38,7 @@ import { MatomoService } from './core/services/matomo/matomo-service'; import { GuidedTourModule } from './library/guided-tour/guided-tour.module'; import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module'; import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-custom-translation-compiler'; +import { CoreAnnotationServiceModule } from 'annotation-service/services/core-service.module'; // AoT requires an exported function for factories export function HttpLoaderFactory(languageHttpService: LanguageHttpService) { @@ -118,6 +119,7 @@ export function InstallationConfigurationFactory(appConfig: ConfigurationService BrowserAnimationsModule, KeycloakAngularModule, CoreServiceModule.forRoot(), + CoreAnnotationServiceModule.forRoot(), AppRoutingModule, CommonUiModule, TranslateModule.forRoot({ diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index b9ebaae25..d23787420 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -118,6 +118,16 @@ export class ConfigurationService extends BaseComponent { return this._notificationServiceEnabled; } + private _annotationServiceAddress: string; + get annotationServiceAddress(): string { + return this._notificationServiceAddress || './'; + } + + private _annotationServiceEnabled: boolean; + get annotationServiceEnabled(): boolean { + return this._notificationServiceEnabled; + } + private _inAppNotificationsCountInterval: number; get inAppNotificationsCountInterval(): number { return this._inAppNotificationsCountInterval || 3200; @@ -183,6 +193,10 @@ export class ConfigurationService extends BaseComponent { this._notificationServiceEnabled = config.notification_service.enabled; this._notificationServiceAddress = config.notification_service.address; } + if (config.annotation_service) { + this._annotationServiceEnabled = config.annotation_service.enabled; + this._annotationServiceAddress = config.annotation_service.address; + } this._inAppNotificationsCountInterval = config.inAppNotificationsCountInterval; } diff --git a/dmp-frontend/tsconfig.json b/dmp-frontend/tsconfig.json index e892561de..1800d0668 100644 --- a/dmp-frontend/tsconfig.json +++ b/dmp-frontend/tsconfig.json @@ -24,6 +24,9 @@ ], "@common/*": [ "./common/*" + ], + "@annotation-service/*":[ + "./annotation-service/*" ] }, "useDefineForClassFields": false