before delete 3software

This commit is contained in:
2025-06-29 18:55:59 +03:00
parent ebd77a3e66
commit b51a472738
147 changed files with 257326 additions and 3151 deletions

View File

@@ -1,30 +1,27 @@
<template>
<pn-page-card>
<template #title>
<div class="flex items-center justify-between col-grow">
<div>{{ $t('projects__projects') }}</div>
<div class="flex items-center">
<q-btn
@click="goAccount()"
flat
no-caps
icon-right="mdi-chevron-right"
align="right"
dense
class="fix-btn"
>
<pn-account-block-name/>
</q-btn>
</div>
</div>
{{ $t('projects__projects') }}
<q-btn
@click="goAccount()"
flat rounded
no-caps
icon-right="mdi-chevron-right"
align="right"
dense
class="fix-btn ellipsis"
>
<pn-account-block-name/>
</q-btn>
</template>
<pn-scroll-list>
<template #card-body-header v-if="projects.length !== 0">
<template
#card-body-header
v-if="projects.length !== 0 || archiveProjects.length !== 0"
>
<q-input
v-if="projects.length !== 0"
v-model="searchProject"
clearable
clear-icon="close"
@@ -38,155 +35,189 @@
</q-input>
</template>
<div id="projects-wrapper">
<q-list separator v-if="projects.length !== 0">
<q-item
v-for = "item in activeProjects"
:key="item.id"
<q-list separator v-if="projects.length !== 0">
<template
v-for = "item in activeProjects"
:key="item.id"
>
<q-slide-item
@right="handleSlideRight($event, item.id)"
clickable
v-ripple
@click="goProject(item.id)"
class="w100"
right-color="red"
left-color="green"
>
<template #right>
<q-icon size="lg" name="mdi-briefcase-remove-outline"/>
</template>
<q-item>
<q-item-section avatar>
<q-avatar rounded >
<q-img v-if="item.logo" :src="item.logo" fit="cover" style="height: 40px"/>
<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">{{ item.name }}</q-item-label>
<q-item-label caption lines="2">{{item.description}}</q-item-label>
</q-item-section>
<q-item-section side class="text-caption ">
<div class="flex items-center column">
<div class="flex items-center">
<q-icon name="mdi-chat-outline"/>
<span>{{ item.chat_count }} </span>
</div>
<div class="flex items-center">
<q-icon name="mdi-account-outline"/>
<span>{{ item.user_count }}</span>
</div>
</div>
</q-item-section>
</q-item>
</q-list>
<div v-if="archiveProjects.length !== 0" class="flex column items-center w100" :class="showArchive ? 'bg-grey-12' : ''">
<div id="btn_show_archive">
<q-btn-dropdown color="grey" flat no-caps @click="showArchive = !showArchive" dropdown-icon="arrow_drop_up">
<template #label>
<span class="text-caption">
<span v-if="!showArchive">{{ $t('projects__show_archive') }}</span>
<span v-else>{{ $t('projects__hide_archive') }}</span>
</span>
</template>
</q-btn-dropdown>
</div>
<q-list separator v-if="showArchive" class="w100">
<q-item
v-for = "item in archiveProjects"
:key="item.id"
clickable
v-ripple
@click="handleArchiveList(item.id)"
class="w100 text-grey"
>
<q-item-section avatar>
<q-avatar rounded >
<q-img v-if="item.logo" :src="item.logo" fit="cover" style="height: 40px"/>
<pn-auto-avatar v-else :name="item.name"/>
</q-avatar>
<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>
<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 side class="text-caption ">
<div class="flex items-center column">
<div class="flex items-center">
<q-icon name="mdi-chat-outline"/>
<span>{{ item.chat_count }} </span>
</div>
<div class="flex items-center">
<q-icon name="mdi-account-outline"/>
<span>{{ item.user_count }}</span>
</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-slide-item>
</template>
</q-list>
<div
v-if="archiveProjects.length!==0"
class="flex column items-center w100"
:class="showArchive ? 'bg-grey-12' : ''"
>
<q-btn-dropdown
class="w100 fix-rotate-arrow"
color="grey"
flat no-caps
@click="showArchive=!showArchive"
dropdown-icon="arrow_drop_up"
>
<template #label>
<span class="text-caption">
{{ !showArchive
? $t('projects__show_archive') + ' (' + archiveProjects.length +')'
: $t('projects__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="showArchive" class="w100">
<q-item
v-for = "item in archiveProjects"
:key="item.id"
clickable
v-ripple
@click="handleArchiveList(item.id)"
class="w100 text-grey"
>
<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-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>
</q-list>
</transition>
</div>
</div>
<pn-onboard-btn
v-if="projects.length === 0 && projectsInit"
icon="mdi-briefcase-plus-outline"
:message1="$t('projects__lets_start')"
:message2="$t('projects__lets_start_description')"
@btn-click="createNewProject"
/>
<div
v-if="projects.length === 0"
class="flex w100 column q-pt-xl q-pa-md"
>
<div class="flex column justify-center col-grow items-center text-grey">
<q-btn flat no-caps @click="createNewProject">
<div class="flex column justify-center col-grow items-center">
<q-icon name="mdi-briefcase-plus-outline" size="160px" class="q-pb-md"/>
<div class="text-h6 text-brand">
{{$t('projects__lets_start')}}
</div>
</div>
</q-btn>
<div class="text-caption" align="center">
{{$t('projects__lets_start_description')}}
</div>
</div>
</div>
class="flex column justify-center items-center w100"
style="position: absolute; bottom: 0;"
v-if="!projectsInit"
>
<q-linear-progress indeterminate />
</div>
</pn-scroll-list>
<q-page-sticky
position="bottom-right"
:offset="[18, 18]"
:offset="[0, 18]"
class="fix-fab-offset"
>
<q-btn
fab
icon="add"
color="brand"
@click="createNewProject"
<transition
appear
enter-active-class="animated zoomIn"
>
<q-btn
fab
icon="add"
color="brand"
@click="createNewProject"
/>
</transition>
</q-page-sticky>
</pn-page-card>
<q-dialog v-model="showDialogArchive">
<q-card class="q-pa-none q-ma-none">
<q-card-section align="center">
<div class="text-h6 text-negative ">{{ $t('projects__restore_archive_warning') }}</div>
</q-card-section>
<q-card-section class="q-pt-none" align="center">
{{ $t('projects__restore_archive_warning_message') }}
</q-card-section>
<pn-small-dialog
v-model="showDialogArchiveProject"
icon="mdi-briefcase-remove-outline"
color="negative"
title="projects__dialog_archive_title"
message1="projects__dialog_archive_message"
mainBtnLabel="projects__dialog_archive_ok"
@clickMainBtn="onConfirmArchiveProject()"
@close="onCancel()"
@before-hide="onDialogBeforeHide()"
/>
<q-card-actions align="center">
<q-btn
flat
:label="$t('back')"
color="primary"
v-close-popup
/>
<q-btn
flat
:label="$t('continue')"
color="primary"
v-close-popup
@click="restoreFromArchive()"
/>
</q-card-actions>
</q-card>
</q-dialog>
<pn-small-dialog
v-model="showDialogRestoreArchive"
icon="mdi-briefcase-upload-outline"
color="green"
title="projects__dialog_restore_title"
message1="projects__dialog_restore_message"
mainBtnLabel="projects__dialog_cancel_ok"
@clickMainBtn="restoreFromArchive()"
/>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useProjectsStore } from 'stores/projects'
import { useSettingsStore } from 'stores/settings'
import type { Project } from 'types/Project'
const router = useRouter()
const projectsStore = useProjectsStore()
const settingsStore = useSettingsStore()
const projects = projectsStore.projects
const projects = projectsStore.getProjects
const projectsInit = computed(() => projectsStore.isInit)
const searchProject = ref('')
const showArchive = ref(false)
const showDialogArchive = ref(false)
const archiveProjectId = ref<number | undefined> (undefined)
const showDialogRestoreArchive = ref(false)
const restoreProjectId = ref<number | undefined> (undefined)
async function goProject (id: number) {
await router.push({ name: 'chats', params: { id }})
@@ -201,12 +232,12 @@
}
function handleArchiveList (id: number) {
showDialogArchive.value = true
archiveProjectId.value = id
showDialogRestoreArchive.value = true
restoreProjectId.value = id
}
function restoreFromArchive () {
if (archiveProjectId.value) projectsStore.restore(archiveProjectId.value)
async function restoreFromArchive () {
if (restoreProjectId.value) await projectsStore.restore(restoreProjectId.value)
}
const displayProjects = computed(() => {
@@ -232,19 +263,63 @@
if (!projectsStore.isInit) {
await projectsStore.init()
}
if (!settingsStore.isInit) {
await settingsStore.init()
}
})
watch(showDialogArchive, (newD :boolean) => {
if (!newD) archiveProjectId.value = undefined
watch(showDialogRestoreArchive, (newD :boolean) => {
if (!newD) restoreProjectId.value = undefined
})
interface SlideEvent {
reset: () => void
}
const currentSlideEvent = ref<SlideEvent | null>(null)
const showDialogArchiveProject = ref<boolean>(false)
const archiveProjectId = ref<number | undefined>(undefined)
const closedByUserAction = ref(false)
function handleSlideRight (event: SlideEvent, id: number) {
currentSlideEvent.value = event
showDialogArchiveProject.value = true
archiveProjectId.value = id
}
function onDialogBeforeHide () {
if (!closedByUserAction.value) {
onCancel()
}
closedByUserAction.value = false
}
async function onConfirmArchiveProject () {
closedByUserAction.value = true
if (archiveProjectId.value) {
await projectsStore.archive(archiveProjectId.value)
}
currentSlideEvent.value = null
}
function onCancel() {
closedByUserAction.value = true
if (currentSlideEvent.value) {
currentSlideEvent.value.reset()
currentSlideEvent.value = null
}
}
</script>
<style scoped>
:deep(.q-slide-item__right) {
align-self: center;
height: 98%;
}
.fix-btn :deep(.q-btn__content) {
flex-wrap: nowrap;
}
.fix-rotate-arrow :deep(.q-btn-dropdown--simple) {
margin-left: 0;
}
</style>