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

View File

@@ -41,14 +41,15 @@
</div>
</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
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && (searching$ | async) !== true"
[paginationOptions]="config"
[collectionSize]="(pageInfoState$ | async)?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">
<div class="table-responsive">
<table id="epeople" class="table table-striped table-hover table-bordered">
<thead>
@@ -60,7 +61,8 @@
</tr>
</thead>
<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}">
<td>{{epersonDto.eperson.id}}</td>
<td>{{ dsoNameService.getName(epersonDto.eperson) }}</td>
@@ -72,23 +74,28 @@
title="{{labelPrefix + 'table.edit.buttons.edit' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}">
<i class="fas fa-edit fa-fw"></i>
</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"
title="{{labelPrefix + 'table.edit.buttons.remove' | translate: { name: dsoNameService.getName(epersonDto.eperson) } }}">
<i class="fas fa-trash-alt fa-fw"></i>
</button>
}
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</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}}
</div>
}
</div>
</div>
</div>

View File

@@ -2,15 +2,13 @@
<div class="group-form row">
<div class="col-12">
<div *ngIf="activeEPerson$ | async; then editHeader; else createHeader"></div>
<ng-template #createHeader>
<h1 class="border-bottom pb-2">{{messagePrefix + '.create' | translate}}</h1>
</ng-template>
<ng-template #editHeader>
@if (activeEPerson$ | async) {
<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"
[formModel]="formModel"
@@ -24,39 +22,51 @@
<i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}
</button>
</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()">
<i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}}
</button>
</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}}
</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}}
</button>
}
</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}}
</button>
}
</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>
<ds-loading [showMessage]="false" *ngIf="groups$ | async | dsHasNoValue"></ds-loading>
@if (groups$ | async | dsHasNoValue) {
<ds-loading [showMessage]="false"></ds-loading>
}
@if ((groups$ | async)?.payload?.totalElements > 0) {
<ds-pagination
*ngIf="(groups$ | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[collectionSize]="(groups$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
(pageChange)="onPageChange($event)">
<div class="table-responsive">
<table id="groups" class="table table-striped table-hover table-bordered">
<thead>
@@ -67,7 +77,8 @@
</tr>
</thead>
<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">
<a (click)="groupsDataService.startEditingNewGroup(group)"
@@ -79,20 +90,23 @@
{{ dsoNameService.getName((group.object | async)?.payload) }}
</td>
</tr>
}
</tbody>
</table>
</div>
</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>
<button [routerLink]="[groupsDataService.getGroupRegistryRouterLink()]"
class="btn btn-primary">{{messagePrefix + '.goToGroups' | translate}}</button>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
</div>

View File

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

View File

@@ -1,10 +1,12 @@
<div class="container">
<h1 id="header">{{'admin.batch-import.page.header' | translate}}</h1>
<p>{{'admin.batch-import.page.help' | translate}}</p>
<p *ngIf="dso">
@if (dso) {
<p>
selected collection: <b>{{getDspaceObjectName()}}</b>&nbsp;
<a href="javascript:void(0)" (click)="removeDspaceObject()">{{'admin.batch-import.page.remove' | translate}}</a>
</p>
}
<p>
<button class="btn btn-primary" (click)="this.selectCollection();">{{'admin.metadata-import.page.button.select-collection' | translate}}</button>
</p>
@@ -30,18 +32,21 @@
</small>
@if (isUpload) {
<ds-file-dropzone-no-uploader
*ngIf="isUpload"
data-test="file-dropzone"
(onFileAdded)="setFile($event)"
[dropMessageLabel]="'admin.batch-import.page.dropMsg'"
[dropMessageLabelReplacement]="'admin.batch-import.page.dropMsgReplace'">
</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}}"
data-test="file-url-input" [(ngModel)]="fileURL">
</div>
}
<div class="space-children-mr">
<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>
</div>
<!-- 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>
<div>
<input formControlName="enabled" hidden id="enabled" name="enabled" type="checkbox">
@@ -13,6 +14,7 @@
</div>
</div>
</div>
}
<!-- In the Name section -->
<div class="mb-5">
<label for="name" class="font-weight-bold">{{ 'ldn-new-service.form.label.name' | translate }}</label>
@@ -22,9 +24,11 @@
id="name"
name="name"
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 }}
</div>
}
</div>
<!-- In the description section -->
@@ -45,9 +49,11 @@
id="url"
name="url"
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 }}
</div>
}
</div>
<div class="d-flex flex-column w-50">
@@ -61,9 +67,11 @@
step=".01"
class="form-control"
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 }}
</div>
}
</div>
</div>
</div>
@@ -85,9 +93,11 @@
name="upperIp"
type="text">
</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 }}
</div>
}
<div class="text-muted">
{{ 'ldn-new-service.form.hint.ipRange' | translate }}
</div>
@@ -102,43 +112,50 @@
id="ldnUrl"
name="ldnUrl"
type="text">
<div *ngIf="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched" >
<div *ngIf="formModel.get('ldnUrl').errors['required']" class="error-text">
@if (formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched) {
<div >
@if (formModel.get('ldnUrl').errors['required']) {
<div class="error-text">
{{ 'ldn-new-service.form.error.ldnurl' | translate }}
</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 }}
</div>
}
</div>
}
</div>
<!-- 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">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label>
</div>
<ng-container *ngIf="formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern">
@if (formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern) {
<div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div>
<div class="col-sm-1">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
</div>
</ng-container>
}
<div class="col-sm-2">
</div>
</div>
}
<!-- In the Inbound Patterns section -->
<div *ngIf="areControlsInitialized">
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index"
@if (areControlsInitialized) {
<div>
@for (patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; track patternGroup; let i = $index) {
<div
[class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)"
formGroupName="notifyServiceInboundPatterns">
<ng-container [formGroupName]="i">
<div class="row mb-1 align-items-center">
<div class="col">
<div #inboundPatternDropdown="ngbDropdown" class="w-80" display="dynamic"
@@ -162,23 +179,22 @@
class="dropdown-menu dropdown-menu-top w-100 "
ngbDropdownMenu>
<div class="scrollable-menu" role="listbox">
@for (pattern of inboundPatterns; track pattern; let internalIndex = $index) {
<button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of inboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
<div>{{ 'ldn-service.form.pattern.' + pattern + '.label' | translate }}</div>
</button>
}
</div>
</div>
</div>
</div>
</div>
<div class="col">
<ng-container
*ngIf="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern">
@if (formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern) {
<div #inboundItemfilterDropdown="ngbDropdown" class="w-100" id="constraint{{i}}" ngbDropdown
placement="top-start">
<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">
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button>
@for (constraint of (itemFiltersRD$ | async)?.payload?.page; track constraint; let internalIndex = $index) {
<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"
ngbDropdownItem
type="button">
<div>{{ constraint.id + '.label' | translate }}</div>
</button>
}
</div>
</div>
</div>
</div>
</ng-container>
}
</div>
<div
[style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern ? 'visible' : 'hidden'"
class="col-sm-1">
@@ -236,8 +252,6 @@
<div class="slider"></div>
</div>
</div>
<div class="col-sm-2">
<div class="btn-group">
<button (click)="markForInboundPatternDeletion(i)" class="btn btn-outline-dark trash-button"
@@ -245,21 +259,22 @@
type="button">
<i class="fas fa-trash"></i>
</button>
@if (markedForDeletionInboundPattern.includes(i)) {
<button (click)="unmarkForInboundPatternDeletion(i)"
*ngIf="markedForDeletionInboundPattern.includes(i)"
[title]="'ldn-service-button-unmark-inbound-deletion' | translate"
class="btn btn-warning "
type="button">
<i class="fas fa-undo"></i>
</button>
}
</div>
</div>
</div>
</ng-container>
</div>
}
</div>
}
<span (click)="addInboundPattern()"
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
@@ -280,8 +295,12 @@
</div>
<ng-template #confirmModal>
<div class="modal-header">
<h4 *ngIf="!isNewService">{{'service.overview.edit.modal' | translate }}</h4>
<h4 *ngIf="isNewService">{{'service.overview.create.modal' | translate }}</h4>
@if (!isNewService) {
<h4>{{'service.overview.edit.modal' | translate }}</h4>
}
@if (isNewService) {
<h4>{{'service.overview.create.modal' | translate }}</h4>
}
<button (click)="closeModal()" aria-label="Close"
class="close" type="button">
<span aria-hidden="true">×</span>
@@ -289,23 +308,32 @@
</div>
<div class="modal-body">
<div *ngIf="!isNewService">
@if (!isNewService) {
<div>
{{ 'service.overview.edit.body' | translate }}
</div>
<span *ngIf="isNewService">
}
@if (isNewService) {
<span>
{{ 'service.overview.create.body' | translate }}
</span>
}
</div>
<div class="modal-footer">
<div *ngIf="!isNewService">
@if (!isNewService) {
<div>
<button (click)="closeModal()" class="btn btn-outline-secondary me-2"
id="delete-confirm-edit">{{ 'service.detail.return' | translate }}
</button>
<button *ngIf="!isNewService" (click)="patchService()"
@if (!isNewService) {
<button (click)="patchService()"
class="btn btn-primary">{{ 'service.detail.update' | translate }}
</button>
}
</div>
<div *ngIf="isNewService">
}
@if (isNewService) {
<div>
<button (click)="closeModal()" class="btn btn-outline-secondary me-2 "
id="delete-confirm-new">{{ 'service.refuse.create' | translate }}
</button>
@@ -313,6 +341,7 @@
class="btn btn-primary">{{ 'service.confirm.create' | translate }}
</button>
</div>
}
</div>
</ng-template>

View File

@@ -6,7 +6,8 @@
<button class="btn btn-success" routerLink="/admin/ldn/services/new"><i
class="fas fa-plus pe-2"></i>{{ 'process.overview.new' | translate }}</button>
</div>
<ds-pagination *ngIf="(ldnServicesRD$ | async)?.payload?.totalElements > 0"
@if ((ldnServicesRD$ | async)?.payload?.totalElements > 0) {
<ds-pagination
[collectionSize]="(ldnServicesRD$ | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
@@ -22,7 +23,8 @@
</tr>
</thead>
<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>
<ds-truncatable [id]="ldnService.id">
@@ -57,10 +59,12 @@
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</ds-pagination>
}
</div>
<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-md-9">
<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}}
<span> ×</span>
</button>
}
</div>
<ds-search-labels [inPlaceSearch]="true"></ds-search-labels>
</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>
@if ((bitstreamFormats$ | async)?.payload?.totalElements > 0) {
<ds-pagination
*ngIf="(bitstreamFormats$ | async)?.payload?.totalElements > 0"
[paginationOptions]="pageConfig"
[collectionSize]="(bitstreamFormats$ | async)?.payload?.totalElements"
[hideGear]="false"
@@ -26,7 +26,8 @@
</tr>
</thead>
<tbody>
<tr *ngFor="let bitstreamFormat of (bitstreamFormats$ | async)?.payload?.page">
@for (bitstreamFormat of (bitstreamFormats$ | async)?.payload?.page; track bitstreamFormat) {
<tr>
<td>
<label class="form-label mb-0">
<input type="checkbox"
@@ -39,20 +40,30 @@
</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.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>
</tr>
}
</tbody>
</table>
</div>
</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}}
</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>
<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>
@if ((bitstreamFormats$ | async)?.payload?.page?.length > 0) {
<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>

View File

@@ -8,13 +8,12 @@
<ds-metadata-schema-form (submitForm)="forceUpdateSchemas()"></ds-metadata-schema-form>
@if ((metadataSchemas | async)?.payload?.totalElements > 0) {
<ds-pagination
*ngIf="(metadataSchemas | async)?.payload?.totalElements > 0"
[paginationOptions]="config"
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
[hideGear]="true"
[hidePagerWhenSinglePage]="true">
<div class="table-responsive">
<table id="metadata-schemas" class="table table-striped table-hover">
<thead>
@@ -26,7 +25,8 @@
</tr>
</thead>
<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}">
<td>
<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.prefix}}</a></td>
</tr>
}
</tbody>
</table>
</div>
</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}}
</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>

