Skip to content

Commit

Permalink
#21701 fix When editing a piece of content, update the pag… (#1904)
Browse files Browse the repository at this point in the history
* #21701 fix When editing a piece of content, update the page title with the content title

* Feedback
  • Loading branch information
alfredo-dotcms authored Mar 4, 2022
1 parent 48288ed commit ee05fc9
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { of } from 'rxjs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { By, Title } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
Expand Down Expand Up @@ -50,6 +50,7 @@ describe('DotContentletWrapperComponent', () => {
let dotAddContentletService: DotContentletEditorService;
let dotAlertConfirmService: DotAlertConfirmService;
let dotRouterService: DotRouterService;
let titleService: Title;
let dotIframeService: DotIframeService;

beforeEach(
Expand All @@ -66,6 +67,7 @@ describe('DotContentletWrapperComponent', () => {
DotcmsConfigService,
LoggerService,
StringUtils,
Title,
{ provide: DotEventsSocketURL, useFactory: dotEventSocketURLFactory },
{
provide: DotHttpErrorManagerService,
Expand Down Expand Up @@ -113,8 +115,10 @@ describe('DotContentletWrapperComponent', () => {
dotAddContentletService = de.injector.get(DotContentletEditorService);
dotAlertConfirmService = de.injector.get(DotAlertConfirmService);
dotRouterService = de.injector.get(DotRouterService);
titleService = de.injector.get(Title);
dotIframeService = de.injector.get(DotIframeService);

spyOn(titleService, 'setTitle');
spyOn(dotIframeService, 'reload');
spyOn(dotAddContentletService, 'clear');
spyOn(dotAddContentletService, 'load');
Expand All @@ -123,6 +127,11 @@ describe('DotContentletWrapperComponent', () => {
spyOn(component.custom, 'emit');
});

afterEach(() => {
component.url = null;
fixture.detectChanges();
});

it('should show dot-iframe-dialog', () => {
fixture.detectChanges();
dotIframeDialog = de.query(By.css('dot-iframe-dialog'));
Expand Down Expand Up @@ -304,6 +313,23 @@ describe('DotContentletWrapperComponent', () => {
dotIframeDialog.triggerEventHandler('custom', params);
expect(dotIframeService.reload).toHaveBeenCalledTimes(1);
});

it('should set Header and Page title', () => {
const params = {
detail: {
name: 'edit-contentlet-loaded',
data: {
contentType: 'Blog',
pageTitle: 'test'
}
}
};
spyOn(titleService, 'getTitle').and.returnValue(' - dotCMS platform');
dotIframeDialog.triggerEventHandler('custom', params);

expect(component.header).toBe('Blog');
expect(titleService.setTitle).toHaveBeenCalledWith('test - dotCMS platform');
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DotMessageService } from '@services/dot-message/dot-messages.service';
import { DotAlertConfirmService } from '@services/dot-alert-confirm';
import { DotRouterService } from '@services/dot-router/dot-router.service';
import { DotIframeService } from '@components/_common/iframe/service/dot-iframe/dot-iframe.service';
import { Title } from '@angular/platform-browser';

export interface DotCMSEditPageEvent {
name: string;
Expand Down Expand Up @@ -49,7 +50,8 @@ export class DotContentletWrapperComponent {
private dotAlertConfirmService: DotAlertConfirmService,
private dotMessageService: DotMessageService,
private dotRouterService: DotRouterService,
private dotIframeService: DotIframeService
private dotIframeService: DotIframeService,
private titleService: Title
) {
if (!this.customEventsHandler) {
this.customEventsHandler = {
Expand Down Expand Up @@ -83,6 +85,13 @@ export class DotContentletWrapperComponent {
},
'edit-contentlet-loaded': (e: CustomEvent) => {
this.header = e.detail.data.contentType;
this.titleService.setTitle(
`${
e.detail.data.pageTitle
? e.detail.data.pageTitle + ' - '
: this.titleService.getTitle()
} ${this.titleService.getTitle().split(' - ')[1]}`
);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DotcmsEventsService, LoginService, Auth } from '@dotcms/dotcms-js';

import { Observable, Subject, of } from 'rxjs';
import { skip } from 'rxjs/operators';
import { Title } from '@angular/platform-browser';

class RouterMock {
_events: Subject<any> = new Subject();
Expand Down Expand Up @@ -69,6 +70,16 @@ class DotMenuServiceMock {
}
}

class TitleServiceMock {
getTitle(): string {
return 'dotCMS platform';
}

setTitle(_title: string): void {
/* */
}
}

class DotcmsEventsServiceMock {
_events: Subject<any> = new Subject();

Expand Down Expand Up @@ -156,6 +167,7 @@ describe('DotNavigationService', () => {
let dotMenuService: DotMenuService;
let loginService: LoginService;
let router;
let titleService: Title;

beforeEach(
waitForAsync(() => {
Expand All @@ -167,6 +179,10 @@ describe('DotNavigationService', () => {
provide: DotcmsEventsService,
useClass: DotcmsEventsServiceMock
},
{
provide: Title,
useClass: TitleServiceMock
},
{
provide: DotMenuService,
useClass: DotMenuServiceMock
Expand Down Expand Up @@ -208,7 +224,9 @@ describe('DotNavigationService', () => {
loginService = testbed.inject(LoginService);
dotEventService = testbed.inject(DotEventsService);
router = testbed.inject(Router);
titleService = testbed.inject(Title);

spyOn(titleService, 'setTitle');
spyOn(dotEventService, 'notify');
spyOn(dotMenuService, 'reloadMenu').and.callThrough();
localStorage.clear();
Expand Down Expand Up @@ -326,7 +344,7 @@ describe('DotNavigationService', () => {
});

it('should go to first portlet on auth change', () => {
((loginService as unknown) as LoginServiceMock).triggerNewAuth(baseMockAuth);
(loginService as unknown as LoginServiceMock).triggerNewAuth(baseMockAuth);

spyOn(dotMenuService, 'loadMenu').and.returnValue(
of([
Expand Down Expand Up @@ -364,6 +382,11 @@ describe('DotNavigationService', () => {
router.triggerNavigationEnd('/123');
});

it('should set Page title based on url', () => {
router.triggerNavigationEnd('url/link1');
expect(titleService.setTitle).toHaveBeenCalledWith('Label 1 - dotCMS platform');
});

// TODO: needs to fix this, looks like the dotcmsEventsService instance is different here not sure why.
xit('should subscribe to UPDATE_PORTLET_LAYOUTS websocket event', () => {
expect(dotcmsEventsService.subscribeTo).toHaveBeenCalledWith('UPDATE_PORTLET_LAYOUTS');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DotRouterService } from '@services/dot-router/dot-router.service';
import { DotIframeService } from '../../_common/iframe/service/dot-iframe/dot-iframe.service';
import { DotEventsService } from '@services/dot-events/dot-events.service';
import { DotLocalstorageService } from '@services/dot-localstorage/dot-localstorage.service';
import { Title } from '@angular/platform-browser';

export const replaceSectionsMap = {
'edit-page': 'site-browser'
Expand Down Expand Up @@ -67,60 +68,59 @@ function isEditPageFromSiteBrowser(menuId: string, previousUrl: string): boolean
return menuId === 'edit-page' && previousUrl === '/c/site-browser';
}

const setActiveItems = ({ url, collapsed, menuId, previousUrl }: DotActiveItemsProps) => (
source: Observable<DotMenu[]>
) => {
let urlId = getTheUrlId(url);

return source.pipe(
map((m: DotMenu[]) => {
const menus: DotMenu[] = [...m];
let isActive = false;

if (
isEditPageFromSiteBrowser(menuId, previousUrl) ||
(isDetailPage(urlId, url) && isMenuActive(menus))
) {
return null;
}

// When user browse using the navigation (Angular Routing)
if (menuId && menuId !== 'edit-page') {
return getActiveMenuFromMenuId({
menus,
menuId,
collapsed,
url: urlId,
previousUrl
});
}

// When user browse using the browser url bar, direct links or reload page
urlId = replaceIdForNonMenuSection(urlId) || urlId;

for (let i = 0; i < menus.length; i++) {
menus[i].active = false;
menus[i].isOpen = false;
const setActiveItems =
({ url, collapsed, menuId, previousUrl }: DotActiveItemsProps) =>
(source: Observable<DotMenu[]>) => {
let urlId = getTheUrlId(url);
return source.pipe(
map((m: DotMenu[]) => {
const menus: DotMenu[] = [...m];
let isActive = false;

if (
isEditPageFromSiteBrowser(menuId, previousUrl) ||
(isDetailPage(urlId, url) && isMenuActive(menus))
) {
return null;
}

for (let k = 0; k < menus[i].menuItems.length; k++) {
// Once we activate the first one all the others are close
if (isActive) {
menus[i].menuItems[k].active = false;
}
// When user browse using the navigation (Angular Routing)
if (menuId && menuId !== 'edit-page') {
return getActiveMenuFromMenuId({
menus,
menuId,
collapsed,
url: urlId,
previousUrl
});
}

if (!isActive && menus[i].menuItems[k].id === urlId) {
isActive = true;
menus[i].active = true;
menus[i].isOpen = true;
menus[i].menuItems[k].active = true;
// When user browse using the browser url bar, direct links or reload page
urlId = replaceIdForNonMenuSection(urlId) || urlId;

for (let i = 0; i < menus.length; i++) {
menus[i].active = false;
menus[i].isOpen = false;

for (let k = 0; k < menus[i].menuItems.length; k++) {
// Once we activate the first one all the others are close
if (isActive) {
menus[i].menuItems[k].active = false;
}

if (!isActive && menus[i].menuItems[k].id === urlId) {
isActive = true;
menus[i].active = true;
menus[i].isOpen = true;
menus[i].menuItems[k].active = true;
}
}
}
}

return menus;
})
);
};
return menus;
})
);
};

const DOTCMS_MENU_STATUS = 'dotcms.menu.status';

Expand All @@ -133,6 +133,7 @@ function getTheUrlId(url: string): string {
export class DotNavigationService {
private _collapsed$: BehaviorSubject<boolean> = new BehaviorSubject(true);
private _items$: BehaviorSubject<DotMenu[]> = new BehaviorSubject([]);
private _appMainTitle: string;

constructor(
private dotEventsService: DotEventsService,
Expand All @@ -142,8 +143,10 @@ export class DotNavigationService {
private dotcmsEventsService: DotcmsEventsService,
private loginService: LoginService,
private router: Router,
private dotLocalstorageService: DotLocalstorageService
private dotLocalstorageService: DotLocalstorageService,
private titleService: Title
) {
this._appMainTitle = this.titleService.getTitle();
const savedMenuStatus = this.dotLocalstorageService.getItem<boolean>(DOTCMS_MENU_STATUS);
this._collapsed$.next(savedMenuStatus === false ? false : true);

Expand All @@ -153,16 +156,23 @@ export class DotNavigationService {

this.onNavigationEnd()
.pipe(
switchMap((event: NavigationEnd) =>
this.dotMenuService.loadMenu().pipe(
switchMap((event: NavigationEnd) => {
return this.dotMenuService.loadMenu().pipe(
tap((menu: DotMenu[]) => {
const pageTitle = this.getPageCurrentTitle(event.url, menu);
this.titleService.setTitle(
`${pageTitle ? pageTitle + ' - ' : ''} ${this._appMainTitle}`
);
return menu;
}),
setActiveItems({
url: event.url,
collapsed: this._collapsed$.getValue(),
menuId: this.router.getCurrentNavigation().extras.state?.menuId,
previousUrl: this.dotRouterService.previousUrl
})
)
),
);
}),
filter((menu) => !!menu)
)
.subscribe((menus: DotMenu[]) => {
Expand Down Expand Up @@ -373,4 +383,17 @@ export class DotNavigationService {
private setMenu(menu: DotMenu[]) {
this._items$.next(this.addMenuLinks(menu));
}

private getPageCurrentTitle(url: string, menu: DotMenu[]): string {
let title = '';
const flattedMenu = menu
.reduce((a, { menuItems }) => [...a, ...menuItems], [])
.reduce((a, { label, menuLink }) => ({ ...a, [menuLink]: label }), {});

Object.entries(flattedMenu).forEach(([menuLink, label]: [string, string]) => {
title = url.indexOf(menuLink) >= 0 ? label : title;
});

return title;
}
}

0 comments on commit ee05fc9

Please sign in to comment.