import type { VNode } from 'vue'; import type { ILocalizedText } from '../../common/localized-text'; import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item'; import type { FormItemWrapperArgs, HintType, MarginType } from '../form/form-item-wrapper'; import type { TranslateGetRequest, TranslateGetResponse } from './translate'; import { Prop, toNative } from 'vue-facing-decorator'; import PowerduckState from '../../app/powerduck-state'; import TsxComponent, { Component } from '../../app/vuetsx'; import { Language } from '../../common/enums/language'; import LocalizedValueHelper from '../../common/localized-value-helper'; import { isNullOrEmpty } from '../../common/utils/is-null-or-empty'; import { LanguageUtils } from '../../common/utils/language-utils'; import { PortalUtils } from '../../common/utils/utils'; import Button from '../button/button'; import { ButtonLayout } from '../button/button-layout'; import FormItemWrapper from '../form/form-item-wrapper'; import Modal, { ModalSize } from '../modal/modal'; import ModalBody from '../modal/modal-body'; import ModalFooter from '../modal/modal-footer'; import globalIcon from './img/global.png'; import Translate from './translate'; import './css/localized-string-input.css'; interface LocalizedStringInputArgs extends FormItemWrapperArgs { value: ILocalizedText; changed: (e: ILocalizedText) => void; supportedLanguages?: Language[]; placeholder?: string; translatable?: boolean; translateApiMethod?: (data?: RQ) => Promise; } @Component class LocalizedStringInputComponent extends TsxComponent implements LocalizedStringInputArgs { @Prop() label!: string | VNode; @Prop() labelButtons!: DropdownButtonItemArgs[]; @Prop() subtitle!: string; @Prop() value!: ILocalizedText; @Prop() changed: (e: ILocalizedText) => void; @Prop() supportedLanguages?: Language[]; @Prop() marginType?: MarginType; @Prop() maxWidth?: number; @Prop() placeholder!: string; @Prop() mandatory!: boolean; @Prop() wrap!: boolean; @Prop() showClearValueButton!: boolean; @Prop() cssClass: string; @Prop() hint: string; @Prop() hintType!: HintType; @Prop() appendIcon: string; @Prop() prependIcon: string; @Prop({ default: false }) translatable: boolean; @Prop() translateApiMethod: (data?: RQ) => Promise; @Prop() appendClicked: () => void; @Prop() prependClicked: () => void; currentValue: ILocalizedText = null; modalWillShow: boolean = false; uuid: string = `lsw-${PortalUtils.randomString(10)}`; raiseChangeEvent(newValue: ILocalizedText): void { this.populateValidationDeclaration(); if (this.changed != null) { this.changed(newValue); } } isAllSame(): boolean { if (this.value != null) { const langList = LanguageUtils.getLanguageList(); const skValue = LocalizedValueHelper.getValue(this.value, Language.sk); for (let i = 0, len = langList.length; i < len; i++) { if (LocalizedValueHelper.getValue(this.value, langList[i].id) != skValue) { return false; } } } return true; } hasSomeValue(): boolean { return !isNullOrEmpty(LocalizedValueHelper.getValue(this.value, Language.sk)); } private getModalContext(): HTMLElement | null { return document.getElementById(this.uuid); } showInputModal(): void { this.modalWillShow = true; this.currentValue = JSON.parse(JSON.stringify(this.value || {})); this.$nextTick(() => { (this.$refs.dlgLocalizedString as typeof Modal.prototype).show({ onShown: () => { setTimeout(() => { const ctx = this.getModalContext(); let input = ctx?.querySelector(`.lsi-main-input[data-inv-lang="${PowerduckState.getCurrentLanguage()}"]`); if (input == null) { input = Array.from(ctx?.querySelectorAll('.lsi-main-input') ?? []) .find(el => el.offsetParent != null || el.getClientRects().length > 0) ?? null; } input?.focus(); }, 15); }, }); }); } handleModalValueChange(newValue: string, lang: { id: Language }) { const value = this.currentValue; const propName = lang.id; if (isNullOrEmpty(newValue)) { value[propName] = null; } else { value[propName] = newValue; } this.getModalContext() ?.querySelectorAll('[data-inv-lang]') .forEach((el) => { const currentVal = el.value; if (currentVal == null || currentVal.length == 0) { const language: Language = el.getAttribute('data-inv-lang') as any; const lsValue = LocalizedValueHelper.getValue(value, language) || ''; el.setAttribute('placeholder', lsValue); } }); } render(h) { return (
{this.renderInput(h)} {this.modalWillShow && this.renderModal(h)}
); } renderInput(h) { const allSame = this.isAllSame(); const hasValue = this.hasSomeValue(); if (allSame && !hasValue) { return this.renderInputPlaceholder(h); } else if (allSame) { return this.renderInputGlobalValue(h); } else { return this.renderInputMultipleValues(h); } } renderInputPlaceholder(h) { return (
this.showInputModal()}> {this.placeholder}
); } renderInputGlobalValue(h) { return (
this.showInputModal()}>   {LocalizedValueHelper.getValue(this.value, Language.sk)}
); } renderInputMultipleValues(h) { return (
this.showInputModal()}> {LanguageUtils.getLanguageList().map((lang) => { if (this.supportedLanguages != null && !(this.supportedLanguages.includes(lang.id))) { return null; } let langValue = this.value[lang.id]; const hasValue = !isNullOrEmpty(langValue); langValue = hasValue ? langValue : LocalizedValueHelper.getValue(this.value, lang.id); return (
  {langValue}
); })}
); } renderModal(h) { return ( {this.currentValue != null && (
{LanguageUtils.getLanguageList().map((lang) => { if (this.supportedLanguages != null && !(this.supportedLanguages.includes(lang.id))) { return null; } let langValue = this.currentValue[lang.id]; const hasValue = !isNullOrEmpty(langValue); langValue = hasValue ? langValue : LocalizedValueHelper.getValue(this.currentValue, lang.id); return (
{this.translatable !== false && ( { this.handleModalValueChange(value, { id: langId }); this.$forceUpdate(); }} getActualValue={(langId, value) => value[langId]} apiMethod={this.translateApiMethod} /> )}
this.handleModalValueChange(e.target.value, lang)} onKeyup={e => this.handleModalValueChange(e.target.value, lang)} value={hasValue ? langValue : null} />
); })}
)}