View File

@@ -13,8 +13,8 @@
<h2>{{'admin.registries.schema.fields.head' | translate}}</h2>
<ng-container *ngVar="(metadataFields$ | async)?.payload as fields">
@if (fields?.totalElements > 0) {
<ds-pagination
*ngIf="fields?.totalElements > 0"
[paginationOptions]="config"
[collectionSize]="fields?.totalElements"
[hideGear]="false"
@@ -30,7 +30,8 @@
</tr>
</thead>
<tbody>
<tr *ngFor="let field of fields?.page"
@for (field of fields?.page; track field) {
<tr
[ngClass]="{'table-primary' : (activeField$ | async)?.id === field.id}">
<td *ngVar="(selectedMetadataFieldIDs$ | async)?.includes(field.id) as selected">
<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)">{{field.scopeNote}}</td>
</tr>
}
</tbody>
</table>
</div>
</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}}
</div>
}
<div>
<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>
</ng-container>

View File

@@ -9,11 +9,15 @@
<span class="col-12">&nbsp;</span>
</ng-container>
</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>
<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>
</div>
}
</ng-container>
</fieldset>
}

View File

@@ -13,8 +13,10 @@
<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>
</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>
}
</div>
</div>
<div class="row">
@@ -22,7 +24,9 @@
<label for="supervisionGroup" class="form-label">{{'supervision-group-selector.select.group.label' | translate}}</label>
<ng-container class="mb-3">
<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>
<ds-eperson-group-list [isListOfEPerson]="false"
(select)="updateGroupObjectSelected($event)"></ds-eperson-group-list>

View File

@@ -1,15 +1,19 @@
<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>
<span>{{'workflow-item.search.result.list.element.supervised-by' | translate}} </span>
</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"
(click)="$event.preventDefault(); $event.stopImmediatePropagation(); deleteSupervisionOrder(supervisionOrder)" aria-label="Close">
{{ dsoNameService.getName(supervisionOrder.group) }}
<span aria-hidden="true"> ×</span>
</a>
}
</div>
</div>
}
</ng-container>

View File

@@ -7,6 +7,8 @@
</div>
<ul #buttons class="list-group list-group-flush">
<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>
</ul>

View File

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

View File

@@ -1,10 +1,12 @@
<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"
[viewMode]="viewModes.ListElement"
[index]="index"
[linkType]="linkType"
[listID]="listID"></ds-listable-object-component-loader>
}
<ds-workspace-item-admin-workflow-actions-element [small]="false"
[supervisionOrderList]="supervisionOrder$ | async"

View File

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

View File

@@ -10,8 +10,12 @@
<i class="fas fa-times"></i> {{'collection.delete.cancel' | translate}}
</button>
<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>
<span *ngIf="(processing$ | async) !== true"><i class="fas fa-trash"></i> {{'collection.delete.confirm' | translate}}</span>
@if (processing$ | async) {
<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>
</div>
</div>

View File

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

View File

@@ -1,5 +1,6 @@
<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>
<div>
<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>{{contentSource?.message ? contentSource?.message: 'collection.source.controls.harvest.no-information'|translate }}</span>
</div>
<button *ngIf="(testConfigRunning$ |async) !== true" class="btn btn-secondary"
@if ((testConfigRunning$ |async) !== true) {
<button class="btn btn-secondary"
[dsBtnDisabled]="!(isEnabled)"
(click)="testConfiguration(contentSource)">
<span>{{'collection.source.controls.test.submit' | translate}}</span>
</button>
<button *ngIf="(testConfigRunning$ |async)" class="btn btn-secondary"
}
@if ((testConfigRunning$ |async)) {
<button class="btn btn-secondary"
[dsBtnDisabled]="true">
<span class="spinner-border spinner-border-sm spinner-button" role="status" aria-hidden="true"></span>
<span>{{'collection.source.controls.test.running' | translate}}</span>
</button>
<button *ngIf="(importRunning$ |async) !== true" class="btn btn-primary"
}
@if ((importRunning$ |async) !== true) {
<button class="btn btn-primary"
[dsBtnDisabled]="!(isEnabled)"
(click)="importNow()">
<span class="d-none d-sm-inline">{{'collection.source.controls.import.submit' | translate}}</span>
</button>
<button *ngIf="(importRunning$ |async)" class="btn btn-primary"
}
@if ((importRunning$ |async)) {
<button class="btn btn-primary"
[dsBtnDisabled]="true">
<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>
</button>
<button *ngIf="(reImportRunning$ |async) !== true" class="btn btn-primary"
}
@if ((reImportRunning$ |async) !== true) {
<button class="btn btn-primary"
[dsBtnDisabled]="!(isEnabled)"
(click)="resetAndReimport()">
<span class="d-none d-sm-inline">&nbsp;{{'collection.source.controls.reset.submit' | translate}}</span>
</button>
<button *ngIf="(reImportRunning$ |async)" class="btn btn-primary"
}
@if ((reImportRunning$ |async)) {
<button class="btn btn-primary"
[dsBtnDisabled]="true">
<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>
</button>
}
</div>
}
</div>

View File

@@ -1,16 +1,20 @@
<div class="container-fluid">
<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"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span>
</button>
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
}
@if (isReinstatable$ | async) {
<button class="btn btn-warning"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span>
</button>
}
<button class="btn btn-primary"
[dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
(click)="onSubmit()"><i
@@ -19,17 +23,24 @@
</button>
</div>
<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"
[checked]="(contentSource?.harvestType !== harvestTypeNone)" (change)="changeExternalSource()">
<label class="form-check-label"
for="externalSourceCheck">{{ 'collection.edit.tabs.source.external' | translate }}</label>
</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 class="row">
<ds-form *ngIf="formGroup && contentSource && (contentSource?.harvestType !== harvestTypeNone)"
@if (formGroup && contentSource && (contentSource?.harvestType !== harvestTypeNone)) {
<ds-form
[formId]="'collection-source-form-id'"
[formGroup]="formGroup"
[formModel]="formModel"
@@ -39,22 +50,28 @@
(dfChange)="onChange($event)"
(submitForm)="onSubmit()"
(cancel)="onCancel()"></ds-form>
}
</div>
<div class="container mt-2" *ngIf="(contentSource?.harvestType !== harvestTypeNone)">
@if ((contentSource?.harvestType !== harvestTypeNone)) {
<div class="container mt-2">
<div class="row">
<div class="col-12">
<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"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.discard-button" | translate}}</span>
</button>
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
}
@if (isReinstatable$ | async) {
<button class="btn btn-warning"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.metadata.reinstate-button" | translate}}</span>
</button>
}
<button class="btn btn-primary"
[dsBtnDisabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
(click)="onSubmit()"><i
@@ -65,6 +82,7 @@
</div>
</div>
</div>
}
<ds-collection-source-controls
[isEnabled]="(hasChanges$ | async) !== true"
[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">
<!-- This is the tree node template for show more node -->
<cdk-tree-node *cdkTreeNodeDef="let node; when: isShowMore" cdkTreeNodePadding
@@ -8,11 +10,15 @@
<span class="fa fa-chevron-right"></span>
</span>
<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">
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
</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 class="text-muted" cdkTreeNodePadding>
@@ -24,7 +30,8 @@
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding
class="example-tree-node expandable-node">
<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) }"
(click)="toggleExpanded(node)"
data-test="expand-button">
@@ -32,21 +39,27 @@
aria-hidden="true"></span>
<span class="sr-only">{{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }}</span>
</button>
}
<!--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>
}
<div class="d-flex flex-row">
<span class="d-flex align-middle my-auto">
<a [routerLink]="node.route" class="lead">{{ dsoNameService.getName(node.payload) }}</a>
<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>
</div>
</div>
<ds-truncatable [id]="node.id">
<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 class="fa fa-chevron-right"></span>
</span>
@@ -54,15 +67,18 @@
<span>{{node.payload.shortDescription}}</span>
</ds-truncatable-part>
</div>
}
</div>
</ds-truncatable>
<div class="d-flex" *ngIf="node===loadingNode && dataSource.loading$ | async"
@if (node===loadingNode && dataSource.loading$ | async) {
<div class="d-flex"
cdkTreeNodePadding>
<span aria-hidden="true" class="btn btn-default invisible">
<span class="fa fa-chevron-right"></span>
</span>
<ds-loading class="ds-themed-loading"></ds-loading>
</div>
}
</cdk-tree-node>
<!-- 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
@@ -77,7 +93,8 @@
</div>
<ds-truncatable [id]="node.id">
<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 class="fa fa-chevron-right"></span>
</span>
@@ -85,6 +102,7 @@
<span>{{node.payload.shortDescription}}</span>
</ds-truncatable-part>
</div>
}
</div>
</ds-truncatable>
</cdk-tree-node>

