Skip to content

Commit 7efe616

Browse files
Merged dspace-cris-2025_02_x into task/dspace-cris-2025_02_x/DSC-1956
2 parents a31ba87 + 93fd862 commit 7efe616

45 files changed

Lines changed: 1765 additions & 610 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { testA11y } from 'cypress/support/utils';
2+
3+
describe('Audit Overview Page', () => {
4+
beforeEach(() => {
5+
// Must login as an Admin to see the page
6+
cy.visit('/auditlogs');
7+
cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD'));
8+
});
9+
10+
it('page structure should be correct and should pass accessibility tests', () => {
11+
// Page must first be visible
12+
cy.get('ds-audit-overview').should('be.visible');
13+
// Check for presence of main container and title
14+
cy.get('.container').should('exist');
15+
cy.get('[data-test="audit-title"]').should('be.visible');
16+
cy.get('body').then($body => {
17+
const hasTable = $body.find('[data-test="audit-table"]').length > 0;
18+
const hasEmpty = $body.find('[data-test="audit-empty"]').length > 0;
19+
// At least one present and not both
20+
expect(hasTable || hasEmpty).to.equal(true);
21+
expect(!(hasTable && hasEmpty)).to.equal(true);
22+
});
23+
// Analyze <ds-audit-overview> for accessibility issues
24+
testA11y('ds-audit-overview');
25+
});
26+
27+
28+
29+
});

