Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b154b78
Add ItemPageCcLicenseFieldComponent to render rights information
abelgomez Sep 20, 2024
049d3a4
Update UntypedItemComponent to use ItemPageLicenseFieldComponent rath…
abelgomez Sep 20, 2024
8250d76
Add rights information to Publication EntityType template (Publicatio…
abelgomez Sep 20, 2024
13ffbef
Fix lint errors
abelgomez Sep 20, 2024
4db6e92
Update UntypedItemComponent to use ItemPageLicenseFieldComponent rath…
abelgomez Sep 20, 2024
da42278
Add rights information to Publication EntityType template (Publicatio…
abelgomez Sep 20, 2024
a89b1e1
Fix lint errors
abelgomez Sep 20, 2024
c8c4d99
Fix comments
abelgomez Sep 20, 2024
397b7f4
Use of the back-end config to check whether license is CC
abelgomez Oct 21, 2024
e2e3906
Merge remote-tracking branch 'upstream/main' into issue-3170
abelgomez Mar 6, 2025
5647483
Merge remote-tracking branch 'upstream/main' into issue-3170
abelgomez Mar 26, 2025
79b2fee
Use innerHTML for the separator
abelgomez Mar 26, 2025
1a41dcb
Migrate to new Angular control flow syntax
abelgomez Mar 26, 2025
a593113
Remove unused imports
abelgomez Mar 26, 2025
808d44b
Move parsing functions for CC licenses to a utility file
abelgomez Mar 26, 2025
d7e8b87
Remove comment no longer needed
abelgomez Mar 26, 2025
a5721d2
Merge remote-tracking branch 'upstream/main' into issue-3170
abelgomez Mar 31, 2025
c23c075
Merge remote-tracking branch 'upstream/main' into issue-3170
abelgomez Apr 1, 2025
bca531c
Don't use manual subscriptions
abelgomez Apr 1, 2025
57bea01
Don't use manual subscriptions
abelgomez Apr 1, 2025
7a57777
Merge branch 'issue-3170' of github.com:sistedes/dspace.ui into issue…
abelgomez Apr 1, 2025
b61653e
Merge remote-tracking branch 'upstream/main' into issue-3170
abelgomez Feb 16, 2026
256b7e2
Fix tests
abelgomez Feb 16, 2026
8b0d83f
Trigger Build
abelgomez Feb 17, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@if (licenses.length > 0 || uris.length > 0) {
<div class="item-page-field">
@if ((hasCcLicenseName$ | async) && (hasCcLicenseUri$ | async)) {
<ds-item-page-cc-license-field [item]="item" [variant]="'full'"></ds-item-page-cc-license-field>
} @else {
<ds-metadata-field-wrapper [label]="'item.page.license.title' | translate">
@if (licenses.length === uris.length) {
@for (license of licenses; track license; let last=$last; let i=$index) {
<a [href]="uris[i]" target="_blank" class="license-link"><span class="license-text">{{ license }}</span></a>
@if (!last) {
<span class="separator" [innerHTML]="separator"></span>
}
}
} @else {
@for (license of licenses; track license; let last=$last) {
<span class="license-text">{{ license }}</span>
@if (!last || uris.length > 0) {
<span class="separator" [innerHTML]="separator"></span>
}
}
@for (uri of uris; track uri; let last=$last) {
<a [href]="uri" target="_blank" class="license-link"><span class="license-text">{{ uri }}</span></a>
@if (!last) {
<span class="separator" [innerHTML]="separator"></span>
}
}
}
</ds-metadata-field-wrapper>
}
</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
import {
ChangeDetectionStrategy,
NO_ERRORS_SCHEMA,
} from '@angular/core';
import {
ComponentFixture,
TestBed,
waitForAsync,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { APP_CONFIG } from '@dspace/config/app-config.interface';
import { ConfigurationDataService } from '@dspace/core/data/configuration-data.service';
import { ConfigurationProperty } from '@dspace/core/shared/configuration-property.model';
import { Item } from '@dspace/core/shared/item.model';
import {
MetadataMap,
MetadataValue,
} from '@dspace/core/shared/metadata.models';
import { ConfigurationDataServiceStub } from '@dspace/core/testing/configuration-data.service.stub';
import { TranslateLoaderMock } from '@dspace/core/testing/translate-loader.mock';
import { createPaginatedList } from '@dspace/core/testing/utils.test';
import { createSuccessfulRemoteDataObject$ } from '@dspace/core/utilities/remote-data.utils';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';

import { environment } from '../../../../../../environments/environment';
import { ItemPageLicenseFieldComponent } from './item-page-license-field.component';


interface TestInstance {
metadata: any;
}


interface TestCase {
testInstance: TestInstance;
expected: {
render: boolean,
textElements: string[],
linkElements: string[],
};
}


const licenseNameMock = 'LICENSE NAME';
const exampleUriMock = 'http://example.com';
const ccUriMock = 'https://creativecommons.org/licenses/by/4.0';


const testCases: TestCase[] = [
{
testInstance: {
metadata: { 'dc.rights': undefined, 'dc.rights.uri': undefined },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': [ undefined, undefined ], 'dc.rights.uri': undefined },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights.license': undefined, 'dc.rights.uri': undefined },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': undefined, 'dc.rights.license': undefined, 'dc.rights.uri': [ undefined, undefined ] },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': null, 'dc.rights.license': null, 'dc.rights.uri': null },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': null, 'dc.rights.license': null, 'dc.rights.uri': [ null, null ] },
},
expected: {
render: false,
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights.uri': exampleUriMock },
},
expected: {
render: true,
textElements: [exampleUriMock],
linkElements: [exampleUriMock],
},
},
{
testInstance: {
metadata: { 'dc.rights': null, 'dc.rights.license': null, 'dc.rights.uri': exampleUriMock },
},
expected: {
render: true,
textElements: [exampleUriMock],
linkElements: [exampleUriMock],
},
},
{
testInstance: {
metadata: { 'dc.rights.uri': ccUriMock },
},
expected: {
render: true,
textElements: [ccUriMock],
linkElements: [ccUriMock],
},
},
{
testInstance: {
metadata: { 'dc.rights': null, 'dc.rights.license': licenseNameMock, 'dc.rights.uri': null },
},
expected: {
render: true,
textElements: [licenseNameMock],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': licenseNameMock, 'dc.rights.uri': ccUriMock },
},
expected: {
render: true,
// This test case is delegated to ItemPageCcLicenseFieldComponent
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': licenseNameMock, 'dc.rights.license': licenseNameMock, 'dc.rights.uri': ccUriMock },
},
expected: {
render: true,
// This test case meets the CC criteria too (since it has 'dc.rights', and 'dc.rights.uri'
// points to a CC license). Thus, it is delegated to ItemPageCcLicenseFieldComponent.
textElements: [],
linkElements: [],
},
},
{
testInstance: {
metadata: { 'dc.rights': licenseNameMock, 'dc.rights.license': licenseNameMock, 'dc.rights.uri': exampleUriMock },
},
expected: {
render: true,
textElements: [licenseNameMock, licenseNameMock, exampleUriMock],
linkElements: [exampleUriMock],
},
},
];


// Updates the component fixture with parameters from the test instance
function configureFixture(
fixture: ComponentFixture<ItemPageLicenseFieldComponent>,
testInstance: TestInstance,
) {
const item = Object.assign(new Item(), {
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
metadata: new MetadataMap(),
});

for (const [key, values] of Object.entries(testInstance.metadata)) {
for (const value of values instanceof Array ? values : [values]) {
item.metadata[key] = [
{
language: 'en_US',
value: value,
},
] as MetadataValue[];
}
}

let component: ItemPageLicenseFieldComponent = fixture.componentInstance;
component.item = item;

fixture.detectChanges();
}


describe('ItemPageLicenseFieldComponent', () => {
let fixture: ComponentFixture<ItemPageLicenseFieldComponent>;
let configurationDataService = new ConfigurationDataServiceStub();

beforeEach(waitForAsync(() => {
configurationDataService.findByPropertyName = jasmine.createSpy()
.withArgs('cc.license.name').and.returnValue(createSuccessfulRemoteDataObject$({
... new ConfigurationProperty(),
name: 'cc.license.name',
values: [ 'dc.rights' ],
},
))
.withArgs('cc.license.uri').and.returnValue(createSuccessfulRemoteDataObject$({
... new ConfigurationProperty(),
name: 'cc.license.uri',
values: [ 'dc.rights.uri' ],
},
));
void TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock,
},
}),
ItemPageLicenseFieldComponent,
],
providers: [
{ provide: APP_CONFIG, useValue: environment },
{ provide: ConfigurationDataService, useValue: configurationDataService },
],
schemas: [NO_ERRORS_SCHEMA],
})
.overrideComponent(ItemPageLicenseFieldComponent, {
set: { changeDetection: ChangeDetectionStrategy.Default },
})
.compileComponents();
}));

