diff --git a/apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts b/apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts index 9b5585d471..a84af33308 100644 --- a/apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts +++ b/apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts @@ -93,7 +93,7 @@ describe('dataset pages', () => { .filter(':visible') .as('navBtns') cy.get('@navBtns').eq(3).click() - cy.get('gn-ui-data-otherlinks').should('be.visible') + cy.get('datahub-record-otherlinks').should('be.visible') }) }) }) @@ -101,7 +101,7 @@ describe('dataset pages', () => { describe('ABOUT SECTION : display & functions', () => { describe('display', () => { it('should display the description', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-info') .find('gn-ui-content-ghost') @@ -112,11 +112,11 @@ describe('dataset pages', () => { }) }) it('should display the contact details', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-contact') .should('have.length', 1) - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-contact') .children('div') @@ -124,13 +124,13 @@ describe('dataset pages', () => { .eq(0) .invoke('text') .should('include', '@') - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-catalog') .should('have.length', 1) }) it('should display the catalog details', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-catalog') .children('div') @@ -142,7 +142,7 @@ describe('dataset pages', () => { }) }) it('should display the keywords', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-info') .children('div') @@ -151,7 +151,7 @@ describe('dataset pages', () => { .should('have.length.gt', 0) }) it('should display the lineage and usage tabs', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-info') .find('gn-ui-expandable-panel') @@ -161,7 +161,7 @@ describe('dataset pages', () => { let targetLink let keyword it('should go to provider website on click', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-contact') .children('div') @@ -178,7 +178,7 @@ describe('dataset pages', () => { }) }) it('should go to dataset search page when clicking on org name and filter by org', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-contact') .children('div') @@ -189,7 +189,7 @@ describe('dataset pages', () => { cy.url().should('include', '/search?publisher=') }) it('should go to dataset search page when clicking on keyword and filter by keyword', () => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="about"]') .find('gn-ui-metadata-info') .children('div') @@ -214,7 +214,7 @@ describe('dataset pages', () => { describe('PREVIEW SECTION : display & functions', () => { beforeEach(() => { - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="preview"]') .first() .as('previewSection') @@ -323,14 +323,14 @@ describe('dataset pages', () => { describe('DOWNLOADS : display & functions', () => { describe('display', () => { it('should have at least one download button', () => { - cy.get('gn-ui-data-downloads') + cy.get('datahub-record-downloads') .find('gn-ui-download-item') .should('have.length.gt', 0) }) it('should have one button per download type + all and others', () => { cy.get('[data-cy="download-format"]').then((format) => { const formatString = format.text() - cy.get('gn-ui-data-downloads') + cy.get('datahub-record-downloads') .find('gn-ui-button') .children('button') .then((btn) => { @@ -356,7 +356,7 @@ describe('dataset pages', () => { }) describe('features', () => { it('filters the download list on format filter click', () => { - cy.get('gn-ui-data-downloads') + cy.get('datahub-record-downloads') .find('gn-ui-button') .children('button') .eq(1) @@ -373,7 +373,7 @@ describe('dataset pages', () => { }) }) it('downloads a file on click', () => { - cy.get('gn-ui-data-downloads') + cy.get('datahub-record-downloads') .find('gn-ui-download-item') .first() .click() @@ -391,21 +391,21 @@ describe('dataset pages', () => { describe('LINKS : display & functions', () => { describe('display', () => { it('should have external, API and internal links with one option', () => { - cy.get('gn-ui-data-otherlinks') + cy.get('datahub-record-otherlinks') .find('gn-ui-link-card') .should('have.length.gt', 0) - cy.get('gn-ui-data-apis') + cy.get('datahub-record-apis') .find('gn-ui-api-card') .should('have.length.gt', 0) cy.get('#related-records') - .find('gn-ui-related-records') + .find('datahub-record-related-records') .find('gn-ui-related-record-card') .should('have.length.gt', 0) }) }) describe('features', () => { it('goes to external link on click', () => { - cy.get('gn-ui-data-otherlinks') + cy.get('datahub-record-otherlinks') .find('gn-ui-link-card') .first() .children('a') @@ -420,7 +420,7 @@ describe('dataset pages', () => { }) }) it('copies the API path on click', () => { - cy.get('gn-ui-data-apis') + cy.get('datahub-record-apis') .find('gn-ui-copy-text-button') .find('button') .first() @@ -437,7 +437,7 @@ describe('dataset pages', () => { it('goes to dataset on click', () => { let targetLink cy.get('#related-records') - .find('gn-ui-related-records') + .find('datahub-record-related-records') .find('gn-ui-related-record-card') .first() .children('a') @@ -458,7 +458,7 @@ describe('dataset pages', () => { describe('record with file distributions', () => { beforeEach(() => { cy.visit('/dataset/n_tri_lill_inondable_s_059') - cy.get('gn-ui-record-metadata') + cy.get('datahub-record-metadata') .find('[id="preview"]') .first() .as('previewSection') diff --git a/apps/datahub/src/app/app.module.ts b/apps/datahub/src/app/app.module.ts index 935be29ada..6b18b04fa7 100644 --- a/apps/datahub/src/app/app.module.ts +++ b/apps/datahub/src/app/app.module.ts @@ -70,6 +70,12 @@ import { METADATA_LANGUAGE } from '@geonetwork-ui/api/repository' import { BrowserAnimationsModule } from '@angular/platform-browser/animations' import { GN_UI_VERSION } from '@geonetwork-ui/feature/record' import { LOGIN_URL } from '@geonetwork-ui/api/repository/gn4' +import { RecordRelatedRecordsComponent } from './record/record-related-records/record-related-records.component' +import { RecordMetadataComponent } from './record/record-metadata/record-metadata.component' +import { RecordOtherlinksComponent } from './record/record-otherlinks/record-otherlinks.component' +import { RecordDownloadsComponent } from './record/record-downloads/record-downloads.component' +import { RecordApisComponent } from './record/record-apis/record-apis.component' +import { MatTabsModule } from '@angular/material/tabs' export const metaReducers: MetaReducer[] = !environment.production ? [] : [] // https://github.com/nrwl/nx/issues/191 @@ -89,6 +95,11 @@ export const metaReducers: MetaReducer[] = !environment.production ? [] : [] LastCreatedComponent, KeyFiguresComponent, NavigationMenuComponent, + RecordRelatedRecordsComponent, + RecordMetadataComponent, + RecordOtherlinksComponent, + RecordDownloadsComponent, + RecordApisComponent, ], imports: [ BrowserModule, @@ -128,6 +139,7 @@ export const metaReducers: MetaReducer[] = !environment.production ? [] : [] FormsModule, UiInputsModule, UiCatalogModule, + MatTabsModule, ], providers: [ { provide: RouterService, useClass: DatahubRouterService }, diff --git a/libs/feature/record/src/lib/data-apis/data-apis.component.css b/apps/datahub/src/app/record/record-apis/record-apis.component.css similarity index 100% rename from libs/feature/record/src/lib/data-apis/data-apis.component.css rename to apps/datahub/src/app/record/record-apis/record-apis.component.css diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.html b/apps/datahub/src/app/record/record-apis/record-apis.component.html new file mode 100644 index 0000000000..b7b623d5e7 --- /dev/null +++ b/apps/datahub/src/app/record/record-apis/record-apis.component.html @@ -0,0 +1,25 @@ +

+ record.metadata.api +

+ + + + diff --git a/libs/feature/record/src/lib/data-apis/data-apis.component.spec.ts b/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts similarity index 65% rename from libs/feature/record/src/lib/data-apis/data-apis.component.spec.ts rename to apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts index 474f5b04f0..948b6b2fc0 100644 --- a/libs/feature/record/src/lib/data-apis/data-apis.component.spec.ts +++ b/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts @@ -1,20 +1,19 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' import { Subject } from 'rxjs' -import { MdViewFacade } from '../state' - -import { DataApisComponent } from './data-apis.component' +import { RecordApisComponent } from './record-apis.component' +import { MdViewFacade } from '@geonetwork-ui/feature/record' class MdViewFacadeMock { apiLinks$ = new Subject() } describe('DataApisComponent', () => { - let component: DataApisComponent - let fixture: ComponentFixture + let component: RecordApisComponent + let fixture: ComponentFixture beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [DataApisComponent], + declarations: [RecordApisComponent], providers: [ { provide: MdViewFacade, @@ -25,7 +24,7 @@ describe('DataApisComponent', () => { }) beforeEach(() => { - fixture = TestBed.createComponent(DataApisComponent) + fixture = TestBed.createComponent(RecordApisComponent) component = fixture.componentInstance fixture.detectChanges() }) diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.ts b/apps/datahub/src/app/record/record-apis/record-apis.component.ts new file mode 100644 index 0000000000..8bcfd1ce86 --- /dev/null +++ b/apps/datahub/src/app/record/record-apis/record-apis.component.ts @@ -0,0 +1,12 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core' +import { MdViewFacade } from '@geonetwork-ui/feature/record' + +@Component({ + selector: 'datahub-record-apis', + templateUrl: './record-apis.component.html', + styleUrls: ['./record-apis.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class RecordApisComponent { + constructor(public facade: MdViewFacade) {} +} diff --git a/libs/feature/record/src/lib/data-downloads/data-downloads.component.css b/apps/datahub/src/app/record/record-downloads/record-downloads.component.css similarity index 100% rename from libs/feature/record/src/lib/data-downloads/data-downloads.component.css rename to apps/datahub/src/app/record/record-downloads/record-downloads.component.css diff --git a/libs/feature/record/src/lib/data-downloads/data-downloads.component.html b/apps/datahub/src/app/record/record-downloads/record-downloads.component.html similarity index 100% rename from libs/feature/record/src/lib/data-downloads/data-downloads.component.html rename to apps/datahub/src/app/record/record-downloads/record-downloads.component.html diff --git a/libs/feature/record/src/lib/data-downloads/data-downloads.component.spec.ts b/apps/datahub/src/app/record/record-downloads/record-downloads.component.spec.ts similarity index 96% rename from libs/feature/record/src/lib/data-downloads/data-downloads.component.spec.ts rename to apps/datahub/src/app/record/record-downloads/record-downloads.component.spec.ts index 170d6f78c4..5212cc1e04 100644 --- a/libs/feature/record/src/lib/data-downloads/data-downloads.component.spec.ts +++ b/apps/datahub/src/app/record/record-downloads/record-downloads.component.spec.ts @@ -5,12 +5,12 @@ import { tick, } from '@angular/core/testing' import { BehaviorSubject, of, throwError } from 'rxjs' -import { MdViewFacade } from '../state' -import { DataDownloadsComponent } from './data-downloads.component' +import { RecordDownloadsComponent } from './record-downloads.component' import { Component, Input, NO_ERRORS_SCHEMA } from '@angular/core' import { By } from '@angular/platform-browser' import { DataService } from '@geonetwork-ui/feature/dataviz' import { DatasetDistribution } from '@geonetwork-ui/common/domain/record' +import { MdViewFacade } from '@geonetwork-ui/feature/record' // This is used to work around a very weird bug when comparing URL objects would fail // if the `searchParams` of the object wasn't accessed beforehand in some cases... @@ -58,6 +58,7 @@ class DataServiceMock { } @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'gn-ui-download-item', template: '
', }) @@ -66,20 +67,21 @@ export class MockDownloadsListItemComponent { } @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'gn-ui-popup-alert', template: '
', }) export class MockPopupAlertComponent {} describe('DataDownloadsComponent', () => { - let component: DataDownloadsComponent - let fixture: ComponentFixture + let component: RecordDownloadsComponent + let fixture: ComponentFixture let facade beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ - DataDownloadsComponent, + RecordDownloadsComponent, MockDownloadsListItemComponent, MockPopupAlertComponent, ], @@ -99,7 +101,7 @@ describe('DataDownloadsComponent', () => { }) beforeEach(() => { - fixture = TestBed.createComponent(DataDownloadsComponent) + fixture = TestBed.createComponent(RecordDownloadsComponent) component = fixture.componentInstance fixture.detectChanges() }) diff --git a/libs/feature/record/src/lib/data-downloads/data-downloads.component.ts b/apps/datahub/src/app/record/record-downloads/record-downloads.component.ts similarity index 91% rename from libs/feature/record/src/lib/data-downloads/data-downloads.component.ts rename to apps/datahub/src/app/record/record-downloads/record-downloads.component.ts index 890e4ea6fe..2e4a2e708e 100644 --- a/libs/feature/record/src/lib/data-downloads/data-downloads.component.ts +++ b/apps/datahub/src/app/record/record-downloads/record-downloads.component.ts @@ -3,19 +3,19 @@ import { DataService } from '@geonetwork-ui/feature/dataviz' import { getFileFormat, getLinkPriority } from '@geonetwork-ui/util/shared' import { combineLatest, of } from 'rxjs' import { catchError, map, switchMap } from 'rxjs/operators' -import { MdViewFacade } from '../state' import { DatasetDistribution, DatasetServiceDistribution, } from '@geonetwork-ui/common/domain/record' +import { MdViewFacade } from '@geonetwork-ui/feature/record' @Component({ - selector: 'gn-ui-data-downloads', - templateUrl: './data-downloads.component.html', - styleUrls: ['./data-downloads.component.css'], + selector: 'datahub-record-downloads', + templateUrl: './record-downloads.component.html', + styleUrls: ['./record-downloads.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DataDownloadsComponent { +export class RecordDownloadsComponent { constructor(public facade: MdViewFacade, private dataService: DataService) {} error: string = null diff --git a/libs/feature/record/src/lib/record-metadata/record-metadata.component.css b/apps/datahub/src/app/record/record-metadata/record-metadata.component.css similarity index 76% rename from libs/feature/record/src/lib/record-metadata/record-metadata.component.css rename to apps/datahub/src/app/record/record-metadata/record-metadata.component.css index e3a0105a26..02a13a131f 100644 --- a/libs/feature/record/src/lib/record-metadata/record-metadata.component.css +++ b/apps/datahub/src/app/record/record-metadata/record-metadata.component.css @@ -33,3 +33,18 @@ .tab-header-label { @apply uppercase text-sm text-primary opacity-75 hover:text-primary-darker; } + +:host { + --container-outside-width: calc(50vw - 1024px / 2); +} +@media (max-width: 1024px) { + :host { + --container-outside-width: 1rem; + } +} + +/deep/ gn-ui-carousel { + display: block; + margin-left: calc(-1 * var(--container-outside-width)); + margin-right: calc(-1 * var(--container-outside-width)); +} diff --git a/libs/feature/record/src/lib/record-metadata/record-metadata.component.html b/apps/datahub/src/app/record/record-metadata/record-metadata.component.html similarity index 93% rename from libs/feature/record/src/lib/record-metadata/record-metadata.component.html rename to apps/datahub/src/app/record/record-metadata/record-metadata.component.html index 39a654b0fb..f7f020a96c 100644 --- a/libs/feature/record/src/lib/record-metadata/record-metadata.component.html +++ b/apps/datahub/src/app/record/record-metadata/record-metadata.component.html @@ -111,16 +111,16 @@ class="container-lg px-4 lg:mx-auto" *ngIf="displayDownload$ | async" > - + @@ -128,9 +128,9 @@
- + >
diff --git a/libs/feature/record/src/lib/record-metadata/record-metadata.component.spec.ts b/apps/datahub/src/app/record/record-metadata/record-metadata.component.spec.ts similarity index 97% rename from libs/feature/record/src/lib/record-metadata/record-metadata.component.spec.ts rename to apps/datahub/src/app/record/record-metadata/record-metadata.component.spec.ts index b2f669fd30..f1ba243c25 100644 --- a/libs/feature/record/src/lib/record-metadata/record-metadata.component.spec.ts +++ b/apps/datahub/src/app/record/record-metadata/record-metadata.component.spec.ts @@ -14,10 +14,10 @@ import { } from '@geonetwork-ui/ui/elements' import { TranslateModule } from '@ngx-translate/core' import { BehaviorSubject, of } from 'rxjs' -import { MdViewFacade } from '../state/mdview.facade' import { RecordMetadataComponent } from './record-metadata.component' import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface' import { DATASET_RECORDS } from '@geonetwork-ui/common/fixtures' +import { MdViewFacade } from '@geonetwork-ui/feature/record' const SAMPLE_RECORD = { ...DATASET_RECORDS[0], @@ -56,43 +56,46 @@ class OrganisationsServiceMock { } @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'gn-ui-map-view', template: '
', }) export class MockDataMapComponent {} @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'gn-ui-data-view', template: '
', }) export class MockDataViewComponent {} @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'gn-ui-data-view-share', template: '
', }) export class MockDataViewShareComponent {} @Component({ - selector: 'gn-ui-data-downloads', + selector: 'datahub-record-downloads', template: '
', }) export class MockDataDownloadsComponent {} @Component({ - selector: 'gn-ui-data-otherlinks', + selector: 'datahub-record-otherlinks', template: '
', }) export class MockDataOtherlinksComponent {} @Component({ - selector: 'gn-ui-data-apis', + selector: 'datahub-record-apis', template: '
', }) export class MockDataApisComponent {} @Component({ - selector: 'gn-ui-related-records', + selector: 'datahub-record-related-records', template: '
', }) export class MockRelatedComponent {} diff --git a/libs/feature/record/src/lib/record-metadata/record-metadata.component.ts b/apps/datahub/src/app/record/record-metadata/record-metadata.component.ts similarity index 96% rename from libs/feature/record/src/lib/record-metadata/record-metadata.component.ts rename to apps/datahub/src/app/record/record-metadata/record-metadata.component.ts index 1280aef175..ed410fd33e 100644 --- a/libs/feature/record/src/lib/record-metadata/record-metadata.component.ts +++ b/apps/datahub/src/app/record/record-metadata/record-metadata.component.ts @@ -4,12 +4,12 @@ import { SearchService } from '@geonetwork-ui/feature/search' import { ErrorType, MetadataQualityDisplay } from '@geonetwork-ui/ui/elements' import { BehaviorSubject, combineLatest } from 'rxjs' import { filter, map, mergeMap } from 'rxjs/operators' -import { MdViewFacade } from '../state/mdview.facade' import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface' import { Organization } from '@geonetwork-ui/common/domain/record' +import { MdViewFacade } from '@geonetwork-ui/feature/record' @Component({ - selector: 'gn-ui-record-metadata', + selector: 'datahub-record-metadata', templateUrl: './record-metadata.component.html', styleUrls: ['./record-metadata.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.css b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.css similarity index 100% rename from libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.css rename to apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.css diff --git a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html new file mode 100644 index 0000000000..91be0773da --- /dev/null +++ b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.html @@ -0,0 +1,25 @@ +

+ record.metadata.links +

+ + + + diff --git a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.spec.ts b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.spec.ts similarity index 61% rename from libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.spec.ts rename to apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.spec.ts index 565ba1e012..13ad395a38 100644 --- a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.spec.ts +++ b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.spec.ts @@ -1,25 +1,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' import { Subject } from 'rxjs' -import { MdViewFacade } from '../state' - -import { DataOtherlinksComponent } from './data-otherlinks.component' +import { RecordOtherlinksComponent } from './record-otherlinks.component' +import { MdViewFacade } from '@geonetwork-ui/feature/record' class MdViewFacadeMock { otherLinks$ = new Subject() } describe('DataOtherlinksComponent', () => { - let component: DataOtherlinksComponent - let fixture: ComponentFixture + let component: RecordOtherlinksComponent + let fixture: ComponentFixture beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [DataOtherlinksComponent], + declarations: [RecordOtherlinksComponent], providers: [{ provide: MdViewFacade, useClass: MdViewFacadeMock }], }).compileComponents() }) beforeEach(() => { - fixture = TestBed.createComponent(DataOtherlinksComponent) + fixture = TestBed.createComponent(RecordOtherlinksComponent) component = fixture.componentInstance fixture.detectChanges() }) diff --git a/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts new file mode 100644 index 0000000000..d77e44adcc --- /dev/null +++ b/apps/datahub/src/app/record/record-otherlinks/record-otherlinks.component.ts @@ -0,0 +1,12 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core' +import { MdViewFacade } from '@geonetwork-ui/feature/record' + +@Component({ + selector: 'datahub-record-otherlinks', + templateUrl: './record-otherlinks.component.html', + styleUrls: ['./record-otherlinks.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class RecordOtherlinksComponent { + constructor(public facade: MdViewFacade) {} +} diff --git a/apps/datahub/src/app/record/record-page/record-page.component.html b/apps/datahub/src/app/record/record-page/record-page.component.html index a4b8388ae1..2f3fca3b97 100644 --- a/apps/datahub/src/app/record/record-page/record-page.component.html +++ b/apps/datahub/src/app/record/record-page/record-page.component.html @@ -2,7 +2,7 @@ - + > diff --git a/libs/feature/record/src/lib/related-records/related-records.component.css b/apps/datahub/src/app/record/record-related-records/record-related-records.component.css similarity index 100% rename from libs/feature/record/src/lib/related-records/related-records.component.css rename to apps/datahub/src/app/record/record-related-records/record-related-records.component.css diff --git a/libs/feature/record/src/lib/related-records/related-records.component.html b/apps/datahub/src/app/record/record-related-records/record-related-records.component.html similarity index 100% rename from libs/feature/record/src/lib/related-records/related-records.component.html rename to apps/datahub/src/app/record/record-related-records/record-related-records.component.html diff --git a/libs/feature/record/src/lib/related-records/related-records.component.spec.ts b/apps/datahub/src/app/record/record-related-records/record-related-records.component.spec.ts similarity index 55% rename from libs/feature/record/src/lib/related-records/related-records.component.spec.ts rename to apps/datahub/src/app/record/record-related-records/record-related-records.component.spec.ts index d67f61b59d..b5e95e7938 100644 --- a/libs/feature/record/src/lib/related-records/related-records.component.spec.ts +++ b/apps/datahub/src/app/record/record-related-records/record-related-records.component.spec.ts @@ -1,19 +1,19 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' -import { RelatedRecordsComponent } from './related-records.component' +import { RecordRelatedRecordsComponent } from './record-related-records.component' describe('RelatedRecordsComponent', () => { - let component: RelatedRecordsComponent - let fixture: ComponentFixture + let component: RecordRelatedRecordsComponent + let fixture: ComponentFixture beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [RelatedRecordsComponent], + declarations: [RecordRelatedRecordsComponent], }).compileComponents() }) beforeEach(() => { - fixture = TestBed.createComponent(RelatedRecordsComponent) + fixture = TestBed.createComponent(RecordRelatedRecordsComponent) component = fixture.componentInstance fixture.detectChanges() }) diff --git a/libs/feature/record/src/lib/related-records/related-records.component.ts b/apps/datahub/src/app/record/record-related-records/record-related-records.component.ts similarity index 54% rename from libs/feature/record/src/lib/related-records/related-records.component.ts rename to apps/datahub/src/app/record/record-related-records/record-related-records.component.ts index e997f444cb..4706ff96a0 100644 --- a/libs/feature/record/src/lib/related-records/related-records.component.ts +++ b/apps/datahub/src/app/record/record-related-records/record-related-records.component.ts @@ -2,11 +2,11 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { CatalogRecord } from '@geonetwork-ui/common/domain/record' @Component({ - selector: 'gn-ui-related-records', - templateUrl: './related-records.component.html', - styleUrls: ['./related-records.component.css'], + selector: 'datahub-record-related-records', + templateUrl: './record-related-records.component.html', + styleUrls: ['./record-related-records.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class RelatedRecordsComponent { +export class RecordRelatedRecordsComponent { @Input() records: CatalogRecord[] } diff --git a/libs/feature/record/src/index.ts b/libs/feature/record/src/index.ts index 21978f97ba..fca1b95e7e 100644 --- a/libs/feature/record/src/index.ts +++ b/libs/feature/record/src/index.ts @@ -1,4 +1,3 @@ export * from './lib/feature-record.module' export * from './lib/state' -export * from './lib/record-metadata/record-metadata.component' export * from './lib/data-view-permalink/data-view-permalink.component' diff --git a/libs/feature/record/src/lib/data-apis/data-apis.component.html b/libs/feature/record/src/lib/data-apis/data-apis.component.html deleted file mode 100644 index 4aa7bd198b..0000000000 --- a/libs/feature/record/src/lib/data-apis/data-apis.component.html +++ /dev/null @@ -1,16 +0,0 @@ -

- record.metadata.api -

-
- - -
diff --git a/libs/feature/record/src/lib/data-apis/data-apis.component.ts b/libs/feature/record/src/lib/data-apis/data-apis.component.ts deleted file mode 100644 index 23d66899cb..0000000000 --- a/libs/feature/record/src/lib/data-apis/data-apis.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core' -import { MdViewFacade } from '../state' - -@Component({ - selector: 'gn-ui-data-apis', - templateUrl: './data-apis.component.html', - styleUrls: ['./data-apis.component.css'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DataApisComponent { - constructor(public facade: MdViewFacade) {} -} diff --git a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.html b/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.html deleted file mode 100644 index 7dae5599f6..0000000000 --- a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.html +++ /dev/null @@ -1,13 +0,0 @@ -

- record.metadata.links -

-
- - -
diff --git a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.ts b/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.ts deleted file mode 100644 index c68bc5d070..0000000000 --- a/libs/feature/record/src/lib/data-otherlinks/data-otherlinks.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core' -import { MdViewFacade } from '../state' - -@Component({ - selector: 'gn-ui-data-otherlinks', - templateUrl: './data-otherlinks.component.html', - styleUrls: ['./data-otherlinks.component.css'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DataOtherlinksComponent { - constructor(public facade: MdViewFacade) {} -} diff --git a/libs/feature/record/src/lib/feature-record.module.ts b/libs/feature/record/src/lib/feature-record.module.ts index 72f9a939ca..b337e884c2 100644 --- a/libs/feature/record/src/lib/feature-record.module.ts +++ b/libs/feature/record/src/lib/feature-record.module.ts @@ -12,15 +12,10 @@ import { MdViewEffects } from './state/mdview.effects' import { MapViewComponent } from './map-view/map-view.component' import { DataViewComponent } from './data-view/data-view.component' import { MD_VIEW_FEATURE_STATE_KEY, reducer } from './state/mdview.reducer' -import { DataApisComponent } from './data-apis/data-apis.component' -import { DataDownloadsComponent } from './data-downloads/data-downloads.component' -import { RecordMetadataComponent } from './record-metadata/record-metadata.component' import { MatTabsModule } from '@angular/material/tabs' import { MatIconModule } from '@angular/material/icon' import { UiWidgetsModule } from '@geonetwork-ui/ui/widgets' import { TranslateModule } from '@ngx-translate/core' -import { DataOtherlinksComponent } from './data-otherlinks/data-otherlinks.component' -import { RelatedRecordsComponent } from './related-records/related-records.component' import { ExternalViewerButtonComponent } from './external-viewer-button/external-viewer-button.component' import { FeatureCatalogModule } from '@geonetwork-ui/feature/catalog' import { TableComponent } from '@geonetwork-ui/ui/dataviz' @@ -32,13 +27,8 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon export const GN_UI_VERSION = new InjectionToken('gnUiVersion') @NgModule({ declarations: [ - RecordMetadataComponent, MapViewComponent, DataViewComponent, - DataDownloadsComponent, - DataApisComponent, - DataOtherlinksComponent, - RelatedRecordsComponent, ExternalViewerButtonComponent, DataViewPermalinkComponent, DataViewWebComponentComponent, @@ -63,12 +53,8 @@ export const GN_UI_VERSION = new InjectionToken('gnUiVersion') ], providers: [MdViewFacade], exports: [ - RecordMetadataComponent, MapViewComponent, DataViewComponent, - DataDownloadsComponent, - DataApisComponent, - DataOtherlinksComponent, DataViewPermalinkComponent, DataViewWebComponentComponent, DataViewShareComponent, diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.css b/libs/ui/layout/src/lib/carousel/carousel.component.css new file mode 100644 index 0000000000..692a8be27f --- /dev/null +++ b/libs/ui/layout/src/lib/carousel/carousel.component.css @@ -0,0 +1,20 @@ +:host .carousel-container /deep/ > * { + flex-shrink: 0; +} +:host { + position: relative; +} +.carousel-step-dot { + width: 6px; + height: 6px; + border-radius: 6px; + position: relative; +} +.carousel-step-dot:after { + content: ''; + position: absolute; + left: -4px; + top: -4px; + width: 14px; + height: 14px; +} diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.html b/libs/ui/layout/src/lib/carousel/carousel.component.html new file mode 100644 index 0000000000..e24c65971c --- /dev/null +++ b/libs/ui/layout/src/lib/carousel/carousel.component.html @@ -0,0 +1,16 @@ +
+ +
+
+ +
diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts b/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts new file mode 100644 index 0000000000..d691b6c08d --- /dev/null +++ b/libs/ui/layout/src/lib/carousel/carousel.component.spec.ts @@ -0,0 +1,85 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing' +import { CarouselComponent } from './carousel.component' +import { Component, Input } from '@angular/core' +import { By } from '@angular/platform-browser' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import { _triggerEvent } from 'embla-carousel' + +jest.mock('embla-carousel', () => { + let _callback = null + return { + default: () => ({ + scrollTo: jest.fn(function (step) { + this._selected = step + _callback() + }), + on(eventName, callback) { + _callback = callback + return this + }, + scrollSnapList() { + return [0, 0.5, 0.75, 1] + }, + selectedScrollSnap() { + return this._selected + }, + _selected: 0, + }), + _triggerEvent() { + _callback() + }, + __esModule: true, + } +}) + +@Component({ + template: ` +
+
`, +}) +class CarouselWrapperComponent { + @Input() blocks = [1, 2, 3] + @Input() width = 100 +} + +describe('CarouselComponent', () => { + let component: CarouselComponent + let fixture: ComponentFixture + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CarouselWrapperComponent, CarouselComponent], + }).compileComponents() + fixture = TestBed.createComponent(CarouselWrapperComponent) + component = fixture.debugElement.query( + By.directive(CarouselComponent) + ).componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) + + describe('steps computation', () => { + beforeEach(() => { + _triggerEvent() + }) + it('computes steps initially', () => { + expect(component.steps).toEqual([0, 0.5, 0.75, 1]) + expect(component.selectedStep).toEqual(0) + }) + describe('click on step', () => { + beforeEach(() => { + component.scrollToStep(2) + }) + it('calls #scrollTo', () => { + expect(component.emblaApi.scrollTo).toHaveBeenCalledWith(2) + }) + it('sets the clicked step as selected', () => { + expect(component.selectedStep).toEqual(2) + }) + }) + }) +}) diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.stories.ts b/libs/ui/layout/src/lib/carousel/carousel.component.stories.ts new file mode 100644 index 0000000000..6086a98635 --- /dev/null +++ b/libs/ui/layout/src/lib/carousel/carousel.component.stories.ts @@ -0,0 +1,42 @@ +import type { Meta, StoryObj } from '@storybook/angular' +import { CarouselComponent } from './carousel.component' +import { componentWrapperDecorator } from '@storybook/angular' + +const meta: Meta = { + component: CarouselComponent, + title: 'Layout/CarouselComponent', + decorators: [ + componentWrapperDecorator( + (story) => + `
${story}
` + ), + ], +} +export default meta +type Story = StoryObj + +export const Primary: Story = { + args: {}, + render: (args) => ({ + props: args, + template: ` + +
+ First box +
+
+ Second box +
+
+ Third box +
+
+ Fourth box +
+
+ Fifth box +
+
+`, + }), +} diff --git a/libs/ui/layout/src/lib/carousel/carousel.component.ts b/libs/ui/layout/src/lib/carousel/carousel.component.ts new file mode 100644 index 0000000000..0d9c52897f --- /dev/null +++ b/libs/ui/layout/src/lib/carousel/carousel.component.ts @@ -0,0 +1,50 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Input, + ViewChild, +} from '@angular/core' +import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel' + +@Component({ + selector: 'gn-ui-carousel', + templateUrl: './carousel.component.html', + styleUrls: ['./carousel.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CarouselComponent implements AfterViewInit { + @Input() containerClass = '' + @Input() stepsContainerClass = '' + @ViewChild('carouselOverflowContainer') + carouselOverflowContainer: ElementRef + steps: number[] = [] + selectedStep = -1 + emblaApi: EmblaCarouselType + + constructor(private changeDetector: ChangeDetectorRef) {} + + ngAfterViewInit() { + this.emblaApi = EmblaCarousel( + this.carouselOverflowContainer.nativeElement, + { + duration: 15, + } + ) + const refreshSteps = () => { + this.steps = this.emblaApi.scrollSnapList() + this.selectedStep = this.emblaApi.selectedScrollSnap() + this.changeDetector.detectChanges() + } + this.emblaApi + .on('init', refreshSteps) + .on('reInit', refreshSteps) + .on('select', refreshSteps) + } + + scrollToStep(stepIndex: number) { + this.emblaApi.scrollTo(stepIndex) + } +} diff --git a/libs/ui/layout/src/lib/ui-layout.module.ts b/libs/ui/layout/src/lib/ui-layout.module.ts index 4cc50c09b6..69a28b9c8b 100644 --- a/libs/ui/layout/src/lib/ui-layout.module.ts +++ b/libs/ui/layout/src/lib/ui-layout.module.ts @@ -6,6 +6,7 @@ import { StickyHeaderComponent } from './sticky-header/sticky-header.component' import { AnchorLinkDirective } from './anchor-link/anchor-link.directive' import { ExpandablePanelButtonComponent } from './expandable-panel-button/expandable-panel-button.component' import { MatIconModule } from '@angular/material/icon' +import { CarouselComponent } from './carousel/carousel.component' @NgModule({ imports: [CommonModule, MatIconModule, TranslateModule.forChild()], @@ -14,12 +15,14 @@ import { MatIconModule } from '@angular/material/icon' StickyHeaderComponent, AnchorLinkDirective, ExpandablePanelButtonComponent, + CarouselComponent, ], exports: [ ExpandablePanelComponent, StickyHeaderComponent, AnchorLinkDirective, ExpandablePanelButtonComponent, + CarouselComponent, ], }) export class UiLayoutModule {} diff --git a/package-lock.json b/package-lock.json index 69e12782d3..78e681ce4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "date-fns": "^2.29.3", "document-register-element": "^1.14.10", "duration-relativetimeformat": "^2.0.3", + "embla-carousel": "^8.0.0-rc14", "express": "^4.17.1", "moment": "^2.29.4", "ng-table-virtual-scroll": "^1.4.1", @@ -17318,6 +17319,11 @@ "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", "dev": true }, + "node_modules/embla-carousel": { + "version": "8.0.0-rc14", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.0.0-rc14.tgz", + "integrity": "sha512-/NLkMFZ7xKryRVYeUjmhbfV63Vr07saPBDwAX2TPMbcaiWwfQfU5Xsc2AiCMZANtwmzsjRK6gSBa7hOy/VXu6g==" + }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", diff --git a/package.json b/package.json index 0a306e27ce..aa9821bc45 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "date-fns": "^2.29.3", "document-register-element": "^1.14.10", "duration-relativetimeformat": "^2.0.3", + "embla-carousel": "^8.0.0-rc14", "express": "^4.17.1", "moment": "^2.29.4", "ng-table-virtual-scroll": "^1.4.1",