View File

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

View File

@@ -10,8 +10,12 @@
<i class="fas fa-times" aria-hidden="true"></i> {{'community.delete.cancel' | translate}}
</button>
<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>
<span *ngIf="(processing$ | async) !== true"><i class="fas fa-trash" aria-hidden="true"></i> {{'community.delete.confirm' | translate}}</span>
@if (processing$ | async) {
<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>
</div>
</div>

View File

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

View File

@@ -4,16 +4,20 @@
<div class="col-12 col-sm-6">
<label class="fw-bold form-label" for="task">{{'curation.form.task-select.label' |translate }}</label>
<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 }}
</option>
}
</select>
</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>
<input id="handle" class="form-control" formControlName="handle">
<small class="text-muted">{{'curation.form.handle.hint' |translate }}</small>
</div>
}
</div>
<button class="btn btn-default btn-primary" type="submit">{{'curation.form.submit' |translate }}</button>
</div>

View File

@@ -2,28 +2,39 @@
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 }">
<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>
<textarea class="form-control" rows="5" *ngIf="mdValue.editing && !mdRepresentation && ((isAuthorityControlled() | async) !== true || (enabledFreeTextEditing && (isSuggesterVocabulary() | async) !== true))" [(ngModel)]="mdValue.newValue.value"
@if (!mdValue.editing && !mdRepresentation) {
<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"
[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"
[group]="group"
[model]="getModel()"
(change)="onChangeAuthorityField($event)">
</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"
[model]="getModel()"
(change)="onChangeAuthorityField($event)">
</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"
(click)="toggleFreeTextEdition()">
<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 }}
</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" >
<i dsAuthorityConfidenceState
class="fas fa-fw p-0"
@@ -34,7 +45,9 @@
{{ dsoType + '.edit.metadata.authority.label' | translate }} {{ mdValue.newValue.authority }}
</span>
</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">
<i dsAuthorityConfidenceState
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"
[attr.aria-label]="(dsoType + '.edit.metadata.edit.authority.key') | translate"
(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"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.open-authority-edition' | translate }}"
(click)="onChangeEditingAuthorityStatus(true)">
<i class="fas fa-lock fa-fw"></i>
</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"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.close-authority-edition' | translate }}"
(click)="onChangeEditingAuthorityStatus(false)">
<i class="fas fa-lock-open fa-fw"></i>
</button>
}
</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>
<ds-type-badge [object]="mdRepresentation"></ds-type-badge>
</div>
}
</div>
<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>
<input class="form-control" type="text" *ngIf="mdValue.editing" [(ngModel)]="mdValue.newValue.language"
@if (!mdValue.editing) {
<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"
[dsDebounce]="300" (onDebounce)="confirm.emit(false)" />
}
</div>
<div class="text-center ds-flex-cell ds-edit-cell" role="cell">
<div class="btn-group">
<div class="edit-field">
<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"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.edit' | translate }}"
[dsBtnDisabled]="isVirtual || mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE || (saving$ | async)" (click)="edit.emit()">
<i class="fas fa-edit fa-fw"></i>
</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"
ngbTooltip="{{ dsoType + '.edit.metadata.edit.buttons.confirm' | translate }}"
[dsBtnDisabled]="isVirtual || (saving$ | async)" (click)="confirm.emit(true)">
<i class="fas fa-check fa-fw"></i>
</button>
}
<button class="btn btn-outline-danger btn-sm" data-test="metadata-remove-btn"
[title]="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">
<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"
@@ -6,30 +7,34 @@
(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>
</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"
[title]="dsoType + '.edit.metadata.reinstate-button' | translate"
(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>
</button>
}
<button class="btn btn-primary ms-1" id="dso-save-btn" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate"
[title]="dsoType + '.edit.metadata.save-button' | translate"
(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>
</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"
[title]="dsoType + '.edit.metadata.discard-button' | translate"
[dsBtnDisabled]="!hasChanges || (saving$ | async)"
(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>
</button>
}
</div>
<div role="table" [attr.aria-label]="'item.edit.head' | translate">
<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">
<ds-metadata-field-selector [dsoType]="dsoType"
[(mdField)]="newMdField"
@@ -52,13 +57,17 @@
</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">
<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()">
{{ dsoType + '.edit.metadata.reset-order-button' | translate }}
</div>
}
</div>
<ds-dso-edit-metadata-field-values class="flex-grow-1" role="cell"
[dso]="dso"
@@ -70,33 +79,42 @@
(valueSaved)="onValueSaved()">
</ds-dso-edit-metadata-field-values>
</div>
}
</div>
<div *ngIf="isEmpty && !form.newValue">
@if (isEmpty && !form.newValue) {
<div>
<ds-alert [content]="dsoType + '.edit.metadata.empty'" [type]="AlertTypeEnum.Info"></ds-alert>
</div>
}
<div class="button-row bottom d-inline-block w-100">
<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"
[title]="dsoType + '.edit.metadata.reinstate-button' | translate"
(click)="reinstate()">
<i class="fas fa-undo-alt" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.reinstate-button' | translate }}
</button>
}
<button class="btn btn-primary" [dsBtnDisabled]="!hasChanges || (saving$ | async)"
[attr.aria-label]="dsoType + '.edit.metadata.save-button' | translate"
[title]="dsoType + '.edit.metadata.save-button' | translate"
(click)="submit()">
<i class="fas fa-save" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.save-button' | translate }}
</button>
<button class="btn btn-danger" *ngIf="!isReinstatable"
@if (!isReinstatable) {
<button class="btn btn-danger"
[attr.aria-label]="dsoType + '.edit.metadata.discard-button' | translate"
[title]="dsoType + '.edit.metadata.discard-button' | translate"
[dsBtnDisabled]="!hasChanges || (saving$ | async)"
(click)="discard()">
<i class="fas fa-times" aria-hidden="true"></i> {{ dsoType + '.edit.metadata.discard-button' | translate }}
</button>
}
</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>-->
<!-- </div>-->
<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>
}
<div *ngIf="!useNameVariants" class="lead" [innerHTML]="dsoTitle"></div>
@if (!useNameVariants) {
<div class="lead" [innerHTML]="dsoTitle"></div>
}
<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">
<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 *ngIf="dso.allMetadata('organization.address.addressCountry').length > 0"
}
@if (dso.allMetadata('organization.address.addressCountry').length > 0) {
<span
class="item-list-address-country">
<span [innerHTML]="firstMetadataValue(['organization.address.addressCountry'])"></span>
</span>
}
</span>
</div>
</div>

View File

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

View File

@@ -11,13 +11,15 @@
<ds-context-help-toggle></ds-context-help-toggle>
<ds-auth-nav-menu></ds-auth-nav-menu>
<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()"
aria-controls="collapsingNav"
aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate">
<span class="fas fa-bars fa-fw toggler-icon" aria-hidden="true"></span>
</button>
</div>
}
</nav>
</div>
</div>

View File

@@ -1,13 +1,19 @@
<div *ngFor="let entry of healthInfoComponent | dsObjNgFor" data-test="collapse">
<div *ngIf="entry && !isPlainProperty(entry.value)" class="mb-3 border-bottom">
@for (entry of healthInfoComponent | dsObjNgFor; track entry) {
<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()">
<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'">
{{ entry.key | titlecase }}
</button>
<div class="d-flex my-auto">
<span *ngIf="collapse.collapsed" class="fas fa-chevron-down"></span>
<span *ngIf="!collapse.collapsed" class="fas fa-chevron-up"></span>
@if (collapse.collapsed) {
<span class="fas fa-chevron-down"></span>
}
@if (!collapse.collapsed) {
<span class="fas fa-chevron-up"></span>
}
</div>
</div>
<div #collapse="ngbCollapse" [id]="'health-info-component-' + entry.key + '-content'" [ngbCollapse]="isCollapsed">
@@ -21,7 +27,9 @@
</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>
</ng-container>
}
</div>
}

View File

@@ -1,6 +1,7 @@
<ng-container *ngIf="healthInfoResponse">
@if (healthInfoResponse) {
<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>
<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)"
@@ -18,5 +19,6 @@
</ds-health-info-component>
</ng-template>
</ngb-panel>
}
</ngb-accordion>
</ng-container>
}

View File

@@ -1,13 +1,18 @@
<ng-container *ngIf="healthComponent?.components">
<div *ngFor="let entry of healthComponent?.components | dsObjNgFor" class="mb-3 border-bottom" data-test="collapse">
@if (healthComponent?.components) {
@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()">
<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'">
{{ entry.key | titlecase }}
</button>
<div class="d-flex my-auto">
<span *ngIf="collapse.collapsed" class="fas fa-chevron-down"></span>
<span *ngIf="!collapse.collapsed" class="fas fa-chevron-up"></span>
@if (collapse.collapsed) {
<span class="fas fa-chevron-down"></span>
}
@if (!collapse.collapsed) {
<span class="fas fa-chevron-up"></span>
}
</div>
</div>
<div #collapse="ngbCollapse" [id]="'health-component-' + entry.key + 'content'" [ngbCollapse]="isCollapsed">
@@ -19,12 +24,15 @@
</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>
</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>
</ng-container>
}

View File

@@ -3,7 +3,8 @@
<ds-health-status [status]="healthResponse.status" class="d-inline-flex"></ds-health-status>
</p>
<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>
<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)"
@@ -21,4 +22,5 @@
</ds-health-component>
</ng-template>
</ngb-panel>
}
</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"
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"
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"
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">
<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>
<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>
</div>
}
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-start ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
</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>
}
</ng-container>

View File

