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/calendar/sharing/interface/src/controls/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/ilovecveti.ru/bitrix/js/calendar/sharing/interface/src/controls/layout.js
import { Dom, Event, Loc, Tag, Type } from 'main.core';
import { EventEmitter } from 'main.core.events';
import { Popup } from 'main.popup';
import { Analytics } from 'calendar.sharing.analytics';
import { Util } from 'calendar.util';
import Settings from './rule/settings';
import UserSelector from './joint/user-selector';
import List from './link-list/list';

import { SettingsModel } from '../model/index';

export type LayoutParams = {
	readOnly: boolean,
	settingsModel: SettingsModel,
	externalIcon: HTMLElement,
};

export class Layout
{
	HELP_DESK_CODE_CALENDAR = 17198666;
	HELP_DESK_CODE_CRM = 17502612;

	CONTEXT = {
		CRM: 'crm',
		CALENDAR: 'calendar',
	};

	#params: LayoutParams;

	#layout: {
		wrap: HTMLElement,
		main: HTMLElement,
		mainTop: HTMLElement,
		mainBottom: HTMLElement,
		buttonHistory: HTMLElement,
		buttonCopy: HTMLElement,
		buttonWhatSeeUsers: HTMLElement,
	};

	#settingsControl: Settings;
	#userSelectorControl: UserSelector;
	#linkList: List;

	constructor(params: LayoutParams)
	{
		this.#params = params;
		this.#layout = {};
		this.#bindEvents();
		this.isGroupContext = params.settingsModel.getCalendarContext()?.sharingObjectType === 'group';
	}

	get #settingsModel(): SettingsModel
	{
		return this.#params.settingsModel;
	}

	#bindEvents(): void
	{
		Event.bind(window, 'beforeunload', () => this.#settingsModel.save());
		EventEmitter.subscribe('CalendarSharing:onJointLinkCopy', async (event) => {
			const shortUrl = event.data.shortUrl;
			const linkHash = event.data.hash;

			await this.copyLink(shortUrl, linkHash);

			Analytics.sendLinkCopiedList(this.#settingsModel.getContext(), {
				peopleCount: event.data.members.length + 1,
				ruleChanges: this.#settingsModel.getChanges(),
			});
		});
	}

	reset(): void
	{
		void this.#settingsModel.save();
		this.#userSelectorControl?.clearSelectedUsers();
		setTimeout(() => this.#linkList?.close(), 200);
	}

	hasShownPopups(): boolean
	{
		const isSettingsPopupShown = this.#settingsControl.hasShownPopups();
		const isUserSelectorDialogOpened = this.#userSelectorControl?.isUserSelectorDialogOpened();
		const isListItemPopupOpened = this.#linkList?.isOpenListItemPopup();

		return isSettingsPopupShown || isUserSelectorDialogOpened || isListItemPopupOpened;
	}

	render(): HTMLElement
	{
		this.#layout.wrap = Tag.render`
			<div class="calendar-sharing__dialog-wrapper">
				${this.#renderMain()}
				${this.isGroupContext ? null : this.#renderLinkList()}
			</div>
		`;

		return this.#layout.wrap;
	}

	#renderMain(): HTMLElement
	{
		this.#layout.main ??= Tag.render`
			<div class="calendar-sharing__dialog-content-wrapper --show">
				${this.#renderTop()}
				<div class="calendar-sharing__dialog-body">
					${this.#renderDialogMessage()}
					${this.#renderSettings()}
					${this.#renderMembers()}
				</div>
				${this.#renderMainBottom()}
			</div>
		`;

		return this.#layout.main;
	}

	#renderDialogMessage(): HTMLElement | string
	{
		if (
			this.#settingsModel.getContext() === this.CONTEXT.CRM
			|| this.isGroupContext
		)
		{
			return '';
		}

		return Tag.render`
			<div class="calendar-sharing__dialog-message">
				<div class="calendar-sharing__dialog-info-icon-container">
					<div class="calendar-sharing__dialog-info-icon"></div>
				</div>
				<div class="calendar-sharing__dialog-notify" onclick="${this.#onOpenLink.bind(this)}">
					${Loc.getMessage('SHARING_INFO_POPUP_CONTENT_4_V3', { '#LINK#': this.#settingsModel.getSharingUrl() })}
				</div>
			</div>
		`;
	}

	async #onOpenLink(): Promise
	{
		await this.#settingsModel.save();
		window.open(this.#settingsModel.getSharingUrl(), '_blank').focus();
	}

	#renderTop(): HTMLElement
	{
		if (!this.#layout.mainTop)
		{
			this.#layout.mainTop = Tag.render`
				<div class="calendar-sharing__dialog-top">
					<div class="calendar-sharing__dialog-title">
						<span>${Loc.getMessage('SHARING_BUTTON_TITLE')}</span>
						${this.#renderHowDoesItWorkIcon()}
						${this.#params.externalIcon ?? ''}
					</div>
					<div class="calendar-sharing__dialog-info">
						${this.#getSharingInfoMessage()}
					</div>
				</div>
			`;

			const howDoesItWork = this.#layout.mainTop.querySelector('[data-role="calendar-sharing-how-does-it-work"]');
			Event.bind(howDoesItWork, 'click', this.#openHelpDesk.bind(this));

			const infoNotify = this.#layout.mainTop.querySelector('[data-role="calendar-sharing_popup-open-link"]');

			if (infoNotify)
			{
				let infoNotifyHint;
				let timer;
				Event.bind(infoNotify, 'mouseenter', () => {
					timer = setTimeout(() => {
						if (!infoNotifyHint)
						{
							infoNotifyHint = new Popup({
								bindElement: infoNotify,
								angle: {
									offset: infoNotify.offsetWidth / 2 + 16,
								},
								width: 410,
								darkMode: true,
								content: Loc.getMessage('SHARING_INFO_POPUP_SLOT_DESC'),
								animation: 'fading-slide',
							});
						}
						infoNotifyHint.show();
					}, 1000);
				});

				Event.bind(infoNotify, 'mouseleave', () => {
					clearTimeout(timer);
					if (infoNotifyHint)
					{
						infoNotifyHint.close();
					}
				});
			}
		}

		return this.#layout.mainTop;
	}

	#renderHowDoesItWorkIcon(): HTMLElement | string
	{
		if (this.#settingsModel.getContext() === this.CONTEXT.CRM)
		{
			return '';
		}

		const howDoesItWork = Tag.render`
			<span
				class="calendar-sharing__dialog-title-help"
				title="${Loc.getMessage('SHARING_INFO_POPUP_HOW_IT_WORK')}"
			></span>
		`;

		Event.bind(howDoesItWork, 'click', this.#openHelpDesk.bind(this));

		return howDoesItWork;
	}

	#openHelpDesk(): void
	{
		top.BX.Helper.show(`redirect=detail&code=${this.#getContextHelpDeskCode()}`);
	}

	#getSharingInfoMessage(): string
	{
		switch (this.#settingsModel.getContext())
		{
			case this.CONTEXT.CALENDAR:
				return Loc.getMessage('SHARING_INFO_POPUP_CONTENT_3_CALENDAR');
			case this.CONTEXT.CRM:
				return Loc.getMessage('SHARING_INFO_POPUP_CONTENT_3_CRM_MSGVER_2');
			default:
				return '';
		}
	}

	#getContextHelpDeskCode(): number
	{
		switch (this.#settingsModel.getContext())
		{
			case this.CONTEXT.CALENDAR:
				return this.HELP_DESK_CODE_CALENDAR;

			case this.CONTEXT.CRM:
				return this.HELP_DESK_CODE_CRM;

			default:
				return 0;
		}
	}

	#renderSettings(): HTMLElement
	{
		this.#settingsControl = new Settings({
			readOnly: this.#params.readOnly,
			model: this.#settingsModel,
		});

		return this.#settingsControl.render();
	}

	#renderMembers(): HTMLElement
	{
		this.#userSelectorControl = new UserSelector({
			model: this.#settingsModel,
			onMembersAdded: () => Analytics.sendMembersAdded(
				this.#settingsModel.getContext(),
				this.#userSelectorControl.getPeopleCount(),
			),
		});

		return this.#userSelectorControl.render();
	}

	#renderMainBottom(): HTMLElement
	{
		if (this.#settingsModel.getContext() === this.CONTEXT.CRM)
		{
			return '';
		}

		this.#layout.mainBottom ??= Tag.render`
			<div class="calendar-sharing__dialog-bottom">
				${this.#renderCopyLinkButton()}
				${this.isGroupContext ? null : this.#renderLinkHistoryButton()}
			</div>
		`;

		return this.#layout.mainBottom;
	}

	#renderCopyLinkButton(): HTMLElement
	{
		if (!this.#layout.buttonCopy)
		{
			this.#layout.buttonCopy = Tag.render`
				<span class="ui-btn ui-btn-success ui-btn-round ui-btn-no-caps calendar-sharing__dialog-copy">
					${Loc.getMessage('SHARING_DIALOG_SHARING_BLOCK_COPY_LINK_BUTTON')}
				</span>
			`;

			Event.bind(this.#layout.buttonCopy, 'click', this.#onButtonCopyClick.bind(this));
		}

		return this.#layout.buttonCopy;
	}

	async #onButtonCopyClick(): void
	{
		const params = {
			peopleCount: this.#userSelectorControl?.getPeopleCount() ?? 1,
			ruleChanges: this.#settingsModel.getChanges(),
		};

		if (this.#userSelectorControl && this.#userSelectorControl.hasChanges())
		{
			Analytics.sendLinkCopied(this.#settingsModel.getContext(), Analytics.linkTypes.multiple, params);

			void this.saveJointLink();
		}
		else if (await this.copyLink(this.#settingsModel.getSharingUrl()))
		{
			Analytics.sendLinkCopied(this.#settingsModel.getContext(), Analytics.linkTypes.solo, params);

			if (!this.isGroupContext)
			{
				this.#settingsModel.increaseFrequentUse();
			}
		}
	}

	async saveJointLink(): Promise
	{
		if (this.#layout.buttonCopy && Dom.hasClass(this.#layout.buttonCopy, 'ui-btn-clock'))
		{
			return;
		}

		Dom.addClass(this.#layout.buttonCopy, 'ui-btn-clock');

		const link = await this.#settingsModel.saveJointLink();

		Dom.removeClass(this.#layout.buttonCopy, 'ui-btn-clock');

		await this.copyLink(link.url, link.hash);

		this.#linkList?.getLinkListInfo();
	}

	#renderLinkHistoryButton(): HTMLElement
	{
		if (!this.#layout.buttonHistory)
		{
			this.#layout.buttonHistory = Tag.render`
				<span
					class="ui-btn ui-btn-round ui-btn-light ui-btn-no-caps calendar-sharing__dialog-people"
					data-id="calendar-sharing-history-btn"
				>
					${Loc.getMessage('SHARING_DIALOG_SHARING_BLOCK_JOINT_SLOTS_BUTTON')}
				</span>
			`;

			Event.bind(this.#layout.buttonHistory, 'click', this.#openLinkList.bind(this));
		}

		return this.#layout.buttonHistory;
	}

	#renderLinkList(): HTMLElement | null
	{
		if (this.#settingsModel.getContext() === this.CONTEXT.CRM)
		{
			return null;
		}

		return this.#getLinkList().render();
	}

	#getLinkList(): List
	{
		this.#linkList ??= new List({
			model: this.#settingsModel,
			onLinkListClose: this.#closeLinkList.bind(this),
		});

		return this.#linkList;
	}

	#openLinkList(): void
	{
		Dom.removeClass(this.#layout.main, '--show');
		this.#linkList.show(this.#layout.main.offsetHeight);
	}

	#closeLinkList(): void
	{
		Dom.addClass(this.#layout.main, '--show');
	}

	async copyLink(url: string, hash: string): Promise<boolean>
	{
		if (!url)
		{
			return false;
		}

		try
		{
			await this.#copyToClipboard(url);
		}
		catch
		{
			return false;
		}

		Util.showNotification(Loc.getMessage('SHARING_COPY_LINK_NOTIFICATION'));
		EventEmitter.emit('CalendarSharing:LinkCopied', { url, hash });

		return true;
	}

	async #copyToClipboard(textToCopy: string): Promise<void>
	{
		if (!Type.isString(textToCopy))
		{
			return Promise.reject();
		}

		// navigator.clipboard defined only if window.isSecureContext === true
		// so or https should be activated, or localhost address
		if (navigator.clipboard)
		{
			// safari not allowed clipboard manipulation as result of ajax request
			// so timeout is hack for this, to prevent "not have permission"
			return new Promise((resolve, reject) => {
				setTimeout(() => (
					navigator.clipboard
						.writeText(textToCopy)
						.then(() => resolve())
						.catch((e) => reject(e))
				), 0);
			});
		}

		return BX.clipboard?.copy(textToCopy) ? Promise.resolve() : Promise.reject();
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit