Skip to content

Commit

Permalink
Fix #24160 dot favorite add favorite page to context menu (#24875)
Browse files Browse the repository at this point in the history
* #24160 Favorite Page portlet: add / edit favorite page from context menu

* #24160 Favorite Page portlet: add / edit favorite page from context menu - Code Cleanup

* #24160 Favorite Page portlet: add / edit favorite page from context menu - unit tests

* #24160 Favorite Page portlet: add / edit favorite page from context menu - feedback
  • Loading branch information
alfredo-dotcms authored May 11, 2023
1 parent 9dc362c commit a44c4a3
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ describe('DotEditPageToolbarComponent', () => {
useValue: new MockDotMessageService({
'dot.common.whats.changed': 'Whats',
'dot.common.cancel': 'Cancel',
'favoritePage.dialog.header.add.page': 'Add Favorite Page'
'favoritePage.dialog.header': 'Add Favorite Page'
})
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,15 @@ export class DotEditContentComponent implements OnInit, OnDestroy {
*/
showFavoritePageDialog(openDialog: boolean): void {
if (openDialog) {
const favoritePageUrl = generateDotFavoritePageUrl(this.pageStateInternal);
const favoritePageUrl = generateDotFavoritePageUrl({
deviceInode: this.pageStateInternal.viewAs.device?.inode,
languageId: this.pageStateInternal.viewAs.language.id,
pageURI: this.pageStateInternal.page.pageURI,
siteId: this.pageStateInternal.site?.identifier
});

this.dialogService.open(DotFavoritePageComponent, {
header: this.dotMessageService.get('favoritePage.dialog.header.add.page'),
header: this.dotMessageService.get('favoritePage.dialog.header'),
width: '80rem',
data: {
page: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,12 @@ export class DotPageStateService {
[page, user]: [page: DotPageRenderParameters, user: CurrentUser] = [null, null]
) => {
if (page) {
const urlParam = generateDotFavoritePageUrl(page);
const urlParam = generateDotFavoritePageUrl({
deviceInode: page.viewAs.device?.inode,
languageId: page.viewAs.language.id,
pageURI: page.page.pageURI,
siteId: page.site?.identifier
});

return this.dotESContentService
.get({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ describe('DotPagesFavoritePanelComponent', () => {
expect(elem.componentInstance['iconPos']).toBe('start');
expect(elem.componentInstance['expandIcon']).toBe('pi pi-angle-down');
expect(elem.componentInstance['collapseIcon']).toBe('pi pi-angle-up');
expect(elem.componentInstance['header']).toBe('favorites');
expect(elem.componentInstance['header']).toBe('favoritePage.panel.header');
expect(elem.componentInstance['toggleable']).toBe(true);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import { HttpCode } from '@dotcms/dotcms-js';
import { DotCMSContentlet } from '@dotcms/dotcms-models';

import { DotFavoritePageComponent } from '../../dot-edit-page/components/dot-favorite-page/dot-favorite-page.component';
import { DotPagesState, DotPageStore } from '../dot-pages-store/dot-pages.store';
import { DotActionsMenuEventParams, FAVORITE_PAGE_LIMIT } from '../dot-pages.component';
import {
DotPagesState,
DotPageStore,
FAVORITE_PAGE_LIMIT
} from '../dot-pages-store/dot-pages.store';
import { DotActionsMenuEventParams } from '../dot-pages.component';

@Component({
selector: 'dot-pages-favorite-panel',
Expand Down Expand Up @@ -102,7 +106,7 @@ export class DotPagesFavoritePanelComponent {

private displayFavoritePageDialog(favoritePage: DotCMSContentlet) {
this.dialogService.open(DotFavoritePageComponent, {
header: this.dotMessageService.get('favoritePage.dialog.header.add.page'),
header: this.dotMessageService.get('favoritePage.dialog.header'),
width: '80rem',
data: {
page: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,23 +501,42 @@ describe('DotPageStore', () => {
}));

it('should get all Workflow actions and static actions from a contentlet', () => {
const expectedInputArray = [{ ...dotcmsContentTypeBasicMock, ...contentTypeDataMock[0] }];
spyOn(dotWorkflowsActionsService, 'getByInode').and.returnValue(of(mockWorkflowsActions));
spyOn(dotESContentService, 'get').and.returnValue(
of({
contentTook: 0,
jsonObjectView: {
contentlets: expectedInputArray as unknown as DotCMSContentlet[]
},
queryTook: 1,
resultsSize: 4
})
);
dotPageStore.showActionsMenu({
item: favoritePagesInitialTestData[0],
actionMenuDomId: 'test1'
});

dotPageStore.state$.subscribe((data) => {
expect(data.pages.menuActions.length).toEqual(6);
expect(data.pages.menuActions[0].label).toEqual('Edit');
expect(data.pages.menuActions[1].label).toEqual(mockWorkflowsActions[0].name);
expect(data.pages.menuActions[2].label).toEqual(mockWorkflowsActions[1].name);
expect(data.pages.menuActions[3].label).toEqual(mockWorkflowsActions[2].name);
expect(data.pages.menuActions[4].label).toEqual('contenttypes.content.push_publish');
expect(data.pages.menuActions[5].label).toEqual('contenttypes.content.add_to_bundle');
expect(data.pages.menuActions.length).toEqual(7);
expect(data.pages.menuActions[0].label).toEqual('favoritePage.contextMenu.action.edit');
expect(data.pages.menuActions[1].label).toEqual('Edit');
expect(data.pages.menuActions[2].label).toEqual(mockWorkflowsActions[0].name);
expect(data.pages.menuActions[3].label).toEqual(mockWorkflowsActions[1].name);
expect(data.pages.menuActions[4].label).toEqual(mockWorkflowsActions[2].name);
expect(data.pages.menuActions[5].label).toEqual('contenttypes.content.push_publish');
expect(data.pages.menuActions[6].label).toEqual('contenttypes.content.add_to_bundle');
expect(data.pages.actionMenuDomId).toEqual('test1');
});

expect(dotESContentService.get).toHaveBeenCalledWith({
itemsPerPage: 1,
offset: '0',
query: '+contentType:dotFavoritePage +deleted:false +working:true +owner:testId +DotFavoritePage.url_dotraw:/index1?&language_id=1&device_inode=',
sortField: 'dotFavoritePage.order',
sortOrder: ESOrderDirection.ASC
});
expect(dotWorkflowsActionsService.getByInode).toHaveBeenCalledWith(
favoritePagesInitialTestData[0].inode,
DotRenderMode.LISTING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ import {
PermissionsType,
UserPermissions
} from '@dotcms/dotcms-models';
import { generateDotFavoritePageUrl } from '@dotcms/utils';

import { DotFavoritePageComponent } from '../../dot-edit-page/components/dot-favorite-page/dot-favorite-page.component';
import { DotPagesCreatePageDialogComponent } from '../dot-pages-create-page-dialog/dot-pages-create-page-dialog.component';

export interface DotPagesState {
Expand Down Expand Up @@ -75,6 +77,7 @@ export interface DotPagesState {
}

const FAVORITE_PAGES_ES_QUERY = `+contentType:dotFavoritePage +deleted:false +working:true`;
export const FAVORITE_PAGE_LIMIT = 5;

@Injectable()
export class DotPageStore extends ComponentStore<DotPagesState> {
Expand Down Expand Up @@ -253,7 +256,7 @@ export class DotPageStore extends ComponentStore<DotPagesState> {
readonly getFavoritePages = this.effect((itemsPerPage$: Observable<number>) => {
return itemsPerPage$.pipe(
switchMap((itemsPerPage: number) =>
this.getFavoritePagesData(itemsPerPage).pipe(
this.getFavoritePagesData({ limit: itemsPerPage }).pipe(
tapResponse(
(items) => {
this.patchState({
Expand Down Expand Up @@ -433,27 +436,36 @@ export class DotPageStore extends ComponentStore<DotPagesState> {
(params$: Observable<{ item: DotCMSContentlet; actionMenuDomId: string }>) => {
return params$.pipe(
switchMap(({ item, actionMenuDomId }) => {
return this.getWorflowActionsFn(item).pipe(
take(1),
map((data: DotCMSPageWorkflowState) => {
return {
actions: this.getSelectActions(data.actions, data.page),
actionMenuDomId
};
return forkJoin({
workflowsData: this.getWorflowActionsFn(item),
dotFavorite: this.getFavoritePagesData({
limit: 1,
url:
item?.contentType === 'dotFavoritePage'
? item.url
: generateDotFavoritePageUrl({
pageURI: item.urlMap || item.url.split('?')[0],
languageId: item.languageId,
siteId: item.host
})
})
}).pipe(
take(1),
tapResponse(
({ workflowsData, dotFavorite }) => {
this.setMenuActions({
actions: this.getSelectActions(
workflowsData.actions,
workflowsData.page,
dotFavorite.jsonObjectView.contentlets[0]
),
actionMenuDomId
});
},
(error: HttpErrorResponse) => this.httpErrorManagerService.handle(error)
)
);
}),
tap(
({
actions,
actionMenuDomId
}: {
actions: MenuItem[];
actionMenuDomId: string;
}) => {
this.setMenuActions({ actions, actionMenuDomId });
}
)
})
);
}
);
Expand Down Expand Up @@ -559,7 +571,7 @@ export class DotPageStore extends ComponentStore<DotPagesState> {
identifier: string
) {
return isFavoritePage
? this.getFavoritePagesData(1, identifier)
? this.getFavoritePagesData({ limit: 1, identifier })
: this.getPagesData(0, sortOrderValue, '', identifier);
}

Expand All @@ -578,25 +590,69 @@ export class DotPageStore extends ComponentStore<DotPagesState> {
});
};

private getFavoritePagesData = (limit: number, identifier?: string) => {
const identifierQuery = identifier ? `+identifier:${identifier}` : '';
private getFavoritePagesData = (params: {
limit: number;
identifier?: string;
url?: string;
}) => {
const { limit, identifier, url } = params;

let extraQueryParams = '';
if (identifier) {
extraQueryParams = `+identifier:${identifier}`;
} else if (url) {
extraQueryParams = `+DotFavoritePage.url_dotraw:${url}`;
}

return this.dotCurrentUser.getCurrentUser().pipe(
switchMap(({ userId }) => {
return this.dotESContentService.get({
itemsPerPage: limit,
offset: '0',
query: `${FAVORITE_PAGES_ES_QUERY} +owner:${userId} ${identifierQuery}`,
query: `${FAVORITE_PAGES_ES_QUERY} +owner:${userId} ${extraQueryParams}`,
sortField: 'dotFavoritePage.order',
sortOrder: ESOrderDirection.ASC
});
})
);
};

private getSelectActions(actions: DotCMSWorkflowAction[], item: DotCMSContentlet): MenuItem[] {
private getSelectActions(
actions: DotCMSWorkflowAction[],
item: DotCMSContentlet,
favoritePage?: DotCMSContentlet
): MenuItem[] {
const selectItems: MenuItem[] = [];

// Adding DotFavorite actions
selectItems.push({
label: favoritePage
? this.dotMessageService.get('favoritePage.contextMenu.action.edit')
: this.dotMessageService.get('favoritePage.contextMenu.action.add'),
command: () => {
this.dialogService.open(DotFavoritePageComponent, {
header: this.dotMessageService.get('favoritePage.dialog.header'),
width: '80rem',
data: {
page: {
favoritePageUrl: generateDotFavoritePageUrl({
pageURI: item.urlMap || item.url,
languageId: item.languageId,
siteId: item.host
}),
favoritePage
},
onSave: () => {
this.getFavoritePages(FAVORITE_PAGE_LIMIT);
},
onDelete: () => {
this.getFavoritePages(FAVORITE_PAGE_LIMIT);
}
}
});
}
});

// Adding Edit & View actions
const { loggedUser, isEnterprise, environments } = this.get();

Expand Down Expand Up @@ -697,7 +753,7 @@ export class DotPageStore extends ComponentStore<DotPagesState> {
*/
setInitialStateData(initialFavoritePagesLimit: number): void {
forkJoin([
this.getFavoritePagesData(initialFavoritePagesLimit),
this.getFavoritePagesData({ limit: initialFavoritePagesLimit }),
this.dotCurrentUser.getCurrentUser(),
this.dotLanguagesService.get(),
this.dotLicenseService.isEnterprise(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import { DotEventsService, DotPageRenderService } from '@dotcms/data-access';
import { HttpCode, SiteService } from '@dotcms/dotcms-js';
import { ComponentStatus, DotCMSContentlet } from '@dotcms/dotcms-models';

import { DotPagesState, DotPageStore } from './dot-pages-store/dot-pages.store';

export const FAVORITE_PAGE_LIMIT = 5;
import {
DotPagesState,
DotPageStore,
FAVORITE_PAGE_LIMIT
} from './dot-pages-store/dot-pages.store';

export interface DotActionsMenuEventParams {
event: MouseEvent;
Expand Down
25 changes: 5 additions & 20 deletions core-web/apps/dotcms-ui/src/app/shared/dot-utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { DotPageRender, DotPageRenderState } from '@dotcms/dotcms-models';
import * as dotUtils from '@dotcms/utils/lib/dot-utils';
import { mockDotRenderedPage, mockUser } from '@dotcms/utils-testing';

describe('Dot Utils', () => {
it('should return anchor with the correct values', () => {
Expand All @@ -14,24 +12,11 @@ describe('Dot Utils', () => {
});

it('should return unique URL with host, language and device Ids', () => {
const mockRenderedPageState = new DotPageRenderState(
mockUser(),
new DotPageRender({
...mockDotRenderedPage(),
viewAs: {
...mockDotRenderedPage().viewAs,
device: {
identifier: 'abc123',
cssHeight: '800',
cssWidth: '1200',
name: 'custom',
inode: '123zxc'
}
}
})
);

const url = dotUtils.generateDotFavoritePageUrl(mockRenderedPageState);
const url = dotUtils.generateDotFavoritePageUrl({
languageId: 1,
pageURI: '/an/url/test',
deviceInode: '123zxc'
});

expect(url).toEqual('/an/url/test?&language_id=1&device_inode=123zxc');
});
Expand Down
19 changes: 11 additions & 8 deletions core-web/libs/utils/src/lib/dot-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { DotPageRenderParameters } from '@dotcms/dotcms-models';

/**
* Generate an anchor element with a Blob file to eventually be click to force a download
* This approach is needed because FF do not hear WS events while waiting for a request.
Expand All @@ -20,13 +18,18 @@ export function formatMessage(message: string, args: string[]): string {
}

// Generates an unique Url with host, language and device Ids
export function generateDotFavoritePageUrl(params: DotPageRenderParameters): string {
const { page, site, viewAs } = params;
export function generateDotFavoritePageUrl(params: {
languageId: number;
pageURI: string;
deviceInode?: string;
siteId?: string;
}): string {
const { deviceInode, languageId, pageURI, siteId } = params;

return (
`${page?.pageURI}?` +
(site?.identifier ? `host_id=${site?.identifier}` : '') +
`&language_id=${viewAs.language.id}` +
(viewAs.device?.inode ? `&device_inode=${viewAs.device?.inode}` : '&device_inode=')
`${pageURI}?` +
(siteId ? `host_id=${siteId}` : '') +
`&language_id=${languageId}` +
(deviceInode ? `&device_inode=${deviceInode}` : '&device_inode=')
);
}
Loading

0 comments on commit a44c4a3

Please sign in to comment.