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): Add settings to Binary Field content type #27455

Merged
merged 27 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3adde7e
create binary settings component
zJaaal Jan 24, 2024
5e2bae4
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Jan 26, 2024
91be976
make the formulary save and delete
zJaaal Jan 26, 2024
99c4e8a
add variables in settings to blacklist
zJaaal Jan 26, 2024
d6facdb
apply settings to binary field
zJaaal Jan 26, 2024
a59b6e7
Update dot-edit-content-binary-field.component.scss
zJaaal Jan 26, 2024
b9c33b9
change divider color
zJaaal Jan 26, 2024
88726a0
add test cases
zJaaal Jan 26, 2024
5aaa5b4
clean tests
zJaaal Jan 26, 2024
3d7836d
add test cases
zJaaal Jan 26, 2024
374ca7f
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Jan 26, 2024
23d1ce0
add translations
zJaaal Jan 26, 2024
8886f32
fix sonarq
zJaaal Jan 26, 2024
885d3be
add test cases
zJaaal Jan 26, 2024
126ebae
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Jan 26, 2024
1330227
add test cases
zJaaal Jan 26, 2024
7f17c84
Merge branch '26906-edit-content-add-settings-to-binary-field' of htt…
zJaaal Jan 26, 2024
bfc43f3
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Jan 28, 2024
353a55b
Refactor, make PR suggestions
KevinDavilaDotCMS Feb 1, 2024
722fda0
Merged with master. Updated FIELD_VARIABLES on save.
KevinDavilaDotCMS Feb 1, 2024
8ead604
Fixed behavior when dont have value
KevinDavilaDotCMS Feb 1, 2024
0d57259
Fixed getter, missed on merge
KevinDavilaDotCMS Feb 2, 2024
156e728
Removed unnecesary code
KevinDavilaDotCMS Feb 2, 2024
5f8f279
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Feb 5, 2024
44abb31
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Feb 5, 2024
95f3c1b
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Feb 6, 2024
e77b3c1
Merge branch 'master' into 26906-edit-content-add-settings-to-binary-…
zJaaal Feb 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<form class="wrapper" [formGroup]="form">
<div class="field">
<label for="allowed-file-type">{{ 'binary-field.settings.allow.type' | dm }}</label>
<input
id="allowed-file-type"
[style]="{ width: '100%' }"
formControlName="accept"
placeholder="ex: images/*"
pInputText
data-testId="setting-accept" />
<small style="display: inline-block; margin-top: 0.5rem">
<a
href="https://www.dotcms.com/docs/latest/field-variables#BinaryField"
target="_blank"
rel="noopener"
>Link to documentation</a
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved
>
</small>
</div>
@for( option of systemOptions; track option.key ) {
<p-divider
[style]="{
margin: '1rem 0'
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved
}"></p-divider>
<div class="horizontal-field">
<p class="info" [innerHTML]="option.message | dm"></p>
<p-inputSwitch [formControlName]="option.key" data-testId="setting-switch"></p-inputSwitch>
</div>

}
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@use "variables" as *;

.wrapper {
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved
padding: $spacing-6;

.field {
padding: 0 $spacing-1;
}
}