@@ -1,13 +1,19 @@
<div class="container">
<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>
<a [routerLink]="getBitstreamLink()">{{'bitstream-request-a-copy.alert.canDownload2'| translate}}</a>
</div>
}
<div>
<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>
<p *ngIf="allfiles.value === 'true'">{{'bitstream-request-a-copy.intro.bitstream.all' | translate}}</p>
@if (bitstream !== undefined && allfiles.value === 'false') {
<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>
<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>
<input [className]="(name.invalid) && (name.dirty || name.touched) ? 'form-control is-invalid' :'form-control'"
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">
<span *ngIf="name.errors && name.errors.required">
@if (name.errors && name.errors.required) {
<span>
{{ 'bitstream-request-a-copy.name.error' | translate }}
</span>
}
</div>
}
</div>
</div>
<div class="row mb-4">
@@ -32,12 +42,16 @@
<input
[className]="(email.invalid) && (email.dirty || email.touched) ? 'form-control is-invalid' :'form-control'"
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">
<span *ngIf="email.errors">
@if (email.errors) {
<span>
{{ 'bitstream-request-a-copy.email.error' | translate }}
</span>
}
</div>
}
<small class="text-muted ds-hint">{{'bitstream-request-a-copy.email.hint' |translate}}</small>
</div>
</div>

View File

@@ -1,13 +1,15 @@
<div class="container">
<ng-container *ngIf="bundles">
@if (bundles) {
<div class="row">
<div class="col-12 mb-2">
<h1>{{'item.bitstreams.upload.title' | translate}}</h1>
<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>{{ dsoNameService.getName(item) }}</span>
</div>
}
</ng-container>
</div>
<div class="col-12">
@@ -24,18 +26,22 @@
(click)="f.open()"
ngDefaultControl>
</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 }}
</button>
<ds-uploader class="w-100" *ngIf="selectedBundleId"
}
@if (selectedBundleId) {
<ds-uploader class="w-100"
[dropMsg]="'item.bitstreams.upload.drop-message'"
[dropOverDocumentMsg]="'item.bitstreams.upload.drop-message'"
[enableDragOverDocument]="true"
[uploadFilesOptions]="uploadFilesOptions"
(onCompleteItem)="onCompleteItem($event)"
(onUploadError)="onUploadError()"></ds-uploader>
}
<button class="btn btn-outline-secondary" (click)="onCancel()">{{'item.bitstreams.upload.cancel' | translate}}</button>
</div>
</div>
</ng-container>
}
</div>

View File

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

View File

@@ -10,68 +10,88 @@
class="fas fa-upload"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.upload-button" | translate}}</span>
</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"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button>
}
<button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i
class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</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"
[dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
</button>
}
</div>
<div *ngIf="item && bundles?.length > 0" class="mt-4 table-border scrollable-table" [ngClass]="{'disabled-overlay': (isProcessingMoveRequest | async)}">
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles; first as isFirst"
@if (item && bundles?.length > 0) {
<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"
[item]="item"
[columnSizes]="columnSizes"
[isFirstTable]="isFirst"
aria-describedby="reorder-description">
</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>
</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">
{{'item.edit.bitstreams.empty' | translate}}
</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="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"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button>
}
<button class="btn btn-primary" [dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i
class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</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"
[dsBtnDisabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
</button>
}
</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>
<ds-pagination *ngIf="(bitstreamsRD$ | async)?.payload as bitstreamsList"
@if ((bitstreamsRD$ | async)?.payload; as bitstreamsList) {
<ds-pagination
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
[hidePaginationDetail]="true"
@@ -9,8 +10,7 @@
[retainScrollPosition]="true"
[ngbTooltip]="'item.edit.bitstreams.bundle.tooltip' | translate" placement="bottom"
[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"
[attr.aria-label]="'item.edit.bitstreams.bundle.table.aria-label' | translate: { bundle: bundleName } ">
<thead [class.visually-hidden]="!isFirstTable">
@@ -29,14 +29,12 @@
</th>
</tr>
</thead>
<tbody cdkDropList (cdkDropListDropped)="drop($event)">
<tr class="bundle-row">
<th id="{{ bundleName }}" class="span" colspan="3" scope="colgroup">
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }}
</th>
<td class="text-center">
<div class="btn-group">
<button [routerLink]="[itemPageRoute, 'bitstreams', 'new']"
[queryParams]="{bundle: bundle.id}"
@@ -53,33 +51,32 @@
aria-expanded="false">
<i class="fas fa-cog" aria-hidden="true"></i>
</button>
<ul id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" role="menu"
ngbDropdownMenu>
<li role="menuitem">
<span class="dropdown-header" id="pagination-control_results-per-page"
role="heading">{{ 'pagination.results-per-page' | translate}}</span>
<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)">
<button (click)="doPageSizeChange(size)" class="dropdown-item">
<i [ngClass]="{'invisible': size !== (pageSize$ | async) }" class="fas fa-check"
aria-hidden="true"></i> {{size}}
</button>
</li>
}
</ul>
</li>
</ul>
</div>
</div>
</td>
</tr>
<ng-container *ngFor="let entry of (tableEntries$ | async)">
<tr *ngIf="updates[entry.id] as update" [ngClass]="getRowClass(update, entry)" class="bitstream-row" cdkDrag
@for (entry of (tableEntries$ | async); track entry) {
@if (updates[entry.id]; as update) {
<tr [ngClass]="getRowClass(update, entry)" class="bitstream-row" cdkDrag
(cdkDragStarted)="dragStart()" (cdkDragEnded)="dragEnd()">
<th class="bitstream-name row-element {{ columnSizes.columns[0].buildClasses() }}"
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
@@ -129,12 +126,12 @@
</div>
</td>
</tr>
</ng-container>
}
}
</tbody>
</table>
</ng-container>
}
</ds-pagination>
}
</ng-template>

View File

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

View File

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

View File

@@ -4,14 +4,18 @@
</span>
</div>
<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">
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</button>
</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">
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</button>
</span>
}
</div>

View File

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

View File

@@ -6,7 +6,7 @@
</button>
</h2>
<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">
<ds-pagination
[paginationOptions]="paginationConfig"
@@ -14,7 +14,8 @@
[hideGear]="true"
[hidePagerWhenSinglePage]="true">
<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"
[fieldUpdate]="updateValue || {}"
[url]="url"
@@ -25,10 +26,15 @@
'alert-danger': updateValue.changeType === 2
}">
</ds-edit-relationship>
}
</div>
</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>
<ds-loading *ngIf="loading$ | async"></ds-loading>
}
@if (loading$ | async) {
<ds-loading></ds-loading>
}
</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">
<ds-listable-object-component-loader
[object]="relatedItem$ | async"
@@ -22,6 +23,7 @@
</div>
</div>
</div>
}
<ng-template #virtualMetadataModal>
<ds-virtual-metadata
[relationshipId]="relationship.id"

View File

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

View File

@@ -4,7 +4,7 @@
</button>
</div>
<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"
(click)="setSelectedVirtualMetadataItem(itemDTO.item, !selected)"
class="item d-flex flex-row">
@@ -16,7 +16,8 @@
<div class="flex-column">
<ds-listable-object-component-loader [object]="itemDTO.item">
</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">
{{metadata.metadataField}}
</div>
@@ -24,9 +25,10 @@
{{metadata.metadataValue.value}}
</div>
</div>
}
</div>
</div>
</ng-container>
}
<div class="d-flex flex-row-reverse m-2">
<button class="btn btn-primary save"
(click)="save.emit()">

View File

@@ -1,44 +1,60 @@
<div class="container" *ngVar="(itemRD$ | async) as itemRD">
<div class="item-page" *ngIf="itemRD?.hasSucceeded" @fadeInOut>
<div *ngIf="itemRD?.payload as item">
@if (itemRD?.hasSucceeded) {
<div class="item-page" @fadeInOut>
@if (itemRD?.payload; as item) {
<div>
<ds-item-alerts [item]="item"></ds-item-alerts>
<ds-item-versions-notice [item]="item"></ds-item-versions-notice>
<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">
<ds-item-page-title-field class="me-auto" [item]="item"></ds-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu>
</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)]">
{{"item.page.link.simple" | translate}}
</a>
</div>
}
<div class="table-responsive">
<table class="table table-striped">
<tbody>
<ng-container *ngFor="let mdEntry of (metadata$ | async) | keyvalue">
<tr *ngFor="let mdValue of mdEntry.value">
@for (mdEntry of (metadata$ | async) | keyvalue; track mdEntry) {
@for (mdValue of mdEntry.value; track mdValue) {
<tr>
<td>{{mdEntry.key}}</td>
<td>{{mdValue.value}}</td>
<td>{{mdValue.language}}</td>
</tr>
</ng-container>
}
}
</tbody>
</table>
</div>
<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-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">
<button class="btn btn-outline-secondary me-1" (click)="back()"><i
class="fas fa-arrow-left"></i> {{'item.page.return' | translate}}</button>
</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>

View File

@@ -1,65 +1,180 @@
<div class="container mb-5">
<h1>{{'person.orcid.registry.auth' | translate}}</h1>
<ng-container *ngIf="(isLinkedToOrcid() | async); then orcidLinked; else orcidNotLinked"></ng-container>
</div>
<ng-template #orcidLinked>
@if ((isLinkedToOrcid() | async)) {
<div data-test="orcidLinked">
<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-header">{{ 'person.page.orcid.granted-authorizations'| translate }}</div>
<div class="card-body">
<div class="container p-0">
<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}}
</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">
<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}}
</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}}
<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 }}
</li>
}
</ul>
</ds-alert>
}
</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">
{{ 'person.page.orcid.remove-orcid-message' | translate}}
</ds-alert>
<div class="row" *ngIf="(ownerCanDisconnectProfileFromOrcid() | async)" data-test="unlinkOwner">
}
@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)">
<span *ngIf="(unlinkProcessing | async) !== true"><i
@if ((unlinkProcessing | async) !== true) {
<span><i
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>
}
</button>
<button *ngIf="(hasMissingOrcidAuthorizations() | async)" type="submit"
@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>
} @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>
</ng-template>

View File

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

View File

