diff --git a/src/app/features/project-editor/facade/project-editor.facade.ts b/src/app/features/project-editor/facade/project-editor.facade.ts index 2e1a87c..32ec9ed 100644 --- a/src/app/features/project-editor/facade/project-editor.facade.ts +++ b/src/app/features/project-editor/facade/project-editor.facade.ts @@ -386,6 +386,31 @@ export class ProjectEditorFacade { return true; } + /** + * Inserts a nav link that points at a static page by id rather than a raw + * route. `type: 'staticPage'` is already understood by the resolvers + * (StaticPageResolverService / FooterResolverService derive the label and + * route from the page itself) - this only closes the editor-side gap of + * never being able to create that item shape. + */ + addStaticPageNavLink(target: 'header' | 'footer', pageId: string): void { + this.updateBootstrap(current => { + const list = current.navigation[target]; + if (!this.isFlatNavList(list) || !pageId) { + return current; + } + const items = list as NavigationItemConfig[]; + const newItem: NavigationItemConfig = { + id: `nav-page-${Date.now()}`, + type: 'staticPage', + key: pageId, + order: items.length + 1, + visible: true, + }; + return { ...current, navigation: { ...current.navigation, [target]: [...items, newItem] } }; + }); + } + addNavLink(target: 'header' | 'footer'): void { this.updateBootstrap(current => { const list = current.navigation[target]; diff --git a/src/app/features/project-editor/sections/navigation-section.component.html b/src/app/features/project-editor/sections/navigation-section.component.html index e3b58a0..a904996 100644 --- a/src/app/features/project-editor/sections/navigation-section.component.html +++ b/src/app/features/project-editor/sections/navigation-section.component.html @@ -3,6 +3,8 @@
{{ 'builder.addLink' | translate }} + + {{ 'builder.insertPageLink' | translate }}
@@ -17,8 +19,12 @@
- - + @if (isStaticPageLink(item)) { + + } @else { + + + }
@@ -29,6 +35,8 @@

{{ 'builder.navigationFooter' | translate }}

@if (footerLinks(); as footer) { {{ 'builder.addLink' | translate }} + + {{ 'builder.insertPageLink' | translate }} } @@ -45,8 +53,12 @@
- - + @if (isStaticPageLink(item)) { + + } @else { + + + }
diff --git a/src/app/features/project-editor/sections/navigation-section.component.ts b/src/app/features/project-editor/sections/navigation-section.component.ts index e1680de..4d524b8 100644 --- a/src/app/features/project-editor/sections/navigation-section.component.ts +++ b/src/app/features/project-editor/sections/navigation-section.component.ts @@ -8,19 +8,44 @@ import { InputComponent } from '../../../shared/ui/input/input.component'; import { SectionCardComponent } from '../../../shared/ui/section-card/section-card.component'; import { ToggleComponent } from '../../../shared/ui/toggle/toggle.component'; import { LocaleTabsComponent } from '../../../shared/ui/locale-tabs/locale-tabs.component'; +import { SelectComponent, SelectOption } from '../../../shared/ui/select/select.component'; +import { ContentManagementFacade } from '../../content-management/facade/content-management.facade'; @Component({ selector: 'app-project-editor-navigation-section', standalone: true, - imports: [FormsModule, TranslatePipe, ButtonComponent, InputComponent, SectionCardComponent, ToggleComponent, LocaleTabsComponent], + imports: [FormsModule, TranslatePipe, ButtonComponent, InputComponent, SectionCardComponent, ToggleComponent, LocaleTabsComponent, SelectComponent], templateUrl: './navigation-section.component.html', styleUrls: ['./section.shared.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class ProjectEditorNavigationSectionComponent { private readonly facade = inject(ProjectEditorFacade); + private readonly contentFacade = inject(ContentManagementFacade); readonly bootstrap = this.facade.bootstrap; + readonly pageOptions = computed(() => + this.contentFacade.pages(this.bootstrap()).map(page => ({ value: page.id, label: page.title || page.id })), + ); + readonly selectedPageId = signal>({ header: '', footer: '' }); + + updateSelectedPage(target: 'header' | 'footer', pageId: string): void { + this.selectedPageId.set({ ...this.selectedPageId(), [target]: pageId }); + } + + insertPageLink(target: 'header' | 'footer'): void { + const pageId = this.selectedPageId()[target]; + if (!pageId) { + return; + } + this.facade.addStaticPageNavLink(target, pageId); + this.updateSelectedPage(target, ''); + } + + isStaticPageLink(item: NavigationItemConfig): boolean { + return item.type === 'staticPage'; + } + readonly supportedLocales = computed(() => this.bootstrap()?.tenant.supportedLocales ?? []); readonly defaultLocale = computed(() => this.bootstrap()?.tenant.defaultLocale ?? ''); readonly activeLocale = signal(null); @@ -40,6 +65,12 @@ export class ProjectEditorNavigationSectionComponent { /** Display label used for the row heading — a stable identifier, not tied to the active locale. */ labelOf(item: NavigationItemConfig): string { + if (this.isStaticPageLink(item) && !item.label) { + // A static-page link has no editable label of its own - the resolver + // derives it from the linked page's title at render time - so fall + // back to the page id rather than showing a blank row heading. + return item.key ?? ''; + } if (typeof item.label === 'string' || !item.label) { return item.label ?? ''; } diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index af2c689..0035b93 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -518,6 +518,8 @@ export const en: Translations = { navigationFooter: 'Footer Navigation', navigationFooterGrouped: 'Footer navigation uses grouped columns and is not editable here yet — edit via the Footer tab.', addLink: 'Add Link', + insertPageLink: 'Insert page link', + linkedToPage: 'Linked to page', removeLink: 'Remove', linkLabel: 'Label', linkUrl: 'URL', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 5484405..465b8af 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -518,6 +518,8 @@ export const hy: Translations = { navigationFooter: 'Ստորին նավիգացիա', navigationFooterGrouped: 'Ստորին նավիգացիան խմբավորված է սյուներով և դեռ խմբագրելի չէ այստեղ. օգտագործեք «Footer» ներդիրը։', addLink: 'Ավելացնել հղում', + insertPageLink: 'Ներդնել էջի հղում', + linkedToPage: 'Կապված է էջի հետ', removeLink: 'Հեռացնել', linkLabel: 'Պիտակ', linkUrl: 'URL', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index c61c31f..ffb8c7c 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -518,6 +518,8 @@ export const ru: Translations = { navigationFooter: 'Навигация в подвале', navigationFooterGrouped: 'Навигация подвала сгруппирована по колонкам и пока недоступна для редактирования здесь — используйте вкладку "Подвал".', addLink: 'Добавить ссылку', + insertPageLink: 'Вставить ссылку на страницу', + linkedToPage: 'Связано со страницей', removeLink: 'Удалить', linkLabel: 'Название', linkUrl: 'URL', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index 5b5d43f..1f017b8 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -516,6 +516,8 @@ export interface Translations { navigationFooter: string; navigationFooterGrouped: string; addLink: string; + insertPageLink: string; + linkedToPage: string; removeLink: string; linkLabel: string; linkUrl: string;