[DURACOM-307] apply migration script to conflicted files resolved in favor of Angular 18 update

This commit is contained in:
FrancescoMolinaro
2025-03-10 18:11:22 +01:00
parent 1aa9faeb2f
commit 51c95de793
193 changed files with 7962 additions and 6485 deletions

View File

@@ -36,9 +36,11 @@
[showPaginator]="false" [showPaginator]="false"
(prev)="pagePrev()" (prev)="pagePrev()"
(next)="pageNext()"> (next)="pageNext()">
<ul *ngIf="(objectsSelected$|async)?.hasSucceeded" class="list-unstyled ms-4"> @if ((objectsSelected$|async)?.hasSucceeded) {
<li *ngFor='let object of (objectsSelected$|async)?.payload?.page | paginate: { itemsPerPage: (paginationOptions$ | async).pageSize, <ul class="list-unstyled ms-4">
currentPage: (paginationOptions$ | async).currentPage, totalItems: (objectsSelected$|async)?.payload?.page.length }; let i = index; let last = last ' @for (object of (objectsSelected$|async)?.payload?.page | paginate: { itemsPerPage: (paginationOptions$ | async).pageSize,
currentPage: (paginationOptions$ | async).currentPage, totalItems: (objectsSelected$|async)?.payload?.page.length }; track object; let i = $index; let last = $last) {
<li
class="mt-4 mb-4 d-flex" class="mt-4 mb-4 d-flex"
[attr.data-test]="'list-object' | dsBrowserOnly"> [attr.data-test]="'list-object' | dsBrowserOnly">
<ds-selectable-list-item-control [index]="i" <ds-selectable-list-item-control [index]="i"
@@ -50,7 +52,9 @@
[showThumbnails]="false" [showThumbnails]="false"
[viewMode]="'list'"></ds-listable-object-component-loader> [viewMode]="'list'"></ds-listable-object-component-loader>
</li> </li>
}
</ul> </ul>
}
</ds-pagination> </ds-pagination>
</ng-template> </ng-template>
</li> </li>

View File

@@ -41,14 +41,15 @@
</div> </div>
</form> </form>
<ds-loading *ngIf="searching$ | async"></ds-loading> @if (searching$ | async) {
<ds-loading></ds-loading>
}
@if ((pageInfoState$ | async)?.totalElements > 0 && (searching$ | async) !== true) {
<ds-pagination <ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && (searching$ | async) !== true"
[paginationOptions]="config" [paginationOptions]="config"
[collectionSize]="(pageInfoState$ | async)?.totalElements" [collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true"> [hidePagerWhenSinglePage]="true">
<div class="table-responsive"> <div class="table-responsive">
<table id="epeople" class="table table-striped table-hover table-bordered"> <table id="epeople" class="table table-striped table-hover table-bordered">
<thead> <thead>
@@ -60,7 +61,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let epersonDto of (ePeopleDto$ | async)?.page" @for (epersonDto of (ePeopleDto$ | async)?.page; track epersonDto) {
<tr
[ngClass]="{'table-primary' : (activeEPerson$ | async) === epersonDto.eperson}"> [ngClass]="{'table-primary' : (activeEPerson$ | async) === epersonDto.eperson}">
<td>{{epersonDto.eperson.id}}</td> <td>{{epersonDto.eperson.id}}</td>
<td>{{ dsoNameService.getName(epersonDto.eperson) }}</td> <td>{{ dsoNameService.getName(epersonDto.eperson) }}</td>
@@ -72,23 +74,28 @@
title="{{labelPrefix + 'table.edit.buttons.edit' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}"> title="{{labelPrefix + 'table.edit.buttons.edit' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}">
<i class="fas fa-edit fa-fw"></i> <i class="fas fa-edit fa-fw"></i>
</button> </button>
<button *ngIf="epersonDto.ableToDelete" (click)="deleteEPerson(epersonDto.eperson)" @if (epersonDto.ableToDelete) {
<button (click)="deleteEPerson(epersonDto.eperson)"
class="delete-button btn btn-outline-danger btn-sm access-control-deleteEPersonButton" class="delete-button btn btn-outline-danger btn-sm access-control-deleteEPersonButton"
title="{{labelPrefix + 'table.edit.buttons.remove' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}"> title="{{labelPrefix + 'table.edit.buttons.remove' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}">
<i class="fas fa-trash-alt fa-fw"></i> <i class="fas fa-trash-alt fa-fw"></i>
</button> </button>
}
</div> </div>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="(pageInfoState$ | async)?.totalElements === 0" class="alert alert-info w-100 mb-2" role="alert"> @if ((pageInfoState$ | async)?.totalElements === 0) {
<div class="alert alert-info w-100 mb-2" role="alert">
{{labelPrefix + 'no-items' | translate}} {{labelPrefix + 'no-items' | translate}}
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -2,15 +2,13 @@
<div class="group-form row"> <div class="group-form row">
<div class="col-12"> <div class="col-12">
<div *ngIf="activeEPerson$ | async; then editHeader; else createHeader"></div> @if (activeEPerson$ | async) {
<ng-template #createHeader>
<h1 class="border-bottom pb-2">{{messagePrefix + '.create' | translate}}</h1>
</ng-template>
<ng-template #editHeader>
<h1 class="border-bottom pb-2">{{messagePrefix + '.edit' | translate}}</h1> <h1 class="border-bottom pb-2">{{messagePrefix + '.edit' | translate}}</h1>
</ng-template> } @else {
<h1 class="border-bottom pb-2">{{messagePrefix + '.create' | translate}}</h1>
}
<ds-form [formId]="formId" <ds-form [formId]="formId"
[formModel]="formModel" [formModel]="formModel"
@@ -24,39 +22,51 @@
<i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}} <i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}
</button> </button>
</div> </div>
<div *ngIf="displayResetPassword" between class="btn-group"> @if (displayResetPassword) {
<div between class="btn-group">
<button class="btn btn-primary" [dsBtnDisabled]="(canReset$ | async) !== true" type="button" (click)="resetPassword()"> <button class="btn btn-primary" [dsBtnDisabled]="(canReset$ | async) !== true" type="button" (click)="resetPassword()">
<i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}} <i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}}
</button> </button>
</div> </div>
<div *ngIf="canImpersonate$ | async" between class="btn-group ms-1"> }
<button *ngIf="!isImpersonated" class="btn btn-primary" type="button" (click)="impersonate()"> @if (canImpersonate$ | async) {
<div between class="btn-group ms-1">
@if (!isImpersonated) {
<button class="btn btn-primary" type="button" (click)="impersonate()">
<i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.impersonate' | translate}} <i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.impersonate' | translate}}
</button> </button>
<button *ngIf="isImpersonated" class="btn btn-primary" type="button" (click)="stopImpersonating()"> }
@if (isImpersonated) {
<button class="btn btn-primary" type="button" (click)="stopImpersonating()">
<i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.stop-impersonating' | translate}} <i class="fa fa-user-secret"></i> {{'admin.access-control.epeople.actions.stop-impersonating' | translate}}
</button> </button>
}
</div> </div>
<button *ngIf="canDelete$ | async" after class="btn btn-danger delete-button" type="button" (click)="delete()"> }
@if (canDelete$ | async) {
<button after class="btn btn-danger delete-button" type="button" (click)="delete()">
<i class="fas fa-trash"></i> {{'admin.access-control.epeople.actions.delete' | translate}} <i class="fas fa-trash"></i> {{'admin.access-control.epeople.actions.delete' | translate}}
</button> </button>
}
</ds-form> </ds-form>
<ds-loading [showMessage]="false" *ngIf="!formGroup"></ds-loading> @if (!formGroup) {
<ds-loading [showMessage]="false"></ds-loading>
}
<div *ngIf="activeEPerson$ | async"> @if (activeEPerson$ | async) {
<div>
<h2>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h2> <h2>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h2>
@if (groups$ | async | dsHasNoValue) {
<ds-loading [showMessage]="false" *ngIf="groups$ | async | dsHasNoValue"></ds-loading> <ds-loading [showMessage]="false"></ds-loading>
}
@if ((groups$ | async)?.payload?.totalElements > 0) {
<ds-pagination <ds-pagination
*ngIf="(groups$ | async)?.payload?.totalElements > 0"
[paginationOptions]="config" [paginationOptions]="config"
[collectionSize]="(groups$ | async)?.payload?.totalElements" [collectionSize]="(groups$ | async)?.payload?.totalElements"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true" [hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)"> (pageChange)="onPageChange($event)">
<div class="table-responsive"> <div class="table-responsive">
<table id="groups" class="table table-striped table-hover table-bordered"> <table id="groups" class="table table-striped table-hover table-bordered">
<thead> <thead>
@@ -67,7 +77,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let group of (groups$ | async)?.payload?.page"> @for (group of (groups$ | async)?.payload?.page; track group) {
<tr>
<td class="align-middle">{{group.id}}</td> <td class="align-middle">{{group.id}}</td>
<td class="align-middle"> <td class="align-middle">
<a (click)="groupsDataService.startEditingNewGroup(group)" <a (click)="groupsDataService.startEditingNewGroup(group)"
@@ -79,20 +90,23 @@
{{ dsoNameService.getName((group.object | async)?.payload) }} {{ dsoNameService.getName((group.object | async)?.payload) }}
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="(groups$ | async)?.payload?.totalElements === 0" class="alert alert-info w-100 mb-2" role="alert"> @if ((groups$ | async)?.payload?.totalElements === 0) {
<div class="alert alert-info w-100 mb-2" role="alert">
<div>{{messagePrefix + '.memberOfNoGroups' | translate}}</div> <div>{{messagePrefix + '.memberOfNoGroups' | translate}}</div>
<div> <div>
<button [routerLink]="[groupsDataService.getGroupRegistryRouterLink()]" <button [routerLink]="[groupsDataService.getGroupRegistryRouterLink()]"
class="btn btn-primary">{{messagePrefix + '.goToGroups' | translate}}</button> class="btn btn-primary">{{messagePrefix + '.goToGroups' | translate}}</button>
</div> </div>
</div> </div>
</div> }
</div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -33,14 +33,15 @@
</div> </div>
</form> </form>
<ds-loading *ngIf="loading$ | async"></ds-loading> @if (loading$ | async) {
<ds-loading></ds-loading>
}
@if ((pageInfoState$ | async)?.totalElements > 0 && (loading$ | async) !== true) {
<ds-pagination <ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && (loading$ | async) !== true"
[paginationOptions]="config" [paginationOptions]="config"
[collectionSize]="(pageInfoState$ | async)?.totalElements" [collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true"> [hidePagerWhenSinglePage]="true">
<div class="table-responsive"> <div class="table-responsive">
<table id="groups" class="table table-striped table-hover table-bordered"> <table id="groups" class="table table-striped table-hover table-bordered">
<thead> <thead>
@@ -53,22 +54,26 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let groupDto of (groupsDto$ | async)?.page"> @for (groupDto of (groupsDto$ | async)?.page; track groupDto) {
<tr>
<td>{{groupDto.group.id}}</td> <td>{{groupDto.group.id}}</td>
<td>{{ dsoNameService.getName(groupDto.group) }}</td> <td>{{ dsoNameService.getName(groupDto.group) }}</td>
<td>{{ dsoNameService.getName((groupDto.group.object | async)?.payload) }}</td> <td>{{ dsoNameService.getName((groupDto.group.object | async)?.payload) }}</td>
<td>{{groupDto.epersons?.totalElements + groupDto.subgroups?.totalElements}}</td> <td>{{groupDto.epersons?.totalElements + groupDto.subgroups?.totalElements}}</td>
<td> <td>
<div class="btn-group edit-field"> <div class="btn-group edit-field">
<ng-container [ngSwitch]="groupDto.ableToEdit"> @switch (groupDto.ableToEdit) {
<button *ngSwitchCase="true" @case (true) {
<button
[routerLink]="groupService.getGroupEditPageRouterLink(groupDto.group)" [routerLink]="groupService.getGroupEditPageRouterLink(groupDto.group)"
class="btn btn-outline-primary btn-sm btn-edit" class="btn btn-outline-primary btn-sm btn-edit"
title="{{messagePrefix + 'table.edit.buttons.edit' | translate: {name: dsoNameService.getName(groupDto.group) } }}" title="{{messagePrefix + 'table.edit.buttons.edit' | translate: {name: dsoNameService.getName(groupDto.group) } }}"
> >
<i class="fas fa-edit fa-fw"></i> <i class="fas fa-edit fa-fw"></i>
</button> </button>
<button *ngSwitchCase="false" }
@case (false) {
<button
[dsBtnDisabled]="true" [dsBtnDisabled]="true"
class="btn btn-outline-primary btn-sm btn-edit" class="btn btn-outline-primary btn-sm btn-edit"
placement="left" placement="left"
@@ -76,23 +81,30 @@
> >
<i class="fas fa-edit fa-fw"></i> <i class="fas fa-edit fa-fw"></i>
</button> </button>
</ng-container> }
<button *ngIf="!groupDto.group?.permanent && groupDto.ableToDelete" }
@if (!groupDto.group?.permanent && groupDto.ableToDelete) {
<button
(click)="deleteGroup(groupDto)" class="btn btn-outline-danger btn-sm btn-delete" (click)="deleteGroup(groupDto)" class="btn btn-outline-danger btn-sm btn-delete"
title="{{messagePrefix + 'table.edit.buttons.remove' | translate: {name: dsoNameService.getName(groupDto.group) } }}"> title="{{messagePrefix + 'table.edit.buttons.remove' | translate: {name: dsoNameService.getName(groupDto.group) } }}">
<i class="fas fa-trash-alt fa-fw"></i> <i class="fas fa-trash-alt fa-fw"></i>
</button> </button>
}
</div> </div>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="(pageInfoState$ | async)?.totalElements === 0" class="alert alert-info w-100 mb-2" role="alert"> @if ((pageInfoState$ | async)?.totalElements === 0) {
<div class="alert alert-info w-100 mb-2" role="alert">
{{messagePrefix + 'no-items' | translate}} {{messagePrefix + 'no-items' | translate}}
</div> </div>
}
</div> </div>
</div> </div>

View File

@@ -1,10 +1,12 @@
<div class="container"> <div class="container">
<h1 id="header">{{'admin.batch-import.page.header' | translate}}</h1> <h1 id="header">{{'admin.batch-import.page.header' | translate}}</h1>
<p>{{'admin.batch-import.page.help' | translate}}</p> <p>{{'admin.batch-import.page.help' | translate}}</p>
<p *ngIf="dso"> @if (dso) {
<p>
selected collection: <b>{{getDspaceObjectName()}}</b>&nbsp; selected collection: <b>{{getDspaceObjectName()}}</b>&nbsp;
<a href="javascript:void(0)" (click)="removeDspaceObject()">{{'admin.batch-import.page.remove' | translate}}</a> <a href="javascript:void(0)" (click)="removeDspaceObject()">{{'admin.batch-import.page.remove' | translate}}</a>
</p> </p>
}
<p> <p>
<button class="btn btn-primary" (click)="this.selectCollection();">{{'admin.metadata-import.page.button.select-collection' | translate}}</button> <button class="btn btn-primary" (click)="this.selectCollection();">{{'admin.metadata-import.page.button.select-collection' | translate}}</button>
</p> </p>
@@ -30,18 +32,21 @@
</small> </small>
@if (isUpload) {
<ds-file-dropzone-no-uploader <ds-file-dropzone-no-uploader
*ngIf="isUpload"
data-test="file-dropzone" data-test="file-dropzone"
(onFileAdded)="setFile($event)" (onFileAdded)="setFile($event)"
[dropMessageLabel]="'admin.batch-import.page.dropMsg'" [dropMessageLabel]="'admin.batch-import.page.dropMsg'"
[dropMessageLabelReplacement]="'admin.batch-import.page.dropMsgReplace'"> [dropMessageLabelReplacement]="'admin.batch-import.page.dropMsgReplace'">
</ds-file-dropzone-no-uploader> </ds-file-dropzone-no-uploader>
}
<div class="mb-3 mt-2" *ngIf="!isUpload"> @if (!isUpload) {
<div class="mb-3 mt-2">
<input class="form-control" type="text" placeholder="{{'admin.metadata-import.page.urlMsg' | translate}}" <input class="form-control" type="text" placeholder="{{'admin.metadata-import.page.urlMsg' | translate}}"
data-test="file-url-input" [(ngModel)]="fileURL"> data-test="file-url-input" [(ngModel)]="fileURL">
</div> </div>
}
<div class="space-children-mr"> <div class="space-children-mr">
<button class="btn btn-secondary" id="backButton" <button class="btn btn-secondary" id="backButton"

View File

@@ -4,7 +4,8 @@
<h1 class="flex-grow-1">{{ isNewService ? ('ldn-create-service.title' | translate) : ('ldn-edit-registered-service.title' | translate) }}</h1> <h1 class="flex-grow-1">{{ isNewService ? ('ldn-create-service.title' | translate) : ('ldn-edit-registered-service.title' | translate) }}</h1>
</div> </div>
<!-- In the toggle section --> <!-- In the toggle section -->
<div class="toggle-switch-container" *ngIf="!isNewService"> @if (!isNewService) {
<div class="toggle-switch-container">
<label class="status-label font-weight-bold" for="enabled">{{ 'ldn-service-status' | translate }}</label> <label class="status-label font-weight-bold" for="enabled">{{ 'ldn-service-status' | translate }}</label>
<div> <div>
<input formControlName="enabled" hidden id="enabled" name="enabled" type="checkbox"> <input formControlName="enabled" hidden id="enabled" name="enabled" type="checkbox">
@@ -13,6 +14,7 @@
</div> </div>
</div> </div>
</div> </div>
}
<!-- In the Name section --> <!-- In the Name section -->
<div class="mb-5"> <div class="mb-5">
<label for="name" class="font-weight-bold">{{ 'ldn-new-service.form.label.name' | translate }}</label> <label for="name" class="font-weight-bold">{{ 'ldn-new-service.form.label.name' | translate }}</label>
@@ -22,9 +24,11 @@
id="name" id="name"
name="name" name="name"
type="text"> type="text">
<div *ngIf="formModel.get('name').invalid && formModel.get('name').touched" class="error-text"> @if (formModel.get('name').invalid && formModel.get('name').touched) {
<div class="error-text">
{{ 'ldn-new-service.form.error.name' | translate }} {{ 'ldn-new-service.form.error.name' | translate }}
</div> </div>
}
</div> </div>
<!-- In the description section --> <!-- In the description section -->
@@ -45,9 +49,11 @@
id="url" id="url"
name="url" name="url"
type="text"> type="text">
<div *ngIf="formModel.get('url').invalid && formModel.get('url').touched" class="error-text"> @if (formModel.get('url').invalid && formModel.get('url').touched) {
<div class="error-text">
{{ 'ldn-new-service.form.error.url' | translate }} {{ 'ldn-new-service.form.error.url' | translate }}
</div> </div>
}
</div> </div>
<div class="d-flex flex-column w-50"> <div class="d-flex flex-column w-50">
@@ -61,9 +67,11 @@
step=".01" step=".01"
class="form-control" class="form-control"
type="number"> type="number">
<div *ngIf="formModel.get('score').invalid && formModel.get('score').touched" class="error-text"> @if (formModel.get('score').invalid && formModel.get('score').touched) {
<div class="error-text">
{{ 'ldn-new-service.form.error.score' | translate }} {{ 'ldn-new-service.form.error.score' | translate }}
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
@@ -85,9 +93,11 @@
name="upperIp" name="upperIp"
type="text"> type="text">
</div> </div>
<div *ngIf="(formModel.get('lowerIp').invalid && formModel.get('lowerIp').touched) || (formModel.get('upperIp').invalid && formModel.get('upperIp').touched)" class="error-text"> @if ((formModel.get('lowerIp').invalid && formModel.get('lowerIp').touched) || (formModel.get('upperIp').invalid && formModel.get('upperIp').touched)) {
<div class="error-text">
{{ 'ldn-new-service.form.error.ipRange' | translate }} {{ 'ldn-new-service.form.error.ipRange' | translate }}
</div> </div>
}
<div class="text-muted"> <div class="text-muted">
{{ 'ldn-new-service.form.hint.ipRange' | translate }} {{ 'ldn-new-service.form.hint.ipRange' | translate }}
</div> </div>
@@ -102,43 +112,50 @@
id="ldnUrl" id="ldnUrl"
name="ldnUrl" name="ldnUrl"
type="text"> type="text">
<div *ngIf="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched" > @if (formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched) {
<div *ngIf="formModel.get('ldnUrl').errors['required']" class="error-text"> <div >
@if (formModel.get('ldnUrl').errors['required']) {
<div class="error-text">
{{ 'ldn-new-service.form.error.ldnurl' | translate }} {{ 'ldn-new-service.form.error.ldnurl' | translate }}
</div> </div>
<div *ngIf="formModel.get('ldnUrl').errors['ldnUrlAlreadyAssociated']" class="error-text"> }
@if (formModel.get('ldnUrl').errors['ldnUrlAlreadyAssociated']) {
<div class="error-text">
{{ 'ldn-new-service.form.error.ldnurl.ldnUrlAlreadyAssociated' | translate }} {{ 'ldn-new-service.form.error.ldnurl.ldnUrlAlreadyAssociated' | translate }}
</div> </div>
}
</div> </div>
}
</div> </div>
<!-- In the Inbound Patterns Labels section --> <!-- In the Inbound Patterns Labels section -->
<div class="row mb-1 mt-5" *ngIf="areControlsInitialized"> @if (areControlsInitialized) {
<div class="row mb-1 mt-5">
<div class="col"> <div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label>
</div> </div>
<ng-container *ngIf="formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern"> @if (formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern) {
<div class="col"> <div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div> </div>
<div class="col-sm-1"> <div class="col-sm-1">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.automatic' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
</div> </div>
</ng-container> }
<div class="col-sm-2"> <div class="col-sm-2">
</div> </div>
</div> </div>
}
<!-- In the Inbound Patterns section --> <!-- In the Inbound Patterns section -->
<div *ngIf="areControlsInitialized"> @if (areControlsInitialized) {
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index" <div>
@for (patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; track patternGroup; let i = $index) {
<div
[class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)" [class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)"
formGroupName="notifyServiceInboundPatterns"> formGroupName="notifyServiceInboundPatterns">
<ng-container [formGroupName]="i"> <ng-container [formGroupName]="i">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<div class="col"> <div class="col">
<div #inboundPatternDropdown="ngbDropdown" class="w-80" display="dynamic" <div #inboundPatternDropdown="ngbDropdown" class="w-80" display="dynamic"
@@ -162,23 +179,22 @@
class="dropdown-menu dropdown-menu-top w-100 " class="dropdown-menu dropdown-menu-top w-100 "
ngbDropdownMenu> ngbDropdownMenu>
<div class="scrollable-menu" role="listbox"> <div class="scrollable-menu" role="listbox">
@for (pattern of inboundPatterns; track pattern; let internalIndex = $index) {
<button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()" <button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of inboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate" [title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100" class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem ngbDropdownItem
type="button"> type="button">
<div>{{ 'ldn-service.form.pattern.' + pattern + '.label' | translate }}</div> <div>{{ 'ldn-service.form.pattern.' + pattern + '.label' | translate }}</div>
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<ng-container @if (formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern) {
*ngIf="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern">
<div #inboundItemfilterDropdown="ngbDropdown" class="w-100" id="constraint{{i}}" ngbDropdown <div #inboundItemfilterDropdown="ngbDropdown" class="w-100" id="constraint{{i}}" ngbDropdown
placement="top-start"> placement="top-start">
<div class="position-relative right-addon" aria-expanded="false" aria-controls="inboundItemfilterDropdown" role="combobox"> <div class="position-relative right-addon" aria-expanded="false" aria-controls="inboundItemfilterDropdown" role="combobox">
@@ -211,20 +227,20 @@
class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button"> class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button">
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span> <span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button> </button>
@for (constraint of (itemFiltersRD$ | async)?.payload?.page; track constraint; let internalIndex = $index) {
<button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation()" <button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation()"
*ngFor="let constraint of (itemFiltersRD$ | async)?.payload?.page; let internalIndex = index"
class="dropdown-item collection-item text-truncate w-100" class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem ngbDropdownItem
type="button"> type="button">
<div>{{ constraint.id + '.label' | translate }}</div> <div>{{ constraint.id + '.label' | translate }}</div>
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</ng-container> }
</div> </div>
<div <div
[style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern ? 'visible' : 'hidden'" [style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern ? 'visible' : 'hidden'"
class="col-sm-1"> class="col-sm-1">
@@ -236,8 +252,6 @@
<div class="slider"></div> <div class="slider"></div>
</div> </div>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<div class="btn-group"> <div class="btn-group">
<button (click)="markForInboundPatternDeletion(i)" class="btn btn-outline-dark trash-button" <button (click)="markForInboundPatternDeletion(i)" class="btn btn-outline-dark trash-button"
@@ -245,21 +259,22 @@
type="button"> type="button">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
</button> </button>
@if (markedForDeletionInboundPattern.includes(i)) {
<button (click)="unmarkForInboundPatternDeletion(i)" <button (click)="unmarkForInboundPatternDeletion(i)"
*ngIf="markedForDeletionInboundPattern.includes(i)"
[title]="'ldn-service-button-unmark-inbound-deletion' | translate" [title]="'ldn-service-button-unmark-inbound-deletion' | translate"
class="btn btn-warning " class="btn btn-warning "
type="button"> type="button">
<i class="fas fa-undo"></i> <i class="fas fa-undo"></i>
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
</ng-container> </ng-container>
</div> </div>
}
</div> </div>
}
<span (click)="addInboundPattern()" <span (click)="addInboundPattern()"
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span> class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
@@ -280,8 +295,12 @@
</div> </div>
<ng-template #confirmModal> <ng-template #confirmModal>
<div class="modal-header"> <div class="modal-header">
<h4 *ngIf="!isNewService">{{'service.overview.edit.modal' | translate }}</h4> @if (!isNewService) {
<h4 *ngIf="isNewService">{{'service.overview.create.modal' | translate }}</h4> <h4>{{'service.overview.edit.modal' | translate }}</h4>
}
@if (isNewService) {
<h4>{{'service.overview.create.modal' | translate }}</h4>
}
<button (click)="closeModal()" aria-label="Close" <button (click)="closeModal()" aria-label="Close"
class="close" type="button"> class="close" type="button">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
@@ -289,23 +308,32 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div *ngIf="!isNewService"> @if (!isNewService) {
<div>
{{ 'service.overview.edit.body' | translate }} {{ 'service.overview.edit.body' | translate }}
</div> </div>
<span *ngIf="isNewService"> }
@if (isNewService) {
<span>
{{ 'service.overview.create.body' | translate }} {{ 'service.overview.create.body' | translate }}
</span> </span>
}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<div *ngIf="!isNewService"> @if (!isNewService) {
<div>
<button (click)="closeModal()" class="btn btn-outline-secondary me-2" <button (click)="closeModal()" class="btn btn-outline-secondary me-2"
id="delete-confirm-edit">{{ 'service.detail.return' | translate }} id="delete-confirm-edit">{{ 'service.detail.return' | translate }}
</button> </button>
<button *ngIf="!isNewService" (click)="patchService()" @if (!isNewService) {
<button (click)="patchService()"
class="btn btn-primary">{{ 'service.detail.update' | translate }} class="btn btn-primary">{{ 'service.detail.update' | translate }}
</button> </button>
}
</div> </div>
<div *ngIf="isNewService"> }
@if (isNewService) {
<div>
<button (click)="closeModal()" class="btn btn-outline-secondary me-2 " <button (click)="closeModal()" class="btn btn-outline-secondary me-2 "
id="delete-confirm-new">{{ 'service.refuse.create' | translate }} id="delete-confirm-new">{{ 'service.refuse.create' | translate }}
</button> </button>
@@ -313,6 +341,7 @@
class="btn btn-primary">{{ 'service.confirm.create' | translate }} class="btn btn-primary">{{ 'service.confirm.create' | translate }}
</button> </button>
</div> </div>
}
</div> </div>
</ng-template> </ng-template>

View File

@@ -6,7 +6,8 @@
<button class="btn btn-success" routerLink="/admin/ldn/services/new"><i <button class="btn btn-success" routerLink="/admin/ldn/services/new"><i
class="fas fa-plus pe-2"></i>{{ 'process.overview.new' | translate }}</button> class="fas fa-plus pe-2"></i>{{ 'process.overview.new' | translate }}</button>
</div> </div>
<ds-pagination *ngIf="(ldnServicesRD$ | async)?.payload?.totalElements > 0" @if ((ldnServicesRD$ | async)?.payload?.totalElements > 0) {
<ds-pagination
[collectionSize]="(ldnServicesRD$ | async)?.payload?.totalElements" [collectionSize]="(ldnServicesRD$ | async)?.payload?.totalElements"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true" [hidePagerWhenSinglePage]="true"
@@ -22,7 +23,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let ldnService of (ldnServicesRD$ | async)?.payload?.page"> @for (ldnService of (ldnServicesRD$ | async)?.payload?.page; track ldnService) {
<tr>
<td class="col-3">{{ ldnService.name }}</td> <td class="col-3">{{ ldnService.name }}</td>
<td> <td>
<ds-truncatable [id]="ldnService.id"> <ds-truncatable [id]="ldnService.id">
@@ -57,10 +59,12 @@
</div> </div>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
</div> </div>
<ng-template #deleteModal> <ng-template #deleteModal>

View File

@@ -3,10 +3,12 @@
<div class="col-12 col-md-3 text-left h4">{{((isInbound$ | async) ? 'admin.notify.dashboard.inbound' : 'admin.notify.dashboard.outbound') | translate}}</div> <div class="col-12 col-md-3 text-left h4">{{((isInbound$ | async) ? 'admin.notify.dashboard.inbound' : 'admin.notify.dashboard.outbound') | translate}}</div>
<div class="col-md-9"> <div class="col-md-9">
<div class="h4"> <div class="h4">
<button (click)="resetDefaultConfiguration()" *ngIf="(selectedSearchConfig$ | async) !== defaultConfiguration" class="badge bg-primary me-1 mb-1"> @if ((selectedSearchConfig$ | async) !== defaultConfiguration) {
<button (click)="resetDefaultConfiguration()" class="badge bg-primary me-1 mb-1">
{{ 'admin-notify-logs.' + (selectedSearchConfig$ | async) | translate}} {{ 'admin-notify-logs.' + (selectedSearchConfig$ | async) | translate}}
<span> ×</span> <span> ×</span>
</button> </button>
}
</div> </div>
<ds-search-labels [inPlaceSearch]="true"></ds-search-labels> <ds-search-labels [inPlaceSearch]="true"></ds-search-labels>
</div> </div>

View File

@@ -8,8 +8,8 @@
<p id="create-new" class="mb-2"><a [routerLink]="'add'" class="btn btn-success">{{'admin.registries.bitstream-formats.create.new' | translate}}</a></p> <p id="create-new" class="mb-2"><a [routerLink]="'add'" class="btn btn-success">{{'admin.registries.bitstream-formats.create.new' | translate}}</a></p>
@if ((bitstreamFormats$ | async)?.payload?.totalElements > 0) {
<ds-pagination <ds-pagination
*ngIf="(bitstreamFormats$ | async)?.payload?.totalElements > 0"
[paginationOptions]="pageConfig" [paginationOptions]="pageConfig"
[collectionSize]="(bitstreamFormats$ | async)?.payload?.totalElements" [collectionSize]="(bitstreamFormats$ | async)?.payload?.totalElements"
[hideGear]="false" [hideGear]="false"
@@ -26,7 +26,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let bitstreamFormat of (bitstreamFormats$ | async)?.payload?.page"> @for (bitstreamFormat of (bitstreamFormats$ | async)?.payload?.page; track bitstreamFormat) {
<tr>
<td> <td>
<label class="form-label mb-0"> <label class="form-label mb-0">
<input type="checkbox" <input type="checkbox"
@@ -39,20 +40,30 @@
</td> </td>
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.id}}</a></td> <td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.id}}</a></td>
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.shortDescription}}</a></td> <td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.shortDescription}}</a></td>
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.mimetype}} <span *ngIf="bitstreamFormat.internal">({{'admin.registries.bitstream-formats.table.internal' | translate}})</span></a></td> <td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.mimetype}} @if (bitstreamFormat.internal) {
<span>({{'admin.registries.bitstream-formats.table.internal' | translate}})</span>
}</a></td>
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{'admin.registries.bitstream-formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</a></td> <td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{'admin.registries.bitstream-formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</a></td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
<div *ngIf="(bitstreamFormats$ | async)?.payload?.totalElements === 0" class="alert alert-info" role="alert"> }
@if ((bitstreamFormats$ | async)?.payload?.totalElements === 0) {
<div class="alert alert-info" role="alert">
{{'admin.registries.bitstream-formats.no-items' | translate}} {{'admin.registries.bitstream-formats.no-items' | translate}}
</div> </div>
}
<div> <div>
<button *ngIf="(bitstreamFormats$ | async)?.payload?.page?.length > 0" class="btn btn-primary deselect" (click)="deselectAll()">{{'admin.registries.bitstream-formats.table.deselect-all' | translate}}</button> @if ((bitstreamFormats$ | async)?.payload?.page?.length > 0) {
<button *ngIf="(bitstreamFormats$ | async)?.payload?.page?.length > 0" type="submit" class="btn btn-danger float-end" (click)="deleteFormats()">{{'admin.registries.bitstream-formats.table.delete' | translate}}</button> <button class="btn btn-primary deselect" (click)="deselectAll()">{{'admin.registries.bitstream-formats.table.deselect-all' | translate}}</button>
}
@if ((bitstreamFormats$ | async)?.payload?.page?.length > 0) {
<button type="submit" class="btn btn-danger float-end" (click)="deleteFormats()">{{'admin.registries.bitstream-formats.table.delete' | translate}}</button>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -8,13 +8,12 @@
<ds-metadata-schema-form (submitForm)="forceUpdateSchemas()"></ds-metadata-schema-form> <ds-metadata-schema-form (submitForm)="forceUpdateSchemas()"></ds-metadata-schema-form>
@if ((metadataSchemas | async)?.payload?.totalElements > 0) {
<ds-pagination <ds-pagination
*ngIf="(metadataSchemas | async)?.payload?.totalElements > 0"
[paginationOptions]="config" [paginationOptions]="config"
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements" [collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true"> [hidePagerWhenSinglePage]="true">
<div class="table-responsive"> <div class="table-responsive">
<table id="metadata-schemas" class="table table-striped table-hover"> <table id="metadata-schemas" class="table table-striped table-hover">
<thead> <thead>
@@ -26,7 +25,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let schema of (metadataSchemas | async)?.payload?.page" @for (schema of (metadataSchemas | async)?.payload?.page; track schema) {
<tr
[ngClass]="{'table-primary' : (activeMetadataSchema$ | async)?.id === schema.id}"> [ngClass]="{'table-primary' : (activeMetadataSchema$ | async)?.id === schema.id}">
<td> <td>
<label class="form-label mb-0"> <label class="form-label mb-0">
@@ -41,18 +41,23 @@
<td class="selectable-row" (click)="editSchema(schema)"><a [routerLink]="[schema.prefix]">{{schema.namespace}}</a></td> <td class="selectable-row" (click)="editSchema(schema)"><a [routerLink]="[schema.prefix]">{{schema.namespace}}</a></td>
<td class="selectable-row" (click)="editSchema(schema)"><a [routerLink]="[schema.prefix]">{{schema.prefix}}</a></td> <td class="selectable-row" (click)="editSchema(schema)"><a [routerLink]="[schema.prefix]">{{schema.prefix}}</a></td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="(metadataSchemas | async)?.payload?.totalElements === 0" class="alert alert-info w-100 mb-2" role="alert"> @if ((metadataSchemas | async)?.payload?.totalElements === 0) {
<div class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.metadata.schemas.no-items' | translate}} {{'admin.registries.metadata.schemas.no-items' | translate}}
</div> </div>
}
<div> <div>
<button *ngIf="(metadataSchemas | async)?.payload?.page?.length > 0" type="submit" class="btn btn-danger float-end" (click)="deleteSchemas()">{{'admin.registries.metadata.schemas.table.delete' | translate}}</button> @if ((metadataSchemas | async)?.payload?.page?.length > 0) {
<button type="submit" class="btn btn-danger float-end" (click)="deleteSchemas()">{{'admin.registries.metadata.schemas.table.delete' | translate}}</button>
}
</div> </div>
</div> </div>

View File

@@ -13,8 +13,8 @@
<h2>{{'admin.registries.schema.fields.head' | translate}}</h2> <h2>{{'admin.registries.schema.fields.head' | translate}}</h2>
<ng-container *ngVar="(metadataFields$ | async)?.payload as fields"> <ng-container *ngVar="(metadataFields$ | async)?.payload as fields">
@if (fields?.totalElements > 0) {
<ds-pagination <ds-pagination
*ngIf="fields?.totalElements > 0"
[paginationOptions]="config" [paginationOptions]="config"
[collectionSize]="fields?.totalElements" [collectionSize]="fields?.totalElements"
[hideGear]="false" [hideGear]="false"
@@ -30,7 +30,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let field of fields?.page" @for (field of fields?.page; track field) {
<tr
[ngClass]="{'table-primary' : (activeField$ | async)?.id === field.id}"> [ngClass]="{'table-primary' : (activeField$ | async)?.id === field.id}">
<td *ngVar="(selectedMetadataFieldIDs$ | async)?.includes(field.id) as selected"> <td *ngVar="(selectedMetadataFieldIDs$ | async)?.includes(field.id) as selected">
<input type="checkbox" <input type="checkbox"
@@ -42,18 +43,24 @@
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}{{field.qualifier ? '.' + field.qualifier : ''}}</td> <td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}{{field.qualifier ? '.' + field.qualifier : ''}}</td>
<td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td> <td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="fields?.totalElements === 0" class="alert alert-info w-100 mb-2" role="alert"> @if (fields?.totalElements === 0) {
<div class="alert alert-info w-100 mb-2" role="alert">
{{'admin.registries.schema.fields.no-items' | translate}} {{'admin.registries.schema.fields.no-items' | translate}}
</div> </div>
}
<div> <div>
<button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button> <button [routerLink]="['/admin/registries/metadata']" class="btn btn-primary">{{'admin.registries.schema.return' | translate}}</button>
<button *ngIf="fields?.page?.length > 0" type="submit" class="btn btn-danger float-end" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button> @if (fields?.page?.length > 0) {
<button type="submit" class="btn btn-danger float-end" (click)="deleteFields()">{{'admin.registries.schema.fields.table.delete' | translate}}</button>
}
</div> </div>
</ng-container> </ng-container>

View File

@@ -9,11 +9,15 @@
<span class="col-12">&nbsp;</span> <span class="col-12">&nbsp;</span>
</ng-container> </ng-container>
</fieldset> </fieldset>
<fieldset class="row row-cols-2" *ngFor="let group of allFilters()"> @for (group of allFilters(); track group) {
<fieldset class="row row-cols-2">
<legend>{{group.key | translate}}</legend> <legend>{{group.key | translate}}</legend>
<ng-container [formGroup]="filtersForm"> <ng-container [formGroup]="filtersForm">
<div *ngFor="let filter of group.filters" class="col-6"> @for (filter of group.filters; track filter) {
<div class="col-6">
<input type="checkbox" id="flt-{{filter.id}}" value="{{filter.id}}" class="form-check-input col-1" formControlName="{{filter.id}}"><label for="flt-{{filter.id}}" class="col-11 align-middle" title="{{filter.tooltipKey | translate}}">{{filter.key | translate}}</label> <input type="checkbox" id="flt-{{filter.id}}" value="{{filter.id}}" class="form-check-input col-1" formControlName="{{filter.id}}"><label for="flt-{{filter.id}}" class="col-11 align-middle" title="{{filter.tooltipKey | translate}}">{{filter.key | translate}}</label>
</div> </div>
}
</ng-container> </ng-container>
</fieldset> </fieldset>
}

View File

@@ -13,8 +13,10 @@
<option value="EDITOR">{{'supervision-group-selector.select.type-of-order.option.editor' | translate}}</option> <option value="EDITOR">{{'supervision-group-selector.select.type-of-order.option.editor' | translate}}</option>
<option value="OBSERVER">{{'supervision-group-selector.select.type-of-order.option.observer' | translate}}</option> <option value="OBSERVER">{{'supervision-group-selector.select.type-of-order.option.observer' | translate}}</option>
</select> </select>
<ds-error *ngIf="isSubmitted && (!selectedOrderType || selectedOrderType === '')" @if (isSubmitted && (!selectedOrderType || selectedOrderType === '')) {
<ds-error
message="{{'supervision-group-selector.select.type-of-order.error' | translate}}"></ds-error> message="{{'supervision-group-selector.select.type-of-order.error' | translate}}"></ds-error>
}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -22,7 +24,9 @@
<label for="supervisionGroup" class="form-label">{{'supervision-group-selector.select.group.label' | translate}}</label> <label for="supervisionGroup" class="form-label">{{'supervision-group-selector.select.group.label' | translate}}</label>
<ng-container class="mb-3"> <ng-container class="mb-3">
<input id="supervisionGroup" class="form-control" type="text" [value]="selectedGroup ? dsoNameService.getName(selectedGroup) : ''" disabled> <input id="supervisionGroup" class="form-control" type="text" [value]="selectedGroup ? dsoNameService.getName(selectedGroup) : ''" disabled>
<ds-error *ngIf="isSubmitted && !selectedGroup" message="{{'supervision-group-selector.select.group.error' | translate}}"></ds-error> @if (isSubmitted && !selectedGroup) {
<ds-error message="{{'supervision-group-selector.select.group.error' | translate}}"></ds-error>
}
</ng-container> </ng-container>
<ds-eperson-group-list [isListOfEPerson]="false" <ds-eperson-group-list [isListOfEPerson]="false"
(select)="updateGroupObjectSelected($event)"></ds-eperson-group-list> (select)="updateGroupObjectSelected($event)"></ds-eperson-group-list>

View File

@@ -1,15 +1,19 @@
<ng-container *ngVar="(supervisionOrderEntries$ | async) as supervisionOrders"> <ng-container *ngVar="(supervisionOrderEntries$ | async) as supervisionOrders">
<div class="item-list-supervision" *ngIf="supervisionOrders?.length > 0"> @if (supervisionOrders?.length > 0) {
<div class="item-list-supervision">
<div> <div>
<span>{{'workflow-item.search.result.list.element.supervised-by' | translate}} </span> <span>{{'workflow-item.search.result.list.element.supervised-by' | translate}} </span>
</div> </div>
<div> <div>
<a class="badge bg-primary me-1 mb-1 text-capitalize mw-100 text-truncate" *ngFor="let supervisionOrder of supervisionOrders" data-test="soBadge" @for (supervisionOrder of supervisionOrders; track supervisionOrder) {
<a class="badge bg-primary me-1 mb-1 text-capitalize mw-100 text-truncate" data-test="soBadge"
[ngbTooltip]="'workflow-item.search.result.list.element.supervised.remove-tooltip' | translate" [ngbTooltip]="'workflow-item.search.result.list.element.supervised.remove-tooltip' | translate"
(click)="$event.preventDefault(); $event.stopImmediatePropagation(); deleteSupervisionOrder(supervisionOrder)" aria-label="Close"> (click)="$event.preventDefault(); $event.stopImmediatePropagation(); deleteSupervisionOrder(supervisionOrder)" aria-label="Close">
{{ dsoNameService.getName(supervisionOrder.group) }} {{ dsoNameService.getName(supervisionOrder.group) }}
<span aria-hidden="true"> ×</span> <span aria-hidden="true"> ×</span>
</a> </a>
}
</div> </div>
</div> </div>
}
</ng-container> </ng-container>

View File

@@ -7,6 +7,8 @@
</div> </div>
<ul #buttons class="list-group list-group-flush"> <ul #buttons class="list-group list-group-flush">
<li class="list-group-item"> <li class="list-group-item">
<ds-workflow-item-admin-workflow-actions-element *ngIf="object" class="d-flex justify-content-between" [wfi]="dso" [small]="true"></ds-workflow-item-admin-workflow-actions-element> @if (object) {
<ds-workflow-item-admin-workflow-actions-element class="d-flex justify-content-between" [wfi]="dso" [small]="true"></ds-workflow-item-admin-workflow-actions-element>
}
</li> </li>
</ul> </ul>

View File

@@ -1,10 +1,12 @@
<div class="workflow-badge"> <div class="workflow-badge">
<span class="badge bg-info">{{ "admin.workflow.item.workflow" | translate }}</span> <span class="badge bg-info">{{ "admin.workflow.item.workflow" | translate }}</span>
</div> </div>
<ds-listable-object-component-loader *ngIf="item$ | async" @if (item$ | async) {
<ds-listable-object-component-loader
[object]="item$ | async" [object]="item$ | async"
[viewMode]="viewModes.ListElement" [viewMode]="viewModes.ListElement"
[index]="index" [index]="index"
[linkType]="linkType" [linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader> [listID]="listID"></ds-listable-object-component-loader>
}
<ds-workflow-item-admin-workflow-actions-element [wfi]="dso" [small]="false"></ds-workflow-item-admin-workflow-actions-element> <ds-workflow-item-admin-workflow-actions-element [wfi]="dso" [small]="false"></ds-workflow-item-admin-workflow-actions-element>

View File

@@ -1,10 +1,12 @@
<span class="badge bg-info">{{ "admin.workflow.item.workspace" | translate }}</span> <span class="badge bg-info">{{ "admin.workflow.item.workspace" | translate }}</span>
<ds-listable-object-component-loader *ngIf="item$ | async" @if (item$ | async) {
<ds-listable-object-component-loader
[object]="item$ | async" [object]="item$ | async"
[viewMode]="viewModes.ListElement" [viewMode]="viewModes.ListElement"
[index]="index" [index]="index"
[linkType]="linkType" [linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader> [listID]="listID"></ds-listable-object-component-loader>
}
<ds-workspace-item-admin-workflow-actions-element [small]="false" <ds-workspace-item-admin-workflow-actions-element [small]="false"
[supervisionOrderList]="supervisionOrder$ | async" [supervisionOrderList]="supervisionOrder$ | async"

View File

@@ -1,8 +1,10 @@
<div class="container"> <div class="container">
<div class="collection-page" <div class="collection-page"
*ngVar="(collectionRD$ | async) as collectionRD"> *ngVar="(collectionRD$ | async) as collectionRD">
<div *ngIf="collectionRD?.hasSucceeded" @fadeInOut> @if (collectionRD?.hasSucceeded) {
<div *ngIf="collectionRD?.payload as collection"> <div @fadeInOut>
@if (collectionRD?.payload; as collection) {
<div>
<ds-view-tracker [object]="collection"></ds-view-tracker> <ds-view-tracker [object]="collection"></ds-view-tracker>
<div class="d-flex flex-row border-bottom mb-4 pb-4"> <div class="d-flex flex-row border-bottom mb-4 pb-4">
<header class="comcol-header me-auto"> <header class="comcol-header me-auto">
@@ -11,11 +13,12 @@
[name]="dsoNameService.getName(collection)"> [name]="dsoNameService.getName(collection)">
</ds-comcol-page-header> </ds-comcol-page-header>
<!-- Collection logo --> <!-- Collection logo -->
<ds-comcol-page-logo *ngIf="logoRD$" @if (logoRD$) {
<ds-comcol-page-logo
[logo]="(logoRD$ | async)?.payload" [logo]="(logoRD$ | async)?.payload"
[alternateText]="'collection.logo' | translate"> [alternateText]="'collection.logo' | translate">
</ds-comcol-page-logo> </ds-comcol-page-logo>
}
<!-- Handle --> <!-- Handle -->
<ds-comcol-page-handle <ds-comcol-page-handle
[content]="collection.handle" [content]="collection.handle"
@@ -41,21 +44,28 @@
[id]="collection.id" [id]="collection.id"
[contentType]="collection.type"> [contentType]="collection.type">
</ds-comcol-page-browse-by> </ds-comcol-page-browse-by>
<router-outlet></router-outlet> <router-outlet></router-outlet>
</section> </section>
<footer *ngIf="collection.copyrightText" class="border-top my-5 pt-4"> @if (collection.copyrightText) {
<footer class="border-top my-5 pt-4">
<!-- Copyright --> <!-- Copyright -->
<ds-comcol-page-content <ds-comcol-page-content
[content]="collection.copyrightText" [content]="collection.copyrightText"
[hasInnerHtml]="true"> [hasInnerHtml]="true">
</ds-comcol-page-content> </ds-comcol-page-content>
</footer> </footer>
}
</div> </div>
}
</div> </div>
<ds-error *ngIf="collectionRD?.hasFailed" }
@if (collectionRD?.hasFailed) {
<ds-error
message="{{'error.collection' | translate}}"></ds-error> message="{{'error.collection' | translate}}"></ds-error>
<ds-loading *ngIf="collectionRD?.isLoading" }
@if (collectionRD?.isLoading) {
<ds-loading
message="{{'loading.collection' | translate}}"></ds-loading> message="{{'loading.collection' | translate}}"></ds-loading>
}
</div> </div>
</div> </div>

View File

@@ -10,8 +10,12 @@
<i class="fas fa-times"></i> {{'collection.delete.cancel' | translate}} <i class="fas fa-times"></i> {{'collection.delete.cancel' | translate}}
</button> </button>
<button class="btn btn-danger" (click)="onConfirm(dso)" [dsBtnDisabled]="(processing$ | async)"> <button class="btn btn-danger" (click)="onConfirm(dso)" [dsBtnDisabled]="(processing$ | async)">
<span *ngIf="processing$ | async"><i class='fas fa-circle-notch fa-spin'></i> {{'collection.delete.processing' | translate}}</span> @if (processing$ | async) {
<span *ngIf="(processing$ | async) !== true"><i class="fas fa-trash"></i> {{'collection.delete.confirm' | translate}}</span> <span><i class='fas fa-circle-notch fa-spin'></i> {{'collection.delete.processing' | translate}}</span>
}
@if ((processing$ | async) !== true) {
<span><i class="fas fa-trash"></i> {{'collection.delete.confirm' | translate}}</span>
}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -1,8 +1,9 @@
<div class="custom-alignment"> <div class="custom-alignment">
@for (comcolRole of comcolRoles$ | async; track comcolRole) {
<ds-comcol-role <ds-comcol-role
*ngFor="let comcolRole of comcolRoles$ | async"
[dso]="collection$ | async" [dso]="collection$ | async"
[comcolRole]="comcolRole" [comcolRole]="comcolRole"
> >
</ds-comcol-role> </ds-comcol-role>
}
</div> </div>

View File

@@ -1,5 +1,6 @@
<div *ngVar="(contentSource$ |async) as contentSource"> <div *ngVar="(contentSource$ |async) as contentSource">
<div class="container-fluid space-children-mr" *ngIf="shouldShow"> @if (shouldShow) {
<div class="container-fluid space-children-mr">
<h3>{{ 'collection.source.controls.head' | translate }}</h3> <h3>{{ 'collection.source.controls.head' | translate }}</h3>
<div> <div>
<span class="fw-bold">{{'collection.source.controls.harvest.status' | translate}}</span> <span class="fw-bold">{{'collection.source.controls.harvest.status' | translate}}</span>
@@ -17,38 +18,48 @@
<span class="fw-bold">{{'collection.source.controls.harvest.message' | translate}}</span> <span class="fw-bold">{{'collection.source.controls.harvest.message' | translate}}</span>
<span>{{contentSource?.message ? contentSource?.message: 'collection.source.controls.harvest.no-information'|translate }}</span> <span>{{contentSource?.message ? contentSource?.message: 'collection.source.controls.harvest.no-information'|translate }}</span>
</div> </div>
@if ((testConfigRunning$ |async) !== true) {
<button *ngIf="(testConfigRunning$ |async) !== true" class="btn btn-secondary" <button class="btn btn-secondary"
[dsBtnDisabled]="!(isEnabled)" [dsBtnDisabled]="!(isEnabled)"
(click)="testConfiguration(contentSource)"> (click)="testConfiguration(contentSource)">
<span>{{'collection.source.controls.test.submit' | translate}}</span> <span>{{'collection.source.controls.test.submit' | translate}}</span>
</button> </button>
<button *ngIf="(testConfigRunning$ |async)" class="btn btn-secondary" }
@if ((testConfigRunning$ |async)) {
<button class="btn btn-secondary"
[dsBtnDisabled]="true"> [dsBtnDisabled]="true">
<span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span> <span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span>
<span>{{'collection.source.controls.test.running' | translate}}</span> <span>{{'collection.source.controls.test.running' | translate}}</span>
</button> </button>
<button *ngIf="(importRunning$ |async) !== true" class="btn btn-primary" }
@if ((importRunning$ |async) !== true) {
<button class="btn btn-primary"
[dsBtnDisabled]="!(isEnabled)" [dsBtnDisabled]="!(isEnabled)"
(click)="importNow()"> (click)="importNow()">
<span class="d-none d-sm-inline">{{'collection.source.controls.import.submit' | translate}}</span> <span class="d-none d-sm-inline">{{'collection.source.controls.import.submit' | translate}}</span>
</button> </button>
<button *ngIf="(importRunning$ |async)" class="btn btn-primary" }
@if ((importRunning$ |async)) {
<button class="btn btn-primary"
[dsBtnDisabled]="true"> [dsBtnDisabled]="true">
<span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span> <span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span>
<span class="d-none d-sm-inline">{{'collection.source.controls.import.running' | translate}}</span> <span class="d-none d-sm-inline">{{'collection.source.controls.import.running' | translate}}</span>
</button> </button>
<button *ngIf="(reImportRunning$ |async) !== true" class="btn btn-primary" }
@if ((reImportRunning$ |async) !== true) {
<button class="btn btn-primary"
[dsBtnDisabled]="!(isEnabled)" [dsBtnDisabled]="!(isEnabled)"
(click)="resetAndReimport()"> (click)="resetAndReimport()">
<span class="d-none d-sm-inline">&nbsp;{{'collection.source.controls.reset.submit' | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{'collection.source.controls.reset.submit' | translate}}</span>
</button> </button>
<button *ngIf="(reImportRunning$ |async)" class="btn btn-primary" }
@if ((reImportRunning$ |async)) {
<button class="btn btn-primary"
[dsBtnDisabled]="true"> [dsBtnDisabled]="true">
<span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span> <span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span>
<span class="d-none d-sm-inline">&nbsp;{{'collection.source.controls.reset.running' | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{'collection.source.controls.reset.running' | translate}}</span>
</button> </button>
}
</div> </div>
}
</div> </div>

View File

@@ -1,16 +1,20 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-inline-block float-end space-children-mr"> <div class="d-inline-block float-end space-children-mr">
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true" @if ((isReinstatable$ | async) !== true) {
<button class=" btn btn-danger"
[dsBtnDisabled]="(hasChanges$ | async) !== true" [dsBtnDisabled]="(hasChanges$ | async) !== true"
(click)="discard()"><i (click)="discard()"><i
class="fas fa-times"></i> class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span>
</button> </button>
<button class="btn btn-warning" *ngIf="isReinstatable$ | async" }
@if (isReinstatable$ | async) {
<button class="btn btn-warning"
(click)="reinstate()"><i (click)="reinstate()"><i
class="fas fa-undo-alt"></i> class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span>
</button> </button>
}
<button class="btn btn-primary" <button class="btn btn-primary"
[dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)" [dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
(click)="onSubmit()"><i (click)="onSubmit()"><i
@@ -19,17 +23,24 @@
</button> </button>
</div> </div>
<h2>{{ 'collection.edit.tabs.source.head' | translate }}</h2> <h2>{{ 'collection.edit.tabs.source.head' | translate }}</h2>
<div *ngIf="contentSource" class="form-check mb-4"> @if (contentSource) {
<div class="form-check mb-4">
<input type="checkbox" class="form-check-input" id="externalSourceCheck" <input type="checkbox" class="form-check-input" id="externalSourceCheck"
[checked]="(contentSource?.harvestType !== harvestTypeNone)" (change)="changeExternalSource()"> [checked]="(contentSource?.harvestType !== harvestTypeNone)" (change)="changeExternalSource()">
<label class="form-check-label" <label class="form-check-label"
for="externalSourceCheck">{{ 'collection.edit.tabs.source.external' | translate }}</label> for="externalSourceCheck">{{ 'collection.edit.tabs.source.external' | translate }}</label>
</div> </div>
<ds-loading *ngIf="!contentSource" [message]="'loading.content-source' | translate"></ds-loading> }
<h3 *ngIf="contentSource && (contentSource?.harvestType !== harvestTypeNone)">{{ 'collection.edit.tabs.source.form.head' | translate }}</h3> @if (!contentSource) {
<ds-loading [message]="'loading.content-source' | translate"></ds-loading>
}
@if (contentSource && (contentSource?.harvestType !== harvestTypeNone)) {
<h3>{{ 'collection.edit.tabs.source.form.head' | translate }}</h3>
}
</div> </div>
<div class="row"> <div class="row">
<ds-form *ngIf="formGroup && contentSource && (contentSource?.harvestType !== harvestTypeNone)" @if (formGroup && contentSource && (contentSource?.harvestType !== harvestTypeNone)) {
<ds-form
[formId]="'collection-source-form-id'" [formId]="'collection-source-form-id'"
[formGroup]="formGroup" [formGroup]="formGroup"
[formModel]="formModel" [formModel]="formModel"
@@ -39,22 +50,28 @@
(dfChange)="onChange($event)" (dfChange)="onChange($event)"
(submitForm)="onSubmit()" (submitForm)="onSubmit()"
(cancel)="onCancel()"></ds-form> (cancel)="onCancel()"></ds-form>
}
</div> </div>
<div class="container mt-2" *ngIf="(contentSource?.harvestType !== harvestTypeNone)"> @if ((contentSource?.harvestType !== harvestTypeNone)) {
<div class="container mt-2">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="d-inline-block float-end ms-1 space-children-mr"> <div class="d-inline-block float-end ms-1 space-children-mr">
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true" @if ((isReinstatable$ | async) !== true) {
<button class=" btn btn-danger"
[dsBtnDisabled]="(hasChanges$ | async) !== true" [dsBtnDisabled]="(hasChanges$ | async) !== true"
(click)="discard()"><i (click)="discard()"><i
class="fas fa-times"></i> class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span>
</button> </button>
<button class="btn btn-warning" *ngIf="isReinstatable$ | async" }
@if (isReinstatable$ | async) {
<button class="btn btn-warning"
(click)="reinstate()"><i (click)="reinstate()"><i
class="fas fa-undo-alt"></i> class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span>
</button> </button>
}
<button class="btn btn-primary" <button class="btn btn-primary"
[dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)" [dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
(click)="onSubmit()"><i (click)="onSubmit()"><i
@@ -65,6 +82,7 @@
</div> </div>
</div> </div>
</div> </div>
}
<ds-collection-source-controls <ds-collection-source-controls
[isEnabled]="(hasChanges$ | async) !== true" [isEnabled]="(hasChanges$ | async) !== true"
[shouldShow]="contentSource?.harvestType !== harvestTypeNone" [shouldShow]="contentSource?.harvestType !== harvestTypeNone"

View File

@@ -1,4 +1,6 @@
<ds-loading *ngIf="(dataSource.loading$ | async) && !loadingNode" class="ds-themed-loading"></ds-loading> @if ((dataSource.loading$ | async) && !loadingNode) {
<ds-loading class="ds-themed-loading"></ds-loading>
}
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl" [trackBy]="trackBy"> <cdk-tree [dataSource]="dataSource" [treeControl]="treeControl" [trackBy]="trackBy">
<!-- This is the tree node template for show more node --> <!-- This is the tree node template for show more node -->
<cdk-tree-node *cdkTreeNodeDef="let node; when: isShowMore" cdkTreeNodePadding <cdk-tree-node *cdkTreeNodeDef="let node; when: isShowMore" cdkTreeNodePadding
@@ -8,11 +10,15 @@
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
<div class="align-middle my-auto"> <div class="align-middle my-auto">
<button *ngIf="(dataSource.loading$ | async) !== true" (click)="getNextPage(node)" @if ((dataSource.loading$ | async) !== true) {
<button (click)="getNextPage(node)"
class="btn btn-outline-primary btn-sm" role="button"> class="btn btn-outline-primary btn-sm" role="button">
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }} <i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
</button> </button>
<ds-loading *ngIf="node===loadingNode && dataSource.loading$ | async" class="ds-themed-loading"></ds-loading> }
@if (node===loadingNode && dataSource.loading$ | async) {
<ds-loading class="ds-themed-loading"></ds-loading>
}
</div> </div>
</div> </div>
<div class="text-muted" cdkTreeNodePadding> <div class="text-muted" cdkTreeNodePadding>
@@ -24,7 +30,8 @@
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding <cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding
class="example-tree-node expandable-node"> class="example-tree-node expandable-node">
<div class="btn-group"> <div class="btn-group">
<button *ngIf="hasChild(null, node) | async" type="button" class="btn btn-default btn-transparent" cdkTreeNodeToggle @if (hasChild(null, node) | async) {
<button type="button" class="btn btn-default btn-transparent" cdkTreeNodeToggle
[attr.aria-label]="(node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) }" [attr.aria-label]="(node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) }"
(click)="toggleExpanded(node)" (click)="toggleExpanded(node)"
data-test="expand-button"> data-test="expand-button">
@@ -32,21 +39,27 @@
aria-hidden="true"></span> aria-hidden="true"></span>
<span class="sr-only">{{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }}</span> <span class="sr-only">{{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }}</span>
</button> </button>
}
<!--Don't render the button when non-expandable otherwise it's still accessible, instead render this placeholder--> <!--Don't render the button when non-expandable otherwise it's still accessible, instead render this placeholder-->
<span *ngIf="(hasChild(null, node) | async) !== true" aria-hidden="true" class="btn btn-default invisible"> @if ((hasChild(null, node) | async) !== true) {
<span aria-hidden="true" class="btn btn-default invisible">
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
}
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<span class="d-flex align-middle my-auto"> <span class="d-flex align-middle my-auto">
<a [routerLink]="node.route" class="lead">{{ dsoNameService.getName(node.payload) }}</a> <a [routerLink]="node.route" class="lead">{{ dsoNameService.getName(node.payload) }}</a>
<span class="pe-2">&nbsp;</span> <span class="pe-2">&nbsp;</span>
<span *ngIf="node.payload.archivedItemsCount >= 0" class="badge rounded-pill bg-secondary align-top archived-items-lead my-auto ps-2 pe-2">{{node.payload.archivedItemsCount}}</span> @if (node.payload.archivedItemsCount >= 0) {
<span class="badge rounded-pill bg-secondary align-top archived-items-lead my-auto ps-2 pe-2">{{node.payload.archivedItemsCount}}</span>
}
</span> </span>
</div> </div>
</div> </div>
<ds-truncatable [id]="node.id"> <ds-truncatable [id]="node.id">
<div class="text-muted" cdkTreeNodePadding> <div class="text-muted" cdkTreeNodePadding>
<div class="d-flex" *ngIf="node.payload.shortDescription"> @if (node.payload.shortDescription) {
<div class="d-flex">
<span aria-hidden="true" class="btn btn-default invisible"> <span aria-hidden="true" class="btn btn-default invisible">
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
@@ -54,15 +67,18 @@
<span>{{node.payload.shortDescription}}</span> <span>{{node.payload.shortDescription}}</span>
</ds-truncatable-part> </ds-truncatable-part>
</div> </div>
}
</div> </div>
</ds-truncatable> </ds-truncatable>
<div class="d-flex" *ngIf="node===loadingNode && dataSource.loading$ | async" @if (node===loadingNode && dataSource.loading$ | async) {
<div class="d-flex"
cdkTreeNodePadding> cdkTreeNodePadding>
<span aria-hidden="true" class="btn btn-default invisible"> <span aria-hidden="true" class="btn btn-default invisible">
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
<ds-loading class="ds-themed-loading"></ds-loading> <ds-loading class="ds-themed-loading"></ds-loading>
</div> </div>
}
</cdk-tree-node> </cdk-tree-node>
<!-- This is the tree node template for leaf nodes (collections and (sub)coms without children) --> <!-- This is the tree node template for leaf nodes (collections and (sub)coms without children) -->
<cdk-tree-node *cdkTreeNodeDef="let node; when: !(hasChild && isShowMore)" cdkTreeNodePadding <cdk-tree-node *cdkTreeNodeDef="let node; when: !(hasChild && isShowMore)" cdkTreeNodePadding
@@ -77,7 +93,8 @@
</div> </div>
<ds-truncatable [id]="node.id"> <ds-truncatable [id]="node.id">
<div class="text-muted" cdkTreeNodePadding> <div class="text-muted" cdkTreeNodePadding>
<div class="d-flex" *ngIf="node.payload.shortDescription"> @if (node.payload.shortDescription) {
<div class="d-flex">
<span aria-hidden="true" class="btn btn-default invisible"> <span aria-hidden="true" class="btn btn-default invisible">
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
@@ -85,6 +102,7 @@
<span>{{node.payload.shortDescription}}</span> <span>{{node.payload.shortDescription}}</span>
</ds-truncatable-part> </ds-truncatable-part>
</div> </div>
}
</div> </div>
</ds-truncatable> </ds-truncatable>
</cdk-tree-node> </cdk-tree-node>

View File

@@ -1,14 +1,18 @@
<div class="container" *ngVar="(communityRD$ | async) as communityRD"> <div class="container" *ngVar="(communityRD$ | async) as communityRD">
<div class="community-page" *ngIf="communityRD?.hasSucceeded" @fadeInOut> @if (communityRD?.hasSucceeded) {
<div *ngIf="communityRD?.payload; let communityPayload"> <div class="community-page" @fadeInOut>
@if (communityRD?.payload; as communityPayload) {
<div>
<ds-view-tracker [object]="communityPayload"></ds-view-tracker> <ds-view-tracker [object]="communityPayload"></ds-view-tracker>
<div class="d-flex flex-row border-bottom mb-4 pb-4"> <div class="d-flex flex-row border-bottom mb-4 pb-4">
<header class="comcol-header me-auto"> <header class="comcol-header me-auto">
<!-- Community name --> <!-- Community name -->
<ds-comcol-page-header [name]="dsoNameService.getName(communityPayload)"></ds-comcol-page-header> <ds-comcol-page-header [name]="dsoNameService.getName(communityPayload)"></ds-comcol-page-header>
<!-- Community logo --> <!-- Community logo -->
<ds-comcol-page-logo *ngIf="logoRD$" [logo]="(logoRD$ | async)?.payload" [alternateText]="'community.logo' | translate"> @if (logoRD$) {
<ds-comcol-page-logo [logo]="(logoRD$ | async)?.payload" [alternateText]="'community.logo' | translate">
</ds-comcol-page-logo> </ds-comcol-page-logo>
}
<!-- Handle --> <!-- Handle -->
<ds-comcol-page-handle [content]="communityPayload.handle" [title]="'community.page.handle'"> <ds-comcol-page-handle [content]="communityPayload.handle" [title]="'community.page.handle'">
</ds-comcol-page-handle> </ds-comcol-page-handle>
@@ -23,21 +27,27 @@
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<section class="comcol-page-browse-section"> <section class="comcol-page-browse-section">
<!-- Browse-By Links --> <!-- Browse-By Links -->
<ds-comcol-page-browse-by [id]="communityPayload.id" [contentType]="communityPayload.type"> <ds-comcol-page-browse-by [id]="communityPayload.id" [contentType]="communityPayload.type">
</ds-comcol-page-browse-by> </ds-comcol-page-browse-by>
<router-outlet></router-outlet> <router-outlet></router-outlet>
</section> </section>
<footer *ngIf="communityPayload.copyrightText" class="border-top my-5 pt-4"> @if (communityPayload.copyrightText) {
<footer class="border-top my-5 pt-4">
<!-- Copyright --> <!-- Copyright -->
<ds-comcol-page-content [content]="communityPayload.copyrightText" [hasInnerHtml]="true"> <ds-comcol-page-content [content]="communityPayload.copyrightText" [hasInnerHtml]="true">
</ds-comcol-page-content> </ds-comcol-page-content>
</footer> </footer>
}
</div> </div>
}
</div> </div>
}
<ds-error *ngIf="communityRD?.hasFailed" message="{{'error.community' | translate}}"></ds-error> @if (communityRD?.hasFailed) {
<ds-loading *ngIf="communityRD?.isLoading" message="{{'loading.community' | translate}}"></ds-loading> <ds-error message="{{'error.community' | translate}}"></ds-error>
}
@if (communityRD?.isLoading) {
<ds-loading message="{{'loading.community' | translate}}"></ds-loading>
}
</div> </div>

View File

@@ -10,8 +10,12 @@
<i class="fas fa-times" aria-hidden="true"></i> {{'community.delete.cancel' | translate}} <i class="fas fa-times" aria-hidden="true"></i> {{'community.delete.cancel' | translate}}
</button> </button>
<button class="btn btn-danger" (click)="onConfirm(dso)" [dsBtnDisabled]="(processing$ | async)"> <button class="btn btn-danger" (click)="onConfirm(dso)" [dsBtnDisabled]="(processing$ | async)">
<span *ngIf="processing$ | async"><i class='fas fa-circle-notch fa-spin' aria-hidden="true"></i> {{'community.delete.processing' | translate}}</span> @if (processing$ | async) {
<span *ngIf="(processing$ | async) !== true"><i class="fas fa-trash" aria-hidden="true"></i> {{'community.delete.confirm' | translate}}</span> <span><i class='fas fa-circle-notch fa-spin' aria-hidden="true"></i> {{'community.delete.processing' | translate}}</span>
}
@if ((processing$ | async) !== true) {
<span><i class="fas fa-trash" aria-hidden="true"></i> {{'community.delete.confirm' | translate}}</span>
}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -1,8 +1,9 @@
<div class="custom-alignment"> <div class="custom-alignment">
@for (comcolRole of comcolRoles$ | async; track comcolRole) {
<ds-comcol-role <ds-comcol-role
*ngFor="let comcolRole of comcolRoles$ | async"
[dso]="community$ | async" [dso]="community$ | async"
[comcolRole]="comcolRole" [comcolRole]="comcolRole"
> >
</ds-comcol-role> </ds-comcol-role>
}
</div> </div>

View File

@@ -4,16 +4,20 @@
<div class="col-12 col-sm-6"> <div class="col-12 col-sm-6">
<label class="fw-bold form-label" for="task">{{'curation.form.task-select.label' |translate }}</label> <label class="fw-bold form-label" for="task">{{'curation.form.task-select.label' |translate }}</label>
<select id="task" formControlName="task" class="form-select"> <select id="task" formControlName="task" class="form-select">
<option *ngFor="let task of tasks" [value]="task"> @for (task of tasks; track task) {
<option [value]="task">
{{ 'curation-task.task.' + task + '.label' | translate }} {{ 'curation-task.task.' + task + '.label' | translate }}
</option> </option>
}
</select> </select>
</div> </div>
<div *ngIf="!hasHandleValue()" class="col-12 col-sm-6"> @if (!hasHandleValue()) {
<div class="col-12 col-sm-6">
<label class="fw-bold form-label" for="handle">{{'curation.form.handle.label' |translate }}</label> <label class="fw-bold form-label" for="handle">{{'curation.form.handle.label' |translate }}</label>
<input id="handle" class="form-control" formControlName="handle"> <input id="handle" class="form-control" formControlName="handle">
<small class="text-muted">{{'curation.form.handle.hint' |translate }}</small> <small class="text-muted">{{'curation.form.handle.hint' |translate }}</small>
</div> </div>
}
</div> </div>
<button class="btn btn-default btn-primary" type="submit">{{'curation.form.submit' |translate }}</button> <button class="btn btn-default btn-primary" type="submit">{{'curation.form.submit' |translate }}</button>
</div> </div>

View File

@@ -2,28 +2,39 @@
cdkDrag (cdkDragStarted)="dragging.emit(true)" (cdkDragEnded)="dragging.emit(false)" cdkDrag (cdkDragStarted)="dragging.emit(true)" (cdkDragEnded)="dragging.emit(false)"
[ngClass]="{ 'ds-warning': mdValue.reordered || mdValue.change === DsoEditMetadataChangeTypeEnum.UPDATE, 'ds-danger': mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE, 'ds-success': mdValue.change === DsoEditMetadataChangeTypeEnum.ADD, 'h-100': isOnlyValue }"> [ngClass]="{ 'ds-warning': mdValue.reordered || mdValue.change === DsoEditMetadataChangeTypeEnum.UPDATE, 'ds-danger': mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE, 'ds-success': mdValue.change === DsoEditMetadataChangeTypeEnum.ADD, 'h-100': isOnlyValue }">
<div class="flex-grow-1 ds-flex-cell ds-value-cell d-flex flex-column" *ngVar="(mdRepresentation$ | async) as mdRepresentation" role="cell"> <div class="flex-grow-1 ds-flex-cell ds-value-cell d-flex flex-column" *ngVar="(mdRepresentation$ | async) as mdRepresentation" role="cell">
<div class="dont-break-out preserve-line-breaks" *ngIf="!mdValue.editing && !mdRepresentation">{{ mdValue.newValue.value }}</div> @if (!mdValue.editing && !mdRepresentation) {
<textarea class="form-control" rows="5" *ngIf="mdValue.editing && !mdRepresentation && ((isAuthorityControlled() | async) !== true || (enabledFreeTextEditing && (isSuggesterVocabulary() | async) !== true))" [(ngModel)]="mdValue.newValue.value" <div class="dont-break-out preserve-line-breaks">{{ mdValue.newValue.value }}</div>
}
@if (mdValue.editing && !mdRepresentation && ((isAuthorityControlled() | async) !== true || (enabledFreeTextEditing && (isSuggesterVocabulary() | async) !== true))) {
<textarea class="form-control" rows="5" [(ngModel)]="mdValue.newValue.value"
[attr.aria-label]="(dsoType + '.edit.metadata.edit.value') | translate" [attr.aria-label]="(dsoType + '.edit.metadata.edit.value') | translate"
[dsDebounce]="300" (onDebounce)="confirm.emit(false)"></textarea> [dsDebounce]="300" (onDebounce)="confirm.emit(false)"></textarea>
<ds-dynamic-scrollable-dropdown *ngIf="mdValue.editing && (isScrollableVocabulary() | async) && !enabledFreeTextEditing" }
@if (mdValue.editing && (isScrollableVocabulary() | async) && !enabledFreeTextEditing) {
<ds-dynamic-scrollable-dropdown
[bindId]="mdField" [bindId]="mdField"
[group]="group" [group]="group"
[model]="getModel()" [model]="getModel()"
(change)="onChangeAuthorityField($event)"> (change)="onChangeAuthorityField($event)">
</ds-dynamic-scrollable-dropdown> </ds-dynamic-scrollable-dropdown>
<ds-dynamic-onebox *ngIf="mdValue.editing && (((isHierarchicalVocabulary() | async) && !enabledFreeTextEditing) || (isSuggesterVocabulary() | async))" }
@if (mdValue.editing && (((isHierarchicalVocabulary() | async) && !enabledFreeTextEditing) || (isSuggesterVocabulary() | async))) {
<ds-dynamic-onebox
[group]="group" [group]="group"
[model]="getModel()" [model]="getModel()"
(change)="onChangeAuthorityField($event)"> (change)="onChangeAuthorityField($event)">
</ds-dynamic-onebox> </ds-dynamic-onebox>
<button class="btn btn-secondary mt-2" *ngIf="mdValue.editing && ((isScrollableVocabulary() | async) || (isHierarchicalVocabulary() | async))" }
@if (mdValue.editing && ((isScrollableVocabulary() | async) || (isHierarchicalVocabulary() | async))) {
<button class="btn btn-secondary mt-2"
[title]="enabledFreeTextEditing ? dsoType + '.edit.metadata.edit.buttons.disable-free-text-editing' : dsoType + '.edit.metadata.edit.buttons.enable-free-text-editing' | translate" [title]="enabledFreeTextEditing ? dsoType + '.edit.metadata.edit.buttons.disable-free-text-editing' : dsoType + '.edit.metadata.edit.buttons.enable-free-text-editing' | translate"
(click)="toggleFreeTextEdition()"> (click)="toggleFreeTextEdition()">
<i class="fas fa-fw" [ngClass]="enabledFreeTextEditing ? 'fa-lock' : 'fa-unlock'"></i> <i class="fas fa-fw" [ngClass]="enabledFreeTextEditing ? 'fa-lock' : 'fa-unlock'"></i>
{{ (enabledFreeTextEditing ? dsoType + '.edit.metadata.edit.buttons.disable-free-text-editing' : dsoType + '.edit.metadata.edit.buttons.enable-free-text-editing') | translate }} {{ (enabledFreeTextEditing ? dsoType + '.edit.metadata.edit.buttons.disable-free-text-editing' : dsoType + '.edit.metadata.edit.buttons.enable-free-text-editing') | translate }}
</button> </button>
<div *ngIf="!isVirtual && !mdValue.editing && mdValue.newValue.authority && mdValue.newValue.confidence !== ConfidenceTypeEnum.CF_UNSET && mdValue.newValue.confidence !== ConfidenceTypeEnum.CF_NOVALUE"> }
@if (!isVirtual && !mdValue.editing && mdValue.newValue.authority && mdValue.newValue.confidence !== ConfidenceTypeEnum.CF_UNSET && mdValue.newValue.confidence !== ConfidenceTypeEnum.CF_NOVALUE) {
<div>
<span class="badge bg-light border" > <span class="badge bg-light border" >
<i dsAuthorityConfidenceState <i dsAuthorityConfidenceState
class="fas fa-fw p-0" class="fas fa-fw p-0"
@@ -34,7 +45,9 @@
{{ dsoType + '.edit.metadata.authority.label' | translate }} {{ mdValue.newValue.authority }} {{ dsoType + '.edit.metadata.authority.label' | translate }} {{ mdValue.newValue.authority }}
</span> </span>
</div> </div>
<div class="mt-2" *ngIf=" mdValue.editing && (isAuthorityControlled() | async) && (isSuggesterVocabulary() | async)"> }
@if ( mdValue.editing && (isAuthorityControlled() | async) && (isSuggesterVocabulary() | async)) {
<div class="mt-2">
<div class="btn-group w-75"> <div class="btn-group w-75">
<i dsAuthorityConfidenceState <i dsAuthorityConfidenceState
class="fas fa-fw p-0 me-1 mt-auto mb-auto" class="fas fa-fw p-0 me-1 mt-auto mb-auto"
@@ -45,47 +58,62 @@
<input class="form-control form-outline" data-test="authority-input" [(ngModel)]="mdValue.newValue.authority" [disabled]="!editingAuthority" <input class="form-control form-outline" data-test="authority-input" [(ngModel)]="mdValue.newValue.authority" [disabled]="!editingAuthority"
[attr.aria-label]="(dsoType + '.edit.metadata.edit.authority.key') | translate" [attr.aria-label]="(dsoType + '.edit.metadata.edit.authority.key') | translate"
(change)="onChangeAuthorityKey()" /> (change)="onChangeAuthorityKey()" />
<button class="btn btn-outline-secondary btn-sm ng-star-inserted" id="metadata-confirm-btn" *ngIf="!editingAuthority" @if (!editingAuthority) {
<button class="btn btn-outline-secondary btn-sm ng-star-inserted" id="metadata-confirm-btn"
[title]="dsoType + '.edit.metadata.edit.buttons.open-authority-edition' | translate" [title]="dsoType + '.edit.metadata.edit.buttons.open-authority-edition' | translate"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.open-authority-edition' | translate }}" ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.open-authority-edition' | translate }}"
(click)="onChangeEditingAuthorityStatus(true)"> (click)="onChangeEditingAuthorityStatus(true)">
<i class="fas fa-lock fa-fw"></i> <i class="fas fa-lock fa-fw"></i>
</button> </button>
<button class="btn btn-outline-success btn-sm ng-star-inserted" id="metadata-confirm-btn" *ngIf="editingAuthority" }
@if (editingAuthority) {
<button class="btn btn-outline-success btn-sm ng-star-inserted" id="metadata-confirm-btn"
[title]="dsoType + '.edit.metadata.edit.buttons.close-authority-edition' | translate" [title]="dsoType + '.edit.metadata.edit.buttons.close-authority-edition' | translate"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.close-authority-edition' | translate }}" ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.close-authority-edition' | translate }}"
(click)="onChangeEditingAuthorityStatus(false)"> (click)="onChangeEditingAuthorityStatus(false)">
<i class="fas fa-lock-open fa-fw"></i> <i class="fas fa-lock-open fa-fw"></i>
</button> </button>
}
</div> </div>
</div> </div>
<div class="d-flex" *ngIf="mdRepresentation"> }
@if (mdRepresentation) {
<div class="d-flex">
<a class="me-2" target="_blank" [routerLink]="mdRepresentationItemRoute$ | async">{{ mdRepresentationName$ | async }}</a> <a class="me-2" target="_blank" [routerLink]="mdRepresentationItemRoute$ | async">{{ mdRepresentationName$ | async }}</a>
<ds-type-badge [object]="mdRepresentation"></ds-type-badge> <ds-type-badge [object]="mdRepresentation"></ds-type-badge>
</div> </div>
}
</div> </div>
<div class="ds-flex-cell ds-lang-cell" role="cell"> <div class="ds-flex-cell ds-lang-cell" role="cell">
<div class="dont-break-out preserve-line-breaks" *ngIf="!mdValue.editing">{{ mdValue.newValue.language }}</div> @if (!mdValue.editing) {
<input class="form-control" type="text" *ngIf="mdValue.editing" [(ngModel)]="mdValue.newValue.language" <div class="dont-break-out preserve-line-breaks">{{ mdValue.newValue.language }}</div>
}
@if (mdValue.editing) {
<input class="form-control" type="text" [(ngModel)]="mdValue.newValue.language"
[attr.aria-label]="(dsoType + '.edit.metadata.edit.language') | translate" [attr.aria-label]="(dsoType + '.edit.metadata.edit.language') | translate"
[dsDebounce]="300" (onDebounce)="confirm.emit(false)" /> [dsDebounce]="300" (onDebounce)="confirm.emit(false)" />
}
</div> </div>
<div class="text-center ds-flex-cell ds-edit-cell" role="cell"> <div class="text-center ds-flex-cell ds-edit-cell" role="cell">
<div class="btn-group"> <div class="btn-group">
<div class="edit-field"> <div class="edit-field">
<div class="btn-group edit-buttons" [ngbTooltip]="isVirtual ? (dsoType + '.edit.metadata.edit.buttons.virtual' | translate) : null"> <div class="btn-group edit-buttons" [ngbTooltip]="isVirtual ? (dsoType + '.edit.metadata.edit.buttons.virtual' | translate) : null">
<button class="btn btn-outline-primary btn-sm ng-star-inserted" data-test="metadata-edit-btn" *ngIf="!mdValue.editing" @if (!mdValue.editing) {
<button class="btn btn-outline-primary btn-sm ng-star-inserted" data-test="metadata-edit-btn"
[title]="dsoType + '.edit.metadata.edit.buttons.edit' | translate" [title]="dsoType + '.edit.metadata.edit.buttons.edit' | translate"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.edit' | translate }}" ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.edit' | translate }}"
[dsBtnDisabled]="isVirtual || mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE || (saving$ | async)" (click)="edit.emit()"> [dsBtnDisabled]="isVirtual || mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE || (saving$ | async)" (click)="edit.emit()">
<i class="fas fa-edit fa-fw"></i> <i class="fas fa-edit fa-fw"></i>
</button> </button>
<button class="btn btn-outline-success btn-sm ng-star-inserted" data-test="metadata-confirm-btn" *ngIf="mdValue.editing" }
@if (mdValue.editing) {
<button class="btn btn-outline-success btn-sm ng-star-inserted" data-test="metadata-confirm-btn"
[title]="dsoType + '.edit.metadata.edit.buttons.confirm' | translate" [title]="dsoType + '.edit.metadata.edit.buttons.confirm' | translate"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.confirm' | translate }}" ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.confirm' | translate }}"
[dsBtnDisabled]="isVirtual || (saving$ | async)" (click)="confirm.emit(true)"> [dsBtnDisabled]="isVirtual || (saving$ | async)" (click)="confirm.emit(true)">
<i class="fas fa-check fa-fw"></i> <i class="fas fa-check fa-fw"></i>
</button> </button>
}
<button class="btn btn-outline-danger btn-sm" data-test="metadata-remove-btn" <button class="btn btn-outline-danger btn-sm" data-test="metadata-remove-btn"
[title]="dsoType + '.edit.metadata.edit.buttons.remove' | translate" [title]="dsoType + '.edit.metadata.edit.buttons.remove' | translate"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.remove' | translate }}" ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.remove' | translate }}"

View File

@@ -1,4 +1,5 @@
<div class="item-metadata" *ngIf="form"> @if (form) {
<div class="item-metadata">
<div class="button-row top d-flex my-2 space-children-mr ms-gap"> <div class="button-row top d-flex my-2 space-children-mr ms-gap">
<button class="me-auto btn btn-success" id="dso-add-btn" [dsBtnDisabled]="form.newValue || (saving$ | async)" <button class="me-auto btn btn-success" id="dso-add-btn" [dsBtnDisabled]="form.newValue || (saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.add-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.add-button' | translate"
@@ -6,30 +7,34 @@
(click)="add()"><i class="fas fa-plus" aria-hidden="true"></i> (click)="add()"><i class="fas fa-plus" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.add-button' | translate }}</span> <span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.add-button' | translate }}</span>
</button> </button>
<button class="btn btn-warning ms-1" id="dso-reinstate-btn" *ngIf="isReinstatable" [dsBtnDisabled]="(saving$ | async)" @if (isReinstatable) {
<button class="btn btn-warning ms-1" id="dso-reinstate-btn" [dsBtnDisabled]="(saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.reinstate-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.reinstate-button' | translate"
[title]="dsoType + '.edit.metadata.reinstate-button' | translate" [title]="dsoType + '.edit.metadata.reinstate-button' | translate"
(click)="reinstate()"><i class="fas fa-undo-alt" aria-hidden="true"></i> (click)="reinstate()"><i class="fas fa-undo-alt" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.reinstate-button' | translate }}</span> <span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.reinstate-button' | translate }}</span>
</button> </button>
}
<button class="btn btn-primary ms-1" id="dso-save-btn" [dsBtnDisabled]="!hasChanges || (saving$ | async)" <button class="btn btn-primary ms-1" id="dso-save-btn" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate"
[title]="dsoType + '.edit.metadata.save-button' | translate" [title]="dsoType + '.edit.metadata.save-button' | translate"
(click)="submit()"><i class="fas fa-save" aria-hidden="true"></i> (click)="submit()"><i class="fas fa-save" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.save-button' | translate }}</span> <span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.save-button' | translate }}</span>
</button> </button>
<button class="btn btn-danger ms-1" id="dso-discard-btn" *ngIf="!isReinstatable" @if (!isReinstatable) {
<button class="btn btn-danger ms-1" id="dso-discard-btn"
[attr.aria-label]="dsoType + '.edit.metadata.discard-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.discard-button' | translate"
[title]="dsoType + '.edit.metadata.discard-button' | translate" [title]="dsoType + '.edit.metadata.discard-button' | translate"
[dsBtnDisabled]="!hasChanges || (saving$ | async)" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
(click)="discard()"><i class="fas fa-times" aria-hidden="true"></i> (click)="discard()"><i class="fas fa-times" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.discard-button' | translate }}</span> <span class="d-none d-sm-inline">&nbsp;{{ dsoType + '.edit.metadata.discard-button' | translate }}</span>
</button> </button>
}
</div> </div>
<div role="table" [attr.aria-label]="'item.edit.head' | translate"> <div role="table" [attr.aria-label]="'item.edit.head' | translate">
<ds-dso-edit-metadata-headers [dsoType]="dsoType"></ds-dso-edit-metadata-headers> <ds-dso-edit-metadata-headers [dsoType]="dsoType"></ds-dso-edit-metadata-headers>
<div class="d-flex flex-row ds-field-row" role="row" *ngIf="form.newValue"> @if (form.newValue) {
<div class="d-flex flex-row ds-field-row" role="row">
<div class="lbl-cell ds-success" role="rowheader"> <div class="lbl-cell ds-success" role="rowheader">
<ds-metadata-field-selector [dsoType]="dsoType" <ds-metadata-field-selector [dsoType]="dsoType"
[(mdField)]="newMdField" [(mdField)]="newMdField"
@@ -52,13 +57,17 @@
</div> </div>
</div> </div>
</div> </div>
<div class="d-flex flex-row ds-field-row" role="row" *ngFor="let mdField of form.fieldKeys"> }
@for (mdField of form.fieldKeys; track mdField) {
<div class="d-flex flex-row ds-field-row" role="row">
<div class="lbl-cell" role="rowheader"> <div class="lbl-cell" role="rowheader">
<span class="dont-break-out preserve-line-breaks">{{ mdField }}</span> <span class="dont-break-out preserve-line-breaks">{{ mdField }}</span>
<div class="btn btn-warning reset-order-button mt-2 w-100" *ngIf="form.hasOrderChanges(mdField)" @if (form.hasOrderChanges(mdField)) {
<div class="btn btn-warning reset-order-button mt-2 w-100"
(click)="form.resetOrder(mdField); onValueSaved()"> (click)="form.resetOrder(mdField); onValueSaved()">
{{ dsoType + '.edit.metadata.reset-order-button' | translate }} {{ dsoType + '.edit.metadata.reset-order-button' | translate }}
</div> </div>
}
</div> </div>
<ds-dso-edit-metadata-field-values class="flex-grow-1" role="cell" <ds-dso-edit-metadata-field-values class="flex-grow-1" role="cell"
[dso]="dso" [dso]="dso"
@@ -70,33 +79,42 @@
(valueSaved)="onValueSaved()"> (valueSaved)="onValueSaved()">
</ds-dso-edit-metadata-field-values> </ds-dso-edit-metadata-field-values>
</div> </div>
}
</div> </div>
@if (isEmpty && !form.newValue) {
<div *ngIf="isEmpty && !form.newValue"> <div>
<ds-alert [content]="dsoType + '.edit.metadata.empty'" [type]="AlertTypeEnum.Info"></ds-alert> <ds-alert [content]="dsoType + '.edit.metadata.empty'" [type]="AlertTypeEnum.Info"></ds-alert>
</div> </div>
}
<div class="button-row bottom d-inline-block w-100"> <div class="button-row bottom d-inline-block w-100">
<div class="mt-2 float-end space-children-mr ms-gap"> <div class="mt-2 float-end space-children-mr ms-gap">
<button class="btn btn-warning" *ngIf="isReinstatable" [dsBtnDisabled]="(saving$ | async)" @if (isReinstatable) {
<button class="btn btn-warning" [dsBtnDisabled]="(saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.reinstate-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.reinstate-button' | translate"
[title]="dsoType + '.edit.metadata.reinstate-button' | translate" [title]="dsoType + '.edit.metadata.reinstate-button' | translate"
(click)="reinstate()"> (click)="reinstate()">
<i class="fas fa-undo-alt" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.reinstate-button' | translate }} <i class="fas fa-undo-alt" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.reinstate-button' | translate }}
</button> </button>
}
<button class="btn btn-primary" [dsBtnDisabled]="!hasChanges || (saving$ | async)" <button class="btn btn-primary" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate"
[title]="dsoType + '.edit.metadata.save-button' | translate" [title]="dsoType + '.edit.metadata.save-button' | translate"
(click)="submit()"> (click)="submit()">
<i class="fas fa-save" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.save-button' | translate }} <i class="fas fa-save" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.save-button' | translate }}
</button> </button>
<button class="btn btn-danger" *ngIf="!isReinstatable" @if (!isReinstatable) {
<button class="btn btn-danger"
[attr.aria-label]="dsoType + '.edit.metadata.discard-button' | translate" [attr.aria-label]="dsoType + '.edit.metadata.discard-button' | translate"
[title]="dsoType + '.edit.metadata.discard-button' | translate" [title]="dsoType + '.edit.metadata.discard-button' | translate"
[dsBtnDisabled]="!hasChanges || (saving$ | async)" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
(click)="discard()"> (click)="discard()">
<i class="fas fa-times" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.discard-button' | translate }} <i class="fas fa-times" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.discard-button' | translate }}
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
<ds-loading *ngIf="!form"></ds-loading> }
@if (!form) {
<ds-loading></ds-loading>
}

View File

@@ -3,20 +3,30 @@
<!-- <ds-themed-thumbnail [thumbnail]="dso?.thumbnail | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-themed-thumbnail>--> <!-- <ds-themed-thumbnail [thumbnail]="dso?.thumbnail | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-themed-thumbnail>-->
<!-- </div>--> <!-- </div>-->
<div class="flex-grow-1"> <div class="flex-grow-1">
<ds-org-unit-input-suggestions *ngIf="useNameVariants" [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)" @if (useNameVariants) {
<ds-org-unit-input-suggestions [suggestions]="allSuggestions" [(ngModel)]="selectedName" (clickSuggestion)="select($event)"
(submitSuggestion)="selectCustom($event)"></ds-org-unit-input-suggestions> (submitSuggestion)="selectCustom($event)"></ds-org-unit-input-suggestions>
}
<div *ngIf="!useNameVariants" class="lead" [innerHTML]="dsoTitle"></div> @if (!useNameVariants) {
<div class="lead" [innerHTML]="dsoTitle"></div>
}
<span class="text-muted"> <span class="text-muted">
<span *ngIf="dso.allMetadata('organization.address.addressLocality').length > 0" @if (dso.allMetadata('organization.address.addressLocality').length > 0) {
<span
class="item-list-address-locality"> class="item-list-address-locality">
<span [innerHTML]="firstMetadataValue(['organization.address.addressLocality'])"></span><span *ngIf="dso.allMetadata('organization.address.addressCountry').length > 0">, </span> <span [innerHTML]="firstMetadataValue(['organization.address.addressLocality'])"></span>@if (dso.allMetadata('organization.address.addressCountry').length > 0) {
<span>, </span>
}
</span> </span>
<span *ngIf="dso.allMetadata('organization.address.addressCountry').length > 0" }
@if (dso.allMetadata('organization.address.addressCountry').length > 0) {
<span
class="item-list-address-country"> class="item-list-address-country">
<span [innerHTML]="firstMetadataValue(['organization.address.addressCountry'])"></span> <span [innerHTML]="firstMetadataValue(['organization.address.addressCountry'])"></span>
</span> </span>
}
</span> </span>
</div> </div>
</div> </div>

View File

@@ -1,14 +1,13 @@
<footer> <footer>
<div *ngIf="showTopFooter" class="top-footer"> @if (showTopFooter) {
<div class="top-footer">
<!-- Grid container --> <!-- Grid container -->
<div class=" container p-4"> <div class=" container p-4">
<!--Grid row--> <!--Grid row-->
<div class="row"> <div class="row">
<!--Grid column--> <!--Grid column-->
<div class="col-lg-4 col-md-6 mb-4 mb-lg-0"> <div class="col-lg-4 col-md-6 mb-4 mb-lg-0">
<h5 class="text-uppercase">Footer Content</h5> <h5 class="text-uppercase">Footer Content</h5>
<ul class="list-unstyled mb-0"> <ul class="list-unstyled mb-0">
<li> <li>
<a routerLink="./" class="">Lorem ipsum</a> <a routerLink="./" class="">Lorem ipsum</a>
@@ -22,11 +21,9 @@
</ul> </ul>
</div> </div>
<!--Grid column--> <!--Grid column-->
<!--Grid column--> <!--Grid column-->
<div class="col-lg-4 col-md-6 mb-4 mb-lg-0"> <div class="col-lg-4 col-md-6 mb-4 mb-lg-0">
<h5 class="text-uppercase">Footer Content</h5> <h5 class="text-uppercase">Footer Content</h5>
<ul class="list-unstyled mb-0"> <ul class="list-unstyled mb-0">
<li> <li>
<a routerLink="./" class="">Suspendisse potenti</a> <a routerLink="./" class="">Suspendisse potenti</a>
@@ -34,11 +31,9 @@
</ul> </ul>
</div> </div>
<!--Grid column--> <!--Grid column-->
<!--Grid column--> <!--Grid column-->
<div class="col-lg-4 col-md-12 mb-4 mb-md-0"> <div class="col-lg-4 col-md-12 mb-4 mb-md-0">
<h5 class="text-uppercase">Footer Content</h5> <h5 class="text-uppercase">Footer Content</h5>
<p> <p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Iste atque ea quis Lorem ipsum dolor sit amet consectetur, adipisicing elit. Iste atque ea quis
molestias. Fugiat pariatur maxime quis culpa corporis vitae repudiandae aliquam molestias. Fugiat pariatur maxime quis culpa corporis vitae repudiandae aliquam
@@ -50,6 +45,7 @@
<!--Grid row--> <!--Grid row-->
</div> </div>
</div> </div>
}
<!-- Grid container --> <!-- Grid container -->
<!-- Copyright --> <!-- Copyright -->
@@ -68,26 +64,34 @@
{{ 'footer.link.cookies' | translate}} {{ 'footer.link.cookies' | translate}}
</button> </button>
</li> </li>
<li *ngIf="showPrivacyPolicy"> @if (showPrivacyPolicy) {
<li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a> routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a>
</li> </li>
<li *ngIf="showEndUserAgreement"> }
@if (showEndUserAgreement) {
<li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a> routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a>
</li> </li>
<li *ngIf="showSendFeedback$ | async"> }
@if (showSendFeedback$ | async) {
<li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/feedback">{{ 'footer.link.feedback' | translate}}</a> routerLink="info/feedback">{{ 'footer.link.feedback' | translate}}</a>
</li> </li>
}
</ul> </ul>
</div> </div>
<div *ngIf="coarLdnEnabled$ | async" class="notify-enabled text-white"> @if (coarLdnEnabled$ | async) {
<div class="notify-enabled text-white">
<a class="coar-notify-support-route" routerLink="info/coar-notify-support"> <a class="coar-notify-support-route" routerLink="info/coar-notify-support">
<img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" /> <img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" />
{{ 'footer.link.coar-notify-support' | translate }} {{ 'footer.link.coar-notify-support' | translate }}
</a> </a>
</div> </div>
}
</div> </div>
<!-- Copyright --> <!-- Copyright -->
</footer> </footer>

View File

@@ -1,4 +1,5 @@
<div class="container" *ngIf="(registration$ |async)"> @if ((registration$ |async)) {
<div class="container">
<h1 class="mb-4">{{'forgot-password.form.head' | translate}}</h1> <h1 class="mb-4">{{'forgot-password.form.head' | translate}}</h1>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'forgot-password.form.identification.header' | translate}}</div> <div class="card-header">{{'forgot-password.form.identification.header' | translate}}</div>
@@ -11,11 +12,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'forgot-password.form.card.security' | translate}}</div> <div class="card-header">{{'forgot-password.form.card.security' | translate}}</div>
<div class="card-body"> <div class="card-body">
<ds-profile-page-security-form <ds-profile-page-security-form
[passwordCanBeEmpty]="false" [passwordCanBeEmpty]="false"
[FORM_PREFIX]="'forgot-password.form.'" [FORM_PREFIX]="'forgot-password.form.'"
@@ -24,7 +23,6 @@
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<button <button
@@ -34,3 +32,4 @@
</div> </div>
</div> </div>
</div> </div>
}

View File

@@ -11,13 +11,15 @@
<ds-context-help-toggle></ds-context-help-toggle> <ds-context-help-toggle></ds-context-help-toggle>
<ds-auth-nav-menu></ds-auth-nav-menu> <ds-auth-nav-menu></ds-auth-nav-menu>
<ds-impersonate-navbar></ds-impersonate-navbar> <ds-impersonate-navbar></ds-impersonate-navbar>
<div *ngIf="isMobile$ | async" class="ps-2"> @if (isMobile$ | async) {
<div class="ps-2">
<button class="navbar-toggler px-0" type="button" (click)="toggleNavbar()" <button class="navbar-toggler px-0" type="button" (click)="toggleNavbar()"
aria-controls="collapsingNav" aria-controls="collapsingNav"
aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate"> aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate">
<span class="fas fa-bars fa-fw toggler-icon" aria-hidden="true"></span> <span class="fas fa-bars fa-fw toggler-icon" aria-hidden="true"></span>
</button> </button>
</div> </div>
}
</nav> </nav>
</div> </div>
</div> </div>

View File

@@ -1,13 +1,19 @@
<div *ngFor="let entry of healthInfoComponent | dsObjNgFor" data-test="collapse"> @for (entry of healthInfoComponent | dsObjNgFor; track entry) {
<div *ngIf="entry && !isPlainProperty(entry.value)" class="mb-3 border-bottom"> <div data-test="collapse">
@if (entry && !isPlainProperty(entry.value)) {
<div class="mb-3 border-bottom">
<div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="collapse.toggle()"> <div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="collapse.toggle()">
<button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="!collapse.collapsed" <button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="!collapse.collapsed"
[attr.aria-controls]="'health-info-component-' + entry.key + '-content'"> [attr.aria-controls]="'health-info-component-' + entry.key + '-content'">
{{ entry.key | titlecase }} {{ entry.key | titlecase }}
</button> </button>
<div class="d-flex my-auto"> <div class="d-flex my-auto">
<span *ngIf="collapse.collapsed" class="fas fa-chevron-down"></span> @if (collapse.collapsed) {
<span *ngIf="!collapse.collapsed" class="fas fa-chevron-up"></span> <span class="fas fa-chevron-down"></span>
}
@if (!collapse.collapsed) {
<span class="fas fa-chevron-up"></span>
}
</div> </div>
</div> </div>
<div #collapse="ngbCollapse" [id]="'health-info-component-' + entry.key + '-content'" [ngbCollapse]="isCollapsed"> <div #collapse="ngbCollapse" [id]="'health-info-component-' + entry.key + '-content'" [ngbCollapse]="isCollapsed">
@@ -21,7 +27,9 @@
</div> </div>
</div> </div>
</div> </div>
<ng-container *ngIf="entry && isPlainProperty(entry.value)"> }
@if (entry && isPlainProperty(entry.value)) {
<p data-test="property"> <span class="fw-bold">{{ getPropertyLabel(entry.key) | titlecase }}</span> : {{entry.value}}</p> <p data-test="property"> <span class="fw-bold">{{ getPropertyLabel(entry.key) | titlecase }}</span> : {{entry.value}}</p>
</ng-container> }
</div> </div>
}

View File

@@ -1,6 +1,7 @@
<ng-container *ngIf="healthInfoResponse"> @if (healthInfoResponse) {
<ngb-accordion #acc="ngbAccordion" [activeIds]="activeId"> <ngb-accordion #acc="ngbAccordion" [activeIds]="activeId">
<ngb-panel [id]="entry.key" *ngFor="let entry of healthInfoResponse | dsObjNgFor"> @for (entry of healthInfoResponse | dsObjNgFor; track entry) {
<ngb-panel [id]="entry.key">
<ng-template ngbPanelTitle> <ng-template ngbPanelTitle>
<div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="acc.toggle(entry.key)" data-test="info-component"> <div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="acc.toggle(entry.key)" data-test="info-component">
<button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="acc.isExpanded(entry.key)" <button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="acc.isExpanded(entry.key)"
@@ -18,5 +19,6 @@
</ds-health-info-component> </ds-health-info-component>
</ng-template> </ng-template>
</ngb-panel> </ngb-panel>
}
</ngb-accordion> </ngb-accordion>
</ng-container> }

View File

@@ -1,13 +1,18 @@
<ng-container *ngIf="healthComponent?.components"> @if (healthComponent?.components) {
<div *ngFor="let entry of healthComponent?.components | dsObjNgFor" class="mb-3 border-bottom" data-test="collapse"> @for (entry of healthComponent?.components | dsObjNgFor; track entry) {
<div class="mb-3 border-bottom" data-test="collapse">
<div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="collapse.toggle()"> <div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="collapse.toggle()">
<button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="!collapse.collapsed" <button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="!collapse.collapsed"
[attr.aria-controls]="'health-component-' + entry.key + 'content'"> [attr.aria-controls]="'health-component-' + entry.key + 'content'">
{{ entry.key | titlecase }} {{ entry.key | titlecase }}
</button> </button>
<div class="d-flex my-auto"> <div class="d-flex my-auto">
<span *ngIf="collapse.collapsed" class="fas fa-chevron-down"></span> @if (collapse.collapsed) {
<span *ngIf="!collapse.collapsed" class="fas fa-chevron-up"></span> <span class="fas fa-chevron-down"></span>
}
@if (!collapse.collapsed) {
<span class="fas fa-chevron-up"></span>
}
</div> </div>
</div> </div>
<div #collapse="ngbCollapse" [id]="'health-component-' + entry.key + 'content'" [ngbCollapse]="isCollapsed"> <div #collapse="ngbCollapse" [id]="'health-component-' + entry.key + 'content'" [ngbCollapse]="isCollapsed">
@@ -19,12 +24,15 @@
</div> </div>
</div> </div>
</div> </div>
</ng-container> }
<ng-container *ngIf="healthComponent?.details"> }
<div *ngFor="let item of healthComponent?.details | dsObjNgFor" data-test="details"> @if (healthComponent?.details) {
@for (item of healthComponent?.details | dsObjNgFor; track item) {
<div data-test="details">
<p data-test="property"><span class="fw-bold">{{ getPropertyLabel(item.key) | titlecase }}</span> : {{item.value}}</p> <p data-test="property"><span class="fw-bold">{{ getPropertyLabel(item.key) | titlecase }}</span> : {{item.value}}</p>
</div> </div>
</ng-container> }
<ng-container *ngIf="!healthComponent?.details && !healthComponent?.components"> }
@if (!healthComponent?.details && !healthComponent?.components) {
<ds-alert [content]="'health-page.section.no-issues'" [type]="AlertTypeEnum.Info"></ds-alert> <ds-alert [content]="'health-page.section.no-issues'" [type]="AlertTypeEnum.Info"></ds-alert>
</ng-container> }

View File

