chat_ui/components/chat/components/Group.vue
2025-03-11 13:45:25 +03:30

2504 lines
81 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="menu-bar__content home-list p-3"
:class="[{ mini: sidebarListStatusGetter }]"
>
<!-- <div class="menu-bar__content home-list p-3"
v-if="showMainpag"
> -->
<div class="groups-header" :class="{ ' border-bottom mb-3': !showSearch }">
<div class="right-icons d-flex">
<button-component
@click="sidebarCollapsedSetter(false)"
classes="footer-menu-item-btn p-0 toggle-menu-bar"
buttonText=""
>
<svg class="icon icon-menu">
<use xlink:href="#icon-menu"></use>
</svg>
</button-component>
<button-component
v-if="sidebarListStatusGetter"
@click="SET_SIDEBAR_LIST_STATUS"
classes="footer-menu-item-btn p-0 toggle-list d-flex"
buttonText=""
>
<span
:style="{
transform: `rotateY(${
sidebarListStatusGetter ? '180deg' : '0deg'
} )`,
}"
class="tavasi tavasi-Component-71--1"
></span>
</button-component>
<!-- <Breadcrumbs class="m-0" /> -->
<svg v-if="$route.name == 'lobbies'" class="icon icon-lobby">
<use xlink:href="#icon-lobby"></use>
</svg>
<svg v-if="$route.name == 'unReads'" class="icon icon-Component-112--1">
<use xlink:href="#icon-Component-112--1"></use>
</svg>
<svg v-if="$route.name == 'groups'" class="icon icon-groups">
<use xlink:href="#icon-groups"></use>
</svg>
<svg v-if="$route.name == 'privates'" class="icon icon-personal">
<use xlink:href="#icon-personal"></use>
</svg>
<span class="group-name"> {{ $t($route.name) }}</span>
</div>
<div class="left-icons">
<div v-if="$route.name != 'lobbies'">
<button
@click.prevent="showSearchs()"
type="button"
class="btn px-1 px-xl-0 toggle-search"
:class="{ 'is-active': showSearch }"
>
<svg v-if="!showSearch" class="icon icon-Component-198--1">
<use xlink:href="#icon-Component-198--1"></use>
</svg>
<!-- <span
id="showSearchs"
class="btn tavasi tavasi-Component-198--1"
></span> -->
<svg v-else class="icon icon-search_off">
<use xlink:href="#icon-search_off"></use>
</svg>
</button>
</div>
<div v-if="$route.name == 'groups' || $route.name == 'lobbies'">
<button
@click="showGroupFilter()"
type="button"
class="btn px-1 px-xl-0 toggle-filter"
:class="{ 'is-active': isGroupFilterActive }"
>
<svg
style="width: 1.3em"
v-if="isGroupFilterActive"
class="icon icon-clear-filter"
>
<use xlink:href="#icon-clear-filter"></use>
</svg>
<svg style="width: 1.3em" v-else class="icon icon-filter">
<use xlink:href="#icon-filter"></use>
</svg>
</button>
</div>
<!-- <user-avatar-dropdown></user-avatar-dropdown> -->
<button-component
@click="SET_SIDEBAR_LIST_STATUS"
classes="footer-menu-item-btn p-0 toggle-sidebar"
buttonText=""
>
<!-- <span class="tavasi tavasi-Component-71--1"></span> -->
<svg class="icon icon-Component-71--1">
<use xlink:href="#icon-Component-71--1"></use>
</svg>
</button-component>
</div>
</div>
<div v-if="showSearch" class="home-list__header p-0">
<div class="search-main" ref="search">
<!-- <button class="button-search open" @click="showSearchs()">
<span class="tavasi tavasi-Component-21--1"></span>
</button> -->
<form class="search-filter" role="search" @submit.prevent="sendQuery">
<div class="mb-3">
<div class="input-group">
<div class="input-group-append">
<span class="tavasi tavasi-Component-198--1"></span>
</div>
<input
ref="search-input"
dir="rtl"
v-model.trim="searchText"
type="search"
required
class="form-control"
id="search-query"
placeholder="جستجو..."
name="search-query"
aria-label="جستجو در اسناد، عناوین و واژگان"
aria-describedby="basic-addon1"
size="50"
@keyup="sendQuery()"
@keydown="onKeyDown()"
/>
<button
v-if="searchText.length"
@click="clearSearchAndGetList"
type="button"
class="btn clear-search p-0"
>
<svg class="icon icon-Component-294--1">
<use xlink:href="#icon-Component-294--1"></use>
</svg>
</button>
<div class="input-group-prepend">
<button
class="btn dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
{{ searchInCurrentGroup ? "جاری" : "همه" }}
</button>
<div class="dropdown-menu">
<button
type="button"
:class="{ active: !searchInCurrentGroup }"
class="dropdown-item"
@click="searchIn(false)"
>
همه
</button>
<button
type="button"
:class="{ active: searchInCurrentGroup }"
class="dropdown-item"
@click="searchIn(true)"
>
جاری
</button>
</div>
</div>
</div>
<!-- <button
@click.prevent="showSearchs()"
type="button"
class="btn close-search p-0 pe-1"
>
<svg class="icon icon-Component-71--1">
<use xlink:href="#icon-Component-71--1"></use>
</svg>
</button> -->
<small v-if="searchInCurrentGroup && listGetter">
جستجو در :
{{ listGetter?.title }}
</small>
</div>
<ul class="nav nav-tabs">
<button
type="button"
@click.prevent="setSearchType('groups')"
:class="{ active: searchType == 'groups' }"
class="nav-link"
>
پیام ها
</button>
<button
type="button"
@click.prevent="setSearchType('titles')"
:class="{ active: searchType == 'titles' }"
class="nav-link"
>
عناوین
</button>
</ul>
</form>
</div>
</div>
<div class="home-list__content" :class="{ loading: fetchingData }">
<div
class="d-flex align-items-center align-items-center border-bottom mb-3"
v-if="isGroupFilterActive"
>
<USelectMenu
v-model="selectedGroupFilter"
class="mb-3"
id="group-filter"
track-by="id"
placeholder="فیلتر گروه ها"
label="title"
:multiple="true"
:items="groupfilters"
:allow-empty="true"
:searchable="true"
:options-limit="300"
:limit="10"
:limit-text="limitText"
:max-height="350"
@select="filterGroupsBySection"
@remove="filterGroupsBySection(undefined)"
selectLabel=""
selectedLabel=""
deselectLabel=""
:close-on-select="true"
:clear-on-select="false"
:preserve-search="true"
>
<div slot="selection" slot-scope="{ values, search, isOpen }">
<span
class="multiselect__single"
v-if="values.length"
v-show="!isOpen"
>{{ values.length }} فیلتر</span
>
</div>
<div slot="noResult" slot-scope="{ values, search, isOpen }">
چیزی یافت نشد.
</div>
<div slot="noOptions" slot-scope="{ values, search, isOpen }">
فهرست خالی است.
</div>
<!-- <div slot="beforeList" slot-scope="{ values, search, isOpen }">
beforeList
</div>
<div slot="afterList" slot-scope="{ values, search, isOpen }">
afterList
</div> -->
<!-- <div slot="singleLabel" slot-scope="{ values, search, isOpen }">
singleLabel
</div>
-->
<!-- <div slot="singleLabel" slot-scope="props">
<span class="option__desc"
><span class="option__title">{{ props.option.title }}</span></span
></div
>
<div slot="option" slot-scope="props">
<div class="option__desc">
<span class="option__title">{{ props.option.lable }}</span>
</div>
</div> -->
</USelectMenu>
<!-- <button
@click="showGroupFilter()"
type="button"
class="btn group-filter-mobile mb-3"
>
<svg class="icon icon-clear-filter">
<use xlink:href="#icon-clear-filter"></use>
</svg>
</button> -->
</div>
<!-- @scroll.passive="loadMore" -->
<div
class="content scroll-needed"
:class="{ 'reset-height': showSearch }"
>
<the-content-loading
class="absolute-positioning"
v-if="fetchingData"
></the-content-loading>
<div v-else>
<div v-if="groups && groups.length">
<div v-if="$route.name == 'privates'">
<div
class="group-item"
v-for="(groupItem, index) in groups"
:key="index"
>
<div class="group-row enable-hover">
<div class="group-picture-container">
<!-- <context-menu
height="auto"
maxHeight="13em"
dataOffset="0,0"
style="position: static"
:list="groups"
:clickedItem="groupItem"
:contextMenu="commonContextMenu"
:parentComponent="'groups-panel'"
@remove-item="removeItem(groupItem)"
@other="makeLink(groupItem)"
>
</context-menu> -->
<img
class="group-picture"
@error="handleImageSrcOnError($event, false)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
<img
class="group-picture mini-mode"
@error="handleImageSrcOnError($event, false)"
@click.prevent="showMessages(groups, groupItem, index)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
</div>
<button
type="button"
@click.prevent="showMessages(groups, groupItem, index)"
:title="groupItem.unread ?? 0"
class="btn group-content"
:class="{ active: groupItem.active ?? false }"
>
<div class="group-title-container">
<h4 class="group-title" :title="groupItem.title">
<!-- <span class="tavasi tavasi-personal"></span> -->
<svg class="icon icon-personal">
<use xlink:href="#icon-personal"></use>
</svg>
{{ groupItem.title }}
</h4>
<span class="group-time">
{{ convertUnixToPersianDateTime(groupItem.created_at) }}
</span>
</div>
<div class="group-description-container">
<!-- <p class="group-description" :title="groupItem.desc">
{{ groupItem.desc }}
</p> -->
<p
class="group-description"
:title="groupItem?.last_message?.text"
>
{{ groupItem?.last_message?.text }}
</p>
<span
v-if="groupItem?.seen_messages?.count > 0"
class="group-unread-indicator badge badge-info"
>
{{ groupItem?.seen_messages?.count ?? 0 }}
</span>
</div>
</button>
</div>
</div>
</div>
<div v-else-if="$route.name == 'groups'">
<div
class="group-item"
v-for="(groupItem, index) in groups"
:key="index"
>
<div class="group-row enable-hover">
<div class="group-picture-container">
<!-- <context-menu
height="auto"
maxHeight="13em"
dataOffset="0,0"
style="position: static"
:list="groups"
:clickedItem="groupItem"
:contextMenu="commonContextMenu"
:parentComponent="'groups-panel'"
@remove-item="removeItem(groupItem)"
@edit-item="editItem(groups, groupItem, index)"
@join-to-group="openGroupSearchForm('groups', groupItem)"
@other="openInvitePostModal(groupItem)"
>
</context-menu> -->
<img
class="group-picture"
@error="handleImageSrcOnError($event, false)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
<img
class="group-picture mini-mode"
@error="handleImageSrcOnError($event, false)"
@click.prevent="showMessages(groups, groupItem, index)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
</div>
<button
type="button"
@click.prevent="showMessages(groups, groupItem, index)"
@click="showFilter()"
:title="groupItem.unread ?? 0"
class="btn group-content"
:class="{ active: groupItem.active ?? false }"
>
<div class="group-title-container">
<h4 class="group-title" :title="groupItem.title">
<!-- <span class="tavasi tavasi-groups"></span> -->
<svg class="icon icon-groups">
<use xlink:href="#icon-groups"></use>
</svg>
{{ groupItem.title }}
</h4>
<span class="group-time">
{{ convertUnixToPersianDateTime(groupItem.created_at) }}
</span>
</div>
<div class="group-description-container">
<!-- <p class="group-description" :title="groupItem.desc">
{{ groupItem.desc }}
</p> -->
<p
class="group-description"
:title="groupItem?.last_message?.text"
>
{{ groupItem?.last_message?.text }}
</p>
<span
v-if="groupItem?.seen_messages?.count > 0"
class="group-unread-indicator badge badge-info"
>
{{ groupItem?.seen_messages?.count ?? 0 }}
</span>
</div>
</button>
</div>
</div>
</div>
<div v-else-if="$route.name == 'unReads'">
<div
v-if="groups.length"
class="group-item unReads"
v-for="(groupItem, index) in groups"
:key="index"
>
<div class="group-row">
<div class="group-picture-container">
<!-- <context-menu
height="auto"
maxHeight="13em"
dataOffset="0,0"
style="position: static"
:list="groups"
:clickedItem="groupItem"
:contextMenu="commonContextMenu"
:parentComponent="'groups-panel'"
@remove-item="removeItem(groupItem)"
@edit-item="editItem(groups, groupItem, index)"
@other="makeLink(groupItem)"
>
</context-menu> -->
<img
class="group-picture"
@error="handleImageSrcOnError($event, false)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
<img
class="group-picture mini-mode"
@error="handleImageSrcOnError($event, false)"
@click.prevent="showMessages(groups, groupItem, index)"
:src="getGroupAvatar(groupItem)"
:alt="groupItem.title"
/>
</div>
<div
class="group-content p-2"
:class="{ active: groupItem.active ?? false }"
>
<div class="group-title-container">
<h4
@click.prevent="showMessages(groups, groupItem, index)"
class="group-title"
:title="groupItem.title"
>
<!-- <span class="tavasi tavasi-personal"></span> -->
{{ groupItem.title }}
</h4>
<div class="unreads-box">
<!-- message info -->
<button
type="button"
@click.prevent="
showMessages(groups, groupItem, index)
"
:title="groupItem.unread ?? 0"
class="btn unread-button"
>
<!-- <span class="unread-message-label">
پیام ها :
</span> -->
<svg class="icon icon-Component-112--1">
<use xlink:href="#icon-Component-112--1"></use>
</svg>
{{ groupItem.seen_messages?.count }}
</button>
<!-- replay info -->
<button
type="button"
@click.prevent="
showMessages(groups, groupItem, index)
"
:title="groupItem.unread ?? 0"
class="btn unread-button"
@click="showFilter()"
>
<!-- <span class="unread-message-label">
پاسخ ها :
</span> -->
<svg class="icon icon-reply">
<use xlink:href="#icon-reply"></use>
</svg>
{{ replayCount(groupItem.seen_replys) }}
</button>
</div>
<!-- <span class="group-time">
{{ convertUnixToPersianDateTime(groupItem.date_c) }}
</span> -->
</div>
<div class="group-description-container">
<p
@click.prevent="showMessages(groups, groupItem, index)"
class="group-description"
:title="groupItem?.last_message?.text"
>
{{ groupItem?.last_message?.text }}
</p>
<!-- <span class="group-unread-indicator badge badge-info">
{{ groupItem.seen.count }}
</span> -->
</div>
</div>
</div>
</div>
</div>
<div v-if="$route.name == 'lobbies'">
<div class="accordion" id="lobby-accordion">
<div
v-for="(lobby, key, index) in groups"
:key="key"
class="card border-0 group-item"
>
<div
class="card-header border-bottom-0 p-0"
:id="'heading' + key"
>
<button
type="button"
class="btn has-indicator group-row lobbies"
:title="lobby.title"
data-bs-toggle="collapse"
:data-bs-target="'#collapse' + key"
:aria-expanded="!collapseAll"
:class="[
{ collapsed: collapseAll },
{ ' enable-hover': isGroupAdmin(lobby) },
]"
:aria-controls="'collapse' + key"
>
<div class="group-picture-container">
<!-- <context-menu
height="auto"
maxHeight="13em"
v-if="isGroupAdmin(lobby)"
dataOffset="0,0"
style="position: static"
:list="groups"
:clickedItem="lobby"
:contextMenu="lobbiesParentContextMenu"
:parentComponent="'groups-panel'"
@remove-item="removeItem(lobby)"
@edit-item="editItem(groups, lobby, key)"
@other="makeLink(lobby)"
>
</context-menu> -->
<img
class="group-picture"
@error="handleImageSrcOnError($event, false)"
:src="getGroupAvatar(lobby)"
:alt="lobby.title"
/>
<img
class="group-picture mini-mode"
@error="handleImageSrcOnError($event, false)"
@click.prevent="showMessages(groups, lobby, index)"
:src="getGroupAvatar(lobby)"
:alt="lobby.title"
/>
</div>
<div
class="group-content"
:class="{ active: lobby.active ?? false }"
>
<div class="group-title-container">
<h4 class="group-title" :title="lobby.title">
<svg class="icon icon-lobby">
<use xlink:href="#icon-lobby"></use>
</svg>
<!-- <img
width="1em"
height="1em"
class=""
src="assets/common/img/lobby.svg"
alt="لابی"
/> -->
{{ lobby.title }}
</h4>
</div>
<div class="group-description-container">
<!-- <p class="group-description" :title="lobby.desc">
{{ lobby.desc }}
</p> -->
<p
class="group-description"
:title="lobby?.last_message?.text"
>
{{ lobby?.last_message?.text }}
</p>
</div>
</div>
</button>
<div class="unreads-box ms-2">
<!-- message info -->
<button
type="button"
@click.prevent="
lobbyParentShowMessages(groups, key, lobby)
"
:title="lobby.unread ?? 0"
class="btn unread-button"
>
<!-- <span class="unread-message-label">
پیام ها :
</span> -->
<svg class="icon icon-Component-112--1">
<use xlink:href="#icon-Component-112--1"></use>
</svg>
{{ lobby.seen_messages.count }}
</button>
<!-- replay info -->
<button
type="button"
@click.prevent="
lobbyParentShowMessages(groups, key, lobby)
"
:title="lobby.unread ?? 0"
class="btn unread-button"
@click="showFilter()"
>
<!-- <span class="unread-message-label">
پاسخ ها :
</span> -->
<svg class="icon icon-reply">
<use xlink:href="#icon-reply"></use>
</svg>
{{ replayCount(lobby.seen_replys) }}
</button>
</div>
</div>
<div
:id="'collapse' + key"
class="collapse"
:class="{ show: !collapseAll }"
:aria-labelledby="'heading' + key"
data-parent="#lobby-accordion"
>
<div class="card-body p-0">
<ul class="list-group list-group-flush">
<li
:key="j"
v-for="(group, j) in lobby.sub_groups"
class="list-group-item p-0"
>
<button
type="button"
@click.prevent="
lobbyShowMessages(groups, key, group, j)
"
class="btn group-row"
:title="group.title"
:class="{ 'enable-hover': isGroupAdmin(group) }"
>
<div class="group-picture-container">
<!-- <context-menu
height="auto"
maxHeight="13em"
v-if="isGroupAdmin(group)"
dataOffset="0,0"
style="position: static"
:list="groups"
:clickedItem="group"
:contextMenu="lobbiesChildContextMenu"
:parentComponent="'groups-panel'"
@edit-item="editItem(groups, group, j)"
@remove-item="removeItem(group)"
>
</context-menu> -->
<img
class="group-picture"
@error="handleImageSrcOnError($event, false)"
:src="getGroupAvatar(group)"
:alt="group.title"
/>
<img
class="group-picture mini-mode"
@error="handleImageSrcOnError($event, false)"
@click.prevent="
showMessages(groups, group, index)
"
:src="getGroupAvatar(group)"
:alt="group.title"
/>
</div>
<div
class="group-content"
:class="{ active: group.active ?? false }"
>
<div class="group-title-container">
<h4 class="group-title" :title="group.title">
<svg class="icon icon-groups">
<use xlink:href="#icon-groups"></use>
</svg>
{{ group.title }}
</h4>
<span class="group-time">
{{ group.created_at }}
</span>
</div>
<div class="group-description-container">
<p class="group-description">
{{
convertUnixToPersianDateTime(
group.created_at
)
}}
</p>
<span
v-if="group?.seen_messages?.count > 0"
class="group-unread-indicator badge badge-secondary"
>
{{ group?.seen_messages?.count ?? 0 }}
</span>
</div>
</div>
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<no-data v-else></no-data>
</div>
</div>
<more-pagination
v-if="groups?.length > 10"
@next-page="pageChanged"
></more-pagination>
<!-- create new message/group button -->
<div class="btn-group dropup actions-button" data-offset="10,10">
<button
type="button"
class="btn"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<!-- plus icon -->
<span class="tavasi tavasi-Component-133--1 plus-icon"></span>
<!-- muliply icon -->
<span class="tavasi tavasi-Component-294--1 multiply-icon"></span>
</button>
<div class="dropdown-menu dropdown-menu-right">
<!-- Dropdown menu links -->
<button
@click.prevent="openUserSearchForm('privates')"
class="btn dropdown-item new-message"
type="button"
>
<span class="tavasi tavasi-personal"></span>
پیام جدید
</button>
<button
@click.prevent="openCreateForm('groups')"
class="btn dropdown-item new-group"
type="button"
>
<span class="tavasi tavasi-groups"></span>
گروه جدید
</button>
<!-- <button
@click.prevent="openCreateForm('lobbies')"
class="btn dropdown-item new-lobby"
type="button"
>
<span class="tavasi tavasi-channel"></span>
تالار جدید
</button> -->
</div>
</div>
</div>
<!-- forms -->
<div class="create-forms" v-if="showForm">
<div class="close-form mb-5">
<button
@click.prevent="closeCreateForm()"
type="button"
class="btn d-flex align-items-center pe-0"
>
<span class="tavasi tavasi-Component-71--1 ms-2"></span>
بازگشت
</button>
</div>
<!-- private chat -->
<div v-if="showUserSearchForm">
<div class="form-group">
<label for="users">انتخاب کاربر: </label>
<USelectMenu
id="users"
track-by="user_id"
placeholder="جستجوی..."
:show-labels="false"
:items="foundUsers"
:searchable="true"
:internal-search="false"
:clear-on-select="false"
:close-on-select="true"
:options-limit="300"
:limit="3"
:limit-text="limitText"
:max-height="350"
:customLabel="
(item) => {
if (item.first_name || item.last_name)
return `${item.first_name} ${item.last_name}`;
return item.username;
}
"
@search-change="asyncFind"
@select="showUserPrivateMessages"
@close="resetFoundUsers"
>
<!-- <div slot="tag" slot-scope="{ option, remove }"
><span class="custom__tag"
><span>{{ option.name }}</span
><span class="custom__remove" @click="remove(option)"
>❌</span
></span
></div
> -->
<!-- <div slot="clear" slot-scope="props">
<div
class="multiselect__clear"
v-if="selectedCountries.length"
@mousedown.prevent.stop="clearAll(props.search)"
></div> </div
><span slot="noResult"
>Oops! No elements found. Consider changing the search
query.</span
> -->
</USelectMenu>
</div>
</div>
<!-- finding group -->
<div v-if="showGroupSearchForm">
<div class="form-group">
<label for="add-member-group">جستجوی گروه: </label>
<USelectMenu
id="add-member-group"
track-by="id"
label="title"
placeholder="جستجوی..."
:items="foundGroups"
:searchable="true"
:internal-search="false"
:clear-on-select="false"
:close-on-select="true"
:options-limit="300"
:limit="3"
:limit-text="limitText"
:max-height="350"
@search-change="asyncFindGroup"
@select="addGroupToSelectedGroup"
@close="resetFoundGroups"
>
</USelectMenu>
</div>
</div>
<!-- group/lobby create/edit form -->
<form v-if="showNewGroupForm" @submit.prevent="createGroup">
<div class="form-group">
<h6>فرم ایجاد گروه</h6>
</div>
<div v-if="formType == 'lobbies'" class="form-group">
<label for="exampleFormControlTextarea1">انتخاب گروه: </label>
<div class="d-flex align-items-center">
<USelectMenu
:allow-empty="true"
:searchable="true"
:close-on-select="true"
:show-labels="false"
label="title"
track-by="id"
placeholder="انتخاب تالار"
v-model="form.parent"
:items="groups"
:hide-selected="false"
:limit-text="
(count) => {
return `و ${count} تالار دیگر`;
}
"
:max-height="350"
>
</USelectMenu>
<div class="dropdown create-group-inner-form">
<button
type="button"
class="btn"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<!-- plus icon -->
<span class="tavasi tavasi-Component-133--1 plus-icon"></span>
<!-- muliply icon -->
<span
class="tavasi tavasi-Component-294--1 multiply-icon"
></span>
</button>
<div class="dropdown-menu">
<div class="form-group">
<label for="form-title">عنوان: </label>
<input
type="text"
class="form-control"
id="form-title"
aria-describedby="title"
v-model.trim="form.title"
/>
</div>
<div class="form-group">
<label for="form-desc">توضیحات: </label>
<textarea
class="form-control"
id="form-desc"
rows="3"
v-model.trim="form.desc"
></textarea>
</div>
<div class="dropdown-divider"></div>
<div class="d-flex justify-content-between text-center">
<a
@click.prevent="createNewGroup"
class="btn btn-primary"
href="#"
>ذخیره</a
>
<a
@click.prevent="createNewGroup"
class="btn btn-danger"
href="#"
>انصراف</a
>
</div>
</div>
</div>
</div>
</div>
<div
class="d-flex align-items-center align-items-center border-bottom mb-3"
v-if="isGroupFilterActive"
>
<USelectMenu
v-model="selectedGroupFilter"
class="mb-3"
id="group-filter"
track-by="id"
placeholder="فیلتر گروه ها"
label="title"
:multiple="true"
:items="groupfilters"
:allow-empty="true"
:searchable="true"
:options-limit="300"
:limit="10"
:limit-text="limitText"
:max-height="350"
@select="filterGroupsBySection"
@remove="filterGroupsBySection(undefined)"
selectLabel=""
selectedLabel=""
deselectLabel=""
:close-on-select="true"
:clear-on-select="false"
:preserve-search="true"
>
<div slot="selection" slot-scope="{ values, search, isOpen }">
<span
class="multiselect__single"
v-if="values.length"
v-show="!isOpen"
>{{ values.length }} فیلتر</span
>
</div>
<div slot="noResult" slot-scope="{ values, search, isOpen }">
چیزی یافت نشد.
</div>
<div slot="noOptions" slot-scope="{ values, search, isOpen }">
فهرست خالی است.
</div>
<!-- <div slot="beforeList" slot-scope="{ values, search, isOpen }">
beforeList
</div>
<div slot="afterList" slot-scope="{ values, search, isOpen }">
afterList
</div> -->
<!-- <div slot="singleLabel" slot-scope="{ values, search, isOpen }">
singleLabel
</div>
-->
<!-- <div slot="singleLabel" slot-scope="props">
<span class="option__desc"
><span class="option__title">{{ props.option.title }}</span></span
></div
>
<div slot="option" slot-scope="props">
<div class="option__desc">
<span class="option__title">{{ props.option.lable }}</span>
</div>
</div> -->
</USelectMenu>
<!-- <button
@click="showGroupFilter()"
type="button"
class="btn group-filter-mobile mb-3"
>
<svg class="icon icon-clear-filter">
<use xlink:href="#icon-clear-filter"></use>
</svg>
</button> -->
</div>
<div class="form-group">
<label for="group-type">نوع گروه:</label>
<select
class="form-control"
placeholder="نوع گروه"
id="group-type"
name="group-type"
v-model.number="form.is_public"
>
<option value="1" :true-value="1" :false-value="0">عمومی</option>
<option value="0" :true-value="1" :false-value="0">خصوصی</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputEmail1">عنوان: </label>
<input
type="text"
class="form-control"
id="exampleInputEmail1"
aria-describedby="title"
v-model.trim="form.title"
/>
<small id="emailHelp" class="form-text text-muted">
این متن فقط جنبه نمایشی دارد.
</small>
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">توضیحات: </label>
<textarea
class="form-control"
id="exampleFormControlTextarea1"
rows="3"
v-model.trim="form.desc"
></textarea>
</div>
<div class="form-group" v-if="form.id">
<div class="custom-checkbox-container position-static">
<div class="custom-control custom-checkbox">
<input
type="checkbox"
class="custom-control-input"
id="enable-add-user-to-group"
v-model="showAddUserForm"
/>
<label
class="custom-control-label"
for="enable-add-user-to-group"
>
افزودن کاربر به گروه
</label>
</div>
</div>
<!-- private chat -->
<div v-if="showAddUserForm">
<div class="form-group">
<label for="users">جستجوی کاربر: </label>
<USelectMenu
id="users"
track-by="user_id"
placeholder="جستجوی..."
:show-labels="false"
:items="foundUsers"
:searchable="true"
:internal-search="false"
:clear-on-select="false"
:close-on-select="true"
:options-limit="300"
:limit="3"
:limit-text="limitText"
:max-height="350"
:customLabel="
(item) => {
return `${item.first_name} ${item.last_name}`;
}
"
@search-change="asyncFind"
@select="addUserToGroup"
@close="resetFoundUsers"
>
</USelectMenu>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">
{{ form.id ? "بروزرسانی" : "ایجاد" }}
</button>
</form>
<!-- upload group/lobby avatar -->
<form v-if="showUploadAvatarForm">
<div class="form-group">
<h5>بارگزاری آواتار</h5>
</div>
<div class="form-group">
<div
class="image-uploader-container"
:class="{ 'hide-preview': hasImage }"
>
<client-only>
<ImageCropper
ref="file-uploader"
:preview="true"
:debug="1"
:maxWidth="300"
:maxHeight="300"
:maxSize="2"
:quality="1"
:autoRotate="true"
outputFormat="file"
accept="image/*"
:className="['fileinput', { 'fileinput--loaded': hasImage }]"
:capture="false"
@input="setImage"
>
<label class="upload-label" for="fileInput" slot="upload-label">
<img
v-if="
form.avatar?.length &&
(getFileExtension(form.avatar) == 'png' ||
getFileExtension(form.avatar) == 'jpg' ||
getFileExtension(form.avatar) == 'jpeg')
"
:src="form.avatar"
class="img-fluid"
:alt="form.avatar"
/>
<span
v-else-if="form.avatar?.length"
class="tavasi"
:class="`tavasi-${getFileExtension(form.avatar)}-file`"
></span>
<!-- replace image src with incoming src -->
<span v-else class="tavasi tavasi-cloud-upload"></span>
</label>
</ImageCropper>
</client-only>
</div>
</div>
<div class="form-group">
<button-component
@click="closeCreateForm()"
classes="btn-primary"
buttonText=""
>
تنظیم پیش فرض
</button-component>
</div>
</form>
</div>
<!-- <base-modal-v2
v-if="showInvitePostModal"
modalSize="modal-lg"
modalTitle="فرم ایجاد پست دعوت نامه"
:hasFooter="false"
@close="closeAndResetInvitePostModal"
>
<invite-post
@close="closeAndResetInvitePostModal"
:group="groupToInvite"
></invite-post>
</base-modal-v2> -->
</div>
</template>
<script>
import chatApi from "@chat/apis/chatApi";
import { mapState, mapActions } from "pinia";
import privatesContextMenu from "@chat/json/chat/json/privatesContextMenu.json";
import groupsContextMenu from "@chat/json/chat/json/groupsContextMenu.json";
import lobbiesChildContextMenu from "@chat/json/chat/json/lobbiesChildContextMenu.json";
import lobbiesParentContextMenu from "@chat/json/chat/json/lobbiesParentContextMenu.json";
import menu from "@chat/json/chat/json/menu.json";
import { useCommonStore } from "@stores/commonStore";
import { useChatStore } from "@chat/stores/chatStore";
export default {
name: "group",
setup() {
definePageMeta({
name: "group",
});
},
// mixins: [dragDropMoveMixin],
emits: ["list-changed", "list-item-changed", "update-messages"],
props: {
statusPagHedear: {
default: 1,
type: Number,
},
},
watch: {
$route: {
handler: function (to) {
if (this.getForwardItem) {
this.groupId = this.getForwardItem?.to.id;
}
this.isRedirectedFromOtherSystems = false;
this.resetPagination();
this.getAll(to.name);
},
deep: true,
// immediate: true,
},
},
beforeMount() {
const { $eventBus } = useNuxtApp();
// fired from chat.vue footer menu
$eventBus.on("open-list", (value) => {
this.showSidebarInMobile = value;
});
// listening to the chat-list component.
$eventBus.on("add-to-lobby", () => {
this.openGroupSearchForm("groups", this.listGetter);
});
$eventBus.on("copy-link", () => {
this.makeLink(this.listGetter);
});
$eventBus.on("open-remove-item-modal", () => {
this.removeItem(this.listGetter);
});
$eventBus.on("open-edit-item-form", () => {
const index = this.groups.findIndex(
(item) => item.id == this.listGetter?.id
);
this.editItem(this.groups, this.listGetter, index);
});
$eventBus.on("update-group-list", () => {
this.getAll(this.$route.name);
});
$eventBus.on("open-create-form", () => {
this.openCreateForm();
});
$eventBus.on("open-user-search-form", () => {
this.openUserSearchForm();
});
$eventBus.on("show-search", (newVal = true) => {
this.isGroupFilterActive = false;
this.showSearchs();
if (this.listGetter) this.searchInCurrentGroup = newVal;
});
$eventBus.on("show-filter", (newVal) => {
this.showSearch = false;
this.isGroupFilterActive = !this.isGroupFilterActive;
});
// const headers = {
// "app-id": import.meta.env.VITE_APP_ID,
// lang: import.meta.env.VITE_LANG,
// "app-version-code": import.meta.env.VITE_APP_VERSION,
// };
this.httpService = useNuxtApp()["$http"];
// this.authHttpService = new HttpService(import.meta.env.VITE_AUTH_BASE_URL);
// this.keyValueHttpService = new HttpService(
// import.meta.env.VITE_KEY_VALUE_BASE_URL
// );
if (this.$route.name == "privates")
this.commonContextMenu = privatesContextMenu;
if (this.$route.name == "groups")
this.commonContextMenu = groupsContextMenu;
if (this.$route.name == "lobbies") {
this.lobbiesParentContextMenu = lobbiesParentContextMenu;
this.lobbiesChildContextMenu = lobbiesChildContextMenu;
// this.commonContextMenu = lobbiesContextMenu;
}
if (this.$route.name == "unReads")
this.commonContextMenu = groupsContextMenu;
this.SET_LIST(undefined);
window.addEventListener("load", this.resizeAction);
window.addEventListener("resize", this.resizeAction);
},
mounted() {
this.SET_SIDEBAR_LIST_STATUS(false);
// check if redirected from other systems.
// or clicked on a copy link.
if (this.$route.query["group-id"]) {
this.groupId = this.$route.query["group-id"];
this.isRedirectedFromOtherSystems = true;
}
// check if redirected from other systems. clicked on the redirect button.
if (
this.$route.query["group-id"] &&
this.$route.query["check-by-reference"]
) {
this.groupId = this.$route.query["group-id"];
this.isRedirectedFromOtherSystems = true;
}
// when user forward a message.
if (this.getForwardItem) {
this.groupId = this.getForwardItem?.to?.id;
// this.isRedirectedFromOtherSystems = true;
}
this.getAll(this.$route.name);
// event fired from authMixin.js
const { $eventBus } = useNuxtApp();
$eventBus.on("authenticated-by-modal", (inviteId) => {
// const headers = {
// "app-id": import.meta.env.VITE_APP_ID,
// lang: import.meta.env.VITE_LANG,
// "app-version-code": import.meta.env.VITE_APP_VERSION,
// };
// this.authHttpService = new HttpService(import.meta.env.VITE_AUTH_BASE_URL);
this.isRedirectedFromOtherSystems = true;
this.redirectViaInviteLink = false;
history.pushState({}, document.title, this.$route.path);
this.addUserToGroupByInviteId(inviteId);
});
this.getGroupTypes();
},
beforeDestroy() {
window.removeEventListener("load", this.resizeAction);
window.removeEventListener("resize", this.resizeAction);
},
data() {
return {
// #region mehdi
showMainpag: true,
menu: menu,
// #endregion
typingTimer: 0,
doneTypingInterval: 500,
searchText: "",
searchType: "groups",
showAddUserForm: false,
busy: false,
foundGroups: [],
showUploadAvatarForm: false,
showGroupSearchForm: false,
groupsExpanded: false,
showNewGroupForm: false,
hasImage: false,
imageUrl: undefined,
uploading: false,
selectedUser: {},
foundUsers: [],
isLoading: false,
showUserSearchForm: false,
selectedGroup: undefined,
commonContextMenu: [],
fetchingData: false,
users: [],
prevSelectedItemIndex: 0,
prevParentSelectedItemIndex: 0,
convertGroupIntegerToString: {
groups: 1,
lobbies: 2,
privates: 3,
},
convertGroupStringToInteger: {
1: "groups",
2: "lobbies",
3: "privates",
},
showForm: false,
formType: 1,
form: {
id: undefined,
title: null,
desc: null,
type: 1,
is_public: 1,
message_state: 1,
members: [],
parent_id: undefined,
},
collapseAll: false,
groups: [],
showReplaceInput: true,
httpService: undefined,
authHttpService: undefined,
list: [],
pagination: {
pages: 0,
total: 0,
page: 1,
offset: 0, // page * per_page
limit: 15, //per_page
},
isRedirectedFromOtherSystems: false,
groupId: undefined,
messageId: undefined,
groupModel: {
id: undefined,
title: null,
desc: null,
avatar: null,
user: undefined,
icon_type: 1,
type: 0,
parent_id: 0,
refrence_id: 0,
subject_id: 0,
template_key: null,
admins: [],
created_at: undefined,
message_state: 0,
live_link: null,
live_button_pic: null,
live_start_time: null,
live_duration: null,
message_expire_time: 0,
file_type: 0,
last_message: {
id: undefined,
text: null,
user: undefined,
message_type: undefined,
date_c: undefined,
date_e: undefined,
},
attachment: {
name: null,
url: null,
ext: null,
size: undefined,
length: 0,
width: 0,
height: 0,
},
},
showSearch: false,
showInvitePostModal: false,
groupToInvite: {},
inviteLinkId: null,
redirectViaInviteLink: false,
searchInCurrentGroup: false,
groupfilters: [],
isGroupFilterActive: false, // toggle group filter
selectedGroupFilter: [], // group filter items.
// showSidebarInMobile: false, // close the panel.
};
},
computed: {
...mapState(useCommonStore, [
"userPermisionGetter",
"sidebarListStatusGetter",
]),
...mapState(useChatStore, ["listGetter", "getForwardItem"]),
},
methods: {
...mapActions(useChatStore, ["SET_LIST", "SET_SIDEBAR_LIST_STATUS"]),
handleImageSrcOnError({ target }, isUserAvatar = true) {
if (isUserAvatar) target.classList.add("human-avatar");
target.classList.add("error");
},
getGroupTypes() {
this.httpService
.postRequest("keyvalue/" + chatApi.forms.groupTypes)
.then((response) => {
this.groupfilters = response.data;
});
},
showGroupFilter() {
if (this.isGroupFilterActive) {
this.selectedGroupFilter = [];
this.resetPagination();
this.getAll(this.$route.name);
}
this.showSearch = false;
this.isGroupFilterActive = !this.isGroupFilterActive;
},
filterGroupsBySection(selectedLabel) {
this.resetPagination();
this.getAll(this.$route.name);
},
searchIn(newVal) {
this.searchInCurrentGroup = newVal;
this.searchInListAndChat();
},
hasPermission(permission) {
if (this.userPermisionGetter && this.userPermisionGetter.length)
return this.userPermisionGetter.includes(permission);
return false;
},
async makeLink(group) {
const params = new URLSearchParams({
["group-id"]: group.id,
});
const link =
location.origin + location.pathname + "?" + params.toString();
try {
await navigator.clipboard.writeText(link);
// mySwalToast({
// html: "لینک کپی شد.",
// });
} catch (err) {
// mySwalToast({
// html: "خطایی رخ داد.لطفا دوباره امتحان کنید.",
// });
}
},
resetFoundUsers() {
this.foundUsers = [];
this.fetchingData = false;
},
resetFoundGroups() {
this.foundGroups = [];
this.fetchingData = false;
},
sendQuery() {
// todo: show loading.
// todo: send query and show result.
// todo: hide loading.
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(() => {
this.searchInListAndChat();
}, this.doneTypingInterval);
},
onKeyDown() {
clearTimeout(this.typingTimer);
},
setSearchType(type) {
this.searchType = type;
this.searchInListAndChat();
},
clearSearchAndGetList() {
this.searchText = "";
this.groups = [];
},
async getAll(listType = "privates") {
if (this.fetchingData) return;
this.fetchingData = true;
let url = "message/" + chatApi[listType].list;
// let urlPrefix = chatApi.groups.list;
if (!(listType == "lobbies" || listType == "unReads"))
url += `${this.pagination.offset}/${this.pagination.limit}`;
// else if (listType == "lobbies") urlPrefix = chatApi.lobbies.list
// else if (listType == "privates") url += `${this.pagination.offset}/${this.pagination.limit}`;
// let url = urlPrefix + `${this.pagination.offset}/${this.pagination.limit}`
// const methodType = listType == "unReads" ? 'postRequest' : 'getRequest'
if (
this.$route.query["invite-id"] &&
this.$route.query["invite-id"].length
) {
url += "/" + this.$route.query["invite-id"];
this.inviteLinkId = this.$route.query["invite-id"];
this.redirectViaInviteLink = true;
}
const tempGroupFilter = this.selectedGroupFilter;
const payload = {
type: tempGroupFilter.map((item) => item.id),
};
return await this.httpService
.postRequest(url, payload)
.then((response) => {
this.groups = response.data;
this.users = response.users;
// this.pagination = { ...this.pagination, ...response.pagination };
if (this.redirectViaInviteLink) {
this.groups.forEach((group, index) => {
if (
group.invite_id == this.inviteLinkId ||
group.reference_id == this.inviteLinkId
) {
this.markActive(this.groups, index);
// group.active = true;
group["redirectViaInviteLink"] = true;
this.SET_LIST(group);
}
});
}
// when redirecting from other pages(jahat).
else if (this.isRedirectedFromOtherSystems) {
this.groups.forEach((group) => {
if (group.id == this.groupId) {
group.active = true;
this.SET_LIST(group);
} else if (group.reference_id == this.groupId) {
this.groupId = group.id;
group.active = true;
this.SET_LIST(group);
}
});
} else if (typeof this.getForwardItem == "object") {
let isExist = false;
if (this.$route.name == "privates") {
this.groups.forEach((group, index) => {
if (group.user == this.groupId) {
isExist = true;
group.active = true;
this.SET_LIST(group);
this.prevSelectedItemIndex = index;
}
});
} else if (this.$route.name == "groups") {
this.groups.forEach((group, index) => {
if (group.id == this.groupId) {
isExist = true;
group.active = true;
this.SET_LIST(group);
this.prevSelectedItemIndex = index;
}
});
}
// if current user does not already has open chat.
if (!isExist) {
this.groupModel = {
...this.groupModel,
...this.getForwardItem.from,
};
this.groupModel.active = true;
this.groups.push(this.groupModel);
this.SET_LIST(this.groupModel);
this.prevSelectedItemIndex = this.groups.length - 1;
}
this.$emit("update-messages");
} else {
this.groups.forEach((group, index) => {
if (this.listGetter?.id == group.id) {
this.markActive(this.groups, index);
}
});
}
return response;
})
.finally(() => {
this.fetchingData = false;
this.busy = false;
this.showMainpag = true;
});
},
setUser(list, responseUsers) {
list.forEach((listItem) => {
listItem.user = responseUsers.find(
(user) => user.user_id == listItem.user
);
});
},
createGroup($event, group_id = undefined) {
if (this.fetchingData) return;
this.fetchingData = true;
let url = "message/" + chatApi[this.$route.name].create;
// if (formType == "groups") urlPrefix =
// else if (formType == "lobbies") urlPrefix = chatApi.lobbies.create
// else if (formType == "privates") urlPrefix = chatApi.privates.create
// const payload = this.form
this.form.members = JSON.stringify(this.form.members);
this.form.admins = undefined;
this.form.group_id = group_id;
this.httpService
.formDataRequest(url, this.form)
.then((res) => {
this.fetchingData = false;
// this.getAll(this.formType);
this.form = res.data;
// mySwalToast({
// title: "",
// html: res.message,
// });
this.showNewGroupForm = false;
this.showUploadAvatarForm = true;
this.hasImage = false;
this.groups.unshift(this.form);
this.markActive(this.groups, 0);
this.SET_LIST(this.form);
})
.catch(({ response }) => {
if (
response.status == 403 &&
response.data?.meta &&
response.data?.meta[0]?.is_guest
) {
logout(this.$route);
this.fetchingData = false;
}
});
},
// remove group/remove lobby group
removeItem(groupItem) {
mySwalConfirm({
title: "هشدار!!!",
html: `از حذف <b>${groupItem?.title}</b> اطمینان دارید؟ `,
icon: "warning",
}).then((result) => {
if (result.isConfirmed) {
const payload = {
group_id: groupItem.id,
};
this.httpService
.postRequest("message/" + chatApi.groups.leave, payload)
.then((res) => {
// mySwalToast({
// html: res.message,
// icon: "success",
// });
this.resetPagination();
this.getAll(this.$route.name);
// groups.splice(index, 1);
});
}
});
},
editItem(groups, groupItem, index) {
this.form = groupItem;
this.markActive(groups, index);
this.openGroupCreateForm(this.convertGroupIntegerToString[this.formType]);
},
resetForm() {
this.form = {
id: undefined,
title: null,
desc: null,
type: 1,
message_state: 1,
members: [],
};
},
// loadMore($event) {
// // const listElm = document.querySelector("#last-search");
// const listElm = $event.target;
// const vm = this;
// if (vm.busy) return;
// if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
// this.busy = true;
// vm.pagination.offset = vm.pagination.offset + vm.pagination.limit;
// if (vm.pagination.total > vm.pagination.offset) {
// setTimeout(() => {
// vm.getListOnScroll();
// }, 300);
// } else {
// // vm.mySwalToast({
// // title: "کاربر محترم",
// // html: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
// // icon: "info",
// // position: "bottom-start",
// // });
// vm.busy = false;
// }
// } else vm.busy = false;
// },
pageChanged(paging) {
// let page = paging.pageNumber;
// page -= 1;
this.pagination.offset = this.pagination.page * this.pagination.limit;
this.pagination.limit = this.pagination.limit;
this.pagination.page++;
this.getListOnScroll();
},
getListOnScroll() {
const listType = this.$route.name;
let url = "message/" + chatApi[listType].list;
// let urlPrefix = chatApi.groups.list;
if (!(listType == "lobbies" || listType == "unReads"))
url += `${this.pagination.offset}/${this.pagination.limit}`;
// else if (listType == "lobbies") urlPrefix = chatApi.lobbies.list
// else if (listType == "privates") url += `${this.pagination.offset}/${this.pagination.limit}`;
// let url = urlPrefix + `${this.pagination.offset}/${this.pagination.limit}`
// const methodType = listType == "unReads" ? 'postRequest' : 'getRequest'
const tempGroupFilter = this.selectedGroupFilter;
const payload = {
type: tempGroupFilter.map((item) => item.id),
};
this.httpService
.postRequest(url, payload)
.then((response) => {
// this.pagination = { ...this.pagination, ...response.pagination };
this.groups = [...this.groups, ...response.data];
})
.finally(() => {
this.busy = false;
});
},
openUserSearchForm(formType = "privates") {
this.showForm = true;
this.showUserSearchForm = true;
this.formType = formType;
// this.loading = false;
// this.groupCreated = false;
},
openGroupSearchForm(formType = "groups", groupItem = undefined) {
this.showForm = true;
this.showGroupSearchForm = true;
this.formType = formType;
this.selectedGroup = groupItem;
},
openGroupCreateForm() {
this.showForm = true;
this.showNewGroupForm = true;
this.formType = "groups";
},
openCreateForm(formType, groupItem = undefined) {
// if (formType == 'privates')
// this.showUserSearchForm = true;
// else if (formType == 'groups')
this.showNewGroupForm = true;
this.selectedGroup = groupItem;
this.showForm = true;
this.formType = "groups";
this.loading = false;
},
closeCreateForm() {
this.showForm = false;
this.showNewGroupForm = false;
this.showGroupSearchForm = false;
this.showUserSearchForm = false;
this.showUploadAvatarForm = false;
this.loading = false;
this.resetForm();
// this.$router
// .push({
// name: this.formType,
// })
// .catch(() => {
this.resetPagination();
this.getAll(this.$route.name);
// });
},
closeCreateFormWithoutRedirect() {
this.showForm = false;
this.showNewGroupForm = false;
this.showGroupSearchForm = false;
this.showUserSearchForm = false;
this.showUploadAvatarForm = false;
this.loading = false;
},
resetPagination() {
this.pagination = {
pages: 0,
total: 0,
page: 1,
offset: 0, // page * per_page
limit: 15, //per_page
};
},
toggleSidebarMenu() {
this.$store.commit("TOGGLE_SIDEBAR_MENU");
},
markActive(groups, index) {
try {
if (this.prevSelectedItemIndex != index) {
this.$set(groups[this.prevSelectedItemIndex], "active", false);
}
this.prevSelectedItemIndex = index;
this.$set(groups[index], "active", true);
} catch (err) {
this.prevSelectedItemIndex = undefined;
}
},
resizeAction(event) {
return window.outerWidth < 992;
},
showMessages(groups, groupItem, index) {
const { $eventBus } = useNuxtApp();
$eventBus.emit("close-replays");
// for mobile mode, closes the panel.
if (this.resizeAction()) {
this.SET_SIDEBAR_LIST_STATUS();
this.showSidebarInMobile = false;
}
this.markActive(groups, index);
this.SET_LIST(groupItem);
// اگر کاربر از طریق لینک دعوت امد،و بر روی گروه دیگری کلیک کرد،
// برای دریافت درست پاسخ ها بایستی invite-id
// در روت رو اصلاح کرد
if (groupItem.redirectViaInviteLink)
this.$set(this.$route.query, "invite-id", this.listGetter?.invite_id);
else this.$set(this.$route.query, "invite-id", undefined);
if (!this.redirectViaInviteLink)
history.pushState(
{},
document.title,
this.$route.path + "#chat-item-" + groupItem.id
);
this.isRedirectedFromOtherSystems = false;
this.redirectViaInviteLink = false;
this.$set(this.$route.query, "group-id", undefined);
this.$set(this.$route.query, "message-id", undefined);
// this.$route.query["group-id"] = undefined;
// this.$route.query["message-id"] = undefined;
if (groupItem.type == 0)
history.pushState(
{},
document.title,
this.$route.path + "#chat-item-" + groupItem.id
);
this.$emit("update-messages");
},
// lobby,lobbyIndex.sub_groups_item, childIndex
lobbyParentShowMessages(lobby, parentIndex, groupItem) {
// اگر تالارثابت باشه و کاربر بر روی گروه های تالار کلیک کند.
if (this.prevParentSelectedItemIndex == parentIndex) {
this.$set(
lobby[this.prevParentSelectedItemIndex].sub_groups[
this.prevSelectedItemIndex
],
"active",
false
);
}
// کاربر بر روی تالار دیگری کلیک کرده است.
else if (this.prevParentSelectedItemIndex != parentIndex) {
this.$set(
lobby[this.prevParentSelectedItemIndex].sub_groups[
this.prevSelectedItemIndex
],
"active",
false
);
}
this.prevParentSelectedItemIndex = parentIndex;
this.$set(lobby[parentIndex], "active", true);
this.SET_LIST(groupItem);
this.$emit("update-messages");
},
// lobby,lobbyIndex.sub_groups_item, childIndex
lobbyShowMessages(lobby, parentIndex, groupItem, index) {
// اگر تالارثابت باشه و کاربر بر روی گروه های تالار کلیک کند.
if (
this.prevParentSelectedItemIndex == parentIndex &&
this.prevSelectedItemIndex != index
) {
this.$set(
lobby[this.prevParentSelectedItemIndex].sub_groups[
this.prevSelectedItemIndex
],
"active",
false
);
}
// کاربر بر روی تالار دیگری کلیک کرده است.
else if (this.prevParentSelectedItemIndex != parentIndex) {
this.$set(
lobby[this.prevParentSelectedItemIndex].sub_groups[
this.prevSelectedItemIndex
],
"active",
false
);
}
this.prevSelectedItemIndex = index;
this.prevParentSelectedItemIndex = parentIndex;
this.$set(lobby[parentIndex].sub_groups[index], "active", true);
this.SET_LIST(groupItem);
this.$emit("update-messages");
},
// after finding the user, on select user event, show the user's messages
showUserPrivateMessages(user) {
user.user = user.user_id;
// user.id = user.user_id;
user.title = userFullname(user);
user.desc = null;
let res = this.groups.find((gfi) => gfi.user == user.user);
if (!res) this.groups.push(user);
this.SET_LIST(user);
this.groups.forEach((groupItem) => {
groupItem.active = false;
if (groupItem.user == user.id) groupItem.active = true;
});
this.closeCreateFormWithoutRedirect();
this.$emit("update-messages");
},
asyncFindGroup(query) {
// if (this.isLoading) return;
// this.isLoading = true;
if (query.trim().length) {
this.httpService
.getRequest("message/group/ve/search/1/" + query)
.then((response) => {
this.foundGroups = response.data ?? [];
})
.finally(() => {
// this.isLoading = false;
});
}
},
// add group to a group(making a lobby)
addGroupToSelectedGroup(comboSelectedGroup) {
if (this.fetchingData) return;
this.fetchingData = true;
let url = "message/" + chatApi[this.$route.name].parent;
if (comboSelectedGroup.parent_id) {
// mySwalToast({
// title: "",
// icon: "warning",
// html: "این گروه قبلا عضو تالاری شده است و امکان عضویت در تالار دوم را ندارد.",
// });
return;
}
const payload = {
parent_id: comboSelectedGroup.id,
group_id: this.selectedGroup.id,
};
this.httpService
.formDataRequest(url, payload)
.then((res) => {
// mySwalToast({
// title: "",
// html: res.message,
// });
this.closeCreateForm();
})
.finally(() => {
this.fetchingData = false;
});
},
// remove from lobby
removeGroupFromLobby(group) {
mySwalConfirm({
title: "هشدار!!!",
html: ` حذف <b>${group.title}</b> ?`,
icon: "warning",
}).then((result) => {
if (result.isConfirmed) {
if (this.fetchingData) return;
this.fetchingData = true;
let url = "message/" + chatApi[this.$route.name].delete;
const payload = {
group_id: group.id,
parent_id: 0,
};
this.httpService.formDataRequest(url, payload).then((res) => {
this.fetchingData = false;
// mySwalToast({
// html: res.message,
// });
this.resetPagination();
this.getAll("lobbies");
});
}
});
},
searchInListAndChat() {
let url = "message/message/get/search";
let contact_id = undefined;
let group_id = undefined;
let all_groups = false;
let all_contacts = false;
if (this.searchInCurrentGroup && this.$route.name == "privates") {
contact_id = [this.listGetter?.user];
}
if (this.searchInCurrentGroup && this.$route.name != "privates") {
group_id = [this.listGetter?.group_id ?? this.listGetter?.id];
}
if (!this.searchInCurrentGroup && this.$route.name == "privates") {
all_contacts = true;
}
if (!this.searchInCurrentGroup && this.$route.name != "privates") {
all_groups = true;
}
const payload = {
query: this.searchText,
title_only: this.searchType == "titles" ? 1 : 0,
group_id: group_id,
contact_id: contact_id,
all_groups: all_groups,
all_contacts: all_contacts,
limit: 500,
};
if (this.$route.name == "privates" && this.searchType == "titles") {
payload.group_id = this.searchInCurrentGroup
? [this.listGetter?.id]
: undefined;
this.findUser(payload);
} else {
this.httpService.postRequest(url, payload).then((response) => {
this.groups = response.data;
this.users = response.users;
this.pagination = { ...this.pagination, ...response.pagination };
if (this.searchText == "") {
this.groups = [];
}
});
}
},
findUser(query) {
const url = loginUrl() + "/user/suggestion";
this.httpService.postRequest(url, query).then((response) => {
response.data.forEach((i) => {
i["user"] = i.user_id;
i["title"] = i.full_name;
i["created_at"] = i.full_name;
i["title"] = i.full_name;
});
this.groups = response.data;
// this.users = response.users;
// this.pagination = { ...this.pagination, ...response.pagination };
if (this.searchText == "") {
this.groups = [];
}
});
},
replayCount(replays = []) {
let sum = 0;
replays.forEach((item) => {
sum += item.count;
});
return sum;
},
limitText(count) {
return `و ${count} کاربر دیگر`;
},
asyncFind(query) {
// if (this.isLoading) return;
// this.isLoading = true;
if (query.trim().length) {
this.httpService
.postRequest("login/user/suggestion", { query })
.then((response) => {
// this.isLoading = false;
this.foundUsers = response.data ?? [];
});
}
},
isGroupAdmin(comment) {
const isAdmin =
comment.admins.findIndex((user) => user == this.currentUser.user_id) >
-1;
return isAdmin;
},
getFileExtension(filename) {
const validtypes = [
"xlsx",
"xls",
"doc",
"docx",
"ppt",
"pptx",
"txt",
"pdf",
"jpg",
"png",
"jpeg",
];
const fileExtension = filename?.split(".").pop();
return validtypes.includes(fileExtension) ? fileExtension : "other";
},
setImage(file) {
this.hasImage = true;
this.imageUrl = file;
this.form.avatar = file.name;
this.saveFile(file);
},
saveFile() {
if (this.uploading) return;
this.uploading = true;
let url = "message/" + chatApi.groups.updateAvatar + this.form.id;
const formData = new FormData();
formData.append("file", this.$refs["file-uploader"].currentFile);
this.httpService
.postRequest(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => {
// mySwalToast({
// title: res.message,
// html: "",
// });
this.closeCreateForm();
// this.getAll();
})
.finally(() => {
this.uploading = false;
});
},
addUserToGroup(selectedUser, inviteId = undefined) {
if (this.fetchingData) return;
this.fetchingData = true;
let url = "message/" + chatApi.groups.addMember;
const payload = {
group_id: this.form.id,
members: [selectedUser.id],
};
this.httpService
.postRequest(url, payload)
.then((res) => {
// mySwalToast({
// title: "",
// html: res.message,
// });
// this.closeCreateForm();
// this.getAll();
})
.finally(() => {
this.resetFoundUsers();
this.fetchingData = false;
});
},
addUserToGroupByInviteId(inviteId) {
let url = "message/" + chatApi.groups.addMember;
const payload = {
members: [this.currentUser.user_id],
invite_id: inviteId,
};
this.httpService
.postRequest(url, payload)
.then((res) => {
// this.$route.query["invite-id"] = undefined;
this.$set(this.$route.query, "invite-id", undefined);
this.groupId = res.data.id;
this.resetPagination();
this.getAll(this.$route.name);
})
.catch((err) => {});
},
// #region mehdi
showFilter() {
this.showMainpag = !this.showMainpag;
},
showSearchs(currentGroup = false) {
this.searchInCurrentGroup = currentGroup;
this.showSearch = !this.showSearch;
this.isGroupFilterActive = false;
if (this.showSearch) {
this.groups = [];
// setTimeout(() => {
// this.$refs["search-input"]?.focus();
// }, 300);
} else {
this.resetPagination();
this.groups = this.getAll(this.$route.name);
}
// this.$refs.search.classList.toggle("hidean-search");
},
// #endregion
// #region invite post methods
openInvitePostModal(comment) {
this.groupToInvite = comment;
this.showInvitePostModal = true;
setTimeout(() => {
$("#base-modal").modal({
backdrop: "static",
keyboard: false,
show: true,
});
}, 200);
},
closeAndResetInvitePostModal() {
this.groupToInvite = {};
$("#base-modal").modal("hide");
setTimeout(() => {
this.showInvitePostModal = false;
}, 500);
},
// #endregion
},
components: {
ImageCropper: defineAsyncComponent(() =>
import("@components/other/ImageCropper.vue")
),
},
};
</script>