Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/app/core/metadata/metadata-bitstream.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ export class MetadataBitstream extends ListableObject implements HALResource {
@autoserialize
canPreview: boolean;

/**
* The access status of this bitstream (e.g. "open.access", "embargo", "restricted").
* Unlike the standard Bitstream HAL resource, this endpoint embeds the status directly
* rather than exposing it via a resolvable accessStatus link.
*/
@autoserialize
status: string;

/**
* The date this bitstream's embargo lifts. Only set when status is "embargo".
*/
@autoserialize
embargoDate: string;

/**
* The {@link HALLink}s for this MetadataField
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
<dl class="dl-horizontal">
<dt>{{'item.file.description.name' | translate}}</dt>
<dd title="ud-treebanks-v2.12.tgz">
{{ fileInput.name }}
<ng-container *ngIf="showAccessStatus && fileInput.status === 'embargo' && fileInput.embargoDate; else plainFileName">
<a (click)="downloadFile()" class="cursor-pointer">
<span class="pr-1"><i class="fas fa-lock"></i></span>{{ fileInput.name }}
</a>
<span class="badge badge-secondary ml-1 access-status-list-element-badge">{{ 'embargo.listelement.badge' | translate: { date: fileInput.embargoDate } }}</span>
</ng-container>
<ng-template #plainFileName>{{ fileInput.name }}</ng-template>
</dd>
<dt>{{'item.file.description.size' | translate}}</dt>
<dd>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { RouterTestingModule } from '@angular/router/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HALEndpointService } from '../../../../../core/shared/hal-endpoint.service';
import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe';
import { environment } from '../../../../../../environments/environment';

describe('FileDescriptionComponent', () => {
let component: FileDescriptionComponent;
Expand Down Expand Up @@ -47,11 +48,7 @@ describe('FileDescriptionComponent', () => {
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(FileDescriptionComponent);
component = fixture.componentInstance;

// Mock the input value
function createFileInput(overrides: Partial<MetadataBitstream> = {}): MetadataBitstream {
const fileInput = new MetadataBitstream();
fileInput.id = 123;
fileInput.name = 'testFile';
Expand All @@ -66,20 +63,86 @@ describe('FileDescriptionComponent', () => {
self: { href: '' },
schema: { href: '' },
};
return Object.assign(fileInput, overrides);
}

describe('by default', () => {
beforeEach(() => {
fixture = TestBed.createComponent(FileDescriptionComponent);
component = fixture.componentInstance;
component.fileInput = createFileInput();
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should display the file name', () => {
const fileNameElement = fixture.debugElement.query(
By.css('.file-content dd')
).nativeElement;
expect(fileNameElement.textContent).toContain('testFile');
});

component.fileInput = fileInput;
it('should not show the embargo badge', () => {
const badge = fixture.debugElement.query(By.css('span.badge'));
expect(badge).toBeNull();
});

fixture.detectChanges();
it('should not show the lock icon', () => {
const lockIcon = fixture.debugElement.query(By.css('.file-content dd i.fa-lock'));
expect(lockIcon).toBeNull();
});
});

it('should create', () => {
expect(component).toBeTruthy();
describe('when the bitstream is embargoed and the feature flag is on', () => {
beforeEach(() => {
environment.item.bitstream.showAccessStatuses = true;
fixture = TestBed.createComponent(FileDescriptionComponent);
component = fixture.componentInstance;
component.fileInput = createFileInput({ status: 'embargo', embargoDate: '2050-01-01' });
fixture.detectChanges();
});

afterEach(() => {
environment.item.bitstream.showAccessStatuses = false;
});

it('should show the embargo badge', () => {
const badge = fixture.debugElement.query(By.css('span.badge'));
expect(badge).not.toBeNull();
expect(badge.nativeElement.textContent).toContain('embargo.listelement.badge');
});

it('should show the lock icon next to the file name', () => {
const lockIcon = fixture.debugElement.query(By.css('.file-content dd i.fa-lock'));
expect(lockIcon).not.toBeNull();
});

it('should render the file name as a clickable link, matching the ZCU-PUB pattern', () => {
const link = fixture.debugElement.query(By.css('.file-content dd a'));
expect(link).not.toBeNull();
expect(link.nativeElement.textContent).toContain('testFile');
});
});

it('should display the file name', () => {
const fileNameElement = fixture.debugElement.query(
By.css('.file-content dd')
).nativeElement;
expect(fileNameElement.textContent).toContain('testFile');
describe('when the bitstream is embargoed but the feature flag is off', () => {
beforeEach(() => {
fixture = TestBed.createComponent(FileDescriptionComponent);
component = fixture.componentInstance;
component.fileInput = createFileInput({ status: 'embargo', embargoDate: '2050-01-01' });
fixture.detectChanges();
});

it('should not show the embargo badge', () => {
const badge = fixture.debugElement.query(By.css('span.badge'));
expect(badge).toBeNull();
});

it('should not show the lock icon', () => {
const lockIcon = fixture.debugElement.query(By.css('.file-content dd i.fa-lock'));
expect(lockIcon).toBeNull();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core';
import { MetadataBitstream } from 'src/app/core/metadata/metadata-bitstream.model';
import { HALEndpointService } from '../../../../../core/shared/hal-endpoint.service';
import {Router} from '@angular/router';
import { environment } from 'src/environments/environment';

const allowedPreviewFormats = ['text/plain', 'text/html', 'application/zip'];
@Component({
Expand All @@ -13,6 +14,14 @@ export class FileDescriptionComponent {
MIME_TYPE_IMAGES_PATH = '/assets/images/mime/';
MIME_TYPE_DEFAULT_IMAGE_NAME = 'application-octet-stream.png';

/**
* Whether to show the embargo-date badge for a restricted bitstream. Same feature flag as
* the standard file-download-link/AccessStatusBadgeComponent path on other customer instances.
*/
get showAccessStatus(): boolean {
return environment.item.bitstream.showAccessStatuses;
}

Comment thread
Copilot marked this conversation as resolved.
@Input()
fileInput: MetadataBitstream;

Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/cs.json5
Original file line number Diff line number Diff line change
Expand Up @@ -8397,4 +8397,6 @@
// "item.page.cc.license.disclaimer": "Except where otherwised noted, this item's license is described as",
// TODO New key - Add a translation
"item.page.cc.license.disclaimer": "Except where otherwised noted, this item's license is described as",
// "embargo.listelement.badge": "Embargo until {{ date }}",
"embargo.listelement.badge": "Embargo do {{ date }}",
}
2 changes: 2 additions & 0 deletions src/assets/i18n/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -5930,4 +5930,6 @@
"navbar.about.service-integrations": "Service integrations",

"navbar.about.project-partnership": "Project partnerships",

"embargo.listelement.badge": "Embargo until {{ date }}",
}
5 changes: 4 additions & 1 deletion src/config/default-app-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ export class DefaultAppConfig implements AppConfig {
// Number of entries in the bitstream list in the item view page.
// Rounded to the nearest size in the list of selectable sizes on the
// settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
pageSize: 5
pageSize: 5,
// Show the bitstream embargo-date badge.
// Keep this false until the backend accessStatus support (DSpace#1380) is deployed.
showAccessStatuses: false
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/config/item-config.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ export interface ItemConfig extends Config {
// Rounded to the nearest size in the list of selectable sizes on the
// settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
pageSize: number;
// Show the bitstream embargo-date badge
showAccessStatuses: boolean;
}
}
4 changes: 3 additions & 1 deletion src/environments/environment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@ export const environment: BuildConfig = {
// Number of entries in the bitstream list in the item view page.
// Rounded to the nearest size in the list of selectable sizes on the
// settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
pageSize: 5
pageSize: 5,
// Show the bitstream embargo-date badge
showAccessStatuses: false
}
},
collection: {
Expand Down
Loading