@@ -3,7 +3,8 @@
<ds-health-status [status]="healthResponse.status" class="d-inline-flex"></ds-health-status> <ds-health-status [status]="healthResponse.status" class="d-inline-flex"></ds-health-status>
</p> </p>
<ngb-accordion #acc="ngbAccordion" [activeIds]="activeId"> <ngb-accordion #acc="ngbAccordion" [activeIds]="activeId">
<ngb-panel [id]="entry.key" *ngFor="let entry of healthResponse.components | dsObjNgFor"> @for (entry of healthResponse.components | dsObjNgFor; track entry) {
<ngb-panel [id]="entry.key">
<ng-template ngbPanelTitle> <ng-template ngbPanelTitle>
<div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="acc.toggle(entry.key)" data-test="component"> <div class="w-100 d-flex gap-3 justify-content-between collapse-toggle" (click)="acc.toggle(entry.key)" data-test="component">
<button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="acc.isExpanded(entry.key)" <button type="button" class="btn btn-link p-0" (click)="$event.preventDefault()" [attr.aria-expanded]="acc.isExpanded(entry.key)"
@@ -21,4 +22,5 @@
</ds-health-component> </ds-health-component>
</ng-template> </ng-template>
</ngb-panel> </ngb-panel>
}
</ngb-accordion> </ngb-accordion>

View File

@@ -1,12 +1,18 @@
<ng-container [ngSwitch]="status">
<i *ngSwitchCase="HealthStatus.UP" @switch (status) {
@case (HealthStatus.UP) {
<i
class="fa fa-check-circle text-success ms-2 mt-1" class="fa fa-check-circle text-success ms-2 mt-1"
ngbTooltip="{{'health-page.status.ok.info' | translate}}" container="body" ></i> ngbTooltip="{{'health-page.status.ok.info' | translate}}" container="body" ></i>
<i *ngSwitchCase="HealthStatus.UP_WITH_ISSUES" }
@case (HealthStatus.UP_WITH_ISSUES) {
<i
class="fa fa-exclamation-triangle text-warning ms-2 mt-1" class="fa fa-exclamation-triangle text-warning ms-2 mt-1"
ngbTooltip="{{'health-page.status.warning.info' | translate}}" container="body"></i> ngbTooltip="{{'health-page.status.warning.info' | translate}}" container="body"></i>
<i *ngSwitchCase="HealthStatus.DOWN" }
@case (HealthStatus.DOWN) {
<i
class="fa fa-times-circle text-danger ms-2 mt-1" class="fa fa-times-circle text-danger ms-2 mt-1"
ngbTooltip="{{'health-page.status.error.info' | translate}}" container="body"></i> ngbTooltip="{{'health-page.status.error.info' | translate}}" container="body"></i>
}
</ng-container> }

View File

@@ -1,14 +1,22 @@
<ng-container *ngVar="(itemRD$ | async) as itemRD"> <ng-container *ngVar="(itemRD$ | async) as itemRD">
<div class="mt-4" [ngClass]="placeholderFontClass" *ngIf="itemRD?.hasSucceeded && itemRD?.payload?.page.length > 0" @fadeIn> @if (itemRD?.hasSucceeded && itemRD?.payload?.page.length > 0) {
<div class="mt-4" [ngClass]="placeholderFontClass" @fadeIn>
<div class="d-flex flex-row border-bottom mb-4 pb-4"></div> <div class="d-flex flex-row border-bottom mb-4 pb-4"></div>
<h2> {{'home.recent-submissions.head' | translate}}</h2> <h2> {{'home.recent-submissions.head' | translate}}</h2>
<div class="my-4" *ngFor="let item of itemRD?.payload?.page"> @for (item of itemRD?.payload?.page; track item) {
<div class="my-4">
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4"> <ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
</div> </div>
}
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-start ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button> <button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-start ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
</div> </div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.recent-submissions' | translate}}"></ds-error> }
<ds-loading *ngIf="!itemRD || itemRD.isLoading" message="{{'loading.recent-submissions' | translate}}"> @if (itemRD?.hasFailed) {
<ds-error message="{{'error.recent-submissions' | translate}}"></ds-error>
}
@if (!itemRD || itemRD.isLoading) {
<ds-loading message="{{'loading.recent-submissions' | translate}}">
</ds-loading> </ds-loading>
}
</ng-container> </ng-container>

View File

@@ -1,13 +1,19 @@
<div class="container"> <div class="container">
<h1 class="mb-4">{{'bitstream-request-a-copy.header' | translate}}</h1> <h1 class="mb-4">{{'bitstream-request-a-copy.header' | translate}}</h1>
<div *ngIf="canDownload$|async" class="alert alert-success"> @if (canDownload$|async) {
<div class="alert alert-success">
<span>{{'bitstream-request-a-copy.alert.canDownload1' | translate}}</span> <span>{{'bitstream-request-a-copy.alert.canDownload1' | translate}}</span>
<a [routerLink]="getBitstreamLink()">{{'bitstream-request-a-copy.alert.canDownload2'| translate}}</a> <a [routerLink]="getBitstreamLink()">{{'bitstream-request-a-copy.alert.canDownload2'| translate}}</a>
</div> </div>
}
<div> <div>
<p>{{'bitstream-request-a-copy.intro' | translate}} <a [routerLink]="getItemPath()">{{itemName}}</a></p> <p>{{'bitstream-request-a-copy.intro' | translate}} <a [routerLink]="getItemPath()">{{itemName}}</a></p>
<p *ngIf="bitstream !== undefined && allfiles.value === 'false'">{{'bitstream-request-a-copy.intro.bitstream.one' | translate}} {{bitstreamName}}</p> @if (bitstream !== undefined && allfiles.value === 'false') {
<p *ngIf="allfiles.value === 'true'">{{'bitstream-request-a-copy.intro.bitstream.all' | translate}}</p> <p>{{'bitstream-request-a-copy.intro.bitstream.one' | translate}} {{bitstreamName}}</p>
}
@if (allfiles.value === 'true') {
<p>{{'bitstream-request-a-copy.intro.bitstream.all' | translate}}</p>
}
</div> </div>
<form [class]="'ng-invalid'" [formGroup]="requestCopyForm" (ngSubmit)="onSubmit()"> <form [class]="'ng-invalid'" [formGroup]="requestCopyForm" (ngSubmit)="onSubmit()">
@@ -17,12 +23,16 @@
<label for="name" class="form-label">{{'bitstream-request-a-copy.name.label' | translate}}</label> <label for="name" class="form-label">{{'bitstream-request-a-copy.name.label' | translate}}</label>
<input [className]="(name.invalid) && (name.dirty || name.touched) ? 'form-control is-invalid' :'form-control'" <input [className]="(name.invalid) && (name.dirty || name.touched) ? 'form-control is-invalid' :'form-control'"
type="text" id="name" formControlName="name"/> type="text" id="name" formControlName="name"/>
<div *ngIf="name.invalid && (name.dirty || name.touched)" @if (name.invalid && (name.dirty || name.touched)) {
<div
class="invalid-feedback show-feedback"> class="invalid-feedback show-feedback">
<span *ngIf="name.errors && name.errors.required"> @if (name.errors && name.errors.required) {
<span>
{{ 'bitstream-request-a-copy.name.error' | translate }} {{ 'bitstream-request-a-copy.name.error' | translate }}
</span> </span>
}
</div> </div>
}
</div> </div>
</div> </div>
<div class="row mb-4"> <div class="row mb-4">
@@ -32,12 +42,16 @@
<input <input
[className]="(email.invalid) && (email.dirty || email.touched) ? 'form-control is-invalid' :'form-control'" [className]="(email.invalid) && (email.dirty || email.touched) ? 'form-control is-invalid' :'form-control'"
id="email" formControlName="email"> id="email" formControlName="email">
<div *ngIf="email.invalid && (email.dirty || email.touched)" @if (email.invalid && (email.dirty || email.touched)) {
<div
class="invalid-feedback show-feedback"> class="invalid-feedback show-feedback">
<span *ngIf="email.errors"> @if (email.errors) {
<span>
{{ 'bitstream-request-a-copy.email.error' | translate }} {{ 'bitstream-request-a-copy.email.error' | translate }}
</span> </span>
}
</div> </div>
}
<small class="text-muted ds-hint">{{'bitstream-request-a-copy.email.hint' |translate}}</small> <small class="text-muted ds-hint">{{'bitstream-request-a-copy.email.hint' |translate}}</small>
</div> </div>
</div> </div>

View File

@@ -1,13 +1,15 @@
<div class="container"> <div class="container">
<ng-container *ngIf="bundles"> @if (bundles) {
<div class="row"> <div class="row">
<div class="col-12 mb-2"> <div class="col-12 mb-2">
<h1>{{'item.bitstreams.upload.title' | translate}}</h1> <h1>{{'item.bitstreams.upload.title' | translate}}</h1>
<ng-container *ngVar="(itemRD$ | async)?.payload as item"> <ng-container *ngVar="(itemRD$ | async)?.payload as item">
<div *ngIf="item"> @if (item) {
<div>
<span class="fw-bold">{{'item.bitstreams.upload.item' | translate}}</span> <span class="fw-bold">{{'item.bitstreams.upload.item' | translate}}</span>
<span>{{ dsoNameService.getName(item) }}</span> <span>{{ dsoNameService.getName(item) }}</span>
</div> </div>
}
</ng-container> </ng-container>
</div> </div>
<div class="col-12"> <div class="col-12">
@@ -24,18 +26,22 @@
(click)="f.open()" (click)="f.open()"
ngDefaultControl> ngDefaultControl>
</ds-dso-input-suggestions> </ds-dso-input-suggestions>
<button *ngIf="!selectedBundleId && selectedBundleName?.length > 0" class="btn btn-success me-2" (click)="createBundle()"> @if (!selectedBundleId && selectedBundleName?.length > 0) {
<button class="btn btn-success me-2" (click)="createBundle()">
<i class="fa fa-plus"></i> {{ 'item.bitstreams.upload.bundle.new' | translate }} <i class="fa fa-plus"></i> {{ 'item.bitstreams.upload.bundle.new' | translate }}
</button> </button>
<ds-uploader class="w-100" *ngIf="selectedBundleId" }
@if (selectedBundleId) {
<ds-uploader class="w-100"
[dropMsg]="'item.bitstreams.upload.drop-message'" [dropMsg]="'item.bitstreams.upload.drop-message'"
[dropOverDocumentMsg]="'item.bitstreams.upload.drop-message'" [dropOverDocumentMsg]="'item.bitstreams.upload.drop-message'"
[enableDragOverDocument]="true" [enableDragOverDocument]="true"
[uploadFilesOptions]="uploadFilesOptions" [uploadFilesOptions]="uploadFilesOptions"
(onCompleteItem)="onCompleteItem($event)" (onCompleteItem)="onCompleteItem($event)"
(onUploadError)="onUploadError()"></ds-uploader> (onUploadError)="onUploadError()"></ds-uploader>
}
<button class="btn btn-outline-secondary" (click)="onCancel()">{{'item.bitstreams.upload.cancel' | translate}}</button> <button class="btn btn-outline-secondary" (click)="onCancel()">{{'item.bitstreams.upload.cancel' | translate}}</button>
</div> </div>
</div> </div>
</ng-container> }
</div> </div>

View File

@@ -3,9 +3,12 @@
<div class="col-12"> <div class="col-12">
<h1 class="border-bottom">{{'item.edit.head' | translate}}</h1> <h1 class="border-bottom">{{'item.edit.head' | translate}}</h1>
<div class="pt-2"> <div class="pt-2">
<ul *ngIf="pages.length > 0" class="nav nav-tabs justify-content-start" role="tablist"> @if (pages.length > 0) {
<li *ngFor="let page of pages" class="nav-item" role="presentation"> <ul class="nav nav-tabs justify-content-start" role="tablist">
<a *ngIf="(page.enabled | async)" @for (page of pages; track page) {
<li class="nav-item" role="presentation">
@if ((page.enabled | async)) {
<a
[attr.aria-selected]="page.page === currentPage" [attr.aria-selected]="page.page === currentPage"
class="nav-link" class="nav-link"
[ngClass]="{'active' : page.page === currentPage}" [ngClass]="{'active' : page.page === currentPage}"
@@ -14,14 +17,19 @@
role="tab"> role="tab">
{{'item.edit.tabs.' + page.page + '.head' | translate}} {{'item.edit.tabs.' + page.page + '.head' | translate}}
</a> </a>
}
<span [ngbTooltip]="'item.edit.tabs.disabled.tooltip' | translate"> <span [ngbTooltip]="'item.edit.tabs.disabled.tooltip' | translate">
<button *ngIf="(page.enabled | async) !== true" @if ((page.enabled | async) !== true) {
<button
class="nav-link disabled"> class="nav-link disabled">
{{'item.edit.tabs.' + page.page + '.head' | translate}} {{'item.edit.tabs.' + page.page + '.head' | translate}}
</button> </button>
}
</span> </span>
</li> </li>
}
</ul> </ul>
}
<div class="tab-pane active"> <div class="tab-pane active">
<div class="mb-4"> <div class="mb-4">
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@@ -10,68 +10,88 @@
class="fas fa-upload"></i> class="fas fa-upload"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.upload-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.upload-button" | translate}}</span>
</button> </button>
<button class="btn btn-warning" *ngIf="isReinstatable$ | async" @if (isReinstatable$ | async) {
<button class="btn btn-warning"
[attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate" [attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate"
(click)="reinstate()"><i (click)="reinstate()"><i
class="fas fa-undo-alt"></i> class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button> </button>
}
<button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting" <button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate" [attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i (click)="submit()"><i
class="fas fa-save"></i> class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</button> </button>
<button class="btn btn-danger" *ngIf="(isReinstatable$ | async) !== true" @if ((isReinstatable$ | async) !== true) {
<button class="btn btn-danger"
[attr.aria-label]="'item.edit.bitstreams.discard-button' | translate" [attr.aria-label]="'item.edit.bitstreams.discard-button' | translate"
[dsBtnDisabled]="(hasChanges$ | async) !== true || submitting" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i (click)="discard()"><i
class="fas fa-times"></i> class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
</button> </button>
}
</div> </div>
<div *ngIf="item && bundles?.length > 0" class="mt-4 table-border scrollable-table" [ngClass]="{'disabled-overlay': (isProcessingMoveRequest | async)}"> @if (item && bundles?.length > 0) {
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles; first as isFirst" <div class="mt-4 table-border scrollable-table" [ngClass]="{'disabled-overlay': (isProcessingMoveRequest | async)}">
@for (bundle of bundles; track bundle; let isFirst = $first) {
<ds-item-edit-bitstream-bundle
[bundle]="bundle" [bundle]="bundle"
[item]="item" [item]="item"
[columnSizes]="columnSizes" [columnSizes]="columnSizes"
[isFirstTable]="isFirst" [isFirstTable]="isFirst"
aria-describedby="reorder-description"> aria-describedby="reorder-description">
</ds-item-edit-bitstream-bundle> </ds-item-edit-bitstream-bundle>
<div class="d-flex justify-content-center" *ngIf="showLoadMoreLink$ | async"> }
@if (showLoadMoreLink$ | async) {
<div class="d-flex justify-content-center">
<button class="btn btn-link my-3" (click)="loadBundles()"> {{'item.edit.bitstreams.load-more.link' | translate}}</button> <button class="btn btn-link my-3" (click)="loadBundles()"> {{'item.edit.bitstreams.load-more.link' | translate}}</button>
</div> </div>
}
</div> </div>
<div *ngIf="bundles?.length === 0" }
@if (bundles?.length === 0) {
<div
class="alert alert-info w-100 d-inline-block mt-4" role="alert"> class="alert alert-info w-100 d-inline-block mt-4" role="alert">
{{'item.edit.bitstreams.empty' | translate}} {{'item.edit.bitstreams.empty' | translate}}
</div> </div>
<ds-loading *ngIf="!bundles" message="{{'loading.bitstreams' | translate}}"></ds-loading> }
@if (!bundles) {
<ds-loading message="{{'loading.bitstreams' | translate}}"></ds-loading>
}
<div class="button-row bottom"> <div class="button-row bottom">
<div class="mt-4 float-end space-children-mr ms-gap"> <div class="mt-4 float-end space-children-mr ms-gap">
<button class="btn btn-warning" *ngIf="isReinstatable$ | async" @if (isReinstatable$ | async) {
<button class="btn btn-warning"
[attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate" [attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate"
(click)="reinstate()"><i (click)="reinstate()"><i
class="fas fa-undo-alt"></i> class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button> </button>
}
<button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting" <button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate" [attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i (click)="submit()"><i
class="fas fa-save"></i> class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</button> </button>
<button class="btn btn-danger" *ngIf="(isReinstatable$ | async) !== true" @if ((isReinstatable$ | async) !== true) {
<button class="btn btn-danger"
[attr.aria-label]="'item.edit.bitstreams.discard-button' | translate" [attr.aria-label]="'item.edit.bitstreams.discard-button' | translate"
[dsBtnDisabled]="(hasChanges$ | async) !== true || submitting" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i (click)="discard()"><i
class="fas fa-times"></i> class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span> <span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
<ds-loading *ngIf="isProcessingMoveRequest | async" class="loading-overlay"></ds-loading> @if (isProcessingMoveRequest | async) {
<ds-loading class="loading-overlay"></ds-loading>
}

View File

@@ -1,6 +1,7 @@
<ng-template #bundleView> <ng-template #bundleView>
<ds-pagination *ngIf="(bitstreamsRD$ | async)?.payload as bitstreamsList" @if ((bitstreamsRD$ | async)?.payload; as bitstreamsList) {
<ds-pagination
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true" [hidePagerWhenSinglePage]="true"
[hidePaginationDetail]="true" [hidePaginationDetail]="true"
@@ -9,8 +10,7 @@
[retainScrollPosition]="true" [retainScrollPosition]="true"
[ngbTooltip]="'item.edit.bitstreams.bundle.tooltip' | translate" placement="bottom" [ngbTooltip]="'item.edit.bitstreams.bundle.tooltip' | translate" placement="bottom"
[autoClose]="false" triggers="manual" #dragTooltip="ngbTooltip"> [autoClose]="false" triggers="manual" #dragTooltip="ngbTooltip">
<ng-container *ngIf="(updates$ | async) as updates"> @if ((updates$ | async); as updates) {
<table class="table" [class.mt-n1]="!isFirstTable" <table class="table" [class.mt-n1]="!isFirstTable"
[attr.aria-label]="'item.edit.bitstreams.bundle.table.aria-label' | translate: { bundle: bundleName } "> [attr.aria-label]="'item.edit.bitstreams.bundle.table.aria-label' | translate: { bundle: bundleName } ">
<thead [class.visually-hidden]="!isFirstTable"> <thead [class.visually-hidden]="!isFirstTable">
@@ -29,14 +29,12 @@
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody cdkDropList (cdkDropListDropped)="drop($event)"> <tbody cdkDropList (cdkDropListDropped)="drop($event)">
<tr class="bundle-row"> <tr class="bundle-row">
<th id="{{ bundleName }}" class="span" colspan="3" scope="colgroup"> <th id="{{ bundleName }}" class="span" colspan="3" scope="colgroup">
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }} {{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }}
</th> </th>
<td class="text-center"> <td class="text-center">
<div class="btn-group"> <div class="btn-group">
<button [routerLink]="[itemPageRoute, 'bitstreams', 'new']" <button [routerLink]="[itemPageRoute, 'bitstreams', 'new']"
[queryParams]="{bundle: bundle.id}" [queryParams]="{bundle: bundle.id}"
@@ -53,33 +51,32 @@
aria-expanded="false"> aria-expanded="false">
<i class="fas fa-cog" aria-hidden="true"></i> <i class="fas fa-cog" aria-hidden="true"></i>
</button> </button>
<ul id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" role="menu" <ul id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" role="menu"
ngbDropdownMenu> ngbDropdownMenu>
<li role="menuitem"> <li role="menuitem">
<span class="dropdown-header" id="pagination-control_results-per-page" <span class="dropdown-header" id="pagination-control_results-per-page"
role="heading">{{ 'pagination.results-per-page' | translate}}</span> role="heading">{{ 'pagination.results-per-page' | translate}}</span>
<ul aria-labelledby="pagination-control_results-per-page" class="list-unstyled" role="listbox"> <ul aria-labelledby="pagination-control_results-per-page" class="list-unstyled" role="listbox">
<li *ngFor="let size of paginationOptions.pageSizeOptions" role="option" @for (size of paginationOptions.pageSizeOptions; track size) {
<li role="option"
[attr.aria-selected]="size === (pageSize$ | async)"> [attr.aria-selected]="size === (pageSize$ | async)">
<button (click)="doPageSizeChange(size)" class="dropdown-item"> <button (click)="doPageSizeChange(size)" class="dropdown-item">
<i [ngClass]="{'invisible': size !== (pageSize$ | async) }" class="fas fa-check" <i [ngClass]="{'invisible': size !== (pageSize$ | async) }" class="fas fa-check"
aria-hidden="true"></i> {{size}} aria-hidden="true"></i> {{size}}
</button> </button>
</li> </li>
}
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</td> </td>
</tr> </tr>
@for (entry of (tableEntries$ | async); track entry) {
<ng-container *ngFor="let entry of (tableEntries$ | async)"> @if (updates[entry.id]; as update) {
<tr *ngIf="updates[entry.id] as update" [ngClass]="getRowClass(update, entry)" class="bitstream-row" cdkDrag <tr [ngClass]="getRowClass(update, entry)" class="bitstream-row" cdkDrag
(cdkDragStarted)="dragStart()" (cdkDragEnded)="dragEnd()"> (cdkDragStarted)="dragStart()" (cdkDragEnded)="dragEnd()">
<th class="bitstream-name row-element {{ columnSizes.columns[0].buildClasses() }}" <th class="bitstream-name row-element {{ columnSizes.columns[0].buildClasses() }}"
scope="row" id="{{ entry.nameStripped }}" headers="{{ bundleName }} name"> scope="row" id="{{ entry.nameStripped }}" headers="{{ bundleName }} name">
<div class="drag-handle text-muted float-left p-1 mr-2 d-inline" tabindex="0" cdkDragHandle <div class="drag-handle text-muted float-left p-1 mr-2 d-inline" tabindex="0" cdkDragHandle
@@ -129,12 +126,12 @@
</div> </div>
</td> </td>
</tr> </tr>
</ng-container> }
}
</tbody> </tbody>
</table> </table>
}
</ng-container>
</ds-pagination> </ds-pagination>
}
</ng-template> </ng-template>

View File

@@ -6,35 +6,34 @@
<p>{{descriptionMessage | translate}}</p> <p>{{descriptionMessage | translate}}</p>
<ds-modify-item-overview [item]="item"></ds-modify-item-overview> <ds-modify-item-overview [item]="item"></ds-modify-item-overview>
<ng-container *ngVar="(typeDTOs$ | async) as types"> <ng-container>
<div *ngIf="types && types.length > 0" class="mb-4">
@if ((typeDTOs$ | async) && (typeDTOs$ | async).length > 0) {
<div class="mb-4">
{{'virtual-metadata.delete-item.info' | translate}} {{'virtual-metadata.delete-item.info' | translate}}
@for (typeDto of (typeDTOs$ | async); track typeDto) {
<div *ngFor="let typeDto of types" class="mb-4"> <div class="mb-4">
<div *ngVar="(typeDto.isSelected$ | async) as selected" <div *ngVar="(typeDto.isSelected$ | async) as selected"
class="d-flex flex-row"> class="d-flex flex-row">
<div class="m-2" (click)="setSelected(typeDto.relationshipType, !selected)"> <div class="m-2" (click)="setSelected(typeDto.relationshipType, !selected)">
<label> <label>
<input type="checkbox" [checked]="selected" [disabled]="isDeleting$ | async"> <input type="checkbox" [checked]="selected" [disabled]="isDeleting$ | async">
</label> </label>
</div> </div>
<div class="flex-column flex-grow-1"> <div class="flex-column flex-grow-1">
<h5 (click)="setSelected(typeDto.relationshipType, !selected)"> <h5 (click)="setSelected(typeDto.relationshipType, !selected)">
{{getRelationshipMessageKey(typeDto.label$ | async) | translate}} {{getRelationshipMessageKey(typeDto.label$ | async) | translate}}
</h5> </h5>
<div *ngFor="let relationshipDto of (typeDto.relationshipDTOs$ | async)" @for (relationshipDto of (typeDto.relationshipDTOs$ | async); track relationshipDto.relationship.id) {
<div
class="d-flex flex-row"> class="d-flex flex-row">
<ng-container *ngVar="(relationshipDto.relatedItem$ | async) as relatedItem"> <ng-container *ngVar="(relationshipDto.relatedItem$ | async) as relatedItem">
@if (relatedItem) {
<ds-listable-object-component-loader <ds-listable-object-component-loader
*ngIf="relatedItem"
[object]="relatedItem" [object]="relatedItem"
[viewMode]="viewMode"> [viewMode]="viewMode">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
}
<div class="ms-auto"> <div class="ms-auto">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-outline-info btn-sm" <button class="btn btn-outline-info btn-sm"
@@ -43,7 +42,6 @@
</button> </button>
</div> </div>
</div> </div>
<ng-template #virtualMetadataModal> <ng-template #virtualMetadataModal>
<div class="thumb-font-1"> <div class="thumb-font-1">
<div class="modal-header"> <div class="modal-header">
@@ -53,12 +51,14 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@if (relatedItem) {
<ds-listable-object-component-loader <ds-listable-object-component-loader
*ngIf="relatedItem"
[object]="relatedItem" [object]="relatedItem"
[viewMode]="viewMode"> [viewMode]="viewMode">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
<div *ngFor="let metadata of (relationshipDto.virtualMetadata$ | async)"> }
@for (metadata of (relationshipDto.virtualMetadata$ | async); track metadata) {
<div>
<div> <div>
<div class="fw-bold"> <div class="fw-bold">
{{metadata.metadataField}} {{metadata.metadataField}}
@@ -68,19 +68,19 @@
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
}
</ng-container> </ng-container>

View File

@@ -41,12 +41,16 @@
<i class="fas fa-arrow-left"></i> {{'item.edit.move.cancel' | translate}} <i class="fas fa-arrow-left"></i> {{'item.edit.move.cancel' | translate}}
</button> </button>
<button class="btn btn-primary" [dsBtnDisabled]="!canMove" (click)="moveToCollection()"> <button class="btn btn-primary" [dsBtnDisabled]="!canMove" (click)="moveToCollection()">
<span *ngIf="!processing"> @if (!processing) {
<span>
<i class="fas fa-save"></i> {{'item.edit.move.save-button' | translate}} <i class="fas fa-save"></i> {{'item.edit.move.save-button' | translate}}
</span> </span>
<span *ngIf="processing"> }
@if (processing) {
<span>
<i class="fas fa-circle-notch fa-spin"></i> {{'item.edit.move.processing' | translate}} <i class="fas fa-circle-notch fa-spin"></i> {{'item.edit.move.processing' | translate}}
</span> </span>
}
</button> </button>
<button class="btn btn-danger" [dsBtnDisabled]="!canSubmit" (click)="discard()"> <button class="btn btn-danger" [dsBtnDisabled]="!canSubmit" (click)="discard()">
<i class="fas fa-times"></i> {{"item.edit.move.discard-button" | translate}} <i class="fas fa-times"></i> {{"item.edit.move.discard-button" | translate}}

View File

@@ -4,14 +4,18 @@
</span> </span>
</div> </div>
<div class="col-12 col-md-9 float-start action-button"> <div class="col-12 col-md-9 float-start action-button">
<span *ngIf="operation.authorized"> @if (operation.authorized) {
<span>
<button class="btn btn-outline-primary" [dsBtnDisabled]="operation.disabled" [routerLink]="operation.operationUrl" [attr.aria-label]="'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate"> <button class="btn btn-outline-primary" [dsBtnDisabled]="operation.disabled" [routerLink]="operation.operationUrl" [attr.aria-label]="'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate">
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}} {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</button> </button>
</span> </span>
<span *ngIf="!operation.authorized" [ngbTooltip]="'item.edit.tabs.status.buttons.unauthorized' | translate"> }
@if (!operation.authorized) {
<span [ngbTooltip]="'item.edit.tabs.status.buttons.unauthorized' | translate">
<button class="btn btn-outline-primary" [dsBtnDisabled]="true" [attr.aria-label]="'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate"> <button class="btn btn-outline-primary" [dsBtnDisabled]="true" [attr.aria-label]="'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate">
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}} {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</button> </button>
</span> </span>
}
</div> </div>

View File

@@ -3,13 +3,17 @@
<div class="col-12"> <div class="col-12">
<h2>{{headerMessage | translate: {id: item.handle} }}</h2> <h2>{{headerMessage | translate: {id: item.handle} }}</h2>
<p>{{descriptionMessage | translate}}</p> <p>{{descriptionMessage | translate}}</p>
<div *ngFor="let identifier of (identifiers$ | async)" class="w-100 p"> @for (identifier of (identifiers$ | async); track identifier) {
<div *ngIf="(identifier.identifierType === 'doi')"> <div class="w-100 p">
@if ((identifier.identifierType === 'doi')) {
<div>
<p class="float-start">{{doiToUpdateMessage | translate}}: {{identifier.value}} <p class="float-start">{{doiToUpdateMessage | translate}}: {{identifier.value}}
({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}}) ({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}})
</p> </p>
</div> </div>
}
</div> </div>
}
<ds-modify-item-overview [item]="item"></ds-modify-item-overview> <ds-modify-item-overview [item]="item"></ds-modify-item-overview>
<div class="space-children-mr"> <div class="space-children-mr">
<button (click)="performAction()" class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}} <button (click)="performAction()" class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}}

View File

@@ -6,7 +6,7 @@
</button> </button>
</h2> </h2>
<ng-container *ngVar="updates$ | async as updates"> <ng-container *ngVar="updates$ | async as updates">
<ng-container *ngIf="updates && (loading$ | async) !== true"> @if (updates && (loading$ | async) !== true) {
<ng-container *ngVar="updates | dsObjectValues as updateValues"> <ng-container *ngVar="updates | dsObjectValues as updateValues">
<ds-pagination <ds-pagination
[paginationOptions]="paginationConfig" [paginationOptions]="paginationConfig"
@@ -14,7 +14,8 @@
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true"> [hidePagerWhenSinglePage]="true">
<div class="my-2"> <div class="my-2">
<ds-edit-relationship *ngFor="let updateValue of updateValues; trackBy: trackUpdate" @for (updateValue of updateValues; track trackUpdate($index, updateValue)) {
<ds-edit-relationship
class="relationship-row d-block alert" class="relationship-row d-block alert"
[fieldUpdate]="updateValue || {}" [fieldUpdate]="updateValue || {}"
[url]="url" [url]="url"
@@ -25,10 +26,15 @@
'alert-danger': updateValue.changeType === 2 'alert-danger': updateValue.changeType === 2
}"> }">
</ds-edit-relationship> </ds-edit-relationship>
}
</div> </div>
</ds-pagination> </ds-pagination>
<div *ngIf="updateValues.length === 0">{{"item.edit.relationships.no-relationships" | translate}}</div> @if (updateValues.length === 0) {
<div>{{"item.edit.relationships.no-relationships" | translate}}</div>
}
</ng-container> </ng-container>
</ng-container> }
<ds-loading *ngIf="loading$ | async"></ds-loading> @if (loading$ | async) {
<ds-loading></ds-loading>
}
</ng-container> </ng-container>

View File

@@ -1,4 +1,5 @@
<div class="row" *ngIf="relatedItem$ | async"> @if (relatedItem$ | async) {
<div class="row">
<div class="col-10 relationship"> <div class="col-10 relationship">
<ds-listable-object-component-loader <ds-listable-object-component-loader
[object]="relatedItem$ | async" [object]="relatedItem$ | async"
@@ -22,6 +23,7 @@
</div> </div>
</div> </div>
</div> </div>
}
<ng-template #virtualMetadataModal> <ng-template #virtualMetadataModal>
<ds-virtual-metadata <ds-virtual-metadata
[relationshipId]="relationship.id" [relationshipId]="relationship.id"

View File

@@ -1,6 +1,7 @@
<p class="mt-2">{{'item.edit.tabs.status.description' | translate}}</p> <p class="mt-2">{{'item.edit.tabs.status.description' | translate}}</p>
<div class="row"> <div class="row">
<div *ngFor="let statusKey of statusDataKeys" class="w-100 pt-1"> @for (statusKey of statusDataKeys; track statusKey) {
<div class="w-100 pt-1">
<div class="col-12 col-md-3 float-start status-label font-weight-bold"> <div class="col-12 col-md-3 float-start status-label font-weight-bold">
{{'item.edit.tabs.status.labels.' + statusKey | translate}}: {{'item.edit.tabs.status.labels.' + statusKey | translate}}:
</div> </div>
@@ -8,16 +9,21 @@
{{statusData[statusKey]}} {{statusData[statusKey]}}
</div> </div>
</div> </div>
}
<div *ngFor="let identifier of (identifiers$ | async)" class="w-100 pt-1"> @for (identifier of (identifiers$ | async); track identifier) {
<div *ngIf="(identifier.identifierType==='doi')"> <div class="w-100 pt-1">
@if ((identifier.identifierType==='doi')) {
<div>
<div class="col-12 col-md-3 float-start status-label font-weight-bold"> <div class="col-12 col-md-3 float-start status-label font-weight-bold">
{{identifier.identifierType.toLocaleUpperCase()}} {{identifier.identifierType.toLocaleUpperCase()}}
</div> </div>
<div class="col-12 col-md-9 float-start status-label font-weight-bold">{{identifier.value}} <div class="col-12 col-md-9 float-start status-label font-weight-bold">{{identifier.value}}
({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}})</div> ({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}})</div>
</div> </div>
}
</div> </div>
}
<div class="col-12 col-md-3 float-start status-label font-weight-bold"> <div class="col-12 col-md-3 float-start status-label font-weight-bold">
{{'item.edit.tabs.status.labels.itemPage' | translate}}: {{'item.edit.tabs.status.labels.itemPage' | translate}}:
@@ -26,8 +32,10 @@
<a [routerLink]="itemPageRoute$ | async">{{itemPageRoute$ | async}}</a> <a [routerLink]="itemPageRoute$ | async">{{itemPageRoute$ | async}}</a>
</div> </div>
<div *ngFor="let operation of (operations$ | async)" class="w-100" [ngClass]="{'pt-3': operation}"> @for (operation of (operations$ | async); track operation) {
<div class="w-100" [ngClass]="{'pt-3': operation}">
<ds-item-operation [operation]="operation"></ds-item-operation> <ds-item-operation [operation]="operation"></ds-item-operation>
</div> </div>
}
</div> </div>

View File

