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/rospirotorg.ru/bitrix/js/im/old-chat-embedding/component/search/src/ |
Upload File : |
import 'ui.design-tokens'; import 'ui.fonts.opensans'; import {RecentUsersCarousel} from './components/recent-users-carousel'; import {SearchResultSection} from './components/search-result-section'; import {SearchResultOpenlineItem} from './components/search-result-openline-item'; import {SearchResultNetworkItem} from './components/search-result-network-item'; import {SearchResultDepartmentItem} from './components/search-result-department-item'; import {SearchResultItem} from './components/search-result-item'; import {RecentLoadingState as LoadingState} from 'im.old-chat-embedding.component.elements'; import {SearchService} from './search-service'; import {SearchCache} from './search-cache'; import {SearchRecentList} from './search-recent-list'; import './css/search.css'; import {Runtime, Extension} from 'main.core'; import {SearchContextMenu} from './search-context-menu'; import {EventEmitter} from 'main.core.events'; import {ApplicationLayout, EventType} from 'im.old-chat-embedding.const'; import {SearchUtils} from './search-utils'; import {SearchItem} from './search-item'; /** * @bitrixEvents EventType.search.openContextMenu * @bitrixEvents EventType.dialog.errors.accessDenied * @bitrixEvents EventType.search.selectItem * @bitrixEvents EventType.recent.updateSearch */ export const Search = { components: { RecentUsersCarousel, SearchResultSection, LoadingState, SearchResultOpenlineItem, SearchResultNetworkItem, SearchResultDepartmentItem, SearchResultItem }, props: { searchQuery: { type: String, required: true }, searchMode: { type: Boolean, required: true } }, data: function() { return { isRecentLoading: false, isLocalLoading: false, isServerLoading: false, isNetworkLoading: false, currentServerQueries: 0, isNetworkButtonClicked: false, isNetworkAvailable: false, isNetworkSearchEnabled: true, result: { recent: new Map(), usersAndChats: new Map(), chatUsers: new Map(), departments: new Map(), openLines: new Map(), network: new Map(), } }; }, computed: { isEmptyState() { if (this.isServerLoading || this.isLocalLoading || this.isNetworkLoading) { return false; } const openLinesLayout = this.applicationLayout === ApplicationLayout.lines; if (!openLinesLayout && this.isNetworkSearchEnabled && !this.isNetworkButtonClicked && this.isServerSearch) { return false; } return this.result.usersAndChats.size === 0 && this.result.departments.size === 0 && this.result.chatUsers.size === 0 && this.result.openLines.size === 0 && this.result.network.size === 0; }, isLoadingState() { return (this.isServerLoading || this.isRecentLoading); }, isServerSearch() { return this.searchQuery.trim().length >= this.minTokenSize; }, needToShowNetworkSection() { return !this.isNetworkButtonClicked || this.result.network.size > 0; }, showSearchResult() { return this.searchQuery.trim().length > 0; }, isNetworkSearchCode(): boolean { return !!(this.searchQuery.length === 32 && /[\da-f]{32}/.test(this.searchQuery)); }, isNetworkAvailableForSearch(): boolean { if (this.applicationLayout !== ApplicationLayout.full) { return false; } if (!this.isNetworkAvailable) { return false; } return this.isNetworkSearchEnabled || this.isNetworkSearchCode; }, itemComponent: () => SearchResultItem, itemDepartmentComponent: () => SearchResultDepartmentItem, itemNetworkComponent: () => SearchResultNetworkItem, itemOpenlineComponent: () => SearchResultOpenlineItem, }, watch: { searchQuery(newValue, oldValue) { const newQuery = newValue.trim(); const previousQuery = oldValue.trim(); if (newQuery === previousQuery) { return; } this.startSearch(newQuery); }, searchMode(newValue, oldValue) { if (newValue === false && oldValue === true) // search switch off { this.isNetworkButtonClicked = false; } else if (newValue === true && oldValue === false) // search switch on { if (this.result.recent.size > 0) { return; } this.isRecentLoading = true; } this.searchService.loadRecentSearchFromServer().then(recentItems => { this.result.recent = recentItems; this.isRecentLoading = false; }); } }, created() { this.initSettings(); this.contextMenuManager = new SearchContextMenu(this.$Bitrix); const cache = new SearchCache(this.getCurrentUserId()); const recentList = new SearchRecentList(this.$Bitrix); this.searchService = SearchService.getInstance(this.$Bitrix, cache, recentList); this.searchOnServerDelayed = Runtime.debounce(this.searchOnServer, 1500, this); this.applicationLayout = this.$Bitrix.Application.get().params.layout; EventEmitter.subscribe(EventType.search.openContextMenu, this.onOpenContextMenu); EventEmitter.subscribe(EventType.dialog.errors.accessDenied, this.onDelete); EventEmitter.subscribe(EventType.search.selectItem, this.onSelectItem); EventEmitter.subscribe(EventType.recent.updateSearch, this.onPressEnterKey); this.loadInitialRecentFromCache(); }, beforeUnmount() { this.searchService.destroy(); this.contextMenuManager.destroy(); EventEmitter.unsubscribe(EventType.search.openContextMenu, this.onOpenContextMenu); EventEmitter.unsubscribe(EventType.dialog.errors.accessDenied, this.onDelete); EventEmitter.unsubscribe(EventType.search.selectItem, this.onSelectItem); EventEmitter.unsubscribe(EventType.recent.updateSearch, this.onPressEnterKey); }, methods: { loadInitialRecentFromCache() { // we don't need an extra request to get recent items while messenger initialization this.searchService.loadRecentSearchFromCache().then(recentItems => { this.result.recent = recentItems; }); }, initSettings() { const settings = Extension.getSettings('im.old-chat-embedding.component.search'); const defaultMinTokenSize = 3; this.minTokenSize = settings.get('minTokenSize', defaultMinTokenSize); this.isNetworkAvailable = settings.get('isNetworkAvailable', false); this.isNetworkSearchEnabled = settings.get('isNetworkSearchEnabled', true); this.isDepartmentsAvailable = settings.get('isDepartmentsAvailable', false); }, startSearch(searchQuery: string) { if (searchQuery.length > 0 && searchQuery.length < this.minTokenSize) { this.isLocalLoading = true; const queryBeforeRequest = searchQuery; this.searchService.searchLocal(searchQuery).then((localSearchResult: Map<string, SearchItem>) => { if (queryBeforeRequest !== this.searchQuery.trim()) { return; } this.result.usersAndChats = localSearchResult; this.isLocalLoading = false; }); } else if (searchQuery.length >= this.minTokenSize) { this.isServerLoading = true; const queryBeforeRequest = searchQuery; this.searchService.searchLocal(searchQuery).then((localSearchResult: Map<string, SearchItem>) => { if (queryBeforeRequest !== this.searchQuery.trim()) { return; } this.result.usersAndChats = localSearchResult; }).then(() => this.searchOnServerDelayed(searchQuery)); } else { this.cleanSearchResult(); } }, cleanSearchResult() { this.result.usersAndChats = new Map(); this.result.departments = new Map(); this.result.chatUsers = new Map(); this.result.network = new Map(); this.result.openLines = new Map(); }, searchOnServer(query: string) { this.currentServerQueries++; this.isNetworkLoading = this.isNetworkButtonClicked; const config = { lines: true, }; if (this.applicationLayout === ApplicationLayout.full) { config.network = this.isNetworkAvailableForSearch && this.isNetworkButtonClicked; config.departments = !BX.MessengerProxy.isCurrentUserExtranet() && this.isDepartmentsAvailable; config.chats = true; } const queryBeforeRequest = query; this.searchService.searchOnServer(query, config).then((searchResultFromServer: Object) => { if (queryBeforeRequest !== this.searchQuery.trim()) { this.stopLoader(); return; } this.result.usersAndChats = this.mergeResults(this.result.usersAndChats, searchResultFromServer.usersAndChats); this.result.departments = searchResultFromServer.departments; this.result.chatUsers = searchResultFromServer.chatUsers; this.result.openLines = searchResultFromServer.openLines; this.result.network = searchResultFromServer.network; }).catch(error => { console.error(error); }).finally(() => { this.currentServerQueries--; this.stopLoader(); }); }, stopLoader() { if (this.currentServerQueries > 0) { return; } this.isNetworkLoading = false; this.isServerLoading = false; this.isLocalLoading = false; }, searchOnNetwork(query: string) { this.isNetworkLoading = true; const queryBeforeRequest = query; this.searchService.searchOnNetwork(query).then((searchResultFromServer: Map<string, SearchItem>) => { if (queryBeforeRequest !== this.searchQuery) { this.isNetworkLoading = false; return; } this.result.network = searchResultFromServer; this.isNetworkButtonClicked = true; this.isNetworkLoading = false; }); }, mergeResults(originalItems: Map<string, SearchItem>, newItems: Map<string, SearchItem>): Map<string, SearchItem> { const mergedMap = new Map(originalItems.entries()); newItems.forEach((newItemValue, newItemKey) => { if (!mergedMap.has(newItemKey)) { mergedMap.set(newItemKey, newItemValue); } }); return mergedMap; }, onOpenContextMenu({data: eventData}) { if (eventData.event.altKey && eventData.event.shiftKey) { return; } this.contextMenuManager.openMenu(eventData.item, eventData.event.currentTarget); }, onDelete({data: eventData}) { const {dialogId} = eventData; this.result.recent.delete(dialogId); this.result.usersAndChats.delete(dialogId); this.result.chatUsers.delete(dialogId); }, onScroll() { this.contextMenuManager.destroy(); }, onClickLoadNetworkResult() { this.searchOnNetwork(this.searchQuery); }, onSelectItem(event) { const {selectedItem, nativeEvent} = event.getData(); EventEmitter.emit(EventType.dialog.open, { dialogId: selectedItem.dialogId, chat: this.$store.getters['dialogues/get'](selectedItem.dialogId, true), user: this.$store.getters['users/get'](selectedItem.dialogId, true) }); if (!nativeEvent.altKey) { BX.MessengerProxy.clearSearchInput(); } }, onPressEnterKey(event) { if (event.data.keyCode !== 13) // enter { return; } const firstItem = this.getFirstItemFromSearchResults(); if (!firstItem) { return; } const selectedItem = { id: firstItem.getId(), entityId: firstItem.getEntityId(), dialogId: firstItem.getDialogId(), }; EventEmitter.emit( EventType.search.selectItem, { selectedItem: selectedItem, onlyOpen: firstItem.isOpeLinesType(), nativeEvent: {} } ); }, getFirstItemFromSearchResults(): ?string { if (!this.showSearchResult && this.result.recent.size > 0) { return SearchUtils.getFirstItemFromMap(this.result.recent); } if (this.result.usersAndChats.size > 0) { return SearchUtils.getFirstItemFromMap(this.result.usersAndChats); } if (this.result.chatUsers.size > 0) { return SearchUtils.getFirstItemFromMap(this.result.chatUsers); } if (this.result.openLines.size > 0) { return SearchUtils.getFirstItemFromMap(this.result.openLines); } return null; }, getCurrentUserId(): number { return this.$store.state.application.common.userId; } }, template: ` <div class="bx-messenger-search" @scroll="onScroll"> <div> <template v-if="!showSearchResult"> <RecentUsersCarousel /> <SearchResultSection :component="itemComponent" :items="result.recent" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_RECENT')" :showMoreButton="false" /> </template> <template v-if="showSearchResult"> <SearchResultSection v-if="result.usersAndChats.size > 0" :component="itemComponent" :items="result.usersAndChats" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_USERS_AND_CHATS')" :min-items:="20" :max-items="50" /> <template v-if="!isLoadingState && isServerSearch"> <SearchResultSection v-if="result.chatUsers.size > 0" :component="itemComponent" :items="result.chatUsers" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_CHAT_USERS')" :min-items:="5" :max-items="20" /> <SearchResultSection v-if="result.departments.size > 0" :component="itemDepartmentComponent" :items="result.departments" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_DEPARTMENTS')" :min-items:="5" :max-items="20" /> <SearchResultSection v-if="result.openLines.size > 0" :component="itemOpenlineComponent" :items="result.openLines" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_OPENLINES')" :min-items:="5" :max-items="20" /> <template v-if="isNetworkAvailableForSearch"> <SearchResultSection v-if="needToShowNetworkSection" :component="itemNetworkComponent" :items="result.network" :title="$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_NETWORK')" :min-items:="5" :max-items="20" /> <template v-if="!isNetworkButtonClicked"> <div v-if="!isNetworkLoading" @click="onClickLoadNetworkResult" class="bx-im-search-network-button" > {{$Bitrix.Loc.getMessage('IM_SEARCH_SECTION_NETWORK_BUTTON_MSGVER_1')}} </div> <div v-else class="bx-search-network-loader-wrapper"> <div class="bx-search-loader bx-search-loader-large-size"></div> </div> </template> </template> </template> <div v-if="isEmptyState" class="bx-im-search-not-found-wrapper"> <div class="bx-im-search-not-found-icon"></div> <div class="bx-im-search-not-found-title">{{ $Bitrix.Loc.getMessage('IM_SEARCH_RESULT_NOT_FOUND') }}</div> <div class="bx-im-search-not-found-title"> {{ $Bitrix.Loc.getMessage('IM_SEARCH_RESULT_NOT_FOUND_DESCRIPTION') }} </div> </div> </template> <LoadingState v-if="isLoadingState" /> </div> </div> ` };