Current Path : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/js/landing/backend/src/ |
Current File : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/js/landing/backend/src/backend.js |
import {Uri, Cache, Loc, Reflection, Type, Http, ajax, Text} from 'main.core'; import {Env} from 'landing.env'; import type {Block, Landing, Site, Template, CreatePageOptions, SourceResponse, PreparedResponse} from './types'; let additionalRequestCompleted = true; /** * @memberOf BX.Landing */ export class Backend { static +instance: Backend = null; static getInstance(): Backend { if (!Backend.instance) { Backend.instance = new Backend(); } return Backend.instance; } static makeResponse(xhr: XMLHttpRequest, sourceResponse: SourceResponse = {}): PreparedResponse { const type = (() => { if (Type.isStringFilled(sourceResponse.type)) { return sourceResponse.type; } if (Type.isPlainObject(sourceResponse) && Object.values(sourceResponse).length > 0) { const allSuccess = Object.values(sourceResponse).every((item) => { return item.type === 'success'; }); if (allSuccess) { return 'success'; } } if (Type.isArray(sourceResponse)) { return 'other'; } return 'error'; })(); if (type === 'other') { return sourceResponse; } return { result: null, type, ...sourceResponse, status: xhr.status, authorized: xhr.getResponseHeader('X-Bitrix-Ajax-Status') !== 'Authorize', }; } static request({url, data}): Promise<any, any> { return new Promise((resolve, reject) => { const fd = data instanceof FormData ? data : Http.Data.convertObjectToFormData(data); const xhr = ajax({ method: 'POST', dataType: 'json', url, data: fd, start: false, preparePost: false, onsuccess: (sourceResponse) => { const response = Backend.makeResponse(xhr, sourceResponse); if ( Type.isStringFilled(response.sessid) && Loc.getMessage('bitrix_sessid') !== response.sessid && additionalRequestCompleted ) { Loc.setMessage('bitrix_sessid', response.sessid); additionalRequestCompleted = false; const newData = {...data, sessid: Loc.getMessage('bitrix_sessid')}; Backend .request({url, data: newData}) .then((newResponse) => { additionalRequestCompleted = true; resolve(newResponse); }) .catch((newResponse) => { additionalRequestCompleted = true; reject(newResponse); }); return; } if (!Type.isPlainObject(response)) { resolve(response); return; } if ( response.type === 'error' || response.authorized === false ) { if (response.authorized === false) { top.window.location.reload(); } else { reject(response); } return; } resolve(response); }, onfailure: (sourceResponse) => { if (sourceResponse === 'auth') { top.window.location.reload(); } else { reject( Backend.makeResponse(xhr, sourceResponse), ); } }, }); xhr.send(fd); }); } cache = new Cache.MemoryCache(); getControllerUrl(): string { return this.cache.remember('controllerUrl', () => { const uri = new Uri('/bitrix/tools/landing/ajax.php'); uri.setQueryParams({ site: Loc.getMessage('SITE_ID') || undefined, type: this.getSitesType(), }); return uri.toString(); }); } getSiteId(): number { return this.cache.remember('siteId', () => { const landing = Reflection.getClass('BX.Landing.Main'); if (landing) { const instance = landing.getInstance(); if ( 'options' in instance && 'site_id' in instance.options && !Type.isUndefined(instance.options.site_id) ) { return instance.options.site_id; } } return -1; }); } getLandingId(): number { return this.cache.remember('landingId', () => { const landing = Reflection.getClass('BX.Landing.Main'); if (landing) { return landing.getInstance().id; } return -1; }); } getSitesType(): 'PAGE' | 'STORE' { return this.cache.remember('siteType', () => { return Env.getInstance().getType(); }); } action( action: string, data: {[key: string]: any} = {}, queryParams = {}, uploadParams = {}, ): Promise<{[key: string]: any}, any> { if (!queryParams.site_id) { queryParams.site_id = this.getSiteId(); } const requestBody = { sessid: Loc.getMessage('bitrix_sessid'), action: uploadParams.action || action.replace('Landing\\Block', 'Block'), data: {...data, uploadParams, lid: data.lid || this.getLandingId()}, }; const uri = new Uri(this.getControllerUrl()); uri.setQueryParams({ action: requestBody.action, ...queryParams, }); return Backend .request({ url: uri.toString(), data: requestBody, }) .then((response) => { if ( requestBody.action === 'Block::updateNodes' || requestBody.action === 'Block::removeCard' || requestBody.action === 'Block::cloneCard' || requestBody.action === 'Block::addCard' || requestBody.action === 'Block::updateStyles' ) { // eslint-disable-next-line BX.Landing.UI.Panel.StatusPanel.getInstance().update(); } BX.onCustomEvent( BX.Landing.PageObject.getRootWindow(), 'BX.Landing.Backend:action', [action, data] ); /*if (!response.result) { BX.Landing.ErrorManager.getInstance().add({ type: 'error' }); }*/ return response.result; }) .catch((err) => { if ( requestBody.action !== 'Landing::downBlock' && requestBody.action !== 'Landing::upBlock' ) { if ( requestBody.action !== 'Block::getById' && requestBody.action !== 'Block::publication' && requestBody.action !== 'Landing::move' && requestBody.action !== 'Landing::copy' && requestBody.action !== 'Landing::publication' && requestBody.action !== 'Site::publication' && requestBody.action !== 'Site::moveFolder' && requestBody.action !== 'Site::markDelete' && requestBody.action !== 'Vk::getVideoInfo' ) { const error = Type.isString(err) ? {type: 'error'} : err; err.action = requestBody.action; // eslint-disable-next-line BX.Landing.ErrorManager.getInstance().add(error); } return Promise.reject(err); } }); } batch(action, data = {}, queryParams = {}): Promise<{[key: string]: any}, any> { queryParams.site_id = this.getSiteId(); const requestBody = { sessid: Loc.getMessage('bitrix_sessid'), action: action.replace('Landing\\Block', 'Block'), data: {lid: data.lid || this.getLandingId()}, batch: data, }; const uri = new Uri(this.getControllerUrl()); uri.setQueryParams({ action: requestBody.action, ...queryParams, }); return Backend .request({ url: uri.toString(), data: requestBody, }) .then((response) => { // eslint-disable-next-line BX.Landing.UI.Panel.StatusPanel.getInstance().update(); BX.onCustomEvent( BX.Landing.PageObject.getRootWindow(), 'BX.Landing.Backend:batch', [action, data] ); /*if (!response.result) { BX.Landing.ErrorManager.getInstance().add({ type: 'error' }); }*/ return response; }) .catch((err) => { if ( requestBody.action !== 'Landing::downBlock' && requestBody.action !== 'Landing::upBlock' ) { if (requestBody.action !== 'Block::getById') { const error = Type.isString(err) ? {type: 'error'} : err; error.action = requestBody.action; // eslint-disable-next-line BX.Landing.ErrorManager.getInstance().add(error); } return Promise.reject(err); } }); } upload(file: File | Blob, uploadParams = {}): Promise<{[key: string]: any}, any> { const formData = new FormData(); formData.append('sessid', Loc.getMessage('bitrix_sessid')); formData.append('picture', file, file.name); if ('block' in uploadParams) { formData.append('action', 'Block::uploadFile'); formData.append('data[block]', uploadParams.block); } if ('lid' in uploadParams) { formData.set('action', 'Landing::uploadFile'); formData.append('data[lid]', uploadParams.lid); } if ('id' in uploadParams) { formData.set('action', 'Site::uploadFile'); formData.append('data[id]', uploadParams.id); } if ('temp' in uploadParams) { formData.append('data[temp]', true); } const uri = new Uri(this.getControllerUrl()); uri.setQueryParams({ action: formData.get('action'), site_id: this.getSiteId(), }); if (uploadParams.context) { uri.setQueryParam('context', uploadParams.context); } return Backend .request({ url: uri.toString(), data: formData, }) .then((response) => response.result) .catch((err) => { const error = Type.isString(err) ? {type: 'error'} : err; error.action = 'Block::uploadFile'; // eslint-disable-next-line BX.Landing.ErrorManager.getInstance().add(error); return Promise.reject(err); }); } getSites({filter = {}} = {}): Promise<Array<Site>> { return this.cache.remember(`sites+${JSON.stringify(filter)}`, () => { return this .action('Site::getList', { params: { filter, order: {ID: 'DESC'} }, }) .then((response) => response); }); } getLandings({siteId = []}: {siteId?: number | Array<number>} = {}, filter: {}): Promise<Array<Landing>> { let skipFilter = false; if (!BX.Type.isPlainObject(filter)) { filter = {}; skipFilter = true; } const ids = Type.isArray(siteId) ? siteId : [siteId]; filter.SITE_ID = ids; const getBathItem = (id) => ({ action: 'Landing::getList', data: { params: { filter: (() => { if (skipFilter) { return { SITE_ID: id, DELETED: 'N', FOLDER: 'N', }; } return filter; })(), order: {ID: 'DESC'}, get_preview: true, check_area: 1, }, }, }); const prepareResponse = (response) => { return response.reduce((acc, item) => { return [...acc, ...item.result]; }, []); }; return this.cache.remember(`landings+${JSON.stringify(ids)}`, () => { if (ids.filter((id) => !Type.isNil(id)).length === 0) { return this.getSites() .then((sites) => { const data = sites.map((site) => getBathItem(site.ID)); return this.batch('Landing::getList', data); }) .then((response) => prepareResponse(response)) .then((response) => { response.forEach((landing) => { this.cache.set(`landing+${landing.ID}`, Promise.resolve(landing)); }); }); } const data = ids.map((id) => getBathItem(id)); return this.batch('Landing::getList', data) .then((response) => prepareResponse(response)) .then((response) => { response.forEach((landing) => { this.cache.set(`landing+${landing.ID}`, Promise.resolve(landing)); }); return response; }); }); } getLanding({landingId}: {landingId: string}): Promise<Landing> { return this.cache.remember(`landing+${landingId}`, () => { return this .action('Landing::getList', { params: { filter: {ID: landingId}, get_preview: true, }, }) .then((response) => { if (Type.isArray(response) && response.length > 0) { return response[0]; } return null; }); }); } getBlocks({landingId}: {landingId: string}): Promise<Array<Block>> { return this.cache.remember(`blocks+${landingId}`, () => { return this .action('Block::getList', { lid: landingId, params: { get_content: true, edit_mode: true, }, }) .then((blocks) => { blocks.forEach((block) => { this.cache.set(`block+${block.id}`, Promise.resolve(block)); }); return blocks; }); }); } getBlock({blockId}: {blockId: string}): Promise<Block> { return this.cache.remember(`blockId+${blockId}`, () => { return this.action('Block::getById', { block: blockId, params: { edit_mode: true, }, }); }); } getTemplates({type = 'page', filter = {}} = {}): Promise<Array<Template>> { return this.cache.remember(`templates+${JSON.stringify(filter)}`, () => { return this .action('Demos::getPageList', {type, filter}) .then((response) => Object.values(response)); }); } getDynamicTemplates(sourceId: string = ''): Promise<Array<Template>> { return this.cache.remember(`dynamicTemplates:${sourceId}`, () => { return this.getTemplates({filter: {section: `dynamic${sourceId ? `:${sourceId}` : ''}`}}); }); } createPage(options: CreatePageOptions = {}) { const envOptions = Env.getInstance().getOptions(); const { title, siteId = envOptions.site_id, siteType = envOptions.params.type, code = Text.getRandom(16), blockId, menuCode, folderId, } = options; const templateCode = (() => { const {theme} = envOptions; if ( Type.isPlainObject(theme) && Type.isArray(theme.newPageTemplate) && Type.isStringFilled(theme.newPageTemplate[0]) ) { return theme.newPageTemplate[0]; } return 'empty'; })(); const requestBody = { siteId, code: templateCode, fields: { TITLE: title, CODE: code, //@todo: refactor ADD_IN_MENU: (siteType === 'KNOWLEDGE' || siteType === 'GROUP') ? 'Y' : 'N' }, }; if (Type.isNumber(blockId) && Type.isString(menuCode)) { requestBody.fields.BLOCK_ID = blockId; requestBody.fields.MENU_CODE = menuCode; } if (Type.isNumber(folderId)) { requestBody.fields.FOLDER_ID = folderId; } return this.action('Landing::addByTemplate', requestBody); } }