@@ -16,8 +16,10 @@
<label class="form-label" for="syncMode">{{ 'person.page.orcid.synchronization-mode.label'| translate }}</label>
<select class="form-select" [(ngModel)]="currentSyncMode" name="syncMode" id="syncMode"
required>
<option *ngFor="let syncMode of syncModes"
@for (syncMode of syncModes; track syncMode) {
<option
[value]="syncMode.value">{{ syncMode.label | translate }}</option>
}
</select>
</div>
</div>
@@ -37,13 +39,15 @@
</ds-alert>
</div>
<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"
name="syncPublications" id="publicationOption_{{option.value}}" [value]="option.value"
required>
<label for="publicationOption_{{option.value}}"
class="ms-2 form-label">{{option.label | translate}}</label>
</div>
}
</div>
</div>
</div>
@@ -60,12 +64,14 @@
</ds-alert>
</div>
<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"
name="syncFundings" id="fundingOption_{{option.value}}" [value]="option.value"
required>
<label for="fundingOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label>
</div>
}
</div>
</div>
</div>
@@ -82,12 +88,14 @@
</ds-alert>
</div>
<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"
name="syncProfile_{{option.value}}" id="profileOption_{{option.value}}"
[value]="option.value">
<label for="profileOption_{{option.value}}" class="ms-2 form-label">{{option.label | translate}}</label>
</div>
}
</div>
</div>
</div>

View File

@@ -1,21 +1,35 @@
<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">
<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 *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) }}
</span>
<span> ({{(file?.sizeBytes) | dsFileSize }})</span>
<span *ngIf="!last" innerHTML="{{separator}}"></span>
@if (!last) {
<span innerHTML="{{separator}}"></span>
}
</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>
</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>
</div>
}
</div>
</ds-metadata-field-wrapper>
}
</ng-container>

View File

@@ -1,20 +1,30 @@
<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">
<ds-metadata-representation-loader *ngFor="let rep of representations"
@for (rep of representations; track rep) {
<ds-metadata-representation-loader
[mdRepresentation]="rep">
</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">
<div *ngIf="(objects.length * incrementBy) < total" class="float-start">
}
@if ((i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)) {
<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' |
translate:{ amount: (total - (objects.length * incrementBy) < incrementBy) ? total - (objects.length * incrementBy) : incrementBy } }}</button>
</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' |
translate:{ amount: representations?.length } }}</button>
</div>
}
</div>
}
</ng-container>
</ng-container>
}
</ds-metadata-field-wrapper>

View File

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

View File

@@ -1,20 +1,30 @@
<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">
<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">
</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">
<div *ngIf="itemsRD?.payload?.totalPages > objects.length" class="float-start" id="view-more">
}
@if ((i + 1) === objects.length && (itemsRD || i > 0) && !(itemsRD?.hasSucceeded && itemsRD?.payload && itemsRD?.payload?.page?.length > 0)) {
<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' |
translate:{ amount: (itemsRD?.payload?.totalElements - (incrementBy * objects.length) < incrementBy) ? itemsRD?.payload?.totalElements - (incrementBy * objects.length) : incrementBy } }} {{label}}</button>
</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' |
translate:{ amount: itemsRD?.payload?.page?.length } }} {{label}}</button>
</div>
}
</div>
}
</ng-container>
</ng-container>
}
</ds-metadata-field-wrapper>

View File

@@ -1,44 +1,50 @@
<div class="left-column">
<span *ngIf="(workspaceId$ | async) || (workflowId$ | async); then versionNumberWithoutLink else versionNumberWithLink"></span>
<ng-template #versionNumberWithLink>
<a [routerLink]="getVersionRoute(version.id)">{{version.version}}</a>
</ng-template>
<ng-template #versionNumberWithoutLink>
@if ((workspaceId$ | async) || (workflowId$ | async)) {
{{version.version}}
</ng-template>
<span *ngIf="version?.id === itemVersion?.id">*</span>
} @else {
<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 }}
</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 }}
</span>
}
</div>
<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-->
@if (workspaceId$ | async) {
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
*ngIf="workspaceId$ | async"
(click)="editWorkspaceItem(workspaceId$)"
title="{{'item.version.history.table.action.editWorkspaceItem' | translate }}">
<i class="fas fa-pencil-alt fa-fw"></i>
</button>
}
<!--CREATE-->
<ng-container *ngIf="canCreateVersion$ | async">
@if (canCreateVersion$ | async) {
<button class="btn btn-outline-primary btn-sm version-row-element-create"
[dsBtnDisabled]="isAnyBeingEdited() || hasDraftVersion"
(click)="createNewVersion(version)"
title="{{createVersionTitle | translate }}">
<i class="fas fa-code-branch fa-fw"></i>
</button>
</ng-container>
}
<!--DELETE-->
<ng-container *ngIf="canDeleteVersion$ | async">
@if (canDeleteVersion$ | async) {
<button class="btn btn-sm version-row-element-delete"
[ngClass]="isAnyBeingEdited() ? 'btn-outline-primary' : 'btn-outline-danger'"
[dsBtnDisabled]="isAnyBeingEdited()"
@@ -46,8 +52,9 @@
title="{{'item.version.history.table.action.deleteVersion' | translate}}">
<i class="fas fa-trash fa-fw"></i>
</button>
</ng-container>
}
</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}}
<button type="button" class="btn-close" (click)="onModalClose()" aria-label="Close">
</button>
@@ -6,9 +7,11 @@
<div class="modal-body">
<p class="pb-2">
{{ "item.version.create.modal.text" | translate }}
<span *ngIf="!firstVersion">
@if (!firstVersion) {
<span>
{{ "item.version.create.modal.text.startingFrom" | translate : {version: versionNumber} }}
</span>
}
</p>
<div class="mb-3">
<label for="summary" class="form-label">{{'item.version.create.modal.form.summary.label' | translate }}:</label>
@@ -33,8 +36,7 @@
</button>
</div>
</div>
<ng-template #waiting>
} @else {
<div class="modal-header">{{'item.version.create.modal.submitted.header' | translate}}</div>
<div class="modal-body">
<p>{{'item.version.create.modal.submitted.text' | translate}}</p>
@@ -42,4 +44,5 @@
<ds-loading [showMessage]="false"></ds-loading>
</div>
</div>
</ng-template>
}

View File