beforeEach(waitForAsync(() => {
fixture = TestBed.createComponent(ItemPageLicenseFieldComponent);
}));

testCases.forEach((testCase) => {
describe('', () => {
beforeEach(async () => {
configureFixture(fixture, testCase.testInstance);
});

it('should render or not the component',
() => {
const componentEl = fixture.debugElement.query(By.css('.item-page-field'));
expect(Boolean(componentEl)).toBe(testCase.expected.render);
},
);

it('should show/hide license as plain text',
() => {
const textEl = fixture.debugElement.queryAll(By.css('.license-text'));
expect(textEl.length).toBe(testCase.expected.textElements.length);
if (textEl && testCase.expected.textElements.length > 0) {
textEl.forEach((elt, idx) =>
expect(elt.nativeElement.innerHTML).toContain(testCase.expected.textElements[idx]),
);
}
},
);

it('should show/hide the license as link',
() => {
const linkEl = fixture.debugElement.queryAll(By.css('.license-link'));
expect(linkEl.length).toBe(testCase.expected.linkElements.length);
if (linkEl && testCase.expected.linkElements.length > 0) {
linkEl.forEach((elt, idx) =>
expect(elt.query(By.css('.license-text')).nativeElement.innerHTML).toContain(testCase.expected.linkElements[idx]),
);
}
},
);
});
});
});
Loading
Loading