mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merged in CST-11048 (pull request #905)
CST-11048 Approved-by: Andrea Bollini
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||
import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component';
|
||||
import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service';
|
||||
import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component';
|
||||
import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: LdnServicesOverviewComponent,
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
data: { title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new' },
|
||||
canActivate: [LdnServicesGuard]
|
||||
},
|
||||
{
|
||||
path: 'new',
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
component: LdnServiceNewComponent,
|
||||
data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' }
|
||||
},
|
||||
{
|
||||
path: 'edit/:serviceId',
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
component: LdnServiceFormEditComponent,
|
||||
data: { title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service' }
|
||||
},
|
||||
]),
|
||||
]
|
||||
})
|
||||
export class AdminLdnServicesRoutingModule {
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AdminLdnServicesRoutingModule } from './admin-ldn-services-routing.module';
|
||||
import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component';
|
||||
import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component';
|
||||
import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
AdminLdnServicesRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
LdnServicesOverviewComponent,
|
||||
LdnServiceNewComponent,
|
||||
LdnServiceFormComponent,
|
||||
LdnServiceFormEditComponent,
|
||||
]
|
||||
})
|
||||
export class AdminLdnServicesModule { }
|
@@ -0,0 +1,155 @@
|
||||
|
||||
<form (ngSubmit)="submitForm()" [formGroup]="formModel">
|
||||
|
||||
<div class="toggle-switch-container">
|
||||
<label for="enabled" class="status-label">{{ 'ldn-service-status' | translate }}</label>
|
||||
<div>
|
||||
<input formControlName="enabled" id="enabled" name="enabled" type="checkbox" hidden>
|
||||
<div class="toggle-switch" [class.checked]="formModel.get('enabled').value" (click)="toggleEnabled()">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label for="name">{{ 'ldn-new-service.form.label.name' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.name' | translate"
|
||||
formControlName="name" id="name" name="name"
|
||||
[class.invalid-field]="formModel.get('name').invalid && formModel.get('name').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-2 d-flex flex-column">
|
||||
<label for="description">{{ 'ldn-new-service.form.label.description' | translate }}</label>
|
||||
<textarea [placeholder]="'ldn-new-service.form.placeholder.description' | translate"
|
||||
formControlName="description" id="description" name="description"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label for="url">{{ 'ldn-new-service.form.label.url' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.url' | translate"
|
||||
formControlName="url" id="url" name="url"
|
||||
[class.invalid-field]="formModel.get('url').invalid && formModel.get('url').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label for="ldnUrl">{{ 'ldn-new-service.form.label.ldnUrl' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.ldnUrl' | translate"
|
||||
formControlName="ldnUrl" id="ldnUrl" name="ldnUrl"
|
||||
[class.invalid-field]="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index"
|
||||
class="mb-2 d-flex align-content-center" formGroupName="notifyServiceInboundPatterns">
|
||||
|
||||
<ng-container [formGroupName]="i">
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<label *ngIf="i === 0" for="additionalInboundPattern{{i}}">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label>
|
||||
<select #inboundPattern formControlName="pattern" id="additionalInboundPattern{{i}}"
|
||||
name="additionalInboundPattern{{i}}" required>
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.inboundPattern' | translate }}</option>
|
||||
<option *ngFor="let pattern of inboundPatterns" [ngValue]="pattern.name">{{ pattern.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="inboundPattern.value">
|
||||
|
||||
<div class="ml-2 flex-grow-1">
|
||||
<label *ngIf="i === 0" for="constraint{{i}}">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
|
||||
<select formControlName="constraint" id="constraint{{i}}" name="constraint{{i}}">
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.selectedItemFilter' | translate }}</option>
|
||||
<option *ngFor="let itemFilter of itemFilterList" [value]="itemFilter.name">{{ itemFilter.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="ml-2 d-flex flex-column align-content-center">
|
||||
<label *ngIf="i === 0" for="automatic{{i}}">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
|
||||
<div class="d-flex flex-grow-1 align-content-center justify-content-center">
|
||||
<input formControlName="automatic" id="automatic{{i}}" name="automatic{{i}}" type="checkbox" hidden>
|
||||
<div class="toggle-switch" [class.checked]="formModel.get('notifyServiceInboundPatterns.' + i + '.automatic').value" (click)="toggleAutomatic(i)">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<div class="d-flex align-items-end justify-content-center">
|
||||
<button (click)="removeInboundPattern(i)" class="btn btn-outline-dark trash-button ml-2">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<span (click)="addInboundPattern()" class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngFor="let patternGroup of formModel.get('notifyServiceOutboundPatterns')['controls']; let i = index"
|
||||
class="mb-2 d-flex align-content-center" formGroupName="notifyServiceOutboundPatterns">
|
||||
|
||||
<ng-container [formGroupName]="i">
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<label *ngIf="i === 0" for="additionalOutboundPattern{{i}}">{{ 'ldn-new-service.form.label.outboundPattern' | translate }}</label>
|
||||
<select #outboundPattern formControlName="pattern" id="additionalOutboundPattern{{i}}"
|
||||
name="additionalOutboundPattern{{i}}"
|
||||
required>
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.outboundPattern' | translate }}</option>
|
||||
<option *ngFor="let pattern of outboundPatterns" [ngValue]="pattern.name">{{ pattern.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div *ngIf="outboundPattern.value" class="ml-2 flex-grow-1">
|
||||
<label *ngIf="i === 0" for="constraint{{i}}">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
|
||||
<select formControlName="constraint" id="constraint{{i}}" name="constraint{{i}}">
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.selectedItemFilter' | translate }}</option>
|
||||
<option *ngFor="let itemFilter of itemFilterList" [value]="itemFilter.name">{{ itemFilter.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-end justify-content-center">
|
||||
<button (click)="removeOutboundPattern(i)" class="btn btn-outline-dark trash-button ml-2">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<span
|
||||
(click)="addOutboundPattern()" class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}
|
||||
</span>
|
||||
|
||||
<div class="mb-2">
|
||||
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit">{{ 'ldn-new-service.form.label.submit' | translate }}</button>
|
||||
</form>
|
@@ -0,0 +1,114 @@
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
max-width: 800px;
|
||||
font-size: 14px;
|
||||
margin-left: 300px;
|
||||
|
||||
& > * {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
select {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
option:not(:first-child) {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.trash-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
height: 200px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.add-pattern-link{
|
||||
color: #0048ff;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.remove-pattern-link{
|
||||
color: #e34949;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.status-checkbox {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
.invalid-field {
|
||||
border: 1px solid red;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.8;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
background-color: #ccc;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.toggle-switch.checked {
|
||||
background-color: #24cc9a;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.toggle-switch .slider {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.toggle-switch.checked .slider {
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
.toggle-switch-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnServiceFormEditComponent } from './ldn-service-form-edit.component';
|
||||
|
||||
describe('LdnServiceFormEditComponent', () => {
|
||||
let component: LdnServiceFormEditComponent;
|
||||
let fixture: ComponentFixture<LdnServiceFormEditComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LdnServiceFormEditComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LdnServiceFormEditComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,374 @@
|
||||
import { ChangeDetectorRef, Component, Input } from '@angular/core';
|
||||
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type';
|
||||
import { Router } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service';
|
||||
import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service';
|
||||
import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model';
|
||||
import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-ldn-service-form-edit',
|
||||
templateUrl: './ldn-service-form-edit.component.html',
|
||||
styleUrls: ['./ldn-service-form-edit.component.scss'],
|
||||
animations: [
|
||||
trigger('toggleAnimation', [
|
||||
state('true', style({})),
|
||||
state('false', style({})),
|
||||
transition('true <=> false', animate('300ms ease-in')),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class LdnServiceFormEditComponent {
|
||||
formModel: FormGroup;
|
||||
|
||||
showItemFilterDropdown = false;
|
||||
|
||||
private originalInboundPatterns: any[] = [];
|
||||
private originalOutboundPatterns: any[] = [];
|
||||
public inboundPatterns: object[] = notifyPatterns;
|
||||
public outboundPatterns: object[] = notifyPatterns;
|
||||
public itemFilterList: LdnServiceConstraint[];
|
||||
|
||||
@Input() public name: string;
|
||||
@Input() public description: string;
|
||||
@Input() public url: string;
|
||||
@Input() public ldnUrl: string;
|
||||
@Input() public inboundPattern: string;
|
||||
@Input() public outboundPattern: string;
|
||||
@Input() public constraint: string;
|
||||
@Input() public automatic: boolean;
|
||||
|
||||
@Input() public headerKey: string;
|
||||
private serviceId: string;
|
||||
|
||||
constructor(
|
||||
private ldnServicesService: LdnServicesService,
|
||||
private ldnDirectoryService: LdnDirectoryService,
|
||||
private formBuilder: FormBuilder,
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private cdRef: ChangeDetectorRef
|
||||
) {
|
||||
|
||||
this.formModel = this.formBuilder.group({
|
||||
id: [''],
|
||||
name: ['', Validators.required],
|
||||
description: ['', Validators.required],
|
||||
url: ['', Validators.required],
|
||||
ldnUrl: ['', Validators.required],
|
||||
inboundPattern: [''],
|
||||
outboundPattern: [''],
|
||||
constraintPattern: [''],
|
||||
enabled: [''],
|
||||
notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]),
|
||||
notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]),
|
||||
type: LDN_SERVICE.value,
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.params.subscribe((params) => {
|
||||
this.serviceId = params.serviceId;
|
||||
if (this.serviceId) {
|
||||
this.fetchServiceData(this.serviceId);
|
||||
}
|
||||
});
|
||||
this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => {
|
||||
this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({
|
||||
name: filter.id
|
||||
}));
|
||||
this.cdRef.detectChanges();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private getOriginalPattern(formArrayName: string, patternId: number): any {
|
||||
let originalPatterns: any[] = [];
|
||||
|
||||
if (formArrayName === 'notifyServiceInboundPatterns') {
|
||||
originalPatterns = this.originalInboundPatterns;
|
||||
} else if (formArrayName === 'notifyServiceOutboundPatterns') {
|
||||
originalPatterns = this.originalOutboundPatterns;
|
||||
}
|
||||
|
||||
return originalPatterns.find((pattern) => pattern.id === patternId);
|
||||
}
|
||||
|
||||
private patternsAreEqual(patternA: any, patternB: any): boolean {
|
||||
return (
|
||||
patternA.pattern === patternB.pattern &&
|
||||
patternA.constraint === patternB.constraint &&
|
||||
patternA.automatic === patternB.automatic
|
||||
);
|
||||
}
|
||||
|
||||
fetchServiceData(serviceId: string): void {
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`;
|
||||
|
||||
this.http.get(apiUrl).subscribe(
|
||||
(data: any) => {
|
||||
console.log(data);
|
||||
|
||||
this.formModel.patchValue({
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
url: data.url,
|
||||
ldnUrl: data.ldnUrl,
|
||||
type: data.type,
|
||||
enabled: data.enabled
|
||||
});
|
||||
|
||||
const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
inboundPatternsArray.clear(); // Clear existing rows
|
||||
|
||||
data.notifyServiceInboundPatterns.forEach((pattern: any) => {
|
||||
console.log(pattern);
|
||||
const patternFormGroup = this.initializeInboundPatternFormGroup();
|
||||
console.log();
|
||||
patternFormGroup.patchValue(pattern);
|
||||
inboundPatternsArray.push(patternFormGroup);
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
|
||||
const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray;
|
||||
outboundPatternsArray.clear();
|
||||
|
||||
data.notifyServiceOutboundPatterns.forEach((pattern: any) => {
|
||||
const patternFormGroup = this.initializeOutboundPatternFormGroup();
|
||||
patternFormGroup.patchValue(pattern);
|
||||
outboundPatternsArray.push(patternFormGroup);
|
||||
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
this.originalInboundPatterns = [...data.notifyServiceInboundPatterns];
|
||||
|
||||
this.originalOutboundPatterns = [...data.notifyServiceOutboundPatterns];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching service data:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
generatePatchOperations(): any[] {
|
||||
const patchOperations: any[] = [];
|
||||
|
||||
this.addReplaceOperation(patchOperations, 'name', '/name');
|
||||
this.addReplaceOperation(patchOperations, 'description', '/description');
|
||||
this.addReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl');
|
||||
this.addReplaceOperation(patchOperations, 'url', '/url');
|
||||
|
||||
this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns');
|
||||
|
||||
this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns');
|
||||
|
||||
return patchOperations;
|
||||
}
|
||||
|
||||
private addReplaceOperation(patchOperations: any[], formControlName: string, path: string): void {
|
||||
if (this.formModel.get(formControlName).dirty) {
|
||||
patchOperations.push({
|
||||
op: 'replace',
|
||||
path,
|
||||
value: this.formModel.get(formControlName).value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private handlePatterns(patchOperations: any[], formArrayName: string): void {
|
||||
const patternsArray = this.formModel.get(formArrayName) as FormArray;
|
||||
|
||||
if (patternsArray.dirty) {
|
||||
for (let i = 0; i < patternsArray.length; i++) {
|
||||
const patternGroup = patternsArray.at(i) as FormGroup;
|
||||
const patternValue = patternGroup.value;
|
||||
|
||||
if (patternValue.isNew) {
|
||||
console.log(this.getOriginalPatternsForFormArray(formArrayName));
|
||||
console.log(patternGroup);
|
||||
delete patternValue.isNew;
|
||||
const addOperation = {
|
||||
op: 'add',
|
||||
path: `${formArrayName}/-`,
|
||||
value: patternValue,
|
||||
};
|
||||
patchOperations.push(addOperation);
|
||||
} else if (patternGroup.dirty) {
|
||||
const replaceOperation = {
|
||||
op: 'replace',
|
||||
path: `${formArrayName}[${i}]`,
|
||||
value: patternValue,
|
||||
};
|
||||
patchOperations.push(replaceOperation);
|
||||
console.log(patternValue.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getOriginalPatternsForFormArray(formArrayName: string): any[] {
|
||||
if (formArrayName === 'notifyServiceInboundPatterns') {
|
||||
return this.originalInboundPatterns;
|
||||
} else if (formArrayName === 'notifyServiceOutboundPatterns') {
|
||||
return this.originalOutboundPatterns;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
submitForm() {
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.serviceId}`;
|
||||
const patchOperations = this.generatePatchOperations();
|
||||
|
||||
this.http.patch(apiUrl, patchOperations).subscribe(
|
||||
(response) => {
|
||||
console.log('Service updated successfully:', response);
|
||||
this.sendBack();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error updating service:', error);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
addInboundPattern() {
|
||||
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup());
|
||||
}
|
||||
|
||||
removeInboundPattern(index: number) {
|
||||
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
if (index >= 0 && index < notifyServiceInboundPatternsArray.length) {
|
||||
const serviceId = this.formModel.get('id').value;
|
||||
|
||||
const patchOperation = [
|
||||
{
|
||||
op: 'remove',
|
||||
path: `notifyServiceInboundPatterns[${index}]`
|
||||
}
|
||||
];
|
||||
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`;
|
||||
|
||||
this.http.patch(apiUrl, patchOperation).subscribe(
|
||||
(response) => {
|
||||
console.log('Pattern removed successfully:', response);
|
||||
|
||||
notifyServiceInboundPatternsArray.removeAt(index);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error removing pattern:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
addOutboundPattern() {
|
||||
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray;
|
||||
notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup());
|
||||
}
|
||||
|
||||
removeOutboundPattern(index: number) {
|
||||
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray;
|
||||
if (index >= 0 && index < notifyServiceOutboundPatternsArray.length) {
|
||||
const serviceId = this.formModel.get('id').value;
|
||||
|
||||
|
||||
const patchOperation = [
|
||||
{
|
||||
op: 'remove',
|
||||
path: `notifyServiceOutboundPatterns[${index}]`
|
||||
}
|
||||
];
|
||||
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`;
|
||||
|
||||
this.http.patch(apiUrl, patchOperation).subscribe(
|
||||
(response) => {
|
||||
console.log('Pattern removed successfully:', response);
|
||||
|
||||
notifyServiceOutboundPatternsArray.removeAt(index);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error removing pattern:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private sendBack() {
|
||||
this.router.navigateByUrl('admin/ldn/services');
|
||||
}
|
||||
|
||||
private createOutboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: '',
|
||||
constraint: '',
|
||||
isNew: true,
|
||||
});
|
||||
}
|
||||
|
||||
private createInboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: '',
|
||||
constraint: '',
|
||||
automatic: '',
|
||||
isNew: true
|
||||
});
|
||||
}
|
||||
|
||||
private initializeOutboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: '',
|
||||
constraint: '',
|
||||
});
|
||||
}
|
||||
|
||||
private initializeInboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: '',
|
||||
constraint: '',
|
||||
automatic: '',
|
||||
});
|
||||
}
|
||||
|
||||
toggleAutomatic(i: number) {
|
||||
const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`);
|
||||
if (automaticControl) {
|
||||
automaticControl.setValue(!automaticControl.value);
|
||||
}
|
||||
}
|
||||
|
||||
toggleEnabled() {
|
||||
const newStatus = !this.formModel.get('enabled').value;
|
||||
const serviceId = this.formModel.get('id').value;
|
||||
const status = this.formModel.get('enabled').value;
|
||||
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`;
|
||||
const patchOperation = {
|
||||
op: 'replace',
|
||||
path: '/enabled',
|
||||
value: newStatus,
|
||||
};
|
||||
|
||||
this.http.patch(apiUrl, [patchOperation]).subscribe(
|
||||
() => {
|
||||
console.log('Status updated successfully.');
|
||||
this.formModel.get('enabled').setValue(newStatus);
|
||||
console.log(this.formModel.get('enabled'));
|
||||
this.cdRef.detectChanges();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error updating status:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,163 @@
|
||||
<form (ngSubmit)="submitForm()" [formGroup]="formModel">
|
||||
|
||||
<!-- In the name section -->
|
||||
<div class="mb-2">
|
||||
<label for="name">{{ 'ldn-new-service.form.label.name' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.name' | translate"
|
||||
formControlName="name" id="name" name="name"
|
||||
[class.invalid-field]="formModel.get('name').invalid && formModel.get('name').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- In the description section -->
|
||||
<div class="mb-2 d-flex flex-column">
|
||||
<label for="description">{{ 'ldn-new-service.form.label.description' | translate }}</label>
|
||||
<textarea [placeholder]="'ldn-new-service.form.placeholder.description' | translate"
|
||||
formControlName="description" id="description" name="description"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- In the url section -->
|
||||
<div class="mb-2">
|
||||
<label for="url">{{ 'ldn-new-service.form.label.url' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.url' | translate"
|
||||
formControlName="url" id="url" name="url"
|
||||
[class.invalid-field]="formModel.get('url').invalid && formModel.get('url').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- In the ldnUrl section -->
|
||||
<div class="mb-2">
|
||||
<label for="ldnUrl">{{ 'ldn-new-service.form.label.ldnUrl' | translate }}</label>
|
||||
<input [placeholder]="'ldn-new-service.form.placeholder.ldnUrl' | translate"
|
||||
formControlName="ldnUrl" id="ldnUrl" name="ldnUrl"
|
||||
[class.invalid-field]="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched"
|
||||
type="text">
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- In the Inbound Patterns section -->
|
||||
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index"
|
||||
class="mb-2 d-flex align-content-center" formGroupName="notifyServiceInboundPatterns">
|
||||
|
||||
<ng-container [formGroupName]="i">
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<label *ngIf="i === 0" for="additionalInboundPattern{{i}}">{{ 'ldn-new-service.form.label.inboundPattern' | translate }}</label>
|
||||
|
||||
<select #inboundPattern formControlName="pattern" id="additionalInboundPattern{{i}}"
|
||||
name="additionalInboundPattern{{i}}" required>
|
||||
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.inboundPattern' | translate }}</option>
|
||||
<option *ngFor="let pattern of inboundPatterns" [ngValue]="pattern.name">{{ pattern.name }}</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="inboundPattern.value">
|
||||
|
||||
<div class="ml-2 flex-grow-1">
|
||||
<label *ngIf="i === 0" for="constraint{{i}}">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
|
||||
|
||||
<select formControlName="constraint" id="constraint{{i}}" name="constraint{{i}}">
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.selectedItemFilter' | translate }}</option>
|
||||
<option *ngFor="let itemFilter of itemFilterList"
|
||||
[value]="itemFilter.name">{{ itemFilter.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="ml-2 d-flex flex-column align-content-center">
|
||||
<label *ngIf="i === 0" for="automatic{{i}}">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
|
||||
<div class="d-flex flex-grow-1 align-content-center justify-content-center">
|
||||
<input formControlName="automatic" id="automatic{{i}}" name="automatic{{i}}" type="checkbox" hidden>
|
||||
<div class="toggle-switch" [class.checked]="formModel.get('notifyServiceInboundPatterns.' + i + '.automatic').value" (click)="toggleAutomatic(i)">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</ng-container>
|
||||
|
||||
<div class="d-flex align-items-end justify-content-center">
|
||||
<button (click)="removeInboundPattern(patternGroup)" class="btn btn-outline-dark trash-button ml-2">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<span (click)="addInboundPattern()"
|
||||
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
|
||||
|
||||
<div class="mb-4">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- In the Outbound Patterns section -->
|
||||
<div *ngFor="let patternGroup of formModel.get('notifyServiceOutboundPatterns')['controls']; let i = index"
|
||||
class="mb-2 d-flex align-content-center" formGroupName="notifyServiceOutboundPatterns">
|
||||
|
||||
<ng-container [formGroupName]="i">
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<label *ngIf="i === 0" for="additionalOutboundPattern{{i}}">{{ 'ldn-new-service.form.label.outboundPattern' | translate }}</label>
|
||||
|
||||
<select #outboundPattern formControlName="pattern" id="additionalOutboundPattern{{i}}"
|
||||
name="additionalOutboundPattern{{i}}"
|
||||
required>
|
||||
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.outboundPattern' | translate }}</option>
|
||||
<option *ngFor="let pattern of outboundPatterns"
|
||||
[ngValue]="pattern.name">{{ pattern.name }}</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div *ngIf="outboundPattern.value" class="ml-2 flex-grow-1">
|
||||
|
||||
<label *ngIf="i === 0" for="constraint{{i}}">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
|
||||
|
||||
<select formControlName="constraint" id="constraint{{i}}" name="constraint{{i}}">
|
||||
<option value="">{{ 'ldn-new-service.form.label.placeholder.selectedItemFilter' | translate }}</option>
|
||||
<option *ngFor="let itemFilter of itemFilterList"
|
||||
[value]="itemFilter.name">{{ itemFilter.name }}</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-end justify-content-center">
|
||||
<button (click)="removeOutboundPattern(patternGroup)" class="btn btn-outline-dark trash-button ml-2">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<span (click)="addOutboundPattern()"
|
||||
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}
|
||||
</span>
|
||||
<div class="mb-2">
|
||||
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">{{ 'ldn-new-service.form.label.submit' | translate }}</button>
|
||||
</form>
|
@@ -0,0 +1,114 @@
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
max-width: 800px;
|
||||
font-size: 14px;
|
||||
margin-left: 300px;
|
||||
|
||||
& > * {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
select {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
option:not(:first-child) {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.trash-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
height: 200px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.add-pattern-link{
|
||||
color: #0048ff;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.remove-pattern-link{
|
||||
color: #e34949;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.status-checkbox {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
.invalid-field {
|
||||
border: 1px solid red;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.8;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
background-color: #ccc;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.toggle-switch.checked {
|
||||
background-color: #24cc9a;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.toggle-switch .slider {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.toggle-switch.checked .slider {
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
.toggle-switch-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnServiceFormComponent } from './ldn-service-form.component';
|
||||
|
||||
describe('LdnServiceFormComponent', () => {
|
||||
let component: LdnServiceFormComponent;
|
||||
let fixture: ComponentFixture<LdnServiceFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LdnServiceFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LdnServiceFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,171 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service';
|
||||
import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model';
|
||||
import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns';
|
||||
import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service';
|
||||
import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-ldn-service-form',
|
||||
templateUrl: './ldn-service-form.component.html',
|
||||
styleUrls: ['./ldn-service-form.component.scss'],
|
||||
animations: [
|
||||
trigger('toggleAnimation', [
|
||||
state('true', style({})), // Define animation states (empty style)
|
||||
state('false', style({})),
|
||||
transition('true <=> false', animate('300ms ease-in')), // Define animation transition with duration
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class LdnServiceFormComponent implements OnInit {
|
||||
formModel: FormGroup;
|
||||
|
||||
|
||||
|
||||
//showItemFilterDropdown = false;
|
||||
|
||||
public inboundPatterns: object[] = notifyPatterns;
|
||||
public outboundPatterns: object[] = notifyPatterns;
|
||||
public itemFilterList: LdnServiceConstraint[];
|
||||
//additionalOutboundPatterns: FormGroup[] = [];
|
||||
//additionalInboundPatterns: FormGroup[] = [];
|
||||
|
||||
|
||||
//@Input() public status: boolean;
|
||||
@Input() public name: string;
|
||||
@Input() public description: string;
|
||||
@Input() public url: string;
|
||||
@Input() public ldnUrl: string;
|
||||
@Input() public inboundPattern: string;
|
||||
@Input() public outboundPattern: string;
|
||||
@Input() public constraint: string;
|
||||
@Input() public automatic: boolean;
|
||||
|
||||
@Input() public headerKey: string;
|
||||
|
||||
/*
|
||||
get notifyServiceInboundPatternsFormArray(): FormArray {
|
||||
return this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
}
|
||||
*/
|
||||
|
||||
constructor(
|
||||
private ldnServicesService: LdnServicesService,
|
||||
private ldnDirectoryService: LdnDirectoryService,
|
||||
private formBuilder: FormBuilder,
|
||||
private http: HttpClient,
|
||||
private router: Router
|
||||
) {
|
||||
|
||||
this.formModel = this.formBuilder.group({
|
||||
enabled: true,
|
||||
id: [''],
|
||||
name: ['', Validators.required],
|
||||
description: [''],
|
||||
url: ['', Validators.required],
|
||||
ldnUrl: ['', Validators.required],
|
||||
inboundPattern: [''],
|
||||
outboundPattern: [''],
|
||||
constraintPattern: [''],
|
||||
notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]),
|
||||
notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]),
|
||||
type: LDN_SERVICE.value,
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => {
|
||||
console.log(itemFilters);
|
||||
this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({
|
||||
name: filter.id
|
||||
}));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
submitForm() {
|
||||
this.formModel.get('name').markAsTouched();
|
||||
this.formModel.get('url').markAsTouched();
|
||||
this.formModel.get('ldnUrl').markAsTouched();
|
||||
|
||||
const name = this.formModel.get('name').value;
|
||||
const url = this.formModel.get('url').value;
|
||||
const ldnUrl = this.formModel.get('ldnUrl').value;
|
||||
|
||||
if (!name || !url || !ldnUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.formModel.removeControl('inboundPattern');
|
||||
this.formModel.removeControl('outboundPattern');
|
||||
this.formModel.removeControl('constraintPattern');
|
||||
console.log('JSON Data:', this.formModel.value);
|
||||
|
||||
const apiUrl = 'http://localhost:8080/server/api/ldn/ldnservices';
|
||||
|
||||
this.http.post(apiUrl, this.formModel.value).subscribe(
|
||||
(response) => {
|
||||
console.log('Service created successfully:', response);
|
||||
this.formModel.reset();
|
||||
this.sendBack();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error creating service:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private sendBack() {
|
||||
this.router.navigateByUrl('admin/ldn/services');
|
||||
}
|
||||
|
||||
addInboundPattern() {
|
||||
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup());
|
||||
}
|
||||
|
||||
removeInboundPattern(patternGroup: FormGroup) {
|
||||
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
|
||||
notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup));
|
||||
}
|
||||
|
||||
addOutboundPattern() {
|
||||
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray;
|
||||
notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup());
|
||||
}
|
||||
|
||||
removeOutboundPattern(patternGroup: FormGroup) {
|
||||
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray;
|
||||
notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup));
|
||||
}
|
||||
|
||||
private createOutboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: [''],
|
||||
constraint: [''],
|
||||
});
|
||||
}
|
||||
|
||||
private createInboundPatternFormGroup(): FormGroup {
|
||||
return this.formBuilder.group({
|
||||
pattern: [''],
|
||||
constraint: [''],
|
||||
automatic: false
|
||||
});
|
||||
}
|
||||
|
||||
toggleAutomatic(i: number) {
|
||||
const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`);
|
||||
if (automaticControl) {
|
||||
automaticControl.setValue(!automaticControl.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
<ds-ldn-service-form></ds-ldn-service-form>
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnServiceNewComponent } from './ldn-service-new.component';
|
||||
|
||||
describe('LdnServiceNewComponent', () => {
|
||||
let component: LdnServiceNewComponent;
|
||||
let fixture: ComponentFixture<LdnServiceNewComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LdnServiceNewComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LdnServiceNewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,28 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LdnService } from "../ldn-services-model/ldn-services.model";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ProcessDataService } from "../../../core/data/processes/process-data.service";
|
||||
import { LinkService } from "../../../core/cache/builders/link.service";
|
||||
import { getFirstSucceededRemoteDataPayload } from "../../../core/shared/operators";
|
||||
|
||||
@Component({
|
||||
selector: 'ds-ldn-service-new',
|
||||
templateUrl: './ldn-service-new.component.html',
|
||||
styleUrls: ['./ldn-service-new.component.scss']
|
||||
})
|
||||
export class LdnServiceNewComponent implements OnInit {
|
||||
/**
|
||||
* Emits preselected process if there is one
|
||||
*/
|
||||
ldnService$?: Observable<LdnService>;
|
||||
|
||||
constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* If there's an id parameter, use this the process with this identifier as presets for the form
|
||||
*/
|
||||
ngOnInit() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
import { LdnService } from '../ldn-services-model/ldn-services.model';
|
||||
import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { Observable, of } from 'rxjs';
|
||||
// Create a mock data object for a single LDN notify service
|
||||
export const mockLdnService: LdnService = {
|
||||
id: 1,
|
||||
name: 'Service Name',
|
||||
description: 'Service Description',
|
||||
url: 'Service URL',
|
||||
ldnUrl: 'Service LDN URL',
|
||||
notifyServiceInboundPatterns: [
|
||||
{
|
||||
pattern: 'patternA',
|
||||
constraint: 'itemFilterA',
|
||||
automatic: false,
|
||||
},
|
||||
{
|
||||
pattern: 'patternB',
|
||||
constraint: 'itemFilterB',
|
||||
automatic: true,
|
||||
},
|
||||
],
|
||||
notifyServiceOutboundPatterns: [
|
||||
{
|
||||
pattern: 'patternC',
|
||||
constraint: 'itemFilterC',
|
||||
},
|
||||
],
|
||||
type: LDN_SERVICE,
|
||||
_links: {
|
||||
self: {
|
||||
href: 'http://localhost/api/ldn/ldnservices/1',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const mockLdnServices = {
|
||||
payload: {
|
||||
elementsPerPage: 20,
|
||||
totalPages: 1,
|
||||
totalElements: 1,
|
||||
currentPage: 1,
|
||||
first: undefined,
|
||||
prev: undefined,
|
||||
next: undefined,
|
||||
last: undefined,
|
||||
page: [mockLdnService],
|
||||
type: LDN_SERVICE,
|
||||
self: undefined,
|
||||
getPageLength: function() {
|
||||
return this.page.length;
|
||||
},
|
||||
_links: {
|
||||
self: {
|
||||
href: 'http://localhost/api/ldn/ldnservices/1',
|
||||
},
|
||||
page: [],
|
||||
},
|
||||
},
|
||||
hasSucceeded: true,
|
||||
msToLive: 0,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a mock ldnServicesRD$ observable
|
||||
export const mockLdnServicesRD$: Observable<RemoteData<PaginatedList<LdnService>>> = of((mockLdnServices as unknown) as RemoteData<PaginatedList<LdnService>>);
|
@@ -0,0 +1,90 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { dataService } from '../../../core/data/base/data-service.decorator';
|
||||
import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type';
|
||||
import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service';
|
||||
import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data';
|
||||
import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
||||
import { HALEndpointService } from '../../../core/shared/hal-endpoint.service';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { FindListOptions } from '../../../core/data/find-list-options.model';
|
||||
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
|
||||
import { MultipartPostRequest } from '../../../core/data/request.models';
|
||||
import { RestRequest } from '../../../core/data/rest-request.model';
|
||||
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
|
||||
import { LdnService } from '../ldn-services-model/ldn-services.model';
|
||||
import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model';
|
||||
|
||||
@Injectable()
|
||||
@dataService(LDN_SERVICE)
|
||||
export class LdnServicesService extends IdentifiableDataService<LdnService> implements FindAllData<LdnService>, DeleteData<LdnService> {
|
||||
private findAllData: FindAllDataImpl<LdnService>; // Corrected the type
|
||||
private deleteData: DeleteDataImpl<LdnService>; // Corrected the type
|
||||
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected notificationsService: NotificationsService,
|
||||
) {
|
||||
super('ldnservices', requestService, rdbService, objectCache, halService);
|
||||
|
||||
this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
|
||||
this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint);
|
||||
}
|
||||
|
||||
findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig<LdnService>[]): Observable<RemoteData<PaginatedList<LdnService>>> {
|
||||
return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
|
||||
}
|
||||
|
||||
public delete(objectId: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> {
|
||||
return this.deleteData.delete(objectId, copyVirtualMetadata);
|
||||
}
|
||||
|
||||
public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> {
|
||||
return this.deleteData.deleteByHref(href, copyVirtualMetadata);
|
||||
}
|
||||
|
||||
public invoke(serviceName: string, parameters: LdnServiceConstraint[], files: File[]): Observable<RemoteData<LdnService>> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
this.getBrowseEndpoint().pipe(
|
||||
take(1),
|
||||
map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes').toString()),
|
||||
map((endpoint: string) => {
|
||||
const body = this.getInvocationFormData(parameters, files);
|
||||
return new MultipartPostRequest(requestId, endpoint, body);
|
||||
})
|
||||
).subscribe((request: RestRequest) => this.requestService.send(request));
|
||||
|
||||
return this.rdbService.buildFromRequestUUID<LdnService>(requestId);
|
||||
}
|
||||
|
||||
private getInvocationFormData(constrain: LdnServiceConstraint[], files: File[]): FormData {
|
||||
const form: FormData = new FormData();
|
||||
form.set('properties', JSON.stringify(constrain));
|
||||
files.forEach((file: File) => {
|
||||
form.append('file', file);
|
||||
});
|
||||
return form;
|
||||
}
|
||||
|
||||
public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable<boolean> {
|
||||
return this.findById(scriptName).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
map((rd: RemoteData<LdnService>) => {
|
||||
return hasValue(rd.payload);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
<div class="container">
|
||||
<div class="d-flex">
|
||||
<h2 class="flex-grow-1">{{ 'ldn-registered-services.title' | translate }}</h2>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button class="btn btn-success" routerLink="/admin/ldn/services/new"><i
|
||||
class="fas fa-plus pr-2"></i>{{ 'process.overview.new' | translate }}</button>
|
||||
</div>
|
||||
<ds-pagination *ngIf="(ldnServicesRD$ | async)?.payload?.totalElements > 0"
|
||||
[collectionSize]="(ldnServicesRD$ | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[pageInfoState]="(ldnServicesRD$ | async)?.payload"
|
||||
[paginationOptions]="pageConfig">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{ 'service.overview.table.name' | translate }}</th>
|
||||
<th scope="col">{{ 'service.overview.table.description' | translate }}</th>
|
||||
<th scope="col">{{ 'service.overview.table.status' | translate }}</th>
|
||||
<th scope="col">{{ 'service.overview.table.actions' | translate }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let ldnService of servicesData">
|
||||
<td>{{ ldnService.name }}</td>
|
||||
<td>{{ ldnService.description }}</td>
|
||||
<td>
|
||||
<span [ngClass]="{ 'status-enabled': ldnService.enabled, 'status-disabled': !ldnService.enabled }"
|
||||
class="status-indicator" (click)="toggleStatus(ldnService)"
|
||||
[title]="ldnService.enabled ? ('ldn-service.overview.table.clickToDisable' | translate) : ('ldn-service.overview.table.clickToEnable' | translate)">
|
||||
{{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button (click)="selectServiceToDelete(ldnService.id)" class="btn btn-outline-danger">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
<button [routerLink]="['/admin/ldn/services/edit/', ldnService.id]"
|
||||
class="btn btn-outline-dark">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ds-pagination>
|
||||
</div>
|
||||
|
||||
<ng-template #deleteModal>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="modal-header">
|
||||
<div>
|
||||
<h4>{{'service.overview.delete.header' | translate }}</h4>
|
||||
</div>
|
||||
<button (click)="closeModal()" aria-label="Close"
|
||||
class="close" type="button">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
{{ 'service.overview.delete.body' | translate }}
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button (click)="closeModal()"
|
||||
class="btn btn-primary mr-2">{{ 'service.detail.delete.cancel' | translate }}</button>
|
||||
<button (click)="deleteSelected()" class="btn btn-danger"
|
||||
id="delete-confirm">{{ 'service.overview.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -0,0 +1,29 @@
|
||||
.status-indicator {
|
||||
padding: 2.5px 25px 2.5px 25px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.status-enabled {
|
||||
background-color: #daf7a6;
|
||||
color: #4f5359;
|
||||
font-size: 85%;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.status-enabled:hover {
|
||||
background-color: #faa0a0;
|
||||
}
|
||||
|
||||
.status-disabled {
|
||||
background-color: #faa0a0;
|
||||
color: #4f5359;
|
||||
font-size: 85%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-disabled:hover {
|
||||
background-color: #daf7a6;
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ServicesDirectoryComponent } from './services-directory.component';
|
||||
|
||||
describe('ServicesDirectoryComponent', () => {
|
||||
let component: ServicesDirectoryComponent;
|
||||
let fixture: ComponentFixture<ServicesDirectoryComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ServicesDirectoryComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ServicesDirectoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,163 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { FindListOptions } from '../../../core/data/find-list-options.model';
|
||||
import { LdnService } from '../ldn-services-model/ldn-services.model';
|
||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service';
|
||||
import { PaginationService } from 'src/app/core/pagination/pagination.service';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
@Component({
|
||||
selector: 'ds-ldn-services-directory',
|
||||
templateUrl: './ldn-services-directory.component.html',
|
||||
styleUrls: ['./ldn-services-directory.component.scss'],
|
||||
})
|
||||
export class LdnServicesOverviewComponent implements OnInit, OnDestroy {
|
||||
|
||||
selectedServiceId: number | null = null;
|
||||
servicesData: any[] = [];
|
||||
@ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef<any>;
|
||||
ldnServicesRD$: Observable<RemoteData<PaginatedList<LdnService>>>;
|
||||
config: FindListOptions = Object.assign(new FindListOptions(), {
|
||||
elementsPerPage: 20
|
||||
});
|
||||
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'po',
|
||||
pageSize: 20
|
||||
});
|
||||
isProcessingSub: Subscription;
|
||||
private modalRef: any;
|
||||
|
||||
constructor(
|
||||
protected processLdnService: LdnServicesService,
|
||||
protected paginationService: PaginationService,
|
||||
protected modalService: NgbModal,
|
||||
public ldnDirectoryService: LdnDirectoryService,
|
||||
private http: HttpClient,
|
||||
private cdRef: ChangeDetectorRef
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
/*this.ldnDirectoryService.listLdnServices();*/
|
||||
this.findAllServices();
|
||||
this.setLdnServices();
|
||||
/*this.ldnServicesRD$.subscribe(data => {
|
||||
console.log('searchByLdnUrl()', data);
|
||||
});*/
|
||||
|
||||
/*this.ldnServicesRD$.pipe(
|
||||
tap(data => {
|
||||
console.log('ldnServicesRD$ data:', data);
|
||||
})
|
||||
).subscribe(() => {
|
||||
this.searchByLdnUrl();
|
||||
});*/
|
||||
|
||||
}
|
||||
|
||||
setLdnServices() {
|
||||
this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe(
|
||||
switchMap((config) => this.processLdnService.findAll(config, true, false))
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.paginationService.clearPagination(this.pageConfig.id);
|
||||
if (hasValue(this.isProcessingSub)) {
|
||||
this.isProcessingSub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
openDeleteModal(content) {
|
||||
this.modalRef = this.modalService.open(content);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
this.modalRef.close();
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
|
||||
|
||||
findAllServices(): void {
|
||||
this.retrieveAll().subscribe(
|
||||
(response) => {
|
||||
this.servicesData = response._embedded.ldnservices;
|
||||
console.log('ServicesData =', this.servicesData);
|
||||
this.cdRef.detectChanges();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
retrieveAll(): Observable<any> {
|
||||
const url = 'http://localhost:8080/server/api/ldn/ldnservices';
|
||||
return this.http.get(url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
deleteSelected() {
|
||||
if (this.selectedServiceId !== null) {
|
||||
const deleteUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.selectedServiceId}`;
|
||||
this.http.delete(deleteUrl).subscribe(
|
||||
() => {
|
||||
this.closeModal();
|
||||
this.findAllServices();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error deleting service:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
selectServiceToDelete(serviceId: number) {
|
||||
this.selectedServiceId = serviceId;
|
||||
this.openDeleteModal(this.deleteModal);
|
||||
}
|
||||
|
||||
toggleStatus(ldnService: any): void {
|
||||
const newStatus = !ldnService.enabled;
|
||||
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`;
|
||||
const patchOperation = {
|
||||
op: 'replace',
|
||||
path: '/enabled',
|
||||
value: newStatus,
|
||||
};
|
||||
|
||||
this.http.patch(apiUrl, [patchOperation]).subscribe(
|
||||
() => {
|
||||
console.log('Status updated successfully.');
|
||||
ldnService.enabled = newStatus;
|
||||
this.cdRef.detectChanges();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error updating status:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fetchServiceData(serviceId: string): void {
|
||||
const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`;
|
||||
|
||||
this.http.get(apiUrl).subscribe(
|
||||
(data: any) => {
|
||||
console.log(data);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching service data:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LdnServicesGuard implements CanActivate {
|
||||
|
||||
constructor(
|
||||
//private notifyInfoService: NotifyInfoService,
|
||||
private router: Router
|
||||
) {}
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
return true;
|
||||
/*return this.notifyInfoService.isCoarConfigEnabled().pipe(
|
||||
map(coarLdnEnabled => {
|
||||
if (coarLdnEnabled) {
|
||||
return true;
|
||||
} else {
|
||||
return this.router.parseUrl('/404');
|
||||
}
|
||||
})
|
||||
);*/
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnServicesGuard } from './ldn-services-guard.service';
|
||||
|
||||
describe('LdnServicesGuard', () => {
|
||||
let guard: LdnServicesGuard;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
guard = TestBed.inject(LdnServicesGuard);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
// @ts-ignore
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
|
||||
/**
|
||||
* A cosntrain that can be used when running a service
|
||||
*/
|
||||
export class LdnServiceConstraint {
|
||||
/**
|
||||
* The name of the constrain
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The value of the constrain
|
||||
*/
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const EndorsmentConstrain = [
|
||||
{
|
||||
name: 'Type 1 Item',
|
||||
value: 'Type1'
|
||||
},
|
||||
{
|
||||
name: 'Type 2 Item',
|
||||
value: 'Type2'
|
||||
},
|
||||
];
|
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* List of services statuses
|
||||
*/
|
||||
export enum LdnServiceStatus {
|
||||
UNKOWN,
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* The resource type for Ldn-Services
|
||||
*
|
||||
* Needs to be in a separate file to prevent circular
|
||||
* dependencies in webpack.
|
||||
*/
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
|
||||
export const LDN_SERVICE = new ResourceType('ldnservices');
|
@@ -0,0 +1,58 @@
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
|
||||
import { autoserialize, deserialize } from 'cerialize';
|
||||
import { LDN_SERVICE } from './ldn-service.resource-type';
|
||||
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
|
||||
import { typedObject } from '../../../core/cache/builders/build-decorators';
|
||||
|
||||
|
||||
@typedObject
|
||||
export class LdnService extends CacheableObject {
|
||||
static type = LDN_SERVICE;
|
||||
|
||||
@excludeFromEquals
|
||||
@autoserialize
|
||||
type: ResourceType;
|
||||
|
||||
@autoserialize
|
||||
id?: number;
|
||||
|
||||
@autoserialize
|
||||
name: string;
|
||||
|
||||
@autoserialize
|
||||
description: string;
|
||||
|
||||
@autoserialize
|
||||
url: string;
|
||||
|
||||
@autoserialize
|
||||
ldnUrl: string;
|
||||
|
||||
@autoserialize
|
||||
notifyServiceInboundPatterns?: NotifyServicePattern[];
|
||||
|
||||
@autoserialize
|
||||
notifyServiceOutboundPatterns?: NotifyServicePattern[];
|
||||
|
||||
@deserialize
|
||||
_links: {
|
||||
self: {
|
||||
href: string;
|
||||
};
|
||||
};
|
||||
|
||||
get self(): string {
|
||||
return this._links.self.href;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NotifyServicePattern {
|
||||
@autoserialize
|
||||
pattern: string;
|
||||
@autoserialize
|
||||
constraint?: string;
|
||||
@autoserialize
|
||||
automatic?: boolean;
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* List of parameter types used for scripts
|
||||
*/
|
||||
export enum LdnServiceConstrainType {
|
||||
STRING = 'String',
|
||||
DATE = 'date',
|
||||
BOOLEAN = 'boolean',
|
||||
FILE = 'InputStream',
|
||||
OUTPUT = 'OutputStream'
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
export const notifyPatterns = [
|
||||
{
|
||||
name: 'Acknowledge and Accept',
|
||||
description: 'This pattern is used to acknowledge and accept a request (offer). It implies an intention to act on the request.',
|
||||
category: 'Acknowledgements'
|
||||
},
|
||||
{
|
||||
name: 'Acknowledge and Reject',
|
||||
description: 'This pattern is used to acknowledge and reject a request (offer). It signifies no further action regarding the request.',
|
||||
category: 'Acknowledgements'
|
||||
},
|
||||
{
|
||||
name: 'Acknowledge and Tentatively Accept',
|
||||
description: 'This pattern is used to acknowledge and tentatively accept a request (offer). It implies an intention to act, which may change.',
|
||||
category: 'Acknowledgements'
|
||||
},
|
||||
{
|
||||
name: 'Acknowledge and Tentatively Reject',
|
||||
description: 'This pattern is used to acknowledge and tentatively reject a request (offer). It signifies no further action, subject to change.',
|
||||
category: 'Acknowledgements'
|
||||
},
|
||||
{
|
||||
name: 'Announce Endorsement',
|
||||
description: 'This pattern is used to announce the existence of an endorsement, referencing the endorsed resource.',
|
||||
category: 'Announcements'
|
||||
},
|
||||
{
|
||||
name: 'Announce Ingest',
|
||||
description: 'This pattern is used to announce that a resource has been ingested.',
|
||||
category: 'Announcements'
|
||||
},
|
||||
{
|
||||
name: 'Announce Relationship',
|
||||
description: 'This pattern is used to announce a relationship between two resources.',
|
||||
category: 'Announcements'
|
||||
},
|
||||
{
|
||||
name: 'Announce Review',
|
||||
description: 'This pattern is used to announce the existence of a review, referencing the reviewed resource.',
|
||||
category: 'Announcements'
|
||||
},
|
||||
{
|
||||
name: 'Announce Service Result',
|
||||
description: 'This pattern is used to announce the existence of a "service result", referencing the relevant resource.',
|
||||
category: 'Announcements'
|
||||
},
|
||||
{
|
||||
name: 'Request Endorsement',
|
||||
description: 'This pattern is used to request endorsement of a resource owned by the origin system.',
|
||||
category: 'Requests'
|
||||
},
|
||||
{
|
||||
name: 'Request Ingest',
|
||||
description: 'This pattern is used to request that the target system ingest a resource.',
|
||||
category: 'Requests'
|
||||
},
|
||||
{
|
||||
name: 'Request Review',
|
||||
description: 'This pattern is used to request a review of a resource owned by the origin system.',
|
||||
category: 'Requests'
|
||||
},
|
||||
{
|
||||
name: 'Undo Offer',
|
||||
description: 'This pattern is used to undo (retract) an offer previously made.',
|
||||
category: 'Undo'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
const pattern = notifyPatterns[0];
|
||||
console.log(`Pattern Name: ${pattern.name}`);
|
||||
console.log(`Pattern Description: ${pattern.description}`);
|
||||
console.log(`Pattern Category: ${pattern.category}`);
|
@@ -0,0 +1,17 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnDirectoryService } from './ldn-directory.service';
|
||||
|
||||
describe('LdnDirectoryService', () => {
|
||||
let service: LdnDirectoryService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(LdnDirectoryService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
// @ts-ignore
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,58 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, tap } from 'rxjs';
|
||||
import { LdnService } from '../ldn-services-model/ldn-services.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LdnDirectoryService {
|
||||
private baseUrl = 'http://localhost:8080/server/api/ldn/ldnservices';
|
||||
private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters';
|
||||
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
|
||||
public listLdnServices(): Observable<LdnService[]> {
|
||||
const endpoint = `${this.baseUrl}`;
|
||||
return this.http.get<LdnService[]>(endpoint).pipe(
|
||||
tap(data => {
|
||||
console.log('listLdnServices() Data:', data);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public getLdnServiceById(id: string): Observable<LdnService> {
|
||||
const endpoint = `${this.baseUrl}/${id}`;
|
||||
return this.http.get<LdnService>(endpoint);
|
||||
}
|
||||
|
||||
public createLdnService(ldnService: LdnService): Observable<LdnService> {
|
||||
return this.http.post<LdnService>(this.baseUrl, ldnService);
|
||||
}
|
||||
|
||||
public updateLdnService(id: string, ldnService: LdnService): Observable<LdnService> {
|
||||
const endpoint = `${this.baseUrl}/${id}`;
|
||||
return this.http.put<LdnService>(endpoint, ldnService);
|
||||
}
|
||||
|
||||
public deleteLdnService(id: string): Observable<void> {
|
||||
const endpoint = `${this.baseUrl}/${id}`;
|
||||
return this.http.delete<void>(endpoint);
|
||||
}
|
||||
|
||||
public searchLdnServicesByLdnUrl(ldnUrl: string): Observable<LdnService[]> {
|
||||
const endpoint = `${this.baseUrl}/search/byLdnUrl?ldnUrl=${ldnUrl}`;
|
||||
return this.http.get<LdnService[]>(endpoint);
|
||||
}
|
||||
|
||||
public getItemFilters(): Observable<any> {
|
||||
const itemFiltersEndpoint = `${this.itemFilterEndpoint}`;
|
||||
return this.http.get(itemFiltersEndpoint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,17 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LdnServicesBulkDeleteService } from './ldn-service-bulk-delete.service';
|
||||
|
||||
describe('LdnServiceBulkDeleteService', () => {
|
||||
let service: LdnServicesBulkDeleteService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(LdnServicesBulkDeleteService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
// @ts-ignore
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,117 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, count, from } from 'rxjs';
|
||||
import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { isNotEmpty } from '../../../shared/empty.util';
|
||||
import { concatMap, filter, tap } from 'rxjs/operators';
|
||||
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { LdnService } from '../ldn-services-model/ldn-services.model';
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
/**
|
||||
* Service to facilitate removing ldn services in bulk.
|
||||
*/
|
||||
export class LdnServicesBulkDeleteService {
|
||||
|
||||
/**
|
||||
* Array to track the services to be deleted
|
||||
*/
|
||||
ldnServicesToDelete: string[] = [];
|
||||
|
||||
/**
|
||||
* Behavior subject to track whether the delete is processing
|
||||
* @protected
|
||||
*/
|
||||
protected isProcessingBehaviorSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
|
||||
constructor(
|
||||
protected processLdnService: LdnServicesService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translateService: TranslateService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or remove a process id to/from the list
|
||||
* If the id is already present it will be removed, otherwise it will be added.
|
||||
*
|
||||
* @param notifyServiceName - The process id to add or remove
|
||||
*/
|
||||
toggleDelete(notifyServiceName: string) {
|
||||
if (this.isToBeDeleted(notifyServiceName)) {
|
||||
this.ldnServicesToDelete.splice(this.ldnServicesToDelete.indexOf(notifyServiceName), 1);
|
||||
} else {
|
||||
this.ldnServicesToDelete.push(notifyServiceName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided service id is present in the to be deleted list
|
||||
* @param notifyServiceName
|
||||
*/
|
||||
isToBeDeleted(notifyServiceName: string) {
|
||||
return this.ldnServicesToDelete.includes(notifyServiceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the list of services to be deleted
|
||||
*/
|
||||
clearAllServices() {
|
||||
this.ldnServicesToDelete.splice(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of processes selected for deletion
|
||||
*/
|
||||
getAmountOfSelectedServices() {
|
||||
return this.ldnServicesToDelete.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a behavior subject to indicate whether the bulk delete is processing
|
||||
*/
|
||||
isProcessing$() {
|
||||
return this.isProcessingBehaviorSubject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there currently are values selected for deletion
|
||||
*/
|
||||
hasSelected(): boolean {
|
||||
return isNotEmpty(this.ldnServicesToDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all selected processes one by one
|
||||
* When the deletion for a process fails, an error notification will be shown with the process id,
|
||||
* but it will continue deleting the other processes.
|
||||
* At the end it will show a notification stating the amount of successful deletes
|
||||
* The successfully deleted processes will be removed from the list of selected values, the failed ones will be retained.
|
||||
*/
|
||||
deleteSelectedLdnServices() {
|
||||
this.isProcessingBehaviorSubject.next(true);
|
||||
|
||||
from([...this.ldnServicesToDelete]).pipe(
|
||||
concatMap((notifyServiceName) => {
|
||||
return this.processLdnService.delete(notifyServiceName).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
tap((rd: RemoteData<LdnService>) => {
|
||||
if (rd.hasFailed) {
|
||||
this.notificationsService.error(this.translateService.get('process.bulk.delete.error.head'), this.translateService.get('process.bulk.delete.error.body', {processId: notifyServiceName}));
|
||||
} else {
|
||||
this.toggleDelete(notifyServiceName);
|
||||
}
|
||||
})
|
||||
);
|
||||
}),
|
||||
filter((rd: RemoteData<LdnService>) => rd.hasSucceeded),
|
||||
count(),
|
||||
).subscribe((value) => {
|
||||
this.notificationsService.success(this.translateService.get('process.bulk.delete.success', {count: value}));
|
||||
this.isProcessingBehaviorSubject.next(false);
|
||||
});
|
||||
}
|
||||
}
|
@@ -11,3 +11,5 @@ export function getRegistriesModuleRoute() {
|
||||
export function getNotificationsModuleRoute() {
|
||||
return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString();
|
||||
}
|
||||
|
||||
export const LDN_PATH = 'ldn';
|
||||
|
@@ -6,7 +6,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso
|
||||
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
|
||||
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
|
||||
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
|
||||
import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths';
|
||||
import { LDN_PATH, REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths';
|
||||
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
|
||||
|
||||
@NgModule({
|
||||
@@ -52,13 +52,24 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import
|
||||
component: BatchImportPageComponent,
|
||||
data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' }
|
||||
},
|
||||
{
|
||||
path: LDN_PATH,
|
||||
children: [
|
||||
{ path: '', pathMatch: 'full', redirectTo: 'services' },
|
||||
{
|
||||
path: 'services',
|
||||
loadChildren: () => import('./admin-ldn-services/admin-ldn-services.module')
|
||||
.then((m) => m.AdminLdnServicesModule),
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'system-wide-alert',
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule),
|
||||
data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'}
|
||||
},
|
||||
])
|
||||
]),
|
||||
],
|
||||
providers: [
|
||||
I18nBreadcrumbResolver,
|
||||
|
@@ -187,6 +187,7 @@ import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-brows
|
||||
import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model';
|
||||
import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions/models/suggestion-target.model';
|
||||
import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model';
|
||||
import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service';
|
||||
|
||||
/**
|
||||
* When not in production, endpoint responses can be mocked for testing purposes
|
||||
@@ -309,7 +310,8 @@ const PROVIDERS = [
|
||||
OrcidAuthService,
|
||||
OrcidQueueDataService,
|
||||
OrcidHistoryDataService,
|
||||
SupervisionOrderDataService
|
||||
SupervisionOrderDataService,
|
||||
LdnServicesService,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -222,6 +222,18 @@ export class MenuResolver implements Resolve<boolean> {
|
||||
text: 'menu.section.new_process',
|
||||
link: '/processes/new'
|
||||
} as LinkMenuItemModel,
|
||||
},/* ldn_services */
|
||||
{
|
||||
id: 'ldn_services_new',
|
||||
parentID: 'new',
|
||||
active: false,
|
||||
visible: isSiteAdmin,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.services_new',
|
||||
link: '/admin/ldn/services/new'
|
||||
} as LinkMenuItemModel,
|
||||
icon: '',
|
||||
},
|
||||
];
|
||||
const editSubMenuList = [
|
||||
@@ -350,6 +362,19 @@ export class MenuResolver implements Resolve<boolean> {
|
||||
icon: 'terminal',
|
||||
index: 10
|
||||
},
|
||||
/* LDN Services */
|
||||
{
|
||||
id: 'ldn_services',
|
||||
active: false,
|
||||
visible: isSiteAdmin,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: 'menu.section.services',
|
||||
link: '/admin/ldn/services'
|
||||
} as LinkMenuItemModel,
|
||||
icon: 'inbox',
|
||||
index: 14
|
||||
},
|
||||
{
|
||||
id: 'health',
|
||||
active: false,
|
||||
|
@@ -902,7 +902,67 @@
|
||||
|
||||
"coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking <a href=\"info/feedback\">here</a>.",
|
||||
|
||||
"service.overview.delete.header": "Delete Service",
|
||||
|
||||
"ldn-registered-services.title": "Registered Services",
|
||||
"ldn-registered-services.table.name":"Name",
|
||||
"ldn-registered-services.table.description": "Description",
|
||||
"ldn-registered-services.table.status": "Status",
|
||||
"ldn-registered-services.table.action": "Action",
|
||||
"ldn-registered-services.new": "NEW",
|
||||
"ldn-registered-services.new.breadcrumbs": "Registered Services",
|
||||
|
||||
"ldn-service.overview.table.enabled": "Enabled",
|
||||
"ldn-service.overview.table.disabled": "Disabled",
|
||||
"ldn-service.overview.table.clickToEnable": "Click to enable",
|
||||
"ldn-service.overview.table.clickToDisable": "Click to disable",
|
||||
|
||||
"ldn-service-status": "Status",
|
||||
"ldn-register-new-service.title": "Register a new service",
|
||||
"ldn-new-service.form.label.submit": "Submit",
|
||||
"ldn-new-service.form.label.name": "Name",
|
||||
"ldn-new-service.form.label.description": "Description",
|
||||
"ldn-new-service.form.label.url": "Service URL",
|
||||
"ldn-new-service.form.label.ldnUrl": "LDN Inbox URL",
|
||||
"ldn-new-service.form.placeholder.name": "Please provide service name",
|
||||
"ldn-new-service.form.placeholder.description": "Please provide a description regarding your service",
|
||||
"ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service",
|
||||
"ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox",
|
||||
"ldn-new-service.form.label.inboundPattern": "Inbound Patterns",
|
||||
"ldn-new-service.form.label.placeholder.inboundPattern": "Select an Inbound Pattern",
|
||||
"ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected",
|
||||
"ldn-new-service.form.label.ItemFilter": "Item Filter",
|
||||
"ldn-new-service.form.label.automatic": "Automatic",
|
||||
"ldn-new-service.form.label.outboundPattern": "Outbound Patterns",
|
||||
"ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern",
|
||||
"ldn-new-service.form.label.addPattern": "+ Add more",
|
||||
"ldn-new-service.form.label.removeItemFilter": "Remove",
|
||||
"ldn-register-new-service.breadcrumbs": "New Service",
|
||||
"service.overview.delete.body": "Are you sure you want to delete this service?",
|
||||
"service.overview.delete": "Delete service",
|
||||
"ldn-edit-service.title": "Edit service",
|
||||
"ldn-edit-service.form.label.name": "Name",
|
||||
"ldn-edit-service.form.label.description": "Description",
|
||||
"ldn-edit-service.form.label.url": "Service URL",
|
||||
"ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL",
|
||||
"ldn-edit-service.form.label.inboundPattern": "Inbound Pattern",
|
||||
"ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern",
|
||||
"ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter",
|
||||
"ldn-edit-service.form.label.selectItemFilter": "No Item Filter",
|
||||
"ldn-edit-service.form.label.automatic": "Automatic",
|
||||
"ldn-edit-service.form.label.addInboundPattern": "+ Add more",
|
||||
"ldn-edit-service.form.label.outboundPattern": "Outbound Pattern",
|
||||
"ldn-edit-service.form.label.noOutboundPatternSelected": "No Outbound Pattern",
|
||||
"ldn-edit-service.form.label.addOutboundPattern": "+ Add more",
|
||||
"ldn-edit-service.form.label.submit": "Submit",
|
||||
"ldn-edit-service.breadcrumbs": "Edit Service",
|
||||
|
||||
|
||||
|
||||
"ldn-register-new-service.notification.error.title": "Error",
|
||||
"ldn-register-new-service.notification.error.content": "An error occurred while creating this process",
|
||||
"ldn-register-new-service.notification.success.title": "Success",
|
||||
"ldn-register-new-service.notification.success.content": "The process was successfully created",
|
||||
|
||||
"collection.create.head": "Create a Collection",
|
||||
|
||||
@@ -2920,6 +2980,8 @@
|
||||
|
||||
"menu.section.icon.notifications": "Notifications menu section",
|
||||
|
||||
"menu.section.icon.ldn_services": "LDN Services overview",
|
||||
|
||||
"menu.section.import": "Import",
|
||||
|
||||
"menu.section.import_batch": "Batch Import (ZIP)",
|
||||
@@ -2958,6 +3020,10 @@
|
||||
|
||||
"menu.section.registries_metadata": "Metadata",
|
||||
|
||||
"menu.section.services": "LDN Services",
|
||||
|
||||
"menu.section.services_new": "LDN Service",
|
||||
|
||||
"menu.section.statistics": "Statistics",
|
||||
|
||||
"menu.section.statistics_task": "Statistics Task",
|
||||
@@ -3346,6 +3412,10 @@
|
||||
|
||||
"process.new.breadcrumbs": "Create a new process",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"process.detail.arguments": "Arguments",
|
||||
|
||||
"process.detail.arguments.empty": "This process doesn't contain any arguments",
|
||||
@@ -3428,6 +3498,39 @@
|
||||
|
||||
"process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted",
|
||||
|
||||
"service.detail.delete.cancel": "Cancel",
|
||||
|
||||
"service.detail.delete.button": "Delete service",
|
||||
|
||||
"service.detail.delete.header": "Delete service",
|
||||
|
||||
"service.detail.delete.body": "Are you sure you want to delete the current service?",
|
||||
|
||||
"service.detail.delete.confirm": "Delete service",
|
||||
|
||||
"service.detail.delete.success": "The service was successfully deleted.",
|
||||
|
||||
"service.detail.delete.error": "Something went wrong when deleting the service",
|
||||
|
||||
"service.overview.table.id": "Services ID",
|
||||
|
||||
"service.overview.table.name": "Name",
|
||||
|
||||
"service.overview.table.start": "Start time (UTC)",
|
||||
|
||||
"service.overview.table.status": "Status",
|
||||
|
||||
"service.overview.table.user": "User",
|
||||
|
||||
"service.overview.title": "Services Overview",
|
||||
|
||||
"service.overview.breadcrumbs": "Services Overview",
|
||||
|
||||
"service.overview.table.actions": "Actions",
|
||||
|
||||
"service.overview.table.description": "Description",
|
||||
|
||||
|
||||
"profile.breadcrumbs": "Update Profile",
|
||||
|
||||
"profile.card.identify": "Identify",
|
||||
|
Reference in New Issue
Block a user