403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/ilovecveti.ru/bitrix/js/bizproc/automation/src/selectors/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/ilovecveti.ru/bitrix/js/bizproc/automation/src/selectors/inline-selector.js
import {
	DelayInterval,
	DelayIntervalSelector,
	Helper,
	SelectorContext,
} from 'bizproc.automation';
import { Dom, Event, Loc, Runtime, Tag, Type } from 'main.core';
import { EventEmitter } from 'main.core.events';
import { Menu, MenuManager } from 'main.popup';
import { Dialog } from 'ui.entity-selector';
import enrichFieldsWithModifiers from './enrich-fields-with-modifiers';
import { DocumentGroup } from './group/document-group';
import { FileGroup } from './group/file-group';

import { Field, MenuGroupItem } from './types';

export class InlineSelector extends EventEmitter
{
	context: SelectorContext;
	fieldProperty: ?Field = null;
	replaceOnWrite: boolean = false;
	menuButton: ?HTMLSpanElement = null;
	targetInput: ?HTMLElement = null;
	#menuGroups: Object<string, MenuGroupItem> = {};
	basisFields: Array<Object> = [];
	#dialog: ?Dialog = null;
	#switcherDialog: ?Menu = null;

	constructor(props: { context: SelectorContext })
	{
		super();
		this.setEventNamespace('BX.Bizproc.Automation.Selector');

		this.context = props.context;
		this.basisFields = this.context.fields;
	}

	hasGroup(groupId: string): boolean
	{
		return this.#menuGroups.hasOwnProperty(groupId);
	}

	addGroup(groupId: string, group: MenuGroupItem)
	{
		const normalizedGroup = this.#normalizeGroup(group);

		if (this.hasGroup(groupId))
		{
			this.#menuGroups[groupId] = (
				this.#normalizeGroup(this.#mergeGroups(this.#menuGroups[groupId], normalizedGroup))
			);

			return;
		}