.horizontal-field {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 $spacing-1;

.info {
margin: 0;
line-height: 140%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import { Spectator, SpyObject, byTestId, createComponentFactory } from '@ngneat/spectator';
import { of, throwError } from 'rxjs';

import { NgFor } from '@angular/common';
import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';

import { DividerModule } from 'primeng/divider';
import { InputSwitchModule } from 'primeng/inputswitch';
import { InputTextModule } from 'primeng/inputtext';

import { DotMessageService, DotHttpErrorManagerService } from '@dotcms/data-access';
import { DotMessagePipe } from '@dotcms/ui';
import { MockDotMessageService, mockFieldVariables } from '@dotcms/utils-testing';

import { DotBinarySettingsComponent } from './dot-binary-settings.component';

import { DotFieldVariablesService } from '../fields/dot-content-type-fields-variables/services/dot-field-variables.service';

const messageServiceMock = new MockDotMessageService({
'contenttypes.dropzone.action.save': 'Save',
'contenttypes.dropzone.action.cancel': 'Cancel'
});

const systemOptions = JSON.stringify({
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved
allowURLImport: false,
allowFileNameEdit: false,
allowCodeWrite: true
});

describe('DotBinarySettingsComponent', () => {
let spectator: Spectator<DotBinarySettingsComponent>;
let component: DotBinarySettingsComponent;
let dotFieldVariableService: SpyObject<DotFieldVariablesService>;
let dotHttpErrorManagerService: SpyObject<DotHttpErrorManagerService>;

const createComponent = createComponentFactory({
component: DotBinarySettingsComponent,
imports: [
NgFor,
FormsModule,
ReactiveFormsModule,
InputTextModule,
InputSwitchModule,
DividerModule,
DotMessagePipe
],
providers: [
FormBuilder,
{
provide: DotFieldVariablesService,
useValue: {
load: () =>
of([
{
clazz: 'com.dotcms.contenttype.model.field.ImmutableStoryBlockField',
fieldId: 'f965a51b-130a-435f-b646-41e07d685363',
id: '9671d2c3-793b-41af-a485-e2c5fcba5fb',
key: 'systemOptions',
value: systemOptions
},
{
clazz: 'com.dotcms.contenttype.model.field.ImmutableStoryBlockField',
fieldId: 'f965a51b-130a-435f-b646-41e07d685363',
id: '9671d2c3-793b-41af-a485-e2c5fcba5fb',
key: 'accept',
value: 'image/*'
}
]),
save: () => of([]),
delete: () => of([])
}
},
{
provide: DotMessageService,
useValue: messageServiceMock
},
{
provide: DotHttpErrorManagerService,
useValue: {
handle: () => of([])
}
}
]
});

beforeEach(async () => {
spectator = createComponent({});
dotFieldVariableService = spectator.inject(DotFieldVariablesService);
dotHttpErrorManagerService = spectator.inject(DotHttpErrorManagerService);

component = spectator.component;
});

it('should setup form values', async () => {
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved
expect(component.form.get('accept').value).toBe('image/*');
expect(component.form.get('allowURLImport').value).toBe(false);
expect(component.form.get('allowCodeWrite').value).toBe(true);
expect(component.form.get('allowFileNameEdit').value).toBe(false);
});

it('should emit changeControls when isVisible input is true', () => {
spyOn(component.changeControls, 'emit');

spectator.setInput('isVisible', true);

expect(component.changeControls.emit).toHaveBeenCalled();
});

it('should emit valid output on form change', () => {
spyOn(component.valid, 'emit');

component.form.get('accept').setValue('text/*');

expect(component.valid.emit).toHaveBeenCalled();
});
KevinDavilaDotCMS marked this conversation as resolved.
Show resolved Hide resolved

it('should save properties on saveSettings', () => {
spyOn(dotFieldVariableService, 'save').and.returnValue(of(mockFieldVariables[0]));
spyOn(component.save, 'emit');

component.saveSettings();

expect(dotFieldVariableService.save).toHaveBeenCalledTimes(2); // One for accept and one for systemOptions
expect(component.save.emit).toHaveBeenCalled();
expect(component.settingsMap['accept'].variable).toEqual(mockFieldVariables[0]);
});

it('should delete properties on saveSettings when is empty', () => {
spyOn(dotFieldVariableService, 'delete').and.returnValue(of(mockFieldVariables[0]));
spyOn(component.save, 'emit');

component.form.get('accept').setValue('');
component.saveSettings();

expect(dotFieldVariableService.delete).toHaveBeenCalled();
expect(component.save.emit).toHaveBeenCalled();
expect(component.settingsMap['accept'].variable).toEqual(mockFieldVariables[0]);
});

it('should handler error if save properties failed', () => {
spyOn(dotFieldVariableService, 'save').and.returnValue(throwError({}));
spyOn(dotHttpErrorManagerService, 'handle').and.returnValue(of());
spyOn(component.save, 'emit');

component.saveSettings();

expect(dotHttpErrorManagerService.handle).toHaveBeenCalledTimes(1);
expect(component.save.emit).not.toHaveBeenCalled();
});
it('should not call save or delete when is empty and not previous variable exist', () => {
spyOn(dotFieldVariableService, 'load');
spyOn(dotFieldVariableService, 'delete').and.returnValue(of([]));
spyOn(dotFieldVariableService, 'save').and.returnValue(of([]));

// Couldn't find a way to force a no variable from load method
component.settingsMap = {
accept: {
key: 'accept',
variable: null
},
systemOptions: {
key: 'systemOptions',
variable: null
}
};

component.form.get('accept').setValue('');
component.saveSettings();

expect(dotFieldVariableService.delete).not.toHaveBeenCalled();
expect(dotFieldVariableService.save).not.toHaveBeenCalledTimes(2); // One for accept and one for systemOptions, accept should not call save or delete
});

it('should have 3 switches with the corresponding control name', () => {
const switches = spectator.queryAll(byTestId('setting-switch'));

expect(switches.length).toBe(3);
expect(
switches.find((s) => s.getAttribute('ng-reflect-name') === 'allowURLImport')
).not.toBeNull();
expect(
switches.find((s) => s.getAttribute('ng-reflect-name') === 'allowCodeWrite')
).not.toBeNull();
expect(
switches.find((s) => s.getAttribute('ng-reflect-name') === 'allowFileNameEdit')
).not.toBeNull();
});

it('should have 1 input with the control name accept', () => {
const [acceptInput] = spectator.queryAll(byTestId('setting-accept'));

expect(acceptInput).not.toBeNull();

expect(acceptInput.getAttribute('ng-reflect-name')).toBe('accept');
});
});