Skip to content

Commit 4ef691a

Browse files
authored
fix (edit content): dotCMS#31940 Activity Feed: error should not show (dotCMS#32162)
### Proposed Changes * Adjust validation messages in the Activity feed. * Styles adjustments in the binary field.
1 parent a3cfc1a commit 4ef691a

File tree

4 files changed

+128
-18
lines changed

4 files changed

+128
-18
lines changed

core-web/libs/edit-content/src/lib/components/dot-edit-content-sidebar/components/dot-edit-content-sidebar-activities/dot-edit-content-sidebar-activities.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
<button
7070
pButton
7171
type="button"
72-
[disabled]="!form.dirty || $isSaving()"
72+
[disabled]="!form.dirty || !commentControl.value?.trim() || $isSaving()"
7373
class="p-button-sm p-button-secondary activities__clear"
7474
data-testid="activities-clear"
7575
(click)="clearComment()">
@@ -79,6 +79,7 @@
7979
pButton
8080
type="submit"
8181
[loading]="$isSaving()"
82+
[disabled]="$isSaving()"
8283
class="p-button-sm p-button-primary activities__submit"
8384
data-testid="activities-submit">
8485
{{ 'edit.content.sidebar.activities.send' | dm }}

core-web/libs/edit-content/src/lib/components/dot-edit-content-sidebar/components/dot-edit-content-sidebar-activities/dot-edit-content-sidebar-activities.component.spec.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,27 @@ describe('DotEditContentSidebarActivitiesComponent', () => {
309309
expect(spectator.component.form.get('comment').untouched).toBe(true);
310310
});
311311

312+
it('should disable clear button when comment field is empty', () => {
313+
// Initially check that it's disabled
314+
let clearButton = spectator.query(byTestId('activities-clear'));
315+
expect(clearButton).toBeDisabled();
316+
317+
// Type something to enable it
318+
const commentInput = spectator.query(byTestId('activities-input'));
319+
spectator.typeInElement('Test comment', commentInput);
320+
spectator.detectChanges();
321+
322+
clearButton = spectator.query(byTestId('activities-clear'));
323+
expect(clearButton).not.toBeDisabled();
324+
325+
// Delete the content to see if it gets disabled again
326+
spectator.typeInElement('', commentInput);
327+
spectator.detectChanges();
328+
329+
clearButton = spectator.query(byTestId('activities-clear'));
330+
expect(clearButton).toBeDisabled();
331+
});
332+
312333
it('should reset form state when clearComment is called', () => {
313334
const commentInput = spectator.query(byTestId('activities-input'));
314335
spectator.typeInElement('Test comment', commentInput);
@@ -322,6 +343,65 @@ describe('DotEditContentSidebarActivitiesComponent', () => {
322343
expect(spectator.component.form.get('comment').untouched).toBe(true);
323344
expect(spectator.component.form.get('comment').value).toBe(null);
324345
});
346+
347+
// New test cases for custom validation behavior
348+
it('should not show validation errors when input field is empty before submit', () => {
349+
const commentInput = spectator.query(byTestId('activities-input'));
350+
351+
// Type something and then delete it
352+
spectator.typeInElement('Test', commentInput);
353+
spectator.detectChanges();
354+
355+
spectator.typeInElement('', commentInput);
356+
spectator.detectChanges();
357+
358+
// Check that there are no errors shown before submission
359+
const control = spectator.component.form.get('comment');
360+
expect(control.valid).toBe(true);
361+
expect(control.errors).toBeFalsy();
362+
expect(commentInput).not.toHaveClass('ng-invalid');
363+
});
364+
365+
it('should apply required validation only when form is submitted with empty value', () => {
366+
const commentInput = spectator.query(byTestId('activities-input'));
367+
const form = spectator.query(byTestId('activities-form'));
368+
369+
// Initially no errors
370+
expect(spectator.component.form.get('comment').errors).toBeFalsy();
371+
372+
// Submit empty form
373+
spectator.dispatchFakeEvent(form, 'submit');
374+
spectator.detectChanges();
375+
376+
// Now should have required error
377+
const control = spectator.component.form.get('comment');
378+
expect(control.errors).toBeTruthy();
379+
expect(control.errors['required']).toBeTruthy();
380+
expect(commentInput).toHaveClass('ng-invalid');
381+
expect(commentInput).toHaveClass('ng-touched');
382+
});
383+
384+
it('should disable submit button while saving', () => {
385+
// Set saving state
386+
spectator.setInput('status', ComponentStatus.SAVING);
387+
spectator.detectChanges();
388+
389+
const submitButton = spectator.query(byTestId('activities-submit'));
390+
391+
expect(submitButton).toBeDisabled();
392+
expect(spectator.component['$isSaving']()).toBe(true);
393+
});
394+
395+
it('should not disable submit button when not saving', () => {
396+
// Set loaded state
397+
spectator.setInput('status', ComponentStatus.LOADED);
398+
spectator.detectChanges();
399+
400+
const submitButton = spectator.query(byTestId('activities-submit'));
401+
402+
expect(submitButton).not.toBeDisabled();
403+
expect(spectator.component['$isSaving']()).toBe(false);
404+
});
325405
});
326406