		this.#menuGroups[groupId] = normalizedGroup;
	}

	#mergeGroups(originalGroup: MenuGroupItem, newGroup: MenuGroupItem): MenuGroupItem
	{
		return {
			...originalGroup,
			...newGroup,
			children: [
				...originalGroup.children,
				...newGroup.children,
			],
		};
	}

	addGroupItem(groupId: string, item: MenuGroupItem)
	{
		if (this.hasGroup(groupId))
		{
			this.#menuGroups[groupId].children.push(this.#normalizeGroup(item));
		}
	}

	#normalizeGroup(group: MenuGroupItem)
	{
		if (!Type.isArray(group.children))
		{
			group.children = [];
		}

		group.children = (
			group
				.children
				.filter(item => item.customData?.field ? this.#shouldShowField(item.customData.field) : true)
				.map(childGroup => this.#normalizeGroup(childGroup))
		);

		return {
			entityId: 'bp',
			tabs: 'recents',
			...group
		};
	}

	renderWith(targetInput: Element): HTMLDivElement
	{
		this.targetInput = Runtime.clone(targetInput);
		this.targetInput.setAttribute('autocomplete', 'off');

		this.menuButton = Tag.render`
			<span 
				onclick="${this.openMenu.bind(this)}"
				class="bizproc-automation-popup-select-dotted"
			></span>
		`;

		this.parseTargetProperties();

		this.replaceOnWrite |= (this.targetInput.getAttribute('data-select-mode') === 'replace');

		return Tag.render`
			<div class="bizproc-automation-popup-select">
				${this.targetInput}
				${this.menuButton}
			</div>
		`;
	}

	renderTo(targetInput: Element): void
	{
		targetInput.parentNode.replaceChild(this.renderWith(targetInput), targetInput);
	}

	bindTargetEvents(): void
	{
		Event.bind(this.targetInput, 'keydown', this.#onKeyDown.bind(this));
	}

	parseTargetProperties(): void
	{
		this.fieldProperty = JSON.parse(this.targetInput.getAttribute('data-property'));
		const propertyType = this.targetInput.getAttribute('data-selector-type');

		if (!this.fieldProperty && propertyType)
		{
			this.fieldProperty = { Type: propertyType };
		}

		if (this.fieldProperty)
		{
			this.fieldProperty.Type = this.fieldProperty.Type || propertyType;
			this.#prepareSelectorUsingFieldType();
		}
		else
		{
			this.context.useSwitcherMenu = false;
		}

		this.replaceOnWrite |= (this.targetInput.getAttribute('data-select-mode') === 'replace');
	}

	#prepareSelectorUsingFieldType(): void
	{
		this.basisFields = this.basisFields.filter((field) => this.#shouldShowField(field));

		const type = this.fieldProperty?.Type;
		if (type === 'file')
		{
			this.replaceOnWrite = true;
		}
		else if (type === 'date' || type === 'datetime')
		{
			this.replaceOnWrite = true;

			const delayIntervalSelector = new DelayIntervalSelector({
				labelNode: this.targetInput,
				basisFields: this.basisFields,
				useAfterBasis: true,
				onchange: (function(delay)
				{
					this.targetInput.value = delay.toExpression(
						this.basisFields,
						Helper.getResponsibleUserExpression(this.context.fields),
					);
				}).bind(this),
			});

			delayIntervalSelector.init(DelayInterval.fromString(this.targetInput.value, this.basisFields));
		}
	}

	#shouldShowField(field: Field): boolean
	{
		const fieldType = this.fieldProperty?.Type;
		if (fieldType === 'file')
		{
			return field.Type === 'file';
		}
		else if (fieldType === 'date' || fieldType === 'datetime')
		{
			return field.Type === 'date' || field.Type === 'datetime';
		}
		else if (fieldType === 'time')
		{
			return field.Type === 'date' || field.Type === 'datetime' || field.Type === 'time';
		}

		return true;
	}

	#onKeyDown(event: KeyboardEvent)
	{
		if (event.keyCode === 45 && event.altKey === false && event.ctrlKey === false && event.shiftKey === false)
		{
			this.openMenu(event);
			event.preventDefault();
		}
	}

	openMenu(event: KeyboardEvent, skipPropertiesSwitcher: boolean = false)
	{
		if (!skipPropertiesSwitcher && this.context.useSwitcherMenu && !this.targetInput.value)
		{
			return this.openPropertiesSwitcherMenu();
		}

		if (this.#dialog)
		{
			this.#dialog.show();
			return;
		}

		this.fillGroups();
		this.onMenuOpen();

		let menuItems = [];
		for (const group of Object.values(this.#menuGroups))
		{
			if (group.children.length > 0)
			{
				menuItems.push(group);
			}
		}

		if (menuItems.length === 1)
		{
			menuItems = menuItems[0].children;
		}

		let menuId = this.menuButton.getAttribute('data-selector-id');
		if (!menuId)
		{
			menuId = Helper.generateUniqueId();
			this.menuButton.setAttribute('data-selector-id', menuId);
		}

		this.#dialog = new Dialog({
			targetNode: this.menuButton,
			width: 500,
			height: 300,
			multiple: false,
			dropdownMode: true,
			enableSearch: true,
			items: this.injectDialogMenuTitles(menuItems),
			showAvatars: false,
			events: {
				'Item:onBeforeSelect': (event) => {
					event.preventDefault();

					const item = event.getData().item;
					this.onFieldSelect(item.getCustomData().get('field'));
				}
			},
			compactView: true,
		});

		this.#dialog.show();
	}

	fillGroups(): void
	{
		this.fillFieldsGroups();
		this.fillFileGroup();
	}

	fillFieldsGroups(): void
	{
		const documentGroup = new DocumentGroup({
			fields: this.getFields(),
			title: this.context.rootGroupTitle,
			setSuperTitle: false,
		});

		documentGroup.groupsWithChildren.forEach((group) => {
			this.addGroup(group.id, group);
		});
	}

	fillFileGroup(): void
	{
		const fileFields = this.getFields().filter((field) => field.Type === 'file');

		const fileGroup = new FileGroup({
			fields: enrichFieldsWithModifiers(
				fileFields,
				'Document',
				{
					friendly: false,
					printable: false,
					server: false,
					responsible: false,
					shortLink: true,
				},
			).filter((field) => field.Type === 'string'),
			setSuperTitle: false,
		});

		fileGroup.groupsWithChildren.forEach((group) => {
			this.addGroup(group.id, group);
		});
	}

	onMenuOpen(): void
	{
		this.emit('onOpenMenu', { selector: this });
	}

	openPropertiesSwitcherMenu()
	{
		const self = this;

		MenuManager.show(
			Helper.generateUniqueId(),
			this.menuButton,
			[
				{
					text: Loc.getMessage('BIZPROC_AUTOMATION_ASK_CONSTANT'),
					disabled: self.fieldProperty?.Type === 'file',
					onclick(event) {
						this.popupWindow.close();
						self.emit('onAskConstant', {fieldProperty: self.fieldProperty});
					}
				},
				{
					text: Loc.getMessage('BIZPROC_AUTOMATION_ASK_PARAMETER'),
					onclick(event) {
						this.popupWindow.close();
						self.emit('onAskParameter', {fieldProperty: self.fieldProperty});
					}
				},
				{
					text: Loc.getMessage('BIZPROC_AUTOMATION_ASK_MANUAL'),
					onclick(event) {
						this.popupWindow.close();
						self.openMenu(event, true);
					}
				}
			],
			{
				autoHide: true,
				offsetLeft: 20,
				angle: { position: 'top'},
				events: {
					onPopupClose()
					{
						this.destroy();
					}
				}
			}
		);
		this.#switcherDialog = MenuManager.currentItem;

		return true;
	}

	injectDialogMenuTitles(items)
	{
		items.forEach((parent) => {
			if (Type.isArray(parent.children))
			{
				this.injectDialogMenuSupertitles(parent.title, parent.children);
			}
		});

		return items;
	}

	injectDialogMenuSupertitles(title: string, children)
	{
		children.forEach((child) => {
			if (!child.supertitle)
			{
				child.supertitle = title;
			}
			if (Type.isArrayFilled(child.children))
			{
				this.injectDialogMenuSupertitles(child.title, child.children);
			}
		});
	}

	onFieldSelect(field: ?Field): void
	{
		if (!field)
		{
			return;
		}

		const inputType = this.targetInput.tagName.toLowerCase();

		if (inputType === 'select')
		{
			let expressionOption = this.targetInput.querySelector('[data-role="expression"]');
			if (!expressionOption)
			{
				expressionOption = (
					this.targetInput.appendChild(
						Dom.create(
							'option',
							{attrs: {'data-role': 'expression'}}
						)
					)
				);
			}
			expressionOption.setAttribute('value', field.Expression);
			expressionOption.textContent = field['Expression'];

			expressionOption.selected = true;
		}
		else if (inputType === 'label')
		{
			this.targetInput.textContent = field.Expression;
			const hiddenInput = document.getElementById(this.targetInput.getAttribute('for'));
			if (hiddenInput)
			{
				hiddenInput.value = field.Expression;
			}
		}
		else
		{
			if (this.replaceOnWrite)
			{
				this.targetInput.value = field.Expression;
				this.targetInput.selectionEnd = this.targetInput.value.length;
			}
			else
			{
				let beforePart = '';
				const middlePart = field.Expression;
				let afterPart = '';
				if (Type.isStringFilled(this.targetInput.value))
				{
					beforePart = this.targetInput.value.substr(0, this.targetInput.selectionEnd);
					afterPart = this.targetInput.value.substr(this.targetInput.selectionEnd);
				}

				this.targetInput.value = beforePart + middlePart + afterPart;
				this.targetInput.selectionEnd = beforePart.length + middlePart.length;
			}
		}

		BX.fireEvent(this.targetInput, 'change');
		this.emit('Field:Selected', { field });
	}

	destroy()
	{
		if (this.#dialog)
		{
			this.#dialog.destroy();
		}
		if (this.#switcherDialog)
		{
			this.#switcherDialog.destroy();
		}
	}

	getFields(): Array<Field>
	{
		return enrichFieldsWithModifiers(this.basisFields, 'Document', { shortLink: false });
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit