before delete 3software
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
|
||||
<div class="flex row q-ma-md justify-between">
|
||||
<div class="flex row q-ma-md justify-between" v-if="chats.length !== 0">
|
||||
<q-input
|
||||
v-model="search"
|
||||
clearable
|
||||
@@ -11,6 +11,7 @@
|
||||
:placeholder="$t('project_chats__search')"
|
||||
dense
|
||||
class="col-grow"
|
||||
v-if="chats.length !== 0"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="mdi-magnify" />
|
||||
@@ -18,26 +19,30 @@
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
<q-list bordered separator>
|
||||
|
||||
<q-list separator v-if="chats.length !== 0">
|
||||
<q-slide-item
|
||||
v-for="item in displayChats"
|
||||
:key="item.id"
|
||||
@right="handleSlide($event, item.id)"
|
||||
right-color="red"
|
||||
@click="goChat(item.invite_link)"
|
||||
>
|
||||
<template #right>
|
||||
<q-icon size="lg" name="mdi-link-off"/>
|
||||
</template>
|
||||
|
||||
<q-item
|
||||
:key="item.id"
|
||||
:clickable="false"
|
||||
clickable
|
||||
v-ripple
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-avatar rounded>
|
||||
<q-img v-if="item.logo" :src="item.logo"/>
|
||||
<pn-auto-avatar v-else :name="item.name"/>
|
||||
</q-avatar>
|
||||
<pn-auto-avatar
|
||||
:img="item.logo"
|
||||
:name="item.name"
|
||||
type="rounded"
|
||||
size="lg"
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold">
|
||||
@@ -47,14 +52,14 @@
|
||||
{{ item.description }}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="1">
|
||||
<div class = "flex justify-start items-center">
|
||||
<div class="q-mr-sm flex items-center">
|
||||
<q-icon name="mdi-account-outline" class="q-mx-sm"/>
|
||||
<span>{{ item.persons }}</span>
|
||||
<div class = "flex justify-start items-center no-wrap">
|
||||
<div class="q-mr-sm flex items-center no-wrap">
|
||||
<q-icon name="mdi-account-multiple-outline" class="q-mr-xs"/>
|
||||
<span>{{ item.user_count }}</span>
|
||||
</div>
|
||||
<div class="q-mx-sm flex items-center">
|
||||
<q-icon name="mdi-key" class="q-mr-sm"/>
|
||||
<span>{{ item.owner_id }} </span>
|
||||
<div class="q-mx-sm flex items-center no-wrap ellipsis" v-if="item.owner_id">
|
||||
<q-icon name="mdi-key" class="q-mr-xs"/>
|
||||
<span class="ellipsis">{{ usersStore.userNameById(item.owner_id) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</q-item-label>
|
||||
@@ -63,111 +68,130 @@
|
||||
</q-slide-item>
|
||||
</q-list>
|
||||
|
||||
<pn-onboard-btn
|
||||
v-if="chats.length === 0 && chatsInit"
|
||||
icon="mdi-chat-plus-outline"
|
||||
:message1="$t('project_chat__onboard_msg1')"
|
||||
:message2="$t('project_chat__onboard_msg2')"
|
||||
@click="showOverlay=true; fabState=true"
|
||||
/>
|
||||
<div
|
||||
class="flex column justify-center items-center w100"
|
||||
style="position: absolute; bottom: 0;"
|
||||
v-if="!chatsInit"
|
||||
>
|
||||
<q-linear-progress indeterminate />
|
||||
</div>
|
||||
</pn-scroll-list>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<q-page-sticky
|
||||
:style="{ zIndex: !showOverlay ? 'inherit' : '5100 !important' }"
|
||||
position="bottom-right"
|
||||
:offset="[18, 18]"
|
||||
:style="{ zIndex: !showOverlay ? 'inherit' : '5100 !important' }"
|
||||
position="bottom-right"
|
||||
:offset="[0, 18]"
|
||||
class="fix-fab-offset"
|
||||
>
|
||||
<transition
|
||||
appear
|
||||
enter-active-class="animated zoomIn"
|
||||
>
|
||||
<transition
|
||||
appear
|
||||
enter-active-class="animated slideInUp"
|
||||
<q-fab
|
||||
v-model="fabState"
|
||||
v-if="showFab"
|
||||
icon="add"
|
||||
color="brand"
|
||||
direction="up"
|
||||
vertical-actions-align="right"
|
||||
@click="showOverlay = !showOverlay"
|
||||
:disable="!tg.initData"
|
||||
>
|
||||
<q-fab
|
||||
v-if="showFab"
|
||||
icon="add"
|
||||
color="brand"
|
||||
direction="up"
|
||||
vertical-actions-align="right"
|
||||
@click="showOverlay = !showOverlay"
|
||||
<template #tooltip>
|
||||
<q-tooltip
|
||||
v-if="!tg.initData"
|
||||
anchor="center left" self="center end"
|
||||
style="width: calc(min(100vw, var(--body-width)) - 102px) !important;"
|
||||
>
|
||||
<q-fab-action
|
||||
v-for="item in fabMenu"
|
||||
:key="item.id"
|
||||
square
|
||||
clickable
|
||||
v-ripple
|
||||
class="bg-white change-fab-action"
|
||||
>
|
||||
<template #icon>
|
||||
<q-item class="q-pa-xs w100">
|
||||
<q-item-section avatar class="items-center">
|
||||
<q-avatar color="brand" rounded text-color="white" :icon="item.icon" />
|
||||
</q-item-section>
|
||||
{{ $t('project_chats_disabled_FAB')}}
|
||||
</q-tooltip>
|
||||
</template>
|
||||
<q-fab-action
|
||||
v-for="item in fabMenu"
|
||||
:key="item.id"
|
||||
square
|
||||
clickable
|
||||
v-ripple
|
||||
class="bg-white change-fab-action"
|
||||
@click="item.func()"
|
||||
>
|
||||
|
||||
<template #icon>
|
||||
<q-item class="q-pa-xs w100">
|
||||
<q-item-section avatar class="items-center">
|
||||
<q-avatar color="brand" rounded text-color="white" :icon="item.icon" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section class="items-start">
|
||||
<q-item-label class="fab-action-item">
|
||||
{{ $t(item.name) }}
|
||||
</q-item-label>
|
||||
<q-item-label caption class="fab-action-item">
|
||||
{{ $t(item.description) }}
|
||||
</q-item-label>
|
||||
<q-item-section class="items-start">
|
||||
<q-item-label class="fab-action-item">
|
||||
{{ $t(item.name) }}
|
||||
</q-item-label>
|
||||
<q-item-label caption class="fab-action-item">
|
||||
{{ $t(item.description) }}
|
||||
</q-item-label>
|
||||
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-fab-action>
|
||||
|
||||
</q-fab>
|
||||
</transition>
|
||||
</q-page-sticky>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-fab-action>
|
||||
</q-fab>
|
||||
</transition>
|
||||
</q-page-sticky>
|
||||
</div>
|
||||
|
||||
<pn-overlay v-if="showOverlay"/>
|
||||
<q-dialog v-model="showDialogDeleteChat" @before-hide="onDialogBeforeHide()">
|
||||
<q-card class="q-pa-none q-ma-none">
|
||||
<q-card-section align="center">
|
||||
<div class="text-h6 text-negative ">{{ $t('project_chat__delete_warning') }}</div>
|
||||
</q-card-section>
|
||||
<pn-overlay v-if="showOverlay"/>
|
||||
|
||||
<q-card-section class="q-pt-none" align="center">
|
||||
{{ $t('project_chat__delete_warning_message') }}
|
||||
</q-card-section>
|
||||
<pn-small-dialog
|
||||
v-model="showDialogDeleteChat"
|
||||
icon="mdi-link-off"
|
||||
color="negative"
|
||||
title="project_chat__delete_warning"
|
||||
message1="project_chat__delete_warning_message"
|
||||
mainBtnLabel="project_chat__dialog_cancel_ok"
|
||||
@clickMainBtn="onConfirm()"
|
||||
@close="onCancel()"
|
||||
@before-hide="onDialogBeforeHide()"
|
||||
/>
|
||||
|
||||
<q-card-actions align="center">
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('back')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="onCancel()"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('delete')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="onConfirm()"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onActivated, onDeactivated, onBeforeUnmount } from 'vue'
|
||||
import { ref, computed, onActivated, onDeactivated, onBeforeUnmount, inject } from 'vue'
|
||||
import { useChatsStore } from 'stores/chats'
|
||||
import { useUsersStore } from 'stores/users'
|
||||
import type { WebApp } from '@twa-dev/types'
|
||||
import { useI18n } from "vue-i18n"
|
||||
const { t } = useI18n()
|
||||
|
||||
const search = ref('')
|
||||
const showOverlay = ref<boolean>(false)
|
||||
const chatsStore = useChatsStore()
|
||||
const usersStore = useUsersStore()
|
||||
const showDialogDeleteChat = ref<boolean>(false)
|
||||
const deleteChatId = ref<number | undefined>(undefined)
|
||||
const currentSlideEvent = ref<SlideEvent | null>(null)
|
||||
const closedByUserAction = ref(false)
|
||||
const tg = inject('tg') as WebApp
|
||||
|
||||
const fabState = ref(false)
|
||||
|
||||
interface SlideEvent {
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
const chats = chatsStore.chats
|
||||
const chats = chatsStore.getChats
|
||||
const chatsInit = computed(() => chatsStore.isInit)
|
||||
|
||||
const fabMenu = [
|
||||
{id: 1, icon: 'mdi-chat-plus-outline', name: 'project_chats__attach_chat', description: 'project_chats__attach_chat_description', func: 'attachChat'},
|
||||
{id: 2, icon: 'mdi-share-outline', name: 'project_chats__send_chat', description: 'project_chats__send_chat_description', func: 'sendChat'},
|
||||
{id: 1, icon: 'mdi-chat-plus-outline', name: 'project_chats__attach_chat', description: 'project_chats__attach_chat_description', func: attachChat},
|
||||
{id: 2, icon: 'mdi-share-outline', name: 'project_chats__send_chat', description: 'project_chats__send_chat_description', func: sendChat},
|
||||
]
|
||||
|
||||
const displayChats = computed(() => {
|
||||
@@ -181,7 +205,7 @@
|
||||
return arrOut
|
||||
})
|
||||
|
||||
function handleSlide (event: SlideEvent, id: number) {
|
||||
function handleSlide (event: SlideEvent, id: number) {
|
||||
currentSlideEvent.value = event
|
||||
showDialogDeleteChat.value = true
|
||||
deleteChatId.value = id
|
||||
@@ -202,14 +226,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm() {
|
||||
async function onConfirm() {
|
||||
closedByUserAction.value = true
|
||||
if (deleteChatId.value) {
|
||||
chatsStore.deleteChat(deleteChatId.value)
|
||||
await chatsStore.unlink(deleteChatId.value)
|
||||
}
|
||||
currentSlideEvent.value = null
|
||||
}
|
||||
|
||||
const botName = 'ready_or_not_2025_bot'
|
||||
const urlAdmin = 'https://t.me/' + botName + '?startgroup='
|
||||
const urlAdminPermission='&admin=' +
|
||||
'post_messages+' +
|
||||
'edit_messages+' +
|
||||
'delete_messages+' +
|
||||
'pin_messages+' +
|
||||
'restrict_members+' +
|
||||
'invite_users'
|
||||
|
||||
async function attachChat () {
|
||||
const key = await chatsStore.getKey()
|
||||
tg.openTelegramLink(urlAdmin + key + urlAdminPermission)
|
||||
}
|
||||
|
||||
async function sendChat () {
|
||||
const key = await chatsStore.getKey()
|
||||
const message = urlAdmin + key + urlAdminPermission
|
||||
const tgShareUrl = 'https://t.me/share/url?url=' +
|
||||
encodeURIComponent( t('project_chats__send_chat_title')) +
|
||||
'&text=' + `${encodeURIComponent(message)}`
|
||||
tg.openTelegramLink(tgShareUrl)
|
||||
}
|
||||
|
||||
function goChat (invite: string) {
|
||||
tg.openTelegramLink(invite)
|
||||
}
|
||||
|
||||
// fix fab jumping
|
||||
const showFab = ref(false)
|
||||
const timerId = ref<ReturnType<typeof setTimeout> | null>(null)
|
||||
@@ -236,6 +288,7 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* width of choose element */
|
||||
.change-fab-action .q-fab__label--internal {
|
||||
max-height: none;
|
||||
}
|
||||
@@ -255,10 +308,4 @@
|
||||
align-self: center;
|
||||
height: 98%;
|
||||
}
|
||||
|
||||
.fix-fab {
|
||||
top: calc(100vh - 92px);
|
||||
left: calc(100vw - 92px);
|
||||
padding: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,29 +2,37 @@
|
||||
<div class="q-pa-none flex column col-grow no-scroll">
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
<div class="w100 flex items-center justify-end q-pa-sm">
|
||||
<q-btn color="primary" flat no-caps dense @click="maskCompany()">
|
||||
<q-icon
|
||||
left
|
||||
size="sm"
|
||||
name="mdi-drama-masks"
|
||||
/>
|
||||
<div>
|
||||
{{ $t('company__mask')}}
|
||||
</div>
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex items-center justify-end q-pa-sm w100" v-if="companies.length !== 0">
|
||||
<q-btn
|
||||
:color="companies.length <= 2 ? 'grey-6' : 'primary'"
|
||||
flat
|
||||
no-caps
|
||||
@click="maskCompany()"
|
||||
:disable="companies.length <= 2"
|
||||
class="q-pr-md"
|
||||
rounded
|
||||
>
|
||||
<q-icon
|
||||
left
|
||||
size="sm"
|
||||
name="mdi-domino-mask"
|
||||
/>
|
||||
<div>
|
||||
{{ $t('company__mask')}}
|
||||
</div>
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<q-list separator>
|
||||
<q-list separator v-if="companies.length !== 0">
|
||||
<q-slide-item
|
||||
v-for="item in companies"
|
||||
v-for="item in displayCompanies"
|
||||
:key="item.id"
|
||||
@right="handleSlide($event, item.id)"
|
||||
right-color="red"
|
||||
>
|
||||
<template #right>
|
||||
<q-icon size="lg" name="mdi-delete-outline"/>
|
||||
<template #right v-if="item.id !== myCompany?.id">
|
||||
<q-icon size="lg" name="mdi-account-multiple-minus-outline"/>
|
||||
</template>
|
||||
<q-item
|
||||
:key="item.id"
|
||||
@@ -33,34 +41,79 @@
|
||||
class="w100"
|
||||
@click="goCompanyInfo(item.id)"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-avatar rounded>
|
||||
<q-img v-if="item.logo" :src="item.logo" fit="cover" style="max-width: unset; height:40px;"/>
|
||||
<pn-auto-avatar v-else :name="item.name"/>
|
||||
</q-avatar>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold">{{ item.name }}</q-item-label>
|
||||
<q-item-label caption lines="2">{{ item.description }}</q-item-label>
|
||||
</q-item-section>
|
||||
<!-- <q-item-section side top>
|
||||
<div class="flex items-center">
|
||||
<q-icon v-if="item.masked" name="mdi-drama-masks" color="black" size="sm"/>
|
||||
<q-item-section avatar>
|
||||
<pn-auto-avatar
|
||||
:img="item.logo"
|
||||
:name="item.name"
|
||||
type="rounded"
|
||||
size="lg"
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-caption text-amber-10" v-if="item.id === myCompany?.id">
|
||||
<div class="flex items-center">
|
||||
<q-icon name="star" class="q-pr-xs"/>
|
||||
{{ $t('company__my_company') }}
|
||||
</div>
|
||||
</q-item-label>
|
||||
<q-item-label lines="1" class="text-bold">{{ item.name }}</q-item-label>
|
||||
<q-item-label
|
||||
caption lines="2"
|
||||
style="max-width: -webkit-fill-available; white-space: pre-line"
|
||||
>
|
||||
{{ item.description }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side top>
|
||||
<div class="flex items-end column">
|
||||
<span class="text-caption flex items-center">
|
||||
<q-icon name="mdi-account-outline" color="grey" />
|
||||
<span>{{ item.qtyPersons }}</span>
|
||||
<span>{{ getQtyUsers(item.id) }}</span>
|
||||
</span>
|
||||
|
||||
<q-icon
|
||||
v-if="companiesStore.checkCompanyMasked(item.id)"
|
||||
name="mdi-domino-mask"
|
||||
color="grey"
|
||||
size="xs"
|
||||
/>
|
||||
|
||||
<div class="flex items-center row text-caption">
|
||||
<q-icon v-if="item.site" name="mdi-web"/>
|
||||
<q-icon v-if="item.address" name="mdi-map-marker-outline"/>
|
||||
<q-icon v-if="item.phone" name="mdi-phone-outline"/>
|
||||
<q-icon v-if="item.email" name="mdi-email-outline"/>
|
||||
</div>
|
||||
</q-item-section> -->
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-slide-item>
|
||||
</q-list>
|
||||
|
||||
<pn-onboard-btn
|
||||
v-if="companies.length <= 1 && companiesInit"
|
||||
icon="mdi-account-multiple-plus-outline"
|
||||
:message1="$t('company__onboard_msg1')"
|
||||
:message2="$t('company__onboard_msg2')"
|
||||
@btn-click="createCompany()"
|
||||
/>
|
||||
<div
|
||||
class="flex column justify-center items-center w100"
|
||||
style="position: absolute; bottom: 0;"
|
||||
v-if="!companiesInit"
|
||||
>
|
||||
<q-linear-progress indeterminate />
|
||||
</div>
|
||||
</pn-scroll-list>
|
||||
|
||||
<q-page-sticky
|
||||
position="bottom-right"
|
||||
:offset="[18, 18]"
|
||||
:offset="[0, 18]"
|
||||
class="fix-fab-offset"
|
||||
>
|
||||
<transition
|
||||
appear
|
||||
enter-active-class="animated slideInUp"
|
||||
enter-active-class="animated zoomIn"
|
||||
>
|
||||
<q-btn
|
||||
v-if="showFab"
|
||||
@@ -72,63 +125,58 @@
|
||||
</transition>
|
||||
</q-page-sticky>
|
||||
</div>
|
||||
<q-dialog v-model="showDialogDeleteCompany" @before-hide="onDialogBeforeHide()">
|
||||
<q-card class="q-pa-none q-ma-none">
|
||||
<q-card-section align="center">
|
||||
<div class="text-h6 text-negative ">{{ $t('company__delete_warning') }}</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="q-pt-none" align="center">
|
||||
{{ $t('company__delete_warning_message') }}
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="center">
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('back')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="onCancel()"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('delete')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="onConfirm()"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<pn-small-dialog
|
||||
v-model="showDialogDeleteCompany"
|
||||
icon="mdi-account-multiple-minus-outline"
|
||||
color="negative"
|
||||
title="company__dialog_delete_title"
|
||||
message1="company__dialog_delete_message"
|
||||
mainBtnLabel="company__dialog_delete_ok"
|
||||
@clickMainBtn="onConfirm()"
|
||||
@close="onCancel()"
|
||||
@before-hide="onDialogBeforeHide()"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onActivated, onDeactivated, onBeforeUnmount } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useCompaniesStore } from 'stores/companies'
|
||||
import { parseIntString } from 'boot/helpers'
|
||||
import { useUsersStore } from 'stores/users'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const companiesStore = useCompaniesStore()
|
||||
const usersStore = useUsersStore()
|
||||
const showDialogDeleteCompany = ref<boolean>(false)
|
||||
const deleteCompanyId = ref<number | undefined>(undefined)
|
||||
const currentSlideEvent = ref<SlideEvent | null>(null)
|
||||
const closedByUserAction = ref(false)
|
||||
const projectId = computed(() => parseIntString(route.params.id))
|
||||
|
||||
interface SlideEvent {
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
const companies = companiesStore.companies
|
||||
const users = computed(() => usersStore.users)
|
||||
const companies = companiesStore.getCompanies
|
||||
const companiesInit = computed(() => companiesStore.isInit)
|
||||
|
||||
const myCompany = computed(() => companies.find(el => el.is_own))
|
||||
|
||||
const displayCompanies = computed(() => {
|
||||
const otherComp = companies.filter(el => !el.is_own)
|
||||
return myCompany.value
|
||||
? [myCompany.value, ...otherComp]
|
||||
: otherComp
|
||||
})
|
||||
|
||||
async function maskCompany () {
|
||||
await router.push({ name: 'company_mask' })
|
||||
}
|
||||
|
||||
async function goCompanyInfo (id :number) {
|
||||
await router.push({ name: 'company_info', params: { id: projectId.value, companyId: id }})
|
||||
async function goCompanyInfo (companyId: number) {
|
||||
await router.push({ name: 'company_info', params: { id: route.params.id, companyId }})
|
||||
}
|
||||
|
||||
async function createCompany () {
|
||||
@@ -156,14 +204,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm() {
|
||||
async function onConfirm() {
|
||||
closedByUserAction.value = true
|
||||
if (deleteCompanyId.value) {
|
||||
companiesStore.deleteCompany(deleteCompanyId.value)
|
||||
await companiesStore.remove(deleteCompanyId.value)
|
||||
}
|
||||
currentSlideEvent.value = null
|
||||
}
|
||||
|
||||
function getQtyUsers (companyId: number) {
|
||||
const arr = users.value.filter(el => el.company_id === companyId)
|
||||
return arr.length
|
||||
}
|
||||
|
||||
// fix fab jumping
|
||||
const showFab = ref(false)
|
||||
const timerId = ref<ReturnType<typeof setTimeout> | null>(null)
|
||||
@@ -195,5 +248,5 @@
|
||||
{
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,189 +1,119 @@
|
||||
<template>
|
||||
<div
|
||||
id="project-info"
|
||||
:style="{ height: headerHeight + 'px' }"
|
||||
class="flex row items-center justify-between no-wrap q-my-sm w100"
|
||||
style="overflow: hidden; transition: height 0.3s ease-in-out;"
|
||||
id="project-info"
|
||||
:style="{ height: headerHeight + 'px', minHeight: '48px' }"
|
||||
class="flex row items-center justify-between no-wrap w100 q-gutter-x-sm"
|
||||
style="overflow: hidden; transition: height 0.3s ease-in-out; margin-left: 0"
|
||||
>
|
||||
<div class="ellipsis overflow-hidden">
|
||||
<div class="ellipsis overflow-hidden q-pa-none q-ma-none">
|
||||
<q-resize-observer @resize="onResize" />
|
||||
<transition
|
||||
enter-active-class="animated slideInUp"
|
||||
leave-active-class="animated slideOutUp"
|
||||
mode="out-in"
|
||||
>
|
||||
>
|
||||
<div
|
||||
v-if="!expandProjectInfo"
|
||||
@click="toggleExpand"
|
||||
class="text-h6 ellipsis no-wrap w100"
|
||||
class="text-h6 ellipsis no-wrap w100 q-pa-none q-ma-none"
|
||||
key="compact"
|
||||
>
|
||||
{{project.name}}
|
||||
>
|
||||
{{ project.name }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="flex items-center no-wrap q-hoverable q-animate--slideUp"
|
||||
class="flex items-center no-wrap q-hoverable q-animate--slideUp q-py-sm"
|
||||
@click="toggleExpand"
|
||||
key="expanded"
|
||||
>
|
||||
<q-avatar rounded>
|
||||
<q-img v-if="project.logo" :src="project.logo" fit="cover" style="height: 100%;"/>
|
||||
<pn-auto-avatar v-else :name="project.name"/>
|
||||
</q-avatar>
|
||||
>
|
||||
<pn-auto-avatar
|
||||
:img="project.logo"
|
||||
:name="project.name"
|
||||
type="rounded"
|
||||
size="lg"
|
||||
/>
|
||||
|
||||
<div class="q-px-md flex column text-white fit">
|
||||
<div class="flex column text-white fit">
|
||||
<div
|
||||
class="text-h6"
|
||||
:style="{ maxWidth: '-webkit-fill-available', whiteSpace: 'normal' }"
|
||||
>
|
||||
{{project.name}}
|
||||
class="text-h6 q-pl-sm text-field"
|
||||
>
|
||||
{{ project.name }}
|
||||
</div>
|
||||
|
||||
<div class="text-caption" :style="{ maxWidth: '-webkit-fill-available', whiteSpace: 'normal' }">
|
||||
{{project.description}}
|
||||
|
||||
<div
|
||||
class="text-caption q-pl-sm text-field"
|
||||
>
|
||||
{{ project.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<q-btn flat round color="white" icon="mdi-pencil" size="sm" class="q-ml-xl q-mr-sm">
|
||||
<q-menu anchor="bottom right" self="top right">
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="item in menuItems"
|
||||
:key="item.id"
|
||||
@click="item.func"
|
||||
clickable
|
||||
v-close-popup
|
||||
class="flex items-center"
|
||||
>
|
||||
<q-icon :name="item.icon" size="sm" :color="item.iconColor"/>
|
||||
<span class="q-ml-xs">{{ $t(item.title) }}</span>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
@click="editProject"
|
||||
flat round
|
||||
color="white"
|
||||
icon="edit"
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
<q-dialog v-model="showDialog">
|
||||
<q-card class="q-pa-none q-ma-none">
|
||||
<q-card-section align="center">
|
||||
<div class="text-h6 text-negative ">
|
||||
{{ $t('project__archive_warning')}}
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="q-pt-none" align="center">
|
||||
{{ $t('project__archive_warning_message')}}
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="center">
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('back')"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
:label="$t('project__archive')"
|
||||
color="negative"
|
||||
v-close-popup
|
||||
@click="archiveProject"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useProjectsStore } from 'stores/projects'
|
||||
import { parseIntString } from 'boot/helpers'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const projectsStore = useProjectsStore()
|
||||
|
||||
const expandProjectInfo = ref<boolean>(false)
|
||||
const showDialog = ref<boolean>(false)
|
||||
const dialogType = ref<null | 'archive'>(null)
|
||||
|
||||
const headerHeight = ref<number>(0)
|
||||
|
||||
const menuItems = [
|
||||
{ id: 1, title: 'project__edit', icon: 'mdi-square-edit-outline', iconColor: '', func: editProject },
|
||||
// { id: 2, title: 'project__backup', icon: 'mdi-content-save-outline', iconColor: '', func: () => {} },
|
||||
{ id: 3, title: 'project__archive', icon: 'mdi-archive-outline', iconColor: 'red', func: () => { showDialog.value = true; dialogType.value = 'archive' }}
|
||||
]
|
||||
|
||||
const projectId = computed(() => parseIntString(route.params.id))
|
||||
const project =ref({
|
||||
name: '',
|
||||
description: '',
|
||||
logo: '',
|
||||
is_logo_bg: false
|
||||
const currentProjectId = computed(() => projectsStore.currentProjectId)
|
||||
|
||||
const project = computed(() => {
|
||||
const currentProject =
|
||||
currentProjectId.value && projectsStore.projectById(currentProjectId.value)
|
||||
|
||||
return currentProject
|
||||
? {
|
||||
name: currentProject.name,
|
||||
description: currentProject.description ?? '',
|
||||
logo: currentProject.logo ?? ''
|
||||
}
|
||||
: {
|
||||
name: '',
|
||||
description: '',
|
||||
logo: ''
|
||||
}
|
||||
})
|
||||
|
||||
const loadProjectData = async () => {
|
||||
if (!projectId.value) {
|
||||
await abort()
|
||||
return
|
||||
} else {
|
||||
const projectFromStore = projectsStore.projectById(projectId.value)
|
||||
if (!projectFromStore) {
|
||||
await abort()
|
||||
return
|
||||
}
|
||||
|
||||
project.value = {
|
||||
name: projectFromStore.name,
|
||||
description: projectFromStore.description || '',
|
||||
logo: projectFromStore.logo || '',
|
||||
is_logo_bg: projectFromStore.is_logo_bg || false
|
||||
}
|
||||
|
||||
function toggleExpand () {
|
||||
expandProjectInfo.value = !expandProjectInfo.value
|
||||
}
|
||||
}
|
||||
|
||||
async function abort () {
|
||||
await router.replace({ name: 'projects' })
|
||||
}
|
||||
async function editProject () {
|
||||
if (currentProjectId.value)
|
||||
await router.push({ name: 'project_info', params: { id: currentProjectId.value } })
|
||||
}
|
||||
|
||||
async function editProject () {
|
||||
if (projectId.value) void projectsStore.update(projectId.value, project.value)
|
||||
await router.push({ name: 'project_info' })
|
||||
}
|
||||
|
||||
async function archiveProject () {
|
||||
if (projectId.value) void projectsStore.archive(projectId.value)
|
||||
await router.replace({ name: 'projects' })
|
||||
}
|
||||
|
||||
function toggleExpand () {
|
||||
expandProjectInfo.value = !expandProjectInfo.value
|
||||
}
|
||||
|
||||
interface sizeParams {
|
||||
interface sizeParams {
|
||||
height: number,
|
||||
width: number
|
||||
}
|
||||
|
||||
function onResize (size :sizeParams) {
|
||||
headerHeight.value = size.height
|
||||
}
|
||||
const headerHeight = ref<number>(0)
|
||||
|
||||
watch(projectId, loadProjectData)
|
||||
|
||||
watch(showDialog, () => {
|
||||
if (showDialog.value === false) dialogType.value = null
|
||||
})
|
||||
|
||||
onMounted(() => loadProjectData())
|
||||
function onResize (size :sizeParams) {
|
||||
headerHeight.value = size.height
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.text-field {
|
||||
max-width: -webkit-fill-available;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="q-pa-none flex column col-grow no-scroll">
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
<div class="flex row q-ma-md justify-between">
|
||||
<q-input
|
||||
v-model="search"
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:placeholder="$t('project_persons__search')"
|
||||
dense
|
||||
class="col-grow"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="mdi-magnify" />
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<q-list separator>
|
||||
<q-item
|
||||
v-for="item in displayPersons"
|
||||
:key="item.id"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="goPersonInfo()"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-avatar>
|
||||
<img v-if="item.logo" :src="item.logo"/>
|
||||
<pn-auto-avatar v-else :name="item.name"/>
|
||||
</q-avatar>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold">
|
||||
{{item.name}}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="2">
|
||||
<span>{{item.tname}}</span>
|
||||
<span class="text-blue q-ml-sm">{{item.tusername}}</span>
|
||||
</q-item-label>
|
||||
<q-item-label lines="1">
|
||||
{{ item.company.name +', ' + item.role }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</pn-scroll-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
const router = useRouter()
|
||||
const search = ref('')
|
||||
|
||||
const persons = [
|
||||
{id: "p1", name: 'Кирюшкин Андрей', logo: 'https://cdn.quasar.dev/img/avatar4.jpg', tname: 'Kir_AA', tusername: '@kiruha90', role: 'DevOps', company: {id: "com11", name: 'Рога и копытца', logo: '', description: 'Монтажники вывески', qtyPersons: 3, masked: false }},
|
||||
{id: "p2", name: 'Пупкин Василий Александрович', logo: '', tname: 'Pupkin', tusername: '@super_pupkin', role: 'Руководитель проекта', company: {id: "com11", name: 'Рога и копытца', logo: '', description: 'Монтажники вывески', qtyPersons: 3, masked: false }},
|
||||
{id: "p3", name: 'Макарова Полина', logo: 'https://cdn.quasar.dev/img/avatar6.jpg', tname: 'Unikorn', tusername: '@unicorn_stars', role: 'Администратор', company: {id: "com21", name: 'ООО "Василек"', logo: '', qtyPersons: 2, masked: true }},
|
||||
{id: "p4", name: 'Жабов Максим', logo: '', tname: 'Zhaba', tusername: '@Zhabchenko', role: 'Аналитик', company: {id: "com21", name: 'ООО "Василек"', logo: 'https://cdn.quasar.dev/img/avatar4.jpg', qtyPersons: 2, masked: true }},
|
||||
]
|
||||
|
||||
const displayPersons = computed(() => {
|
||||
if (!search.value || !(search.value && search.value.trim())) return persons
|
||||
const searchValue = search.value.trim().toLowerCase()
|
||||
const arrOut = persons
|
||||
.filter(el =>
|
||||
el.name.toLowerCase().includes(searchValue) ||
|
||||
el.tname && el.tname.toLowerCase().includes(searchValue) ||
|
||||
el.tusername && el.tusername.toLowerCase().includes(searchValue) ||
|
||||
el.role && el.role.toLowerCase().includes(searchValue) ||
|
||||
el.company.name && el.company.name.toLowerCase().includes(searchValue)
|
||||
)
|
||||
return arrOut
|
||||
})
|
||||
|
||||
async function goPersonInfo () {
|
||||
console.log('update')
|
||||
await router.push({ name: 'person_info' })
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
297
src/pages/project-page/ProjectPageUsers.vue
Normal file
297
src/pages/project-page/ProjectPageUsers.vue
Normal file
@@ -0,0 +1,297 @@
|
||||
<template>
|
||||
<div class="q-pa-none flex column col-grow no-scroll">
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
<div class="flex row q-ma-md justify-between" v-if="users.length !== 0">
|
||||
<q-input
|
||||
v-model="search"
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:placeholder="$t('project_users__search')"
|
||||
dense
|
||||
class="col-grow"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="mdi-magnify" />
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<q-list separator v-if="users.length !== 0">
|
||||
<q-slide-item
|
||||
v-for="item in displayUsers"
|
||||
:key="item.id"
|
||||
@right="handleSlide($event, item.id)"
|
||||
right-color="red"
|
||||
>
|
||||
<template #right>
|
||||
<q-icon size="lg" name="mdi-account-remove-outline"/>
|
||||
</template>
|
||||
<q-item
|
||||
:key="item.id"
|
||||
v-ripple
|
||||
clickable
|
||||
class="w100"
|
||||
@click="goUserInfo(item.id)"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<pn-auto-avatar
|
||||
:img="item.photo"
|
||||
:name="item.section1"
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold" v-if="item.section1">
|
||||
{{item.section1}}
|
||||
</q-item-label>
|
||||
<q-item-label lines="1" caption v-if="item.section3">
|
||||
{{item.section3}}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="2">
|
||||
<div class="flex items-center">
|
||||
<q-icon name="telegram" v-if="item.section2_1 || item.section2_2" class="q-pr-xs" style="color: #27a7e7"/>
|
||||
<div v-if="item.section2_1" class="q-mr-sm text-bold">{{item.section2_1}}</div>
|
||||
<div class="text-blue" v-if="item.section2_2">{{'@' + item.section2_2}}</div>
|
||||
</div>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-slide-item>
|
||||
</q-list>
|
||||
|
||||
<div
|
||||
v-if="blockedUsers.length!==0"
|
||||
class="flex column items-center w100"
|
||||
:class="showBlockedUsers ? 'bg-grey-12' : ''"
|
||||
>
|
||||
<q-btn-dropdown
|
||||
class="w100 fix-rotate-arrow"
|
||||
color="grey"
|
||||
flat no-caps
|
||||
@click="showBlockedUsers=!showBlockedUsers"
|
||||
dropdown-icon="arrow_drop_up"
|
||||
>
|
||||
<template #label>
|
||||
<span class="text-caption">
|
||||
{{ !showBlockedUsers
|
||||
? $t('users__show_archive') + ' (' + blockedUsers.length +')'
|
||||
: $t('user__hide_archive')
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</q-btn-dropdown>
|
||||
|
||||
<div class="w100" style="overflow: hidden">
|
||||
<transition
|
||||
appear
|
||||
enter-active-class="animated slideInDown"
|
||||
leave-active-class="animated slideOutUp"
|
||||
>
|
||||
<q-list separator v-if="showBlockedUsers" class="w100">
|
||||
<q-item
|
||||
v-for = "item in blockedUsers"
|
||||
:key="item.id"
|
||||
clickable
|
||||
v-ripple
|
||||
@click="handleUnblockUser(item.id)"
|
||||
class="w100 text-grey"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<pn-auto-avatar
|
||||
:img="item.photo"
|
||||
:name="item.section1"
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold" v-if="item.section1">
|
||||
{{item.section1}}
|
||||
</q-item-label>
|
||||
<q-item-label lines="1" caption v-if="item.section3">
|
||||
{{item.section3}}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="2">
|
||||
<div class="flex items-center">
|
||||
<q-icon name="telegram" v-if="item.section2_1 || item.section2_2" class="q-pr-xs" style="color: #27a7e7"/>
|
||||
<div v-if="item.section2_1" class="q-mr-sm text-bold">{{item.section2_1}}</div>
|
||||
<div class="text-blue" v-if="item.section2_2">{{'@' + item.section2_2}}</div>
|
||||
</div>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pn-onboard-btn
|
||||
v-if="users.length === 0 && usersInit"
|
||||
icon="mdi-account-outline"
|
||||
:message1="$t('project_users__onboard_msg1')"
|
||||
:message2="$t('project_users__onboard_msg2')"
|
||||
noBtn
|
||||
/>
|
||||
<div
|
||||
class="flex column justify-center items-center w100"
|
||||
style="position: absolute; bottom: 0;"
|
||||
v-if="!usersInit"
|
||||
>
|
||||
<q-linear-progress indeterminate />
|
||||
</div>
|
||||
</pn-scroll-list>
|
||||
</div>
|
||||
|
||||
<pn-small-dialog
|
||||
v-model="showDialogDeleteUser"
|
||||
icon="mdi-account-remove-outline"
|
||||
color="negative"
|
||||
title="user__dialog_delete_title"
|
||||
message1="user__dialog_delete_message"
|
||||
mainBtnLabel="user__dialog_delete_ok"
|
||||
@clickMainBtn="onConfirmDeleteUser()"
|
||||
@close="onCancel()"
|
||||
@before-hide="onDialogBeforeHide()"
|
||||
/>
|
||||
|
||||
<pn-small-dialog
|
||||
v-model="showDialogRestoreUser"
|
||||
icon="mdi-account-reactivate-outline"
|
||||
color="green"
|
||||
title="user__dialog_restore_title"
|
||||
message1="user__dialog_restore_message"
|
||||
mainBtnLabel="user__dialog_restore_ok"
|
||||
@clickMainBtn="onConfirmRestoreUser()"
|
||||
/>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useUsersStore } from 'stores/users'
|
||||
import { useCompaniesStore } from 'stores/companies'
|
||||
import type { User } from 'types/Users'
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const search = ref('')
|
||||
const usersStore = useUsersStore()
|
||||
const companiesStore = useCompaniesStore()
|
||||
|
||||
const users = usersStore.getUsers
|
||||
const usersInit = computed(() => usersStore.isInit)
|
||||
|
||||
const deleteUserId = ref<number | undefined>(undefined)
|
||||
const showDialogDeleteUser = ref<boolean>(false)
|
||||
const currentSlideEvent = ref<SlideEvent | null>(null)
|
||||
const closedByUserAction = ref(false)
|
||||
|
||||
const mapUsers = computed(() => users.map(el => ({...el, ...userSection(el)})))
|
||||
|
||||
interface SlideEvent {
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
const displayUsersAll = computed(() => {
|
||||
if (!search.value || !(search.value && search.value.trim())) return mapUsers.value
|
||||
const searchValue = search.value.trim().toLowerCase()
|
||||
const arrOut = mapUsers.value
|
||||
.filter(el =>
|
||||
el.section1.toLowerCase().includes(searchValue) ||
|
||||
el.section2_1.toLowerCase().includes(searchValue) ||
|
||||
el.section2_2.toLowerCase().includes(searchValue) ||
|
||||
el.section3.toLowerCase().includes(searchValue)
|
||||
)
|
||||
return arrOut
|
||||
})
|
||||
|
||||
const displayUsers = computed(() => displayUsersAll.value.filter(el => !el.is_block))
|
||||
|
||||
function userSection (user: User) {
|
||||
const tname = () => {
|
||||
return user.firstname
|
||||
? user.lastname
|
||||
? user.firstname + ' ' + user.lastname
|
||||
: user.firstname
|
||||
: user.lastname ?? ''
|
||||
}
|
||||
|
||||
const section1 = user.fullname ?? tname()
|
||||
|
||||
const section2_1 = user.fullname ? tname() : ''
|
||||
|
||||
const section2_2 = user.username ?? ''
|
||||
|
||||
const section3 = (
|
||||
user.company_id && companiesStore.companyById(user.company_id)
|
||||
? companiesStore.companyById(user.company_id)?.name + ((user.role || user.department ) ? ' / ' :'')
|
||||
: '') +
|
||||
(user.department ? user.department + (user.role ? ' / ' : '') : '') +
|
||||
(user.role ?? '')
|
||||
|
||||
return {
|
||||
section1,
|
||||
section2_1, section2_2,
|
||||
section3
|
||||
}
|
||||
}
|
||||
|
||||
async function goUserInfo (id: number) {
|
||||
await router.push({ name: 'user_info', params: { id: route.params.id, userId: id }})
|
||||
}
|
||||
|
||||
function handleSlide (event: SlideEvent, id: number) {
|
||||
currentSlideEvent.value = event
|
||||
showDialogDeleteUser.value = true
|
||||
deleteUserId.value = id
|
||||
}
|
||||
|
||||
function onDialogBeforeHide () {
|
||||
if (!closedByUserAction.value) {
|
||||
onCancel()
|
||||
}
|
||||
closedByUserAction.value = false
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
closedByUserAction.value = true
|
||||
if (currentSlideEvent.value) {
|
||||
currentSlideEvent.value.reset()
|
||||
currentSlideEvent.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function onConfirmDeleteUser() {
|
||||
closedByUserAction.value = true
|
||||
if (deleteUserId.value) {
|
||||
await usersStore.blockUser(deleteUserId.value)
|
||||
}
|
||||
currentSlideEvent.value = null
|
||||
}
|
||||
|
||||
const showBlockedUsers = ref(false)
|
||||
const blockedUsers = computed(() => displayUsersAll.value.filter(el => el.is_block))
|
||||
const unblockUserId = ref<number | undefined> (undefined)
|
||||
const showDialogRestoreUser = ref(false)
|
||||
|
||||
function handleUnblockUser (id: number) {
|
||||
showDialogRestoreUser.value = true
|
||||
unblockUserId.value = id
|
||||
}
|
||||
|
||||
async function onConfirmRestoreUser () {
|
||||
if (unblockUserId.value) await usersStore.restore(unblockUserId.value)
|
||||
}
|
||||
|
||||
watch(showDialogRestoreUser, (newD :boolean) => {
|
||||
if (!newD) unblockUserId.value = undefined
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user