docker/docker-compose-ci.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ services:
3333
# This allows us to generate statistics in e2e tests so that statistics pages can be tested thoroughly.
3434
solr__D__statistics__P__autoCommit: ${solr__D__statistics__P__autoCommit:-false}
3535
LOGGING_CONFIG: ${LOGGING_CONFIG:-/dspace/config/log4j2-container.xml}
36-
image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-9_x-test}"
36+
image: "${DOCKER_REGISTRY:-docker.io}/${DOCKER_OWNER:-4science}/dspace-cris:${DSPACE_VER:-dspace-cris-2025_02_x-test}"
3737
depends_on:
3838
- dspacedb
3939
networks:
@@ -97,7 +97,7 @@ services:
9797
user: root
9898
entrypoint:
9999
- /bin/bash
100-
- "-c"
100+
- '-c'
101101
- |
102102
init-var-solr
103103
precreate-core authority /opt/solr/server/solr/configsets/authority
@@ -118,6 +118,12 @@ services:
118118
cp -r /opt/solr/server/solr/configsets/audit/* audit
119119
chown -R solr:solr /var/solr
120120
runuser -u solr -- solr-foreground
121+
healthcheck:
122+
test: ["CMD", "curl", "-f", "http://localhost:8983/solr/"]
123+
interval: 15s
124+
timeout: 5s
125+
retries: 10
126+
start_period: 30s
121127
volumes:
122128
assetstore:
123129
pgdata:

src/app/app.menus.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { MenuRoute } from './shared/menu/menu-route.model';
1111
import { AccessControlMenuProvider } from './shared/menu/providers/access-control.menu';
1212
import { AdminCommunityListMenuProvider } from './shared/menu/providers/admin-community-list.menu';
1313
import { AdminSearchMenuProvider } from './shared/menu/providers/admin-search.menu';
14+
import { AuditLogsMenuProvider } from './shared/menu/providers/audit-item.menu';
15+
import { AuditOverviewMenuProvider } from './shared/menu/providers/audit-overview.menu';
1416
import { CoarNotifyMenuProvider } from './shared/menu/providers/coar-notify.menu';
1517
import { SubscribeMenuProvider } from './shared/menu/providers/comcol-subscribe.menu';
1618
import { CommunityListMenuProvider } from './shared/menu/providers/community-list.menu';
@@ -78,6 +80,7 @@ export const MENUS = buildMenuStructure({
7880
HealthMenuProvider,
7981
SystemWideAlertMenuProvider,
8082
CoarNotifyMenuProvider,
83+
AuditOverviewMenuProvider,
8184
UserAgreementMenuProvider,
8285
MetadataCmsMenuProvider,
8386
],
@@ -98,6 +101,11 @@ export const MENUS = buildMenuStructure({
98101
VersioningMenuProvider.onRoute(
99102
MenuRoute.ITEM_PAGE,
100103
),
104+
AuditLogsMenuProvider.onRoute(
105+
MenuRoute.COMMUNITY_PAGE,
106+
MenuRoute.COLLECTION_PAGE,
107+
MenuRoute.ITEM_PAGE,
108+
),
101109
OrcidMenuProvider.onRoute(
102110
MenuRoute.ITEM_PAGE,
103111
),

src/app/audit-page/audit-page-routes.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,18 @@ import { Route } from '@angular/router';
22

33
import { authenticatedGuard } from '../core/auth/authenticated.guard';
44
import { i18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
5-
import { auditPageResolver } from './audit-page.resolver';
6-
import { AuditDetailComponent } from './detail/audit-detail.component';
7-
import { ObjectAuditOverviewComponent } from './object-audit-overview/object-audit-overview.component';
85
import { AuditOverviewComponent } from './overview/audit-overview.component';
96

107
export const ROUTES: Route[] = [
118
{
129
path: '',
13-
resolve: { breadcrumb: i18nBreadcrumbResolver },
14-
data: { breadcrumbKey: 'audit.overview' },
1510
canActivate: [authenticatedGuard],
1611
children: [
1712
{
1813
path: '',
1914
component: AuditOverviewComponent,
20-
data: { title: 'audit.overview.title' },
21-
},
22-
{
23-
path: ':id',
24-
component: AuditDetailComponent,
25-
resolve: {
26-
process: auditPageResolver,
27-
// TODO: breadcrumbs resolver
28-
},
29-
},
30-
{
31-
path: 'object/:objectId',
32-
component: ObjectAuditOverviewComponent,
33-
// TODO: breadcrumbs resolver
15+
data: { title: 'audit.overview.title', breadcrumbKey: 'audit.overview' },
16+
resolve: { breadcrumb: i18nBreadcrumbResolver },
3417
},
3518
],
3619
},

src/app/audit-page/audit-page.resolver.spec.ts

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/app/audit-page/audit-page.resolver.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
@if (audits.totalElements === 0) {
2+
<div>{{ 'audit.data.not-found' | translate }}</div>
3+
} @else {
4+
<ds-pagination
5+
[paginationOptions]="pageConfig"
6+
[collectionSize]="audits?.totalElements"
7+
[hideGear]="true"
8+
[hidePagerWhenSinglePage]="true">
9+
<div class="table-responsive">
10+
<table class="table table-striped table-hover">
11+
<thead>
12+
<tr>
13+
<th>{{ 'audit.overview.table.entityType' | translate }}</th>
14+
<th>{{ 'audit.overview.table.eperson' | translate }}</th>
15+
<th>{{ 'audit.overview.table.timestamp' | translate }}</th>
16+
@if (isOverviewPage) {
17+
<th>{{ 'audit.overview.table.subjectUUID' | translate }}</th>
18+
<th>{{ 'audit.overview.table.subjectType' | translate }}</th>
19+
<th>{{ 'audit.overview.table.objectUUID' | translate }}</th>
20+
<th>{{ 'audit.overview.table.objectType' | translate }}</th>
21+
} @else {
22+
<th>{{ 'audit.overview.table.other' | translate }}</th>
23+
}
24+
</tr>
25+
</thead>
26+
<tbody>
27+
@for (audit of audits?.page; track audit) {
28+
<tr>
29+
<td>
30+
@if (audit.hasDetails) {
31+
<div role="button" class="d-flex align-items-center" (click)="toggleCollapse(audit)">
32+
<div class="btn btn-link p-1 mr-1">
33+
@if (audit.isCollapsed) {
34+
<i class="fas fa-caret-right"></i>
35+
} @else {
36+
<i class="fas fa-caret-down"></i>
37+
}
38+
</div>
39+
<div>
40+
{{ audit.eventType }}
41+
</div>
42+
</div>
43+
} @else {
44+
<div class="ml-4">
45+
{{ audit.eventType }}
46+
</div>
47+
}
48+
</td>
49+
<td>{{ audit.epersonName }}</td>
50+
<td>{{ audit.timeStamp | date:dateFormat:'UTC' }}</td>
51+
@if (isOverviewPage) {
52+
<td>
53+
@if (audit.objectUUID) {
54+
<ng-container *ngVar="(getObjectRoute$(audit.objectUUID) | async) as objectRoute">
55+
@if (objectRoute !== ('/' + auditPath)) {
56+
<a [routerLink]="[objectRoute]">{{audit.objectUUID}}</a>
57+
} @else {
58+
<span>{{audit.objectUUID}}</span>
59+
}
60+
</ng-container>
61+
}
62+
</td>
63+
<td>{{ audit.objectType }}</td>
64+
<td>
65+
@if (audit.subjectUUID) {
66+
<ng-container *ngVar="(getObjectRoute$(audit.subjectUUID) | async) as subjectRoute">
67+
@if (subjectRoute !== ('/' + auditPath)) {
68+
<a [routerLink]="[subjectRoute]">{{audit.subjectUUID}}</a>
69+
} @else {
70+
<span>{{audit.subjectUUID}}</span>
71+
}
72+
</ng-container>
73+
}
74+
</td>
75+
<td>{{ audit.subjectType }}</td>
76+
} @else {
77+
<td>
78+
<span>
79+
@if (audit.otherAuditObject; as dso) {
80+
{{ getDsoName(dso) }} <em>({{ dso.type }})</em>
81+
} @else {
82+
{{ 'audit.data.self' | translate}}
83+
}
84+
</span>
85+
</td>
86+
}
87+
</tr>
88+
@if (audit.hasDetails) {
89+
<tr [(ngbCollapse)]="audit.isCollapsed" [id]="audit.id" [ngClass]="{'border-top-0': !audit.isCollapsed}" class="w-100 nested-row">
90+
@if (isOverviewPage) {
91+
<td colspan="7" class="border-top-0">
92+
<ng-container *ngTemplateOutlet="auditInto; context: { audit }"></ng-container>
93+
</td>
94+
} @else {
95+
<td colspan="4" class="border-top-0">
96+
<ng-container *ngTemplateOutlet="auditInto; context: { audit }"></ng-container>
97+
</td>
98+
}
99+
</tr>
100+
}
101+
}
102+
</tbody>
103+
</table>
104+
</div>
105+
</ds-pagination>
106+
}
107+
108+
<ng-template #auditInto let-audit=audit>
109+
<div class="w-100">
110+
<div class="d-flex flex-column mw-100 w-100">
111+
@if (audit.metadataField) {
112+
<div class="d-flex mb-1">
113+
<small class="font-weight-bold me-2" >{{"audit.detail.metadata.field" | translate}}</small>
114+
<small>{{ audit.metadataField | dsStringReplace: "_":"." }}</small>
115+
</div>
116+
}
117+
@if (audit.value) {
118+
<div class="d-flex mb-1">
119+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.value" | translate}}</small>
120+
<small class="content dont-break-out preserve-line-breaks">
121+
{{ audit.value }}
122+
</small>
123+
</div>
124+
}
125+
@if (audit.authority) {
126+
<div class="d-flex mb-1">
127+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.authority" | translate}}</small>
128+
<small>{{ audit.authority }}</small>
129+
</div>
130+
}
131+
@if (audit.confidence !== null) {
132+
<div class="d-flex mb-1">
133+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.confidence" | translate}}</small>
134+
<small>{{ audit.confidence }}</small>
135+
</div>
136+
}
137+
@if (audit.place !== null) {
138+
<div class="d-flex mb-1">
139+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.place" | translate}}</small>
140+
<small>{{ audit.place }}</small>
141+
</div>
142+
}
143+
@if (audit.action) {
144+
<div class="d-flex mb-1">
145+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.action" | translate}}</small>
146+
<small>{{ audit.action }}</small>
147+
</div>
148+
}
149+
@if (audit.checksum) {
150+
<div class="d-flex">
151+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.checksum" | translate}}</small>
152+
<small>{{ audit.checksum }}</small>
153+
</div>
154+
}
155+
</div>
156+
</div>
157+
</ng-template>

0 commit comments

Comments
 (0)