@@ -1,11 +1,17 @@
<div *ngIf="(versionsDTO$ | async) as versionsDTO; else noItemVersion">
<div *ngIf="(versionRD$ | async)?.payload as itemVersion">
<div class="mb-2" *ngIf="versionsDTO.versionDTOs.length > 0 || displayWhenEmpty">
<h2 *ngIf="displayTitle" class="h4">{{"item.version.history.head" | translate}}</h2>
@if ((versionsDTO$ | async); as versionsDTO) {
<div>
@if ((versionRD$ | async)?.payload; as itemVersion) {
<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">
{{ "item.version.history.selected.alert" | translate : {version: itemVersion.version} }}
</ds-alert>
<ds-pagination *ngIf="versionsDTO.versionDTOs.length > 0"
@if (versionsDTO.versionDTOs.length > 0) {
<ds-pagination
(paginationChange)="onPageChange()"
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
@@ -16,13 +22,16 @@
<thead>
<tr>
<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.summary" | translate}}</th>
</tr>
</thead>
<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">
<ds-item-versions-row-element-version [hasDraftVersion]="hasDraftVersion$ | async"
[version]="versionDTO.version"
@@ -32,25 +41,32 @@
(versionsHistoryChange)="getAllVersions($event)"
></ds-item-versions-row-element-version>
</td>
<td class="version-row-element-editor" *ngIf="(showSubmitter$ | async)">
@if ((showSubmitter$ | async)) {
<td class="version-row-element-editor">
{{versionDTO.version.submitterName}}
</td>
}
<td class="version-row-element-date">
{{versionDTO.version.created | date : 'yyyy-MM-dd HH:mm:ss'}}
</td>
<td class="version-row-element-summary">
<div class="float-start">
<ng-container *ngIf="isThisBeingEdited(versionDTO.version); then editSummary else showSummary"></ng-container>
<ng-template #showSummary>{{versionDTO.version.summary}}</ng-template>
@if (isThisBeingEdited(versionDTO.version)) {
<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>
<input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate"
[(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()"
class="form-control" type="text"/>
</ng-template>
</div>
<div class="float-end btn-group edit-field space-children-mr" *ngIf="displayActions && versionDTO.canEditVersion | async">
<ng-container *ngIf="isThisBeingEdited(versionDTO.version); else notThisBeingEdited">
@if (displayActions && versionDTO.canEditVersion | async) {
<div class="float-end btn-group edit-field space-children-mr">
@if (isThisBeingEdited(versionDTO.version)) {
<!--DISCARD EDIT-->
<button class="btn btn-sm btn-outline-warning"
(click)="disableVersionEditing()"
@@ -63,8 +79,7 @@
title="{{'item.version.history.table.action.saveSummary' | translate}}">
<i class="fas fa-check fa-fw"></i>
</button>
</ng-container>
<ng-template #notThisBeingEdited>
} @else {
<!--EDIT-->
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
[dsBtnDisabled]="isAnyBeingEdited()"
@@ -72,21 +87,28 @@
title="{{'item.version.history.table.action.editSummary' | translate}}">
<i class="fas fa-edit fa-fw"></i>
</button>
</ng-template>
}
</div>
}
</td>
</tr>
}
</tbody>
</table>
<div>*&nbsp;{{"item.version.history.selected" | translate}}</div>
</ds-pagination>
}
</div>
}
</div>
}
</div>
<ng-template #noItemVersion>
<ds-alert *ngIf="displayWhenEmpty"
} @else {
@if (displayWhenEmpty) {
<ds-alert
[content]="'item.version.history.empty'"
[type]="AlertTypeEnum.Info">
</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"
[attr.aria-label]="'mydspace.new-submission-external' | translate" [dsBtnDisabled]="(initialized$ | async) !== true"
(click)="openPage(singleEntity)" role="button"
@@ -6,9 +7,11 @@
<i class="fa fa-file-import" aria-hidden="true"></i>
</button>
</div>
}
@if ((moreThanOne$ | async)) {
<div class="add w-100" display="dynamic" placement="bottom-right"
ngbDropdown
*ngIf="(moreThanOne$ | async)">
>
<button class="btn btn-lg btn-outline-primary mt-1 ms-2" id="dropdownImport" ngbDropdownToggle
type="button" [dsBtnDisabled]="(initialized$ | async) !== true"
[attr.aria-label]="'mydspace.new-submission-external' | translate"
@@ -24,3 +27,4 @@
<ds-entity-dropdown [isSubmission]="false" (selectionChange)="openPage($event)"></ds-entity-dropdown>
</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"
[dsBtnDisabled]="(initialized$ | async) !== true" (click)="openDialog(singleEntity)" role="button">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
</button>
</div>
}
@if ((moreThanOne$ | async)) {
<div class="add w-100" display="dynamic" placement="bottom-right"
ngbDropdown
*ngIf="(moreThanOne$ | async)">
>
<button class="btn btn-lg btn-primary mt-1 ms-2" id="dropdownSubmission" ngbDropdownToggle
type="button" [dsBtnDisabled]="(initialized$ | async) !== true"
[attr.aria-label]="'mydspace.new-submission' | translate"
@@ -22,3 +25,4 @@
<ds-entity-dropdown [isSubmission]="true" (selectionChange)="openDialog($event)"></ds-entity-dropdown>
</div>
</div>
}

View File

@@ -1,8 +1,8 @@
<ng-container *ngIf="(sources$ | async)?.length > 0">
<ng-container *ngFor="let source of sources$ | async">
@if ((sources$ | async)?.length > 0) {
@for (source of sources$ | async; track source) {
@if (source.totalEvents > 0) {
<div
class="alert alert-info d-flex flex-row"
*ngIf="source.totalEvents > 0"
>
<div class="source-logo-container">
<img
@@ -25,5 +25,6 @@
</button>
</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="w-100">
<div id="collapsingNav">
<ng-container *ngIf="(isMobile$ | async) && (isAuthenticated$ | async)">
@if ((isMobile$ | async) && (isAuthenticated$ | async)) {
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
</ng-container>
}
<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
*ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
</ng-container>
}
</div>
</div>
</div>

View File

@@ -6,13 +6,17 @@
{{'notifications.events.title'| translate}}
</div>
</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>
</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>
<a [routerLink]="itemPageUrl" target="_blank">{{(getTargetItemTitle() | async)}}</a>
</ds-alert>
}
</div>
</div>
<div class="row">
@@ -21,102 +25,135 @@
{{'quality-assurance.events.topic' | translate}} {{this.showTopic}}
</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"
[collectionSize]="(totalElements$ | async)"
[sortOptions]="paginationSortConfig"
(paginationChange)="getQualityAssuranceEvents()">
<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}}
</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">
<thead>
<tr>
<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 *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}}
</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">
{{'quality-assurance.event.table.reasons' | translate}}
</th>
<th scope="col" class="content-col">
{{'quality-assurance.event.table.person-who-requested' | translate}}
</th>
</ng-container>
}
<th scope="col" class="button-col">{{'quality-assurance.event.table.actions' | translate}}</th>
</tr>
</thead>
<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>
<td><a *ngIf="eventElement?.target"
<td>@if (eventElement?.target) {
<a
target="_blank"
rel="noopener noreferrer"
[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 [title]="eventElement.event.message.serviceId">
<a [href]="eventElement.event.message.serviceId" target="_blank">{{eventElement.event.message.serviceId}}</a>
</span>
</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 [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>
</span>
</div>
}
</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.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}}
</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>
</td>
<td *ngIf="showTopic.indexOf('/SUBJECT') !== -1">
}
@if (showTopic.indexOf('/SUBJECT') !== -1) {
<td>
<p><span class="small">{{'quality-assurance.event.table.subjectValue' | translate}}
</span><br><span class="badge bg-info">{{eventElement.event.message.value}}</span></p>
</td>
<td *ngIf="showTopic.indexOf('/ABSTRACT') !== -1">
}
@if (showTopic.indexOf('/ABSTRACT') !== -1) {
<td>
<p class="abstract-container" [class.show]="showMore">
<span class="small">{{'quality-assurance.event.table.abstract' | translate}}</span><br>
<span class="text-ellipsis">{{eventElement.event.message.abstract}}</span>
</p>
<button class="btn btn-outline-primary btn-sm" (click)="showMore = !showMore">
<i *ngIf="!showMore" class="fas fa-angle-down"></i>
<i *ngIf="showMore" class="fas fa-angle-up"></i>
@if (!showMore) {
<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 }}
</button>
</td>
<ng-container *ngIf="showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1">
}
@if (showTopic.indexOf('/REINSTATE') !== -1 || showTopic.indexOf('/WITHDRAWN') !== -1) {
<td>
<p>
<span *ngIf="eventElement.event.message">
@if (eventElement.event.message) {
<span>
<span>{{eventElement.event.message.reason}}</span><br>
</span>
}
</p>
</td>
<td>
<p>
<span *ngIf="eventElement.event.originalId">
@if (eventElement.event.originalId) {
<span>
<ds-eperson-data [ePersonId]="eventElement.event.originalId" [properties]="['email']"></ds-eperson-data>
</span>
}
</p>
</td>
</ng-container>
<td *ngIf="showTopic.indexOf('/PROJECT') !== -1">
}
@if (showTopic.indexOf('/PROJECT') !== -1) {
<td>
<p>
{{'quality-assurance.event.table.suggestedProject' | translate}}
</p>
@@ -125,18 +162,31 @@
<a href="{{sourceUrlForProjectSearch}}{{ eventElement.event.message.sourceId}}" rel="noopener noreferrer" target="_blank">{{eventElement.event.message.title}}</a>
</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>
<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 *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>
<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>
@if (eventElement.event.message.acronym) {
<span><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.code) {
<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>
<hr>
<div>
{{(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">
<button *ngIf="!eventElement.hasProject"
@if (!eventElement.hasProject) {
<button
class="btn btn-outline-primary btn-sm"
[dsBtnDisabled]="eventElement.isRunning"
(click)="openModalLookup(eventElement); $event.stopPropagation();"
@@ -144,7 +194,9 @@
>
<i class="fas fa-search"></i>
</button>
<button *ngIf="eventElement.hasProject"
}
@if (eventElement.hasProject) {
<button
class="btn btn-outline-danger btn-sm"
[dsBtnDisabled]="eventElement.isRunning"
(click)="removeProject(eventElement)"
@@ -152,12 +204,16 @@
>
<i class="fas fa-trash-alt"></i>
</button>
}
</div>
</div>
</td>
}
<td>
<div *ngIf="(isAdmin$ | async) || !isReinstateWithdrawnRequest" class="btn-group button-width">
<button *ngIf="showTopic.indexOf('/PROJECT') !== -1"
@if ((isAdmin$ | async) || !isReinstateWithdrawnRequest) {
<div class="btn-group button-width">
@if (showTopic.indexOf('/PROJECT') !== -1) {
<button
class="btn btn-outline-success btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.import' | translate}}"
container="body"
@@ -167,7 +223,9 @@
>
<i class="fas fa-check"></i>
</button>
<button *ngIf="showTopic.indexOf('/PROJECT') === -1"
}
@if (showTopic.indexOf('/PROJECT') === -1) {
<button
class="btn btn-outline-success btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.accept' | translate}}"
container="body"
@@ -177,6 +235,7 @@
>
<i class="fas fa-check"></i>
</button>
}
<button class="btn btn-outline-dark btn-sm button-width"
ngbTooltip="{{'quality-assurance.event.action.ignore' | translate}}"
container="body"
@@ -186,8 +245,8 @@
>
<i class="fas fa-ban"></i>
</button>
@if ((isAdmin$ | async)) {
<button class="btn btn-outline-danger btn-sm button-width"
*ngIf="(isAdmin$ | async)"
ngbTooltip="{{'quality-assurance.event.action.reject' | translate}}"
container="body"
[dsBtnDisabled]="eventElement.isRunning"
@@ -196,8 +255,9 @@
>
<i class="fas fa-trash-alt"></i>
</button>
}
@if ((isAdmin$ | async) === false) {
<button class="btn btn-outline-danger btn-sm button-width"
*ngIf="(isAdmin$ | async) === false"
ngbTooltip="{{'quality-assurance.event.action.undo' | translate }}"
container="body"
[dsBtnDisabled]="eventElement.isRunning"
@@ -205,8 +265,11 @@
(click)="openModal('UNDO', eventElement, undoModal)">
<i class="fas fa-trash-alt"></i>
</button>
}
</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"
ngbTooltip="{{'quality-assurance.event.action.undo' | translate}}"
container="body"
@@ -216,13 +279,17 @@
<i class="fas fa-trash-alt"></i>
</button>
</div>
}
</td>
</tr>
}
</tbody>
</table>
</div>
}
</ng-container>
</ds-pagination>
}
</div>
</div>
</div>

View File

@@ -9,20 +9,27 @@
<div class="col-12">
<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>
<ds-pagination *ngIf="(isSourceLoading() | async) !== true"
@if ((isSourceLoading() | async)) {
<ds-loading class="container" message="{{'quality-assurance.loading' | translate}}"></ds-loading>
}
@if ((isSourceLoading() | async) !== true) {
<ds-pagination
[paginationOptions]="paginationConfig"
[collectionSize]="(totalElements$ | async)"
[hideGear]="false"
[hideSortOptions]="true"
(paginationChange)="getQualityAssuranceSource()">
<ds-loading class="container" *ngIf="(isSourceProcessing() | async)" 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)) {
<ds-loading class="container" message="'quality-assurance.loading' | translate"></ds-loading>
}
@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}}
</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">
<thead>
<tr>
@@ -32,7 +39,8 @@
</tr>
</thead>
<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.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td>
<td>
@@ -47,11 +55,14 @@
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</ng-container>
}
}
</ds-pagination>
}
</div>
</div>
</div>

View File

