Skip to content

Commit

Permalink
Don't hide the Juke icon when focus is inside the input #3784
Browse files Browse the repository at this point in the history
  • Loading branch information
ashklianko committed Nov 15, 2024
1 parent 85eb248 commit 7eb9794
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 174 deletions.
70 changes: 0 additions & 70 deletions src/main/resources/assets/admin/common/js/ai/AiControls.ts

This file was deleted.

41 changes: 41 additions & 0 deletions src/main/resources/assets/admin/common/js/ai/AiDialogControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as Q from 'q';
import {Button} from '../ui/button/Button';
import {i18n} from '../util/Messages';
import {AiContentOperatorOpenDialogEvent} from './event/AiContentOperatorOpenDialogEvent';

export class AiDialogControl
extends Button {

private dataPath?: string;

constructor() {
super();

this.initListeners();
}

setDataPath(dataPath: string): AiDialogControl {
this.dataPath = dataPath;
return this;
}

getDataPath(): string {
return this.dataPath;
}

protected initListeners(): void {
this.onClicked(() => {
if (this.dataPath) {
new AiContentOperatorOpenDialogEvent(this.dataPath).fire();
}
});
}

doRender(): Q.Promise<boolean> {
return super.doRender().then((rendered: boolean) => {
this.addClass('ai-dialog-control').setTitle(i18n('ai.action.contentOperator.use'));

return rendered;
});
}
}
59 changes: 47 additions & 12 deletions src/main/resources/assets/admin/common/js/ai/AiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import {PropertyPath} from '../data/PropertyPath';
import {Element} from '../dom/Element';
import {Store} from '../store/Store';
import {i18n} from '../util/Messages';
import {AiControls} from './AiControls';
import {AiStateControl} from './AiStateControl';
import {AiHelperState} from './AiHelperState';
import {AiDialogControl} from './AiDialogControl';

export interface AiHelperConfig {
dataPathElement: Element;
getPath: () => PropertyPath;
setValue?: (value: string) => void;
controls?: {
container: Element;
stateControl?: {
stateContainer: Element;
label: string;
showAiButton?: boolean;
};
aiButtonContainer?: Element;
}

const AI_HELPERS_KEY = 'AiHelpers';
Expand All @@ -23,9 +24,13 @@ export class AiHelper {

private static readonly DATA_ATTR = 'data-path';

private static DIALOG_CONTROL_REGISTRY = new Map<Element, AiDialogControl>();

private readonly config: AiHelperConfig;

private readonly aiControls?: AiControls;
private readonly aiStateControl?: AiStateControl;

private readonly aiDialogControl?: AiDialogControl;

private state: AiHelperState = AiHelperState.DEFAULT;

Expand All @@ -44,10 +49,13 @@ export class AiHelper {

Store.instance().get(AI_HELPERS_KEY).push(this);

const {controls} = this.config;
if (controls) {
this.aiControls = new AiControls({showAiButton: controls.showAiButton});
controls.container.appendChild(this.aiControls);
if (this.config.stateControl) {
this.aiStateControl = new AiStateControl();
this.config.stateControl.stateContainer.appendChild(this.aiStateControl);
}

if (this.config.aiButtonContainer) {
this.aiDialogControl = this.setupAiIcon();
}
}

Expand All @@ -70,7 +78,34 @@ export class AiHelper {
private updateInputElDataPath(): void {
const dataPath = AiHelper.convertToPath(this.config.getPath());
this.config.dataPathElement.getEl().setAttribute(AiHelper.DATA_ATTR, dataPath);
this.aiControls?.setDataPath(dataPath);

if (this.config.dataPathElement.hasFocus()) {
this.aiDialogControl?.setDataPath(dataPath);
}
}

private setupAiIcon(): AiDialogControl {
const aiIcon = this.getOrCreateAiIcon();

this.config.dataPathElement.onFocus(() => {
aiIcon.setDataPath(this.getDataPath()).addClass('input-focused');
});

this.config.dataPathElement.onBlur(() => aiIcon.removeClass('input-focused'));

return aiIcon;
}

private getOrCreateAiIcon(): AiDialogControl {
if (AiHelper.DIALOG_CONTROL_REGISTRY.has(this.config.aiButtonContainer)) {
return AiHelper.DIALOG_CONTROL_REGISTRY.get(this.config.aiButtonContainer);
}

const aiIcon = new AiDialogControl();
this.config.aiButtonContainer.appendChild(aiIcon);
AiHelper.DIALOG_CONTROL_REGISTRY.set(this.config.aiButtonContainer, aiIcon);

return aiIcon;
}

setState(state: AiHelperState): this {
Expand All @@ -79,7 +114,7 @@ export class AiHelper {
}

this.state = state;
this.aiControls?.setState(state);
this.aiStateControl?.setState(state);

if (state === AiHelperState.COMPLETED || state === AiHelperState.FAILED) {
setTimeout(() => {
Expand Down Expand Up @@ -116,7 +151,7 @@ export class AiHelper {
parent.setAttribute('data-title', parent.getTitle());
}

parent.setTitle(i18n('ai.field.processing', this.config.controls?.label));
parent.setTitle(i18n('ai.field.processing', this.config.stateControl?.label));
}

private resetTitle(): void {
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/assets/admin/common/js/ai/AiStateControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {DivEl} from '../dom/DivEl';
import {AiHelperState} from './AiHelperState';

export class AiStateControl
extends DivEl {

constructor() {
super();

this.setState(AiHelperState.DEFAULT);
}

setState(state: AiHelperState): this {
this.setClass(`ai-state-control ${state}`);

return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ export class InputOccurrenceView
refresh() {
if (this.formItemOccurrence.oneAndOnly()) {
this.addClass('single-occurrence').removeClass('multiple-occurrence');
this.inputTypeView.removeClass('has-multiple-occurrence');
} else {
this.addClass('multiple-occurrence').removeClass('single-occurrence');
this.inputTypeView.addClass('has-multiple-occurrence');
}

this.removeButtonEl.setVisible(this.formItemOccurrence.isRemoveButtonRequiredStrict());
Expand Down Expand Up @@ -198,11 +200,11 @@ export class InputOccurrenceView
AiHelper.attach({
dataPathElement: this.inputElement,
getPath: () => this.getDataPath(),
controls: {
container: this.inputWrapper,
stateControl: {
stateContainer: this.inputWrapper,
label: this.inputTypeView.getInput().getLabel(),
showAiButton: true,
},
aiButtonContainer: this.inputTypeView,
setValue: (val: string) => {
this.property.setValue(this.inputTypeView.getValueType().newValue(val));
this.inputTypeView.updateInputOccurrenceElement(this.inputElement, this.property);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
button.ai-dialog-control {
position: absolute;
top: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
width: 20px;
height: 20px;
box-sizing: border-box;
font-size: 16px;
padding: 0;

&:not(:hover):not(:focus):not(:focus-within):not(.input-focused) {
display: none;
}

background: transparent;

&:hover:not(:disabled) {
background: transparent;
}

&::before {
content: '';
display: inline-block;
width: 1em;
height: 1em;
background: url("../../../images/juke-eye-centered.svg") center / contain no-repeat;
}
}

Loading

0 comments on commit 7eb9794

Please sign in to comment.