Merge remote-tracking branch 'origin/dev' into dev
All checks were successful
Build and Deploy / test-backend (push) Successful in 31s
PR Checks / prettier-autofix (pull_request) Successful in 10s
Build and Deploy / test-frontend (push) Successful in 1m6s
PR Checks / security-sast (pull_request) Successful in 31s
PR Checks / test-backend (pull_request) Successful in 28s
Build and Deploy / build-and-push (push) Successful in 30s
PR Checks / test-frontend (pull_request) Successful in 1m5s
Build and Deploy / deploy (push) Successful in 24s
All checks were successful
Build and Deploy / test-backend (push) Successful in 31s
PR Checks / prettier-autofix (pull_request) Successful in 10s
Build and Deploy / test-frontend (push) Successful in 1m6s
PR Checks / security-sast (pull_request) Successful in 31s
PR Checks / test-backend (pull_request) Successful in 28s
Build and Deploy / build-and-push (push) Successful in 30s
PR Checks / test-frontend (pull_request) Successful in 1m5s
Build and Deploy / deploy (push) Successful in 24s
This commit is contained in:
@@ -61,7 +61,7 @@ const appChildRoutes: Routes = [
|
|||||||
'Scopri il team 3D fab e il laboratorio di stampa 3D con sedi in Ticino e Bienne.',
|
'Scopri il team 3D fab e il laboratorio di stampa 3D con sedi in Ticino e Bienne.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/* {
|
/* {
|
||||||
path: 'materials',
|
path: 'materials',
|
||||||
loadComponent: () =>
|
loadComponent: () =>
|
||||||
import('./features/materials/materials-page.component').then(
|
import('./features/materials/materials-page.component').then(
|
||||||
|
|||||||
@@ -130,7 +130,9 @@
|
|||||||
<div class="cart-line-copy">
|
<div class="cart-line-copy">
|
||||||
<strong>{{ cartItemName(item) }}</strong>
|
<strong>{{ cartItemName(item) }}</strong>
|
||||||
@if (cartItemVariant(item); as variant) {
|
@if (cartItemVariant(item); as variant) {
|
||||||
<span class="cart-line-meta">{{ variant | translate }}</span>
|
<span class="cart-line-meta">{{
|
||||||
|
variant | translate
|
||||||
|
}}</span>
|
||||||
}
|
}
|
||||||
@if (cartItemColor(item); as color) {
|
@if (cartItemColor(item); as color) {
|
||||||
<span class="cart-line-color">
|
<span class="cart-line-color">
|
||||||
|
|||||||
@@ -59,9 +59,11 @@ export class SeoService {
|
|||||||
applyPageSeo(override: PageSeoOverride): void {
|
applyPageSeo(override: PageSeoOverride): void {
|
||||||
const cleanPath = this.getCleanPath(this.router.url);
|
const cleanPath = this.getCleanPath(this.router.url);
|
||||||
const lang = this.resolveLangFromPath(cleanPath);
|
const lang = this.resolveLangFromPath(cleanPath);
|
||||||
const title = this.asString(override.title) ?? this.defaultTitleByLang[lang];
|
const title =
|
||||||
|
this.asString(override.title) ?? this.defaultTitleByLang[lang];
|
||||||
const description =
|
const description =
|
||||||
this.asString(override.description) ?? this.defaultDescriptionByLang[lang];
|
this.asString(override.description) ??
|
||||||
|
this.defaultDescriptionByLang[lang];
|
||||||
const robots = this.asString(override.robots) ?? 'index, follow';
|
const robots = this.asString(override.robots) ?? 'index, follow';
|
||||||
const ogTitle = this.asString(override.ogTitle) ?? title;
|
const ogTitle = this.asString(override.ogTitle) ?? title;
|
||||||
const ogDescription = this.asString(override.ogDescription) ?? description;
|
const ogDescription = this.asString(override.ogDescription) ?? description;
|
||||||
@@ -135,7 +137,11 @@ export class SeoService {
|
|||||||
): string | undefined {
|
): string | undefined {
|
||||||
const mapKey = `${key}ByLang`;
|
const mapKey = `${key}ByLang`;
|
||||||
const localized = routeData[mapKey];
|
const localized = routeData[mapKey];
|
||||||
if (localized && typeof localized === 'object' && !Array.isArray(localized)) {
|
if (
|
||||||
|
localized &&
|
||||||
|
typeof localized === 'object' &&
|
||||||
|
!Array.isArray(localized)
|
||||||
|
) {
|
||||||
const mapped = localized as SeoMap;
|
const mapped = localized as SeoMap;
|
||||||
const byLang = this.asString(mapped[lang]);
|
const byLang = this.asString(mapped[lang]);
|
||||||
if (byLang) {
|
if (byLang) {
|
||||||
@@ -152,7 +158,10 @@ export class SeoService {
|
|||||||
|
|
||||||
private resolveLangFromPath(path: string): SupportedLang {
|
private resolveLangFromPath(path: string): SupportedLang {
|
||||||
const firstSegment = path.split('/').filter(Boolean)[0]?.toLowerCase();
|
const firstSegment = path.split('/').filter(Boolean)[0]?.toLowerCase();
|
||||||
if (firstSegment && this.supportedLangs.has(firstSegment as SupportedLang)) {
|
if (
|
||||||
|
firstSegment &&
|
||||||
|
this.supportedLangs.has(firstSegment as SupportedLang)
|
||||||
|
) {
|
||||||
return firstSegment as SupportedLang;
|
return firstSegment as SupportedLang;
|
||||||
}
|
}
|
||||||
return 'it';
|
return 'it';
|
||||||
|
|||||||
@@ -212,10 +212,10 @@
|
|||||||
<input
|
<input
|
||||||
class="ui-form-control"
|
class="ui-form-control"
|
||||||
type="text"
|
type="text"
|
||||||
[(ngModel)]="categoryForm.slug"
|
[(ngModel)]="categoryForm.slug"
|
||||||
name="categorySlug"
|
name="categorySlug"
|
||||||
placeholder="desk-accessories"
|
placeholder="desk-accessories"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="ui-button ui-button--ghost"
|
class="ui-button ui-button--ghost"
|
||||||
|
|||||||
@@ -1343,7 +1343,9 @@ export class AdminShopComponent implements OnInit, OnDestroy {
|
|||||||
seoTitleEn: this.optionalValue(this.categoryForm.seoTitles['en']),
|
seoTitleEn: this.optionalValue(this.categoryForm.seoTitles['en']),
|
||||||
seoTitleDe: this.optionalValue(this.categoryForm.seoTitles['de']),
|
seoTitleDe: this.optionalValue(this.categoryForm.seoTitles['de']),
|
||||||
seoTitleFr: this.optionalValue(this.categoryForm.seoTitles['fr']),
|
seoTitleFr: this.optionalValue(this.categoryForm.seoTitles['fr']),
|
||||||
seoDescription: this.optionalValue(this.categoryForm.seoDescriptions['it']),
|
seoDescription: this.optionalValue(
|
||||||
|
this.categoryForm.seoDescriptions['it'],
|
||||||
|
),
|
||||||
seoDescriptionIt: this.optionalValue(
|
seoDescriptionIt: this.optionalValue(
|
||||||
this.categoryForm.seoDescriptions['it'],
|
this.categoryForm.seoDescriptions['it'],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -239,7 +239,8 @@
|
|||||||
|
|
||||||
<div class="order-item-meta">
|
<div class="order-item-meta">
|
||||||
<span
|
<span
|
||||||
>{{ "CHECKOUT.QTY" | translate }}: {{ item.quantity }}</span
|
>{{ "CHECKOUT.QTY" | translate }}:
|
||||||
|
{{ item.quantity }}</span
|
||||||
>
|
>
|
||||||
<span *ngIf="showItemMaterial(item)">
|
<span *ngIf="showItemMaterial(item)">
|
||||||
{{ "CHECKOUT.MATERIAL" | translate }}:
|
{{ "CHECKOUT.MATERIAL" | translate }}:
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
}}</a>
|
}}</a>
|
||||||
@for (crumb of p.breadcrumbs; track crumb.id) {
|
@for (crumb of p.breadcrumbs; track crumb.id) {
|
||||||
<span class="breadcrumbs__separator">/</span>
|
<span class="breadcrumbs__separator">/</span>
|
||||||
<a class="breadcrumbs__item" [routerLink]="categoryLink(crumb.slug)"
|
<a
|
||||||
|
class="breadcrumbs__item"
|
||||||
|
[routerLink]="categoryLink(crumb.slug)"
|
||||||
>{{ crumb.name }}</a
|
>{{ crumb.name }}</a
|
||||||
>
|
>
|
||||||
}
|
}
|
||||||
@@ -143,12 +145,15 @@
|
|||||||
<span>{{ selectedMaterial()?.label }}</span>
|
<span>{{ selectedMaterial()?.label }}</span>
|
||||||
}
|
}
|
||||||
@if (
|
@if (
|
||||||
colorLabel(activeVariant) !== selectedMaterial()?.label
|
colorLabel(activeVariant) !==
|
||||||
|
selectedMaterial()?.label
|
||||||
) {
|
) {
|
||||||
@if (selectedMaterial()?.label) {
|
@if (selectedMaterial()?.label) {
|
||||||
<span aria-hidden="true">·</span>
|
<span aria-hidden="true">·</span>
|
||||||
}
|
}
|
||||||
<span>{{ colorLabel(activeVariant) | translate }}</span>
|
<span>{{
|
||||||
|
colorLabel(activeVariant) | translate
|
||||||
|
}}</span>
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
@@ -174,7 +179,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="material-grid">
|
<div class="material-grid">
|
||||||
@for (material of materialOptions(); track material.key) {
|
@for (
|
||||||
|
material of materialOptions();
|
||||||
|
track material.key
|
||||||
|
) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="material-option"
|
class="material-option"
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|||||||
import { catchError, combineLatest, finalize, of, switchMap, tap } from 'rxjs';
|
import { catchError, combineLatest, finalize, of, switchMap, tap } from 'rxjs';
|
||||||
import { SeoService } from '../../core/services/seo.service';
|
import { SeoService } from '../../core/services/seo.service';
|
||||||
import { LanguageService } from '../../core/services/language.service';
|
import { LanguageService } from '../../core/services/language.service';
|
||||||
import {
|
import { findColorHex, getColorHex } from '../../core/constants/colors.const';
|
||||||
findColorHex,
|
|
||||||
getColorHex,
|
|
||||||
} from '../../core/constants/colors.const';
|
|
||||||
import { AppButtonComponent } from '../../shared/components/app-button/app-button.component';
|
import { AppButtonComponent } from '../../shared/components/app-button/app-button.component';
|
||||||
import { AppCardComponent } from '../../shared/components/app-card/app-card.component';
|
import { AppCardComponent } from '../../shared/components/app-card/app-card.component';
|
||||||
import { StlViewerComponent } from '../../shared/components/stl-viewer/stl-viewer.component';
|
import { StlViewerComponent } from '../../shared/components/stl-viewer/stl-viewer.component';
|
||||||
@@ -381,7 +378,9 @@ export class ProductDetailComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
colorLabel(variant: ShopProductVariantOption): string {
|
colorLabel(variant: ShopProductVariantOption): string {
|
||||||
return variant.colorLabel || variant.colorName || variant.variantLabel || '-';
|
return (
|
||||||
|
variant.colorLabel || variant.colorName || variant.variantLabel || '-'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
colorHex(variant: ShopProductVariantOption | null | undefined): string {
|
colorHex(variant: ShopProductVariantOption | null | undefined): string {
|
||||||
|
|||||||
@@ -84,7 +84,9 @@
|
|||||||
<div class="cart-line-copy">
|
<div class="cart-line-copy">
|
||||||
<strong>{{ cartItemName(item) }}</strong>
|
<strong>{{ cartItemName(item) }}</strong>
|
||||||
@if (cartItemVariant(item); as variant) {
|
@if (cartItemVariant(item); as variant) {
|
||||||
<span class="cart-line-meta">{{ variant | translate }}</span>
|
<span class="cart-line-meta">{{
|
||||||
|
variant | translate
|
||||||
|
}}</span>
|
||||||
}
|
}
|
||||||
@if (cartItemColor(item); as color) {
|
@if (cartItemColor(item); as color) {
|
||||||
<span class="cart-line-color">
|
<span class="cart-line-color">
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
import { Component, input, output, signal, computed, inject } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
signal,
|
||||||
|
computed,
|
||||||
|
inject,
|
||||||
|
} from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import {
|
import {
|
||||||
|
|||||||
Reference in New Issue
Block a user