@@ -2,31 +2,42 @@
<div class="row">
<div class="col-12">
<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>
<ds-alert *ngIf="targetId" [type]="'alert-info'">
@if (!targetId) {
<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} }}
<a [routerLink]="itemPageUrl">{{(getTargetItemTitle() | async)}}</a>
</ds-alert>
}
</div>
</div>
<div class="row">
<div class="col-12">
<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>
<ds-pagination *ngIf="(isTopicsLoading() | async) !== true"
@if ((isTopicsLoading() | async)) {
<ds-loading class="container" message="{{'quality-assurance.loading' | translate}}"></ds-loading>
}
@if ((isTopicsLoading() | async) !== true) {
<ds-pagination
[paginationOptions]="paginationConfig"
[collectionSize]="(totalElements$ | async)"
[hideGear]="false"
[hideSortOptions]="true"
(paginationChange)="getQualityAssuranceTopics(sourceId, targetId)">
<ds-loading class="container" *ngIf="(isTopicsProcessing() | async)" 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)) {
<ds-loading class="container" message="'quality-assurance.loading' | translate"></ds-loading>
}
@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}}
</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">
<thead>
<tr>
@@ -36,7 +47,8 @@
</tr>
</thead>
<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.lastEvent | date: 'dd/MM/yyyy hh:mm' }}</td>
<td>
@@ -51,11 +63,14 @@
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</ng-container>
}
}
</ds-pagination>
}
</div>
</div>
</div>

View File

@@ -1,29 +1,35 @@
<div 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}}
</button>
<ng-template #chooseCollection>
} @else {
<button class="btn btn-success" id="dropdownSubmission" ngbDropdownToggle
type="button">
<i class="fa fa-check" aria-hidden="true"></i> {{ approveAndImportLabel() | translate}}
<span class="caret"></span>
</button>
<div ngbDropdownMenu
class="dropdown-menu"
id="entityControlsDropdownMenu"
aria-labelledby="dropdownSubmission">
<ds-entity-dropdown (selectionChange)="openDialog($event)"></ds-entity-dropdown>
</div>
</ng-template>
}
</div>
<button (click)="ignoreSuggestion()" class="btn btn-danger ms-2"><i class="fa fa-ban"></i>
{{ 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>
<ng-container *ngIf="!seeEvidence"> {{ 'suggestion.seeEvidence' | translate}}</ng-container>
<ng-container *ngIf="seeEvidence"> {{ 'suggestion.hideEvidence' | translate}}</ng-container>
@if (!seeEvidence) {
{{ 'suggestion.seeEvidence' | translate}}
}
@if (seeEvidence) {
{{ 'suggestion.hideEvidence' | translate}}
}
</button>
}
</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">
<button (click)="removePopup()"
type="button" class="close pt-0 pe-1 pe-0 pb-0" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<div class="d-flex flex-row">
<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>
<div class="d-flex flex-column justify-content-center align-content-stretch text-left p-2">
<ng-container *ngIf="(suggestionsRD$ | async) as suggestions">
<ng-container *ngFor="let suggestion of suggestions" class="alert alert-info">
<div *ngIf="suggestion.total > 0">
@if ((suggestionsRD$ | async); as suggestions) {
@for (suggestion of suggestions; track suggestion) {
<ng-container class="alert alert-info">
@if (suggestion.total > 0) {
<div>
<div [innerHTML]="'notification.suggestion' | translate: getNotificationSuggestionInterpolation(suggestion)"></div>
{{ 'notification.suggestion.please' | translate }}
<a [routerLink]="getNotificationSuggestionInterpolation(suggestion).url"> {{ 'notification.suggestion.review' | translate}} </a>
</div>
}
</ng-container>
</ng-container>
}
}
</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="col-10">
<h1 class="flex-grow-1">
{{ 'process.detail.title' | translate:{ id: process?.processId, name: process?.scriptName } }}
</h1>
</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>
</div>
}
</div>
<ds-process-detail-field id="process-name" [title]="'process.detail.script'">
<div>{{ process?.scriptName }}</div>
</ds-process-detail-field>
<ds-process-detail-field *ngIf="process?.parameters && process?.parameters?.length > 0" id="process-arguments"
@if (process?.parameters && process?.parameters?.length > 0) {
<ds-process-detail-field id="process-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>
}
<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'">
<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>({{(file?.sizeBytes) | dsFileSize }})</span>
</ds-file-download-link>
}
</div>
</ds-process-detail-field>
}
</div>
<ds-process-detail-field *ngIf="process && process.startTime" id="process-start-time"
@if (process && process.startTime) {
<ds-process-detail-field id="process-start-time"
[title]="'process.detail.start-time' | translate">
<div>{{ process.startTime | date:dateFormat:'UTC' }}</div>
</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">
<div>{{ process.endTime | date:dateFormat:'UTC' }}</div>
</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">
<div>{{ process.processStatus }}</div>
</ds-process-detail-field>
<ds-process-detail-field *ngIf="isProcessFinished(process)" id="process-output" [title]="'process.detail.output'">
<button *ngIf="!showOutputLogs && process?._links?.output?.href !== undefined" id="showOutputButton"
}
@if (isProcessFinished(process)) {
<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()">
{{ 'process.detail.logs.button' | translate }}
</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>
}
@if (showOutputLogs && (outputLogs$ | async)?.length > 0) {
<pre class="fw-bold text-secondary bg-light p-3" tabindex="0"
*ngIf="showOutputLogs && (outputLogs$ | async)?.length > 0">{{ (outputLogs$ | async) }}</pre>
<p id="no-output-logs-message" *ngIf="((retrievingOutputLogs$ | async) !== true && showOutputLogs)
&& (outputLogs$ | async | dsHasNoValue) || (outputLogs$ | async)?.length === 0 || !process._links.output">
>{{ (outputLogs$ | async) }}</pre>
}
@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 }}
</p>
}
</ds-process-detail-field>
}
<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
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)">
<i class="fas fa-trash pe-2"></i>{{ 'process.detail.delete.button' | translate }}
</button>
}
</ds-process-detail-field>
<div style="text-align: right;">
<a class="btn btn-outline-secondary mt-3" [routerLink]="'/processes'">{{'process.detail.back' | translate}}</a>
</div>
</div>
}
<ng-template #deleteModal >
<div *ngIf="(processRD$ | async)?.payload as process">
@if ((processRD$ | async)?.payload; as process) {
<div>
<div class="modal-header">
<div>
<h4>{{'process.detail.delete.header' | translate }}</h4>
@@ -88,7 +109,6 @@
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div>{{'process.detail.delete.body' | translate }}</div>
<div class="mt-4">
@@ -98,9 +118,8 @@
</button>
</div>
</div>
</div>
}
</ng-template>

View File

@@ -12,14 +12,20 @@
</form>
</div>
<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 *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}}
<ul>
<li *ngFor="let missing of missingParameters">{{missing}}</li>
@for (missing of missingParameters; track missing) {
<li>{{missing}}</li>
}
</ul>
</div>
}
</div>

View File

@@ -6,15 +6,21 @@
[(ngModel)]="selectedParameter"
#param="ngModel">
<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}}
</option>
}
</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>
<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">
<i class="fas fa-trash"></i>
</button>
<span *ngIf="!removable" class="col-1"></span>
}
@if (!removable) {
<span class="col-1"></span>
}
</div>

View File

@@ -5,9 +5,13 @@
<span class="file-name ms-1">{{fileObject?.name}}</span>
</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)"/>
<div *ngIf="file.invalid && (file.dirty || file.touched)"
@if (file.invalid && (file.dirty || file.touched)) {
<div
class="alert alert-danger validation-error">
<div *ngIf="file.errors.required">
@if (file.errors.required) {
<div>
{{'process.new.parameter.file.required' | translate}}
</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>
@for (value of parameterValues; track value; let i = $index; let last = $last) {
<ds-parameter-select
*ngFor="let value of parameterValues; let i = index; let last = last"
[parameters]="script.parameters"
[parameterValue]="value"
[removable]="!last"
[index]="i"
(removeParameter)="removeParameter(i)"
(changeParameter)="updateParameter($event, i)"></ds-parameter-select>
}
</div>
}

View File

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

View File

@@ -30,14 +30,18 @@
<ng-template #buttons>
<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
class="fas fa-undo pe-2"></i>{{'process.overview.delete.clear' | translate }}
</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
class="fas fa-trash pe-2"></i>{{'process.overview.delete' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}
</button>
}
<button class="btn btn-success" routerLink="/processes/new"><i
class="fas fa-plus pe-2"></i>{{'process.overview.new' | translate}}</button>
</div>
@@ -58,11 +62,15 @@
</div>
<div class="modal-body">
<div *ngIf="(processBulkDeleteService.isProcessing$() | async) !== true">{{'process.overview.delete.body' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</div>
<div *ngIf="processBulkDeleteService.isProcessing$() |async" class="alert alert-info">
@if ((processBulkDeleteService.isProcessing$() | async) !== true) {
<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> {{ 'process.overview.delete.processing' | translate: {count: processBulkDeleteService.getAmountOfSelectedProcesses()} }}</span>
</div>
}
<div class="mt-4">
<button class="btn btn-primary me-2" [dsBtnDisabled]="processBulkDeleteService.isProcessing$() |async"
(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">
<h2 class="flex-grow-1">
{{'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"
*ngIf="(processesRD$ | async) as processesRD">
>
{{processesRD?.payload?.totalElements}}
</span>
}
<span class="ms-2 toggle-icon">
<i class="fas" [ngClass]="collapse.collapsed ? 'fa-angle-right' : 'fa-angle-down'"></i>
</span>
@@ -15,14 +17,16 @@
<div ngbCollapse #collapse="ngbCollapse" [ngbCollapse]="isCollapsed">
<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)"
[collectionSize]="processesRD?.payload?.totalElements"
[retainScrollPosition]="true"
[hideGear]="true">
<div class="table-responsive mt-1">
<table class="table table-striped table-hover">
<thead>
@@ -34,9 +38,9 @@
<th scope="col" class="actions-header">{{'process.overview.table.actions' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tableEntry of processesRD?.payload?.page"
@for (tableEntry of processesRD?.payload?.page; track tableEntry) {
<tr
[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.scriptName}}</a></td>
@@ -50,15 +54,18 @@
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</ds-pagination>
}
<div *ngIf="processesRD?.payload?.totalElements === 0">
@if (processesRD?.payload?.totalElements === 0) {
<div>
<p>{{'process.overview.table.empty' | translate}}</p>
</div>
}
</ng-container>
</div>

View File

@@ -9,7 +9,8 @@
</div>
<div class="dropdown-divider"></div>
<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"
title="{{ dsoNameService.getName(listEntry.indexableObject) }}"
(click)="selectItem(listEntry.indexableObject)" #listEntryElement>
@@ -17,6 +18,7 @@
[linkType]=linkTypes.None></ds-listable-object-component-loader>
</button>
</div>
}
<div class="row">
<div class="col-md mt-2">
</div>

View File

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

View File

@@ -1,7 +1,8 @@
<ng-container *ngVar="(user$ | async) as user">
<div class="container" *ngIf="user">
@if (user) {
<div class="container">
<h1>{{'profile.title' | translate}}</h1>
<ng-container *ngIf="isResearcherProfileEnabled$ | async">
@if (isResearcherProfileEnabled$ | async) {
<div class="card mb-4">
<div class="card-header">{{'profile.card.researcher' | translate}}</div>
<div class="card-body">
@@ -11,14 +12,15 @@
<ds-suggestions-notification></ds-suggestions-notification>
</div>
</div>
</ng-container>
}
<div class="card mb-4">
<div class="card-header">{{'profile.card.identify' | translate}}</div>
<div class="card-body">
<ds-profile-page-metadata-form [user]="user"></ds-profile-page-metadata-form>
</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-body">
<ds-profile-page-security-form
@@ -29,44 +31,56 @@
></ds-profile-page-security-form>
</div>
</div>
}
<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>
</div>
<ng-container *ngIf="(groupsRD$ | async) as groupsRD;">
@if ((groupsRD$ | async); as groupsRD;) {
<ng-container *ngTemplateOutlet="groupsRD?.isLoading ? loader : content"></ng-container>
<ng-template #content>
<ds-pagination *ngIf="groupsRD?.payload"
@if (groupsRD?.payload) {
<ds-pagination
[hideGear]="true"
[hidePagerWhenSinglePage]="true"
[hidePaginationDetail]="true"
[paginationOptions]="optionsGroupsPagination"
[collectionSize]="groupsRD?.payload?.totalElements">
<ng-container *ngIf="groupsRD?.payload?.page as groups">
<div *ngIf="groups?.length > 0">
@if (groupsRD?.payload?.page; as groups) {
@if (groups?.length > 0) {
<div>
<h2 class="mt-4">{{ 'profile.groups.head' | translate }}</h2>
<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>
</div>
</ng-container>
}
}
</ds-pagination>
}
</ng-template>
<ng-template #loader>
<ds-loading [showMessage]="false"></ds-loading>
</ng-template>
<ds-error *ngIf="groupsRD?.hasFailed" message="{{ 'error.profile-groups' | translate }}"></ds-error>
</ng-container>
@if (groupsRD?.hasFailed) {
<ds-error message="{{ 'error.profile-groups' | translate }}"></ds-error>
}
}
<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>
<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) }}
</li>
}
</ul>
</div>
}
</ng-container>
</div>
}
</ng-container>

