Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cursor/plans/rxjs_7_migration_plan_c65e7afc.plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: RxJS 7 Migration Plan
overview: Comprehensive migration plan to clean up all deprecated RxJS 6 patterns remaining in the core-web codebase after upgrading to RxJS 7.8.2. Covers 6 categories of changes across ~120+ files.
todos: []
isProject: false
---

# RxJS 6
Comment thread
nicobytes marked this conversation as resolved.
Outdated
6 changes: 3 additions & 3 deletions core-web/apps/dotcdn/src/app/dotcdn.component.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { inject, Injectable } from '@angular/core';

import { SelectItem } from 'primeng/api';

import { mergeMap, switchMapTo, tap } from 'rxjs/operators';
import { mergeMap, switchMap, tap } from 'rxjs/operators';

import {
ChartData,
Expand Down Expand Up @@ -167,7 +167,7 @@ export class DotCDNStore extends ComponentStore<DotCDNState> {
);

return loading$.pipe(
switchMapTo(
switchMap(() =>
this.dotCdnService.purgeCache(urls).pipe(
tap(() => {
this.dispatchLoading({
Expand All @@ -188,7 +188,7 @@ export class DotCDNStore extends ComponentStore<DotCDNState> {
})
);

$loading.pipe(switchMapTo(this.dotCdnService.purgeCacheAll())).subscribe(() => {
$loading.pipe(switchMap(() => this.dotCdnService.purgeCacheAll())).subscribe(() => {
this.dispatchLoading({
loadingState: LoadingState.LOADED,
loader: Loader.PURGE_PULL_ZONE
Expand Down
20 changes: 6 additions & 14 deletions core-web/apps/dotcms-ui/src/app/api/services/dot-menu.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@ import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';

import {
defaultIfEmpty,
filter,
find,
map,
mergeMap,
pluck,
publishLast,
refCount
} from 'rxjs/operators';
import { defaultIfEmpty, filter, find, map, mergeMap, shareReplay } from 'rxjs/operators';

import { DotCMSResponse, DotMenu, DotMenuItem } from '@dotcms/dotcms-models';

Expand All @@ -33,7 +24,7 @@ export class DotMenuService {
getUrlById(id: string): Observable<string> {
return this.getMenuItems().pipe(
filter((res: DotMenuItem) => !res.angular && res.id === id),
pluck('url'),
map((res) => res?.url),
defaultIfEmpty('')
);
}
Expand Down Expand Up @@ -69,9 +60,10 @@ export class DotMenuService {
*/
loadMenu(force = false): Observable<DotMenu[]> {
if (!this.menu$ || force) {
this.menu$ = this.http
.get<DotCMSResponse<DotMenu>>(this.urlMenus)
.pipe(publishLast(), refCount(), pluck('entity'));
this.menu$ = this.http.get<DotCMSResponse<DotMenu>>(this.urlMenus).pipe(
Comment thread
nicobytes marked this conversation as resolved.
Outdated
shareReplay({ bufferSize: 1, refCount: true }),
map((x) => x?.entity)
);
}

return this.menu$;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('DynamicRouteInitializerService', () => {
});

it('should resolve to 0 on error', async () => {
(menuService.loadMenu as jest.Mock).mockReturnValue(throwError(new Error('fail')));
(menuService.loadMenu as jest.Mock).mockReturnValue(throwError(() => new Error('fail')));

const count = await service.initialize();

Expand Down
8 changes: 5 additions & 3 deletions core-web/apps/dotcms-ui/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ describe('AppComponent', () => {

it('should use default colors when configuration fails to load', () => {
const error = new Error('Failed to load configuration');
jest.spyOn(dotCmsConfigService, 'getConfig').mockReturnValue(throwError(error));
jest.spyOn(dotCmsConfigService, 'getConfig').mockReturnValue(throwError(() => error));

fixture.detectChanges();

Expand All @@ -178,7 +178,9 @@ describe('AppComponent', () => {

it('should handle configuration error gracefully (unauthenticated user)', () => {
const httpError = { status: 401, message: 'Unauthorized' };
jest.spyOn(dotCmsConfigService, 'getConfig').mockReturnValue(throwError(httpError));
jest.spyOn(dotCmsConfigService, 'getConfig').mockReturnValue(
throwError(() => httpError)
);

fixture.detectChanges();

Expand All @@ -199,7 +201,7 @@ describe('AppComponent', () => {

it('should always set colors even when configuration fails', () => {
jest.spyOn(dotCmsConfigService, 'getConfig').mockReturnValue(
throwError(new Error('Network error'))
throwError(() => new Error('Network error'))
);

// Mock querySelector to return null (edge case)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';

import { ButtonModule } from 'primeng/button';

import { pluck, take } from 'rxjs/operators';
import { map, take } from 'rxjs/operators';

import { DotAppsService, DotRouterService } from '@dotcms/data-access';
import { DotApp, DotAppsSaveData, DotAppsSecret } from '@dotcms/dotcms-models';
Expand Down Expand Up @@ -39,13 +39,18 @@ export class DotAppsConfigurationDetailComponent implements OnInit {
formValid = false;

ngOnInit() {
this.route.data.pipe(pluck('data'), take(1)).subscribe((app: DotApp) => {
this.apps = app;
this.formFields = this.getSecrets(app.sites[0].secrets);
this.dynamicVariables = this.transformSecretsToKeyValue(
this.getSecrets(app.sites[0].secrets, true)
);
});
this.route.data
.pipe(
map((x) => x?.data),
take(1)
)
.subscribe((app: DotApp) => {
this.apps = app;
this.formFields = this.getSecrets(app.sites[0].secrets);
this.dynamicVariables = this.transformSecretsToKeyValue(
this.getSecrets(app.sites[0].secrets, true)
);
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { LazyLoadEvent } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { InputTextModule } from 'primeng/inputtext';

import { debounceTime, pluck, take } from 'rxjs/operators';
import { debounceTime, map, take } from 'rxjs/operators';

import {
DotAlertConfirmService,
Expand Down Expand Up @@ -81,22 +81,27 @@ export class DotAppsConfigurationComponent implements OnInit, AfterViewInit {
});

ngOnInit() {
this.#route.data.pipe(pluck('data'), take(1)).subscribe((app: DotApp) => {
patchState(this.$state, {
app: {
...app,
sites: []
}
});
this.#route.data
.pipe(
map((x) => x?.data),
take(1)
)
.subscribe((app: DotApp) => {
patchState(this.$state, {
app: {
...app,
sites: []
}
});

// Initialize pagination after app data is available
this.paginationService.url = `v1/apps/${app.key}`;
this.paginationService.paginationPerPage = this.$paginationPerPage();
this.paginationService.sortField = 'name';
this.paginationService.setExtraParams('filter', '');
this.paginationService.sortOrder = 1;
this.loadData();
});
// Initialize pagination after app data is available
this.paginationService.url = `v1/apps/${app.key}`;
this.paginationService.paginationPerPage = this.$paginationPerPage();
this.paginationService.sortField = 'name';
this.paginationService.setExtraParams('filter', '');
this.paginationService.sortOrder = 1;
this.loadData();
});
}

ngAfterViewInit() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ describe('DotAppsImportExportDialogStore', () => {
it('should set error on import error', () => {
spectator.service.openImport();
dotAppsService.importConfiguration.mockReturnValue(
throwError(new Error('Network error'))
throwError(() => new Error('Network error'))
);

spectator.service.importConfiguration({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ActivatedRoute } from '@angular/router';

import { MenuItem } from 'primeng/api';

import { pluck, switchMap, take, tap } from 'rxjs/operators';
import { map, switchMap, take, tap } from 'rxjs/operators';

import {
DotAlertConfirmService,
Expand Down Expand Up @@ -79,7 +79,10 @@ export class DotContainerListStore extends ComponentStore<DotContainerListState>

this.paginatorService.setExtraParams('host', identifier);

return this.route.data.pipe(pluck('dotContainerListResolverData'), take(1));
return this.route.data.pipe(
map((x) => x?.dotContainerListResolverData),
take(1)
);
})
)
.subscribe(([isEnterprise, hasEnvironments]: [boolean, boolean]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';

import { TabsModule } from 'primeng/tabs';

import { pluck, take } from 'rxjs/operators';
import { map, take } from 'rxjs/operators';

import { DotRouterService } from '@dotcms/data-access';
import { DotContainerEntity } from '@dotcms/dotcms-models';
Expand Down Expand Up @@ -38,7 +38,10 @@ export class DotContainerCreateComponent implements OnInit {

ngOnInit() {
this.activatedRoute.data
.pipe(pluck('container'), take(1))
.pipe(
map((x) => x?.container),
take(1)
)
.subscribe((container: DotContainerEntity) => {
if (container?.container) this.containerId = container.container.identifier;
else this.dotRouterService.goToCreateContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { HttpErrorResponse } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { catchError, filter, pluck, switchMap, take, tap } from 'rxjs/operators';
import { catchError, filter, map, switchMap, take, tap } from 'rxjs/operators';

import {
DotContentTypeService,
Expand Down Expand Up @@ -61,7 +61,7 @@ export class DotContainerPropertiesStore extends ComponentStore<DotContainerProp
});
this.activatedRoute.data
.pipe(
pluck('container'),
map((x) => x?.container),
take(1),
filter((containerEntity) => !!containerEntity)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AsyncPipe } from '@angular/common';
import { Component, OnInit, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { pluck } from 'rxjs/operators';
import { map } from 'rxjs/operators';

import { DotNotLicenseComponent } from '@dotcms/ui';

Expand All @@ -22,6 +22,6 @@ export class DotFormBuilderComponent implements OnInit {
haveLicense$: Observable<boolean>;

ngOnInit() {
this.haveLicense$ = this.route.data.pipe(pluck('haveLicense'));
this.haveLicense$ = this.route.data.pipe(map((x) => x?.haveLicense));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ describe('DotPageStore', () => {

it('should load null Favorite Pages data when error on initial data fetch', () => {
const error500 = mockResponseView(500, '/test', null, { message: 'error' });
jest.spyOn(dotESContentService, 'get').mockReturnValue(throwError(error500));
jest.spyOn(dotESContentService, 'get').mockReturnValue(throwError(() => error500));
// Mock sessionStorage.getItem
(sessionStorage.getItem as jest.Mock).mockReturnValue(null);

Expand Down Expand Up @@ -557,7 +557,7 @@ describe('DotPageStore', () => {

it('should handle error when get Pages value fails', () => {
const error500 = mockResponseView(500, '/test', null, { message: 'error' });
jest.spyOn(dotESContentService, 'get').mockReturnValue(throwError(error500));
jest.spyOn(dotESContentService, 'get').mockReturnValue(throwError(() => error500));
dotPageStore.getPages({ offset: 0, sortField: 'title', sortOrder: 1 });

dotPageStore.state$.subscribe((data) => {
Expand Down Expand Up @@ -854,7 +854,9 @@ describe('DotPageStore', () => {
jest.spyOn(dotPageWorkflowsActionsService, 'getByUrl').mockReturnValue(
of({ actions, page })
);
jest.spyOn(dotWorkflowActionsFireService, 'fireTo').mockReturnValue(throwError(error));
jest.spyOn(dotWorkflowActionsFireService, 'fireTo').mockReturnValue(
throwError(() => error)
);

dotPageStore.showActionsMenu({ item, actionMenuDomId: 'test1' });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,9 @@ describe('DotPageActionsService', () => {

it('should handle delete favorite error', fakeAsync(() => {
const error = new Error('Delete error');
mockWorkflowActionsFireService.deleteContentlet.mockReturnValue(throwError(error));
mockWorkflowActionsFireService.deleteContentlet.mockReturnValue(
throwError(() => error)
);

spectator.service.getItems(MOCK_FAVORITE_PAGE).subscribe((items) => {
const deleteAction = items.find((item) =>
Expand Down Expand Up @@ -552,7 +554,7 @@ describe('DotPageActionsService', () => {

it('should handle workflow action error', fakeAsync(() => {
const error = new Error('Workflow error');
mockWorkflowActionsFireService.fireTo.mockReturnValue(throwError(error));
mockWorkflowActionsFireService.fireTo.mockReturnValue(throwError(() => error));
mockActionsService.getByInode.mockReturnValue(of([MOCK_WORKFLOW_ACTION_NO_INPUTS]));

spectator.service.getItems(MOCK_HTMLPAGE_CONTENTLET).subscribe((items) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe('DotCMSPagesStore', () => {

it('should set status=error and call httpErrorManagerService.handle(error) when request fails', () => {
const error = new Error('Pages failed');
dotPageListService.getPages.mockReturnValueOnce(throwError(error));
dotPageListService.getPages.mockReturnValueOnce(throwError(() => error));

store.getPages({ search: 'x' });

Expand Down Expand Up @@ -296,7 +296,7 @@ describe('DotCMSPagesStore', () => {
store.getPages();

const error = new Error('Single page failed');
dotPageListService.getSinglePage.mockReturnValueOnce(throwError(error));
dotPageListService.getSinglePage.mockReturnValueOnce(throwError(() => error));

store.updatePageNode('page-2');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('withFavorites', () => {

it('getFavoritePages() should call httpErrorManagerService.handle(error) and set favoriteState=error when request fails', () => {
const error = new Error('Favorites failed');
dotPageListService.getFavoritePages.mockReturnValueOnce(throwError(error));
dotPageListService.getFavoritePages.mockReturnValueOnce(throwError(() => error));

store.getFavoritePages();

Expand Down Expand Up @@ -202,7 +202,7 @@ describe('withFavorites', () => {
patchState(store, { favoritePages: current, favoriteState: 'loaded' });

const error = new Error('Single page failed');
dotPageListService.getSinglePage.mockReturnValueOnce(throwError(error));
dotPageListService.getSinglePage.mockReturnValueOnce(throwError(() => error));

store.updateFavoritePageNode('page-2');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ describe('DotTemplateThumbnailFieldComponent', () => {
jest.spyOn(
dotWorkflowActionsFireService,
'publishContentletAndWaitForIndex'
).mockReturnValue(throwError({}));
).mockReturnValue(throwError(() => ({})));
jest.spyOn(dotTempFileUploadService, 'upload').mockReturnValue(
of([
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class DotTemplateThumbnailFieldComponent implements ControlValueAccessor
.pipe(
switchMap(([{ id, image }]: DotCMSTempFile[]) => {
if (!image) {
return throwError(
return throwError(() =>
this.dotMessageService.get(
'templates.properties.form.thumbnail.error.invalid.url'
)
Expand Down
Loading
Loading