diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index 9820d672c98..046056a3bb8 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -37,7 +37,7 @@ export class BreadcrumbsComponent { showBreadcrumbs$: Observable; constructor( - private breadcrumbsService: BreadcrumbsService, + protected breadcrumbsService: BreadcrumbsService, ) { this.breadcrumbs$ = breadcrumbsService.breadcrumbs$; this.showBreadcrumbs$ = breadcrumbsService.showBreadcrumbs$; diff --git a/src/app/item-page/field-components/collections/collections.component.html b/src/app/item-page/field-components/collections/collections.component.html index 7c08ce5c1cc..0df43cc8b30 100644 --- a/src/app/item-page/field-components/collections/collections.component.html +++ b/src/app/item-page/field-components/collections/collections.component.html @@ -1,9 +1,12 @@ - +
{{'item.page.collections.loading' | translate}} diff --git a/src/app/item-page/field-components/collections/collections.component.scss b/src/app/item-page/field-components/collections/collections.component.scss new file mode 100644 index 00000000000..dc851b3dc4b --- /dev/null +++ b/src/app/item-page/field-components/collections/collections.component.scss @@ -0,0 +1,17 @@ +.collections { + list-style-type: disc; + padding-left: 1.5em; + margin: 0; + + li { + margin-bottom: 0.5em; + } + + a { + text-decoration: none; + } + + a:hover { + text-decoration: underline; + } +} \ No newline at end of file diff --git a/src/app/item-page/field-components/collections/collections.component.ts b/src/app/item-page/field-components/collections/collections.component.ts index e70dcfba2c9..bcd9422e98a 100644 --- a/src/app/item-page/field-components/collections/collections.component.ts +++ b/src/app/item-page/field-components/collections/collections.component.ts @@ -47,6 +47,7 @@ import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wr @Component({ selector: 'ds-item-page-collections', + styleUrls: ['./collections.component.scss'], templateUrl: './collections.component.html', imports: [ MetadataFieldWrapperComponent, diff --git a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html index 4cef0a15920..3a8ecd49482 100644 --- a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html +++ b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html @@ -1,5 +1,7 @@ - - {{ linktext || mdValue.value }} + {{getDomain(mdValue.value)}}/... + diff --git a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts index 76c7defe35d..8e0fa153f7e 100644 --- a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts +++ b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts @@ -53,4 +53,19 @@ export class MetadataUriValuesComponent extends MetadataValuesComponent { * The label for this iteration of metadata values */ @Input() label: string; + + /** + * Extract the domain from a URL + * @param url The full URL + * @returns The domain of the URL + */ + getDomain(url: string): string { + try { + const parsedUrl = new URL(url); + return parsedUrl.origin; + } catch (e) { + console.error('Invalid URL:', url); + return url; + } + } } diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.html b/src/app/item-page/field-components/metadata-values/metadata-values.component.html index 4fc0b41136c..d92545f1dac 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.html +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.html @@ -4,7 +4,7 @@ Choose a template. Priority: markdown, link, browse link. --> + context: {value: mdValue.value, authority: mdValue.authority, img}"> @@ -39,12 +39,12 @@ - {{value}} + - + {{value}} + [queryParams]="getQueryParams(value, authority)">{{value}} diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index 354879de2bd..3a0ba29da72 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -115,8 +115,8 @@ export class MetadataValuesComponent implements OnChanges { * definition is metadata browse, or item browse * @param value the specific metadata value being linked */ - getQueryParams(value) { - const queryParams = { startsWith: value }; + getQueryParams(value, authority) { + const queryParams = { value: value, authority: authority }; // todo: should compare with type instead? // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison if (this.browseDefinition.getRenderType() === VALUE_LIST_BROWSE_DEFINITION.value) { diff --git a/src/app/menu-resolver.service.ts b/src/app/menu-resolver.service.ts index 683111b32ad..2e9faeb3b68 100644 --- a/src/app/menu-resolver.service.ts +++ b/src/app/menu-resolver.service.ts @@ -99,50 +99,112 @@ export class MenuResolverService { createPublicMenu$(): Observable { const menuList: any[] = [ /* Communities & Collections tree */ - { - id: `browse_global_communities_and_collections`, + // { + // id: `browse_global_communities_and_collections`, + // active: false, + // visible: true, + // index: 0, + // model: { + // type: MenuItemType.LINK, + // text: `menu.section.browse_global_communities_and_collections`, + // link: `/community-list`, + // } as LinkMenuItemModel, + // }, + ]; + + const itemsInstitucional = [ + { id: '¿Qué es SEDICI?', texto: '¿Qué es SEDICI?', ruta: '¿Qué es SEDICI?' }, + { id: 'Políticas del repositorio', texto: 'Políticas del repositorio', ruta: 'Políticas del repositorio' }, + { id: 'Links', texto: 'Links', ruta: 'Links' }, + { id: 'Staff', texto: 'Staff', ruta: 'Staff' }, + { id: '¿Cómo llegar?', texto: '¿Cómo llegar?', ruta: '¿Cómo llegar?' }, + ]; + itemsInstitucional.forEach(item => { + menuList.push({ + id: item.id, + parentID: 'Institucional', active: false, visible: true, - index: 0, model: { type: MenuItemType.LINK, - text: `menu.section.browse_global_communities_and_collections`, - link: `/community-list`, + text: item.texto, + link: `${item.ruta}`, } as LinkMenuItemModel, - }, + }); + }); + menuList.push({ + id: 'Institucional', + active: false, + visible: true, + index: 3, + model: { + type: MenuItemType.TEXT, + text: 'Institucional', + } as TextMenuItemModel, + }); + + const itemsPreguntasFrecuentes = [ + { id: '¿Cómo agregar trabajos?', texto: '¿Cómo agregar trabajos?', ruta: '¿Cómo agregar trabajos?' }, + { id: 'Información para tesistas', texto: 'Información para tesistas', ruta: 'Información para tesistas' }, + { id: 'Revistas de Acceso Abierto', texto: 'Revistas de Acceso Abierto', ruta: 'Revistas de Acceso Abierto' }, + { id: 'Más preguntas frecuentes', texto: 'Más preguntas frecuentes', ruta: 'Más preguntas frecuentes' }, ]; + itemsPreguntasFrecuentes.forEach(item => { + menuList.push({ + id: item.id, + parentID: 'PreguntasFrecuentes', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: item.texto, + link: `${item.ruta}`, + } as LinkMenuItemModel, + }); + }); + menuList.push({ + id: 'PreguntasFrecuentes', + active: false, + visible: true, + index: 4, + model: { + type: MenuItemType.TEXT, + text: 'Preguntas frecuentes', + } as TextMenuItemModel, + }); + // Read the different Browse-By types from config and add them to the browse menu this.browseService.getBrowseDefinitions() .pipe(getFirstCompletedRemoteData>()) .subscribe((browseDefListRD: RemoteData>) => { - if (browseDefListRD.hasSucceeded) { - browseDefListRD.payload.page.forEach((browseDef: BrowseDefinition) => { - menuList.push({ - id: `browse_global_by_${browseDef.id}`, - parentID: 'browse_global', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: `menu.section.browse_global_by_${browseDef.id}`, - link: `/browse/${browseDef.id}`, - } as LinkMenuItemModel, - }); - }); - menuList.push( - /* Browse */ - { - id: 'browse_global', - active: false, - visible: true, - index: 1, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.browse_global', - } as TextMenuItemModel, - }, - ); - } + // if (browseDefListRD.hasSucceeded) { + // browseDefListRD.payload.page.forEach((browseDef: BrowseDefinition) => { + // menuList.push({ + // id: `browse_global_by_${browseDef.id}`, + // parentID: 'browse_global', + // active: false, + // visible: true, + // model: { + // type: MenuItemType.LINK, + // text: `menu.section.browse_global_by_${browseDef.id}`, + // link: `/browse/${browseDef.id}`, + // } as LinkMenuItemModel, + // }); + // }); + // menuList.push( + // /* Browse */ + // { + // id: 'browse_global', + // active: false, + // visible: true, + // index: 4, + // model: { + // type: MenuItemType.TEXT, + // text: 'menu.section.browse_global', + // } as TextMenuItemModel, + // }, + // ); + // } menuList.forEach((menuSection) => this.menuService.addSection(MenuID.PUBLIC, Object.assign(menuSection, { shouldPersistOnRouteChange: true, }))); diff --git a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html index 0af5c706b76..31e4b6f0749 100644 --- a/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html +++ b/src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.html @@ -15,7 +15,7 @@ [attr.aria-controls]="expandableNavbarSectionId()" class="d-flex flex-row flex-nowrap align-items-center gapx-1 ds-menu-toggler-wrapper" [class.disabled]="section.model?.disabled"> - + diff --git a/src/app/root/root.component.ts b/src/app/root/root.component.ts index b5c1c9be48e..526504a4b35 100644 --- a/src/app/root/root.component.ts +++ b/src/app/root/root.component.ts @@ -12,6 +12,7 @@ import { import { Router, RouterOutlet, + NavigationEnd, } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { @@ -19,12 +20,14 @@ import { combineLatest as combineLatestObservable, Observable, of, + Subscription, } from 'rxjs'; import { first, map, skipWhile, startWith, + filter, } from 'rxjs/operators'; import { INotificationBoardOptions } from 'src/config/notifications-config.interfaces'; @@ -40,7 +43,7 @@ import { import { ThemedFooterComponent } from '../footer/themed-footer.component'; import { ThemedHeaderNavbarWrapperComponent } from '../header-nav-wrapper/themed-header-navbar-wrapper.component'; import { slideSidebarPadding } from '../shared/animations/slide'; -import { HostWindowService } from '../shared/host-window.service'; +import { HostWindowService, WidthCategory } from '../shared/host-window.service'; import { LiveRegionComponent } from '../shared/live-region/live-region.component'; import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component'; import { MenuService } from '../shared/menu/menu.service'; @@ -82,6 +85,12 @@ export class RootComponent implements OnInit { browserOsClasses = new BehaviorSubject([]); + isMobile$: Observable; + maxMobileWidth = WidthCategory.SM; + + public isHomePage$: BehaviorSubject = new BehaviorSubject(false); + private routerSubscription: Subscription; + /** * Whether or not to show a full screen loader */ @@ -135,6 +144,34 @@ export class RootComponent implements OnInit { if (this.router.url === getPageInternalServerErrorRoute()) { this.shouldShowRouteLoader = false; } + + this.isMobile$ = this.windowService.isUpTo(this.maxMobileWidth); + + const currentUrl = this.router.url; + this.isHomePage$.next(this.isHomeUrl(currentUrl)); + + this.routerSubscription = this.router.events.pipe( + filter(event => event instanceof NavigationEnd), + map((event: NavigationEnd) => { + const isHome = this.isHomeUrl(event.urlAfterRedirects); + return isHome; + }) + ).subscribe(isHome => { + this.isHomePage$.next(isHome); + }); + } + + ngOnDestroy() { + // Importante: limpiar la suscripción para evitar pérdidas de memoria + if (this.routerSubscription) { + this.routerSubscription.unsubscribe(); + } + } + + private isHomeUrl(url: string): boolean { + return url === '/' || + url === '/home' || + url.startsWith('/home?'); } skipToMainContent() { diff --git a/src/app/shared/file-download-link/file-download-link.component.ts b/src/app/shared/file-download-link/file-download-link.component.ts index 3080a94bd3e..f0ff05f0761 100644 --- a/src/app/shared/file-download-link/file-download-link.component.ts +++ b/src/app/shared/file-download-link/file-download-link.component.ts @@ -73,7 +73,7 @@ export class FileDownloadLinkComponent implements OnInit { canDownload$: Observable; constructor( - private authorizationService: AuthorizationDataService, + protected authorizationService: AuthorizationDataService, public dsoNameService: DSONameService, ) { } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html index 5463b068276..93280cbf4e4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html @@ -16,7 +16,7 @@
    -
  • {{entry.value}}
  • +
  • {{entry.display}}
diff --git a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html index 7748e385ca4..a5b9f9851d8 100644 --- a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html +++ b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html @@ -1,6 +1,6 @@ -
-

{{ label }}

-
+
+
{{ label }}
+
diff --git a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss index bf17d63d6c6..a40e3d85881 100644 --- a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss +++ b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss @@ -1,8 +1,24 @@ -:host { - .simple-view-element { - margin-bottom: 15px; +.simple-view-element { + margin-bottom: .5rem; + h6 { + display: inline; + margin-right: 0.5em; } - .simple-view-element-header { - font-size: 1.25rem; + div { + display: inline; + } +} + +.simple-view-element-header { + font-weight: bold; +} + +.not-inline-label { + h6 { + display: block; + margin-right: 0; + } + div { + display: block; } } diff --git a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts index af139e78e6f..fae5b6f6b39 100644 --- a/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts +++ b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts @@ -1,4 +1,4 @@ -import { NgIf } from '@angular/common'; +import { NgIf, NgClass } from '@angular/common'; import { Component, Input, @@ -13,7 +13,7 @@ import { styleUrls: ['./metadata-field-wrapper.component.scss'], templateUrl: './metadata-field-wrapper.component.html', standalone: true, - imports: [NgIf], + imports: [NgIf, NgClass], }) export class MetadataFieldWrapperComponent { @@ -23,4 +23,6 @@ export class MetadataFieldWrapperComponent { @Input() label: string; @Input() hideIfNoTextContent = true; + + @Input() inlineLabel: boolean = true; } diff --git a/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts b/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts index 0b86b782f6f..249d4ba7036 100644 --- a/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts +++ b/src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts @@ -62,7 +62,7 @@ export class AccessStatusBadgeComponent implements OnDestroy, OnInit { * * @param {AccessStatusDataService} accessStatusDataService */ - constructor(private accessStatusDataService: AccessStatusDataService) { } + constructor(protected accessStatusDataService: AccessStatusDataService) { } ngOnInit(): void { this.showAccessStatus = environment.item.showAccessStatuses; diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-filter.component.ts index 734e372e5b5..b8cc8511de5 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-filter.component.ts @@ -150,6 +150,9 @@ export class SearchFilterComponent implements OnInit, OnChanges, OnDestroy { this.isVisibilityComputed.emit(true); }), ); + if(this.filter.name === 'itemtype') { + this.filterService.expand(this.filter.name); + } } ngOnChanges(): void { diff --git a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.html b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.html index 55ebe2d9575..94004f75be8 100644 --- a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.html +++ b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.html @@ -1,5 +1,5 @@
-
+
-
- - - -
-
- -
- -
- - - -
-
- -
- -
+
+ +
+ + +
+ + +
+
- - - -
-
- - +
- - + \ No newline at end of file diff --git a/src/themes/custom/app/header/header.component.scss b/src/themes/custom/app/header/header.component.scss index dd3bbd310d0..52890f1bca3 100644 --- a/src/themes/custom/app/header/header.component.scss +++ b/src/themes/custom/app/header/header.component.scss @@ -1,14 +1,41 @@ :host { + + #main-site-header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1025; + border-bottom: 3px var(--sedici-color) solid; + + @media (max-width: 767px) { + border-bottom: 0px; + padding: 10px; + } + } + + .color-header { + background-color: var(--sedici-color); + + .toggler-icon { + color: white; + } + } + + img#header-logo { + height: 100vh; + max-height: var(--ds-header-logo-height); + } + header { background-color: var(--ds-header-bg); } - .navbar-brand img { - max-height: var(--ds-header-logo-height); - //max-width: 100%; + .navbar-brand { + margin-right: 0px; } - .navbar-toggler { + #navbar-toggler { border: none; color: var(--ds-header-icon-color); @@ -31,16 +58,38 @@ margin-right: 20px; } - .botones-header{ - //padding-right: 13%; + .left-container { display: flex; - flex-direction: row; + flex-basis: 100%; + } + + .right-container-mobile { + display: flex; + align-items: center; + justify-content: end; + padding: 0 .5rem; + flex-basis: 100%; + + ds-search-navbar { + width: 100%; + } + } + + .right-container { + display: flex; + justify-content: end; + align-items: center; - .btn{ - white-space: nowrap; /* Asegura que el texto no se envuelva */ - width: auto; /* Asegura que el botón se ajuste al contenido */ + ds-search-navbar { + width: 450px; } } + ::ng-deep ds-navbar .container{ + max-width: 100%; + } + ::ng-deep ds-navbar ds-lang-switch .dropdown-item{ + padding: 0.25rem; + } } diff --git a/src/themes/custom/app/header/header.component.ts b/src/themes/custom/app/header/header.component.ts index 279b6fc852c..9c0d7316349 100644 --- a/src/themes/custom/app/header/header.component.ts +++ b/src/themes/custom/app/header/header.component.ts @@ -1,11 +1,17 @@ import { AsyncPipe, NgIf, + NgClass, } from '@angular/common'; -import { Component, NgModule } from '@angular/core'; -import { RouterLink } from '@angular/router'; +import { + Component, + OnInit, +} from '@angular/core'; +import { Router, RouterLink, NavigationEnd } from '@angular/router'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; +import { Observable, BehaviorSubject, Subscription } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { ThemedLangSwitchComponent } from 'src/app/shared/lang-switch/themed-lang-switch.component'; import { ContextHelpToggleComponent } from '../../../../app/header/context-help-toggle/context-help-toggle.component'; @@ -15,6 +21,8 @@ import { ThemedAuthNavMenuComponent } from '../../../../app/shared/auth-nav-menu import { ImpersonateNavbarComponent } from '../../../../app/shared/impersonate-navbar/impersonate-navbar.component'; import { ThemedNavbarComponent } from '../../../../app/navbar/themed-navbar.component'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { MenuService } from 'src/app/shared/menu/menu.service'; +import { HostWindowService } from 'src/app/shared/host-window.service'; /** * Represents the header with the logo and simple navigation @@ -26,7 +34,48 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; templateUrl: 'header.component.html', // templateUrl: '../../../../app/header/header.component.html', standalone: true, - imports: [RouterLink, ThemedLangSwitchComponent, NgbDropdownModule, ThemedSearchNavbarComponent, ThemedNavbarComponent, ContextHelpToggleComponent, ThemedAuthNavMenuComponent, ImpersonateNavbarComponent, TranslateModule, AsyncPipe, NgIf, NgbModule], + imports: [RouterLink, ThemedLangSwitchComponent, NgbDropdownModule, ThemedSearchNavbarComponent, ThemedNavbarComponent, ContextHelpToggleComponent, ThemedAuthNavMenuComponent, ImpersonateNavbarComponent, TranslateModule, AsyncPipe, NgIf, NgClass, NgbModule], }) -export class HeaderComponent extends BaseComponent { +export class HeaderComponent extends BaseComponent implements OnInit { + public isNavBarCollapsed$: Observable; + public isHomePage$: BehaviorSubject = new BehaviorSubject(false); + private routerSubscription: Subscription; + + constructor(protected menuService: MenuService, protected windowService: HostWindowService, private router: Router) { + super(menuService, windowService); + } + + ngOnInit() { + super.ngOnInit(); + this.isNavBarCollapsed$ = this.menuService.isMenuCollapsed(this.menuID); + + // Verifica la URL inicial al cargar + const currentUrl = this.router.url; + this.isHomePage$.next(this.isHomeUrl(currentUrl)); + + // Detecta cambios en la URL mientras navegas + this.routerSubscription = this.router.events.pipe( + filter(event => event instanceof NavigationEnd), + map((event: NavigationEnd) => { + const isHome = this.isHomeUrl(event.urlAfterRedirects); + return isHome; + }) + ).subscribe(isHome => { + this.isHomePage$.next(isHome); + }); + } + + ngOnDestroy() { + // Importante: limpiar la suscripción para evitar pérdidas de memoria + if (this.routerSubscription) { + this.routerSubscription.unsubscribe(); + } + } + + // Método helper para determinar si una URL es la página de inicio + private isHomeUrl(url: string): boolean { + return url === '/' || + url === '/home' || + url.startsWith('/home?'); + } } diff --git a/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.html b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.html new file mode 100644 index 00000000000..1d05e52c2b3 --- /dev/null +++ b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.html @@ -0,0 +1,21 @@ + + + + + +
+

{{title}}

+ +
+
\ No newline at end of file diff --git a/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.scss b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.scss new file mode 100644 index 00000000000..fa94dc26be1 --- /dev/null +++ b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.scss @@ -0,0 +1,93 @@ +.section-destacados { + margin: 2rem 0; + + .section-title { + position: relative; + text-align: center; + color: #333; + padding: 0.25rem 0; + font-size: 1rem; + letter-spacing: 1px; + + &::before, + &::after { + content: ""; + position: absolute; + top: 50%; + width: 100%; + height: 1px; + background-color: #d4d4d4; + } + + &::before { + margin-left: -102%; + width: 100%; + margin-right: 15px; + } + + &::after { + margin-left: 2%; + width: 100%; + } + } + + .section-grid { + display: flex; + gap: 2rem; + + .section-item { + text-align: center; + + .img-container { + margin-bottom: 1rem; + height: 100px; + display: flex; + align-items: center; + justify-content: center; + + img { + max-width: 100%; + max-height: 100px; + object-fit: contain; + } + } + + .section-texto { + p { + color: #666; + } + } + } + } + + @media (max-width: 767px) { + .section-grid { + overflow-x: auto; + + .section-item { + min-width: 30vw; // Me aseguro que aparazcan 2 y 1/2 para que sepa que se puede deslizar + } + } + + .section-grid .section-item.multi-row .img-container { + margin-bottom: 0rem; + height: auto; + } + } + + @media (min-width: 768px) { + .section-grid { + flex-wrap: wrap; + justify-content: space-around; + align-items: center; + } + + .single-row { + flex: 0 1 150px; + } + + .multi-row { + flex: 0 1 250px; + } + } +} diff --git a/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.ts b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.ts new file mode 100644 index 00000000000..7bdaeed40d2 --- /dev/null +++ b/src/themes/custom/app/home-page/comcol-grid/comcol-grid.component.ts @@ -0,0 +1,202 @@ +import { + NgClass, + NgIf, + NgTemplateOutlet, + NgFor, +} from '@angular/common'; +import { RouterLink } from '@angular/router'; +import { Component } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; + +interface ExploracionDestacada { + title: string; + img: string; + href: string; + description?: string; +} +@Component({ + selector: 'comcol-grid', + styleUrls: ['./comcol-grid.component.scss'], + templateUrl: './comcol-grid.component.html', + standalone: true, + imports: [NgTemplateOutlet, NgIf, NgFor, RouterLink, TranslateModule, NgClass], +}) +export class ComcolGridComponent { + + coleccionesDestacadas:Array = [ + { + title: "Red de Museos de la UNLP", + img: "assets/custom/images/ComCol/redmuseos.png", + href: "handle/10915/27268", + } as ExploracionDestacada, + { + title: "Red de Universidades con Carreras en Informática (RedUNCI)", + img: "assets/custom/images/ComCol/redunci.png", + href: "handle/10915/18267", + } as ExploracionDestacada, + { + title: "Radio Universidad Nacional de La Plata", + img: "assets/custom/images/ComCol/Logo_Radio_Universidad.png", + href: "handle/10915/25224", + } as ExploracionDestacada, + { + title: "Dirección General de Educación a Distancia y Tecnologías (EAD)", + img: "assets/custom/images/ComCol/ead.png", + href: "handle/10915/21328", + } as ExploracionDestacada, + { + title: "Sociedad Argentina de Informática (SADIO)", + img: "assets/custom/images/ComCol/sadio.jpg", + href: "handle/10915/38367", + } as ExploracionDestacada, + { + title: "Presidencia", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "handle/10915/47", + } as ExploracionDestacada, + ]; + + facultades:Array = [ + { + title: "Facultad de Arquitectura y Urbanismo", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/25", + description: "Arquitectura y Urbanismo", + } as ExploracionDestacada, + { + title: "Facultad de Artes", + img: "assets/custom/images/ComCol/artes.png", + href: "/handle/10915/38", + description: "Artes", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Agrarias y Forestales", + img: "assets/custom/images/ComCol/fca.png", + href: "/handle/10915/10", + description: "Ciencias Agrarias y Forestales", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Astronómicas y Geofísicas", + img: "assets/custom/images/ComCol/astronomia.png", + href: "/handle/10915/15", + description: "Ciencias Astronómicas y Geofísicas", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Económicas", + img: "assets/custom/images/ComCol/fce.png", + href: "/handle/10915/33", + description: "Ciencias Económicas", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Exactas", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/22", + description: "Ciencias Exactas", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Jurídicas y Sociales", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/7", + description: "Ciencias Jurídicas y Sociales", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Médicas", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/44", + description: "Ciencias Médicas", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Naturales y Museo", + img: "assets/custom/images/ComCol/museo.png", + href: "/handle/10915/41", + description: "Ciencias Naturales y Museo", + } as ExploracionDestacada, + { + title: "Facultad de Ciencias Veterinarias", + img: "assets/custom/images/ComCol/veterinaria.png", + href: "/handle/10915/5", + description: "Ciencias Veterinarias", + } as ExploracionDestacada, + { + title: "Facultad de Humanidades y Ciencias de la Educación", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/30", + description: "Humanidades y Ciencias de la Educación", + } as ExploracionDestacada, + { + title: "Facultad de Informática", + img: "assets/custom/images/ComCol/informatica.png", + href: "/handle/10915/36", + description: "Informática", + } as ExploracionDestacada, + { + title: "Facultad de Ingeniería", + img: "assets/custom/images/ComCol/ing.png", + href: "/handle/10915/2", + description: "Ingeniería", + } as ExploracionDestacada, + { + title: "Facultad de Odontología", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/20", + description: "Odontología", + } as ExploracionDestacada, + { + title: "Facultad de Periodismo y Comunicación Social", + img: "assets/custom/images/ComCol/periodismo.png", + href: "/handle/10915/12", + description: "Periodismo y Comunicación Social", + } as ExploracionDestacada, + { + title: "Facultad de Psicología", + img: "assets/custom/images/ComCol/psicologia.png", + href: "/handle/10915/28", + description: "Psicología", + } as ExploracionDestacada, + { + title: "Facultad de Trabajo Social", + img: "assets/custom/images/ComCol/fts.png", + href: "/handle/10915/18", + description: "Trabajo Social", + } as ExploracionDestacada, + { + title: "Escuela Universitaria de Oficios", + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/102525", + description: "Escuela Universitaria de Oficios", + } as ExploracionDestacada, + ]; + + pregrado:Array = [ + { + title: 'Bachillerato de Bellas Artes "Francisco A. De Santo"', + img: "assets/custom/images/ComCol/bachillerato.png", + href: "/handle/10915/71503", + description: 'Bachillerato de Bellas Artes "Francisco A. De Santo"', + } as ExploracionDestacada, + { + title: 'Colegio Nacional "Rafael Hernández"', + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/65311", + description: 'Colegio Nacional "Rafael Hernández"', + } as ExploracionDestacada, + { + title: 'Escuela de Agricultura y Ganadería "María Cruz y Manuel L. Inchausti"', + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/155239", + description: 'Escuela de Agricultura y Ganadería "María Cruz y Manuel L. Inchausti"', + } as ExploracionDestacada, + { + title: 'Escuela Graduada "Joaquín V. González"', + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/74301", + description: 'Escuela Graduada "Joaquín V. González"', + } as ExploracionDestacada, + { + title: 'Liceo "Víctor Mercante"', + img: "assets/custom/images/ComCol/UNLP_Logo.png", + href: "/handle/10915/73404", + description: 'Liceo "Víctor Mercante"', + } as ExploracionDestacada, + ]; +} diff --git a/src/themes/custom/app/home-page/home-news/home-news.component.html b/src/themes/custom/app/home-page/home-news/home-news.component.html index 338d89224a4..7694c08b508 100644 --- a/src/themes/custom/app/home-page/home-news/home-news.component.html +++ b/src/themes/custom/app/home-page/home-news/home-news.component.html @@ -1,59 +1,40 @@
-
- +
+ Escudo UNLP +
+
+ Logo UNLP
-
- UNLP +
+ Escudo UNLP
- El Servicio de Difusión de la Creación Intelectual es el Repositorio Institucional de la Universidad Nacional de La Plata, un servicio libre y gratuito creado para albergar, preservar y dar visibilidad a las producciones de las Unidades Académicas de la Universidad + El Servicio de Difusión de la Creación Intelectual es el Repositorio Institucional de la Universidad Nacional de La Plata, un servicio libre y gratuito creado para albergar, preservar y dar visibilidad a las producciones de las Unidades Académicas de la Universidad.
- + +
-
-
-
- UNLP -
-
-

Autores

-

Profesores, investigadores, estudiantes u otros colaboradores

-
-
-
-
- UNLP -
-
-

Publicaciones

-

Revistas, libras, informes tecincos, trabajos de conferencias, tesis ...

-
-
-
-
- UNLP -
-
-

Unidades Academicas

-

Facultades, colegios, laboratorios, institutos, centros, unidades academicas ...

-
-
-
-
- UNLP -
-
-

Datos

-

Conjuntos de datos recopilados, resultados de encuestas ...

+ + - - -
diff --git a/src/themes/custom/app/home-page/home-news/home-news.component.scss b/src/themes/custom/app/home-page/home-news/home-news.component.scss index a5769cd37a1..843db409bb8 100644 --- a/src/themes/custom/app/home-page/home-news/home-news.component.scss +++ b/src/themes/custom/app/home-page/home-news/home-news.component.scss @@ -2,79 +2,65 @@ display: block; div.background-image-container { - color: white; position: relative; - - .background-image > img { - background-color: var(--bs-info); - position: absolute; - z-index: -1; - top: 0; - left: 0; - width: 100%; - height: 100%; - object-fit: cover; - object-position: top; - } - - .container { - position: relative; - text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6); - - &:before, &:after { - content: ''; - display: block; - width: var(--ds-banner-background-gradient-width); - height: 100%; - top: 0; - position: absolute; - } - - &:before { - background: linear-gradient(to left, var(--ds-banner-text-background), transparent); - left: calc(-1 * var(--ds-banner-background-gradient-width)); - - } - - &:after { - background: linear-gradient(to right, var(--ds-banner-text-background), transparent); - right: calc(-1 * var(--ds-banner-background-gradient-width)); - } - - background-color: var(--ds-banner-text-background); - } - - - small.credits { - a { - color: inherit; - } - - opacity: 0.3; - position: absolute; - right: var(--bs-spacer); - bottom: 0; + background-image: + linear-gradient(135deg, + rgba(220,235,255,1) 0%, + rgba(210,230,255,1) 5%, + rgba(150,200,255,1) 15%, + rgba(70,150,255,1) 40%, + rgba(0,120,255,1) 60%, + rgba(0,120,255,0.8) 80% + ); + + @media (max-width: 768px) { + background-image: + linear-gradient(to bottom, rgba(0, 123, 255, 0) 80%, white 100%), + linear-gradient(-25deg, white, #007BFF); + background-blend-mode: normal; } } .sedici-description { display: flex; align-items: center; - font-size: 21px; - padding-bottom: 18px; + padding-bottom: 1rem; justify-content: space-between; // Asegura que el contenido esté distribuido adecuadamente } - .logo-container { - display: flex; - align-items: center; // Centra verticalmente la imagen y el texto - width: 25%; + @media screen and (min-width: map-get($grid-breakpoints, md)) { + .escudo-container { + margin-right: 1rem; + } + } + + @media screen and (max-width: map-get($grid-breakpoints, md)) { + flex-direction: column; + text-align: left; + + .escudo-container { + width: 50%; + } + + .text { + width: 100%; + font-size: 0.75rem; + line-height: 2.5; + text-align: justify; + } } .jumbotron { background-color: transparent; - padding-bottom: 20px; + padding-bottom: 0px; margin-bottom: 0px; + + @media screen and (max-width: map-get($grid-breakpoints, md)) { + .sedici-logo-container { + text-align: center; + margin-bottom: 1rem; + } + } } a { @@ -85,39 +71,55 @@ } } - .horizontal-sections { - display: flex; - justify-content: space-between; /* Espacio igual entre las secciones */ - text-align: left; /* Centra el texto dentro de cada sección */ + .destacado { + padding-bottom: 15px; - .section { - flex: 1; /* Cada sección ocupa la misma cantidad de espacio */ - padding: 10px; /* Espaciado interno */ - margin: 0 10px; /* Espaciado entre las secciones */ + .collection-card { display: flex; - - h3 { - margin-bottom: 10px; /* Espacio debajo del título */ - font-size: 1.5rem; /* Tamaño del título */ + flex-direction: row; + align-items: center; + text-align: left; + padding: 1rem; + height: 100%; + + .icon-container { + margin-right: 1rem; + + img { + width: 80px; + height: 80px; + object-fit: contain; + } } - - p { - font-size: 1rem; /* Tamaño del texto pequeño */ + + .text-container { + h4 { + font-size: 1rem; + font-weight: bold; + margin-bottom: 0; + } + + p { + font-size: 0.625rem; + color: #333; + margin: 0; + } } - .img-container { - margin-right: 10px; // Espacio entre la imagen y el texto + a { + color: inherit; } - } - - .section:first-child { - margin-left: 25px; /* Elimina el margen izquierdo del primer elemento */ - } - - .section:last-child { - margin-right: 15px; /* Elimina el margen derecho del último elemento */ + + @media (max-width: 767px) { + .collection-card { + .icon-container { + img { + width: 60px; // Un poco más pequeño para ajustar al espacio + height: 60px; + } + } + } } } - } diff --git a/src/themes/custom/app/home-page/home-news/home-news.component.ts b/src/themes/custom/app/home-page/home-news/home-news.component.ts index c428210d1f8..f3755c2c15f 100644 --- a/src/themes/custom/app/home-page/home-news/home-news.component.ts +++ b/src/themes/custom/app/home-page/home-news/home-news.component.ts @@ -1,8 +1,26 @@ -import { Component } from '@angular/core'; +import { + AsyncPipe, + NgIf, + NgFor, +} from '@angular/common'; +import { RouterLink } from '@angular/router'; +import { Component, ChangeDetectorRef } from '@angular/core'; +import { Observable } from 'rxjs'; +import { HostWindowService, WidthCategory } from 'src/app/shared/host-window.service'; import { HomeNewsComponent as BaseComponent } from '../../../../../app/home-page/home-news/home-news.component'; import { SearchFormComponent } from '../../shared/search-form/search-form.component'; +import { ThemedSearchNavbarComponent } from 'src/app/search-navbar/themed-search-navbar.component'; +import { environment } from 'src/environments/environment'; +import { HttpClient } from '@angular/common/http'; + +export interface CardItem { + title: string; + img: string; + description: string; + href: string; +} @Component({ selector: 'ds-themed-home-news', styleUrls: ['./home-news.component.scss'], @@ -10,7 +28,7 @@ import { SearchFormComponent } from '../../shared/search-form/search-form.compon templateUrl: './home-news.component.html', //templateUrl: '../../../../../app/home-page/home-news/home-news.component.html', imports:[ - SearchFormComponent, + AsyncPipe, NgIf, NgFor, SearchFormComponent, ThemedSearchNavbarComponent, RouterLink, ], standalone: true, }) @@ -18,5 +36,56 @@ import { SearchFormComponent } from '../../shared/search-form/search-form.compon /** * Component to render the news section on the home page */ -export class HomeNewsComponent extends BaseComponent {} +export class HomeNewsComponent extends BaseComponent { + public isMobile$: Observable; + + maxMobileWidth = WidthCategory.SM; + + constructor( + protected windowService: HostWindowService, + private http: HttpClient, + private cdr: ChangeDetectorRef, + ) { + super() + } + + ngOnInit(): void { + this.isMobile$ = this.windowService.isUpTo(this.maxMobileWidth); + this.loadItemCount(); + } + + totalItems = 0; + + loadItemCount(): void { + const searchUrl = `${environment.rest.baseUrl}/api/discover/search/objects?size=1&page=0`; + + this.http.get(searchUrl).subscribe((response: any) => { + if (response._embedded.searchResult.page.totalElements !== undefined) { + this.totalItems = response._embedded.searchResult.page.totalElements; + this.cdr.detectChanges(); + } + }, (error) => { + console.error('Error al cargar el conteo de items:', error); + }); + } + + cardItems:Array = [ + { + title: "Autores", + img: "assets/custom/images/autores.png", + href: "/browse/author", + description: "Profesores, investigadores, estudiantes u otros colaboradores", + } as CardItem,{ + title: "Publicaciones", + img: "assets/custom/images/publicaciones.png", + href: "/search", + description: "Revistas, libras, informes tecincos, trabajos de conferencias, tesis ..." + } as CardItem,{ + title: "Unidades Academicas", + img: "assets/custom/images/unidades_academicas.png", + href: "/handle/10915/1", + description: "Facultades, colegios, laboratorios, institutos, centros ..." + } as CardItem + ]; +} diff --git a/src/themes/custom/app/home-page/home-page.component.html b/src/themes/custom/app/home-page/home-page.component.html index 62fcc63d34c..9a41708a3ed 100644 --- a/src/themes/custom/app/home-page/home-page.component.html +++ b/src/themes/custom/app/home-page/home-page.component.html @@ -17,56 +17,61 @@ - - - - - - - - - +
+
+

Explorar

+

PRODUCCIÓN DE LA UNLP

+
+ +
-
-
- -
Ayuda para investigadores
-
-
- -
Obligación de depósito en el repositorio
-
-
- -
Estadísticas de crecimiento
-
+ + +
+
+ +
Ayuda para investigadores
+
+
+ +
Obligación de depósito en el repositorio
+
+
+ +
Estadísticas de crecimiento
+
-
+

Aliados

- SNRD Logo - La Referencia Logo - COAR Logo + + SNRD Logo + + + La Referencia Logo + + + COAR Logo +
diff --git a/src/themes/custom/app/home-page/home-page.component.scss b/src/themes/custom/app/home-page/home-page.component.scss index 8bf68bffcc5..daac28c2526 100644 --- a/src/themes/custom/app/home-page/home-page.component.scss +++ b/src/themes/custom/app/home-page/home-page.component.scss @@ -5,52 +5,124 @@ margin: 20px 0; /* Espacio arriba y abajo del título */ } -.destacado { - display: flex; - justify-content: space-around; /* Espacio igual entre las secciones */ - align-items: center; /* Centra verticalmente las secciones */ - flex-wrap: wrap; /* Permite que las secciones se ajusten si no caben en una fila */ - text-align: center; /* Centra el texto dentro de cada sección */ +.explorar-title-container { + margin: 2rem 0 1.5rem 0; - .section { - flex: 1 1 20%; /* Ajusta la flexibilidad de las secciones */ - padding: 10px; /* Espaciado interno */ - margin: 10px; /* Espaciado entre las secciones */ + @media screen and (min-width: map-get($grid-breakpoints, md)) { + text-align: center; + } + + .explorar-title { + color: var(--sedici-color); + font-size: 2rem; + margin-bottom: 0.2rem; + } + + .explorar-subtitle { + color: #666; + font-size: 1rem; + letter-spacing: 0.5px; + margin: 0; + } +} + +.destacado { + .collection-card { display: flex; - align-items: center; /* Centra verticalmente la imagen y el texto */ flex-direction: column; - - img { - width: 120px; /* Anchura de la imagen */ - height: 120px; /* Altura de la imagen */ - margin-bottom: 10px; /* Espacio entre la imagen y el texto */ + align-items: center; + text-align: center; + padding: 15px; + height: 100%; + border-radius: 5px; + box-shadow: 1px 5px rgba(0,0,0,0.1); + + .icon-container { + margin-bottom: 10px; + + img { + width: 80px; + height: 80px; + object-fit: contain; + } } - + .text-container { - display: flex; - flex-direction: column; - align-items: center; /* Centra el texto horizontalmente */ + h4 { + font-size: 1rem; + font-weight: bold; + margin-bottom: 0; + } + + p { + font-size: 0.625rem; + color: #666; + margin: 0; + } } + } - h4 { - margin-bottom: 10px; /* Espacio debajo del título */ - font-size: 1.1rem; /* Tamaño del título */ + a { + color: inherit; + } + + // Estilo para dispositivos medianos y grandes (horizontal) + @media (min-width: 768px) { + .collection-card { + flex-direction: row; + text-align: left; + + .icon-container { + margin-right: 15px; + margin-bottom: 0; + } + + .text-container { + flex: 1; + } } + } - p { - font-size: 1rem; /* Tamaño del texto pequeño */ + // Estilo para dispositivos móviles (grid 2x2) con ícono a la derecha + @media (max-width: 767px) { + .collection-card { + flex-direction: row; // Cambiamos a horizontal para móvil + text-align: left; + padding: 15px; + height: 100%; + justify-content: space-between; // Distribuir espaciado + align-items: center; + + .icon-container { + order: 2; // Mueve el ícono a la derecha + margin-bottom: 0; + margin-left: 10px; // Espacio entre texto e icono + + img { + width: 60px; // Un poco más pequeño para ajustar al espacio + height: 60px; + } + } + + .text-container { + order: 1; // Mueve el texto a la izquierda + flex: 1; + } } } - } .help { - margin-top: 20px; padding: 20px 10%; - height: 300px; - background-color: #cecece; /* Color de fondo similar al de la imagen */ + background-color: #cecece; + + @media screen and (max-width: map-get($grid-breakpoints, md)) { + background-color: white; + gap: 3rem; + box-shadow: 0 -5px rgba(0,0,0,0.1); + } - i{ + i { font-size: 9rem; color:#777777; margin-bottom: 4.5%; @@ -71,7 +143,7 @@ h5 { .aliados-title { flex: 1; text-align: right; - background: linear-gradient(to left, #d1d1d1, #f7f7f7 2%,#fdfdfd 5%); + background: linear-gradient(to left, #d1d1d1, #f7f7f7 1%,#fdfdfd 3%); height: 100%; padding-right: 2%; @@ -88,7 +160,6 @@ h5 { align-items: center; img { - max-width: 150px; /* Ajusta el tamaño de las imágenes */ margin: 0 10px; } } diff --git a/src/themes/custom/app/home-page/home-page.component.ts b/src/themes/custom/app/home-page/home-page.component.ts index 5135f0f635c..6c30c0d675b 100644 --- a/src/themes/custom/app/home-page/home-page.component.ts +++ b/src/themes/custom/app/home-page/home-page.component.ts @@ -1,24 +1,13 @@ -import { CollectionDataService } from './../../../../app/core/data/collection-data.service'; -import { CommunityDataService } from './../../../../app/core/data/community-data.service'; import { AsyncPipe, NgClass, NgIf, NgTemplateOutlet, + NgFor, } from '@angular/common'; -import { - Component, - Inject, - ChangeDetectorRef, -} from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { - filter, - map, - mergeMap, -} from 'rxjs/operators'; -import { RemoteData } from 'src/app/core/data/remote-data'; import { HomeCoarComponent } from '../../../../app/home-page/home-coar/home-coar.component'; import { ThemedHomeNewsComponent } from '../../../../app/home-page/home-news/themed-home-news.component'; @@ -30,22 +19,17 @@ import { ThemedConfigurationSearchPageComponent } from '../../../../app/search-p import { ThemedSearchFormComponent } from '../../../../app/shared/search-form/themed-search-form.component'; import { PageWithSidebarComponent } from '../../../../app/shared/sidebar/page-with-sidebar.component'; import { ViewTrackerComponent } from '../../../../app/statistics/angulartics/dspace/view-tracker.component'; -import { HomeSliderComponent, SliderItem, SliderItem2 } from './sedici-home-slider/home-slider.component'; -import { - APP_CONFIG, - AppConfig, -} from 'src/config/app-config.interface'; -import { ActivatedRoute } from '@angular/router'; -import { getFirstSucceededRemoteDataPayload } from 'src/app/core/shared/operators'; -import { getAllSucceededRemoteDataPayload } from 'src/app/core/shared/operators'; -import { Community } from 'src/app/core/shared/community.model'; +import { HomeSliderComponent } from './sedici-home-slider/home-slider.component'; import { ComcolPageLogoComponent } from 'src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component'; -import { Bitstream } from 'src/app/core/shared/bitstream.model'; -import { Collection } from 'src/app/core/shared/collection.model'; -import { hasValue } from 'src/app/shared/empty.util'; -import { FollowLinkConfig, followLink } from 'src/app/shared/utils/follow-link-config.model'; -import { DSpaceObject } from 'src/app/core/shared/dspace-object.model'; -import { COMMUNITY_PAGE_LINKS_TO_FOLLOW } from 'src/app/community-page/community-page.resolver'; +import { ComcolGridComponent } from './comcol-grid/comcol-grid.component'; + +interface ExploracionDestacada { + title: string; + img: string; + href: string; + description?: string; + queryParams?: {[key: string]: any}; +} @Component({ selector: 'ds-themed-home-page', styleUrls: ['./home-page.component.scss'], @@ -53,120 +37,46 @@ import { COMMUNITY_PAGE_LINKS_TO_FOLLOW } from 'src/app/community-page/community templateUrl: './home-page.component.html', // templateUrl: '../../../../app/home-page/home-page.component.html', standalone: true, - imports: [ThemedHomeNewsComponent, ComcolPageLogoComponent, NgTemplateOutlet, NgIf, ViewTrackerComponent, ThemedSearchFormComponent, ThemedTopLevelCommunityListComponent, RecentItemListComponent, AsyncPipe, TranslateModule, NgClass, SuggestionsPopupComponent, ThemedConfigurationSearchPageComponent, PageWithSidebarComponent, HomeCoarComponent, HomeSliderComponent], + imports: [ThemedHomeNewsComponent, ComcolPageLogoComponent, NgTemplateOutlet, NgIf, NgFor, RouterLink, ViewTrackerComponent, ThemedSearchFormComponent, ThemedTopLevelCommunityListComponent, RecentItemListComponent, AsyncPipe, TranslateModule, NgClass, SuggestionsPopupComponent, ThemedConfigurationSearchPageComponent, PageWithSidebarComponent, HomeCoarComponent, HomeSliderComponent, ComcolGridComponent], }) export class HomePageComponent extends BaseComponent { - aux = 0; - numCollection = this.appConfig.highlightCollections.length; - highlightCollections: any; - collectionName: String; - logo: Bitstream; - logoRD$: Observable>; - communityRD$: Observable>; - collectionRD$: Observable>; - //linksToFollow: FollowLinkConfig[] = COMMUNITY_PAGE_LINKS_TO_FOLLOW as FollowLinkConfig[]; - comlinksToFollow: FollowLinkConfig[] = [ - followLink('logo'), - ]; - collinksToFollow: FollowLinkConfig[] = [ - followLink('logo'), - ]; - - colecciones:Array = [ + exploraciones:Array = [ { title: "Revistas", img: "assets/custom/images/revistas.png", - href: "", - description: "Tesis de grado, postgrado y otros documentos", - } as SliderItem,{ + href: "/handle/10915/51", + description: "123.456", + } as ExploracionDestacada, + { title: "Eventos", img: "assets/custom/images/eventos.png", - href: "", - description: "Tesis de grado, postgrado y otros documentos" - } as SliderItem,{ + href: "/handle/10915/1038", + description: "123.456" + } as ExploracionDestacada, + { title: "Libros", img: "assets/custom/images/libros2.png", - href: "", - description: "Tesis de grado, postgrado y otros documentos" - } as SliderItem,{ - title: "Tesis", - img: "assets/custom/images/tesis.png", - href: "", - description: "Tesis de grado, postgrado y otros documentos" - } as SliderItem - ]; - - carrousel2 :SliderItem2[][] = []; - - constructor( - @Inject(APP_CONFIG) protected appConfig: AppConfig, - protected route: ActivatedRoute, - protected comuds: CommunityDataService, - protected collds: CollectionDataService, - protected cdr: ChangeDetectorRef - ) { - super(appConfig, route); - this.highlightCollections = this.appConfig.highlightCollections; - } - - - ngOnInit(): void { - super.ngOnInit(); - const resultado = []; - for (let i = 0; i < this.appConfig.highlightCollections.length; i += 5) { - const subarreglo = this.appConfig.highlightCollections.slice(i, i + 5); - resultado.push(subarreglo); - } - for (const arreglo of resultado){ - const slider = []; - for (const uuid of arreglo){ - if(uuid.type == "com"){ - this.communityRD$ = this.comuds.findById( - uuid.id, - true, - true, - ...this.comlinksToFollow, - ); - this.communityRD$.pipe( - getFirstSucceededRemoteDataPayload(), - ).subscribe((community: Community) => { - slider.push( - {title: community.name, - href:"/communities/"+uuid.id, - img: community.logo}as SliderItem2 - ); - console.log(this.carrousel2); - this.logoRD$ = community.logo; - this.aux += 1; - console.log(this.aux); - this.cdr.detectChanges(); - }); - }else{ - this.collectionRD$ = this.collds.findById( - uuid.id, - true, - true, - ...this.collinksToFollow, - ); - this.collectionRD$.pipe( - getFirstSucceededRemoteDataPayload(), - ).subscribe((collection: Collection) => { - slider.push( - {title: collection.name, - href:"/collections/"+uuid.id, - img: collection.logo}as SliderItem2 - ); - console.log(this.carrousel2); - this.logoRD$ = collection.logo; - this.aux += 1; - console.log(this.aux); - this.cdr.detectChanges(); - }); - } + href: "/search", + description: "123.456", + queryParams: { + "spc.page": 1, + "f.itemtype": "Libro,equals", + "spc.sf": "dc.date.accessioned", + "spc.sd": "DESC" } - this.carrousel2.push(slider) - } - } - + } as ExploracionDestacada, + { + title: "Datos", + img: "assets/custom/images/datos.png", + href: "/search", + description: "123.456", + queryParams: { + "spc.page": 1, + "f.itemtype": "Conjunto de datos,equals", + "spc.sf": "dc.date.accessioned", + "spc.sd": "DESC" + } + } as ExploracionDestacada, + ]; } diff --git a/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.html b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.html new file mode 100644 index 00000000000..013d0e9da99 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.html @@ -0,0 +1,27 @@ + + + + + + + +
+ + {{badgeLabel}} + + + {{ mdValue.value }} + + + {{ mdValue.value }} + + + + {{mdValue.value}} + + + + + +
+
diff --git a/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.scss b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.scss new file mode 100644 index 00000000000..efb9fedb7be --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.scss @@ -0,0 +1,63 @@ +.badge-group { + display: inline-flex; + margin-right: 0.5rem; + + .badge { + font-size: 1.1667em; + font-weight: var(--font-weight-regular); + border-radius: 0px; + padding: 0; + } + + .badge-label { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + color: white; + background-color: #706f6f; + border: 1px solid #706f6f; + padding: 0.35em 0.5em; + } + + .badge-content { + display: flex; + align-items: center; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + background-color: white; + color: #706f6f; + + a.no-format { + border: 1px solid #dee2e6; + padding: 0.35em; + color: inherit; + text-decoration: none; + } + + .plainText { + border: 1px solid #dee2e6; + padding: 0.35em; + } + } +} + +.copy-button-wrapper { + display: inline-block; + background-color: #f6f6f6; + border: 1px solid #b3b1b4; + padding: .35em; + line-height: 1; + vertical-align: middle; + cursor: pointer; +} + +.copy-button-wrapper:hover { + background-color: #e9ecef; +} + +.copyButton { + color: #b3b1b4; + font-size: 0.85em; + background: none; + border: none; + padding: 0; +} diff --git a/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.ts b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.ts new file mode 100644 index 00000000000..fdba85e4bab --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/badge-metadata-values/badge-metadata-values.component.ts @@ -0,0 +1,38 @@ +import { Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { MetadataValuesComponent } from 'src/app/item-page/field-components/metadata-values/metadata-values.component'; +import { MetadataFieldWrapperComponent } from 'src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component'; + +@Component({ + selector: 'ds-badge-metadata-values', + standalone: true, + templateUrl: './badge-metadata-values.component.html', + styleUrls: ['./badge-metadata-values.component.scss'], + imports: [CommonModule, MetadataFieldWrapperComponent, TranslateModule], +}) +export class BadgeMetadataValuesComponent extends MetadataValuesComponent { + @Input() badgeType: string; + @Input() badgeUrl: string; + @Input() badgeLabel: string; + @Input() badgeLabelType: string; + @Input() copyToClipboardButton: boolean = false; + @Input() url: string; + + copyToClipboard(el: HTMLDivElement, id: string) { + if (navigator.clipboard) { + navigator.clipboard.writeText(el.innerText).then(() => { + document.getElementById(id).classList.remove('fa-copy'); + document.getElementById(id).classList.add('fa-check'); + setTimeout(() => { + document.getElementById(id).classList.remove('fa-check'); + document.getElementById(id).classList.add('fa-copy'); + }, 1000); + }, (error) => { + console.log(error); + }); + } else { + console.log('Browser do not support Clipboard API'); + } + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.html b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.html new file mode 100644 index 00000000000..e84ee4a6bd1 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.html @@ -0,0 +1,23 @@ + + diff --git a/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.scss b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.scss new file mode 100644 index 00000000000..ddce8e16ff3 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.scss @@ -0,0 +1,32 @@ +.apa-citation-container { + border: 1px dashed #cccccc; + padding: 10px; + border-radius: 5px; + background-color: #f9f9f9; +} + +.apa-citation { + font-style: italic; +} + +.copy-button-container { + display: flex; + justify-content: flex-end; + padding-top: .25rem; + gap: .25rem; +} + +.copy-text { + font-size: .75rem; + color: #666666; +} + +.copyButton { + cursor: pointer; + font-size: 1rem; + transition: color 0.3s; +} + +.copyButton:hover { + color: #42a5f5; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.ts b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.ts new file mode 100644 index 00000000000..52fbbc51bd1 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/citation/sedici-citation.component.ts @@ -0,0 +1,66 @@ +import { CommonModule } from '@angular/common'; +import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'sedici-citation', + templateUrl: './sedici-citation.component.html', + styleUrls: ['./sedici-citation.component.scss'], + standalone: true, + imports: [CommonModule], +}) +export class SediciCitationComponent implements OnInit { + + @ViewChild('elementContentToCopy') elementContentToCopy: ElementRef; + citation: string; + citationType: string = 'apa'; + + citationOptions = [ + { value: 'apa', label: 'APA' }, + { value: 'chicago', label: 'Chicago' }, + { value: 'mla', label: 'MLA' }, + ]; + + constructor(public activeModal: NgbActiveModal) {} + + ngOnInit(): void { + this.generateCitation(this.citationType); + } + + generateCitation(type: string): void { + if (type === 'apa') { + this.citation = 'Melville, H. & Schaeffer, M. (1922) Moby Dick. New York, Dodd, Mead and company. [Pdf] Retrieved from the Library of Congress, https://www.loc.gov/item/22022440/'; + } else if (type === 'chicago') { + this.citation = 'Melville, Herman, and Mead Schaeffer. Moby Dick. New York, Dodd, Mead and company, 1922. Pdf. https://www.loc.gov/item/22022440/'; + } else { + this.citation = 'Melville, Herman, and Mead Schaeffer. Moby Dick. New York, Dodd, Mead and company, 1922. Pdf. Retrieved from the Library of Congress, '; + } + } + + onCitationTypeChange(event: Event): void { + const selectElement = event.target as HTMLSelectElement; + this.citationType = selectElement.value; + this.generateCitation(this.citationType); + } + + copyToClipboard(el: HTMLDivElement, id: string) { + if (navigator.clipboard) { + navigator.clipboard.writeText(el.innerText).then(() => { + document.getElementById(id).classList.remove('fa-copy'); + document.getElementById(id).classList.add('fa-check'); + setTimeout(() => { + document.getElementById(id).classList.remove('fa-check'); + document.getElementById(id).classList.add('fa-copy'); + }, 1000); + }, (error) => { + console.log(error); + }); + } else { + console.log('Browser do not support Clipboard API'); + } + } + + close() { + this.activeModal.close(); + } +} diff --git a/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.html b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.html new file mode 100644 index 00000000000..860059e60a7 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.html @@ -0,0 +1,3 @@ +
+ {{ getContextInfo() }} +
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.scss b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.scss new file mode 100644 index 00000000000..8d5ada13018 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.scss @@ -0,0 +1,3 @@ +span { + line-height: 1.5; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.ts b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.ts new file mode 100644 index 00000000000..cd1af459270 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/context/sedici-context.component.ts @@ -0,0 +1,89 @@ +import { Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DSpaceObject } from 'src/app/core/shared/dspace-object.model'; + +@Component({ + selector: 'sedici-context', + standalone: true, + imports: [CommonModule], + templateUrl: './sedici-context.component.html', + styleUrls: ['./sedici-context.component.scss'] +}) +export class SediciContextComponent { + + @Input() object: DSpaceObject; + + getThesisInfo(): string { + const thesisDegreeName = this.object.firstMetadataValue('thesis.degree.name'); + const thesisDegreeGrantor = this.object.firstMetadataValue('thesis.degree.grantor'); + + if (thesisDegreeName && thesisDegreeGrantor) { + return `${thesisDegreeName}; ${thesisDegreeGrantor}`; + } else { + return ''; + } + } + + getBookInfo(): string { + const bookTitle = this.object.firstMetadataValue('sedici.relation.bookTitle'); + if (bookTitle) { + return bookTitle; + } + return ''; + } + + getJournalInfo(): string { + const journalTitle = this.object.firstMetadataValue('sedici.relation.journalTitle'); + const journalVolumeAndIssue = this.object.firstMetadataValue('sedici.relation.journalVolumeAndIssue'); + + if (journalTitle && journalVolumeAndIssue) { + return `${journalTitle}; ${journalVolumeAndIssue}`; + } else if (journalTitle) { + return journalTitle; + } + return ''; + } + + getEventInfo(): string { + const event = this.object.firstMetadataValue('sedici.relation.event'); + if (event) { + return event; + } + return ''; + } + + getCicloInfo(): string { + const ciclo = this.object.firstMetadataValue('sedici.relation.ciclo'); + if (ciclo) { + return ciclo; + } + return ''; + } + + getContextInfo(): string { + const thesis = this.getThesisInfo(); + if (thesis) { + return thesis; + }; + const bookTitle = this.getBookInfo(); + if (bookTitle) { + return bookTitle; + }; + const journal = this.getJournalInfo(); + const event = this.getEventInfo(); + if (journal || event) { + if (journal && event) { + return `${journal} | ${event}`; + } else if (journal) { + return journal; + } else { + return event; + }; + }; + const ciclo = this.getCicloInfo(); + if (ciclo) { + return ciclo; + }; + return ''; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.html b/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.html new file mode 100644 index 00000000000..3b11b5e5a52 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.html @@ -0,0 +1,3 @@ + + {{ dateString }} + \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.ts b/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.ts new file mode 100644 index 00000000000..5934e092f01 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/date-metadata-values/sedici-date-metadata-values.component.ts @@ -0,0 +1,36 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { MetadataValuesComponent } from 'src/app/item-page/field-components/metadata-values/metadata-values.component'; +import { MetadataFieldWrapperComponent } from 'src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component'; +import { TranslateModule } from '@ngx-translate/core'; + +/** + * This component renders the configured 'values' into the ds-metadata-field-wrapper component. + * It puts the given 'separator' between each two values. + */ +@Component({ + selector: 'ds-sedici-date-metadata-values', + templateUrl: './sedici-date-metadata-values.component.html', + standalone: true, + imports: [ + TranslateModule, + MetadataValuesComponent, + MetadataFieldWrapperComponent, + ], +}) +export class SediciDateMetadataValuesComponent extends MetadataValuesComponent implements OnInit { + @Input() inlineLabel: boolean = true; + dateString: string; + + ngOnInit(): void { + const date = this.mdValues?.[0]?.value; + if (date !== undefined) { + if (date.length === 10 || date.includes('T')) { + this.dateString = new Date(date).toLocaleDateString('es-AR',{ year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }); + } else if (date.length === 7) { + this.dateString = new Date(date).toLocaleDateString('es-AR',{ year: 'numeric', month: 'long', timeZone: 'UTC' }); + } else { + this.dateString = date; + } + } + } +} diff --git a/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.html b/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.html new file mode 100644 index 00000000000..b6fa087014b --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.html @@ -0,0 +1,3 @@ + + {{ languageString }} + \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.ts b/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.ts new file mode 100644 index 00000000000..75831660b47 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/language-metadata-values/sedici-language-metadata-values.component.ts @@ -0,0 +1,36 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { MetadataValuesComponent } from 'src/app/item-page/field-components/metadata-values/metadata-values.component'; +import { MetadataFieldWrapperComponent } from 'src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component'; +import { TranslateModule } from '@ngx-translate/core'; + +/** + * This component renders the configured 'values' into the ds-metadata-field-wrapper component. + * It puts the given 'separator' between each two values. + */ +@Component({ + selector: 'ds-sedici-language-metadata-values', + templateUrl: './sedici-language-metadata-values.component.html', + standalone: true, + imports: [ + TranslateModule, + MetadataValuesComponent, + MetadataFieldWrapperComponent, + ], +}) +export class SediciLanguageMetadataValuesComponent extends MetadataValuesComponent implements OnInit { + @Input() inlineLabel: boolean = true; + languageString: string; + + ngOnInit(): void { + const language = this.mdValues?.[0]?.value; + if (language === 'es') { + this.languageString = 'Español'; + } else if (language === 'en') { + this.languageString = 'Inlgés'; + } else if (language === 'pt') { + this.languageString = 'Portugués'; + } else if (language === 'de') { + this.languageString = 'Alemán'; + } + } +} diff --git a/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.html b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.html new file mode 100644 index 00000000000..f320c034747 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.html @@ -0,0 +1,41 @@ + + + diff --git a/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.scss b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.scss new file mode 100644 index 00000000000..2e6722960f7 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.scss @@ -0,0 +1,68 @@ +.share-modal-content { + padding: 20px; +} + +.link-bar { + display: flex; + align-items: center; + margin-bottom: 1rem; +} + +.share-link { + flex: 1; + padding: .25rem; + border: 1px solid #ccc; + border-radius: 4px; + outline: none; +} + +#copyButton { + margin-left: 5px; + padding: 5px 10px; + border: none; + background-color: #007bff; + color: white; + border-radius: 4px; + cursor: pointer; + outline: none; +} + +#copyButton:hover { + background-color: #0056b3; +} + +.copy-success-message { + color: green; + margin-left: 10px; +} + +.social-buttons { + display: flex; + justify-content: space-around; + padding: 10px 0; +} + +.social-icon-button { + background: none; + border: none; + cursor: pointer; + padding: 0; + outline: none; +} + +.social-icon-button i { + font-size: 3rem; + border-radius: 50%; + transition: transform 0.2s ease; +} + +.social-icon-button:hover i { + transform: scale(1.1); +} + +/* Colores específicos para cada red social */ +.fa-researchgate { color: #63e6be; } +.fa-mendeley { color: #c70039; } +.fa-whatsapp { color: #25d366; } +.fa-linkedin { color: #0077b5; } +.fa-x-twitter { color: black; } diff --git a/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.ts b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.ts new file mode 100644 index 00000000000..c8b0b8c6ee9 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/share-buttons/sedici-share-buttons.component.ts @@ -0,0 +1,70 @@ +import { CommonModule } from '@angular/common'; +import { Component, ViewChild, ElementRef, Input } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { HostWindowService } from 'src/app/shared/host-window.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'sedici-share-buttons', + templateUrl: './sedici-share-buttons.component.html', + styleUrls: ['./sedici-share-buttons.component.scss'], + standalone: true, + imports: [CommonModule], +}) +export class SediciShareButtonsComponent { + + @ViewChild('elementContentToCopy') elementContentToCopy: ElementRef; + @Input() link: string; + @Input() title: string; + @Input() type: string; + isMobile$: Observable; + copySuccess: boolean = false; + + constructor(public activeModal: NgbActiveModal, private windowService: HostWindowService) { + this.isMobile$ = this.windowService.isMobile(); + } + + copyToClipboard(element: HTMLInputElement) { + navigator.clipboard.writeText(element.value).then(() => { + this.copySuccess = true; + setTimeout(() => this.copySuccess = false, 2000); // Ocultar el mensaje después de 2 segundos + }).catch(err => { + console.error('Error al copiar el texto: ', err); + }); + } + + get researchGateLink(): string { + const subject = `${this.type} compartido desde sedici.unlp.edu.ar`; + const text = `¡Hola! Quiero compartir este/a ${this.type} desde el repositorio SEDICI (sedici.unlp.edu.ar).\n${this.title}\n${this.link}`; + return `https://www.researchgate.net/messages?ocmd=1&messageModalSubject=${encodeURIComponent(subject)}&messageModalText=${encodeURIComponent(text)}`; + } + + get mendeleyLink(): string { + return `https://www.mendeley.com/import/?url=${encodeURIComponent(this.link)}`; + } + + get whatsappLink(): string { + let baseURL = ''; + this.isMobile$.subscribe(isMobile => { + if (isMobile) { + baseURL = 'https://api.whatsapp.com/send'; + } else { + baseURL = 'https://web.whatsapp.com/send'; + } + }); + const message = `¡Hola! Quiero compartir este/a ${this.type} desde el repositorio SEDICI (sedici.unlp.edu.ar).\n${this.title}\n${this.link}`; + return `${baseURL}?text=${encodeURIComponent(message)}`; + } + + get linkedinLink(): string { + return `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(this.link)}&title=${encodeURIComponent(this.title)}`; + } + + get xLink(): string { + return `https://x.com/share?text=${encodeURIComponent(this.title)}&url=${encodeURIComponent(this.link)}&via=sedici_unlp`; + } + + close() { + this.activeModal.close(); + } +} diff --git a/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.html b/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.html new file mode 100644 index 00000000000..934552f4937 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.html @@ -0,0 +1,7 @@ +
+ +
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.ts b/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.ts new file mode 100644 index 00000000000..c76d04ae996 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/specific-field/identfier-other/item-page-identifier.other-field.ts @@ -0,0 +1,52 @@ +import { + Component, + Input, +} from '@angular/core'; + +import { Item } from 'src/app/core/shared/item.model'; +import { MetadataValuesComponent } from 'src/app/item-page/field-components/metadata-values/metadata-values.component'; +import { MetadataValue } from 'src/app/core/shared/metadata.models'; + +@Component({ + selector: 'ds-item-page-identifier-other-field', + templateUrl: './item-page-identifier.other-field.html', + standalone: true, + imports: [MetadataValuesComponent], +}) + +export class ItemPageIdentifierOtherFieldComponent{ + + /** + * The item to display metadata for + */ + @Input() item: Item; + + /** + * Fields (schema.element.qualifier) used to render their values. + */ + fields: string[] = ['sedici.identifier.other']; + + /** + * Label i18n key for the rendered metadata + */ + label: string = 'Otros idenfiticadores'; + + /** + * Separator string between multiple values of the metadata fields defined + * @type {string} + */ + separator = '
'; + + mdValues: MetadataValue[]; + + ngOnInit() { + this.selectNotPersistentIdentifiers(); + } + + selectNotPersistentIdentifiers(): void { + const persistentIdentifiers = ['doi', 'DOI', 'handle', 'hdl', 'arxiv', 'arXiv', 'pmcid', 'pmid', 'ark']; + this.mdValues = this.item.allMetadata(this.fields).filter(mdValue => { + return !persistentIdentifiers.some(identifier => mdValue.value.includes(identifier)); + }); + } +} diff --git a/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.html b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.html new file mode 100644 index 00000000000..387ff456e13 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.html @@ -0,0 +1,21 @@ + + \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.scss b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.scss new file mode 100644 index 00000000000..1ac5baffbdc --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.scss @@ -0,0 +1,13 @@ +.modal-header { + display: inherit; + + .close { + padding: 0; + margin: 0; + font-size: 2.25em; + } +} + +::ng-deep ngb-modal-backdrop.fade.show { + background-color: rgba(0, 0, 0, 0.75) !important; // Aumenta la opacidad de 0.5 a 0.85 +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.ts b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.ts new file mode 100644 index 00000000000..b95ccf00a98 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/field-components/viewer/sedici-viewer.component.ts @@ -0,0 +1,24 @@ +import { CommonModule } from '@angular/common'; +import { Component, OnInit, Input } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ModalSwipeBackDirective } from 'src/themes/custom/app/shared/utils/modal-swipe-back.directive'; + +@Component({ + selector: 'sedici-viewer', + templateUrl: './sedici-viewer.component.html', + styleUrls: ['./sedici-viewer.component.scss'], + standalone: true, + imports: [CommonModule, ModalSwipeBackDirective], +}) +export class SediciViewerComponent { + @Input() content: any; + @Input() headerTemplate: any; + @Input() embargoedFile: boolean; + @Input() isAssetAvailable: boolean; + + constructor(public activeModal: NgbActiveModal) {} + + close() { + this.activeModal.close(); + } +} diff --git a/src/themes/custom/app/item-page/simple/item-page.component.html b/src/themes/custom/app/item-page/simple/item-page.component.html index e69de29bb2d..0603a37983f 100644 --- a/src/themes/custom/app/item-page/simple/item-page.component.html +++ b/src/themes/custom/app/item-page/simple/item-page.component.html @@ -0,0 +1,15 @@ +
+
+
+ + + + + + + +
+
+ + +
diff --git a/src/themes/custom/app/item-page/simple/item-page.component.ts b/src/themes/custom/app/item-page/simple/item-page.component.ts index 7daa65287a5..90efde101e5 100644 --- a/src/themes/custom/app/item-page/simple/item-page.component.ts +++ b/src/themes/custom/app/item-page/simple/item-page.component.ts @@ -28,10 +28,10 @@ import { ViewTrackerComponent } from '../../../../../app/statistics/angulartics/ */ @Component({ selector: 'ds-themed-item-page', - // styleUrls: ['./item-page.component.scss'], - styleUrls: ['../../../../../app/item-page/simple/item-page.component.scss'], - // templateUrl: './item-page.component.html', - templateUrl: '../../../../../app/item-page/simple/item-page.component.html', + styleUrls: ['./item-page.component.scss'], + // styleUrls: ['../../../../../app/item-page/simple/item-page.component.scss'], + templateUrl: './item-page.component.html', + // templateUrl: '../../../../../app/item-page/simple/item-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [fadeInOut], standalone: true, diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.html new file mode 100644 index 00000000000..d0b7f359442 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.html @@ -0,0 +1,15 @@ +
+ + +
+
+
+ {{ citation }} +
+
+
+ Copiar al portapapeles + +
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.scss new file mode 100644 index 00000000000..6772bdafcf4 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.scss @@ -0,0 +1,37 @@ +.apa-citation-container { + border: 1px dashed #cccccc; + padding: 10px; + border-radius: 5px; + background-color: #f9f9f9; + font-family: Arial, sans-serif; +} + +.apa-citation { + color: #333333; + line-height: 1.5; + font-style: italic; + padding: 5px 0; +} + +.copy-button-container { + display: flex; + justify-content: flex-end; + padding-top: .25rem; + gap: .25rem; +} + +.copy-text { + font-size: 12px; + color: #666666; +} + +.copyButton { + cursor: pointer; + font-size: 1rem; + color: #333333; + transition: color 0.3s; +} + +.copyButton:hover { + color: #007bff; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.ts new file mode 100644 index 00000000000..0e5f3dd8b75 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/apa-citation.component.ts @@ -0,0 +1,59 @@ +import { Component, Input, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@Component({ + selector: 'ds-apa-citation', + standalone: true, + imports: [CommonModule], + templateUrl: './apa-citation.component.html', + styleUrls: ['./apa-citation.component.scss'] +}) +export class ApaCitationComponent implements OnInit { + @Input() item: any; + @ViewChild('elementContentToCopy') elementContentToCopy: ElementRef; + citation: string; + citationType: string = 'apa'; + + citationOptions = [ + { value: 'apa', label: 'APA' }, + { value: 'chicago', label: 'Chicago' }, + { value: 'mla', label: 'MLA' }, + ]; + + ngOnInit(): void { + this.generateCitation(this.citationType); + } + + generateCitation(type: string): void { + if (type === 'apa') { + this.citation = 'Melville, H. & Schaeffer, M. (1922) Moby Dick. New York, Dodd, Mead and company. [Pdf] Retrieved from the Library of Congress, https://www.loc.gov/item/22022440/'; + } else if (type === 'chicago') { + this.citation = 'Melville, Herman, and Mead Schaeffer. Moby Dick. New York, Dodd, Mead and company, 1922. Pdf. https://www.loc.gov/item/22022440/'; + } else { + this.citation = 'Melville, Herman, and Mead Schaeffer. Moby Dick. New York, Dodd, Mead and company, 1922. Pdf. Retrieved from the Library of Congress, '; + } + } + + onCitationTypeChange(event: Event): void { + const selectElement = event.target as HTMLSelectElement; + this.citationType = selectElement.value; + this.generateCitation(this.citationType); + } + + copyToClipboard(el: HTMLDivElement, id: string) { + if (navigator.clipboard) { + navigator.clipboard.writeText(el.innerText).then(() => { + document.getElementById(id).classList.remove('fa-copy'); + document.getElementById(id).classList.add('fa-check'); + setTimeout(() => { + document.getElementById(id).classList.remove('fa-check'); + document.getElementById(id).classList.add('fa-copy'); + }, 1000); + }, (error) => { + console.log(error); + }); + } else { + console.log('Browser do not support Clipboard API'); + } + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.html new file mode 100644 index 00000000000..aefbfa7aede --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.html @@ -0,0 +1,166 @@ +
+
+
+
+
+ +
+
+ File icon +
+
+ {{ getFileDescription(file) }} +
+
+ +
+
+
+ + + + + + +
+
+ {{ getFileDescription(file) }} +
+
+ + +
+
+
+
+
+ +
+
+ +
+ +
+ OCURRIÓ UN ERROR INESPERADO: PREVISUALIZACIÓN NO DISPONIBLE +
+ +
+ NO HAY ARCHIVO/S CON PREVISUALIZACIÓN DISPONIBLE +
+
+
+
+
+ + +
+
+
+ File icon +
+
+ {{ getFileDescription(file) }} + + + Preview no disponible + +
+
+ +
+
+
+
+ + +
+ + + + + + + + +
+ +
+
+ +
+ {{ dsoNameService.getName(selectedFile) }} +
+
+
+ +
+ +
+
+
+ + +
+ +
+
+ + +
+
+ + +
+ {{ dsoNameService.getName(selectedFile) }} +
+
+ + +
    + +
+ +
    +
  • + + {{ key }} + + + + + + + + + + + + + + {{ key }} + +
  • +
+
+
+
+ + + Lamentablemente el ítem seleccionado no tiene archivos para ver/descargar. Si lo desea, puede contactar directamente con el autor. En caso de ser el autor, es bienvenido a subir los archivos correspondientes para así poder completar el registro. + + +
+ + + Cargando archivos... + \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.scss new file mode 100644 index 00000000000..1751601211a --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.scss @@ -0,0 +1,246 @@ +.content-container { + + .file-list { + flex: 1; + display: flex; + flex-direction: column; + max-height: 85vh; + overflow-y: auto; + } + + .file-preview { + position: relative; + padding-right: 0px; + padding-left: 0px; + + .content-preview-wrapper { + position: relative; + min-height: 85vh; + + .sticky-download { + position: absolute; + bottom: 20px; + right: 20px; + left: auto; + width: auto; + z-index: 100; + + ::ng-deep ds-sedici-file-download-link { + display: block; + + .download-btn { + padding: 0; + background: none; + border: none; + overflow: visible; + box-shadow: 0 3px 6px rgba(0,0,0,0.2); + border-radius: 30px; + + .svg-container { + position: relative; + width: 60px; + height: 60px; + transition: all 0.3s ease; + } + + .svg-circle { + position: absolute; + top: 0; + right: 0; + opacity: 1; + transition: opacity 0.3s ease; + } + + .svg-expanded { + position: absolute; + top: 0; + right: 0; + opacity: 0; + pointer-events: none; + transform: translateX(0); + transition: all 0.3s ease; + } + } + + &:hover .download-btn { + .svg-container { + width: 180px; + } + + .svg-circle { + opacity: 0; + } + + .svg-expanded { + opacity: 1; + } + } + } + } + } + } + + .no-preview { + width: 100%; + height: 85vh; + display: flex; + justify-content: center; + align-items: center; + border: 2px solid #ccc; + background-color: #f5f5f5; + + span { + font-size: 1.5rem; + color: #aaa; + } + } +} + +.row { + flex-wrap: nowrap; +} + +.selected-file .file-item{ + background-color: #aaa; +} + +.file-item { + align-items: center; + padding: .5rem; + cursor: pointer; + + &:hover { + background-color: #ccc; + } + + .file-icon { + display: flex; + justify-content: center; + } + + .file-name { + font-size: .75rem; + overflow: hidden; // Oculta el texto que se desborda + text-overflow: ellipsis; // Agrega puntos suspensivos al texto que se desborda + display: -webkit-box; // Necesario para line-clamp + -webkit-box-orient: vertical; // Necesario para line-clamp + -webkit-line-clamp: 2; // Limita el texto a 2 líneas + line-clamp: 2; // Limita el texto a 2 líneas + word-break: break-word; + } + + .text-no-preview-available { + font-style: italic; + font-weight: 100; + } + + .download-button{ + padding: 0px; + } +} + +.header-template { + display: flex; + flex-direction: column; + gap: 0.5rem; + + .file-name-container { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .button-container { + display: flex; + gap: 0; + + button, + ds-sedici-file-download-link { + flex: 1 100%; + } + + ::ng-deep .download-btn { + font-size: .75em; + padding: .75rem; + } + } +} + +// En caso de no tener preview, le saco el hover y la manito al pasar el mouse +.file-no-preview-available .file-item { + cursor: default; + + &:hover { + background-color: transparent; + } +} + +.preview-image { + max-width: 85vh; + max-height: 85vh; + + @media screen and (max-width: map-get($grid-breakpoints, md)) { + width: 100%; + height: 100%; + } +} + +.loading-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.8); + z-index: 10; +} + +.loading-spinner { + font-size: 2rem; + color: #333; +} + +ul { + list-style-type: none; + margin-left: 20px; + padding-left: 0; + + li { + margin: 5px 0; + } + + i { + margin-right: 8px; + } +} + +::ng-deep .fullscreen-modal .modal-dialog { + margin: 0; + max-width: 100%; +} + +::ng-deep .fullscreen-modal .modal-body { + padding: 0; +} + +::ng-deep .fullscreen-modal .sticky-download { + display: none; // Oculto el sticky-download solo dentro del modal +} + +// Versión con botón de preview +.preview-btn { + background-color: black; + color: white; + border: none; + cursor: pointer; + border-radius: .5rem; + font-size: .625rem; + width: 60px; + + &:hover { + background-color: #666; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.ts new file mode 100644 index 00000000000..4b655577ecd --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/content-files.component.ts @@ -0,0 +1,353 @@ +import { Component, Input, Inject, ViewChild, ElementRef } from '@angular/core'; +import { NgFor, NgIf, NgStyle, NgClass, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, AsyncPipe } from '@angular/common'; +import { Item } from 'src/app/core/shared/item.model'; +import { BitstreamDataService } from 'src/app/core/data/bitstream-data.service'; +import { APP_CONFIG, AppConfig } from 'src/config/app-config.interface'; +import { Bitstream } from 'src/app/core/shared/bitstream.model'; +import { FileSizePipe } from 'src/app/shared/utils/file-size-pipe'; +import { DSONameService } from 'src/app/core/breadcrumbs/dso-name.service'; +import { SediciFileDownloadLinkComponent } from './sedici-file-download-link.component'; +import { isNotEmpty } from 'src/app/shared/empty.util'; +import { FeatureID } from 'src/app/core/data/feature-authorization/feature-id'; + +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { SediciViewerComponent } from '../../field-components/viewer/sedici-viewer.component'; + +import { ChangeDetectorRef } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import * as JSZip from 'jszip'; + +import { HostWindowService, WidthCategory } from 'src/app/shared/host-window.service'; +import { Observable } from 'rxjs'; +import { NotificationsService } from 'src/app/shared/notifications/notifications.service'; + +import { PdfJsViewerModule } from "ng2-pdfjs-viewer"; +import { AuthService } from 'src/app/core/auth/auth.service'; +import { AuthorizationDataService } from 'src/app/core/data/feature-authorization/authorization-data.service'; +import { SediciShareButtonsComponent } from '../../field-components/share-buttons/sedici-share-buttons.component'; +@Component({ + selector: 'content-files', + styleUrls: ['./content-files.component.scss'], + templateUrl: './content-files.component.html', + standalone: true, + imports: [ + NgFor, + NgIf, + NgStyle, + NgClass, + NgSwitch, + NgSwitchCase, + NgSwitchDefault, + NgTemplateOutlet, + AsyncPipe, + FileSizePipe, + SediciFileDownloadLinkComponent, + SediciViewerComponent, + PdfJsViewerModule, + ], +}) +export class ContentFilesComponent { + @Input() object: Item; + @ViewChild('pdfViewerOnDemand') pdfViewerOnDemand; + + primaryBitsreamId: string; + previewUrl: string; + + isLoading = true; + + onDocLoaded() { + this.isLoading = false; + } + + openModal(content: any, headerTemplate: any) { + const modalRef = this.modalService.open(SediciViewerComponent, { size: 'lg', windowClass: 'fullscreen-modal', centered: true }); + modalRef.componentInstance.content = content; + modalRef.componentInstance.headerTemplate = headerTemplate; + modalRef.componentInstance.embargoedFile = this.embargoedFile; + modalRef.componentInstance.isAssetAvailable = this.isAssetAvailable; + } + + openModalShareButtons() { + const modalRef = this.modalService.open(SediciShareButtonsComponent, { + centered: true, // Centra el modal + }); + modalRef.componentInstance.link = this.object.firstMetadataValue('dc.identifier.uri'); + modalRef.componentInstance.title = this.object.firstMetadataValue('dc.title'); + modalRef.componentInstance.type = this.object.firstMetadataValue('sedici.subtype') || this.object.firstMetadataValue('dc.type'); + } + + isLoadingFiles: boolean = true; + files: Bitstream[] = []; + + isMobile$: Observable; + isMobile = false; + + constructor( + protected bitstreamDataService: BitstreamDataService, + public dsoNameService: DSONameService, + @Inject(APP_CONFIG) protected appConfig: AppConfig, + private modalService: NgbModal, + private http: HttpClient, + private cdr: ChangeDetectorRef, + private windowService: HostWindowService, + private notificationsService: NotificationsService, + private authService: AuthService, + private authorizationService: AuthorizationDataService, + ) { + this.isMobile$ = this.windowService.isUpTo(WidthCategory.MD); + } + + selectedFile: Bitstream | null = null; + embargoedFile: boolean = false; + isAssetAvailable: boolean = true; + + selectFile(file: Bitstream) { + this.selectedFile = file; + const extension = this.getFileExtension(file.name); + this.isLoading = true; + this.embargoedFile = false; + this.isAssetAvailable = true; + const authToken = this.authService.getToken(); + this.cdr.detectChanges(); + + switch (extension) { + case 'jpg': + case 'jpeg': + case 'png': + case 'gif': + case 'bmp': + this.previewUrl = file._links.content.href; + this.isLoading = false; + break; + case 'zip': + this.previewUrl = file._links.content.href; + this.loadZipFromUrl(this.previewUrl); + this.isLoading = false; + break; + case 'pdf': + this.previewUrl = file._links.content.href; + + const waitForDownloadable = (file: Bitstream) => { + if (this.isDownloadable(file) !== undefined) { + if(this.isDownloadable(this.selectedFile)) { + // Usar HttpClient para obtener el archivo con autenticación + this.http.get(this.previewUrl, { + headers: new HttpHeaders({ + 'Authorization': `Bearer ${authToken}` + }), + responseType: 'blob' + }).subscribe((data: Blob) => { + // Crear una URL para el blob + const objectUrl = URL.createObjectURL(data); + + // Verificar si el visor PDF está disponible + const assignBlobUrl = () => { + if (this.pdfViewerOnDemand) { + // Asignar la URL del blob al visor PDF + this.pdfViewerOnDemand._src = objectUrl; + this.pdfViewerOnDemand.refresh(); + this.isLoading = false; + } else { + console.error('El visor PDF no está disponible.'); + setTimeout(assignBlobUrl, 100); // Intentar nuevamente después de 100ms + } + }; + assignBlobUrl(); + }, error => { + console.error('Error al cargar el archivo:', error); + if (error.status === 401 || error.status === 403) { + this.embargoedFile = true; + this.cdr.detectChanges(); + } + if (error.status === 500) { + this.isAssetAvailable = false; + this.cdr.detectChanges(); + } + this.isLoading = false; + }); + } + this.isLoading = false; + this.cdr.detectChanges(); + } else { + setTimeout(() => waitForDownloadable(file), 100); + } + } + waitForDownloadable(this.selectedFile); + break; + default: + this.previewUrl = file._links.content.href; + break; + } + } + + isPreviewAvailable(fileName: string): boolean { + const extension = this.getFileExtension(fileName); + return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'zip', 'pdf'].includes(extension); + } + + getFileExtension(fileName: string): string { + const parts = fileName.split('.'); + return (parts.length > 1 ? parts.pop() : '').toLowerCase(); + } + + isImageFile(extension: string): boolean { + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp']; + return imageExtensions.includes(extension); + } + + getIconPath(fileName: string): string { + const extension = this.getFileExtension(fileName); + if (this.isImageFile(extension)) { + return `assets/custom/images/icon_imagen.png`; + } + return `assets/custom/images/icon_${extension}.png`; + } + + getFileDescription(file: Bitstream): string { + return file.metadata['dc.description']?.[0]?.value || this.dsoNameService.getName(file) ; + } + + ngOnInit(): void { + this.isMobile$.subscribe(isMobile => { + this.isMobile = isMobile; + }); + this.getPrimaryBitstreamId().then(() => { + this.getAllPages(); + }); + } + + zipContent: { name: string, type: 'file' | 'folder' }[] = []; // Lista para mostrar los archivos dentro del ZIP y su tipo + zipContentTree; + + async loadZipFromUrl(url: string) { + try { + // Descargar el archivo ZIP como Blob + const zipBlob = await this.http.get(url, { responseType: 'blob' }).toPromise(); + + // Cargar el archivo ZIP con JSZip + const loadedZip = await JSZip.loadAsync(zipBlob); + + // Obtener y listar los nombres de los archivos en el ZIP + this.zipContent = Object.keys(loadedZip.files).map(fileName => { + const file = loadedZip.files[fileName]; + return { + name: fileName, + type: fileName.endsWith('/') ? 'folder' : 'file', // Determina si es un archivo o una carpeta + }; + }); + + const files = Object.keys(loadedZip.files); + this.zipContentTree = this.buildTree(files); + + // Forzar la actualización de la vista + this.cdr.detectChanges(); + } catch (error) { + console.error('Error al cargar el archivo ZIP:', error); + } + } + + // Convierte una lista de rutas en un árbol jerárquico + buildTree(filePaths: string[]): any { + const tree: any = {}; + + filePaths.forEach((filePath) => { + const parts = filePath.split('/').filter((part) => part.trim() !== ''); + let currentLevel = tree; + + parts.forEach((part, index) => { + if (!currentLevel[part]) { + currentLevel[part] = index === parts.length - 1 ? null : {}; + } + currentLevel = currentLevel[part]; + }); + }); + + return tree; + } + + // Devuelve las claves de un objeto + objectKeys(obj: any): string[] { + return Object.keys(obj); + } + + // Determina si un nodo es una carpeta + isFolder(node: any): boolean { + return node !== null && typeof node === 'object'; + } + + private getPrimaryBitstreamId(): Promise { + return new Promise((resolve) => { + this.bitstreamDataService.findPrimaryBitstreamByItemAndName(this.object, 'ORIGINAL', true, true).subscribe((primaryBitstream: Bitstream | null) => { + if (primaryBitstream) { + this.primaryBitsreamId = primaryBitstream.id; + resolve(this.primaryBitsreamId); + } else { + resolve(null); + } + }); + resolve(null); + }); + } + + getAllPages(): void { + this.isLoadingFiles = true; + this.bitstreamDataService.findAllByItemAndBundleName(this.object, 'ORIGINAL', { currentPage: 0, elementsPerPage: 1000 }).subscribe((response: any) => { + if (response && response.hasSucceeded) { + if (response.payload && response.payload.page.length > 0) { + this.files = response.payload.page; + } + this.cdr.detectChanges(); + this.checkAndSaveDownloadStatus(); + if (!this.isMobile && this.files.length >= 1) { + // Seleccionar el primary bitstream si está disponible y tiene un preview + const primaryBitstream = this.files.find(file => file.id === this.primaryBitsreamId && this.isPreviewAvailable(file.name)); + if (primaryBitstream) { + this.selectFile(primaryBitstream); + } else { + // Seleccionar el primer archivo con preview disponible + const firstPreviewableFile = this.files.find(file => this.isPreviewAvailable(file.name)); + if (firstPreviewableFile) { + this.selectFile(firstPreviewableFile); + } + } + } + this.isLoadingFiles = false; + } + }, + (err) => { + console.error('Error en la solicitud:', err); + this.notificationsService.error('Error', 'Ocurrió un error al intentar cargar los archivos.'); + this.isLoadingFiles = false; + }); + } + + checkAndSaveDownloadStatus(): void { + this.files.forEach(file => { + this.authorizationService.isAuthorized( + FeatureID.CanDownload, + isNotEmpty(file) ? file.self : undefined) + .subscribe(canDownload => { + // Extiende el objeto file con una nueva propiedad canDownload + (file as any).canDownload = canDownload; + this.cdr.detectChanges(); + }); + }); + } + + isDownloadable(file: Bitstream): boolean { + return (file as any).canDownload; + } + + hasPreviewAndDownloadableFiles(): boolean { + return this.files.some(file => this.isPreviewAvailable(file.name) && (file as any).canDownload); + } + + handleClick(file: Bitstream, contentTemplate: any, headerTemplate: any) { + this.selectFile(file); + setTimeout(() => { + if (this.isMobile) { + this.openModal(contentTemplate, headerTemplate); + } + }, 100); + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/expandable-metadata.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/expandable-metadata.ts new file mode 100644 index 00000000000..69de7ec2ce5 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/expandable-metadata.ts @@ -0,0 +1,100 @@ +import { Component, Input, ElementRef, Renderer2, AfterViewInit, ViewChild } from '@angular/core'; +import { + NgIf, + NgClass, +} from '@angular/common'; + +@Component({ + selector: 'app-expandable-metadata', + standalone: true, + template: ` +
+ +
+ +
+
+
+ {{ expanded ? '\u2303' : '\u2304' }} +
+
+ `, + styles: [` + div.truncated { + position: relative; + overflow: hidden; + max-height: calc(2em * 10); /* Altura máxima (10 líneas) */ + } + + div.truncated::after { + content: ""; /* Degradado para dar la sensación de texto desapareciendo */ + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 2em; /* Ajusta la altura del degradado */ + background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, #f6f6f6 100%); + pointer-events: none; + } + + .button-container { + display: flex; + flex-direction: column; /* Cambié de row a column para colocar la flecha debajo */ + align-items: center; /* Centra la flecha debajo de la línea */ + margin-top: .5rem; + cursor: pointer; + color: #6c757d; /* Color gris más neutro para el icono */ + } + + .button-container .line { + width: 100%; /* Asegura que la línea ocupe todo el ancho */ + height: 1px; + background-color: #ccc; /* Color gris más suave para la línea */ + } + `], + imports: [ + NgIf, + NgClass, + ], +}) +export class ExpandableMetadataComponent implements AfterViewInit { + @ViewChild('containerRef', { static: false }) containerRef!: ElementRef; + + @Input() maxLines = 10; // Número máximo de líneas + isTruncated = false; + expanded = false; + + constructor(private el: ElementRef, private renderer: Renderer2) {} + + ngAfterViewInit() { + this.checkTruncation(); + } + + checkTruncation() { + const container = this.containerRef.nativeElement; + + const lineHeight = parseFloat(getComputedStyle(container).lineHeight); + const maxHeight = lineHeight * this.maxLines; + + // Verifica si se necesita truncar + if (container.scrollHeight > maxHeight) { + this.isTruncated = true; + } + } + + toggleExpand() { + this.expanded = !this.expanded; + const container = this.containerRef.nativeElement; + this.renderer.setStyle(container, 'max-height', this.expanded ? 'none' : `calc(2em * ${this.maxLines})`); + + // Desplazarse al principio del componente cuando se cierra + if (!this.expanded) { + this.scrollToTop(); + } + } + + scrollToTop() { + // Mueve el contenedor hacia la parte superior + this.el.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } +} diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.html new file mode 100644 index 00000000000..c5e1bad1eab --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.html @@ -0,0 +1,21 @@ +
+ + + + + + + + + + + +
{{ row.label | translate }}{{ value }}
+
+ + + \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.scss new file mode 100644 index 00000000000..fbe7552cb1e --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.scss @@ -0,0 +1,16 @@ +tbody { + font-size: 1.25em; + font-weight: var(--font-weight-regular); +} + +.label { + white-space: nowrap; +} + +ds-item-page-collections { + font-size: 1.25em; + + ::ng-deep h6 { + font-size: 1.2em; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.ts new file mode 100644 index 00000000000..02ec2e10969 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/full-item.component.ts @@ -0,0 +1,123 @@ +import { Component, Input } from '@angular/core'; +import { NgFor } from '@angular/common'; +import { Item } from 'src/app/core/shared/item.model'; +import { RouterLink } from '@angular/router'; +import { getItemPageRoute } from 'src/app/item-page/item-page-routing-paths'; +import { TranslateModule } from '@ngx-translate/core'; + +import { GenericItemPageFieldComponent } from 'src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; +import { SediciDateMetadataValuesComponent } from '../../field-components/date-metadata-values/sedici-date-metadata-values.component'; +import { SediciLanguageMetadataValuesComponent } from '../../field-components/language-metadata-values/sedici-language-metadata-values.component'; +import { CollectionsComponent } from 'src/app/item-page/field-components/collections/collections.component'; +import { ItemPageIdentifierOtherFieldComponent } from '../../field-components/specific-field/identfier-other/item-page-identifier.other-field'; + +interface MetadataMapping { + fieldName: string; // Nombre del campo de metadatos (dc.date.issued, etc.) + labelKey: string; // Clave para la traducción (sedici.item.page.dc.date.issued) + specialType?: string; // Para campos que requieren tratamiento especial (date, language) +} +@Component({ + selector: 'full-item', + styleUrls: ['./full-item.component.scss'], + templateUrl: './full-item.component.html', + standalone: true, + imports: [ + NgFor, + RouterLink, + TranslateModule, + GenericItemPageFieldComponent, + SediciDateMetadataValuesComponent, + SediciLanguageMetadataValuesComponent, + CollectionsComponent, + ItemPageIdentifierOtherFieldComponent, + ], +}) +export class FullItemComponent { + @Input() object: Item; + itemPageRoute: string; + + metadataMappings: MetadataMapping[] = [ + { fieldName: 'dc.date.issued', labelKey: 'sedici.item.page.dc.date.issued', specialType: 'date' }, + { fieldName: 'dc.date.created', labelKey: 'sedici.item.page.dc.date.created', specialType: 'date' }, + { fieldName: 'sedici.date.exposure', labelKey: 'sedici.item.page.sedici.date.exposure', specialType: 'date' }, + { fieldName: 'dc.description.filiation', labelKey: 'sedici.item.page.dc.description.filiation' }, + { fieldName: 'sedici.identifier.expediente', labelKey: 'sedici.item.page.sedici.identifier.expediente' }, + { fieldName: 'mods.location', labelKey: 'sedici.item.page.mods.location' }, + { fieldName: 'sedici.subject.ford', labelKey: 'sedici.item.page.sedici.subject.ford' }, + { fieldName: 'dc.language', labelKey: 'sedici.item.page.dc.language', specialType: 'language' }, + // Identificadores especiales se manejan aparte + { fieldName: 'thesis.degree.name', labelKey: 'sedici.item.page.thesis.degree.name' }, + { fieldName: 'thesis.degree.grantor', labelKey: 'sedici.item.page.thesis.degree.grantor' }, + { fieldName: 'sedici.relation.event', labelKey: 'sedici.item.page.sedici.relation.event' }, + { fieldName: 'sedici.relation.journalTitle', labelKey: 'sedici.item.page.sedici.relation.journalTitle' }, + { fieldName: 'sedici.relation.journalVolumeAndIssue', labelKey: 'sedici.item.page.sedici.relation.journalVolumeAndIssue' }, + { fieldName: 'sedici.relation.bookTitle', labelKey: 'sedici.item.page.sedici.relation.bookTitle' }, + { fieldName: 'sedici.relation.ciclo', labelKey: 'sedici.item.page.sedici.relation.ciclo' }, + { fieldName: 'dc.format.extent', labelKey: 'sedici.item.page.dc.format.extent' }, + { fieldName: 'dc.date.accessioned', labelKey: 'sedici.item.page.dc.date.accessioned', specialType: 'date' } + ]; + + metadataRows: { label: string, values: string[] }[] = []; + + ngOnInit(): void { + this.itemPageRoute = getItemPageRoute(this.object); + this.processMetadata(); + } + + processMetadata() { + this.metadataRows = []; + + this.metadataMappings.forEach(mapping => { + const label = mapping.labelKey; + let values: string[] = []; + + if (mapping.specialType === 'date') { + values = this.getDateValues(mapping.fieldName); + } else if (mapping.specialType === 'language') { + values = this.getLanguageValues(mapping.fieldName); + } else { + values = this.getGenericValues(mapping.fieldName); + } + + if (values.length > 0) { + this.metadataRows.push({ label, values }); + } + }); + } + + getDateValues(fieldName: string): string[] { + const date = this.object?.allMetadata([fieldName])[0]?.value; + let dateString: string; + if (date !== undefined) { + if (date.length === 10 || date.includes('T')) { + dateString = new Date(date).toLocaleDateString('es-AR',{ year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }); + } else if (date.length === 7) { + dateString = new Date(date).toLocaleDateString('es-AR',{ year: 'numeric', month: 'long', timeZone: 'UTC' }); + } else { + dateString = date; + } + return [dateString]; + } + return []; + } + + getLanguageValues(fieldName: string): string[] { + const language = this.object?.allMetadata([fieldName])[0].value; + let languageString: string; + if (language === 'es') { + languageString = 'Español'; + } else if (language === 'en') { + languageString = 'Inlgés'; + } else if (language === 'pt') { + languageString = 'Portugués'; + } else if (language === 'de') { + languageString = 'Alemán'; + } + return [languageString]; + } + + getGenericValues(fieldName: string): string[] { + const values = this.object?.allMetadata([fieldName]); + return values.map(value => value.value); + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.html new file mode 100644 index 00000000000..28006779d58 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.html @@ -0,0 +1,16 @@ +
+
+ + +

+
+
+
+
+ +
+
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.scss new file mode 100644 index 00000000000..386ac1c66df --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.scss @@ -0,0 +1,73 @@ +.language-switcher-wrapper { + padding-bottom: 1rem; + font-size: 1.25em; + + @media screen and (min-width: 769px) { + display: flex; + } +} + +.language-sidebar { + display: flex; + flex-direction: column; + padding: 1rem 0px; + + @media screen and (max-width: 768px) { + flex-direction: row; + padding: 0px 1rem; + } +} + +.language-sidebar button { + width: 40px; + margin-right: -40px; + background-color: #ffffff; + border: none; + color: #666666; + cursor: pointer; + transition: background-color 0.3s, color 0.3s, font-weight 0.3s; + opacity: .5; + + @media screen and (max-width: 768px) { + margin-right: 0px; + } +} + +.language-sidebar button.active { + border: 1px solid #e0e0e0; + color: #333333; + font-weight: bold; + border-bottom-right-radius: 4px; + opacity: 1; + + @media screen and (min-width: 769px) { + border-left: none; + border-top-right-radius: 4px; + } + + @media screen and (max-width: 768px) { + border-top: none; + border-bottom-left-radius: 4px; + } +} + +.language-switcher-container { + padding: 1rem 1.5rem; + box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1); + border-radius: 0.5rem; + background-color: #ffffff; + width: 100%; +} + +.abstract-text { + font-weight: var(--font-weight-regular); + white-space: pre-wrap; + text-align: justify; +} + +::ng-deep .language-switcher-wrapper ds-truncatable-part .collapseButton, +::ng-deep .language-switcher-wrapper ds-truncatable-part .expandButton { + margin-left: auto; + margin-right: 0; + display: block; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.ts new file mode 100644 index 00000000000..a5f885a3c7f --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/language-switcher.component.ts @@ -0,0 +1,59 @@ +import { Component, Input } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { NgIf, NgFor } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component'; +import { TruncatablePartComponent } from 'src/app/shared/truncatable/truncatable-part/truncatable-part.component'; + +@Component({ + selector: 'language-switcher', + styleUrls: ['./language-switcher.component.scss'], + templateUrl: './language-switcher.component.html', + standalone: true, + imports: [ + NgIf, + NgFor, + TranslateModule, + TruncatableComponent, + TruncatablePartComponent, + ], +}) +export class LanguageSwitcherComponent { + @Input() item: any; + selectedLanguage: string; + availableLanguages: any[]; + + constructor(private sanitizer: DomSanitizer) {} + + ngOnInit() { + this.selectedLanguage = this.item.metadata['dc.language']?.[0]?.value || 'es'; + this.availableLanguages = this.getAvailableLanguages(); + } + + getAbstract(): SafeHtml { + const abstracts = this.item.metadata['dc.description.abstract']; + if (abstracts) { + let abstract = abstracts.find((abstract: any) => (abstract.language || 'es') === this.selectedLanguage)?.value || ''; + if (!abstract) { + abstract = abstracts[0].value; + this.selectedLanguage = abstracts[0].language; + } + const prefix = 'Resumen: '; + abstract = prefix + abstract; + return this.sanitizer.bypassSecurityTrustHtml(abstract); + } + return this.sanitizer.bypassSecurityTrustHtml(''); + } + + changeLanguage(language: string) { + this.selectedLanguage = language; + } + + getAvailableLanguages() { + const abstracts = this.item.metadata['dc.description.abstract']; + if (abstracts) { + return [...new Set(abstracts.map((abstract: any) => abstract.language))]; + } + return []; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.html new file mode 100644 index 00000000000..d219d108894 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.html @@ -0,0 +1,40 @@ + +
+ +
+
+ + +
+ +
+
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.scss new file mode 100644 index 00000000000..c01d48ed527 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.scss @@ -0,0 +1,42 @@ +a { + text-decoration: none; +} + +.download-btn { + background-color: var(--sedici-color); + color: white; + border: none; + cursor: pointer; + border-radius: .5rem; + font-size: .625rem; + width: 60px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); // Sombra sutil + transition: background-color 0.2s ease; + + &:hover { + background-color: #5c9acb; // Azul un poco más oscuro al hover + } +} + +.sticky-button { + .download-btn { + display: flex; + justify-content: center; + padding: 1rem; + font-size: 0.875rem; + align-items: center; + width: 80%; + margin: 0 auto; + + .download-content { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + } + + .fas { + font-size: 1em; + } + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.ts new file mode 100644 index 00000000000..b3012206fcd --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-file-download-link.component.ts @@ -0,0 +1,91 @@ +import { + AsyncPipe, + NgClass, + NgIf, +} from '@angular/common'; +import { Component, OnInit, Input } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { FileSizePipe } from 'src/app/shared/utils/file-size-pipe'; +import { FileDownloadLinkComponent } from 'src/app/shared/file-download-link/file-download-link.component'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { AuthorizationDataService } from 'src/app/core/data/feature-authorization/authorization-data.service'; +import { ChangeDetectorRef } from '@angular/core'; +import { + combineLatest as observableCombineLatest, + Observable, + of as observableOf, +} from 'rxjs'; +import { FeatureID } from 'src/app/core/data/feature-authorization/feature-id'; +import { map } from 'rxjs/operators'; +import { isNotEmpty } from 'src/app/shared/empty.util'; +import { DSONameService } from 'src/app/core/breadcrumbs/dso-name.service'; +@Component({ + selector: 'ds-sedici-file-download-link', + templateUrl: './sedici-file-download-link.component.html', + styleUrls: ['./sedici-file-download-link.component.scss'], + standalone: true, + imports: [ + AsyncPipe, + NgClass, + NgIf, + RouterLink, + TranslateModule, + FileSizePipe, + NgbTooltipModule, + ], +}) +export class SediciFileDownloadLinkComponent extends FileDownloadLinkComponent implements OnInit { + @Input() isSticky: boolean = false; + @Input() isMobile: boolean = false; + + constructor( + protected authorizationService: AuthorizationDataService, + public dsoNameService: DSONameService, + private cdr: ChangeDetectorRef + ) { + super(authorizationService, dsoNameService); + } + + ngOnChanges() { + this.bitstreamPath$ = this.getBitstreamPathObservable(); + this.cdr.detectChanges(); // Forzar la detección de cambios + } + + private getBitstreamPathObservable(): Observable<{ routerLink: string, queryParams: any }> { + if (this.enableRequestACopy) { + this.canDownload$ = this.authorizationService.isAuthorized(FeatureID.CanDownload, isNotEmpty(this.bitstream) ? this.bitstream.self : undefined); + const canRequestACopy$ = this.authorizationService.isAuthorized(FeatureID.CanRequestACopy, isNotEmpty(this.bitstream) ? this.bitstream.self : undefined); + return observableCombineLatest([this.canDownload$, canRequestACopy$]).pipe( + map(([canDownload, canRequestACopy]) => this.getBitstreamPath(canDownload, canRequestACopy)), + ); + } else { + return observableOf(this.getBitstreamDownloadPath()); + } + } + + public isFileDownloadable(): Observable { + return this.authorizationService.isAuthorized(FeatureID.CanDownload, + isNotEmpty(this.bitstream) ? this.bitstream.self : undefined); + } + + adaptFileSize (size: string): string { + if (size.includes("KB")) { + const kbValue = parseFloat(size.replace("KB", "").trim()); // Extraer el valor numérico en KB + const mbValue = kbValue / 1024; // Convertir a MB y formatear a 1 decimal + const roundedMbValue = Math.round(mbValue * 10) / 10; // Redondear a 1 decimal + const formattedMbValue = roundedMbValue % 1 === 0 ? roundedMbValue.toFixed(0) : roundedMbValue.toFixed(1); // Verificar si es un valor entero + return `${formattedMbValue} MB`; + } else if (size.includes("MB")) { + const mbValue = parseFloat(size.replace("MB", "").trim()); // Extraer el valor numérico en MB + if (mbValue >= 1000) { // Si el valor en MB es mayor o igual a 1000, convertir a GB + // const gbValue = mbValue / 1000; + // const roundedGbValue = Math.round(gbValue * 10) / 10; + // const formattedGbValue = roundedGbValue % 1 === 0 ? roundedGbValue.toFixed(0) : roundedGbValue.toFixed(1); + // return `${formattedGbValue} GB`; + return "1 GB"; // Todavía en SEDICI no hay archivos que superen 1 GB, pero queda plateado a futuro el método + } + } + return size; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.html new file mode 100644 index 00000000000..c44f99d56e3 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.html @@ -0,0 +1,168 @@ +
+
+ + +
+
+

No Copyright

+ +
+ +
+ This work has been identified as being free of known restrictions under copyright law, including all related and neighboring rights. +
+
+ +
+
+ You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. +
+
+
+ + +
+

No Copyright

+ +
+ +
+ The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. +
+
+ +
+
+ You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. +
+
+
+
+ + +
+

{{ 'sedici.license.free' | translate }}

+ +
+
+ {{ 'sedici.license.share' | translate }} - {{ 'sedici.license.share.description' | translate }} +
+
+ +
+
+ {{ 'sedici.license.adapt' | translate }} - {{ 'sedici.license.adapt.description' | translate }} +
+
+ +
+
+ {{ 'sedici.license.description' | translate }} +
+
+
+
+
+
+
+
+
+

Other Information

+ +
+
+ The work may not be free of known copyright restrictions in all jurisdictions. +
+
+ +
+
+ Persons may have other rights in or related to the work, such as patent or trademark rights, and others may have rights in how the work is used, such as publicity or privacy rights. +
+
+ +
+
+ In some jurisdictions moral rights of the author may persist beyond the term of copyright. These rights may include the right to be identified as the author and the right to object to derogatory treatments. +
+
+ +
+
+ Unless expressly stated otherwise, the person who identified the work makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. +
+
+ +
+
+ When using or citing the work, you should not imply endorsement by the author or the person who identified the work. +
+
+
+ + +
+

Other Information

+ +
+
+ In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. +
+
+ +
+
+ Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. +
+
+ +
+
+ When using or citing the work, you should not imply endorsement by the author or the affirmer. +
+
+
+
+ + +
+

{{ 'sedici.license.terms' | translate }}

+ +
+ +
+ {{ 'sedici.license.attribution' | translate }} - {{ 'sedici.license.attribution.description' | translate }} +
+
+ +
+ +
+ {{ 'sedici.license.nonCommercial' | translate }} - {{ 'sedici.license.nonCommercial.description' | translate }} +
+
+ +
+ +
+ {{ 'sedici.license.noDerivateWorks' | translate }} - {{ 'sedici.license.noDerivateWorks.description' | translate }} +
+
+ +
+ +
+ {{ 'sedici.license.shareAlike' | translate }} - {{ 'sedici.license.shareAlike.description' | translate }} +
+
+ +
+
+ {{ 'sedici.license.restriction' | translate }} - {{ 'sedici.license.restriction.description' | translate }} +
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.scss new file mode 100644 index 00000000000..4040b80187c --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.scss @@ -0,0 +1,16 @@ +.licencias { + .license-title { + font-weight: bold; + } +} + +.licencia-item { + display: flex; + align-items: center; + margin: 15px 0; + + i { + font-size: 3rem; + margin-right: 1rem; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.ts new file mode 100644 index 00000000000..dfa717fb7a9 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-license.component.ts @@ -0,0 +1,27 @@ +import { Component, Input } from '@angular/core'; +import { CommonModule, NgIf } from '@angular/common'; +import { Item } from 'src/app/core/shared/item.model'; +import { TranslateModule } from '@ngx-translate/core'; +import { ItemPageCcLicenseFieldComponent } from 'src/app/item-page/simple/field-components/specific-field/cc-license/item-page-cc-license-field.component'; + +@Component({ + selector: 'sedici-license', + standalone: true, + imports: [ + CommonModule, + TranslateModule, + ItemPageCcLicenseFieldComponent, + NgIf, + ], + templateUrl: './sedici-license.component.html', + styleUrls: ['./sedici-license.component.scss'] +}) +export class SediciLicenseComponent { + @Input() object: Item; + + license: string; + + ngOnInit() { + this.license = this.object?.allMetadata(['sedici.rights.license'])[0]?.value; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.html new file mode 100644 index 00000000000..7f4c9af2aed --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.html @@ -0,0 +1,9 @@ + + +
{{ label | translate }}
+ +
+
\ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.scss new file mode 100644 index 00000000000..b3bef7c03fd --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.scss @@ -0,0 +1,5 @@ +.label { + display: inline; + margin-right: 0.5em; + font-weight: bold; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.ts new file mode 100644 index 00000000000..a3aba7fdb4f --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/sedici-truncatable-generic-item-page-field.ts @@ -0,0 +1,50 @@ +import { Component, Input } from '@angular/core'; +import { Item } from 'src/app/core/shared/item.model'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { NgIf } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component'; +import { SediciTruncatablePartComponent } from 'src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component'; +@Component({ + selector: 'sedici-truncatable-generic-item-page-field', + styleUrls: ['./sedici-truncatable-generic-item-page-field.scss'], + templateUrl: './sedici-truncatable-generic-item-page-field.html', + standalone: true, + imports: [ + NgIf, + TranslateModule, + TruncatableComponent, + SediciTruncatablePartComponent, + ], +}) +export class SediciTruncatableGenericItemPageFieldComponent { + @Input() item: Item; + @Input() fields: string[]; + @Input() label: string; + @Input() minLines: number = 4; + metadataTextValue: SafeHtml; + length: number = -1; + + constructor(private sanitizer: DomSanitizer) {} + + ngOnInit() { + this.metadataTextValue = this.getMetadataText(); + } + + getMetadataText(): SafeHtml { + let metadataArray: any[]; + metadataArray = this.item.allMetadata(this.fields); + let concat = ''; + metadataArray.forEach((metadata, index) => { + concat += metadata.value; + if (index < metadataArray.length - 1) { + concat += '; '; + } + }); + if (concat.length > 0) { + this.length = concat.length; + return this.sanitizer.bypassSecurityTrustHtml(concat); + } + return this.sanitizer.bypassSecurityTrustHtml(''); + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.html new file mode 100644 index 00000000000..dd88c4bd245 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.html @@ -0,0 +1,37 @@ +
+
+ +
+ {{ tab.label | translate }} +
+
+
+
+ +
+ +
+
+ +
+
+
+
+ LA REFERENCIA +
+
+
+
+ +
+
+ Selecciona una solapa. +
+
+
+
+ \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.scss new file mode 100644 index 00000000000..7c0001acaa3 --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.scss @@ -0,0 +1,65 @@ +.tab-container { + display: flex; + flex-direction: column; +} + +.tab-header { + display: flex; + border-bottom: 2px solid #42a5f5; + overflow-x: auto; // Permitir el desplazamiento horizontal + white-space: nowrap; // Evitar que los tabs se envuelvan en una nueva línea + justify-content: space-around; + + // Ocultar las barras de desplazamiento en algunos navegadores + &::-webkit-scrollbar { + display: none; + } +} + +.tab { + color: #555; + font-size: 1.5em; + padding: 10px 20px; + text-align: center; + cursor: pointer; + font-weight: var(--font-weight-regular); + position: relative; + transition: color 0.3s ease; + white-space: nowrap; + + @media screen and (max-width: map-get($grid-breakpoints, md)) { + padding: 5px 10px; + } +} + +.tab.active { + color: #42a5f5; + font-weight: var(--font-weight-bold); +} + +.tab.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 4px; + background-color: #42a5f5; + border-radius: 2px; +} + +.tab:hover { + color: #42a5f5; +} + +.tab-content { + padding: 1rem; + background-color: #ffffff; + min-height: 500px; +} + +.reference-image { + // max-width: 50%; + height: auto; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.ts new file mode 100644 index 00000000000..586483739fd --- /dev/null +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/tabbed-content.component.ts @@ -0,0 +1,44 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { CommonModule, NgIf } from '@angular/common'; +import { Item } from 'src/app/core/shared/item.model'; +import { FullItemComponent } from './full-item.component'; +import { ContentFilesComponent } from './content-files.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { SediciLicenseComponent } from './sedici-license.component'; + +@Component({ + selector: 'ds-tabbed-content', + standalone: true, + imports: [ + CommonModule, + NgIf, + FullItemComponent, + ContentFilesComponent, + SediciLicenseComponent, + TranslateModule, + ], + templateUrl: './tabbed-content.component.html', + styleUrls: ['./tabbed-content.component.scss'] +}) +export class TabbedContentComponent implements OnInit { + @Input() object: Item; + + selectedTabIndex = 0; + + tabs = [ + { label: 'sedici.tabs.files', visible: true }, + { label: 'sedici.tabs.license', visible: true }, + { label: 'sedici.tabs.statistics', visible: true }, + { label: 'sedici.tabs.moreInformation', visible: true } + ]; + + ngOnInit() { + if (!this.object?.allMetadata(['sedici.rights.license'])[0]?.value) { + this.tabs[1].visible = false; + } + } + + selectTab(index: number) { + this.selectedTabIndex = index; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.html index 7aa21532981..ad14fa5c401 100644 --- a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -1,239 +1,216 @@ - -
-
- - +
+
+
+
+
+ +
+

+ + +

+
+ +
+
+

+ + +

+
+
+
+ + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+
+ + +
+
-
-

- -

- -
-
- - - -
-
-
- - - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - -
- - {{"item.page.link.full" | translate}} - +
+
+
+
+ + +
+ + +
+
+
+
+ +
diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss index e69de29bb2d..aca311f46b0 100644 --- a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss @@ -0,0 +1,159 @@ +.container { + font-size: .75rem; +} + +.jumbotron { + padding: 1rem 0 0; + margin-bottom: 0; + background-color: #f6f6f6; +} + +.badge-title-container { + display: flex; +} + +.badge-title-content { + display: flex; + flex-direction: column; + + .title-content { + font-size: 1.75em; + font-weight: bold; + margin-bottom: 0; + + ::ng-deep .simple-view-element { + margin-bottom: 0px; + } + } +} + +.edit-menu { + margin-left: auto; +} + +.subtitle-content { + font-size: 1.33333em; + font-weight: var(--font-weight-regular); + font-style: italic; + color: #555; + margin-bottom: 0.5rem; + + ::ng-deep .simple-view-element { + margin-top: 0.5rem; + } +} + +.divider { + border-top: 1px solid #ccc; +} + +.divider-top { + margin-top: 1rem; + margin-bottom: .5rem; +} + +.section-divider { + border-bottom: 1px solid #D8E8Eb; +} + +sedici-context, +.author-container { + ::ng-deep span, ::ng-deep a { + font-size: 1.33333em; + font-weight: var(--font-weight-regular); + } + + ::ng-deep h6 { + font-size: 1.33333em; + font-weight: var(--font-weight-bold); + } +} + +.author-container { + ::ng-deep .simple-view-element { + line-height: 1.5; + } +} + +.flex-container { + @media screen and (min-width: 769px) { + display: flex; + justify-content: space-between; + align-items: center; + } +} + +.item-identifiers { + display: flex; + flex-wrap: wrap; + gap: 0.2rem; + margin: 0.5rem 0; + + @media screen and (min-width: 769px) { + ::ng-deep .simple-view-element { + margin-bottom: 0px; + } + } + +} + +.botones-context { + display: flex; + gap: 0.2rem; + flex-shrink: 0; + + @media screen and (max-width: 768px) { + gap: 0; + + button { + flex: 1 100%; + border-radius: 0; + border-top: 1px solid #ccc; + } + + button + button { + border-left: 1px solid #ccc; /* Línea divisoria */ + padding-left: 0.5rem; /* Espacio después de la línea */ + } + } + + ::ng-deep .btn { + font-size: 1.33333em; + font-weight: var(--font-weight-light); + } +} + +app-expandable-metadata { + ::ng-deep .simple-view-element { + line-height: 1.5; + } + + sedici-truncatable-generic-item-page-field { + ::ng-deep .content { + line-height: 1.5; + } + } +} + +.metadata-column { + padding: 0 .5rem ; + + ::ng-deep ds-generic-item-page-field, + ::ng-deep sedici-truncatable-generic-item-page-field, + ::ng-deep ds-item-page-uri-field { + h6 { + font-size: 1.25em; + font-weight: var(--font-weight-bold); + } + + span, a { + font-size: 1.25em; + font-weight: var(--font-weight-regular); + } + } +} + +// Modifico todos los botones que están incluidos en el componente +:host ::ng-deep .btn:focus { + outline-style: none !important; +} diff --git a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts index 9609ad35739..cfbe13d0216 100644 --- a/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts +++ b/src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts @@ -1,10 +1,15 @@ import { AsyncPipe, NgIf, + NgFor, + NgStyle, + NgClass, } from '@angular/common'; import { ChangeDetectionStrategy, Component, + ElementRef, + ViewChild, } from '@angular/core'; import { RouterLink } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; @@ -12,29 +17,31 @@ import { TranslateModule } from '@ngx-translate/core'; import { Context } from '../../../../../../../app/core/shared/context.model'; import { Item } from '../../../../../../../app/core/shared/item.model'; import { ViewMode } from '../../../../../../../app/core/shared/view-mode.model'; -import { CollectionsComponent } from '../../../../../../../app/item-page/field-components/collections/collections.component'; -import { ThemedMediaViewerComponent } from '../../../../../../../app/item-page/media-viewer/themed-media-viewer.component'; -import { MiradorViewerComponent } from '../../../../../../../app/item-page/mirador-viewer/mirador-viewer.component'; -import { ThemedFileSectionComponent } from '../../../../../../../app/item-page/simple/field-components/file-section/themed-file-section.component'; -import { ItemPageAbstractFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/abstract/item-page-abstract-field.component'; -import { ItemPageCcLicenseFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/cc-license/item-page-cc-license-field.component'; -import { ItemPageDateFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/date/item-page-date-field.component'; import { GenericItemPageFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; -import { ThemedItemPageTitleFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/title/themed-item-page-field.component'; import { ItemPageUriFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/uri/item-page-uri-field.component'; import { UntypedItemComponent as BaseComponent } from '../../../../../../../app/item-page/simple/item-types/untyped-item/untyped-item.component'; -import { ThemedMetadataRepresentationListComponent } from '../../../../../../../app/item-page/simple/metadata-representation-list/themed-metadata-representation-list.component'; import { DsoEditMenuComponent } from '../../../../../../../app/shared/dso-page/dso-edit-menu/dso-edit-menu.component'; -import { MetadataFieldWrapperComponent } from '../../../../../../../app/shared/metadata-field-wrapper/metadata-field-wrapper.component'; import { listableObjectComponent } from '../../../../../../../app/shared/object-collection/shared/listable-object/listable-object.decorator'; -import { ThemedResultsBackButtonComponent } from '../../../../../../../app/shared/results-back-button/themed-results-back-button.component'; -import { ThemedThumbnailComponent } from '../../../../../../../app/thumbnail/themed-thumbnail.component'; -import { MetadataValuesComponent } from 'src/app/item-page/field-components/metadata-values/metadata-values.component'; -import { MetadataRepresentationListComponent } from '../../metadata-representation-list/metadata-representation-list.component'; -import { FileSectionComponent } from '../../field-components/file-section/file-section.component'; -import { MediaViewerComponent } from '../../../media-viewer/media-viewer.component'; -import { ThumbnailComponent } from 'src/themes/custom/app/thumbnail/thumbnail.component'; -import { ResultsBackButtonComponent } from 'src/themes/custom/app/shared/results-back-button/results-back-button.component'; +import { SediciContextBadgeComponent } from 'src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component'; +import { LanguageSwitcherComponent } from './language-switcher.component'; +import { MetadataValue } from 'src/app/core/shared/metadata.models'; +import { BadgeMetadataValuesComponent } from '../../field-components/badge-metadata-values/badge-metadata-values.component'; +import { TabbedContentComponent } from './tabbed-content.component'; +import { SediciDateMetadataValuesComponent } from '../../field-components/date-metadata-values/sedici-date-metadata-values.component'; +import { SediciLanguageMetadataValuesComponent } from '../../field-components/language-metadata-values/sedici-language-metadata-values.component'; +import { setPersistentIdentifiers } from 'src/app/shared/utils/persistent.identifier'; +import { SediciTruncatableGenericItemPageFieldComponent } from './sedici-truncatable-generic-item-page-field'; +import { SediciContextComponent } from '../../field-components/context/sedici-context.component'; + +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { SediciCitationComponent } from '../../field-components/citation/sedici-citation.component'; +import { RouteService } from 'src/app/core/services/route.service'; +import { Router } from '@angular/router'; + +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { SediciShareButtonsComponent } from '../../field-components/share-buttons/sedici-share-buttons.component'; + +import { ExpandableMetadataComponent } from './expandable-metadata'; /** * Component that represents an untyped Item page */ @@ -49,30 +56,71 @@ import { ResultsBackButtonComponent } from 'src/themes/custom/app/shared/results standalone: true, imports: [ NgIf, - ThemedResultsBackButtonComponent, - MiradorViewerComponent, - ThemedItemPageTitleFieldComponent, + NgFor, + NgStyle, + NgClass, DsoEditMenuComponent, - MetadataFieldWrapperComponent, - ThemedThumbnailComponent, - ThemedMediaViewerComponent, - ThemedFileSectionComponent, - ItemPageDateFieldComponent, - ThemedMetadataRepresentationListComponent, GenericItemPageFieldComponent, - ItemPageAbstractFieldComponent, ItemPageUriFieldComponent, - CollectionsComponent, RouterLink, AsyncPipe, TranslateModule, - ItemPageCcLicenseFieldComponent, - MetadataValuesComponent, - MetadataRepresentationListComponent, - FileSectionComponent, - MediaViewerComponent, - ThumbnailComponent, - ResultsBackButtonComponent, + LanguageSwitcherComponent, + BadgeMetadataValuesComponent, + TabbedContentComponent, + SediciDateMetadataValuesComponent, + SediciLanguageMetadataValuesComponent, + SediciContextBadgeComponent, + SediciTruncatableGenericItemPageFieldComponent, + SediciContextComponent, + SediciCitationComponent, + NgbModule, + SediciShareButtonsComponent, + ExpandableMetadataComponent, ], }) -export class UntypedItemComponent extends BaseComponent {} +export class UntypedItemComponent extends BaseComponent { + subtype; + identifierOtherMetadataName = ['dc.identifier.uri', 'sedici.identifier.other']; + itemIdentifiers: { mdValue: MetadataValue, label: string, url: string }[]; + + @ViewChild('tabbedContent', { read: ElementRef }) tabbedContentElement: ElementRef; + @ViewChild('tabbedContent') tabbedContentComponent: TabbedContentComponent; + + constructor(private modalService: NgbModal, protected routeService: RouteService, protected router: Router) { + super(routeService, router); + } + + openModalCitation() { + this.modalService.open(SediciCitationComponent, { + centered: true, // Centra el modal + }); + } + + openModalShareButtons() { + const modalRef = this.modalService.open(SediciShareButtonsComponent, { + centered: true, // Centra el modal + }); + modalRef.componentInstance.link = this.object.firstMetadataValue('dc.identifier.uri'); + modalRef.componentInstance.title = this.object.firstMetadataValue('dc.title'); + modalRef.componentInstance.type = this.object.firstMetadataValue('sedici.subtype') || this.object.firstMetadataValue('dc.type'); + } + + get hasMetadata(): boolean { + return this.hasField('sedici.description.note') || + this.hasField('dc.format') || + this.hasField('dc.format.medium'); + } + + // Comprueba si el campo existe y tiene contenido + private hasField(field: string): boolean { + const value = this.object.metadata[field]; + return value && value.length > 0; + } + + ngOnInit() { + super.ngOnInit(); + this.subtype = this.object.metadata['sedici.subtype'][0]?.value; + this.itemIdentifiers = setPersistentIdentifiers(this.object, this.identifierOtherMetadataName); + } +} diff --git a/src/themes/custom/app/navbar/navbar.component.html b/src/themes/custom/app/navbar/navbar.component.html index e69de29bb2d..fcab3a7ec84 100644 --- a/src/themes/custom/app/navbar/navbar.component.html +++ b/src/themes/custom/app/navbar/navbar.component.html @@ -0,0 +1,23 @@ + diff --git a/src/themes/custom/app/navbar/navbar.component.scss b/src/themes/custom/app/navbar/navbar.component.scss index e69de29bb2d..48e6d38781b 100644 --- a/src/themes/custom/app/navbar/navbar.component.scss +++ b/src/themes/custom/app/navbar/navbar.component.scss @@ -0,0 +1,62 @@ +:host { + --ds-expandable-navbar-height: auto; + + nav.navbar { + background-color: var(--ds-navbar-bg); + align-items: baseline; + padding: 0; + } + + /** Mobile menu styling **/ + @media screen and (max-width: map-get($grid-breakpoints, md)-0.02) { + .navbar { + width: 100vw; + background-color: var(--bs-white); + position: fixed; + overflow: hidden; + height: 0; + z-index: var(--ds-nav-z-index); + &.open { + height: auto; + border-bottom: 3px var(--sedici-color) solid; // open navbar covers header-navbar-wrapper border + } + } + } + + @media screen and (min-width: map-get($grid-breakpoints, md)) { + .reset-padding-md { + margin-left: calc(var(--bs-spacer) / -1); + margin-right: calc(var(--bs-spacer) / -1); + } + } + + /* TODO remove when https://github.com/twbs/bootstrap/issues/24726 is fixed */ + .navbar-expand-md.navbar-container { + @media screen and (max-width: map-get($grid-breakpoints, md)-0.02) { + > .navbar-inner-container { + padding: 0 var(--bs-spacer); + } + padding: 0; + } + } + + #main-navbar ::ng-deep { + .ds-menu-item, .ds-menu-toggler-wrapper { + white-space: nowrap; + text-decoration: none; + } + + .dropdown-menu { + padding: 0.5rem !important; + } + + .ds-menu-item { + display: block; + padding: 0.5rem; + + &:hover, &:focus { + color: var(--ds-navbar-link-color-hover); + } + } + } +} diff --git a/src/themes/custom/app/navbar/navbar.component.ts b/src/themes/custom/app/navbar/navbar.component.ts index 9a5ee91b606..a40d2e423d1 100644 --- a/src/themes/custom/app/navbar/navbar.component.ts +++ b/src/themes/custom/app/navbar/navbar.component.ts @@ -13,18 +13,21 @@ import { ThemedUserMenuComponent } from 'src/app/shared/auth-nav-menu/user-menu/ import { NavbarComponent as BaseComponent } from '../../../../app/navbar/navbar.component'; import { slideMobileNav } from '../../../../app/shared/animations/slide'; +import { ImpersonateNavbarComponent } from 'src/app/shared/impersonate-navbar/impersonate-navbar.component'; +import { ThemedAuthNavMenuComponent } from 'src/app/shared/auth-nav-menu/themed-auth-nav-menu.component'; +import { ThemedLangSwitchComponent } from 'src/app/shared/lang-switch/themed-lang-switch.component'; /** * Component representing the public navbar */ @Component({ selector: 'ds-themed-navbar', - // styleUrls: ['./navbar.component.scss'], - styleUrls: ['../../../../app/navbar/navbar.component.scss'], - // templateUrl: './navbar.component.html', - templateUrl: '../../../../app/navbar/navbar.component.html', + styleUrls: ['./navbar.component.scss'], + // styleUrls: ['../../../../app/navbar/navbar.component.scss'], + templateUrl: './navbar.component.html', + // templateUrl: '../../../../app/navbar/navbar.component.html', animations: [slideMobileNav], standalone: true, - imports: [NgbDropdownModule, NgClass, NgIf, ThemedUserMenuComponent, NgFor, NgComponentOutlet, AsyncPipe, TranslateModule], + imports: [NgbDropdownModule, NgClass, NgIf, ThemedUserMenuComponent, NgFor, NgComponentOutlet, AsyncPipe, TranslateModule, ImpersonateNavbarComponent, ThemedAuthNavMenuComponent, ThemedLangSwitchComponent], }) export class NavbarComponent extends BaseComponent { } diff --git a/src/themes/custom/app/root/root.component.html b/src/themes/custom/app/root/root.component.html index e69de29bb2d..41eb7d59ade 100644 --- a/src/themes/custom/app/root/root.component.html +++ b/src/themes/custom/app/root/root.component.html @@ -0,0 +1,34 @@ + + +
+ +
+ + + +
+ +
+ +
+
+ +
+
+ + + +
+
+ + + + +
+ +
diff --git a/src/themes/custom/app/root/root.component.ts b/src/themes/custom/app/root/root.component.ts index 4894746e52d..6318709bcba 100644 --- a/src/themes/custom/app/root/root.component.ts +++ b/src/themes/custom/app/root/root.component.ts @@ -17,13 +17,14 @@ import { LiveRegionComponent } from '../../../../app/shared/live-region/live-reg import { ThemedLoadingComponent } from '../../../../app/shared/loading/themed-loading.component'; import { NotificationsBoardComponent } from '../../../../app/shared/notifications/notifications-board/notifications-board.component'; import { SystemWideAlertBannerComponent } from '../../../../app/system-wide-alert/alert-banner/system-wide-alert-banner.component'; +import { BottomNavigationBarComponent } from '../bottom-navigation-bar/bottom-navigation-bar'; @Component({ selector: 'ds-themed-root', // styleUrls: ['./root.component.scss'], styleUrls: ['../../../../app/root/root.component.scss'], - // templateUrl: './root.component.html', - templateUrl: '../../../../app/root/root.component.html', + templateUrl: './root.component.html', + // templateUrl: '../../../../app/root/root.component.html', animations: [slideSidebarPadding], standalone: true, imports: [ @@ -40,6 +41,7 @@ import { SystemWideAlertBannerComponent } from '../../../../app/system-wide-aler NotificationsBoardComponent, AsyncPipe, LiveRegionComponent, + BottomNavigationBarComponent, ], }) export class RootComponent extends BaseComponent { diff --git a/src/themes/custom/app/search-navbar/search-navbar.component.html b/src/themes/custom/app/search-navbar/search-navbar.component.html index e69de29bb2d..508ead4c1b0 100644 --- a/src/themes/custom/app/search-navbar/search-navbar.component.html +++ b/src/themes/custom/app/search-navbar/search-navbar.component.html @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/src/themes/custom/app/search-navbar/search-navbar.component.scss b/src/themes/custom/app/search-navbar/search-navbar.component.scss index e69de29bb2d..2dcbd223a32 100644 --- a/src/themes/custom/app/search-navbar/search-navbar.component.scss +++ b/src/themes/custom/app/search-navbar/search-navbar.component.scss @@ -0,0 +1,52 @@ +.navbar { + padding: 0; +} + +.navbar-brand { + width: 100%; + margin: 0; + padding: 0; +} + +form { + width: 100%; +} + +.search-form-container { + position: relative; + width: 100%; +} + +.search-icon { + position: absolute; + top: 50%; + transform: translateY(-50%); + color: #888; + z-index: 2; + cursor: pointer; +} + +.search-input { + border-radius: 10px; + padding: 10px 40px 10px 40px; + font-size: 14px; + height: auto; + background-color: white; + border: 1px solid #e0e0e0; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + width: 100%; + + &:focus { + outline: none; + box-shadow: 0 1px 4px rgba(0,0,0,0.15); + border-color: #d0d0d0; + } +} + +// Asegurarse de que se vea bien en móviles +@media screen and (max-width: map-get($grid-breakpoints, md)) { + .search-input { + width: 100%; + max-width: 100%; + } +} \ No newline at end of file diff --git a/src/themes/custom/app/search-navbar/search-navbar.component.ts b/src/themes/custom/app/search-navbar/search-navbar.component.ts index 59f6bf08a1a..c63fc69611d 100644 --- a/src/themes/custom/app/search-navbar/search-navbar.component.ts +++ b/src/themes/custom/app/search-navbar/search-navbar.component.ts @@ -1,23 +1,82 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { FormsModule, ReactiveFormsModule, + UntypedFormBuilder, } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { SearchService } from 'src/app/core/shared/search/search.service'; import { SearchNavbarComponent as BaseComponent } from '../../../../app/search-navbar/search-navbar.component'; import { BrowserOnlyPipe } from '../../../../app/shared/utils/browser-only.pipe'; import { ClickOutsideDirective } from '../../../../app/shared/utils/click-outside.directive'; @Component({ selector: 'ds-themed-search-navbar', - // styleUrls: ['./search-navbar.component.scss'], - styleUrls: ['../../../../app/search-navbar/search-navbar.component.scss'], - // templateUrl: './search-navbar.component.html' - templateUrl: '../../../../app/search-navbar/search-navbar.component.html', + styleUrls: ['./search-navbar.component.scss'], + // styleUrls: ['../../../../app/search-navbar/search-navbar.component.scss'], + templateUrl: './search-navbar.component.html', + // templateUrl: '../../../../app/search-navbar/search-navbar.component.html', standalone: true, imports: [ClickOutsideDirective, FormsModule, ReactiveFormsModule, TranslateModule, BrowserOnlyPipe], }) export class SearchNavbarComponent extends BaseComponent { + @Input() alwaysExpanded = false; + private localRouter: Router; + private localSearchService: SearchService; + + constructor( + formBuilder: UntypedFormBuilder, + router: Router, + searchService: SearchService, + private activatedRoute: ActivatedRoute + ) { + super(formBuilder, router, searchService); + this.localRouter = router; + this.localSearchService = searchService; + } + + ngOnInit() { + if (this.alwaysExpanded) { + this.searchExpanded = true; + this.isExpanded = 'expanded'; + } + + const currentQuery = this.activatedRoute.snapshot.queryParams?.query; + if (currentQuery) { + this.searchForm.patchValue({ + query: currentQuery + }); + } + } + + /** + * Sobrescribe el método onSubmit del componente base + * para mantener los parámetros de búsqueda existentes + */ + onSubmit(data: any) { + this.collapse(); + + // Obtiene los parámetros actuales de la URL + const currentParams = { ...this.activatedRoute.snapshot.queryParams }; + + // Combina los parámetros actuales con el nuevo término de búsqueda + const queryParams = { + ...currentParams, + query: data.query + }; + + // Si la query está vacía, eliminarla de los parámetros + if (!data.query) { + delete queryParams.query; + } + + const linkToNavigateTo = [this.localSearchService.getSearchLink().replace('/', '')]; + + this.localRouter.navigate(linkToNavigateTo, { + queryParams: queryParams, + }); + } } diff --git a/src/themes/custom/app/search-page/search-page.component.html b/src/themes/custom/app/search-page/search-page.component.html index e69de29bb2d..44f4802bd88 100644 --- a/src/themes/custom/app/search-page/search-page.component.html +++ b/src/themes/custom/app/search-page/search-page.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/themes/custom/app/search-page/search-page.component.scss b/src/themes/custom/app/search-page/search-page.component.scss index e69de29bb2d..33eb3628d63 100644 --- a/src/themes/custom/app/search-page/search-page.component.scss +++ b/src/themes/custom/app/search-page/search-page.component.scss @@ -0,0 +1,3 @@ +::ng-deep #search-form { + display: none; +} \ No newline at end of file diff --git a/src/themes/custom/app/search-page/search-page.component.ts b/src/themes/custom/app/search-page/search-page.component.ts index 2d8093c7541..fddc4554072 100644 --- a/src/themes/custom/app/search-page/search-page.component.ts +++ b/src/themes/custom/app/search-page/search-page.component.ts @@ -7,9 +7,9 @@ import { ThemedSearchComponent } from '../../../../app/shared/search/themed-sear @Component({ selector: 'ds-themed-search-page', - // styleUrls: ['./search-page.component.scss'], - // templateUrl: './search-page.component.html' - templateUrl: '../../../../app/search-page/search-page.component.html', + styleUrls: ['./search-page.component.scss'], + templateUrl: './search-page.component.html', + // templateUrl: '../../../../app/search-page/search-page.component.html', providers: [ { provide: SEARCH_CONFIG_SERVICE, diff --git a/src/themes/custom/app/shared/auth-nav-menu/auth-nav-menu.component.html b/src/themes/custom/app/shared/auth-nav-menu/auth-nav-menu.component.html index 78b0dcd67d3..7a18555d34b 100644 --- a/src/themes/custom/app/shared/auth-nav-menu/auth-nav-menu.component.html +++ b/src/themes/custom/app/shared/auth-nav-menu/auth-nav-menu.component.html @@ -3,7 +3,7 @@ class="nav-item" (click)="$event.stopPropagation();">
-
- + {{ 'nav.login' | translate }}(current) diff --git a/src/themes/custom/app/shared/lang-switch/lang-switch.component.html b/src/themes/custom/app/shared/lang-switch/lang-switch.component.html index 691c4f3704d..7cf6b68929b 100644 --- a/src/themes/custom/app/shared/lang-switch/lang-switch.component.html +++ b/src/themes/custom/app/shared/lang-switch/lang-switch.component.html @@ -4,7 +4,7 @@ aria-controls="language-menu-list" aria-haspopup="menu" [title]="'nav.language' | translate" - (click)="$event.preventDefault()" data-toggle="dropdown" ngbDropdownToggle + ngbDropdownToggle tabindex="0" class="text-uppercase"> {{translate.currentLang}} diff --git a/src/themes/custom/app/shared/lang-switch/lang-switch.component.scss b/src/themes/custom/app/shared/lang-switch/lang-switch.component.scss index 613274eb4c6..0d3457d5aac 100644 --- a/src/themes/custom/app/shared/lang-switch/lang-switch.component.scss +++ b/src/themes/custom/app/shared/lang-switch/lang-switch.component.scss @@ -1,7 +1,3 @@ -.dropdown-toggle::after { - display:none; -} - .dropdown-toggle { color: var(--ds-header-icon-color); @@ -19,18 +15,8 @@ } /* Asegúrate de que el menú desplegable no se corte */ -.dropdown-menu { - transform-origin: top right; /* Asegura que se despliegue desde la parte superior derecha */ - right: 0 !important; /* Alínea el borde derecho del menú con el contenedor */ - top: 100% !important; /* Desplaza el menú justo debajo del botón */ - transform: translateX(-85%); /* Lo mueve hacia la izquierda */ -} - - -.custom-dropdown-menu { - position: absolute; - top: 100%; /* Asegura que el menú aparezca justo debajo del botón */ - left: 0; /* Asegura que el menú aparezca alineado a la izquierda del botón */ - transform: translateY(0); /* Ajuste para evitar el corte por el borde de la pantalla */ - /* Otras propiedades que puedas necesitar */ +@media screen and (max-width: map-get($grid-breakpoints, md)) { + .dropdown-menu { + transform: translateY(-100%) !important; + } } diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html index e69de29bb2d..4f91c12fd1a 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html +++ b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html @@ -0,0 +1,10 @@ + + + + + + + {{ accessStatus | translate }} + + + \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.scss b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.scss index e69de29bb2d..b4863f5873d 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.scss +++ b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.scss @@ -0,0 +1,14 @@ +.access-status-open-access-listelement-badge { + color: green; + border: 1px solid green; + border-radius: 0px; +} + +.access-status-embargo-listelement-badge, +.access-status-metadata-only-listelement-badge, +.access-status-restricted-listelement-badge, +.access-status-unknown-listelement-badge { + color: grey; + border: 1px solid grey; + border-radius: 0px; +} \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts index 24e0006b884..5e17a61d473 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts +++ b/src/themes/custom/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts @@ -2,17 +2,72 @@ import { AsyncPipe, NgIf, } from '@angular/common'; -import { Component } from '@angular/core'; +import { + Component, +} from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; +import { + of as observableOf, +} from 'rxjs'; +import { + catchError, + map, +} from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +import { Item } from 'src/app/core/shared/item.model'; +import { ITEM } from 'src/app/core/shared/item.resource-type'; +import { hasValue } from 'src/app/shared/empty.util'; +import { AccessStatusObject } from 'src/app/shared/object-collection/shared/badges/access-status-badge/access-status.model'; import { AccessStatusBadgeComponent as BaseComponent } from 'src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component'; +import { RemoteData } from 'src/app/core/data/remote-data'; @Component({ selector: 'ds-themed-access-status-badge', - // styleUrls: ['./access-status-badge.component.scss'], - // templateUrl: './access-status-badge.component.html', - templateUrl: '../../../../../../../../app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html', + styleUrls: ['./access-status-badge.component.scss'], + templateUrl: './access-status-badge.component.html', + // templateUrl: '../../../../../../../../app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.html', standalone: true, imports: [NgIf, AsyncPipe, TranslateModule], }) export class AccessStatusBadgeComponent extends BaseComponent { + + ngOnInit(): void { + this.showAccessStatus = environment.item.showAccessStatuses; + if (this.object.type.toString() !== ITEM.value || !this.showAccessStatus || this.object == null) { + // Do not show the badge if the feature is inactive or if the item is null. + return; + } + + const item = this.object as Item; + let accessStatus$; + + if (item.accessStatus == null) { + // In case the access status has not been loaded, do it individually. + accessStatus$ = this.accessStatusDataService.findAccessStatusFor(item); + } else { + accessStatus$ = item.accessStatus; + } + + this.accessStatus$ = accessStatus$.pipe( + map((accessStatusRD: RemoteData) => { + if (accessStatusRD.statusCode !== 401 && hasValue(accessStatusRD.payload)) { + return accessStatusRD.payload; + } else { + return []; + } + }), + map((accessStatus: AccessStatusObject) => hasValue(accessStatus.status) ? accessStatus.status : 'unknown'), + map((status: string) => `access-status.${status.toLowerCase()}.listelement.badge`), + catchError(() => observableOf('access-status.unknown.listelement.badge')), + ); + + // stylesheet based on the access status value + this.subs.push( + this.accessStatus$.pipe( + map((accessStatusClass: string) => accessStatusClass.replace(/\./g, '-')), + ).subscribe((accessStatusClass: string) => { + this.accessStatusClass = accessStatusClass; + }), + ); + } } diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.html b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.html new file mode 100644 index 00000000000..2e8ea554692 --- /dev/null +++ b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.html @@ -0,0 +1,11 @@ + + + + +
+ + + + + {{ getYear() }} +
diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.scss b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.scss new file mode 100644 index 00000000000..7e869b02540 --- /dev/null +++ b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.scss @@ -0,0 +1,17 @@ +.badge-container { + display: flex; + align-items: center; + margin-bottom: 10px; + + .year { + font-weight: var(--font-weight-regular); + font-size: 1.66667em; + padding-left: 0.25rem; + } +} + +:host ::ng-deep .badge { + font-size: 1.16667em; + font-weight: var(--font-weight-regular); + padding: .5em; +} \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.ts b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.ts new file mode 100644 index 00000000000..4e80c02f319 --- /dev/null +++ b/src/themes/custom/app/shared/object-collection/shared/badges/sedici-context-badge/sedici-context-badge.component.ts @@ -0,0 +1,26 @@ +import { NgIf } from '@angular/common'; +import { Component } from '@angular/core'; +import { BadgesComponent as BaseComponent } from '../badges.component'; + +import { ThemedAccessStatusBadgeComponent } from 'src/app/shared/object-collection/shared/badges/access-status-badge/themed-access-status-badge.component'; +import { ThemedMyDSpaceStatusBadgeComponent } from 'src/app/shared/object-collection/shared/badges/my-dspace-status-badge/themed-my-dspace-status-badge.component'; +import { ThemedStatusBadgeComponent } from 'src/app/shared/object-collection/shared/badges/status-badge/themed-status-badge.component'; +import { ThemedTypeBadgeComponent } from 'src/app/shared/object-collection/shared/badges/type-badge/themed-type-badge.component'; + +@Component({ + selector: 'ds-sedici-context-badge', + styleUrls: ['./sedici-context-badge.component.scss'], + templateUrl: './sedici-context-badge.component.html', + standalone: true, + imports: [ThemedStatusBadgeComponent, NgIf, ThemedMyDSpaceStatusBadgeComponent, ThemedTypeBadgeComponent, ThemedAccessStatusBadgeComponent], +}) +export class SediciContextBadgeComponent extends BaseComponent { + + getYear(): string { + let dateString = this.object.firstMetadataValue('dc.date.issued') || this.object.firstMetadataValue('dc.date.created') || this.object.firstMetadataValue('sedici.date.exposure'); + if (dateString) { + return dateString.split('-')[0]; + } + return ''; + } +} diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.html b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.html index 93ff21e9c32..22b996a0965 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.html +++ b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.html @@ -1,3 +1,3 @@ - {{ typeBadgeMessage | translate }} + {{ typeBadgeMessage | translate }} \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.scss b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.scss index e69de29bb2d..f439633c398 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.scss +++ b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.scss @@ -0,0 +1,6 @@ +.badge { + color: white; + background-color: var(--sedici-color); + border: 1px solid var(--sedici-color); + border-radius: 0px; +} \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.ts b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.ts index 39436e0c6bf..d41e03f565e 100644 --- a/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.ts +++ b/src/themes/custom/app/shared/object-collection/shared/badges/type-badge/type-badge.component.ts @@ -8,7 +8,7 @@ import { TypeBadgeComponent as BaseComponent } from 'src/app/shared/object-colle @Component({ selector: 'ds-themed-type-badge', - // styleUrls: ['./type-badge.component.scss'], + styleUrls: ['./type-badge.component.scss'], templateUrl: './type-badge.component.html', // templateUrl: '../../../../../../../../app/shared/object-collection/shared/badges/type-badge/type-badge.component.html', standalone: true, diff --git a/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss b/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss index e69de29bb2d..ee97ef9f6aa 100644 --- a/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss +++ b/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss @@ -0,0 +1,11 @@ +// @import '../../../../../../../styles/variables'; + +.item-list-supervision { + a { + cursor: pointer; + } +} + +::ng-deep ds-badges .badge { + padding: .3rem; +} \ No newline at end of file diff --git a/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts b/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts index 7b2309dd758..a251978b66c 100644 --- a/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts +++ b/src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts @@ -21,8 +21,8 @@ import { ThemedThumbnailComponent } from '../../../../../../../../../app/thumbna @listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.Any, 'custom') @Component({ selector: 'ds-item-search-result-list-element', - // styleUrls: ['./item-search-result-list-element.component.scss'], - styleUrls: ['../../../../../../../../../app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss'], + styleUrls: ['./item-search-result-list-element.component.scss'], + // styleUrls: ['../../../../../../../../../app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.scss'], templateUrl: './item-search-result-list-element.component.html', // templateUrl: '../../../../../../../../../app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html', standalone: true, diff --git a/src/themes/custom/app/shared/search-form/search-form.component.scss b/src/themes/custom/app/shared/search-form/search-form.component.scss index 65e739444bc..de85b38fcac 100644 --- a/src/themes/custom/app/shared/search-form/search-form.component.scss +++ b/src/themes/custom/app/shared/search-form/search-form.component.scss @@ -21,7 +21,6 @@ .form-control { background-color: rgba(255, 255, 255, 0.7); // Fondo blanco con transparencia - color: white; // Texto blanco border: none; // Sin borde border-radius: 0; // Sin bordes redondeados en el input box-shadow: none; // Sin sombra en el input diff --git a/src/themes/custom/app/shared/search/search.component.html b/src/themes/custom/app/shared/search/search.component.html index e69de29bb2d..e0902806920 100644 --- a/src/themes/custom/app/shared/search/search.component.html +++ b/src/themes/custom/app/shared/search/search.component.html @@ -0,0 +1,106 @@ +
+
+
+ +
+
+
+ +
+ +
+ + + + + + +
+
+ + + + +
+
+
+ + +
+ + +
+
+
+ + + + + + + + + + +
+
+ + +
+
+
diff --git a/src/themes/custom/app/shared/search/search.component.ts b/src/themes/custom/app/shared/search/search.component.ts index 85a453c16cc..6a08b269bc7 100644 --- a/src/themes/custom/app/shared/search/search.component.ts +++ b/src/themes/custom/app/shared/search/search.component.ts @@ -22,8 +22,8 @@ import { ViewModeSwitchComponent } from '../../../../../app/shared/view-mode-swi selector: 'ds-themed-search', // styleUrls: ['./search.component.scss'], styleUrls: ['../../../../../app/shared/search/search.component.scss'], - // templateUrl: './search.component.html', - templateUrl: '../../../../../app/shared/search/search.component.html', + templateUrl: './search.component.html', + // templateUrl: '../../../../../app/shared/search/search.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [pushInOut], standalone: true, diff --git a/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.html b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.html new file mode 100644 index 00000000000..ef83cbf6448 --- /dev/null +++ b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.html @@ -0,0 +1,13 @@ +
+
+ +
+ + +
\ No newline at end of file diff --git a/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.scss b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.scss new file mode 100644 index 00000000000..a96cb5924d5 --- /dev/null +++ b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.scss @@ -0,0 +1,27 @@ +.content:not(.truncated) ~ button.expandButton { + display: none; +} + +.btn:focus { + box-shadow: none !important; +} + +.removeFaded.content::after { + display: none; +} + +@for $i from 1 through 10 { + .clamp-default-#{$i} { + margin-bottom: .5rem; + + .content { + &:after { + background: linear-gradient(to right, rgba(255, 255, 255, 0), #f6f6f6 70%); + } + } + } +} + +.clamp-default-none { + margin-bottom: .5rem; +} \ No newline at end of file diff --git a/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.ts b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.ts new file mode 100644 index 00000000000..bcbb857e711 --- /dev/null +++ b/src/themes/custom/app/shared/truncatable/truncatable-part/sedici-truncatable-part.component.ts @@ -0,0 +1,26 @@ +import { NgIf } from '@angular/common'; +import { + Component, + Input, +} from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; + +import { DragClickDirective } from 'src/app/shared/utils/drag-click.directive'; + +import { TruncatablePartComponent } from "src/app/shared/truncatable/truncatable-part/truncatable-part.component"; + +@Component({ + selector: 'sedici-truncatable-part', + templateUrl: './sedici-truncatable-part.component.html', + styleUrls: ['./sedici-truncatable-part.component.scss'], + standalone: true, + imports: [ + NgIf, + TranslateModule, + DragClickDirective, + ], +}) + +export class SediciTruncatablePartComponent extends TruncatablePartComponent { + @Input() showCollapseButton = true; +} diff --git a/src/themes/custom/app/shared/utils/modal-swipe-back.directive.ts b/src/themes/custom/app/shared/utils/modal-swipe-back.directive.ts new file mode 100644 index 00000000000..5ea067f1f3f --- /dev/null +++ b/src/themes/custom/app/shared/utils/modal-swipe-back.directive.ts @@ -0,0 +1,57 @@ +import { Directive, HostListener, ElementRef, OnInit } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { HostWindowService, WidthCategory } from 'src/app/shared/host-window.service'; +import { Observable } from 'rxjs'; + +@Directive({ + selector: 'div', + standalone: true +}) +export class ModalSwipeBackDirective implements OnInit { + private startX: number; + private swipeThreshold = -100; + + isMobile$: Observable; + isMobile = false; + + constructor( + private el: ElementRef, + private modalService: NgbModal, + private windowService: HostWindowService + ) { + this.isMobile$ = this.windowService.isUpTo(WidthCategory.MD); + } + + ngOnInit() { + this.isMobile$.subscribe(isMobile => { + this.isMobile = isMobile; + }); + + // Solo aplicar en dispositivos móviles + if (!this.isMobile) return; + + // Configurar prevención de swipe back del navegador + history.pushState(null, '', location.href); + window.onpopstate = () => { + history.pushState(null, '', location.href); + this.modalService.dismissAll(); + }; + } + + @HostListener('touchstart', ['$event']) + onTouchStart(event: TouchEvent) { + if (!this.isMobile) return; + this.startX = event.touches[0].clientX; + } + + @HostListener('touchend', ['$event']) + onTouchEnd(event: TouchEvent) { + if (!this.isMobile) return; + + const endX = event.changedTouches[0].clientX; + if (endX - this.startX < this.swipeThreshold) { + this.modalService.dismissAll(); + event.preventDefault(); + } + } +} \ No newline at end of file diff --git a/src/themes/custom/assets/images/COAR.png b/src/themes/custom/assets/images/COAR.png new file mode 100644 index 00000000000..e84cdd36f50 Binary files /dev/null and b/src/themes/custom/assets/images/COAR.png differ diff --git a/src/themes/custom/assets/images/ComCol/Logo_Radio_Universidad.png b/src/themes/custom/assets/images/ComCol/Logo_Radio_Universidad.png new file mode 100644 index 00000000000..c4fd7d81600 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/Logo_Radio_Universidad.png differ diff --git a/src/themes/custom/assets/images/ComCol/UNLP_Logo.png b/src/themes/custom/assets/images/ComCol/UNLP_Logo.png new file mode 100644 index 00000000000..526a50dc565 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/UNLP_Logo.png differ diff --git a/src/themes/custom/assets/images/ComCol/artes.png b/src/themes/custom/assets/images/ComCol/artes.png new file mode 100644 index 00000000000..264344e16c4 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/artes.png differ diff --git a/src/themes/custom/assets/images/ComCol/astronomia.png b/src/themes/custom/assets/images/ComCol/astronomia.png new file mode 100644 index 00000000000..d087b0c58ca Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/astronomia.png differ diff --git a/src/themes/custom/assets/images/ComCol/bachillerato.png b/src/themes/custom/assets/images/ComCol/bachillerato.png new file mode 100644 index 00000000000..5cfd5d8c776 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/bachillerato.png differ diff --git a/src/themes/custom/assets/images/ComCol/ead.png b/src/themes/custom/assets/images/ComCol/ead.png new file mode 100644 index 00000000000..c17356fe657 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/ead.png differ diff --git a/src/themes/custom/assets/images/ComCol/fca.png b/src/themes/custom/assets/images/ComCol/fca.png new file mode 100644 index 00000000000..264bdad7ca2 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/fca.png differ diff --git a/src/themes/custom/assets/images/ComCol/fce.png b/src/themes/custom/assets/images/ComCol/fce.png new file mode 100644 index 00000000000..f315c3c7aaa Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/fce.png differ diff --git a/src/themes/custom/assets/images/ComCol/fts.png b/src/themes/custom/assets/images/ComCol/fts.png new file mode 100644 index 00000000000..307e17f2f75 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/fts.png differ diff --git a/src/themes/custom/assets/images/ComCol/informatica.png b/src/themes/custom/assets/images/ComCol/informatica.png new file mode 100644 index 00000000000..42f44334d44 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/informatica.png differ diff --git a/src/themes/custom/assets/images/ComCol/ing.png b/src/themes/custom/assets/images/ComCol/ing.png new file mode 100644 index 00000000000..516e5f55200 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/ing.png differ diff --git a/src/themes/custom/assets/images/ComCol/logoradio.png b/src/themes/custom/assets/images/ComCol/logoradio.png new file mode 100644 index 00000000000..4a8d41e09a6 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/logoradio.png differ diff --git a/src/themes/custom/assets/images/ComCol/museo.png b/src/themes/custom/assets/images/ComCol/museo.png new file mode 100644 index 00000000000..38b8d786d67 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/museo.png differ diff --git a/src/themes/custom/assets/images/ComCol/periodismo.png b/src/themes/custom/assets/images/ComCol/periodismo.png new file mode 100644 index 00000000000..3a201e7b73d Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/periodismo.png differ diff --git a/src/themes/custom/assets/images/ComCol/psicologia.png b/src/themes/custom/assets/images/ComCol/psicologia.png new file mode 100644 index 00000000000..0876d97b062 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/psicologia.png differ diff --git a/src/themes/custom/assets/images/ComCol/redmuseos.png b/src/themes/custom/assets/images/ComCol/redmuseos.png new file mode 100644 index 00000000000..42f51fcaefa Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/redmuseos.png differ diff --git a/src/themes/custom/assets/images/ComCol/redunci.png b/src/themes/custom/assets/images/ComCol/redunci.png new file mode 100644 index 00000000000..41d1510a7c7 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/redunci.png differ diff --git a/src/themes/custom/assets/images/ComCol/sadio.jpg b/src/themes/custom/assets/images/ComCol/sadio.jpg new file mode 100644 index 00000000000..27894973d06 Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/sadio.jpg differ diff --git a/src/themes/custom/assets/images/ComCol/veterinaria.png b/src/themes/custom/assets/images/ComCol/veterinaria.png new file mode 100644 index 00000000000..4490a3f742a Binary files /dev/null and b/src/themes/custom/assets/images/ComCol/veterinaria.png differ diff --git a/src/themes/custom/assets/images/DescargarHover.svg b/src/themes/custom/assets/images/DescargarHover.svg new file mode 100644 index 00000000000..52d2c87569f --- /dev/null +++ b/src/themes/custom/assets/images/DescargarHover.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/themes/custom/assets/images/DescargarOff.svg b/src/themes/custom/assets/images/DescargarOff.svg new file mode 100644 index 00000000000..020c212b246 --- /dev/null +++ b/src/themes/custom/assets/images/DescargarOff.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/themes/custom/assets/images/La referencia.png b/src/themes/custom/assets/images/La referencia.png new file mode 100644 index 00000000000..3d7bda6d2f7 Binary files /dev/null and b/src/themes/custom/assets/images/La referencia.png differ diff --git a/src/themes/custom/assets/images/Open_Access.png b/src/themes/custom/assets/images/Open_Access.png new file mode 100644 index 00000000000..df669a87e4c Binary files /dev/null and b/src/themes/custom/assets/images/Open_Access.png differ diff --git a/src/themes/custom/assets/images/SEDICIUNLP.svg b/src/themes/custom/assets/images/SEDICIUNLP.svg new file mode 100644 index 00000000000..94f000a2873 --- /dev/null +++ b/src/themes/custom/assets/images/SEDICIUNLP.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/themes/custom/assets/images/SEDICI_2024_mobile.svg b/src/themes/custom/assets/images/SEDICI_2024_mobile.svg new file mode 100644 index 00000000000..91d212bede5 --- /dev/null +++ b/src/themes/custom/assets/images/SEDICI_2024_mobile.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/src/themes/custom/assets/images/SNRD.png b/src/themes/custom/assets/images/SNRD.png new file mode 100644 index 00000000000..34c0c44f461 Binary files /dev/null and b/src/themes/custom/assets/images/SNRD.png differ diff --git a/src/themes/custom/assets/images/creative commons.svg b/src/themes/custom/assets/images/creative commons.svg new file mode 100644 index 00000000000..a02ef65491b --- /dev/null +++ b/src/themes/custom/assets/images/creative commons.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/themes/custom/assets/images/dspace.png b/src/themes/custom/assets/images/dspace.png new file mode 100644 index 00000000000..0d810938944 Binary files /dev/null and b/src/themes/custom/assets/images/dspace.png differ diff --git a/src/themes/custom/assets/images/escudoUNLP.svg b/src/themes/custom/assets/images/escudoUNLP.svg new file mode 100644 index 00000000000..9fcbc1f53fb --- /dev/null +++ b/src/themes/custom/assets/images/escudoUNLP.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/themes/custom/assets/images/fondo.avif b/src/themes/custom/assets/images/fondo.avif deleted file mode 100644 index 1addece4876..00000000000 Binary files a/src/themes/custom/assets/images/fondo.avif and /dev/null differ diff --git a/src/themes/custom/assets/images/icon_audio.png b/src/themes/custom/assets/images/icon_audio.png new file mode 100644 index 00000000000..2de13ba7569 Binary files /dev/null and b/src/themes/custom/assets/images/icon_audio.png differ diff --git a/src/themes/custom/assets/images/icon_imagen.png b/src/themes/custom/assets/images/icon_imagen.png new file mode 100644 index 00000000000..95432564981 Binary files /dev/null and b/src/themes/custom/assets/images/icon_imagen.png differ diff --git a/src/themes/custom/assets/images/icon_pdf.png b/src/themes/custom/assets/images/icon_pdf.png new file mode 100644 index 00000000000..78396db75bb Binary files /dev/null and b/src/themes/custom/assets/images/icon_pdf.png differ diff --git a/src/themes/custom/assets/images/icon_zip.png b/src/themes/custom/assets/images/icon_zip.png new file mode 100644 index 00000000000..f4e3b410b42 Binary files /dev/null and b/src/themes/custom/assets/images/icon_zip.png differ diff --git a/src/themes/custom/styles/_global-styles.scss b/src/themes/custom/styles/_global-styles.scss index 3857f1ad0ac..7c26e951ba5 100644 --- a/src/themes/custom/styles/_global-styles.scss +++ b/src/themes/custom/styles/_global-styles.scss @@ -2,3 +2,13 @@ // imports the base global style @import '../../../styles/_global-styles.scss'; + +.container { + @media screen and (min-width: 1200px) { + max-width: 90%; + } + + @media screen and (min-width: 1500px) { + max-width: 1400px; + } +} \ No newline at end of file diff --git a/src/themes/custom/styles/_theme_css_variable_overrides.scss b/src/themes/custom/styles/_theme_css_variable_overrides.scss index 3ff54cbf8f8..e56e30d2f00 100644 --- a/src/themes/custom/styles/_theme_css_variable_overrides.scss +++ b/src/themes/custom/styles/_theme_css_variable_overrides.scss @@ -5,4 +5,14 @@ //--ds-header-logo-height-xs: 50px; //--ds-header-icon-color: #{$link-color}; //--ds-header-icon-color-hover: #{darken($link-color, 15%)}; + --sedici-color: #{$sedici-color} !important; + + --ds-breadcrumb-bg: #{$white} !important; + --ds-breadcrumb-max-length: 500px; + --ds-breadcrumb-max-length-mobile: 300px; + + --font-weight-thin: #{$font-weight-thin} !important; + --font-weight-light: #{$font-weight-light} !important; + --font-weight-regular: #{$font-weight-regular} !important; + --font-weight-bold: #{$font-weight-bold} !important; } diff --git a/src/themes/custom/styles/_theme_sass_variable_overrides.scss b/src/themes/custom/styles/_theme_sass_variable_overrides.scss index f1387aa619b..718d96556f9 100644 --- a/src/themes/custom/styles/_theme_sass_variable_overrides.scss +++ b/src/themes/custom/styles/_theme_sass_variable_overrides.scss @@ -3,11 +3,15 @@ // still uses Sass variables internally. So if you want to override bootstrap (or other sass // variables) you can do so here. Their CSS counterparts will include the changes you make here -// $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default; +@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,200;0,300;0,400;0,600;0,700;0,800;1,200;1,300;1,400;1,600;1,700;1,800&display=swap'); + +$font-family-sans-serif: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default; // // $gray-700: #495057 !default; // Bootstrap $gray-700 // $gray-100: #f8f9fa !default; // $gray-100 // +$sedici-color: #42a5f5 !default; +$white: #ffffff !default; // $blue: #2B4E72 !default; // $green: #94BA65 !default; // $cyan: #006666 !default; @@ -27,3 +31,12 @@ // ) !default; // // $link-color: map-get($theme-colors, info) !default; + +/*** MODIFICACIÓN DE VARIABLES PARA CUSTOM ***/ +$font-size-base: 0.875rem !default; // Assumes the browser default, typically `16px` +$line-height-base: 2 !default; // En lugar del 1.5 por defecto + +$font-weight-thin: 100 !default; +$font-weight-light: 300 !default; +$font-weight-regular: 400 !default; +$font-weight-bold: 700 !default; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4c8145c4be7..2cd85d6aa71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11416,4 +11416,4 @@ yocto-queue@^1.0.0: zone.js@~0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.15.0.tgz#4810624e58d6dcf7b8379c1631765589917a0d8f" - integrity sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA== + integrity sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA== \ No newline at end of file