View File

@@ -2,9 +2,11 @@
<h1>{{MESSAGE_PREFIX + '.header'|translate}}</h1>
<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(', ')}}
</p>
}
<form [class]="'ng-invalid'" [formGroup]="form">
@@ -18,18 +20,24 @@
[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-invalid]="email.invalid"/>
<div *ngIf="email.invalid && (email.dirty || email.touched)"
@if (email.invalid && (email.dirty || email.touched)) {
<div
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 }}
</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 }}
<ng-container *ngIf="validMailDomains.length > 0">
@if (validMailDomains.length > 0) {
{{ MESSAGE_PREFIX + '.email.error.not-valid-domain' | translate: { domains: validMailDomains.join(', ') } }}
</ng-container>
}
</span>
}
</div>
}
</div>
<div class="col-12">
{{MESSAGE_PREFIX + '.email.hint' |translate}}
@@ -39,28 +47,31 @@
</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"><a href="javascript:void(0);" (click)="this.orejimeService.showSettings()">{{ MESSAGE_PREFIX + '.google-recaptcha.open-cookie-settings' | translate }}</a></p>
</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)"
(executeRecaptcha)="register($event)" (checkboxChecked)="onCheckboxChecked($event)"
(showNotification)="showNotification($event)"></ds-google-recaptcha>
</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()">
{{ MESSAGE_PREFIX + '.submit' | translate }}
</button>
</ng-container>
<ng-template #v2Invisible>
} @else {
<button class="btn btn-primary" [dsBtnDisabled]="form.invalid" (click)="executeRecaptcha()">
{{ MESSAGE_PREFIX + '.submit' | translate }}
</button>
</ng-template>
}
</form>
</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>
<div class="card mb-4">
<div class="card-header">{{'register-page.create-profile.identification.header' | translate}}</div>
@@ -10,21 +11,23 @@
<span id="email">{{(registration$ |async).email}}</span></div>
</div>
<form [class]="'ng-invalid'" [formGroup]="userInfoForm" (ngSubmit)="submitEperson()">
<div class="mb-3">
<div class="row">
<div class="col-12">
<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'"
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">
<span *ngIf="firstName.errors && firstName.errors.required">
@if (firstName.errors && firstName.errors.required) {
<span>
{{ 'register-page.create-profile.identification.first-name.error' | translate }}
</span>
}
</div>
}
</div>
</div>
<div class="row">
<div class="col-12">
@@ -33,12 +36,16 @@
<input
[className]="(lastName.invalid) && (lastName.dirty || lastName.touched) ? 'form-control is-invalid' :'form-control'"
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">
<span *ngIf="lastName.errors && lastName.errors.required">
@if (lastName.errors && lastName.errors.required) {
<span>
{{ 'register-page.create-profile.identification.last-name.error' | translate }}
</span>
}
</div>
}
</div>
</div>
<div class="row">
@@ -52,10 +59,11 @@
<div class="col-12">
<label class="form-label"
for="language">{{'register-page.create-profile.identification.language' |translate}}</label>
<select id="language" formControlName="language" class="form-select">
<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>
</div>
</div>
@@ -63,11 +71,9 @@
</form>
</div>
</div>
<div class="card mb-4">
<div class="card-header">{{'register-page.create-profile.security.header' | translate}}</div>
<div class="card-body">
<ds-profile-page-security-form
[passwordCanBeEmpty]="false"
[FORM_PREFIX]="'register-page.create-profile.security.'"
@@ -76,8 +82,6 @@
></ds-profile-page-security-form>
</div>
</div>
<div class="row">
<div class="col-12">
<button
@@ -86,6 +90,5 @@
(click)="submitEperson()">{{'register-page.create-profile.submit' | translate}}</button>
</div>
</div>
</div>
}

View File

@@ -2,9 +2,11 @@
<div class="mb-3">
<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">
<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 }}
</div>
}
</div>
<div class="mb-3">
<label for="message" class="form-label">{{ 'grant-deny-request-copy.email.message' | translate }}</label>

View File

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

View File

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

View File

@@ -7,9 +7,9 @@
</button>
</div>
<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
*ngIf="data.payload.page.length > 0"
[config]="paginationConfig"
[context]="context"
[objects]="data"
@@ -18,13 +18,14 @@
[showPaginator]="true"
(pageChange)="loadForPage($event)">
</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">
{{'access-control-select-bitstreams-modal.no-items' | translate}}
</div>
</ng-container>
}
}
</div>
<div class="modal-footer">
<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">
<span *ngIf="content" [innerHTML]="content | translate"></span>
@if (!dismissed) {
<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>
<button *ngIf="dismissible" type="button" class="btn-close" data-dismiss="alert" aria-label="Close" (click)="dismiss()">
@if (dismissible) {
<button type="button" class="btn-close" data-dismiss="alert" aria-label="Close" (click)="dismiss()">
</button>
}
</div>
}

View File

@@ -1,5 +1,7 @@
<div class="navbar-nav me-auto" *ngIf="(isMobile$ | async) !== true; else mobileButtons" data-test="auth-nav">
<div *ngIf="(isAuthenticated | async) !== true && (showAuth | async)"
@if ((isMobile$ | async) !== true) {
<div class="navbar-nav me-auto" data-test="auth-nav">
@if ((isAuthenticated | async) !== true && (showAuth | async)) {
<div
class="nav-item"
(click)="$event.stopPropagation();">
<div ngbDropdown #loginDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
@@ -18,7 +20,9 @@
</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>
<a href="javascript:void(0);"
role="menuitem"
@@ -34,19 +38,24 @@
</div>
</div>
</div>
}
</div>
<ng-template #mobileButtons>
} @else {
<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>
</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>
<span class="sr-only">(current)</span>
</a>
}
</div>
</ng-template>
}
<!-- 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"
class="form-control w-100"
(click)="$event.stopPropagation();"
@@ -6,6 +7,7 @@
[formControl]="searchField"
#searchFieldEl>
</div>
}
<div class="dropdown-divider m-0"></div>
<ul class="scrollable-menu p-0 m-0"
role="menu"
@@ -18,27 +20,35 @@
[scrollWindow]="false"
(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}}
</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"
role="menuitem"
title="{{ listItem.collection.name }}"
(click)="onSelect(listItem)">
<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>
</div>
}
<div class="list-item text-truncate text-primary fw-bold">{{ listItem.collection.name}}</div>
</div>
</li>
</ng-container>
<li *ngIf="(isLoading | async)">
}
}
@if ((isLoading | async)) {
<li>
<button class="dropdown-item disabled">
<ds-loading message="{{'loading.default' | translate}}">
</ds-loading>
</button>
</li>
}
</ul>

View File

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

View File

@@ -12,7 +12,8 @@
</div>
<div class="pt-2">
<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"
[attr.aria-selected]="page === currentPage"
[ngClass]="{'active' : page === currentPage}"
@@ -21,15 +22,18 @@
{{ type + '.edit.tabs.' + page + '.head' | translate}}
</a>
</li>
}
</ul>
<div class="tab-pane active">
<div class="mb-4">
<router-outlet></router-outlet>
</div>
<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 }}
</a>
}
</div>
</div>
</div>

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,8 @@
<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
*ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
</div>
}
</div>

View File

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

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