Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/js/ui/uploader/stack-widget/src/components/
Upload File :
Current File : /var/www/homesaver/www/bitrix/js/ui/uploader/stack-widget/src/components/stack-widget-component.js

import { Text, Loc } from 'main.core';
import { Popup, PopupOptions } from 'main.popup';
import { CloseButton } from 'ui.buttons';

import { FileStatus, FileOrigin, UploaderStatus } from 'ui.uploader.core';
import { VueUploaderComponent } from 'ui.uploader.vue';
import { TileList, ErrorPopup, DragOverMixin } from 'ui.uploader.tile-widget';

import { StackUpload } from './stack-upload';
import { StackLoad } from './stack-load';
import { StackPreview } from './stack-preview';
import { StackDropArea } from './stack-drop-area';

import type { BaseEvent } from 'main.core.events';

const isItemLoading = item => item.status === FileStatus.LOADING;

/**
 * @memberof BX.UI.Uploader
 */
export const StackWidgetComponent = {
	name: 'StackWidget',
	extends: VueUploaderComponent,
	components: {
		TileList,
		ErrorPopup,
		StackUpload,
		StackLoad,
		StackPreview,
		StackDropArea,
	},
	mixins: [
		DragOverMixin,
	],
	data: () => ({
		popupContentId: null,
		queueItems: [],
		enableAnimation: true,
		dragMode: false,
		isMounted: false,
	}),
	computed: {
		containerClasses(): Array
		{
			return [
				{
					'--multiple': this.uploader.isMultiple(),
					'--only-images': this.uploader.shouldAcceptOnlyImages(),
					'--many-items': this.items.length > 1,
				},
				`--${this.widgetOptions.size}`
			];
		},
		currentComponent()
		{
			if (this.items.length === 0 || this.dragOver)
			{
				if (this.dragOver)
				{
					this.dragMode = true;
				}

				return StackDropArea;
			}

			if (this.queueItems.length > 0)
			{
				return StackUpload;
			}

			if (this.items.some(isItemLoading))
			{
				return StackLoad;
			}

			return StackPreview;
		},
		currentComponentProps()
		{
			if (this.currentComponent === StackDropArea || this.currentComponent === StackLoad)
			{
				return {};
			}
			else if (this.currentComponent === StackUpload)
			{
				return {
					items: this.items,
					queueItems: this.queueItems,
				};
			}
			else if (this.currentComponent === StackPreview)
			{
				return {
					items: this.items,
				}
			}
		},
		error()
		{
			if (this.uploaderError)
			{
				return this.uploaderError;
			}
			else if (this.errorsCount > 0)
			{
				return Loc.getMessage('STACK_WIDGET_FILE_UPLOAD_ERROR');
			}

			return null;
		},
		errorsCount(): number
		{
			return this.items.reduce((errors, item) => {
				if (item.status === FileStatus.LOAD_FAILED || item.status === FileStatus.UPLOAD_FAILED)
				{
					return errors + 1;
				}
				else
				{
					return errors;
				}
			}, 0);
		},
		errorPopupOptions(): PopupOptions
		{
			return {
				bindElement: this.$refs.item,
				bindOptions: {
					position: 'top',
				},
				darkMode: true,
				offsetTop: 3,
				background: '#d2000d',
				contentBackground: 'transparent',
				contentColor: 'white',
				padding: this.uploaderError === null ? 10 : 20,
				closeIcon: this.uploaderError !== null,
			};
		},
	},
	watch: {
		currentComponent(newValue, oldValue): void
		{
			if (this.dragOver)
			{
				this.enableAnimation = false;
			}
			else if (oldValue === StackDropArea && this.dragMode)
			{
				this.enableAnimation = false;
			}
			else if (oldValue === StackPreview)
			{
				this.enableAnimation = false;
			}
			else
			{
				this.dragMode = false;
				this.enableAnimation = true;
			}
		},
		items: {
			handler() {
				if (this.items.length === 0 && this.popup)
				{
					this.popup.close();
				}
			},
			deep: true,
		}
	},
	created()
	{
		this.popup = null;

		this.adapter.subscribe('Uploader:onUploadStart', () => {
			this.items.forEach(item => {
				if (item.origin === FileOrigin.CLIENT && item.queued !== true)
				{
					item.queued = true;
					this.queueItems.push(item);
				}
			})
		});

		this.adapter.subscribe('Uploader:onUploadComplete', () => {
			this.queueItems = [];
		});

		this.adapter.subscribe('Item:onAdd', (event: BaseEvent) => {
			this.uploaderError = null;
			if (this.uploader.getStatus() === UploaderStatus.STARTED)
			{
				const item = event.getData().item;
				item.queued = true;
				this.queueItems.push(event.getData().item);
			}
		});

		this.adapter.subscribe('Item:onRemove', (event: BaseEvent) => {
			this.uploaderError = null;
			const item = event.getData().item;
			const position = this.queueItems.indexOf(item);
			if (position >= 0)
			{
				this.queueItems.splice(position, 1);
			}
		});
	},
	mounted()
	{
		this.uploader.assignBrowse(this.$refs['add-button']);
		this.isMounted = true;
	},
	methods: {
		showPopup()
		{
			if (!this.popup)
			{
				const id = 'stack-uploader-' + Text.getRandom().toLowerCase();
				this.popup = new Popup({
					width: 750,
					height: 400,
					draggable: true,
					titleBar: Loc.getMessage('STACK_WIDGET_POPUP_TITLE'),
					content: `<div id="${id}"></div>`,
					cacheable: false,
					closeIcon: true,
					closeByEsc: true,
					resizable: true,
					minWidth: 450,
					minHeight: 300,
					events: {
						onDestroy: () => {
							this.popup = null;
							this.popupContentId = null;
						},
					},
					buttons: [
						new CloseButton({ onclick: () => this.popup.close() }),
					]
				});

				this.popupContentId = `#${id}`;
			}

			this.popup.show();
		},
		abortUpload()
		{
			const items = Array.from(this.queueItems);
			this.queueItems = [];

			items.forEach(item => {
				this.uploader.removeFile(item.id);
			});
		},
		handlePopupDestroy(error)
		{
			if (this.uploaderError === error)
			{
				this.uploaderError = null;
			}
		}
	},
	// language=Vue
	template: `
		<div class="ui-uploader-stack-widget" :class="containerClasses" v-drop>
			<Teleport v-if="popupContentId !== null" :to="popupContentId">
				<TileList :items="items" />
			</Teleport>
			<div class="ui-uploader-stack-item" ref="item">
				<transition
					:leave-active-class="enableAnimation ? 'ui-uploader-stack-item-leave-active' : ''" 
					:leave-to-class="enableAnimation ? 'ui-uploader-stack-item-leave-to' : ''" 
					mode="out-in"
				>
					<keep-alive>
						<component
							:is="currentComponent"
							v-bind="currentComponentProps"
							@showPopup="showPopup"
							@abortUpload="abortUpload"
						/>
					</keep-alive>
				</transition>
			</div>
			<div v-if="uploader.isMultiple()" ref="add-button" class="ui-uploader-stack-add-btn"></div>
		</div>
		<ErrorPopup
			v-if="error !== null && isMounted"
			:error="error"
			:popup-options="errorPopupOptions"
			@onDestroy="handlePopupDestroy"
		/>
	`
};