diff --git a/core-web/apps/dotcms-ui/.storybook/main.js b/core-web/apps/dotcms-ui/.storybook/main.js
index 8d8ae7d46183..c1ff1d7aa361 100644
--- a/core-web/apps/dotcms-ui/.storybook/main.js
+++ b/core-web/apps/dotcms-ui/.storybook/main.js
@@ -13,7 +13,8 @@ module.exports = {
'../../../libs/template-builder/**/*.stories.@(js|jsx|ts|tsx|mdx)',
'../../../libs/block-editor/**/*.stories.@(js|jsx|ts|tsx|mdx)',
'../../../libs/contenttype-fields/**/*.stories.@(js|jsx|ts|tsx|mdx)',
- '../../../libs/ui/**/*.stories.@(js|jsx|ts|tsx|mdx)'
+ '../../../libs/ui/**/*.stories.@(js|jsx|ts|tsx|mdx)',
+ '../../../libs/portlets/**/*.stories.@(js|jsx|ts|tsx|mdx)'
],
addons: ['storybook-design-token', '@storybook/addon-essentials', ...rootMain.addons],
features: {
diff --git a/core-web/apps/dotcms-ui/.storybook/tsconfig.json b/core-web/apps/dotcms-ui/.storybook/tsconfig.json
index 65c1db876c17..e3ced7fe28e7 100644
--- a/core-web/apps/dotcms-ui/.storybook/tsconfig.json
+++ b/core-web/apps/dotcms-ui/.storybook/tsconfig.json
@@ -9,6 +9,7 @@
"../../../**/template-builder/**/src/lib/**/*.stories.ts",
"../../../**/block-editor/**/src/lib/**/*.stories.ts",
"../../../**/contenttype-fields/**/src/lib/**/*.stories.ts",
- "../../../**/ui/**/src/lib/**/*.stories.ts"
+ "../../../**/ui/**/src/lib/**/*.stories.ts",
+ "../../../**/portlets/**/src/lib/**/*.stories.ts"
]
}
diff --git a/core-web/libs/portlets/dot-experiments/portlet/src/lib/dot-experiments-configuration/components/dot-experiments-configuration-goal-select/dot-experiments-configuration-goal-select.component.html b/core-web/libs/portlets/dot-experiments/portlet/src/lib/dot-experiments-configuration/components/dot-experiments-configuration-goal-select/dot-experiments-configuration-goal-select.component.html
index 4f8b65dddb93..d1e29eaee30e 100644
--- a/core-web/libs/portlets/dot-experiments/portlet/src/lib/dot-experiments-configuration/components/dot-experiments-configuration-goal-select/dot-experiments-configuration-goal-select.component.html
+++ b/core-web/libs/portlets/dot-experiments/portlet/src/lib/dot-experiments-configuration/components/dot-experiments-configuration-goal-select/dot-experiments-configuration-goal-select.component.html
@@ -3,20 +3,17 @@
[(visible)]="vm.status.isOpen"
(onHide)="closeSidebar()"
dotSidebar
- dotSize="{{ sidebarSizes.LG }}"
- >
+ dotSize="{{ sidebarSizes.LG }}">
+ dotTitle="{{ 'experiments.configure.goals.sidebar.header' | dm }}" />
@@ -31,17 +30,16 @@
(keydown.escape)="deactivateInplace()"
data-testId="inplace-input"
dotAutofocus
+ dotTrimInput
formControlName="text"
- pInputText
- />
+ pInputText />
+ data-testId="variant-inplace-button">
+ type="button">
diff --git a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.scss b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.scss
index bdb70727b9e5..4c9437e14dff 100644
--- a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.scss
+++ b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.scss
@@ -17,16 +17,14 @@
}
&::ng-deep {
- .p-disabled,
- .p-component {
- width: 100%;
-
+ .p-disabled {
&:disabled {
opacity: 0.8;
}
}
p-inplace .p-inplace {
+ width: 100%;
.p-inplace-display {
padding: 0;
white-space: pre-wrap;
diff --git a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.spec.ts b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.spec.ts
index 854853bb829c..80d1c36c45ff 100644
--- a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.spec.ts
+++ b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.spec.ts
@@ -21,7 +21,7 @@ const LONG_TEXT =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed condimentum eros sit amet malesuada mattis. Morbi ac congue lectus, ut vestibulum velit. Ut sed ornare metus. Proin a orci lacus. Aenean odio lacus, fringilla eu ipsum non, pellentesque sagittis purus. Integer non.';
const NEW_EXPERIMENT_DESCRIPTION = 'new experiment description';
-describe('DotExperimentsExperimentSummaryComponent', () => {
+describe('DotExperimentsInlineEditTextComponent', () => {
let spectator: Spectator;
const createComponent = createComponentFactory({
component: DotExperimentsInlineEditTextComponent,
@@ -176,6 +176,17 @@ describe('DotExperimentsExperimentSummaryComponent', () => {
expect(deactivate).toHaveBeenCalled();
});
+ it('should deactivate the textControl if isLoading input has `currentValue = true` ', () => {
+ spectator.dispatchMouseEvent(byTestId('text-input'), 'click');
+
+ const input = spectator.query(byTestId('inplace-input')) as HTMLInputElement;
+
+ expect(input.disabled).toBe(false);
+
+ spectator.setInput('isLoading', true);
+ expect(input.disabled).toBe(true);
+ });
+
it('should show `dot-field-validation-message` message error by default', () => {
spectator.setInput('text', SHORT_TEXT);
spectator.setInput('required', true);
diff --git a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.ts b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.ts
index 0510fa508091..a55eac57f558 100644
--- a/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.ts
+++ b/core-web/libs/portlets/dot-experiments/portlet/src/lib/shared/ui/dot-experiments-inline-edit-text/dot-experiments-inline-edit-text.component.ts
@@ -23,7 +23,7 @@ import { InputTextModule } from 'primeng/inputtext';
import { DotFieldValidationMessageModule } from '@components/_common/dot-field-validation-message/dot-file-validation-message.module';
import { MAX_INPUT_DESCRIPTIVE_LENGTH } from '@dotcms/dotcms-models';
-import { DotAutofocusDirective, DotMessagePipe } from '@dotcms/ui';
+import { DotAutofocusDirective, DotMessagePipe, DotTrimInputDirective } from '@dotcms/ui';
import { DotValidators } from '@shared/validators/dotValidators';
type InplaceInputSize = 'small' | 'large';
@@ -50,7 +50,8 @@ const InplaceInputSizeMapPrimeNg: Record;
+
+const Template: Story = (
+ args: DotExperimentsInlineEditTextComponent
+) => ({
+ props: { ...args, textChanged: action('textChanged') }
+});
+
+export const Default = Template.bind({});
diff --git a/core-web/libs/ui/src/index.ts b/core-web/libs/ui/src/index.ts
index 603a72dbadc4..af0778d59de8 100644
--- a/core-web/libs/ui/src/index.ts
+++ b/core-web/libs/ui/src/index.ts
@@ -12,3 +12,4 @@ export * from './lib/components/dot-empty-container/dot-empty-container.componen
export * from './lib/dot-tab-buttons/dot-tab-buttons.component';
export * from './lib/dot-remove-confirm-popup/dot-remove-confirm-popup.directive';
export * from './lib/directives/dot-autofocus/dot-autofocus.directive';
+export * from './lib/directives/dot-trim-input/dot-trim-input.directive';
diff --git a/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.spec.ts b/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.spec.ts
new file mode 100644
index 000000000000..0466ac448ce0
--- /dev/null
+++ b/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.spec.ts
@@ -0,0 +1,43 @@
+import { byTestId, createComponentFactory, Spectator } from '@ngneat/spectator';
+
+import { Component } from '@angular/core';
+import { FormsModule, NgControl } from '@angular/forms';
+
+import { DotTrimInputDirective } from '@dotcms/ui';
+
+const STRING_WITH_SPACES = ' Test Value ';
+
+@Component({
+ template: ``
+})
+export class DotTrimInputHostMockComponent {
+ name = STRING_WITH_SPACES;
+}
+
+describe('DotTrimInputDirective', () => {
+ let spectator: Spectator;
+ const createComponent = createComponentFactory({
+ component: DotTrimInputHostMockComponent,
+ imports: [FormsModule, DotTrimInputDirective],
+ providers: [NgControl]
+ });
+
+ beforeEach(() => {
+ spectator = createComponent();
+ });
+
+ it('should trim the input value on blur', async () => {
+ const input = spectator.query(byTestId('input-to-trim')) as HTMLInputElement;
+ const expectedValue = STRING_WITH_SPACES.trim();
+
+ await spectator.fixture.whenStable();
+
+ expect(spectator.query(byTestId('input-to-trim'))).toExist();
+ expect(input.value).toBe(STRING_WITH_SPACES);
+
+ spectator.dispatchFakeEvent(input, 'blur');
+ spectator.detectComponentChanges();
+
+ expect(input.value).toBe(expectedValue);
+ });
+});
diff --git a/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.ts b/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.ts
new file mode 100644
index 000000000000..18866c6f6ffb
--- /dev/null
+++ b/core-web/libs/ui/src/lib/directives/dot-trim-input/dot-trim-input.directive.ts
@@ -0,0 +1,27 @@
+import { AfterViewInit, Directive, ElementRef, HostListener, Optional, Self } from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+/**
+ * Directive for trimming the input value on blur.
+ */
+@Directive({
+ selector: '[dotTrimInput]',
+ standalone: true
+})
+export class DotTrimInputDirective implements AfterViewInit {
+ constructor(
+ @Optional() @Self() private readonly ngControl: NgControl,
+ private readonly el: ElementRef
+ ) {}
+
+ @HostListener('blur')
+ onBlur() {
+ this.ngControl.control.setValue(this.ngControl.value.trim());
+ }
+
+ ngAfterViewInit(): void {
+ if (this.el.nativeElement.tagName.toLowerCase() !== 'input') {
+ console.warn('DotTrimInputDirective is for use with Inputs');
+ }
+ }
+}