@@ -4,7 +4,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ng-container *ngFor="let itemDTO of itemDTOs$ | async; trackBy: trackItemDTO"> @for (itemDTO of itemDTOs$ | async; track trackItemDTO($index, itemDTO)) {
<div *ngVar="(itemDTO.isSelectedVirtualMetadataItem$ | async) as selected" <div *ngVar="(itemDTO.isSelectedVirtualMetadataItem$ | async) as selected"
(click)="setSelectedVirtualMetadataItem(itemDTO.item, !selected)" (click)="setSelectedVirtualMetadataItem(itemDTO.item, !selected)"
class="item d-flex flex-row"> class="item d-flex flex-row">
@@ -16,7 +16,8 @@
<div class="flex-column"> <div class="flex-column">
<ds-listable-object-component-loader [object]="itemDTO.item"> <ds-listable-object-component-loader [object]="itemDTO.item">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
<div *ngFor="let metadata of virtualMetadata.get(itemDTO.item.uuid)"> @for (metadata of virtualMetadata.get(itemDTO.item.uuid); track metadata) {
<div>
<div class="fw-bold"> <div class="fw-bold">
{{metadata.metadataField}} {{metadata.metadataField}}
</div> </div>
@@ -24,9 +25,10 @@
{{metadata.metadataValue.value}} {{metadata.metadataValue.value}}
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>
</ng-container> }
<div class="d-flex flex-row-reverse m-2"> <div class="d-flex flex-row-reverse m-2">
<button class="btn btn-primary save" <button class="btn btn-primary save"
(click)="save.emit()"> (click)="save.emit()">

View File

@@ -1,44 +1,60 @@
<div class="container" *ngVar="(itemRD$ | async) as itemRD"> <div class="container" *ngVar="(itemRD$ | async) as itemRD">
<div class="item-page" *ngIf="itemRD?.hasSucceeded" @fadeInOut> @if (itemRD?.hasSucceeded) {
<div *ngIf="itemRD?.payload as item"> <div class="item-page" @fadeInOut>
@if (itemRD?.payload; as item) {
<div>
<ds-item-alerts [item]="item"></ds-item-alerts> <ds-item-alerts [item]="item"></ds-item-alerts>
<ds-item-versions-notice [item]="item"></ds-item-versions-notice> <ds-item-versions-notice [item]="item"></ds-item-versions-notice>
<ds-view-tracker [object]="item"></ds-view-tracker> <ds-view-tracker [object]="item"></ds-view-tracker>
<div *ngIf="!item.isWithdrawn || (isAdmin$|async)" class="full-item-info"> @if (!item.isWithdrawn || (isAdmin$|async)) {
<div class="full-item-info">
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field class="me-auto" [item]="item"></ds-item-page-title-field> <ds-item-page-title-field class="me-auto" [item]="item"></ds-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="simple-view-link my-3" *ngIf="!fromSubmissionObject"> @if (!fromSubmissionObject) {
<div class="simple-view-link my-3">
<a class="btn btn-outline-primary" [routerLink]="[(itemPageRoute$ | async)]"> <a class="btn btn-outline-primary" [routerLink]="[(itemPageRoute$ | async)]">
{{"item.page.link.simple" | translate}} {{"item.page.link.simple" | translate}}
</a> </a>
</div> </div>
}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">
<tbody> <tbody>
<ng-container *ngFor="let mdEntry of (metadata$ | async) | keyvalue"> @for (mdEntry of (metadata$ | async) | keyvalue; track mdEntry) {
<tr *ngFor="let mdValue of mdEntry.value"> @for (mdValue of mdEntry.value; track mdValue) {
<tr>
<td>{{mdEntry.key}}</td> <td>{{mdEntry.key}}</td>
<td>{{mdValue.value}}</td> <td>{{mdValue.value}}</td>
<td>{{mdValue.language}}</td> <td>{{mdValue.language}}</td>
</tr> </tr>
</ng-container> }
}
</tbody> </tbody>
</table> </table>
</div> </div>
<ds-item-page-full-file-section [item]="item"></ds-item-page-full-file-section> <ds-item-page-full-file-section [item]="item"></ds-item-page-full-file-section>
<ds-item-page-collections [item]="item"></ds-item-page-collections> <ds-item-page-collections [item]="item"></ds-item-page-collections>
<ds-item-versions class="mt-2" [item]="item"></ds-item-versions> <ds-item-versions class="mt-2" [item]="item"></ds-item-versions>
<div class="button-row bottom" *ngIf="fromSubmissionObject"> @if (fromSubmissionObject) {
<div class="button-row bottom">
<div class="text-end"> <div class="text-end">
<button class="btn btn-outline-secondary me-1" (click)="back()"><i <button class="btn btn-outline-secondary me-1" (click)="back()"><i
class="fas fa-arrow-left"></i> {{'item.page.return' | translate}}</button> class="fas fa-arrow-left"></i> {{'item.page.return' | translate}}</button>
</div> </div>
</div> </div>
}
</div> </div>
}
</div> </div>
}
</div> </div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.item' | translate}}"></ds-error> }
<ds-loading *ngIf="itemRD?.isLoading" message="{{'loading.item' | translate}}"></ds-loading> @if (itemRD?.hasFailed) {
<ds-error message="{{'error.item' | translate}}"></ds-error>
}
@if (itemRD?.isLoading) {
<ds-loading message="{{'loading.item' | translate}}"></ds-loading>
}
</div> </div>

View File

@@ -1,65 +1,180 @@
<div class="container mb-5"> <div class="container mb-5">
<h1>{{'person.orcid.registry.auth' | translate}}</h1> <h1>{{'person.orcid.registry.auth' | translate}}</h1>
<ng-container *ngIf="(isLinkedToOrcid() | async); then orcidLinked; else orcidNotLinked"></ng-container> @if ((isLinkedToOrcid() | async)) {
</div>
<ng-template #orcidLinked>
<div data-test="orcidLinked"> <div data-test="orcidLinked">
<div class="row"> <div class="row">
<div *ngIf="(hasOrcidAuthorizations() | async)" class="col-sm-6 mb-3" data-test="hasOrcidAuthorizations"> @if ((hasOrcidAuthorizations() | async)) {
<div class="col-sm-6 mb-3" data-test="hasOrcidAuthorizations">
<div class="card h-100"> <div class="card h-100">
<div class="card-header">{{ 'person.page.orcid.granted-authorizations'| translate }}</div> <div class="card-header">{{ 'person.page.orcid.granted-authorizations'| translate }}</div>
<div class="card-body"> <div class="card-body">
<div class="container p-0"> <div class="container p-0">
<ul> <ul>
<li *ngFor="let auth of (getOrcidAuthorizations() | async)" data-test="orcidAuthorization"> @for (auth of (getOrcidAuthorizations() | async); track auth) {
<li data-test="orcidAuthorization">
{{getAuthorizationDescription(auth) | translate}} {{getAuthorizationDescription(auth) | translate}}
</li> </li>
}
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
}
<div class="col-sm-6 mb-3"> <div class="col-sm-6 mb-3">
<div class="card h-100"> <div class="card h-100">
<div class="card-header">{{ 'person.page.orcid.missing-authorizations'| translate }}</div> <div class="card-header">{{ 'person.page.orcid.missing-authorizations'| translate }}</div>
<div class="card-body"> <div class="card-body">
<div class="container"> <div class="container">
<ds-alert *ngIf="(hasMissingOrcidAuthorizations() | async) !== true" [type]="'alert-success'" data-test="noMissingOrcidAuthorizations"> @if ((hasMissingOrcidAuthorizations() | async) !== true) {
<ds-alert [type]="'alert-success'" data-test="noMissingOrcidAuthorizations">
{{'person.page.orcid.no-missing-authorizations-message' | translate}} {{'person.page.orcid.no-missing-authorizations-message' | translate}}
</ds-alert> </ds-alert>
<ds-alert *ngIf="(hasMissingOrcidAuthorizations() | async)" [type]="'alert-warning'" data-test="missingOrcidAuthorizations"> }
@if ((hasMissingOrcidAuthorizations() | async)) {
<ds-alert [type]="'alert-warning'" data-test="missingOrcidAuthorizations">
{{'person.page.orcid.missing-authorizations-message' | translate}} {{'person.page.orcid.missing-authorizations-message' | translate}}
<ul> <ul>
<li *ngFor="let auth of (getMissingOrcidAuthorizations() | async)" data-test="missingOrcidAuthorization"> @for (auth of (getMissingOrcidAuthorizations() | async); track auth) {
<li data-test="missingOrcidAuthorization">
{{getAuthorizationDescription(auth) | translate }} {{getAuthorizationDescription(auth) | translate }}
</li> </li>
}
</ul> </ul>
</ds-alert> </ds-alert>
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<ds-alert *ngIf="(onlyAdminCanDisconnectProfileFromOrcid() | async) && (ownerCanDisconnectProfileFromOrcid() | async) !== true" @if ((onlyAdminCanDisconnectProfileFromOrcid() | async) && (ownerCanDisconnectProfileFromOrcid() | async) !== true) {
<ds-alert
[type]="'alert-warning'" data-test="unlinkOnlyAdmin"> [type]="'alert-warning'" data-test="unlinkOnlyAdmin">
{{ 'person.page.orcid.remove-orcid-message' | translate}} {{ 'person.page.orcid.remove-orcid-message' | translate}}
</ds-alert> </ds-alert>
<div class="row" *ngIf="(ownerCanDisconnectProfileFromOrcid() | async)" data-test="unlinkOwner"> }
@if ((ownerCanDisconnectProfileFromOrcid() | async)) {
<div class="row" data-test="unlinkOwner">
<div class="col"> <div class="col">
<button type="submit" class="btn btn-danger float-end" (click)="unlinkOrcid()" <button type="submit" class="btn btn-danger float-end" (click)="unlinkOrcid()"
[dsBtnDisabled]="(unlinkProcessing | async)"> [dsBtnDisabled]="(unlinkProcessing | async)">
<span *ngIf="(unlinkProcessing | async) !== true"><i @if ((unlinkProcessing | async) !== true) {
<span><i
class="fas fa-unlink"></i> {{ 'person.page.orcid.unlink' | translate }}</span> class="fas fa-unlink"></i> {{ 'person.page.orcid.unlink' | translate }}</span>
<span *ngIf="(unlinkProcessing | async)"><i }
@if ((unlinkProcessing | async)) {
<span><i
class='fas fa-circle-notch fa-spin'></i> {{'person.page.orcid.unlink.processing' | translate}}</span> class='fas fa-circle-notch fa-spin'></i> {{'person.page.orcid.unlink.processing' | translate}}</span>
}
</button> </button>
<button *ngIf="(hasMissingOrcidAuthorizations() | async)" type="submit" @if ((hasMissingOrcidAuthorizations() | async)) {
<button type="submit"
class="btn btn-primary float-end" (click)="linkOrcid()"> class="btn btn-primary float-end" (click)="linkOrcid()">
<span><i class="fas fa-check"></i> {{ 'person.page.orcid.grant-authorizations' | translate }}</span> <span><i class="fas fa-check"></i> {{ 'person.page.orcid.grant-authorizations' | translate }}</span>
</button> </button>
}
</div> </div>
</div> </div>
}
</div>
} @else {
<div data-test="orcidNotLinked">
<div class="row">
<div class="col-2"><img alt="orcid-logo" src="../../../../assets/images/orcid.logo.icon.svg"/></div>
<div class="col">
<ds-alert [type]="'alert-info'">{{ getOrcidNotLinkedMessage() | async }}</ds-alert>
</div>
</div>
<div class="row">
<div class="col">
<button class="btn btn-primary float-end" (click)="linkOrcid()">
<i class="fas fa-link"></i>
{{'person.page.orcid.link' | translate}}
</button>
</div>
</div>
</div>
}
</div>
<ng-template #orcidLinked>
<div data-test="orcidLinked">
<div class="row">
@if ((hasOrcidAuthorizations() | async)) {
<div class="col-sm-6 mb-3" data-test="hasOrcidAuthorizations">
<div class="card h-100">
<div class="card-header">{{ 'person.page.orcid.granted-authorizations'| translate }}</div>
<div class="card-body">
<div class="container p-0">
<ul>
@for (auth of (getOrcidAuthorizations() | async); track auth) {
<li data-test="orcidAuthorization">
{{getAuthorizationDescription(auth) | translate}}
</li>
}
</ul>
</div>
</div>
</div>
</div>
}
<div class="col-sm-6 mb-3">
<div class="card h-100">
<div class="card-header">{{ 'person.page.orcid.missing-authorizations'| translate }}</div>
<div class="card-body">
<div class="container">
@if ((hasMissingOrcidAuthorizations() | async) !== true) {
<ds-alert [type]="'alert-success'" data-test="noMissingOrcidAuthorizations">
{{'person.page.orcid.no-missing-authorizations-message' | translate}}
</ds-alert>
}
@if ((hasMissingOrcidAuthorizations() | async)) {
<ds-alert [type]="'alert-warning'" data-test="missingOrcidAuthorizations">
{{'person.page.orcid.missing-authorizations-message' | translate}}
<ul>
@for (auth of (getMissingOrcidAuthorizations() | async); track auth) {
<li data-test="missingOrcidAuthorization">
{{getAuthorizationDescription(auth) | translate }}
</li>
}
</ul>
</ds-alert>
}
</div>
</div>
</div>
</div>
</div>
@if ((onlyAdminCanDisconnectProfileFromOrcid() | async) && (ownerCanDisconnectProfileFromOrcid() | async) !== true) {
<ds-alert
[type]="'alert-warning'" data-test="unlinkOnlyAdmin">
{{ 'person.page.orcid.remove-orcid-message' | translate}}
</ds-alert>
}
@if ((ownerCanDisconnectProfileFromOrcid() | async)) {
<div class="row" data-test="unlinkOwner">
<div class="col">
<button type="submit" class="btn btn-danger float-end" (click)="unlinkOrcid()"
[dsBtnDisabled]="(unlinkProcessing | async)">
@if ((unlinkProcessing | async) !== true) {
<span><i
class="fas fa-unlink"></i> {{ 'person.page.orcid.unlink' | translate }}</span>
}
@if ((unlinkProcessing | async)) {
<span><i
class='fas fa-circle-notch fa-spin'></i> {{'person.page.orcid.unlink.processing' | translate}}</span>
}
</button>
@if ((hasMissingOrcidAuthorizations() | async)) {
<button type="submit"
class="btn btn-primary float-end" (click)="linkOrcid()">
<span><i class="fas fa-check"></i> {{ 'person.page.orcid.grant-authorizations' | translate }}</span>
</button>
}
</div>
</div>
}
</div> </div>
</ng-template> </ng-template>

View File

@@ -1,14 +1,23 @@
<ds-loading *ngIf="(processingConnection | async)" [message]="'person.page.orcid.link.processing' | translate"></ds-loading> @if ((processingConnection | async)) {
<div class="container" *ngIf="(processingConnection | async) !== true && (connectionStatus | async) !== true" data-test="error-box"> <ds-loading [message]="'person.page.orcid.link.processing' | translate"></ds-loading>
}
@if ((processingConnection | async) !== true && (connectionStatus | async) !== true) {
<div class="container" data-test="error-box">
<ds-alert [type]="AlertType.Error">{{'person.page.orcid.link.error.message' | translate}}</ds-alert> <ds-alert [type]="AlertType.Error">{{'person.page.orcid.link.error.message' | translate}}</ds-alert>
</div> </div>
<ng-container *ngIf="(processingConnection | async) !== true && (item | async) && (connectionStatus | async)" > }
@if ((processingConnection | async) !== true && (item | async) && (connectionStatus | async)) {
<ds-orcid-auth [item]="(item | async)" (unlink)="updateItem()" data-test="orcid-auth"></ds-orcid-auth> <ds-orcid-auth [item]="(item | async)" (unlink)="updateItem()" data-test="orcid-auth"></ds-orcid-auth>
<ds-orcid-sync-setting *ngIf="isLinkedToOrcid()" [item]="(item | async)" (settingsUpdated)="updateItem()" data-test="orcid-sync-setting"></ds-orcid-sync-setting> @if (isLinkedToOrcid()) {
<ds-orcid-queue *ngIf="isLinkedToOrcid()" [item]="(item | async)"></ds-orcid-queue> <ds-orcid-sync-setting [item]="(item | async)" (settingsUpdated)="updateItem()" data-test="orcid-sync-setting"></ds-orcid-sync-setting>
</ng-container> }
@if (isLinkedToOrcid()) {
<ds-orcid-queue [item]="(item | async)"></ds-orcid-queue>
}
}
<div *ngIf="(processingConnection | async) !== true && (item | async)" class="container"> @if ((processingConnection | async) !== true && (item | async)) {
<div class="container">
<div class="button-row bottom mb-3"> <div class="button-row bottom mb-3">
<div class="text-end"> <div class="text-end">
<a [routerLink]="getItemPage()" role="button" class="btn btn-outline-secondary" data-test="back-button"> <a [routerLink]="getItemPage()" role="button" class="btn btn-outline-secondary" data-test="back-button">
@@ -17,3 +26,4 @@
</div> </div>
</div> </div>
</div> </div>
}

View File

@@ -16,8 +16,10 @@
<label class="form-label" for="syncMode">{{ 'person.page.orcid.synchronization-mode.label'| translate }}</label> <label class="form-label" for="syncMode">{{ 'person.page.orcid.synchronization-mode.label'| translate }}</label>
<select class="form-select" [(ngModel)]="currentSyncMode" name="syncMode" id="syncMode" <select class="form-select" [(ngModel)]="currentSyncMode" name="syncMode" id="syncMode"
required> required>
<option *ngFor="let syncMode of syncModes" @for (syncMode of syncModes; track syncMode) {
<option
[value]="syncMode.value">{{ syncMode.label | translate }}</option> [value]="syncMode.value">{{ syncMode.label | translate }}</option>
}
</select> </select>
</div> </div>
</div> </div>
@@ -37,13 +39,15 @@
</ds-alert> </ds-alert>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div *ngFor="let option of syncPublicationOptions" class="row form-check"> @for (option of syncPublicationOptions; track option) {
<div class="row form-check">
<input type="radio" [(ngModel)]="currentSyncPublications" <input type="radio" [(ngModel)]="currentSyncPublications"
name="syncPublications" id="publicationOption_{{option.value}}" [value]="option.value" name="syncPublications" id="publicationOption_{{option.value}}" [value]="option.value"
required> required>
<label for="publicationOption_{{option.value}}" <label for="publicationOption_{{option.value}}"
class="ms-2 form-label">{{option.label | translate}}</label> class="ms-2 form-label">{{option.label | translate}}</label>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
@@ -60,12 +64,14 @@
</ds-alert> </ds-alert>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div *ngFor="let option of syncFundingOptions" class="row form-check"> @for (option of syncFundingOptions; track option) {
<div class="row form-check">
<input type="radio" [(ngModel)]="currentSyncFunding" <input type="radio" [(ngModel)]="currentSyncFunding"
name="syncFundings" id="fundingOption_{{option.value}}" [value]="option.value" name="syncFundings" id="fundingOption_{{option.value}}" [value]="option.value"
required> required>
<label for="fundingOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label> <label for="fundingOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
@@ -82,12 +88,14 @@
</ds-alert> </ds-alert>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div *ngFor="let option of syncProfileOptions" class="row form-check"> @for (option of syncProfileOptions; track option) {
<div class="row form-check">
<input type="checkbox" [(ngModel)]="option.checked" <input type="checkbox" [(ngModel)]="option.checked"
name="syncProfile_{{option.value}}" id="profileOption_{{option.value}}" name="syncProfile_{{option.value}}" id="profileOption_{{option.value}}"
[value]="option.value"> [value]="option.value">
<label for="profileOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label> <label for="profileOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,21 +1,35 @@
<ng-container *ngVar="(bitstreams$ | async) as bitstreams"> <ng-container *ngVar="(bitstreams$ | async) as bitstreams">
<ds-metadata-field-wrapper *ngIf="bitstreams?.length > 0" [label]="label | translate"> @if (bitstreams?.length > 0) {
<ds-metadata-field-wrapper [label]="label | translate">
<div class="file-section"> <div class="file-section">
<ds-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file" [item]="item"> @for (file of bitstreams; track file; let last = $last) {
<ds-file-download-link [bitstream]="file" [item]="item">
<span> <span>
<span *ngIf="primaryBitsreamId === file.id" class="badge bg-primary">{{ 'item.page.bitstreams.primary' | translate }}</span> @if (primaryBitsreamId === file.id) {
<span class="badge bg-primary">{{ 'item.page.bitstreams.primary' | translate }}</span>
}
{{ dsoNameService.getName(file) }} {{ dsoNameService.getName(file) }}
</span> </span>
<span> ({{(file?.sizeBytes) | dsFileSize }})</span> <span> ({{(file?.sizeBytes) | dsFileSize }})</span>
<span *ngIf="!last" innerHTML="{{separator}}"></span> @if (!last) {
<span innerHTML="{{separator}}"></span>
}
</ds-file-download-link> </ds-file-download-link>
<ds-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-loading> }
<div *ngIf="!isLastPage" class="mt-1" id="view-more"> @if (isLoading) {
<ds-loading message="{{'loading.default' | translate}}" [showMessage]="false"></ds-loading>
}
@if (!isLastPage) {
<div class="mt-1" id="view-more">
<button class="bitstream-view-more btn btn-outline-secondary btn-sm" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</button> <button class="bitstream-view-more btn btn-outline-secondary btn-sm" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</button>
</div> </div>
<div *ngIf="isLastPage && currentPage !== 1" class="mt-1" id="collapse"> }
@if (isLastPage && currentPage !== 1) {
<div class="mt-1" id="collapse">
<button class="bitstream-collapse btn btn-outline-secondary btn-sm" (click)="currentPage = undefined; getNextPage();">{{'item.page.bitstreams.collapse' | translate}}</button> <button class="bitstream-collapse btn btn-outline-secondary btn-sm" (click)="currentPage = undefined; getNextPage();">{{'item.page.bitstreams.collapse' | translate}}</button>
</div> </div>
}
</div> </div>
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>
}
</ng-container> </ng-container>

View File

@@ -1,20 +1,30 @@
<ds-metadata-field-wrapper [label]="label"> <ds-metadata-field-wrapper [label]="label">
<ng-container *ngFor="let objectPage of objects; let i = index"> @for (objectPage of objects; track objectPage; let i = $index) {
<ng-container *ngVar="(objectPage | async) as representations"> <ng-container *ngVar="(objectPage | async) as representations">
<ds-metadata-representation-loader *ngFor="let rep of representations" @for (rep of representations; track rep) {
<ds-metadata-representation-loader
[mdRepresentation]="rep"> [mdRepresentation]="rep">
</ds-metadata-representation-loader> </ds-metadata-representation-loader>
<ds-loading *ngIf="(i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)" message="{{'loading.default' | translate}}"></ds-loading> }
<div class="d-inline-block w-100 mt-2" *ngIf="(i + 1) === objects.length && representations?.length > 0"> @if ((i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)) {
<div *ngIf="(objects.length * incrementBy) < total" class="float-start"> <ds-loading message="{{'loading.default' | translate}}"></ds-loading>
}
@if ((i + 1) === objects.length && representations?.length > 0) {
<div class="d-inline-block w-100 mt-2">
@if ((objects.length * incrementBy) < total) {
<div class="float-start">
<button class="btn btn-link btn-link-inline" (click)="increase()">{{'item.page.related-items.view-more' | <button class="btn btn-link btn-link-inline" (click)="increase()">{{'item.page.related-items.view-more' |
translate:{ amount: (total - (objects.length * incrementBy) < incrementBy) ? total - (objects.length * incrementBy) : incrementBy } }}</button> translate:{ amount: (total - (objects.length * incrementBy) < incrementBy) ? total - (objects.length * incrementBy) : incrementBy } }}</button>
</div> </div>
<div *ngIf="objects.length > 1" class="float-end"> }
@if (objects.length > 1) {
<div class="float-end">
<button class="btn btn-link btn-link-inline" (click)="decrease()">{{'item.page.related-items.view-less' | <button class="btn btn-link btn-link-inline" (click)="decrease()">{{'item.page.related-items.view-less' |
translate:{ amount: representations?.length } }}</button> translate:{ amount: representations?.length } }}</button>
</div> </div>
}
</div> </div>
}
</ng-container> </ng-container>
</ng-container> }
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>

View File

@@ -1,6 +1,7 @@
<ng-container *ngIf="(sources$ | async) as sources"> @if ((sources$ | async); as sources) {
<ng-container *ngFor="let source of sources"> @for (source of sources; track source) {
<div class="alert alert-info d-flex flex-row" *ngIf="source.totalEvents > 0"> @if (source.totalEvents > 0) {
<div class="alert alert-info d-flex flex-row">
<div class="source-logo-container"> <div class="source-logo-container">
<img class="source-logo" <img class="source-logo"
src="assets/images/qa-{{(source.id | dsSplit: ':')[0]}}-logo.png" src="assets/images/qa-{{(source.id | dsSplit: ':')[0]}}-logo.png"
@@ -18,5 +19,6 @@
</button> </button>
</div> </div>
</div> </div>
</ng-container> }
</ng-container> }
}

View File

@@ -1,20 +1,30 @@
<ds-metadata-field-wrapper [label]="label" [ngClass]="placeholderFontClass"> <ds-metadata-field-wrapper [label]="label" [ngClass]="placeholderFontClass">
<ng-container *ngFor="let objectPage of objects; let i = index"> @for (objectPage of objects; track objectPage; let i = $index) {
<ng-container *ngVar="(objectPage | async) as itemsRD"> <ng-container *ngVar="(objectPage | async) as itemsRD">
<ds-listable-object-component-loader *ngFor="let item of itemsRD?.payload?.page" @for (item of itemsRD?.payload?.page; track item) {
<ds-listable-object-component-loader
[object]="item" [viewMode]="viewMode"> [object]="item" [viewMode]="viewMode">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
<ds-loading *ngIf="(i + 1) === objects.length && (itemsRD || i > 0) && !(itemsRD?.hasSucceeded && itemsRD?.payload && itemsRD?.payload?.page?.length > 0)" message="{{'loading.default' | translate}}"></ds-loading> }
<div class="d-inline-block w-100 mt-2" *ngIf="(i + 1) === objects.length && itemsRD?.payload?.page?.length > 0"> @if ((i + 1) === objects.length && (itemsRD || i > 0) && !(itemsRD?.hasSucceeded && itemsRD?.payload && itemsRD?.payload?.page?.length > 0)) {
<div *ngIf="itemsRD?.payload?.totalPages > objects.length" class="float-start" id="view-more"> <ds-loading message="{{'loading.default' | translate}}"></ds-loading>
}
@if ((i + 1) === objects.length && itemsRD?.payload?.page?.length > 0) {
<div class="d-inline-block w-100 mt-2">
@if (itemsRD?.payload?.totalPages > objects.length) {
<div class="float-start" id="view-more">
<button class="btn btn-link btn-link-inline text-capitalize" (click)="increase()">{{'item.page.related-items.view-more' | <button class="btn btn-link btn-link-inline text-capitalize" (click)="increase()">{{'item.page.related-items.view-more' |
translate:{ amount: (itemsRD?.payload?.totalElements - (incrementBy * objects.length) < incrementBy) ? itemsRD?.payload?.totalElements - (incrementBy * objects.length) : incrementBy } }} {{label}}</button> translate:{ amount: (itemsRD?.payload?.totalElements - (incrementBy * objects.length) < incrementBy) ? itemsRD?.payload?.totalElements - (incrementBy * objects.length) : incrementBy } }} {{label}}</button>
</div> </div>
<div *ngIf="objects.length > 1" class="float-end" id="view-less"> }
@if (objects.length > 1) {
<div class="float-end" id="view-less">
<button class="btn btn-link btn-link-inline text-capitalize" (click)="decrease()">{{'item.page.related-items.view-less' | <button class="btn btn-link btn-link-inline text-capitalize" (click)="decrease()">{{'item.page.related-items.view-less' |
translate:{ amount: itemsRD?.payload?.page?.length } }} {{label}}</button> translate:{ amount: itemsRD?.payload?.page?.length } }} {{label}}</button>
</div> </div>
}
</div> </div>
}
</ng-container> </ng-container>
</ng-container> }
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>

View File

@@ -1,44 +1,50 @@
<div class="left-column"> <div class="left-column">
<span *ngIf="(workspaceId$ | async) || (workflowId$ | async); then versionNumberWithoutLink else versionNumberWithLink"></span> @if ((workspaceId$ | async) || (workflowId$ | async)) {
<ng-template #versionNumberWithLink>
<a [routerLink]="getVersionRoute(version.id)">{{version.version}}</a>
</ng-template>
<ng-template #versionNumberWithoutLink>
{{version.version}} {{version.version}}
</ng-template> } @else {
<span *ngIf="version?.id === itemVersion?.id">*</span> <a [routerLink]="getVersionRoute(version.id)">{{version.version}}</a>
}
@if (version?.id === itemVersion?.id) {
<span>*</span>
}
<span *ngIf="workspaceId$ | async" class="text-light badge bg-primary ms-3"> @if (workspaceId$ | async) {
<span class="text-light badge bg-primary ms-3">
{{ "item.version.history.table.workspaceItem" | translate }} {{ "item.version.history.table.workspaceItem" | translate }}
</span> </span>
}
<span *ngIf="workflowId$ | async" class="text-light badge bg-info ms-3"> @if (workflowId$ | async) {
<span class="text-light badge bg-info ms-3">
{{ "item.version.history.table.workflowItem" | translate }} {{ "item.version.history.table.workflowItem" | translate }}
</span> </span>
}
</div> </div>
<div class="right-column"> <div class="right-column">
<div class="btn-group edit-field space-children-mr" *ngIf="displayActions"> @if (displayActions) {
<div class="btn-group edit-field space-children-mr">
<!--EDIT WORKSPACE ITEM--> <!--EDIT WORKSPACE ITEM-->
@if (workspaceId$ | async) {
<button class="btn btn-outline-primary btn-sm version-row-element-edit" <button class="btn btn-outline-primary btn-sm version-row-element-edit"
*ngIf="workspaceId$ | async"
(click)="editWorkspaceItem(workspaceId$)" (click)="editWorkspaceItem(workspaceId$)"
title="{{'item.version.history.table.action.editWorkspaceItem' | translate }}"> title="{{'item.version.history.table.action.editWorkspaceItem' | translate }}">
<i class="fas fa-pencil-alt fa-fw"></i> <i class="fas fa-pencil-alt fa-fw"></i>
</button> </button>
}
<!--CREATE--> <!--CREATE-->
<ng-container *ngIf="canCreateVersion$ | async"> @if (canCreateVersion$ | async) {
<button class="btn btn-outline-primary btn-sm version-row-element-create" <button class="btn btn-outline-primary btn-sm version-row-element-create"
[dsBtnDisabled]="isAnyBeingEdited() || hasDraftVersion" [dsBtnDisabled]="isAnyBeingEdited() || hasDraftVersion"
(click)="createNewVersion(version)" (click)="createNewVersion(version)"
title="{{createVersionTitle | translate }}"> title="{{createVersionTitle | translate }}">
<i class="fas fa-code-branch fa-fw"></i> <i class="fas fa-code-branch fa-fw"></i>
</button> </button>
</ng-container> }
<!--DELETE--> <!--DELETE-->
<ng-container *ngIf="canDeleteVersion$ | async"> @if (canDeleteVersion$ | async) {
<button class="btn btn-sm version-row-element-delete" <button class="btn btn-sm version-row-element-delete"
[ngClass]="isAnyBeingEdited() ? 'btn-outline-primary' : 'btn-outline-danger'" [ngClass]="isAnyBeingEdited() ? 'btn-outline-primary' : 'btn-outline-danger'"
[dsBtnDisabled]="isAnyBeingEdited()" [dsBtnDisabled]="isAnyBeingEdited()"
@@ -46,8 +52,9 @@
title="{{'item.version.history.table.action.deleteVersion' | translate}}"> title="{{'item.version.history.table.action.deleteVersion' | translate}}">
<i class="fas fa-trash fa-fw"></i> <i class="fas fa-trash fa-fw"></i>
</button> </button>
</ng-container> }
</div> </div>
}
</div> </div>

View File

@@ -1,4 +1,5 @@
<div *ngIf="(this.submitted$ | async) !== true; else waiting"> @if ((this.submitted$ | async) !== true) {
<div>
<div class="modal-header">{{'item.version.create.modal.header' | translate}} <div class="modal-header">{{'item.version.create.modal.header' | translate}}
<button type="button" class="btn-close" (click)="onModalClose()" aria-label="Close"> <button type="button" class="btn-close" (click)="onModalClose()" aria-label="Close">
</button> </button>
@@ -6,9 +7,11 @@
<div class="modal-body"> <div class="modal-body">
<p class="pb-2"> <p class="pb-2">
{{ "item.version.create.modal.text" | translate }} {{ "item.version.create.modal.text" | translate }}
<span *ngIf="!firstVersion"> @if (!firstVersion) {
<span>
{{ "item.version.create.modal.text.startingFrom" | translate : {version: versionNumber} }} {{ "item.version.create.modal.text.startingFrom" | translate : {version: versionNumber} }}
</span> </span>
}
</p> </p>
<div class="mb-3"> <div class="mb-3">
<label for="summary" class="form-label">{{'item.version.create.modal.form.summary.label' | translate }}:</label> <label for="summary" class="form-label">{{'item.version.create.modal.form.summary.label' | translate }}:</label>
@@ -33,8 +36,7 @@
</button> </button>
</div> </div>
</div> </div>
} @else {
<ng-template #waiting>
<div class="modal-header">{{'item.version.create.modal.submitted.header' | translate}}</div> <div class="modal-header">{{'item.version.create.modal.submitted.header' | translate}}</div>
<div class="modal-body"> <div class="modal-body">
<p>{{'item.version.create.modal.submitted.text' | translate}}</p> <p>{{'item.version.create.modal.submitted.text' | translate}}</p>
@@ -42,4 +44,5 @@
<ds-loading [showMessage]="false"></ds-loading> <ds-loading [showMessage]="false"></ds-loading>
</div> </div>
</div> </div>
</ng-template> }

View File

@@ -1,11 +1,17 @@
<div *ngIf="(versionsDTO$ | async) as versionsDTO; else noItemVersion"> @if ((versionsDTO$ | async); as versionsDTO) {
<div *ngIf="(versionRD$ | async)?.payload as itemVersion"> <div>
<div class="mb-2" *ngIf="versionsDTO.versionDTOs.length > 0 || displayWhenEmpty"> @if ((versionRD$ | async)?.payload; as itemVersion) {
<h2 *ngIf="displayTitle" class="h4">{{"item.version.history.head" | translate}}</h2> <div>
@if (versionsDTO.versionDTOs.length > 0 || displayWhenEmpty) {
<div class="mb-2">
@if (displayTitle) {
<h2 class="h4">{{"item.version.history.head" | translate}}</h2>
}
<ds-alert [type]="AlertTypeEnum.Info"> <ds-alert [type]="AlertTypeEnum.Info">
{{ "item.version.history.selected.alert" | translate : {version: itemVersion.version} }} {{ "item.version.history.selected.alert" | translate : {version: itemVersion.version} }}
</ds-alert> </ds-alert>
<ds-pagination *ngIf="versionsDTO.versionDTOs.length > 0" @if (versionsDTO.versionDTOs.length > 0) {
<ds-pagination
(paginationChange)="onPageChange()" (paginationChange)="onPageChange()"
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true" [hidePagerWhenSinglePage]="true"
@@ -16,13 +22,16 @@
<thead> <thead>
<tr> <tr>
<th scope="col">{{"item.version.history.table.version" | translate}}</th> <th scope="col">{{"item.version.history.table.version" | translate}}</th>
<th scope="col" *ngIf="(showSubmitter$ | async)">{{"item.version.history.table.editor" | translate}}</th> @if ((showSubmitter$ | async)) {
<th scope="col">{{"item.version.history.table.editor" | translate}}</th>
}
<th scope="col">{{"item.version.history.table.date" | translate}}</th> <th scope="col">{{"item.version.history.table.date" | translate}}</th>
<th scope="col">{{"item.version.history.table.summary" | translate}}</th> <th scope="col">{{"item.version.history.table.summary" | translate}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let versionDTO of versionsDTO.versionDTOs" [id]="'version-row-' + versionDTO.version.id"> @for (versionDTO of versionsDTO.versionDTOs; track versionDTO) {
<tr [id]="'version-row-' + versionDTO.version.id">
<td class="version-row-element-version"> <td class="version-row-element-version">
<ds-item-versions-row-element-version [hasDraftVersion]="hasDraftVersion$ | async" <ds-item-versions-row-element-version [hasDraftVersion]="hasDraftVersion$ | async"
[version]="versionDTO.version" [version]="versionDTO.version"
@@ -32,25 +41,32 @@
(versionsHistoryChange)="getAllVersions($event)" (versionsHistoryChange)="getAllVersions($event)"
></ds-item-versions-row-element-version> ></ds-item-versions-row-element-version>
</td> </td>
<td class="version-row-element-editor" *ngIf="(showSubmitter$ | async)"> @if ((showSubmitter$ | async)) {
<td class="version-row-element-editor">
{{versionDTO.version.submitterName}} {{versionDTO.version.submitterName}}
</td> </td>
}
<td class="version-row-element-date"> <td class="version-row-element-date">
{{versionDTO.version.created | date : 'yyyy-MM-dd HH:mm:ss'}} {{versionDTO.version.created | date : 'yyyy-MM-dd HH:mm:ss'}}
</td> </td>
<td class="version-row-element-summary"> <td class="version-row-element-summary">
<div class="float-start"> <div class="float-start">
<ng-container *ngIf="isThisBeingEdited(versionDTO.version); then editSummary else showSummary"></ng-container> @if (isThisBeingEdited(versionDTO.version)) {
<ng-template #showSummary>{{versionDTO.version.summary}}</ng-template> <input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate"
[(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()"
class="form-control" type="text"/>
} @else {
<span>{{versionDTO.version.summary}}</span>
}
<ng-template #editSummary> <ng-template #editSummary>
<input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate" <input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate"
[(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()" [(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()"
class="form-control" type="text"/> class="form-control" type="text"/>
</ng-template> </ng-template>
</div> </div>
@if (displayActions && versionDTO.canEditVersion | async) {
<div class="float-end btn-group edit-field space-children-mr" *ngIf="displayActions && versionDTO.canEditVersion | async"> <div class="float-end btn-group edit-field space-children-mr">
<ng-container *ngIf="isThisBeingEdited(versionDTO.version); else notThisBeingEdited"> @if (isThisBeingEdited(versionDTO.version)) {
<!--DISCARD EDIT--> <!--DISCARD EDIT-->
<button class="btn btn-sm btn-outline-warning" <button class="btn btn-sm btn-outline-warning"
(click)="disableVersionEditing()" (click)="disableVersionEditing()"
@@ -63,8 +79,7 @@
title="{{'item.version.history.table.action.saveSummary' | translate}}"> title="{{'item.version.history.table.action.saveSummary' | translate}}">
<i class="fas fa-check fa-fw"></i> <i class="fas fa-check fa-fw"></i>
</button> </button>
</ng-container> } @else {
<ng-template #notThisBeingEdited>
<!--EDIT--> <!--EDIT-->
<button class="btn btn-outline-primary btn-sm version-row-element-edit" <button class="btn btn-outline-primary btn-sm version-row-element-edit"
[dsBtnDisabled]="isAnyBeingEdited()" [dsBtnDisabled]="isAnyBeingEdited()"
@@ -72,21 +87,28 @@
title="{{'item.version.history.table.action.editSummary' | translate}}"> title="{{'item.version.history.table.action.editSummary' | translate}}">
<i class="fas fa-edit fa-fw"></i> <i class="fas fa-edit fa-fw"></i>
</button> </button>
</ng-template> }
</div> </div>
}
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
<div>*&nbsp;{{"item.version.history.selected" | translate}}</div> <div>*&nbsp;{{"item.version.history.selected" | translate}}</div>
</ds-pagination> </ds-pagination>
}
</div> </div>
}
</div> </div>
}
</div> </div>
} @else {
<ng-template #noItemVersion> @if (displayWhenEmpty) {
<ds-alert *ngIf="displayWhenEmpty" <ds-alert
[content]="'item.version.history.empty'" [content]="'item.version.history.empty'"
[type]="AlertTypeEnum.Info"> [type]="AlertTypeEnum.Info">
</ds-alert> </ds-alert>
</ng-template> }
}

View File

@@ -1,4 +1,5 @@
<div class="add" *ngIf="(moreThanOne$ | async) !== true"> @if ((moreThanOne$ | async) !== true) {
<div class="add">
<button class="btn btn-lg btn-outline-primary mt-1 ms-2" <button class="btn btn-lg btn-outline-primary mt-1 ms-2"
[attr.aria-label]="'mydspace.new-submission-external' | translate" [dsBtnDisabled]="(initialized$ | async) !== true" [attr.aria-label]="'mydspace.new-submission-external' | translate" [dsBtnDisabled]="(initialized$ | async) !== true"
(click)="openPage(singleEntity)" role="button" (click)="openPage(singleEntity)" role="button"
@@ -6,9 +7,11 @@
<i class="fa fa-file-import" aria-hidden="true"></i> <i class="fa fa-file-import" aria-hidden="true"></i>
</button> </button>
</div> </div>
}
@if ((moreThanOne$ | async)) {
<div class="add w-100" display="dynamic" placement="bottom-right" <div class="add w-100" display="dynamic" placement="bottom-right"
ngbDropdown ngbDropdown
*ngIf="(moreThanOne$ | async)"> >
<button class="btn btn-lg btn-outline-primary mt-1 ms-2" id="dropdownImport" ngbDropdownToggle <button class="btn btn-lg btn-outline-primary mt-1 ms-2" id="dropdownImport" ngbDropdownToggle
type="button" [dsBtnDisabled]="(initialized$ | async) !== true" type="button" [dsBtnDisabled]="(initialized$ | async) !== true"
[attr.aria-label]="'mydspace.new-submission-external' | translate" [attr.aria-label]="'mydspace.new-submission-external' | translate"
@@ -24,3 +27,4 @@
<ds-entity-dropdown [isSubmission]="false" (selectionChange)="openPage($event)"></ds-entity-dropdown> <ds-entity-dropdown [isSubmission]="false" (selectionChange)="openPage($event)"></ds-entity-dropdown>
</div> </div>
</div> </div>
}

View File

@@ -1,12 +1,15 @@
<div class="add" *ngIf="(moreThanOne$ | async) !== true"> @if ((moreThanOne$ | async) !== true) {
<div class="add">
<button class="btn btn-lg btn-primary mt-1 ms-2" [attr.aria-label]="'mydspace.new-submission' | translate" <button class="btn btn-lg btn-primary mt-1 ms-2" [attr.aria-label]="'mydspace.new-submission' | translate"
[dsBtnDisabled]="(initialized$ | async) !== true" (click)="openDialog(singleEntity)" role="button"> [dsBtnDisabled]="(initialized$ | async) !== true" (click)="openDialog(singleEntity)" role="button">
<i class="fa fa-plus-circle" aria-hidden="true"></i> <i class="fa fa-plus-circle" aria-hidden="true"></i>
</button> </button>
</div> </div>
}
@if ((moreThanOne$ | async)) {
<div class="add w-100" display="dynamic" placement="bottom-right" <div class="add w-100" display="dynamic" placement="bottom-right"
ngbDropdown ngbDropdown
*ngIf="(moreThanOne$ | async)"> >
<button class="btn btn-lg btn-primary mt-1 ms-2" id="dropdownSubmission" ngbDropdownToggle <button class="btn btn-lg btn-primary mt-1 ms-2" id="dropdownSubmission" ngbDropdownToggle
type="button" [dsBtnDisabled]="(initialized$ | async) !== true" type="button" [dsBtnDisabled]="(initialized$ | async) !== true"
[attr.aria-label]="'mydspace.new-submission' | translate" [attr.aria-label]="'mydspace.new-submission' | translate"
@@ -22,3 +25,4 @@
<ds-entity-dropdown [isSubmission]="true" (selectionChange)="openDialog($event)"></ds-entity-dropdown> <ds-entity-dropdown [isSubmission]="true" (selectionChange)="openDialog($event)"></ds-entity-dropdown>
</div> </div>
</div> </div>
}

View File

@@ -1,8 +1,8 @@
<ng-container *ngIf="(sources$ | async)?.length > 0"> @if ((sources$ | async)?.length > 0) {
<ng-container *ngFor="let source of sources$ | async"> @for (source of sources$ | async; track source) {
@if (source.totalEvents > 0) {
<div <div
class="alert alert-info d-flex flex-row" class="alert alert-info d-flex flex-row"
*ngIf="source.totalEvents > 0"
> >
<div class="source-logo-container"> <div class="source-logo-container">
<img <img
@@ -25,5 +25,6 @@
</button> </button>
</div> </div>
</div> </div>
</ng-container> }
</ng-container> }
}

View File

@@ -6,14 +6,14 @@
<div class="navbar-inner-container w-100" [class.container]="(isMobile$ | async) !== true"> <div class="navbar-inner-container w-100" [class.container]="(isMobile$ | async) !== true">
<div class="w-100"> <div class="w-100">
<div id="collapsingNav"> <div id="collapsingNav">
<ng-container *ngIf="(isMobile$ | async) && (isAuthenticated$ | async)"> @if ((isMobile$ | async) && (isAuthenticated$ | async)) {
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu> <ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
</ng-container> }
<div class="navbar-nav align-items-md-center me-auto shadow-none gapx-3"> <div class="navbar-nav align-items-md-center me-auto shadow-none gapx-3">
<ng-container *ngFor="let section of (sections | async)"> @for (section of (sections | async); track section) {
<ng-container <ng-container
*ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container> *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
</ng-container> }
</div> </div>
</div> </div>
</div> </div>

View File

@@ -6,13 +6,17 @@
{{'notifications.events.title'| translate}} {{'notifications.events.title'| translate}}
</div> </div>
</h1> </h1>
<ds-alert *ngIf="!targetId" [type]="'alert-info'"> @if (!targetId) {
<ds-alert [type]="'alert-info'">
<span [innerHTML]="'quality-assurance.events.description' | translate : {topic: selectedTopicName, source: sourceId}"></span> <span [innerHTML]="'quality-assurance.events.description' | translate : {topic: selectedTopicName, source: sourceId}"></span>
</ds-alert> </ds-alert>
<ds-alert *ngIf="targetId" [type]="'alert-info'"> }
@if (targetId) {
<ds-alert [type]="'alert-info'">
<span [innerHTML]="'quality-assurance.events.description-with-topic-and-target' | translate : {topic: selectedTopicName, source: sourceId}"></span> <span [innerHTML]="'quality-assurance.events.description-with-topic-and-target' | translate : {topic: selectedTopicName, source: sourceId}"></span>
<a [routerLink]="itemPageUrl" target="_blank">{{(getTargetItemTitle() | async)}}</a> <a [routerLink]="itemPageUrl" target="_blank">{{(getTargetItemTitle() | async)}}</a>
</ds-alert> </ds-alert>
}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -21,102 +25,135 @@
{{'quality-assurance.events.topic' | translate}} {{this.showTopic}} {{'quality-assurance.events.topic' | translate}} {{this.showTopic}}
</h2> </h2>
<ds-loading class="container" *ngIf="(isEventPageLoading | async)" message="{{'quality-assurance.loading' | translate}}"></ds-loading> @if ((isEventPageLoading | async)) {
<ds-loading class="container" message="{{'quality-assurance.loading' | translate}}"></ds-loading>
}
<ds-pagination *ngIf="(isEventPageLoading | async) !== true" @if ((isEventPageLoading | async) !== true) {
<ds-pagination
[paginationOptions]="paginationConfig" [paginationOptions]="paginationConfig"
[collectionSize]="(totalElements$ | async)" [collectionSize]="(totalElements$ | async)"
[sortOptions]="paginationSortConfig" [sortOptions]="paginationSortConfig"
(paginationChange)="getQualityAssuranceEvents()"> (paginationChange)="getQualityAssuranceEvents()">
<ng-container> <ng-container>
<div *ngIf="(eventsUpdated$ | async)?.length === 0" class="alert alert-info w-100 mb-2 mt-2" role="alert"> @if ((eventsUpdated$ | async)?.length === 0) {
<div class="alert alert-info w-100 mb-2 mt-2" role="alert">
{{'quality-assurance.noEvents' | translate}} {{'quality-assurance.noEvents' | translate}}
</div> </div>
<div *ngIf="(eventsUpdated$ | async)?.length !== 0" class="table-responsive mt-2"> }
@if ((eventsUpdated$ | async)?.length !== 0) {
<div class="table-responsive mt-2">
<table id="events" class="table table-striped table-hover table-bordered"> <table id="events" class="table table-striped table-hover table-bordered">
<thead> <thead>
<tr> <tr>
<th scope="col" class="trust-col">{{'quality-assurance.event.table.trust' | translate}}</th> <th scope="col" class="trust-col">{{'quality-assurance.event.table.trust' | translate}}</th>
<th scope="col" class="title-col">{{'quality-assurance.event.table.publication' | translate}}</th> <th scope="col" class="title-col">{{'quality-assurance.event.table.publication' | translate}}</th>
<th *ngIf="hasDetailColumn() && showTopic.indexOf('/PROJECT') !== -1" scope="col" class="content-col"> @if (hasDetailColumn() && showTopic.indexOf('/PROJECT') !== -1) {
<th scope="col" class="content-col">
{{'quality-assurance.event.table.project-details' | translate}} {{'quality-assurance.event.table.project-details' | translate}}
</th> </th>
<ng-container *ngIf="hasDetailColumn() && (showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1)"> }
@if (hasDetailColumn() && (showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1)) {
<th scope="col" class="content-col"> <th scope="col" class="content-col">
{{'quality-assurance.event.table.reasons' | translate}} {{'quality-assurance.event.table.reasons' | translate}}
</th> </th>
<th scope="col" class="content-col"> <th scope="col" class="content-col">
{{'quality-assurance.event.table.person-who-requested' | translate}} {{'quality-assurance.event.table.person-who-requested' | translate}}
</th> </th>
</ng-container> }
<th scope="col" class="button-col">{{'quality-assurance.event.table.actions' | translate}}</th> <th scope="col" class="button-col">{{'quality-assurance.event.table.actions' | translate}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let eventElement of (eventsUpdated$ | async); let i = index"> @for (eventElement of (eventsUpdated$ | async); track eventElement; let i = $index) {
<tr>
<td>{{eventElement?.event?.trust}} <td>{{eventElement?.event?.trust}}
</td> </td>
<td><a *ngIf="eventElement?.target" <td>@if (eventElement?.target) {
<a
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
[routerLink]="['/items', eventElement?.target?.id]">{{eventElement.title}}</a> [routerLink]="['/items', eventElement?.target?.id]">{{eventElement.title}}</a>
<span *ngIf="!eventElement?.target">{{eventElement.title}}</span> }
<div *ngIf="eventElement?.event?.message?.serviceId"> @if (!eventElement?.target) {
<span>{{eventElement.title}}</span>
}
@if (eventElement?.event?.message?.serviceId) {
<div>
<span class="small pe-1">{{'quality-assurance.event.table.event.message.serviceUrl' | translate}}</span> <span class="small pe-1">{{'quality-assurance.event.table.event.message.serviceUrl' | translate}}</span>
<span [title]="eventElement.event.message.serviceId"> <span [title]="eventElement.event.message.serviceId">
<a [href]="eventElement.event.message.serviceId" target="_blank">{{eventElement.event.message.serviceId}}</a> <a [href]="eventElement.event.message.serviceId" target="_blank">{{eventElement.event.message.serviceId}}</a>
</span> </span>
</div> </div>
<div *ngIf="eventElement?.event?.message?.href" class="d-flex align-items-center"> }
@if (eventElement?.event?.message?.href) {
<div class="d-flex align-items-center">
<span class="small pe-1">{{'quality-assurance.event.table.event.message.link' | translate}}</span> <span class="small pe-1">{{'quality-assurance.event.table.event.message.link' | translate}}</span>
<span [title]="eventElement.event.message.href" class="text-truncate d-inline-block w-75"> <span [title]="eventElement.event.message.href" class="text-truncate d-inline-block w-75">
<a [href]="eventElement.event.message.href" target="_blank">{{eventElement.event.message.href}}</a> <a [href]="eventElement.event.message.href" target="_blank">{{eventElement.event.message.href}}</a>
</span> </span>
</div> </div>
}
</td> </td>
<td *ngIf="showTopic.indexOf('/PID') !== -1"> @if (showTopic.indexOf('/PID') !== -1) {
<td>
<p><span class="small">{{'quality-assurance.event.table.pidtype' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.type}}</span></p> <p><span class="small">{{'quality-assurance.event.table.pidtype' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.type}}</span></p>
<p><span class="small">{{'quality-assurance.event.table.pidvalue' | translate}}</span><br> <p><span class="small">{{'quality-assurance.event.table.pidvalue' | translate}}</span><br>
<a *ngIf="hasPIDHref(eventElement.event.message); else noPID" href="{{getPIDHref(eventElement.event.message)}}" rel="noopener noreferrer" target="_blank"> @if (hasPIDHref(eventElement.event.message)) {
<a href="{{getPIDHref(eventElement.event.message)}}" rel="noopener noreferrer" target="_blank">
{{eventElement.event.message.value}} {{eventElement.event.message.value}}
</a> </a>
<ng-template #noPID><span class="badge bg-info">{{eventElement.event.message.value}}</span></ng-template> } @else {
<span class="badge bg-info">{{eventElement.event.message.value}}</span>
}
</p> </p>
</td> </td>
<td *ngIf="showTopic.indexOf('/SUBJECT') !== -1"> }
@if (showTopic.indexOf('/SUBJECT') !== -1) {
<td>
<p><span class="small">{{'quality-assurance.event.table.subjectValue' | translate}} <p><span class="small">{{'quality-assurance.event.table.subjectValue' | translate}}
</span><br><span class="badge bg-info">{{eventElement.event.message.value}}</span></p> </span><br><span class="badge bg-info">{{eventElement.event.message.value}}</span></p>
</td> </td>
<td *ngIf="showTopic.indexOf('/ABSTRACT') !== -1"> }
@if (showTopic.indexOf('/ABSTRACT') !== -1) {
<td>
<p class="abstract-container" [class.show]="showMore"> <p class="abstract-container" [class.show]="showMore">
<span class="small">{{'quality-assurance.event.table.abstract' | translate}}</span><br> <span class="small">{{'quality-assurance.event.table.abstract' | translate}}</span><br>
<span class="text-ellipsis">{{eventElement.event.message.abstract}}</span> <span class="text-ellipsis">{{eventElement.event.message.abstract}}</span>
</p> </p>
<button class="btn btn-outline-primary btn-sm" (click)="showMore = !showMore"> <button class="btn btn-outline-primary btn-sm" (click)="showMore = !showMore">
<i *ngIf="!showMore" class="fas fa-angle-down"></i> @if (!showMore) {
<i *ngIf="showMore" class="fas fa-angle-up"></i> <i class="fas fa-angle-down"></i>
}
@if (showMore) {
<i class="fas fa-angle-up"></i>
}
{{ (showMore ? 'quality-assurance.event.table.less': 'quality-assurance.event.table.more') | translate }} {{ (showMore ? 'quality-assurance.event.table.less': 'quality-assurance.event.table.more') | translate }}
</button> </button>
</td> </td>
<ng-container *ngIf="showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1"> }
@if (showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1) {
<td> <td>
<p> <p>
<span *ngIf="eventElement.event.message"> @if (eventElement.event.message) {
<span>
<span>{{eventElement.event.message.reason}}</span><br> <span>{{eventElement.event.message.reason}}</span><br>
</span> </span>
}
</p> </p>
</td> </td>
<td> <td>
<p> <p>
<span *ngIf="eventElement.event.originalId"> @if (eventElement.event.originalId) {
<span>
<ds-eperson-data [ePersonId]="eventElement.event.originalId" [properties]="['email']"></ds-eperson-data> <ds-eperson-data [ePersonId]="eventElement.event.originalId" [properties]="['email']"></ds-eperson-data>
</span> </span>
}
</p> </p>
</td> </td>
</ng-container> }
@if (showTopic.indexOf('/PROJECT') !== -1) {
<td *ngIf="showTopic.indexOf('/PROJECT') !== -1"> <td>
<p> <p>
{{'quality-assurance.event.table.suggestedProject' | translate}} {{'quality-assurance.event.table.suggestedProject' | translate}}
</p> </p>
@@ -125,18 +162,31 @@
<a href="{{sourceUrlForProjectSearch}}{{ eventElement.event.message.sourceId}}" rel="noopener noreferrer" target="_blank">{{eventElement.event.message.title}}</a> <a href="{{sourceUrlForProjectSearch}}{{ eventElement.event.message.sourceId}}" rel="noopener noreferrer" target="_blank">{{eventElement.event.message.title}}</a>
</p> </p>
<p> <p>
<span *ngIf="eventElement.event.message.acronym"><span class="small">{{'quality-assurance.event.table.acronym' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.acronym}}</span><br></span> @if (eventElement.event.message.acronym) {
<span *ngIf="eventElement.event.message.code"><span class="small">{{'quality-assurance.event.table.code' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.code}}</span><br></span> <span><span class="small">{{'quality-assurance.event.table.acronym' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.acronym}}</span><br></span>
<span *ngIf="eventElement.event.message.funder"><span class="small">{{'quality-assurance.event.table.funder' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.funder}}</span><br></span> }
<span *ngIf="eventElement.event.message.fundingProgram"><span class="small">{{'quality-assurance.event.table.fundingProgram' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.fundingProgram}}</span><br></span> @if (eventElement.event.message.code) {
<span *ngIf="eventElement.event.message.jurisdiction"><span class="small">{{'quality-assurance.event.table.jurisdiction' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.jurisdiction}}</span></span> <span><span class="small">{{'quality-assurance.event.table.code' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.code}}</span><br></span>
}
@if (eventElement.event.message.funder) {
<span><span class="small">{{'quality-assurance.event.table.funder' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.funder}}</span><br></span>
}
@if (eventElement.event.message.fundingProgram) {
<span><span class="small">{{'quality-assurance.event.table.fundingProgram' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.fundingProgram}}</span><br></span>
}
@if (eventElement.event.message.jurisdiction) {
<span><span class="small">{{'quality-assurance.event.table.jurisdiction' | translate}}</span>&nbsp;<span class="badge bg-info">{{eventElement.event.message.jurisdiction}}</span></span>
}
</p> </p>
<hr> <hr>
<div> <div>
{{(eventElement.hasProject ? 'quality-assurance.event.project.found' : 'quality-assurance.event.project.notFound') | translate}} {{(eventElement.hasProject ? 'quality-assurance.event.project.found' : 'quality-assurance.event.project.notFound') | translate}}
<a target="_blank" rel="noopener noreferrer" *ngIf="eventElement.hasProject" title="{{eventElement.projectTitle}}" [routerLink]="['/items', eventElement.projectId]">{{eventElement.handle}} </a> @if (eventElement.hasProject) {
<a target="_blank" rel="noopener noreferrer" title="{{eventElement.projectTitle}}" [routerLink]="['/items', eventElement.projectId]">{{eventElement.handle}} </a>
}
<div class="btn-group"> <div class="btn-group">
<button *ngIf="!eventElement.hasProject" @if (!eventElement.hasProject) {
<button
class="btn btn-outline-primary btn-sm" class="btn btn-outline-primary btn-sm"
[dsBtnDisabled]="eventElement.isRunning" [dsBtnDisabled]="eventElement.isRunning"
(click)="openModalLookup(eventElement); $event.stopPropagation();" (click)="openModalLookup(eventElement); $event.stopPropagation();"
@@ -144,7 +194,9 @@
> >
<i class="fas fa-search"></i> <i class="fas fa-search"></i>
</button> </button>
<button *ngIf="eventElement.hasProject" }
@if (eventElement.hasProject) {
<button
class="btn btn-outline-danger btn-sm" class="btn btn-outline-danger btn-sm"
[dsBtnDisabled]="eventElement.isRunning" [dsBtnDisabled]="eventElement.isRunning"
(click)="removeProject(eventElement)" (click)="removeProject(eventElement)"
@@ -152,12 +204,16 @@
> >
<i class="fas fa-trash-alt"></i> <i class="fas fa-trash-alt"></i>
</button> </button>
}
</div> </div>
</div> </div>
</td> </td>
}
<td> <td>
<div *ngIf="(isAdmin$ | async) || !isReinstateWithdrawnRequest" class="btn-group button-width"> @if ((isAdmin$ | async) || !isReinstateWithdrawnRequest) {
<button *ngIf="showTopic.indexOf('/PROJECT') !== -1" <div class="btn-group button-width">
@if (showTopic.indexOf('/PROJECT') !== -1) {
<button
class="btn btn-outline-success btn-sm button-width" class="btn btn-outline-success btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.import' | translate}}" ngbTooltip="{{'quality-assurance.event.action.import' | translate}}"
container="body" container="body"
@@ -167,7 +223,9 @@
> >
<i class="fas fa-check"></i> <i class="fas fa-check"></i>
</button> </button>
<button *ngIf="showTopic.indexOf('/PROJECT') === -1" }
@if (showTopic.indexOf('/PROJECT') === -1) {
<button
class="btn btn-outline-success btn-sm button-width" class="btn btn-outline-success btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.accept' | translate}}" ngbTooltip="{{'quality-assurance.event.action.accept' | translate}}"
container="body" container="body"
@@ -177,6 +235,7 @@
> >
<i class="fas fa-check"></i> <i class="fas fa-check"></i>
</button> </button>
}
<button class="btn btn-outline-dark btn-sm button-width" <button class="btn btn-outline-dark btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.ignore' | translate}}" ngbTooltip="{{'quality-assurance.event.action.ignore' | translate}}"
container="body" container="body"
@@ -186,8 +245,8 @@
> >
<i class="fas fa-ban"></i> <i class="fas fa-ban"></i>
</button> </button>
@if ((isAdmin$ | async)) {
<button class="btn btn-outline-danger btn-sm button-width" <button class="btn btn-outline-danger btn-sm button-width"
*ngIf="(isAdmin$ | async)"
ngbTooltip="{{'quality-assurance.event.action.reject' | translate}}" ngbTooltip="{{'quality-assurance.event.action.reject' | translate}}"
container="body" container="body"
[dsBtnDisabled]="eventElement.isRunning" [dsBtnDisabled]="eventElement.isRunning"
@@ -196,8 +255,9 @@
> >
<i class="fas fa-trash-alt"></i> <i class="fas fa-trash-alt"></i>
</button> </button>
}
@if ((isAdmin$ | async) === false) {
<button class="btn btn-outline-danger btn-sm button-width" <button class="btn btn-outline-danger btn-sm button-width"
*ngIf="(isAdmin$ | async) === false"
ngbTooltip="{{'quality-assurance.event.action.undo' | translate }}" ngbTooltip="{{'quality-assurance.event.action.undo' | translate }}"
container="body" container="body"
[dsBtnDisabled]="eventElement.isRunning" [dsBtnDisabled]="eventElement.isRunning"
@@ -205,8 +265,11 @@
(click)="openModal('UNDO', eventElement, undoModal)"> (click)="openModal('UNDO', eventElement, undoModal)">
<i class="fas fa-trash-alt"></i> <i class="fas fa-trash-alt"></i>
</button> </button>
}
</div> </div>
<div *ngIf="(isAdmin$ | async) !== true && isReinstateWithdrawnRequest" class="btn-group button-width"> }
@if ((isAdmin$ | async) !== true && isReinstateWithdrawnRequest) {
<div class="btn-group button-width">
<button class="btn btn-outline-danger btn-sm button-width" <button class="btn btn-outline-danger btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.undo' | translate}}" ngbTooltip="{{'quality-assurance.event.action.undo' | translate}}"
container="body" container="body"
@@ -216,13 +279,17 @@
<i class="fas fa-trash-alt"></i> <i class="fas fa-trash-alt"></i>
</button> </button>
</div> </div>
}
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
}
</ng-container> </ng-container>
</ds-pagination> </ds-pagination>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -9,20 +9,27 @@
<div class="col-12"> <div class="col-12">
<h2 class="h4 border-bottom pb-2">{{'quality-assurance.source'| translate}}</h2> <h2 class="h4 border-bottom pb-2">{{'quality-assurance.source'| translate}}</h2>
<ds-loading class="container" *ngIf="(isSourceLoading() | async)" message="{{'quality-assurance.loading' | translate}}"></ds-loading> @if ((isSourceLoading() | async)) {
<ds-pagination *ngIf="(isSourceLoading() | async) !== true" <ds-loading class="container" message="{{'quality-assurance.loading' | translate}}"></ds-loading>
}
@if ((isSourceLoading() | async) !== true) {
<ds-pagination
[paginationOptions]="paginationConfig" [paginationOptions]="paginationConfig"
[collectionSize]="(totalElements$ | async)" [collectionSize]="(totalElements$ | async)"
[hideGear]="false" [hideGear]="false"
[hideSortOptions]="true" [hideSortOptions]="true"
(paginationChange)="getQualityAssuranceSource()"> (paginationChange)="getQualityAssuranceSource()">
@if ((isSourceProcessing() | async)) {
<ds-loading class="container" *ngIf="(isSourceProcessing() | async)" message="'quality-assurance.loading' | translate"></ds-loading> <ds-loading class="container" message="'quality-assurance.loading' | translate"></ds-loading>
<ng-container *ngIf="(isSourceProcessing() | async) !== true"> }
<div *ngIf="(sources$ | async)?.length === 0" class="alert alert-info w-100 mb-2 mt-2" role="alert"> @if ((isSourceProcessing() | async) !== true) {
@if ((sources$ | async)?.length === 0) {
<div class="alert alert-info w-100 mb-2 mt-2" role="alert">
{{'quality-assurance.noSource' | translate}} {{'quality-assurance.noSource' | translate}}
</div> </div>
<div *ngIf="(sources$ | async)?.length !== 0" class="table-responsive mt-2"> }
@if ((sources$ | async)?.length !== 0) {
<div class="table-responsive mt-2">
<table id="epeople" class="table table-striped table-hover table-bordered"> <table id="epeople" class="table table-striped table-hover table-bordered">
<thead> <thead>
<tr> <tr>
@@ -32,7 +39,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let sourceElement of (sources$ | async); let i = index"> @for (sourceElement of (sources$ | async); track sourceElement; let i = $index) {
<tr>
<td>{{sourceElement.id}}</td> <td>{{sourceElement.id}}</td>
<td>{{sourceElement.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td> <td>{{sourceElement.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td>
<td> <td>
@@ -47,11 +55,14 @@
</div> </div>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ng-container> }
}
</ds-pagination> </ds-pagination>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -2,31 +2,42 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h1 class="border-bottom pb-2">{{'quality-assurance.title'| translate}}</h1> <h1 class="border-bottom pb-2">{{'quality-assurance.title'| translate}}</h1>
<ds-alert *ngIf="!targetId" [type]="'alert-info'">{{'quality-assurance.topics.description'| translate:{source: sourceId} }}</ds-alert> @if (!targetId) {
<ds-alert *ngIf="targetId" [type]="'alert-info'"> <ds-alert [type]="'alert-info'">{{'quality-assurance.topics.description'| translate:{source: sourceId} }}</ds-alert>
}
@if (targetId) {
<ds-alert [type]="'alert-info'">
{{'quality-assurance.topics.description-with-target'| translate:{source: sourceId} }} {{'quality-assurance.topics.description-with-target'| translate:{source: sourceId} }}
<a [routerLink]="itemPageUrl">{{(getTargetItemTitle() | async)}}</a> <a [routerLink]="itemPageUrl">{{(getTargetItemTitle() | async)}}</a>
</ds-alert> </ds-alert>
}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="border-bottom pb-2">{{'quality-assurance.topics'| translate}}</h2> <h2 class="border-bottom pb-2">{{'quality-assurance.topics'| translate}}</h2>
<ds-loading class="container" *ngIf="(isTopicsLoading() | async)" message="{{'quality-assurance.loading' | translate}}"></ds-loading> @if ((isTopicsLoading() | async)) {
<ds-pagination *ngIf="(isTopicsLoading() | async) !== true" <ds-loading class="container" message="{{'quality-assurance.loading' | translate}}"></ds-loading>
}
@if ((isTopicsLoading() | async) !== true) {
<ds-pagination
[paginationOptions]="paginationConfig" [paginationOptions]="paginationConfig"
[collectionSize]="(totalElements$ | async)" [collectionSize]="(totalElements$ | async)"
[hideGear]="false" [hideGear]="false"
[hideSortOptions]="true" [hideSortOptions]="true"
(paginationChange)="getQualityAssuranceTopics(sourceId, targetId)"> (paginationChange)="getQualityAssuranceTopics(sourceId, targetId)">
@if ((isTopicsProcessing() | async)) {
<ds-loading class="container" *ngIf="(isTopicsProcessing() | async)" message="'quality-assurance.loading' | translate"></ds-loading> <ds-loading class="container" message="'quality-assurance.loading' | translate"></ds-loading>
<ng-container *ngIf="(isTopicsProcessing() | async) !== true"> }
<div *ngIf="(topics$ | async)?.length === 0" class="alert alert-info w-100 mb-2 mt-2" role="alert"> @if ((isTopicsProcessing() | async) !== true) {
@if ((topics$ | async)?.length === 0) {
<div class="alert alert-info w-100 mb-2 mt-2" role="alert">
{{'quality-assurance.noTopics' | translate}} {{'quality-assurance.noTopics' | translate}}
</div> </div>
<div *ngIf="(topics$ | async)?.length !== 0" class="table-responsive mt-2"> }
@if ((topics$ | async)?.length !== 0) {
<div class="table-responsive mt-2">
<table id="epeople" class="table table-striped table-hover table-bordered"> <table id="epeople" class="table table-striped table-hover table-bordered">
<thead> <thead>
<tr> <tr>
@@ -36,7 +47,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let topicElement of (topics$ | async); let i = index"> @for (topicElement of (topics$ | async); track topicElement; let i = $index) {
<tr>
<td>{{topicElement.name}}</td> <td>{{topicElement.name}}</td>
<td>{{topicElement.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td> <td>{{topicElement.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td>
<td> <td>
@@ -51,11 +63,14 @@
</div> </div>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ng-container> }
}
</ds-pagination> </ds-pagination>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,29 +1,35 @@
<div class="d-inline"> <div class="d-inline">
<div ngbDropdown class="d-inline"> <div ngbDropdown class="d-inline">
<button *ngIf="isCollectionFixed; else chooseCollection" class="btn btn-success" type="button" (click)="approveAndImportCollectionFixed()"> @if (isCollectionFixed) {
<button class="btn btn-success" type="button" (click)="approveAndImportCollectionFixed()">
<i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}} <i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}}
</button> </button>
<ng-template #chooseCollection> } @else {
<button class="btn btn-success" id="dropdownSubmission" ngbDropdownToggle <button class="btn btn-success" id="dropdownSubmission" ngbDropdownToggle
type="button"> type="button">
<i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}} <i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}}
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<div ngbDropdownMenu <div ngbDropdownMenu
class="dropdown-menu" class="dropdown-menu"
id="entityControlsDropdownMenu" id="entityControlsDropdownMenu"
aria-labelledby="dropdownSubmission"> aria-labelledby="dropdownSubmission">
<ds-entity-dropdown (selectionChange)="openDialog($event)"></ds-entity-dropdown> <ds-entity-dropdown (selectionChange)="openDialog($event)"></ds-entity-dropdown>
</div> </div>
</ng-template> }
</div> </div>
<button (click)="ignoreSuggestion()" class="btn btn-danger ms-2"><i class="fa fa-ban"></i> <button (click)="ignoreSuggestion()" class="btn btn-danger ms-2"><i class="fa fa-ban"></i>
{{ ignoreSuggestionLabel() | translate}}</button> {{ ignoreSuggestionLabel() | translate}}</button>
<button *ngIf="!isBulk" (click)="toggleSeeEvidences()" [dsBtnDisabled]="!hasEvidence" class="btn btn-info ms-2"> @if (!isBulk) {
<button (click)="toggleSeeEvidences()" [dsBtnDisabled]="!hasEvidence" class="btn btn-info ms-2">
<i class="fa fa-eye"></i> <i class="fa fa-eye"></i>
<ng-container *ngIf="!seeEvidence"> {{ 'suggestion.seeEvidence' | translate}}</ng-container> @if (!seeEvidence) {
<ng-container *ngIf="seeEvidence"> {{ 'suggestion.hideEvidence' | translate}}</ng-container> {{ 'suggestion.seeEvidence' | translate}}
}
@if (seeEvidence) {
{{ 'suggestion.hideEvidence' | translate}}
}
</button> </button>
}
</div> </div>

View File

@@ -1,27 +1,32 @@
<div class="notifications-wrapper position-fixed top right" *ngIf="suggestionsRD$ | async"> @if (suggestionsRD$ | async) {
<div class="notifications-wrapper position-fixed top right">
<div class="notification alert alert-success alert-dismissible m-3 shadow" role="alert"> <div class="notification alert alert-success alert-dismissible m-3 shadow" role="alert">
<button (click)="removePopup()" <button (click)="removePopup()"
type="button" class="close pt-0 pe-1 pe-0 pb-0" data-dismiss="alert" aria-label="Close"> type="button" class="close pt-0 pe-1 pe-0 pb-0" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<div class="d-flex flex-column justify-content-center align-items-center"> <div class="d-flex flex-column justify-content-center align-items-center">
<div class="notification-icon d-flex justify-content-center"><i class="fas fa-2x fa-check-circle"></i></div> <div class="notification-icon d-flex justify-content-center"><i class="fas fa-2x fa-check-circle"></i></div>
</div> </div>
<div class="d-flex flex-column justify-content-center align-content-stretch text-left p-2"> <div class="d-flex flex-column justify-content-center align-content-stretch text-left p-2">
<ng-container *ngIf="(suggestionsRD$ | async) as suggestions"> @if ((suggestionsRD$ | async); as suggestions) {
<ng-container *ngFor="let suggestion of suggestions" class="alert alert-info"> @for (suggestion of suggestions; track suggestion) {
<div *ngIf="suggestion.total > 0"> <ng-container class="alert alert-info">
@if (suggestion.total > 0) {
<div>
<div [innerHTML]="'notification.suggestion' | translate: getNotificationSuggestionInterpolation(suggestion)"></div> <div [innerHTML]="'notification.suggestion' | translate: getNotificationSuggestionInterpolation(suggestion)"></div>
{{ 'notification.suggestion.please' | translate }} {{ 'notification.suggestion.please' | translate }}
<a [routerLink]="getNotificationSuggestionInterpolation(suggestion).url"> {{ 'notification.suggestion.review' | translate}} </a> <a [routerLink]="getNotificationSuggestionInterpolation(suggestion).url"> {{ 'notification.suggestion.review' | translate}} </a>
</div> </div>
}
</ng-container> </ng-container>
</ng-container> }
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
}

View File

@@ -1,84 +1,105 @@
<div class="container" *ngIf="(processRD$ | async)?.payload as process"> @if ((processRD$ | async)?.payload; as process) {
<div class="container">
<div class="row"> <div class="row">
<div class="col-10"> <div class="col-10">
<h1 class="flex-grow-1"> <h1 class="flex-grow-1">
{{ 'process.detail.title' | translate:{ id: process?.processId, name: process?.scriptName } }} {{ 'process.detail.title' | translate:{ id: process?.processId, name: process?.scriptName } }}
</h1> </h1>
</div> </div>
<div *ngIf="isRefreshing$ | async" class="col-2 refresh-counter"> @if (isRefreshing$ | async) {
<div class="col-2 refresh-counter">
{{ 'process.detail.refreshing' | translate }} <i class="fas fa-sync-alt fa-spin"></i> {{ 'process.detail.refreshing' | translate }} <i class="fas fa-sync-alt fa-spin"></i>
</div> </div>
}
</div> </div>
<ds-process-detail-field id="process-name" [title]="'process.detail.script'"> <ds-process-detail-field id="process-name" [title]="'process.detail.script'">
<div>{{ process?.scriptName }}</div> <div>{{ process?.scriptName }}</div>
</ds-process-detail-field> </ds-process-detail-field>
@if (process?.parameters && process?.parameters?.length > 0) {
<ds-process-detail-field *ngIf="process?.parameters && process?.parameters?.length > 0" id="process-arguments" <ds-process-detail-field id="process-arguments"
[title]="'process.detail.arguments'"> [title]="'process.detail.arguments'">
<div *ngFor="let argument of process?.parameters">{{ argument?.name }} {{ argument?.value }}</div> @for (argument of process?.parameters; track argument) {
<div>{{ argument?.name }} {{ argument?.value }}</div>
}
</ds-process-detail-field> </ds-process-detail-field>
}
<div *ngVar="(filesRD$ | async)?.payload?.page as files"> <div *ngVar="(filesRD$ | async)?.payload?.page as files">
<ds-process-detail-field *ngIf="files && files?.length > 0" id="process-files" @if (files && files?.length > 0) {
<ds-process-detail-field id="process-files"
[title]="'process.detail.output-files'"> [title]="'process.detail.output-files'">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<ds-file-download-link *ngFor="let file of files; let last=last;" [bitstream]="file"> @for (file of files; track file; let last = $last) {
<ds-file-download-link [bitstream]="file">
<span>{{getFileName(file)}}</span> <span>{{getFileName(file)}}</span>
<span>({{(file?.sizeBytes) | dsFileSize }})</span> <span>({{(file?.sizeBytes) | dsFileSize }})</span>
</ds-file-download-link> </ds-file-download-link>
}
</div> </div>
</ds-process-detail-field> </ds-process-detail-field>
}
</div> </div>
@if (process && process.startTime) {
<ds-process-detail-field *ngIf="process && process.startTime" id="process-start-time" <ds-process-detail-field id="process-start-time"
[title]="'process.detail.start-time' | translate"> [title]="'process.detail.start-time' | translate">
<div>{{ process.startTime | date:dateFormat:'UTC' }}</div> <div>{{ process.startTime | date:dateFormat:'UTC' }}</div>
</ds-process-detail-field> </ds-process-detail-field>
}
<ds-process-detail-field *ngIf="process && process.endTime" id="process-end-time" @if (process && process.endTime) {
<ds-process-detail-field id="process-end-time"
[title]="'process.detail.end-time' | translate"> [title]="'process.detail.end-time' | translate">
<div>{{ process.endTime | date:dateFormat:'UTC' }}</div> <div>{{ process.endTime | date:dateFormat:'UTC' }}</div>
</ds-process-detail-field> </ds-process-detail-field>
}
<ds-process-detail-field *ngIf="process && process.processStatus" id="process-status" @if (process && process.processStatus) {
<ds-process-detail-field id="process-status"
[title]="'process.detail.status' | translate"> [title]="'process.detail.status' | translate">
<div>{{ process.processStatus }}</div> <div>{{ process.processStatus }}</div>
</ds-process-detail-field> </ds-process-detail-field>
}
<ds-process-detail-field *ngIf="isProcessFinished(process)" id="process-output" [title]="'process.detail.output'"> @if (isProcessFinished(process)) {
<button *ngIf="!showOutputLogs && process?._links?.output?.href !== undefined" id="showOutputButton" <ds-process-detail-field id="process-output" [title]="'process.detail.output'">
@if (!showOutputLogs && process?._links?.output?.href !== undefined) {
<button id="showOutputButton"
class="btn btn-primary" (click)="showProcessOutputLogs()"> class="btn btn-primary" (click)="showProcessOutputLogs()">
{{ 'process.detail.logs.button' | translate }} {{ 'process.detail.logs.button' | translate }}
</button> </button>
<ds-loading *ngIf="retrievingOutputLogs$ | async" class="ds-themed-loading" }
@if (retrievingOutputLogs$ | async) {
<ds-loading class="ds-themed-loading"
message="{{ 'process.detail.logs.loading' | translate }}"></ds-loading> message="{{ 'process.detail.logs.loading' | translate }}"></ds-loading>
}
@if (showOutputLogs && (outputLogs$ | async)?.length > 0) {
<pre class="fw-bold text-secondary bg-light p-3" tabindex="0" <pre class="fw-bold text-secondary bg-light p-3" tabindex="0"
*ngIf="showOutputLogs && (outputLogs$ | async)?.length > 0">{{ (outputLogs$ | async) }}</pre> >{{ (outputLogs$ | async) }}</pre>
<p id="no-output-logs-message" *ngIf="((retrievingOutputLogs$ | async) !== true && showOutputLogs) }
&& (outputLogs$ | async | dsHasNoValue) || (outputLogs$ | async)?.length === 0 || !process._links.output"> @if (((retrievingOutputLogs$ | async) !== true && showOutputLogs)
&& (outputLogs$ | async | dsHasNoValue) || (outputLogs$ | async)?.length === 0 || !process._links.output) {
<p id="no-output-logs-message">
{{ 'process.detail.logs.none' | translate }} {{ 'process.detail.logs.none' | translate }}
</p> </p>
}
</ds-process-detail-field> </ds-process-detail-field>
}
<ds-process-detail-field id="process-actions" [title]="'process.detail.actions'"> <ds-process-detail-field id="process-actions" [title]="'process.detail.actions'">
<button class="btn btn-success me-2" routerLink="/processes/new" [queryParams]="{id: process?.processId}"><i <button class="btn btn-success me-2" routerLink="/processes/new" [queryParams]="{id: process?.processId}"><i
class="fas fa-plus pe-2"></i>{{'process.detail.create' | translate}}</button> class="fas fa-plus pe-2"></i>{{'process.detail.create' | translate}}</button>
<button *ngIf="isProcessFinished(process)" id="delete" class="btn btn-danger" @if (isProcessFinished(process)) {
<button id="delete" class="btn btn-danger"
(click)="openDeleteModal(deleteModal)"> (click)="openDeleteModal(deleteModal)">
<i class="fas fa-trash pe-2"></i>{{ 'process.detail.delete.button' | translate }} <i class="fas fa-trash pe-2"></i>{{ 'process.detail.delete.button' | translate }}
</button> </button>
}
</ds-process-detail-field> </ds-process-detail-field>
<div style="text-align: right;"> <div style="text-align: right;">
<a class="btn btn-outline-secondary mt-3" [routerLink]="'/processes'">{{'process.detail.back' | translate}}</a> <a class="btn btn-outline-secondary mt-3" [routerLink]="'/processes'">{{'process.detail.back' | translate}}</a>
</div> </div>
</div> </div>
}
<ng-template #deleteModal > <ng-template #deleteModal >
<div *ngIf="(processRD$ | async)?.payload as process"> @if ((processRD$ | async)?.payload; as process) {
<div>
<div class="modal-header"> <div class="modal-header">
<div> <div>
<h4>{{'process.detail.delete.header' | translate }}</h4> <h4>{{'process.detail.delete.header' | translate }}</h4>
@@ -88,7 +109,6 @@
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div>{{'process.detail.delete.body' | translate }}</div> <div>{{'process.detail.delete.body' | translate }}</div>
<div class="mt-4"> <div class="mt-4">
@@ -98,9 +118,8 @@
</button> </button>
</div> </div>
</div> </div>
</div> </div>
}
</ng-template> </ng-template>

View File

@@ -12,14 +12,20 @@
</form> </form>
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<ds-script-help *ngIf="selectedScript" [script]="selectedScript"></ds-script-help> @if (selectedScript) {
<ds-script-help [script]="selectedScript"></ds-script-help>
}
</div> </div>
</div> </div>
<div *ngIf="missingParameters.length > 0" class="mt-3 alert alert-danger validation-error"> @if (missingParameters.length > 0) {
<div class="mt-3 alert alert-danger validation-error">
{{'process.new.parameter.required.missing' | translate}} {{'process.new.parameter.required.missing' | translate}}
<ul> <ul>
<li *ngFor="let missing of missingParameters">{{missing}}</li> @for (missing of missingParameters; track missing) {
<li>{{missing}}</li>
}
</ul> </ul>
</div> </div>
}
</div> </div>

View File

@@ -6,15 +6,21 @@
[(ngModel)]="selectedParameter" [(ngModel)]="selectedParameter"
#param="ngModel"> #param="ngModel">
<option [ngValue]="undefined">{{ 'process.new.add-parameter' | translate }}</option> <option [ngValue]="undefined">{{ 'process.new.add-parameter' | translate }}</option>
<option *ngFor="let param of parameters" [ngValue]="param.name"> @for (param of parameters; track param) {
<option [ngValue]="param.name">
{{param.nameLong || param.name}} {{param.nameLong || param.name}}
</option> </option>
}
</select> </select>
<ds-parameter-value-input [initialValue]="parameterValue.value" [parameter]="selectedScriptParameter" (updateValue)="selectedParameterValue = $event" class="d-block col px-0" [index]="index"></ds-parameter-value-input> <ds-parameter-value-input [initialValue]="parameterValue.value" [parameter]="selectedScriptParameter" (updateValue)="selectedParameterValue = $event" class="d-block col px-0" [index]="index"></ds-parameter-value-input>
<button *ngIf="removable" [attr.aria-label]="'process.new.delete-parameter' | translate" @if (removable) {
<button [attr.aria-label]="'process.new.delete-parameter' | translate"
(click)="removeParameter.emit(parameterValue);" class="btn btn-danger col-1 remove-button"> (click)="removeParameter.emit(parameterValue);" class="btn btn-danger col-1 remove-button">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
</button> </button>
<span *ngIf="!removable" class="col-1"></span> }
@if (!removable) {
<span class="col-1"></span>
}
</div> </div>

View File

@@ -5,9 +5,13 @@
<span class="file-name ms-1">{{fileObject?.name}}</span> <span class="file-name ms-1">{{fileObject?.name}}</span>
</label> </label>
<input requireFile #file="ngModel" type="file" name="file-upload-{{index}}" id="file-upload-{{index}}" class="form-control-file d-none" [ngModel]="fileObject" (ngModelChange)="setFile($event)"/> <input requireFile #file="ngModel" type="file" name="file-upload-{{index}}" id="file-upload-{{index}}" class="form-control-file d-none" [ngModel]="fileObject" (ngModelChange)="setFile($event)"/>
<div *ngIf="file.invalid && (file.dirty || file.touched)" @if (file.invalid && (file.dirty || file.touched)) {
<div
class="alert alert-danger validation-error"> class="alert alert-danger validation-error">
<div *ngIf="file.errors.required"> @if (file.errors.required) {
<div>
{{'process.new.parameter.file.required' | translate}} {{'process.new.parameter.file.required' | translate}}
</div> </div>
}
</div> </div>
}

View File

@@ -1,11 +1,14 @@
<div class="mb-3" *ngIf="script?.parameters?.length" data-testID="parameters-select-container"> @if (script?.parameters?.length) {
<div class="mb-3" data-testID="parameters-select-container">
<label class="form-label">{{'process.new.select-parameters' | translate}}</label> <label class="form-label">{{'process.new.select-parameters' | translate}}</label>
@for (value of parameterValues; track value; let i = $index; let last = $last) {
<ds-parameter-select <ds-parameter-select
*ngFor="let value of parameterValues; let i = index; let last = last"
[parameters]="script.parameters" [parameters]="script.parameters"
[parameterValue]="value" [parameterValue]="value"
[removable]="!last" [removable]="!last"
[index]="i" [index]="i"
(removeParameter)="removeParameter(i)" (removeParameter)="removeParameter(i)"
(changeParameter)="updateParameter($event, i)"></ds-parameter-select> (changeParameter)="updateParameter($event, i)"></ds-parameter-select>
}
</div> </div>
}

View File

@@ -19,29 +19,34 @@
[infiniteScrollUpDistance]="1.5" [infiniteScrollUpDistance]="1.5"
[fromRoot]="true" [fromRoot]="true"
[scrollWindow]="false"> [scrollWindow]="false">
@for (script of scripts; track script) {
<button class="dropdown-item" <button class="dropdown-item"
*ngFor="let script of scripts"
role="menuitem" role="menuitem"
type="button" type="button"
title="{{ script.name }}" title="{{ script.name }}"
(click)="onSelect(script);"> (click)="onSelect(script);">
<span class="text-truncate">{{ script.name }}</span> <span class="text-truncate">{{ script.name }}</span>
</button> </button>
<ng-container *ngIf="(isLoading$ | async)"> }
@if ((isLoading$ | async)) {
<button class="dropdown-item disabled" role="menuitem"> <button class="dropdown-item disabled" role="menuitem">
<ds-loading message="{{'loading.default' | translate}}"> <ds-loading message="{{'loading.default' | translate}}">
</ds-loading> </ds-loading>
</button> </button>
</ng-container> }
</div> </div>
</div> </div>
</div> </div>
<div> <div>
<div *ngIf="script.invalid && (script.dirty || script.touched)" @if (script.invalid && (script.dirty || script.touched)) {
<div
class="alert alert-danger validation-error"> class="alert alert-danger validation-error">
<div *ngIf="script.errors.required"> @if (script.errors.required) {
<div>
{{ 'process.new.select-script.required' | translate }} {{ 'process.new.select-script.required' | translate }}
</div> </div>
</div> }
</div>
}
</div> </div>
</div> </div>

View File

@@ -30,14 +30,18 @@
<ng-template #buttons> <ng-template #buttons>
<div class="d-flex justify-content-end mb-2"> <div class="d-flex justify-content-end mb-2">
<button *ngIf="processBulkDeleteService.hasSelected()" class="btn btn-primary me-2" @if (processBulkDeleteService.hasSelected()) {
<button class="btn btn-primary me-2"
(click)="processBulkDeleteService.clearAllProcesses()"><i (click)="processBulkDeleteService.clearAllProcesses()"><i
class="fas fa-undo pe-2"></i>{{'process.overview.delete.clear' | translate }} class="fas fa-undo pe-2"></i>{{'process.overview.delete.clear' | translate }}
</button> </button>
<button *ngIf="processBulkDeleteService.hasSelected()" class="btn btn-danger me-2" }
@if (processBulkDeleteService.hasSelected()) {
<button class="btn btn-danger me-2"
(click)="openDeleteModal(deleteModal)"><i (click)="openDeleteModal(deleteModal)"><i
class="fas fa-trash pe-2"></i>{{'process.overview.delete' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }} class="fas fa-trash pe-2"></i>{{'process.overview.delete' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}
</button> </button>
}
<button class="btn btn-success" routerLink="/processes/new"><i <button class="btn btn-success" routerLink="/processes/new"><i
class="fas fa-plus pe-2"></i>{{'process.overview.new' | translate}}</button> class="fas fa-plus pe-2"></i>{{'process.overview.new' | translate}}</button>
</div> </div>
@@ -58,11 +62,15 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div *ngIf="(processBulkDeleteService.isProcessing$() | async) !== true">{{'process.overview.delete.body' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</div> @if ((processBulkDeleteService.isProcessing$() | async) !== true) {
<div *ngIf="processBulkDeleteService.isProcessing$() |async" class="alert alert-info"> <div>{{'process.overview.delete.body' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</div>
}
@if (processBulkDeleteService.isProcessing$() |async) {
<div class="alert alert-info">
<span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span> <span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span>
<span> {{ 'process.overview.delete.processing' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</span> <span> {{ 'process.overview.delete.processing' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</span>
</div> </div>
}
<div class="mt-4"> <div class="mt-4">
<button class="btn btn-primary me-2" [dsBtnDisabled]="processBulkDeleteService.isProcessing$() |async" <button class="btn btn-primary me-2" [dsBtnDisabled]="processBulkDeleteService.isProcessing$() |async"
(click)="closeModal()">{{'process.detail.delete.cancel' | translate}}</button> (click)="closeModal()">{{'process.detail.delete.cancel' | translate}}</button>

View File

@@ -2,10 +2,12 @@
<div class="d-flex" (click)="collapse.toggle()" [attr.aria-expanded]="!collapse.collapsed" role="button"> <div class="d-flex" (click)="collapse.toggle()" [attr.aria-expanded]="!collapse.collapsed" role="button">
<h2 class="flex-grow-1"> <h2 class="flex-grow-1">
{{'process.overview.table.' + processStatus.toLowerCase() + '.title' | translate}} {{'process.overview.table.' + processStatus.toLowerCase() + '.title' | translate}}
@if ((processesRD$ | async); as processesRD) {
<span class="badge rounded-pill bg-primary badge-nb-processes ps-2 pe-2" <span class="badge rounded-pill bg-primary badge-nb-processes ps-2 pe-2"
*ngIf="(processesRD$ | async) as processesRD"> >
{{processesRD?.payload?.totalElements}} {{processesRD?.payload?.totalElements}}
</span> </span>
}
<span class="ms-2 toggle-icon"> <span class="ms-2 toggle-icon">
<i class="fas" [ngClass]="collapse.collapsed ? 'fa-angle-right' : 'fa-angle-down'"></i> <i class="fas" [ngClass]="collapse.collapsed ? 'fa-angle-right' : 'fa-angle-down'"></i>
</span> </span>
@@ -15,14 +17,16 @@
<div ngbCollapse #collapse="ngbCollapse" [ngbCollapse]="isCollapsed"> <div ngbCollapse #collapse="ngbCollapse" [ngbCollapse]="isCollapsed">
<ng-container *ngVar="(processesRD$ | async) as processesRD"> <ng-container *ngVar="(processesRD$ | async) as processesRD">
<ds-loading *ngIf="!processesRD || processesRD.isLoading"/> @if (!processesRD || processesRD.isLoading) {
<ds-loading/>
}
<ds-pagination *ngIf="processesRD?.payload?.totalElements > 0" @if (processesRD?.payload?.totalElements > 0) {
<ds-pagination
[paginationOptions]="(paginationOptions$ | async)" [paginationOptions]="(paginationOptions$ | async)"
[collectionSize]="processesRD?.payload?.totalElements" [collectionSize]="processesRD?.payload?.totalElements"
[retainScrollPosition]="true" [retainScrollPosition]="true"
[hideGear]="true"> [hideGear]="true">
<div class="table-responsive mt-1"> <div class="table-responsive mt-1">
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">
<thead> <thead>
@@ -34,9 +38,9 @@
<th scope="col" class="actions-header">{{'process.overview.table.actions' | translate}}</th> <th scope="col" class="actions-header">{{'process.overview.table.actions' | translate}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let tableEntry of processesRD?.payload?.page" @for (tableEntry of processesRD?.payload?.page; track tableEntry) {
<tr
[class]="getRowClass(tableEntry.process)"> [class]="getRowClass(tableEntry.process)">
<td><a [routerLink]="['/processes/', tableEntry.process.processId]">{{tableEntry.process.processId}}</a></td> <td><a [routerLink]="['/processes/', tableEntry.process.processId]">{{tableEntry.process.processId}}</a></td>
<td><a [routerLink]="['/processes/', tableEntry.process.processId]">{{tableEntry.process.scriptName}}</a></td> <td><a [routerLink]="['/processes/', tableEntry.process.processId]">{{tableEntry.process.scriptName}}</a></td>
@@ -50,15 +54,18 @@
</button> </button>
</td> </td>
</tr> </tr>
}
</tbody> </tbody>
</table> </table>
</div> </div>
</ds-pagination> </ds-pagination>
}
<div *ngIf="processesRD?.payload?.totalElements === 0"> @if (processesRD?.payload?.totalElements === 0) {
<div>
<p>{{'process.overview.table.empty' | translate}}</p> <p>{{'process.overview.table.empty' | translate}}</p>
</div> </div>
}
</ng-container> </ng-container>
</div> </div>

View File

@@ -9,7 +9,8 @@
</div> </div>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<div class="scrollable-menu list-group container"> <div class="scrollable-menu list-group container">
<div *ngFor="let listEntry of (listEntries$ | async)?.payload.page" class="row"> @for (listEntry of (listEntries$ | async)?.payload.page; track listEntry) {
<div class="row">
<button class="list-group-item list-group-item-action border-0 list-entry" <button class="list-group-item list-group-item-action border-0 list-entry"
title="{{ dsoNameService.getName(listEntry.indexableObject) }}" title="{{ dsoNameService.getName(listEntry.indexableObject) }}"
(click)="selectItem(listEntry.indexableObject)" #listEntryElement> (click)="selectItem(listEntry.indexableObject)" #listEntryElement>
@@ -17,6 +18,7 @@
[linkType]=linkTypes.None></ds-listable-object-component-loader> [linkType]=linkTypes.None></ds-listable-object-component-loader>
</button> </button>
</div> </div>
}
<div class="row"> <div class="row">
<div class="col-md mt-2"> <div class="col-md mt-2">
</div> </div>

View File

@@ -1,5 +1,6 @@
<div *ngVar="(researcherProfile$ | async) as researcherProfile"> <div *ngVar="(researcherProfile$ | async) as researcherProfile">
<div *ngIf="researcherProfile"> @if (researcherProfile) {
<div>
<p>{{'researcher.profile.associated' | translate}}</p> <p>{{'researcher.profile.associated' | translate}}</p>
<p class="align-items-center researcher-profile-switch" > <p class="align-items-center researcher-profile-switch" >
<span class="me-3">{{'researcher.profile.status' | translate}}</span> <span class="me-3">{{'researcher.profile.status' | translate}}</span>
@@ -9,30 +10,43 @@
(change)="toggleProfileVisibility(researcherProfile)" ></ui-switch> (change)="toggleProfileVisibility(researcherProfile)" ></ui-switch>
</p> </p>
</div> </div>
<div *ngIf="!researcherProfile"> }
@if (!researcherProfile) {
<div>
<p>{{'researcher.profile.not.associated' | translate}}</p> <p>{{'researcher.profile.not.associated' | translate}}</p>
</div> </div>
<button *ngIf="!researcherProfile" class="btn btn-primary me-2" }
@if (!researcherProfile) {
<button class="btn btn-primary me-2"
[dsBtnDisabled]="(isProcessingCreate() | async)" [dsBtnDisabled]="(isProcessingCreate() | async)"
(click)="createProfile()"> (click)="createProfile()">
<span *ngIf="(isProcessingCreate() | async)"> @if ((isProcessingCreate() | async)) {
<span>
<i class='fas fa-circle-notch fa-spin'></i> {{'researcher.profile.action.processing' | translate}} <i class='fas fa-circle-notch fa-spin'></i> {{'researcher.profile.action.processing' | translate}}
</span> </span>
<span *ngIf="(isProcessingCreate() | async) !== true"> }
@if ((isProcessingCreate() | async) !== true) {
<span>
<i class="fas fa-plus"></i> &nbsp;{{'researcher.profile.create.new' | translate}} <i class="fas fa-plus"></i> &nbsp;{{'researcher.profile.create.new' | translate}}
</span> </span>
}
</button> </button>
<ng-container *ngIf="researcherProfile"> }
@if (researcherProfile) {
<button class="btn btn-primary me-2" [dsBtnDisabled]="!researcherProfile" (click)="viewProfile(researcherProfile)"> <button class="btn btn-primary me-2" [dsBtnDisabled]="!researcherProfile" (click)="viewProfile(researcherProfile)">
<i class="fas fa-info-circle"></i> {{'researcher.profile.view' | translate}} <i class="fas fa-info-circle"></i> {{'researcher.profile.view' | translate}}
</button> </button>
<button class="btn btn-danger" [dsBtnDisabled]="!researcherProfile" (click)="deleteProfile(researcherProfile)"> <button class="btn btn-danger" [dsBtnDisabled]="!researcherProfile" (click)="deleteProfile(researcherProfile)">
<span *ngIf="(isProcessingDelete() | async)"> @if ((isProcessingDelete() | async)) {
<span>
<i class='fas fa-circle-notch fa-spin'></i> {{'researcher.profile.action.processing' | translate}} <i class='fas fa-circle-notch fa-spin'></i> {{'researcher.profile.action.processing' | translate}}
</span> </span>
<span *ngIf="(isProcessingDelete() | async) !== true"> }
@if ((isProcessingDelete() | async) !== true) {
<span>
<i class="fas fa-trash-alt"></i> &nbsp;{{'researcher.profile.delete' | translate}} <i class="fas fa-trash-alt"></i> &nbsp;{{'researcher.profile.delete' | translate}}
</span> </span>
}
</button> </button>
</ng-container> }
</div> </div>

View File

@@ -1,7 +1,8 @@
<ng-container *ngVar="(user$ | async) as user"> <ng-container *ngVar="(user$ | async) as user">
<div class="container" *ngIf="user"> @if (user) {
<div class="container">
<h1>{{'profile.title' | translate}}</h1> <h1>{{'profile.title' | translate}}</h1>
<ng-container *ngIf="isResearcherProfileEnabled$ | async"> @if (isResearcherProfileEnabled$ | async) {
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'profile.card.researcher' | translate}}</div> <div class="card-header">{{'profile.card.researcher' | translate}}</div>
<div class="card-body"> <div class="card-body">
@@ -11,14 +12,15 @@
<ds-suggestions-notification></ds-suggestions-notification> <ds-suggestions-notification></ds-suggestions-notification>
</div> </div>
</div> </div>
</ng-container> }
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'profile.card.identify' | translate}}</div> <div class="card-header">{{'profile.card.identify' | translate}}</div>
<div class="card-body"> <div class="card-body">
<ds-profile-page-metadata-form [user]="user"></ds-profile-page-metadata-form> <ds-profile-page-metadata-form [user]="user"></ds-profile-page-metadata-form>
</div> </div>
</div> </div>
<div *ngIf="canChangePassword$ | async" class="card mb-4 security-section"> @if (canChangePassword$ | async) {
<div class="card mb-4 security-section">
<div class="card-header">{{'profile.card.security' | translate}}</div> <div class="card-header">{{'profile.card.security' | translate}}</div>
<div class="card-body"> <div class="card-body">
<ds-profile-page-security-form <ds-profile-page-security-form
@@ -29,44 +31,56 @@
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>
}
<div class="col-12 text-end pe-0"> <div class="col-12 text-end pe-0">
<button class="btn btn-primary" (click)="updateProfile()"><i class="fas fa-edit"></i> {{'profile.form.submit' | translate}}</button> <button class="btn btn-primary" (click)="updateProfile()"><i class="fas fa-edit"></i> {{'profile.form.submit' | translate}}</button>
</div> </div>
@if ((groupsRD$ | async); as groupsRD;) {
<ng-container *ngIf="(groupsRD$ | async) as groupsRD;">
<ng-container *ngTemplateOutlet="groupsRD?.isLoading ? loader : content"></ng-container> <ng-container *ngTemplateOutlet="groupsRD?.isLoading ? loader : content"></ng-container>
<ng-template #content> <ng-template #content>
<ds-pagination *ngIf="groupsRD?.payload" @if (groupsRD?.payload) {
<ds-pagination
[hideGear]="true" [hideGear]="true"
[hidePagerWhenSinglePage]="true" [hidePagerWhenSinglePage]="true"
[hidePaginationDetail]="true" [hidePaginationDetail]="true"
[paginationOptions]="optionsGroupsPagination" [paginationOptions]="optionsGroupsPagination"
[collectionSize]="groupsRD?.payload?.totalElements"> [collectionSize]="groupsRD?.payload?.totalElements">
<ng-container *ngIf="groupsRD?.payload?.page as groups"> @if (groupsRD?.payload?.page; as groups) {
<div *ngIf="groups?.length > 0"> @if (groups?.length > 0) {
<div>
<h2 class="mt-4">{{ 'profile.groups.head' | translate }}</h2> <h2 class="mt-4">{{ 'profile.groups.head' | translate }}</h2>
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
<li *ngFor="let group of groups" class="list-group-item">{{ dsoNameService.getName(group) }}</li> @for (group of groups; track group) {
<li class="list-group-item">{{ dsoNameService.getName(group) }}</li>
}
</ul> </ul>
</div> </div>
</ng-container> }
}
</ds-pagination> </ds-pagination>
}
</ng-template> </ng-template>
<ng-template #loader> <ng-template #loader>
<ds-loading [showMessage]="false"></ds-loading> <ds-loading [showMessage]="false"></ds-loading>
</ng-template> </ng-template>
<ds-error *ngIf="groupsRD?.hasFailed" message="{{ 'error.profile-groups' | translate }}"></ds-error> @if (groupsRD?.hasFailed) {
</ng-container> <ds-error message="{{ 'error.profile-groups' | translate }}"></ds-error>
}
}
<ng-container *ngVar="(specialGroupsRD$ | async)?.payload?.page as specialGroups"> <ng-container *ngVar="(specialGroupsRD$ | async)?.payload?.page as specialGroups">
<div *ngIf="specialGroups?.length > 0" data-test="specialGroups"> @if (specialGroups?.length > 0) {
<div data-test="specialGroups">
<h2 class="mt-4">{{'profile.special.groups.head' | translate}}</h2> <h2 class="mt-4">{{'profile.special.groups.head' | translate}}</h2>
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
<li *ngFor="let specialGroup of specialGroups" class="list-group-item"> @for (specialGroup of specialGroups; track specialGroup) {
<li class="list-group-item">
{{ dsoNameService.getName(specialGroup) }} {{ dsoNameService.getName(specialGroup) }}
</li> </li>
}
</ul> </ul>
</div> </div>
}
</ng-container> </ng-container>
</div> </div>
}
</ng-container> </ng-container>

View File

@@ -2,9 +2,11 @@
<h1>{{MESSAGE_PREFIX + '.header'|translate}}</h1> <h1>{{MESSAGE_PREFIX + '.header'|translate}}</h1>
<p>{{MESSAGE_PREFIX + '.info' | translate}}</p> <p>{{MESSAGE_PREFIX + '.info' | translate}}</p>
<p *ngIf="validMailDomains.length !== 0 && typeRequest === TYPE_REQUEST_REGISTER"> @if (validMailDomains.length !== 0 && typeRequest === TYPE_REQUEST_REGISTER) {
<p>
{{ MESSAGE_PREFIX + '.info.maildomain' | translate}} {{ validMailDomains.join(', ')}} {{ MESSAGE_PREFIX + '.info.maildomain' | translate}} {{ validMailDomains.join(', ')}}
</p> </p>
}
<form [class]="'ng-invalid'" [formGroup]="form"> <form [class]="'ng-invalid'" [formGroup]="form">
@@ -18,18 +20,24 @@
[attr.aria-label]="MESSAGE_PREFIX + '.aria.label' | translate" [attr.aria-label]="MESSAGE_PREFIX + '.aria.label' | translate"
[attr.aria-describedby]="(!email.errors) ? '' : (email.errors.required ? 'email-errors-required' : 'email-error-not-valid')" [attr.aria-describedby]="(!email.errors) ? '' : (email.errors.required ? 'email-errors-required' : 'email-error-not-valid')"
[attr.aria-invalid]="email.invalid"/> [attr.aria-invalid]="email.invalid"/>
<div *ngIf="email.invalid && (email.dirty || email.touched)" @if (email.invalid && (email.dirty || email.touched)) {
<div
class="invalid-feedback show-feedback"> class="invalid-feedback show-feedback">
<span *ngIf="email.errors && email.errors.required" id="email-errors-required"> @if (email.errors && email.errors.required) {
<span id="email-errors-required">
{{ MESSAGE_PREFIX + '.email.error.required' | translate }} {{ MESSAGE_PREFIX + '.email.error.required' | translate }}
</span> </span>
<span *ngIf="email.errors && ((email.errors.pattern && this.typeRequest === TYPE_REQUEST_REGISTER) || email.errors.email)" id="email-error-not-valid"> }
@if (email.errors && ((email.errors.pattern && this.typeRequest === TYPE_REQUEST_REGISTER) || email.errors.email)) {
<span id="email-error-not-valid">
{{ MESSAGE_PREFIX + '.email.error.not-email-form' | translate }} {{ MESSAGE_PREFIX + '.email.error.not-email-form' | translate }}
<ng-container *ngIf="validMailDomains.length > 0"> @if (validMailDomains.length > 0) {
{{ MESSAGE_PREFIX + '.email.error.not-valid-domain' | translate: { domains: validMailDomains.join(', ') } }} {{ MESSAGE_PREFIX + '.email.error.not-valid-domain' | translate: { domains: validMailDomains.join(', ') } }}
</ng-container> }
</span> </span>
}
</div> </div>
}
</div> </div>
<div class="col-12"> <div class="col-12">
{{MESSAGE_PREFIX + '.email.hint' |translate}} {{MESSAGE_PREFIX + '.email.hint' |translate}}
@@ -39,28 +47,31 @@
</div> </div>
<ds-alert [type]="AlertTypeEnum.Warning" *ngIf="registrationVerification && !isRecaptchaCookieAccepted()"> @if (registrationVerification && !isRecaptchaCookieAccepted()) {
<ds-alert [type]="AlertTypeEnum.Warning">
<p class="m-0" [innerHTML]="MESSAGE_PREFIX + '.google-recaptcha.must-accept-cookies' | translate"></p> <p class="m-0" [innerHTML]="MESSAGE_PREFIX + '.google-recaptcha.must-accept-cookies' | translate"></p>
<p class="m-0"><a href="javascript:void(0);" (click)="this.orejimeService.showSettings()">{{ MESSAGE_PREFIX + '.google-recaptcha.open-cookie-settings' | translate }}</a></p> <p class="m-0"><a href="javascript:void(0);" (click)="this.orejimeService.showSettings()">{{ MESSAGE_PREFIX + '.google-recaptcha.open-cookie-settings' | translate }}</a></p>
</ds-alert> </ds-alert>
}
<div class="my-3" *ngIf="isRecaptchaCookieAccepted() && (googleRecaptchaService.captchaVersion() | async) === 'v2'"> @if (isRecaptchaCookieAccepted() && (googleRecaptchaService.captchaVersion() | async) === 'v2') {
<div class="my-3">
<ds-google-recaptcha [captchaMode]="(googleRecaptchaService.captchaMode() | async)" <ds-google-recaptcha [captchaMode]="(googleRecaptchaService.captchaMode() | async)"
(executeRecaptcha)="register($event)" (checkboxChecked)="onCheckboxChecked($event)" (executeRecaptcha)="register($event)" (checkboxChecked)="onCheckboxChecked($event)"
(showNotification)="showNotification($event)"></ds-google-recaptcha> (showNotification)="showNotification($event)"></ds-google-recaptcha>
</div> </div>
}
<ng-container *ngIf="(!registrationVerification || ((googleRecaptchaService.captchaVersion() | async) !== 'v2' && (googleRecaptchaService.captchaMode() | async) === 'invisible')); else v2Invisible"> @if ((!registrationVerification || ((googleRecaptchaService.captchaVersion() | async) !== 'v2' && (googleRecaptchaService.captchaMode() | async) === 'invisible'))) {
<button class="btn btn-primary" [dsBtnDisabled]="form.invalid || registrationVerification && !isRecaptchaCookieAccepted() || disableUntilChecked" (click)="register()"> <button class="btn btn-primary" [dsBtnDisabled]="form.invalid || registrationVerification && !isRecaptchaCookieAccepted() || disableUntilChecked" (click)="register()">
{{ MESSAGE_PREFIX + '.submit' | translate }} {{ MESSAGE_PREFIX + '.submit' | translate }}
</button> </button>
</ng-container> } @else {
<ng-template #v2Invisible>
<button class="btn btn-primary" [dsBtnDisabled]="form.invalid" (click)="executeRecaptcha()"> <button class="btn btn-primary" [dsBtnDisabled]="form.invalid" (click)="executeRecaptcha()">
{{ MESSAGE_PREFIX + '.submit' | translate }} {{ MESSAGE_PREFIX + '.submit' | translate }}
</button> </button>
</ng-template> }
</form> </form>
</div> </div>

View File

@@ -1,4 +1,5 @@
<div class="container" *ngIf="(registration$ |async)"> @if ((registration$ |async)) {
<div class="container">
<h3 class="mb-4">{{'register-page.create-profile.header' | translate}}</h3> <h3 class="mb-4">{{'register-page.create-profile.header' | translate}}</h3>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'register-page.create-profile.identification.header' | translate}}</div> <div class="card-header">{{'register-page.create-profile.identification.header' | translate}}</div>
@@ -10,21 +11,23 @@
<span id="email">{{(registration$ |async).email}}</span></div> <span id="email">{{(registration$ |async).email}}</span></div>
</div> </div>
<form [class]="'ng-invalid'" [formGroup]="userInfoForm" (ngSubmit)="submitEperson()"> <form [class]="'ng-invalid'" [formGroup]="userInfoForm" (ngSubmit)="submitEperson()">
<div class="mb-3"> <div class="mb-3">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<label for="firstName" class="form-label">{{'register-page.create-profile.identification.first-name' | translate}}</label> <label for="firstName" class="form-label">{{'register-page.create-profile.identification.first-name' | translate}}</label>
<input [className]="(firstName.invalid) && (firstName.dirty || firstName.touched) ? 'form-control is-invalid' :'form-control'" <input [className]="(firstName.invalid) && (firstName.dirty || firstName.touched) ? 'form-control is-invalid' :'form-control'"
type="text" id="firstName" formControlName="firstName"/> type="text" id="firstName" formControlName="firstName"/>
<div *ngIf="firstName.invalid && (firstName.dirty || firstName.touched)" @if (firstName.invalid && (firstName.dirty || firstName.touched)) {
<div
class="invalid-feedback show-feedback"> class="invalid-feedback show-feedback">
<span *ngIf="firstName.errors && firstName.errors.required"> @if (firstName.errors && firstName.errors.required) {
<span>
{{ 'register-page.create-profile.identification.first-name.error' | translate }} {{ 'register-page.create-profile.identification.first-name.error' | translate }}
</span> </span>
}
</div> </div>
}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@@ -33,12 +36,16 @@
<input <input
[className]="(lastName.invalid) && (lastName.dirty || lastName.touched) ? 'form-control is-invalid' :'form-control'" [className]="(lastName.invalid) && (lastName.dirty || lastName.touched) ? 'form-control is-invalid' :'form-control'"
id="lastName" formControlName="lastName"> id="lastName" formControlName="lastName">
<div *ngIf="lastName.invalid && (lastName.dirty || lastName.touched)" @if (lastName.invalid && (lastName.dirty || lastName.touched)) {
<div
class="invalid-feedback show-feedback"> class="invalid-feedback show-feedback">
<span *ngIf="lastName.errors && lastName.errors.required"> @if (lastName.errors && lastName.errors.required) {
<span>
{{ 'register-page.create-profile.identification.last-name.error' | translate }} {{ 'register-page.create-profile.identification.last-name.error' | translate }}
</span> </span>
}
</div> </div>
}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -52,10 +59,11 @@
<div class="col-12"> <div class="col-12">
<label class="form-label" <label class="form-label"
for="language">{{'register-page.create-profile.identification.language' |translate}}</label> for="language">{{'register-page.create-profile.identification.language' |translate}}</label>
<select id="language" formControlName="language" class="form-select"> <select id="language" formControlName="language" class="form-select">
<option [value]="''"></option> <option [value]="''"></option>
<option *ngFor="let lang of activeLangs" [value]="lang.code">{{lang.label}}</option> @for (lang of activeLangs; track lang) {
<option [value]="lang.code">{{lang.label}}</option>
}
</select> </select>
</div> </div>
</div> </div>
@@ -63,11 +71,9 @@
</form> </form>
</div> </div>
</div> </div>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">{{'register-page.create-profile.security.header' | translate}}</div> <div class="card-header">{{'register-page.create-profile.security.header' | translate}}</div>
<div class="card-body"> <div class="card-body">
<ds-profile-page-security-form <ds-profile-page-security-form
[passwordCanBeEmpty]="false" [passwordCanBeEmpty]="false"
[FORM_PREFIX]="'register-page.create-profile.security.'" [FORM_PREFIX]="'register-page.create-profile.security.'"
@@ -76,8 +82,6 @@
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<button <button
@@ -86,6 +90,5 @@
(click)="submitEperson()">{{'register-page.create-profile.submit' | translate}}</button> (click)="submitEperson()">{{'register-page.create-profile.submit' | translate}}</button>
</div> </div>
</div> </div>
</div> </div>
}

View File

@@ -2,9 +2,11 @@
<div class="mb-3"> <div class="mb-3">
<label for="subject" class="form-label">{{ 'grant-deny-request-copy.email.subject' | translate }}</label> <label for="subject" class="form-label">{{ 'grant-deny-request-copy.email.subject' | translate }}</label>
<input type="text" class="form-control" id="subject" [ngClass]="{'is-invalid': !subject || subject.length === 0}" [(ngModel)]="subject" name="subject"> <input type="text" class="form-control" id="subject" [ngClass]="{'is-invalid': !subject || subject.length === 0}" [(ngModel)]="subject" name="subject">
<div *ngIf="!subject || subject.length === 0" class="invalid-feedback"> @if (!subject || subject.length === 0) {
<div class="invalid-feedback">
{{ 'grant-deny-request-copy.email.subject.empty' | translate }} {{ 'grant-deny-request-copy.email.subject.empty' | translate }}
</div> </div>
}
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="message" class="form-label">{{ 'grant-deny-request-copy.email.message' | translate }}</label> <label for="message" class="form-label">{{ 'grant-deny-request-copy.email.message' | translate }}</label>

View File

@@ -1,11 +1,12 @@
<form #ngForm="ngForm"> <form #ngForm="ngForm">
<div *ngIf="showWarning" class="alert alert-warning"> @if (showWarning) {
<div class="alert alert-warning">
{{'access-control-no-access-conditions-warning-message' | translate}} {{'access-control-no-access-conditions-warning-message' | translate}}
</div> </div>
}
<ng-container *ngFor="let control of form.accessControls; trackBy: trackById"> @for (control of form.accessControls; track trackById($index, control)) {
<div ngModelGroup="access-control-item-{{control.id}}" class="access-control-item mt-3"> <div ngModelGroup="access-control-item-{{control.id}}" class="access-control-item mt-3">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<div> <div>
<label class="form-label" for="accesscontroloption-{{control.id}}"> <label class="form-label" for="accesscontroloption-{{control.id}}">
@@ -19,16 +20,18 @@
name="itemName-{{control.id}}" name="itemName-{{control.id}}"
class="form-select"> class="form-select">
<option value=""></option> <option value=""></option>
<option *ngFor="let option of dropdownOptions" [value]="option.name"> @for (option of dropdownOptions; track option) {
<option [value]="option.name">
{{ option.name }} {{ option.name }}
</option> </option>
}
</select> </select>
<small class="form-text text-muted"> <small class="form-text text-muted">
{{'access-control-option-note' | translate}} {{'access-control-option-note' | translate}}
</small> </small>
</div> </div>
@if (control.hasStartDate) {
<div *ngIf="control.hasStartDate" class="mt-3"> <div class="mt-3">
<label class="form-label" for="accesscontrolstartdate-{{control.id}}"> <label class="form-label" for="accesscontrolstartdate-{{control.id}}">
{{'access-control-option-start-date' | translate}} {{'access-control-option-start-date' | translate}}
</label> </label>
@@ -56,8 +59,9 @@
{{'access-control-option-start-date-note' | translate}} {{'access-control-option-start-date-note' | translate}}
</small> </small>
</div> </div>
}
<div *ngIf="control.hasEndDate" class="mt-3"> @if (control.hasEndDate) {
<div class="mt-3">
<label class="form-label" for="accesscontrolenddate-{{control.id}}"> <label class="form-label" for="accesscontrolenddate-{{control.id}}">
{{'access-control-option-end-date' | translate}} {{'access-control-option-end-date' | translate}}
</label> </label>
@@ -85,12 +89,11 @@
{{'access-control-option-end-date-note' | translate}} {{'access-control-option-end-date-note' | translate}}
</small> </small>
</div> </div>
}
</div> </div>
<div> <div>
<span aria-hidden="true" class="mb-2 d-inline-block">&nbsp;</span> <span aria-hidden="true" class="mb-2 d-inline-block">&nbsp;</span>
<div class="input-group"> <div class="input-group">
<button type="button" class="btn btn-outline-danger" <button type="button" class="btn btn-outline-danger"
[attr.aria-label]="'access-control-remove' | translate" [attr.aria-label]="'access-control-remove' | translate"
[dsBtnDisabled]="ngForm.disabled || form.accessControls.length === 1" [dsBtnDisabled]="ngForm.disabled || form.accessControls.length === 1"
@@ -100,7 +103,7 @@
</div> </div>
</div> </div>
</div> </div>
</ng-container> }
<button type="button" id="add-btn-{{type}}" class="btn btn-outline-primary mt-3" <button type="button" id="add-btn-{{type}}" class="btn btn-outline-primary mt-3"
[dsBtnDisabled]="ngForm.disabled" [dsBtnDisabled]="ngForm.disabled"

View File

@@ -1,12 +1,13 @@
<div class="container"> <div class="container">
<div class="card border-0"> <div class="card border-0">
<div class="card-body"> <div class="card-body">
@if (titleMessage) {
<ds-alert <ds-alert
*ngIf="titleMessage"
[type]="AlertType.Info" [type]="AlertType.Info"
[content]="titleMessage" [content]="titleMessage"
class="d-block pb-3"> class="d-block pb-3">
</ds-alert> </ds-alert>
}
<div class="row mt-5"> <div class="row mt-5">
<div class="col-12 col-md-6 border-end d-flex flex-column justify-content-between"> <div class="col-12 col-md-6 border-end d-flex flex-column justify-content-between">
@@ -75,7 +76,8 @@
</ui-switch> </ui-switch>
</div> </div>
<div *ngIf="showLimitToSpecificBitstreams" class="row mt-3"> @if (showLimitToSpecificBitstreams) {
<div class="row mt-3">
<fieldset class="col-12"> <fieldset class="col-12">
<legend class="h4"> <legend class="h4">
{{'access-control-limit-to-specific' | translate}} {{'access-control-limit-to-specific' | translate}}
@@ -97,20 +99,20 @@
<label class="form-check-label" for="processSelected"> <label class="form-check-label" for="processSelected">
{{ state.bitstream.selectedBitstreams.length }} {{ state.bitstream.selectedBitstreams.length }}
{{'access-control-bitstreams-selected' | translate}} {{'access-control-bitstreams-selected' | translate}}
@if (itemRD) {
<button <button
*ngIf="itemRD"
[attr.aria-label]="'access-control-bitstreams-select' | translate" [attr.aria-label]="'access-control-bitstreams-select' | translate"
[dsBtnDisabled]="!state.bitstream.toggleStatus || state.bitstream.changesLimit !== 'selected'" [dsBtnDisabled]="!state.bitstream.toggleStatus || state.bitstream.changesLimit !== 'selected'"
(click)="openSelectBitstreamsModal(itemRD.payload)" (click)="openSelectBitstreamsModal(itemRD.payload)"
class="btn btn-outline-dark border-0" type="button"> class="btn btn-outline-dark border-0" type="button">
<i class="fa fa-search"></i> <i class="fa fa-search"></i>
</button> </button>
}
</label> </label>
</div> </div>
</fieldset> </fieldset>
</div> </div>
}
</div> </div>
<fieldset class="row mt-3"> <fieldset class="row mt-3">
@@ -152,9 +154,12 @@
</div> </div>
</div> </div>
<hr *ngIf="showSubmit"> @if (showSubmit) {
<hr>
}
<div *ngIf="showSubmit" class="d-flex justify-content-end"> @if (showSubmit) {
<div class="d-flex justify-content-end">
<button class="btn btn-outline-primary me-3" (click)="reset()" type="button"> <button class="btn btn-outline-primary me-3" (click)="reset()" type="button">
{{ 'access-control-cancel' | translate }} {{ 'access-control-cancel' | translate }}
</button> </button>
@@ -164,6 +169,7 @@
{{ 'access-control-execute' | translate }} {{ 'access-control-execute' | translate }}
</button> </button>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,9 +7,9 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ng-container *ngIf="data$ | async as data"> @if (data$ | async; as data) {
@if (data.payload.page.length > 0) {
<ds-viewable-collection <ds-viewable-collection
*ngIf="data.payload.page.length > 0"
[config]="paginationConfig" [config]="paginationConfig"
[context]="context" [context]="context"
[objects]="data" [objects]="data"
@@ -18,13 +18,14 @@
[showPaginator]="true" [showPaginator]="true"
(pageChange)="loadForPage($event)"> (pageChange)="loadForPage($event)">
</ds-viewable-collection> </ds-viewable-collection>
}
<div *ngIf="data && data.payload.page.length === 0" @if (data && data.payload.page.length === 0) {
<div
class="alert alert-info w-100" role="alert"> class="alert alert-info w-100" role="alert">
{{'access-control-select-bitstreams-modal.no-items' | translate}} {{'access-control-select-bitstreams-modal.no-items' | translate}}
</div> </div>
}
</ng-container> }
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-outline-dark" <button type="button" class="btn btn-outline-dark"

View File

@@ -1,8 +1,12 @@
<div *ngIf="!dismissed" class="alert {{type}} alert-dismissible fade show w-100 p-3" role="alert" [@enterLeave]="animate"> @if (!dismissed) {
<span *ngIf="content" [innerHTML]="content | translate"></span> <div class="alert {{type}} alert-dismissible fade show w-100 p-3" role="alert" [@enterLeave]="animate">
@if (content) {
<span [innerHTML]="content | translate"></span>
}
<ng-content></ng-content> <ng-content></ng-content>
@if (dismissible) {
<button *ngIf="dismissible" type="button" class="btn-close" data-dismiss="alert" aria-label="Close" (click)="dismiss()"> <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close" (click)="dismiss()">
</button> </button>
}
</div> </div>
}

View File

@@ -1,5 +1,7 @@
<div class="navbar-nav me-auto" *ngIf="(isMobile$ | async) !== true; else mobileButtons" data-test="auth-nav"> @if ((isMobile$ | async) !== true) {
<div *ngIf="(isAuthenticated | async) !== true && (showAuth | async)" <div class="navbar-nav me-auto" data-test="auth-nav">
@if ((isAuthenticated | async) !== true && (showAuth | async)) {
<div
class="nav-item" class="nav-item"
(click)="$event.stopPropagation();"> (click)="$event.stopPropagation();">
<div ngbDropdown #loginDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown #loginDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
@@ -18,7 +20,9 @@
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="(isAuthenticated | async) && (showAuth | async)" class="nav-item"> }
@if ((isAuthenticated | async) && (showAuth | async)) {
<div class="nav-item">
<div ngbDropdown #loggedInDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown #loggedInDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="javascript:void(0);" <a href="javascript:void(0);"
role="menuitem" role="menuitem"
@@ -34,19 +38,24 @@
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
} @else {
<ng-template #mobileButtons>
<div data-test="auth-nav"> <div data-test="auth-nav">
<a *ngIf="(isAuthenticated | async) !== true" routerLink="/login" routerLinkActive="active" class="loginLink px-0.5" role="button"> @if ((isAuthenticated | async) !== true) {
<a routerLink="/login" routerLinkActive="active" class="loginLink px-0.5" role="button">
{{ 'nav.login' | translate }}<span class="sr-only">(current)</span> {{ 'nav.login' | translate }}<span class="sr-only">(current)</span>
</a> </a>
<a *ngIf="(isAuthenticated | async)" role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="logoutLink px-1"> }
@if ((isAuthenticated | async)) {
<a role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="logoutLink px-1">
<i class="fas fa-sign-out-alt fa-lg fa-fw"></i> <i class="fas fa-sign-out-alt fa-lg fa-fw"></i>
<span class="sr-only">(current)</span> <span class="sr-only">(current)</span>
</a> </a>
}
</div> </div>
</ng-template> }
<!-- Do not use ul/li in this menu as it breaks e2e accessibility tests --> <!-- Do not use ul/li in this menu as it breaks e2e accessibility tests -->

View File

@@ -1,4 +1,5 @@
<div *ngIf="searchField" class="mb-3 w-100 pe-2 ps-2 my-2"> @if (searchField) {
<div class="mb-3 w-100 pe-2 ps-2 my-2">
<input type="search" <input type="search"
class="form-control w-100" class="form-control w-100"
(click)="$event.stopPropagation();" (click)="$event.stopPropagation();"
@@ -6,6 +7,7 @@
[formControl]="searchField" [formControl]="searchField"
#searchFieldEl> #searchFieldEl>
</div> </div>
}
<div class="dropdown-divider m-0"></div> <div class="dropdown-divider m-0"></div>
<ul class="scrollable-menu p-0 m-0" <ul class="scrollable-menu p-0 m-0"
role="menu" role="menu"
@@ -18,27 +20,35 @@
[scrollWindow]="false" [scrollWindow]="false"
(scrolled)="onScrollDown()"> (scrolled)="onScrollDown()">
<li class="dropdown-item disabled" role="menuitem" *ngIf="searchListCollection?.length === 0 && (isLoading | async) !== true"> @if (searchListCollection?.length === 0 && (isLoading | async) !== true) {
<li class="dropdown-item disabled" role="menuitem">
{{'submission.sections.general.no-collection' | translate}} {{'submission.sections.general.no-collection' | translate}}
</li> </li>
<ng-container *ngIf="searchListCollection?.length > 0"> }
<li *ngFor="let listItem of searchListCollection" @if (searchListCollection?.length > 0) {
@for (listItem of searchListCollection; track listItem) {
<li
class="dropdown-item collection-item" class="dropdown-item collection-item"
role="menuitem" role="menuitem"
title="{{ listItem.collection.name }}" title="{{ listItem.collection.name }}"
(click)="onSelect(listItem)"> (click)="onSelect(listItem)">
<div class="list-unstyled mb-0"> <div class="list-unstyled mb-0">
<div class="list-item text-truncate text-secondary" *ngFor="let item of listItem.communities"> @for (item of listItem.communities; track item) {
<div class="list-item text-truncate text-secondary">
{{ item.name}} <i class="fa fa-level-down" aria-hidden="true"></i> {{ item.name}} <i class="fa fa-level-down" aria-hidden="true"></i>
</div> </div>
}
<div class="list-item text-truncate text-primary fw-bold">{{ listItem.collection.name}}</div> <div class="list-item text-truncate text-primary fw-bold">{{ listItem.collection.name}}</div>
</div> </div>
</li> </li>
</ng-container> }
<li *ngIf="(isLoading | async)"> }
@if ((isLoading | async)) {
<li>
<button class="dropdown-item disabled"> <button class="dropdown-item disabled">
<ds-loading message="{{'loading.default' | translate}}"> <ds-loading message="{{'loading.default' | translate}}">
</ds-loading> </ds-loading>
</button> </button>
</li> </li>
}
</ul> </ul>

View File

@@ -4,24 +4,30 @@
<label class="form-label">{{type.value + '.edit.logo.label' | translate}}</label> <label class="form-label">{{type.value + '.edit.logo.label' | translate}}</label>
</div> </div>
<ng-container *ngVar="(dso?.logo | async)?.payload as logo"> <ng-container *ngVar="(dso?.logo | async)?.payload as logo">
<div class="col-12 d-inline-block alert" id="logo-section" *ngIf="logo"> @if (logo) {
<div class="col-12 d-inline-block alert" id="logo-section">
<div class="row"> <div class="row">
<div class="col-8 d-inline-block"> <div class="col-8 d-inline-block">
<ds-comcol-page-logo [alternateText]="type.value + '.logo.alt'" [logo]="logo"></ds-comcol-page-logo> <ds-comcol-page-logo [alternateText]="type.value + '.logo.alt'" [logo]="logo"></ds-comcol-page-logo>
</div> </div>
<div class="col-4 d-inline-block"> <div class="col-4 d-inline-block">
<div *ngIf="logo" class="float-end"> @if (logo) {
<div class="float-end">
<button <button
(click)="confirmLogoDeleteWithModal()" (click)="confirmLogoDeleteWithModal()"
class="btn btn-danger" class="btn btn-danger"
type="button">{{ 'community.edit.logo.delete.title' | translate }} type="button">{{ 'community.edit.logo.delete.title' | translate }}
</button> </button>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="!logo" class="col-12 d-inline-block"> }
<ds-uploader *ngIf="initializedUploaderOptions | async" @if (!logo) {
<div class="col-12 d-inline-block">
@if (initializedUploaderOptions | async) {
<ds-uploader
[ariaLabel]="type.value + '.browse.logo'" [ariaLabel]="type.value + '.browse.logo'"
[dropMsg]="type.value + '.edit.logo.upload'" [dropMsg]="type.value + '.edit.logo.upload'"
[dropOverDocumentMsg]="type.value + '.edit.logo.upload'" [dropOverDocumentMsg]="type.value + '.edit.logo.upload'"
@@ -29,11 +35,14 @@
[uploadFilesOptions]="uploadFilesOptions" [uploadFilesOptions]="uploadFilesOptions"
(onCompleteItem)="onCompleteItem()" (onCompleteItem)="onCompleteItem()"
(onUploadError)="onUploadError()"></ds-uploader> (onUploadError)="onUploadError()"></ds-uploader>
}
</div> </div>
}
</ng-container> </ng-container>
</div> </div>
</div> </div>
<ds-form *ngIf="formModel" @if (formModel) {
<ds-form
[formId]="'comcol-form-id'" [formId]="'comcol-form-id'"
[formModel]="formModel" [formModel]="formModel"
[displayCancel]="false" [displayCancel]="false"
@@ -42,4 +51,5 @@
<i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type.value + '.edit.return' | translate }} <i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type.value + '.edit.return' | translate }}
</button> </button>
</ds-form> </ds-form>
}

View File

@@ -12,7 +12,8 @@
</div> </div>
<div class="pt-2"> <div class="pt-2">
<ul class="nav nav-tabs justify-content-start mb-2" role="tablist"> <ul class="nav nav-tabs justify-content-start mb-2" role="tablist">
<li *ngFor="let page of pages" class="nav-item" role="presentation"> @for (page of pages; track page) {
<li class="nav-item" role="presentation">
<a class="nav-link" role="tab" <a class="nav-link" role="tab"
[attr.aria-selected]="page === currentPage" [attr.aria-selected]="page === currentPage"
[ngClass]="{'active' : page === currentPage}" [ngClass]="{'active' : page === currentPage}"
@@ -21,15 +22,18 @@
{{ type + '.edit.tabs.' + page + '.head' | translate}} {{ type + '.edit.tabs.' + page + '.head' | translate}}
</a> </a>
</li> </li>
}
</ul> </ul>
<div class="tab-pane active"> <div class="tab-pane active">
<div class="mb-4"> <div class="mb-4">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
<div class="col-12 text-end custom-alignment"> <div class="col-12 text-end custom-alignment">
<a *ngIf="!hideReturnButton" [routerLink]="getPageUrl((dsoRD$ | async)?.payload)" class="btn btn-outline-secondary"> @if (!hideReturnButton) {
<a [routerLink]="getPageUrl((dsoRD$ | async)?.payload)" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type + '.edit.return' | translate }} <i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type + '.edit.return' | translate }}
</a> </a>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,9 +1,10 @@
<h2 class="comcol-browse-label">{{'browse.comcol.head' | translate}}</h2> <h2 class="comcol-browse-label">{{'browse.comcol.head' | translate}}</h2>
<nav *ngIf="(allOptions$ | async) as allOptions" class="comcol-browse mb-4" aria-label="Browse Community or Collection"> @if ((allOptions$ | async); as allOptions) {
<nav class="comcol-browse mb-4" aria-label="Browse Community or Collection">
<div class="d-none d-sm-block"> <div class="d-none d-sm-block">
<div class="list-group list-group-horizontal" role="tablist"> <div class="list-group list-group-horizontal" role="tablist">
<a *ngFor="let option of allOptions" @for (option of allOptions; track option) {
<a
[attr.aria-current]="(currentOption$ | async)?.id === option.id" [attr.aria-current]="(currentOption$ | async)?.id === option.id"
class="list-group-item" class="list-group-item"
role="tab" role="tab"
@@ -12,19 +13,22 @@
[class.active]="(currentOption$ | async)?.id === option.id"> [class.active]="(currentOption$ | async)?.id === option.id">
{{ option.label | translate }} {{ option.label | translate }}
</a> </a>
}
</div> </div>
</div> </div>
<div class="d-block d-sm-none"> <div class="d-block d-sm-none">
<select name="browse-type" <select name="browse-type"
class="form-select" class="form-select"
aria-label="Browse Community or Collection" aria-label="Browse Community or Collection"
(change)="onSelectChange($event)"> (change)="onSelectChange($event)">
<option *ngFor="let option of allOptions" @for (option of allOptions; track option) {
<option
[value]="option.id" [value]="option.id"
[attr.selected]="(currentOption$ | async)?.id === option.id ? 'selected' : null"> [attr.selected]="(currentOption$ | async)?.id === option.id ? 'selected' : null">
{{ option.label | translate }} {{ option.label | translate }}
</option> </option>
}
</select> </select>
</div> </div>
</nav> </nav>
}

View File

@@ -1,10 +1,22 @@
<div *ngIf="(this.submitted$ | async) !== true; else waiting"> @if ((this.submitted$ | async) !== true) {
<div *ngIf="this.canWithdraw; else reinstateHeader" class="modal-header"> <div>
@if (this.canWithdraw) {
<div class="modal-header">
{{ 'item.qa.withdrawn.modal.header' | translate }} {{ 'item.qa.withdrawn.modal.header' | translate }}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close"> <button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
</button> </button>
</div> </div>
} @else {
@if (!this.canWithdraw) {
<div class="modal-header">
{{'item.qa.reinstate.modal.header' | translate}}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
}
}
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="reason">{{ this.canWithdraw ? ('qa-withdrawn.create.modal.form.summary.label' | translate) <label for="reason">{{ this.canWithdraw ? ('qa-withdrawn.create.modal.form.summary.label' | translate)
@@ -35,21 +47,13 @@
</button> </button>
</div> </div>
</div> </div>
} @else {
<ng-template #waiting>
<div class="modal-header">{{'item.qa.withdrawn.modal.submitted.header' | translate}}</div> <div class="modal-header">{{'item.qa.withdrawn.modal.submitted.header' | translate}}</div>
<div class="modal-body"> <div class="modal-body">
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<ds-loading [showMessage]="false"></ds-loading> <ds-loading [showMessage]="false"></ds-loading>
</div> </div>
</div> </div>
</ng-template> }
<ng-template #reinstateHeader>
<div *ngIf="!this.canWithdraw" class="modal-header">
{{'item.qa.reinstate.modal.header' | translate}}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</ng-template>

View File

@@ -2,9 +2,11 @@
<div ngbDropdown class="btn-group" (openChange)="toggled.emit($event)"> <div ngbDropdown class="btn-group" (openChange)="toggled.emit($event)">
<span *ngIf="label" id="dsSelectMenuLabel" class="input-group-text"> @if (label) {
<span id="dsSelectMenuLabel" class="input-group-text">
{{ label | translate }} {{ label | translate }}
</span> </span>
}
<button aria-describedby="dsSelectMenuLabel" <button aria-describedby="dsSelectMenuLabel"
id="dsSelectMenuButton" id="dsSelectMenuButton"

View File

@@ -5,15 +5,22 @@
<i class="fas fa-{{section.icon}} fa-fw"></i> <i class="fas fa-{{section.icon}} fa-fw"></i>
</button> </button>
<ul ngbDropdownMenu class="dso-edit-menu-dropdown"> <ul ngbDropdownMenu class="dso-edit-menu-dropdown">
<li class="nav-item nav-link d-flex flex-row" *ngFor="let subSection of (subSections$ | async)"> @for (subSection of (subSections$ | async); track subSection) {
<div *ngIf="renderIcons$ | async" class="me-2"> <li class="nav-item nav-link d-flex flex-row">
<i *ngIf="subSection.icon; else spacer" class="fas fa-{{subSection.icon}} fa-fw"></i> @if (renderIcons$ | async) {
<ng-template #spacer><i class="fas fa-fw"></i></ng-template> <div class="me-2">
@if (subSection.icon) {
<i class="fas fa-{{subSection.icon}} fa-fw"></i>
} @else {
<i class="fas fa-fw"></i>
}
</div> </div>
}
<ng-container <ng-container
*ngComponentOutlet="(sectionMap$ | async).get(subSection.id).component; injector: (sectionMap$ | async).get(subSection.id).injector;"> *ngComponentOutlet="(sectionMap$ | async).get(subSection.id).component; injector: (sectionMap$ | async).get(subSection.id).injector;">
</ng-container> </ng-container>
</li> </li>
}
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,8 @@
<div class="dso-edit-menu d-flex"> <div class="dso-edit-menu d-flex">
<div *ngFor="let section of (sections | async)" class="ms-1"> @for (section of (sections | async); track section) {
<div class="ms-1">
<ng-container <ng-container
*ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container> *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
</div> </div>
}
</div> </div>

View File

@@ -15,12 +15,15 @@
[infiniteScrollContainer]="'#scrollable-menu-dso-selector-' + randomSeed" [infiniteScrollContainer]="'#scrollable-menu-dso-selector-' + randomSeed"
[fromRoot]="true" [fromRoot]="true"
(scrolled)="onScrollDown()"> (scrolled)="onScrollDown()">
<ng-container *ngIf="listEntries$ | async"> @if (listEntries$ | async) {
@if ((listEntries$ | async).length === 0) {
<button class="list-group-item list-group-item-action border-0 disabled" <button class="list-group-item list-group-item-action border-0 disabled"
*ngIf="(listEntries$ | async).length === 0"> >
{{'dso-selector.no-results' | translate: { type: typesString } }} {{'dso-selector.no-results' | translate: { type: typesString } }}
</button> </button>
<button *ngFor="let listEntry of (listEntries$ | async)" }
@for (listEntry of (listEntries$ | async); track listEntry) {
<button
class="list-group-item list-group-item-action border-0 list-entry" class="list-group-item list-group-item-action border-0 list-entry"
[ngClass]="{'bg-primary': listEntry['id'] === currentDSOId}" [ngClass]="{'bg-primary': listEntry['id'] === currentDSOId}"
title="{{ getName(listEntry) }}" title="{{ getName(listEntry) }}"
@@ -29,11 +32,14 @@
<ds-listable-object-component-loader [object]="listEntry" [viewMode]="viewMode" <ds-listable-object-component-loader [object]="listEntry" [viewMode]="viewMode"
[linkType]=linkTypes.None [context]="getContext(listEntry['id'])"></ds-listable-object-component-loader> [linkType]=linkTypes.None [context]="getContext(listEntry['id'])"></ds-listable-object-component-loader>
</button> </button>
</ng-container> }
<button *ngIf="loading" }
@if (loading) {
<button
title="{{'loading.default' | translate}}" title="{{'loading.default' | translate}}"
class="list-group-item list-group-item-action border-0 list-entry"> class="list-group-item list-group-item-action border-0 list-entry">
<ds-loading [showMessage]="false"></ds-loading> <ds-loading [showMessage]="false"></ds-loading>
</button> </button>
}
</div> </div>
</div> </div>

Some files were not shown because too many files have changed in this diff Show More