Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(edit-content): #27289 Allow user to enable a new edit mode from the content types #27477

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DotContentletEditorService } from '@components/dot-contentlet-editor/se
import { dotEventSocketURLFactory, MockDotUiColorsService } from '@dotcms/app/test/dot-test-bed';
import {
DotAlertConfirmService,
DotContentTypeService,
DotCurrentUserService,
DotEventsService,
DotGenerateSecurePasswordService,
Expand Down Expand Up @@ -42,7 +43,7 @@ import {
StringUtils,
UserModel
} from '@dotcms/dotcms-js';
import { FeaturedFlags } from '@dotcms/dotcms-models';
import { DotCMSContentType, FeaturedFlags } from '@dotcms/dotcms-models';
import { DotLoadingIndicatorService } from '@dotcms/utils';
import {
CoreWebServiceMock,
Expand All @@ -67,6 +68,7 @@ describe('DotCustomEventHandlerService', () => {
let dotWorkflowEventHandlerService: DotWorkflowEventHandlerService;
let dotEventsService: DotEventsService;
let dotLicenseService: DotLicenseService;
let dotContentTypeService: DotContentTypeService;
let router: Router;

const createFeatureFlagResponse = (
Expand Down Expand Up @@ -119,7 +121,8 @@ describe('DotCustomEventHandlerService', () => {
LoginService,
DotLicenseService,
{ provide: DotPropertiesService, useValue: dotPropertiesMock },
Router
Router,
DotContentTypeService
],
imports: [RouterTestingModule, HttpClientTestingModule]
});
Expand All @@ -135,9 +138,15 @@ describe('DotCustomEventHandlerService', () => {
dotWorkflowEventHandlerService = TestBed.inject(DotWorkflowEventHandlerService);
dotEventsService = TestBed.inject(DotEventsService);
dotLicenseService = TestBed.inject(DotLicenseService);
dotContentTypeService = TestBed.inject(DotContentTypeService);
router = TestBed.inject(Router);
};

const metadata = {};
const metadata2 = {};
metadata[FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED] = true;
metadata2[FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED] = false;

beforeEach(() => {
setup({
getKeys: () => of(createFeatureFlagResponse())
Expand Down Expand Up @@ -390,6 +399,9 @@ describe('DotCustomEventHandlerService', () => {
});

spyOn(router, 'navigate');
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata } as DotCMSContentType)
);
});

it('should create a contentlet', () => {
Expand Down Expand Up @@ -449,6 +461,9 @@ describe('DotCustomEventHandlerService', () => {
});

it('should create a contentlet', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata } as DotCMSContentType)
);
spyOn(dotContentletEditorService, 'create');

service.handle(
Expand All @@ -464,6 +479,9 @@ describe('DotCustomEventHandlerService', () => {
});

it('should edit a a workflow task', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata } as DotCMSContentType)
);
service.handle(
new CustomEvent('ng-event', {
detail: {
Expand All @@ -480,6 +498,9 @@ describe('DotCustomEventHandlerService', () => {
});

it('should edit a contentlet', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata } as DotCMSContentType)
);
service.handle(
new CustomEvent('ng-event', {
detail: {
Expand All @@ -495,6 +516,9 @@ describe('DotCustomEventHandlerService', () => {
});

it('should not create a contentlet', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata: metadata2 } as DotCMSContentType)
);
spyOn(dotContentletEditorService, 'create');

service.handle(
Expand All @@ -510,6 +534,10 @@ describe('DotCustomEventHandlerService', () => {
});

it('should not edit a a workflow task', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata: metadata2 } as DotCMSContentType)
);

service.handle(
new CustomEvent('ng-event', {
detail: {
Expand All @@ -526,6 +554,9 @@ describe('DotCustomEventHandlerService', () => {
});

it('should not edit a contentlet', () => {
spyOn(dotContentTypeService, 'getContentType').and.returnValue(
of({ metadata: metadata2 } as DotCMSContentType)
);
service.handle(
new CustomEvent('ng-event', {
detail: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

import { take } from 'rxjs/operators';

import { DotContentCompareEvent } from '@components/dot-content-compare/dot-content-compare.component';
import { DotCMSEditPageEvent } from '@components/dot-contentlet-editor/components/dot-contentlet-wrapper/dot-contentlet-wrapper.component';
import { DotContentletEditorService } from '@components/dot-contentlet-editor/services/dot-contentlet-editor.service';
import {
DotContentTypeService,
DotEventsService,
DotGenerateSecurePasswordService,
DotLicenseService,
Expand All @@ -14,7 +17,7 @@ import {
DotWorkflowEventHandlerService
} from '@dotcms/data-access';
import { DotPushPublishDialogService, DotUiColors } from '@dotcms/dotcms-js';
import { FeaturedFlags } from '@dotcms/dotcms-models';
import { DotCMSContentType, FeaturedFlags } from '@dotcms/dotcms-models';
import { DotLoadingIndicatorService } from '@dotcms/utils';
import { DotDownloadBundleDialogService } from '@services/dot-download-bundle-dialog/dot-download-bundle-dialog.service';
import { DotNavLogoService } from '@services/dot-nav-logo/dot-nav-logo.service';
Expand All @@ -32,8 +35,6 @@ export const COMPARE_CUSTOM_EVENT = 'compare-contentlet';
export class DotCustomEventHandlerService {
private handlers: Record<string, ($event: CustomEvent) => void>;

private contentTypesFeatureFlag: string[];

constructor(
private dotLoadingIndicatorService: DotLoadingIndicatorService,
private dotRouterService: DotRouterService,
Expand All @@ -48,22 +49,14 @@ export class DotCustomEventHandlerService {
private dotEventsService: DotEventsService,
private dotLicenseService: DotLicenseService,
private router: Router,
private dotPropertiesService: DotPropertiesService
private dotPropertiesService: DotPropertiesService,
private dotContentTypeService: DotContentTypeService
) {
this.dotPropertiesService
.getKeys([
FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED,
FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_CONTENT_TYPE
])
.getKeys([FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED])
.subscribe((response) => {
const contentEditorFeatureFlag =
response[FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED] === 'true';
const contentTypeFeatureFlag =
response[FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_CONTENT_TYPE];

this.contentTypesFeatureFlag = contentTypeFeatureFlag
.split(',')
.map((item) => item.trim());

if (!this.handlers) {
this.handlers = {
Expand Down Expand Up @@ -119,11 +112,16 @@ export class DotCustomEventHandlerService {
}

private createContentlet($event: CustomEvent): void {
if (this.shouldRedirectToOldContentEditor($event.detail.data.contentType)) {
return this.createContentletLegacy($event);
}
this.dotContentTypeService
.getContentType($event.detail.data.contentType)
.pipe(take(1))
.subscribe((contentType) => {
if (this.shouldRedirectToOldContentEditor(contentType)) {
return this.createContentletLegacy($event);
}

this.router.navigate([`content/new/${$event.detail.data.contentType}`]);
this.router.navigate([`content/new/${$event.detail.data.contentType}`]);
});
}

private goToEditPage($event: CustomEvent<DotCMSEditPageEvent>): void {
Expand All @@ -140,23 +138,33 @@ export class DotCustomEventHandlerService {
}

private editContentlet($event: CustomEvent): void {
if (this.shouldRedirectToOldContentEditor($event.detail.data.contentType)) {
return this.editContentletLegacy($event);
}
this.dotContentTypeService
.getContentType($event.detail.data.contentType)
.pipe(take(1))
.subscribe((contentType) => {
if (this.shouldRedirectToOldContentEditor(contentType)) {
return this.editContentletLegacy($event);
}

this.router.navigate([`content/${$event.detail.data.inode}`]);
this.router.navigate([`content/${$event.detail.data.inode}`]);
});
}

private editTaskLegacy($event: CustomEvent): void {
this.dotRouterService.goToEditTask($event.detail.data.inode);
}

private editTask($event: CustomEvent): void {
if (this.shouldRedirectToOldContentEditor($event.detail.data.contentType)) {
return this.editTaskLegacy($event);
}
this.dotContentTypeService
.getContentType($event.detail.data.contentType)
.pipe(take(1))
.subscribe((contentType) => {
if (this.shouldRedirectToOldContentEditor(contentType)) {
return this.editTaskLegacy($event);
}

this.router.navigate([`content/${$event.detail.data.inode}`]);
this.router.navigate([`content/${$event.detail.data.inode}`]);
});
}

private setPersonalization($event: CustomEvent): void {
Expand Down Expand Up @@ -199,17 +207,14 @@ export class DotCustomEventHandlerService {
}

/**
* Check if the content type is in the feature flag list
* Check if the content type have the feature flag in the metadata.
*
* @private
* @param {string} contentType
* @param {DotCMSContentType} contentType
* @return {*} {boolean}
* @memberof DotCustomEventHandlerService
*/
private shouldRedirectToOldContentEditor(contentType: string): boolean {
return (
!this.contentTypesFeatureFlag.includes('*') &&
this.contentTypesFeatureFlag.indexOf(contentType) === -1
);
private shouldRedirectToOldContentEditor(contentType: DotCMSContentType): boolean {
return !contentType?.metadata?.[FeaturedFlags.FEATURE_FLAG_CONTENT_EDITOR2_ENABLED];
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { mockProvider } from '@ngneat/spectator';
import { of } from 'rxjs';

import { HttpClientTestingModule } from '@angular/common/http/testing';
Expand Down Expand Up @@ -30,6 +31,7 @@ import { dotEventSocketURLFactory, MockDotUiColorsService } from '@dotcms/app/te
import {
DotAlertConfirmService,
DotContentletLockerService,
DotContentTypeService,
DotEditPageService,
DotESContentService,
DotEventsService,
Expand Down Expand Up @@ -299,6 +301,7 @@ describe('DotEditContentComponent', () => {
DotExperimentsService,
DotSeoMetaTagsService,
DotSeoMetaTagsUtilService,
mockProvider(DotContentTypeService),
{
provide: LoginService,
useClass: LoginServiceMock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { DotUiColorsService } from '@dotcms/app/api/services/dot-ui-colors/dot-u
import { dotEventSocketURLFactory, MockDotUiColorsService } from '@dotcms/app/test/dot-test-bed';
import {
DotAlertConfirmService,
DotContentTypeService,
DotCurrentUserService,
DotEventsService,
DotGenerateSecurePasswordService,
Expand Down Expand Up @@ -189,7 +190,8 @@ describe('DotEditPageMainComponent', () => {
LoginService,
DotLicenseService,
Title,
mockProvider(DotSessionStorageService)
mockProvider(DotSessionStorageService),
mockProvider(DotContentTypeService)
]
});
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { mockProvider } from '@ngneat/spectator';

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { DebugElement, Injectable } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
Expand All @@ -16,6 +18,7 @@ import { DotDownloadBundleDialogService } from '@dotcms/app/api/services/dot-dow
import { DotUiColorsService } from '@dotcms/app/api/services/dot-ui-colors/dot-ui-colors.service';
import {
DotAlertConfirmService,
DotContentTypeService,
DotCurrentUserService,
DotEventsService,
DotGenerateSecurePasswordService,
Expand Down Expand Up @@ -119,7 +122,8 @@ describe('DotContentletsComponent', () => {
DotIframeService,
LoginService,
DotGenerateSecurePasswordService,
DotDownloadBundleDialogService
DotDownloadBundleDialogService,
mockProvider(DotContentTypeService)
]
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { mockProvider } from '@ngneat/spectator';

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
Expand All @@ -15,6 +17,7 @@ import { DotUiColorsService } from '@dotcms/app/api/services/dot-ui-colors/dot-u
import { dotEventSocketURLFactory, MockDotUiColorsService } from '@dotcms/app/test/dot-test-bed';
import {
DotAlertConfirmService,
DotContentTypeService,
DotCurrentUserService,
DotEventsService,
DotGenerateSecurePasswordService,
Expand Down Expand Up @@ -86,7 +89,8 @@ describe('DotPortletDetailComponent', () => {
DotGlobalMessageService,
DotEventsService,
DotGenerateSecurePasswordService,
DotLicenseService
DotLicenseService,
mockProvider(DotContentTypeService)
],
declarations: [DotPortletDetailComponent],
imports: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { mockProvider } from '@ngneat/spectator';

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { DebugElement, Injectable } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
Expand All @@ -19,6 +21,7 @@ import { DotUiColorsService } from '@dotcms/app/api/services/dot-ui-colors/dot-u
import { dotEventSocketURLFactory, MockDotUiColorsService } from '@dotcms/app/test/dot-test-bed';
import {
DotAlertConfirmService,
DotContentTypeService,
DotCurrentUserService,
DotEventsService,
DotGenerateSecurePasswordService,
Expand Down Expand Up @@ -136,7 +139,8 @@ describe('DotWorkflowTaskComponent', () => {
DotWorkflowActionsFireService,
DotGlobalMessageService,
DotGenerateSecurePasswordService,
DotEventsService
DotEventsService,
mockProvider(DotContentTypeService)
]
});

Expand Down