Skip to content

Commit

Permalink
Filter system host when is isRequired (#28931)
Browse files Browse the repository at this point in the history
If a host/folder field is marked as required, then we do not allow/show
SYSTEM_HOST

### Proposed Changes
* Add isRequired attr to enable filter

### Checklist
- [x] Tests
- [x] Translations
- [x] Security Implications Contemplated (add notes if applicable)
  • Loading branch information
nicobytes authored and oidacra committed Jun 26, 2024
1 parent cbf469a commit bacd61d
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
effect,
inject
} from '@angular/core';
import { ControlContainer, FormControl, ReactiveFormsModule } from '@angular/forms';
import { ControlContainer, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';

import { DotCMSContentTypeField } from '@dotcms/dotcms-models';

Expand Down Expand Up @@ -64,7 +64,11 @@ export class DotEditContentHostFolderFieldComponent implements OnInit {

ngOnInit() {
const currentPath = this.formControl.value;
this.store.loadSites(currentPath);
const isRequired = this.formControl.hasValidator(Validators.required);
this.store.loadSites({
path: currentPath,
isRequired
});
}

get formControl(): FormControl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type HostFolderFiledState = {
error: string | null;
};

const initialState: HostFolderFiledState = {
export const initialState: HostFolderFiledState = {
nodeSelected: null,
nodeExpaned: null,
tree: [],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { SpyObject, createSpyObject } from '@ngneat/spectator/jest';
import { signalStore, withState } from '@ngrx/signals';
import { of } from 'rxjs';

import { TestBed } from '@angular/core/testing';

import { loadSites, SYSTEM_HOST_NAME } from './loadSites';

import { DotEditContentService } from '../../../../services/dot-edit-content.service';
import { TREE_SELECT_SITES_MOCK } from '../../../../utils/mocks';
import { initialState } from '../host-folder-field.store';

describe('rxMethod: loadSites', () => {
let Store = signalStore(withState(initialState));
let store: InstanceType<typeof Store>;
let service: SpyObject<DotEditContentService>;

beforeEach(() => {
service = createSpyObject(DotEditContentService);
Store = signalStore(withState(initialState));
store = new Store();
});

it('should include System Host when isRequired is false.', () => {
service.getSitesTreePath.mockReturnValue(of(TREE_SELECT_SITES_MOCK));
const rxMethod = TestBed.runInInjectionContext(() => loadSites(store, service));
const props = {
path: '',
isRequired: false
};
rxMethod(props);
const hasSystemHost = store.tree().some((item) => item.label === SYSTEM_HOST_NAME);
expect(hasSystemHost).toBe(true);
});

it('should not include System Host when isRequired is true.', () => {
service.getSitesTreePath.mockReturnValue(of(TREE_SELECT_SITES_MOCK));
const rxMethod = TestBed.runInInjectionContext(() => loadSites(store, service));
const props = {
path: '',
isRequired: true
};
rxMethod(props);
const hasSystemHost = store.tree().some((item) => item.label === SYSTEM_HOST_NAME);
expect(hasSystemHost).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,28 @@ import type { HostFolderFiledState } from './../host-folder-field.store';

const PEER_PAGE_LIMIT = 7000;

type Props = {
path: string | null;
isRequired: boolean;
};

export const SYSTEM_HOST_NAME = 'System Host';

export const loadSites = (store, dotEditContentService: DotEditContentService) => {
return rxMethod<string | null>(
return rxMethod<Props>(
pipe(
tap(() => patchState(store, { status: 'LOADING' })),
switchMap((path) => {
switchMap(({ path, isRequired }) => {
return dotEditContentService
.getSitesTreePath({ perPage: PEER_PAGE_LIMIT, filter: '*' })
.pipe(
map((sites) => {
if (isRequired) {
return sites.filter((site) => site.label !== SYSTEM_HOST_NAME);
}

return sites;
}),
tapResponse({
next: (sites) => patchState(store, { tree: sites }),
error: () => patchState(store, { status: 'FAILED', error: '' }),
Expand Down
11 changes: 11 additions & 0 deletions core-web/libs/edit-content/src/lib/utils/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,17 @@ export const TREE_SELECT_SITES_MOCK: TreeNodeItem[] = [
},
expandedIcon: 'pi pi-folder-open',
collapsedIcon: 'pi pi-folder'
},
{
key: 'System Host',
label: 'System Host',
data: {
hostname: 'System Host',
path: '',
type: 'site'
},
expandedIcon: 'pi pi-folder-open',
collapsedIcon: 'pi pi-folder'
}
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

<div *ngIf="!isContainerEmpty" [ngStyle]="styles.actions" class="actions" data-testId="actions">
@if (contentletArea.payload.vtlFiles?.length) {
<p-menu [model]="vtlFiles" [popup]="true" #menuVTL appendTo="body" />
<p-button
(click)="menuVTL.toggle($event)"
data-testId="edit-vtl-button"
styleClass="p-button-rounded p-button-raised"
icon="pi pi-code" />
<p-menu [model]="vtlFiles" [popup]="true" #menuVTL appendTo="body" />
<p-button
(click)="menuVTL.toggle($event)"
data-testId="edit-vtl-button"
styleClass="p-button-rounded p-button-raised"
icon="pi pi-code" />
}

<p-button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,22 @@
[variantId]="es.editorData.variantId"
data-testId="palette" />

@if ( es.editorData.canEditVariant && (es.editorData.mode === editorMode.EDIT ||
es.editorData.mode === editorMode.EDIT_VARIANT) ) {
<dot-edit-ema-dialog
(action)="onCustomEvent($event)"
(reloadFromDialog)="reloadFromDialog()"
#dialog
data-testId="ema-dialog"></dot-edit-ema-dialog>
<p-confirmDialog
[style]="{
width: '400px'
}"
rejectIcon="hidden"
acceptIcon="hidden"
rejectButtonStyleClass="p-button-outlined"
data-testId="confirm-dialog"></p-confirmDialog>
@if (
es.editorData.canEditVariant &&
(es.editorData.mode === editorMode.EDIT || es.editorData.mode === editorMode.EDIT_VARIANT)
) {
<dot-edit-ema-dialog
(action)="onCustomEvent($event)"
(reloadFromDialog)="reloadFromDialog()"
#dialog
data-testId="ema-dialog"></dot-edit-ema-dialog>
<p-confirmDialog
[style]="{
width: '400px'
}"
rejectIcon="hidden"
acceptIcon="hidden"
rejectButtonStyleClass="p-button-outlined"
data-testId="confirm-dialog"></p-confirmDialog>
}
</ng-container>

0 comments on commit bacd61d

Please sign in to comment.