ng-easycommerce-v18 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, makeEnvironmentProviders, inject, Injectable, PLATFORM_ID, RendererFactory2, afterNextRender, signal, EnvironmentInjector, runInInjectionContext, Component, ChangeDetectorRef, HostListener, CUSTOM_ELEMENTS_SCHEMA, Input, Pipe, Injector, EventEmitter, Output, forwardRef, afterRender, ViewChild, computed, Renderer2, ChangeDetectionStrategy, Directive, Inject } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
- import { isPlatformBrowser, DOCUMENT, AsyncPipe, CommonModule, TitleCasePipe, JsonPipe, UpperCasePipe, Location } from '@angular/common';
4
+ import { DOCUMENT, isPlatformBrowser, AsyncPipe, CommonModule, TitleCasePipe, JsonPipe, UpperCasePipe, Location } from '@angular/common';
5
5
  import { take, BehaviorSubject, shareReplay, map, catchError, of, filter, ReplaySubject, firstValueFrom, concatMap, throwError, switchMap, combineLatest } from 'rxjs';
6
6
  import { HttpClient, HttpHeaders } from '@angular/common/http';
7
7
  import * as i1$1 from '@ngx-translate/core';
@@ -225,6 +225,10 @@ class CoreConstantsService {
225
225
  * Provee el ID de la plataforma en donde se esta ejecutando el codigo, esto sirve para poder diferenciar si es de un servidor o un navegador web.
226
226
  */
227
227
  platformId = inject(PLATFORM_ID);
228
+ /**
229
+ * Document token para acceso SSR-compatible al documento
230
+ */
231
+ document = inject(DOCUMENT);
228
232
  /**
229
233
  * Guarda la variable window del web browser.
230
234
  */
@@ -264,6 +268,77 @@ class CoreConstantsService {
264
268
  * @returns
265
269
  */
266
270
  url = () => this.apiConstants.API_URL.replace(/\/$/, ''); // remove last slash
271
+ /**
272
+ * URL del sitio frontend - Compatible con Angular SSR
273
+ */
274
+ get FRONTEND_URL() {
275
+ // Verificar si estamos en el navegador
276
+ if (isPlatformBrowser(this.platformId)) {
277
+ // Primero intenta leer de window.__env (configurado por Docker)
278
+ const windowEnv = this.window?.__env;
279
+ if (windowEnv?.frontendUrl) {
280
+ return windowEnv.frontendUrl;
281
+ }
282
+ // Si no hay configuración específica, construir desde window.location
283
+ if (this.window?.location) {
284
+ return `${this.window.location.protocol}//${this.window.location.host}`;
285
+ }
286
+ }
287
+ // Para SSR, intentar construir desde el document si está disponible
288
+ if (this.document?.location) {
289
+ return `${this.document.location.protocol}//${this.document.location.host}`;
290
+ }
291
+ // Fallback - retornar URL vacía
292
+ return '';
293
+ }
294
+ /**
295
+ * Retorna la URL completa del frontend con una ruta opcional
296
+ * @param path - Ruta opcional para agregar a la URL base
297
+ * @returns {string} URL completa del frontend
298
+ */
299
+ getFrontendUrl = (path) => {
300
+ const baseUrl = this.FRONTEND_URL;
301
+ if (!path) {
302
+ return baseUrl;
303
+ }
304
+ // Asegurar que la ruta comience con '/' y no tenga doble slash
305
+ const cleanPath = path.startsWith('/') ? path : `/${path}`;
306
+ const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
307
+ return `${cleanBaseUrl}${cleanPath}`;
308
+ };
309
+ /**
310
+ * Retorna la URL absoluta de una imagen para meta tags (compatible con SSR)
311
+ * @param postMedia - Ruta de la imagen
312
+ * @returns {string} URL absoluta de la imagen
313
+ */
314
+ getAbsoluteImageUrl = (postMedia) => {
315
+ // Si la URL ya es absoluta, devolverla tal como está
316
+ if (postMedia && (postMedia.startsWith('http://') || postMedia.startsWith('https://'))) {
317
+ return postMedia;
318
+ }
319
+ // Construir la URL de la imagen usando la URL del API
320
+ const imageUrl = this.mediaImageUrl(postMedia);
321
+ // Si la URL de la imagen ya es absoluta, devolverla
322
+ if (imageUrl.startsWith('http://') || imageUrl.startsWith('https://')) {
323
+ return imageUrl;
324
+ }
325
+ // Si es una URL relativa, convertirla a absoluta usando la URL base del API
326
+ const apiBaseUrl = this.apiConstants.API_URL;
327
+ if (apiBaseUrl.startsWith('http://') || apiBaseUrl.startsWith('https://')) {
328
+ // API_URL ya es absoluta
329
+ return imageUrl;
330
+ }
331
+ // Si API_URL es relativa, usar la URL del frontend como base
332
+ const frontendUrl = this.FRONTEND_URL;
333
+ if (!frontendUrl) {
334
+ return imageUrl; // Fallback si no podemos determinar la URL del frontend
335
+ }
336
+ // Construir URL absoluta
337
+ const cleanApiUrl = apiBaseUrl.startsWith('/') ? apiBaseUrl.substring(1) : apiBaseUrl;
338
+ const cleanFrontendUrl = frontendUrl.endsWith('/') ? frontendUrl.slice(0, -1) : frontendUrl;
339
+ const cleanImageUrl = imageUrl.startsWith('/') ? imageUrl.substring(1) : imageUrl;
340
+ return `${cleanFrontendUrl}/${cleanApiUrl}${cleanImageUrl}`;
341
+ };
267
342
  /**
268
343
  * Retorna la url de las imagenes de los banners
269
344
  * @returns
@@ -8429,15 +8504,13 @@ class ProductDetailEcComponent {
8429
8504
  _meta = inject(Meta);
8430
8505
  _title = inject(Title);
8431
8506
  _location = inject(Location);
8432
- _router = inject(Router);
8433
- _document = inject(DOCUMENT);
8434
- _platformId = inject(PLATFORM_ID);
8435
8507
  product$ = this._productDetailService.product$;
8436
8508
  options$ = this._productDetailService.options$;
8437
8509
  data$ = this._productDetailService.associatedData$;
8438
8510
  routeSubscription;
8439
8511
  route = inject(ActivatedRoute);
8440
8512
  currentProductId;
8513
+ _router = inject(Router);
8441
8514
  ngOnDestroy() {
8442
8515
  this.routeSubscription?.unsubscribe();
8443
8516
  }
@@ -8457,7 +8530,6 @@ class ProductDetailEcComponent {
8457
8530
  creditAccountShowPrices = null;
8458
8531
  // Agregar esta propiedad al inicio de la clase
8459
8532
  productSignal = signal(null);
8460
- lastMetaTagsProductId = null;
8461
8533
  constructor() {
8462
8534
  this._activedRoute.params.subscribe(queryParams => {
8463
8535
  this.code = queryParams["id"];
@@ -8500,86 +8572,13 @@ class ProductDetailEcComponent {
8500
8572
  }
8501
8573
  updateMetaTags(product) {
8502
8574
  const descripcionLimpia = he.decode(product.description || '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
8503
- // Obtener la URL completa de manera compatible con SSR
8504
- let currentUrl = '';
8505
- if (isPlatformBrowser(this._platformId)) {
8506
- // En el navegador, usar window.location
8507
- currentUrl = window.location.href;
8508
- }
8509
- else {
8510
- // En SSR, construir la URL completa manualmente
8511
- const routerUrl = this._router.url;
8512
- // Obtener el origin del documento o usar uno por defecto
8513
- let origin = '';
8514
- try {
8515
- // Intentar obtener el origin del documento
8516
- if (this._document.defaultView && this._document.defaultView.location) {
8517
- origin = this._document.defaultView.location.origin;
8518
- }
8519
- else {
8520
- // Fallback: construir el origin desde los headers de la request
8521
- // Detectar el protocolo correcto del documento actual
8522
- const protocol = this._document.location?.protocol ||
8523
- (typeof window !== 'undefined' ? window.location.protocol : 'http:');
8524
- const host = this._document.location?.host || 'localhost';
8525
- origin = `${protocol}//${host}`;
8526
- }
8527
- }
8528
- catch (error) {
8529
- // Si falla, usar la URL base de las constantes como fallback
8530
- const fallbackUrl = this._consts.url ? this._consts.url() :
8531
- (typeof window !== 'undefined' ? `${window.location.protocol}//${window.location.host}` : 'http://localhost');
8532
- origin = fallbackUrl.replace(/\/$/, ''); // Remover trailing slash
8533
- }
8534
- currentUrl = origin + routerUrl;
8535
- }
8536
- // Verificar que el producto tenga datos válidos
8537
- if (!product || !product.name) {
8538
- console.warn('Product is null, undefined, or missing name for meta tags');
8539
- return;
8540
- }
8541
- // Evitar actualizaciones duplicadas para el mismo producto
8542
- const productId = String(product.id || product.name);
8543
- if (this.lastMetaTagsProductId === productId) {
8544
- return;
8545
- }
8546
- this.lastMetaTagsProductId = productId;
8547
- // Log para debug (comentado para producción)
8548
- // console.log('Updating meta tags for product:', {
8549
- // name: product.name,
8550
- // description: product.description,
8551
- // pictures: product.picturesdefault
8552
- // });
8553
- // Preparar los valores con fallbacks más robustos
8554
- const title = product.name || 'Producto sin nombre';
8555
- const description = descripcionLimpia || 'Producto disponible';
8556
- // Manejar la imagen de manera más robusta
8557
- let imageUrl = '';
8558
- if (product.picturesdefault) {
8559
- const firstImage = Array.isArray(product.picturesdefault) ? product.picturesdefault[0] : product.picturesdefault;
8560
- if (firstImage) {
8561
- imageUrl = this._consts.mediaImageUrl(firstImage) || '';
8562
- }
8563
- }
8564
- // Si no hay imagen, usar una imagen por defecto o vacía
8565
- if (!imageUrl) {
8566
- imageUrl = ''; // O puedes poner una imagen por defecto
8567
- }
8568
- // Actualizar las meta tags
8569
- this._meta.updateTag({ property: 'og:title', content: title });
8570
- this._meta.updateTag({ property: 'og:description', content: description });
8571
- this._meta.updateTag({ property: 'og:image', content: imageUrl });
8575
+ const currentUrl = this._consts.getFrontendUrl() + this._router.url; // URL absoluta del producto
8576
+ const imageUrl = this._consts.getAbsoluteImageUrl(Array.isArray(product.picturesdefault) ? product.picturesdefault[0] : product.picturesdefault);
8577
+ this._meta.updateTag({ property: 'og:title', content: product.name || '' });
8578
+ this._meta.updateTag({ property: 'og:description', content: descripcionLimpia || '' });
8579
+ this._meta.updateTag({ property: 'og:image', content: imageUrl || '' });
8572
8580
  this._meta.updateTag({ property: 'og:url', content: currentUrl });
8573
8581
  this._meta.updateTag({ property: 'og:type', content: 'product' });
8574
- // También actualizar el título de la página
8575
- this._title.setTitle(title);
8576
- // Log para verificar los valores finales (comentado para producción)
8577
- // console.log('Meta tags updated:', {
8578
- // title,
8579
- // description,
8580
- // imageUrl,
8581
- // currentUrl
8582
- // });
8583
8582
  }
8584
8583
  decodeHtml(html) {
8585
8584
  const txt = document.createElement('textarea');