327407
describe('Computed Properties', () => {

core-web/libs/edit-content/src/lib/components/dot-edit-content-sidebar/components/dot-edit-content-sidebar-activities/dot-edit-content-sidebar-activities.component.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ import {
1010
output,
1111
viewChildren
1212
} from '@angular/core';
13-
import {
14-
FormBuilder,
15-
FormControl,
16-
FormGroup,
17-
ReactiveFormsModule,
18-
Validators
19-
} from '@angular/forms';
13+
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
2014

2115
import { AvatarModule } from 'primeng/avatar';
2216
import { ButtonModule } from 'primeng/button';
@@ -76,9 +70,36 @@ export class DotEditContentSidebarActivitiesComponent {
7670
comment: [
7771
'',
7872
[
79-
Validators.required,
80-
Validators.minLength(COMMENT_MIN_LENGTH),
81-
Validators.maxLength(COMMENT_MAX_LENGTH)
73+
// Custom validator: only validate when field has value
74+
(control: FormControl) => {
75+
const value = control.value?.trim() || '';
76+
77+
// If empty, no validation needed
78+
if (!value) {
79+
return null;
80+
}
81+
82+
// Otherwise apply min/max length validators
83+
if (value.length < COMMENT_MIN_LENGTH) {
84+
return {
85+
minlength: {
86+
requiredLength: COMMENT_MIN_LENGTH,
87+
actualLength: value.length
88+
}
89+
};
90+
}
91+
92+
if (value.length > COMMENT_MAX_LENGTH) {
93+
return {
94+
maxlength: {
95+
requiredLength: COMMENT_MAX_LENGTH,
96+
actualLength: value.length
97+
}
98+
};
99+
}
100+
101+
return null;
102+
}
82103
]
83104
]
84105
});
@@ -155,16 +176,23 @@ export class DotEditContentSidebarActivitiesComponent {
155176
* Validates the form and emits the comment if valid
156177
*/
157178
onSubmit(): void {
158-
if (this.form.invalid) {
179+
const comment = this.commentControl.value?.trim();
180+
181+
// Check for empty comment and mark as touched to trigger validation
182+
if (!comment) {
183+
this.commentControl.setErrors({ required: true });
159184
this.commentControl.markAsDirty();
160185
this.commentControl.markAsTouched();
161-
this.commentControl.updateValueAndValidity({ onlySelf: true });
162186

163187
return;
164188
}
165189

166-
const comment = this.commentControl.value?.trim();
167-
if (!comment) {
190+
// Check for other validation errors
191+
if (this.form.invalid) {
192+
this.commentControl.markAsDirty();
193+
this.commentControl.markAsTouched();
194+
this.commentControl.updateValueAndValidity({ onlySelf: true });
195+
168196
return;
169197
}
170198

core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/components/dot-binary-field-preview/dot-binary-field-preview.component.scss

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ dot-contentlet-thumbnail {
9898
}
9999

100100
.preview-resource-links__actions {
101-
position: relative;
101+
position: absolute;
102102
top: 0;
103103
right: 0;
104-
display: flex;
104+
display: none;
105105
flex-direction: column;
106106
gap: $spacing-0;
107107
padding-top: $spacing-1;
@@ -125,6 +125,7 @@ dot-contentlet-thumbnail {
125125
display: flex;
126126
flex-direction: column;
127127
gap: $spacing-1;
128+
z-index: 100;
128129
}
129130

130131
code {
@@ -182,7 +183,7 @@ code {
182183
gap: $spacing-0;
183184
}
184185

185-
@container preview (min-width: 376px) {
186+
@container preview (min-width: 500px) {
186187
.preview-metadata__container,
187188
.preview-metadata__actions {
188189
display: flex;

0 commit comments

Comments
 (0)