@coopenomics/desktop 2025.5.14 → 2025.6.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env-example +4 -0
- package/extensions/participant/install.ts +37 -25
- package/extensions/soviet/install.ts +23 -20
- package/package.json +7 -5
- package/quasar.config.cjs +1 -1
- package/src/app/App.vue +1 -0
- package/src/app/providers/routes/index.ts +12 -0
- package/src/app/styles/app.scss +1 -1
- package/src/app/styles/style.css +11 -0
- package/src/css/quasar.variables.scss +1 -1
- package/src/entities/Desktop/model/store.ts +68 -0
- package/src/entities/Desktop/model/types.ts +7 -0
- package/src/entities/Document/model/types.ts +1 -1
- package/src/entities/Meet/api/index.ts +2 -28
- package/src/entities/Meet/model/store.ts +7 -22
- package/src/entities/Wallet/api/index.ts +3 -3
- package/src/env.d.ts +1 -0
- package/src/features/Meet/CloseMeetWithDecision/model/index.ts +119 -17
- package/src/features/Meet/CreateMeet/model/index.ts +51 -9
- package/src/features/Meet/CreateMeet/ui/CreateMeet.vue +37 -6
- package/src/features/Meet/CreateMeet/ui/CreateMeetForm.vue +87 -65
- package/src/features/Meet/GenerateSovietDecision/model/index.ts +14 -4
- package/src/features/Meet/RestartMeet/model/index.ts +121 -3
- package/src/features/Meet/RestartMeet/ui/RestartMeet.vue +4 -6
- package/src/features/Meet/RestartMeet/ui/RestartMeetForm.vue +64 -28
- package/src/features/Meet/SignNotification/index.ts +2 -0
- package/src/features/Meet/SignNotification/model/index.ts +137 -0
- package/src/features/Meet/SignNotification/ui/SignNotificationButton.vue +61 -0
- package/src/features/Meet/SignNotification/ui/index.ts +1 -0
- package/src/features/Meet/VoteOnMeet/model/composable.ts +180 -0
- package/src/features/Meet/VoteOnMeet/model/index.ts +2 -17
- package/src/features/Meet/VoteOnMeet/model/types.ts +4 -0
- package/src/features/Meet/index.ts +6 -0
- package/src/features/User/LoginRedirect/ui/LoginRedirectPage.vue +15 -0
- package/src/features/User/LoginRedirect/ui/index.ts +1 -0
- package/src/features/User/LoginUser/ui/LoginForm/LoginForm.vue +38 -1
- package/src/features/User/LoginWithRedirect/ui/LoginRedirectForm/LoginRedirectForm.vue +0 -0
- package/src/pages/Cooperative/ListOfMeets/ui/ListOfMeetsPage.vue +22 -46
- package/src/pages/Cooperative/MeetDetails/ui/MeetDetailsPage.vue +84 -28
- package/src/pages/PermissionDenied/PermissionDenied.vue +1 -1
- package/src/processes/init-app/index.ts +12 -5
- package/src/processes/navigation-guard-setup/index.ts +37 -5
- package/src/processes/process-decisions/index.ts +7 -6
- package/src/shared/config/Environment.ts +35 -27
- package/src/shared/lib/composables/index.ts +1 -0
- package/src/shared/lib/composables/useMeetStatus.ts +96 -0
- package/src/shared/lib/consts/index.ts +1 -0
- package/src/shared/lib/consts/meet-statuses.ts +114 -0
- package/src/shared/lib/document/model/entity.ts +4 -2
- package/src/shared/lib/types/certificate/index.ts +6 -0
- package/src/shared/lib/types/document/index.ts +1 -1
- package/src/shared/lib/types/workspace.ts +24 -0
- package/src/shared/lib/utils/dates/index.ts +5 -0
- package/src/shared/lib/utils/dates/moment.ts +43 -2
- package/src/shared/lib/utils/dates/timezone.ts +75 -0
- package/src/shared/lib/utils/getNameFromCertificate.ts +108 -0
- package/src/shared/lib/utils/index.ts +1 -0
- package/src/shared/lib/utils/parseLinks.ts +10 -0
- package/src/shared/ui/AgendaNumberAvatar/AgendaNumberAvatar.vue +12 -0
- package/src/shared/ui/AgendaNumberAvatar/index.ts +1 -0
- package/src/shared/ui/BaseDocument/BaseDocument.vue +37 -8
- package/src/shared/ui/ExpandableDocument/ExpandableDocument.vue +49 -0
- package/src/shared/ui/ExpandableDocument/index.ts +1 -0
- package/src/shared/ui/MeetInfoCard/index.ts +1 -0
- package/src/shared/ui/MeetInfoCard/ui/MeetInfoCard.vue +62 -0
- package/src/shared/ui/MeetStatusBanner/index.ts +1 -0
- package/src/shared/ui/MeetStatusBanner/ui/MeetStatusBanner.vue +94 -0
- package/src/shared/ui/index.ts +1 -0
- package/src/widgets/Cooperative/Documents/ListOfDocuments/ui/DocumentsTable.vue +3 -3
- package/src/widgets/Cooperative/Orders/ListOfOrders/ui/ListOfOrdersWidget.vue +2 -2
- package/src/widgets/Cooperative/Payments/ListOfPayments/ui/ListOfPaymentsWidget.vue +2 -2
- package/src/widgets/Desktop/WorkspaceMenu/WorkspaceMenu.vue +74 -82
- package/src/widgets/Header/CommonHeader/CooperativeSettingsHeader.vue +1 -1
- package/src/widgets/Header/CommonHeader/ExtstoreHeader.vue +1 -1
- package/src/widgets/Header/CommonHeader/MainHeader.vue +6 -0
- package/src/widgets/Header/CommonHeader/UserSettingsHeader.vue +1 -1
- package/src/widgets/Meets/MeetCardsList/index.ts +1 -0
- package/src/widgets/Meets/MeetCardsList/ui/MeetCardsList.vue +55 -0
- package/src/widgets/Meets/MeetDetailsActions/MeetDetailsActions.vue +33 -15
- package/src/widgets/Meets/MeetDetailsAgenda/MeetDetailsAgenda.vue +34 -15
- package/src/widgets/Meets/MeetDetailsInfo/MeetDetailsInfo.vue +27 -0
- package/src/widgets/Meets/MeetDetailsInfo/index.ts +1 -0
- package/src/widgets/Meets/MeetDetailsResults/MeetDetailsResults.vue +129 -0
- package/src/widgets/Meets/MeetDetailsResults/index.ts +1 -0
- package/src/widgets/Meets/MeetDetailsVoting/MeetDetailsVoting.vue +221 -62
- package/src/widgets/Meets/MeetQuorumIndicator/MeetQuorumIndicator.vue +0 -0
- package/src/widgets/Meets/MeetQuorumIndicator/index.ts +1 -0
- package/src/widgets/Meets/MeetQuorumIndicator/ui/MeetQuorumIndicator.vue +35 -0
- package/src/widgets/Meets/MeetsTable/ui/MeetsTable.vue +56 -65
- package/src/widgets/NotificationCenter/NotificationCenter.vue +90 -0
- package/src/widgets/NotificationCenter/index.ts +1 -0
- package/src/widgets/Participants/ui/ParticipantsTable.vue +1 -1
- package/src/widgets/Questions/ui/QuestionsTable/QuestionsTable.vue +22 -10
- package/src/widgets/Questions/ui/VotingButtons/VotingButtons.vue +59 -14
- package/src/widgets/Registrator/AlreadyRegistered/AlreadyRegistered.vue +1 -1
- package/src/widgets/User/PaymentMethods/ui/PaymentMethods.vue +0 -1
- package/src-ssr/middlewares/injectEnv.ts +18 -12
- package/src/features/Meet/GenerateAgenda/index.ts +0 -1
- package/src/features/Meet/GenerateAgenda/model/index.ts +0 -18
- package/src/features/Meet/GenerateBallot/index.ts +0 -1
- package/src/features/Meet/GenerateBallot/model/index.ts +0 -18
- package/src/features/Meet/GenerateNotification/index.ts +0 -1
- package/src/features/Meet/GenerateNotification/model/index.ts +0 -18
- package/src/features/Meet/MeetDetailsManagement/index.ts +0 -1
- package/src/features/Meet/MeetDetailsManagement/model/index.ts +0 -121
- package/src/pages/Cooperative/ListOfMeets/model/index.ts +0 -1
- package/src/pages/Cooperative/ListOfMeets/model/model.ts +0 -117
- package/src/widgets/Meets/MeetDetailsActions/model.ts +0 -46
- package/src/widgets/Meets/MeetDetailsHeader/MeetDetailsHeader.vue +0 -40
- package/src/widgets/Meets/MeetDetailsHeader/index.ts +0 -1
- package/src/widgets/Meets/MeetDetailsVoting/model.ts +0 -117
- package/src/widgets/Meets/MeetInfoCard/ui/MeetInfoCard.vue +0 -38
- package/src/widgets/Meets/MeetInfoCard/ui/index.ts +0 -1
- /package/src/{widgets/Meets/MeetInfoCard → features/User/LoginRedirect}/index.ts +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
export { default as AgendaNumberAvatar } from './AgendaNumberAvatar.vue';
|
@@ -29,7 +29,7 @@ q-card(:flat="isMobile" style="word-break: break-all !important; white-space: no
|
|
29
29
|
q-expansion-item(
|
30
30
|
v-for="(signature, index) in documentAggregate.document.signatures"
|
31
31
|
:key="index"
|
32
|
-
:label="`Подпись ${index + 1}: ${getSignerName(signature.
|
32
|
+
:label="`Подпись ${index + 1}: ${getSignerName(signature.signer_certificate)}`"
|
33
33
|
header-class="signature-header"
|
34
34
|
dense
|
35
35
|
)
|
@@ -38,7 +38,7 @@ q-card(:flat="isMobile" style="word-break: break-all !important; white-space: no
|
|
38
38
|
div.q-mb-sm
|
39
39
|
q-badge(:color="signature.is_valid ? 'teal' : 'red'").text-center.q-pa-xs
|
40
40
|
span Подписант
|
41
|
-
p.q-mt-sm.q-ml-lg {{ getSignerName(signature.
|
41
|
+
p.q-mt-sm.q-ml-lg {{ getSignerName(signature.signer_certificate) }}
|
42
42
|
|
43
43
|
div(v-if="signature.public_key").q-mb-sm
|
44
44
|
q-badge(:color="signature.is_valid ? 'teal' : 'red'").text-center.q-pa-xs
|
@@ -68,9 +68,9 @@ import { useGlobalStore } from 'src/shared/store';
|
|
68
68
|
import DOMPurify from 'dompurify';
|
69
69
|
import { DigitalDocument } from 'src/shared/lib/document';
|
70
70
|
import { FailAlert, SuccessAlert } from 'src/shared/api';
|
71
|
-
import { getNameFromUserData } from 'src/shared/lib/utils/getNameFromUserData';
|
72
71
|
import { useWindowSize } from 'src/shared/hooks';
|
73
72
|
import type { IDocumentAggregate } from 'src/entities/Document/model';
|
73
|
+
import { getNameFromCertificate } from 'src/shared/lib/utils/getNameFromCertificate';
|
74
74
|
|
75
75
|
const props = defineProps({
|
76
76
|
documentAggregate: {
|
@@ -106,7 +106,10 @@ const regenerate = async() => {
|
|
106
106
|
|
107
107
|
// Функция для декодирования и очистки HTML
|
108
108
|
function sanitizeHtml(html: string) {
|
109
|
-
return DOMPurify.sanitize(html
|
109
|
+
return DOMPurify.sanitize(html, {
|
110
|
+
ADD_TAGS: ['style'],
|
111
|
+
ADD_ATTR: ['class', 'id']
|
112
|
+
});
|
110
113
|
}
|
111
114
|
|
112
115
|
const safeHtml = computed(() => sanitizeHtml(doc.value?.html ?? ''));
|
@@ -131,10 +134,10 @@ const hashBuffer = async () => {
|
|
131
134
|
}
|
132
135
|
}
|
133
136
|
|
134
|
-
// Получение
|
135
|
-
const getSignerName = (
|
136
|
-
if (!
|
137
|
-
return
|
137
|
+
// Получение ФИО/названия подписанта по сертификату
|
138
|
+
const getSignerName = (signer_certificate: any) => {
|
139
|
+
if (!signer_certificate) return 'Неизвестный подписант';
|
140
|
+
return getNameFromCertificate(signer_certificate) || 'Неизвестный подписант';
|
138
141
|
}
|
139
142
|
|
140
143
|
// Верификация всех подписей из агрегата
|
@@ -228,4 +231,30 @@ const hasInvalidSignature = computed(() => props.documentAggregate?.document?.si
|
|
228
231
|
padding: 10px !important;
|
229
232
|
}
|
230
233
|
}
|
234
|
+
/*
|
235
|
+
/* Стили для таблиц внутри документа */
|
236
|
+
.description table {
|
237
|
+
width: 100%;
|
238
|
+
border-collapse: collapse;
|
239
|
+
}
|
240
|
+
|
241
|
+
.description th,
|
242
|
+
.description td {
|
243
|
+
border: 1px solid #ccc;
|
244
|
+
padding: 8px;
|
245
|
+
text-align: left;
|
246
|
+
word-wrap: break-word;
|
247
|
+
overflow-wrap: break-word;
|
248
|
+
}
|
249
|
+
|
250
|
+
.description th {
|
251
|
+
background-color: #f4f4f4;
|
252
|
+
width: 30% !important;
|
253
|
+
max-width: 30% !important;
|
254
|
+
word-break: break-word !important;
|
255
|
+
}
|
256
|
+
.q-table--no-wrap th, .q-table--no-wrap td {
|
257
|
+
white-space: break-spaces !important;
|
258
|
+
word-break: break-word !important;
|
259
|
+
}
|
231
260
|
</style>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<template lang="pug">
|
2
|
+
q-card(flat).expandable-document.q-mb-md
|
3
|
+
q-expansion-item(
|
4
|
+
switch-toggle-side
|
5
|
+
:label="title || 'Электронный документ'"
|
6
|
+
icon="article"
|
7
|
+
header-class="document-header"
|
8
|
+
expand-icon-class="text-primary"
|
9
|
+
)
|
10
|
+
q-card
|
11
|
+
q-card-section
|
12
|
+
div.row.justify-center
|
13
|
+
BaseDocument(
|
14
|
+
:documentAggregate="documentAggregate"
|
15
|
+
).col-xs-12.col-md-10
|
16
|
+
</template>
|
17
|
+
|
18
|
+
<script setup lang="ts">
|
19
|
+
import { BaseDocument } from '../BaseDocument'
|
20
|
+
import type { IDocumentAggregate } from 'src/entities/Document/model'
|
21
|
+
|
22
|
+
defineProps({
|
23
|
+
documentAggregate: {
|
24
|
+
type: Object as () => IDocumentAggregate,
|
25
|
+
required: true
|
26
|
+
},
|
27
|
+
title: {
|
28
|
+
type: String,
|
29
|
+
default: 'Документ собрания'
|
30
|
+
}
|
31
|
+
})
|
32
|
+
</script>
|
33
|
+
|
34
|
+
<style lang="scss" scoped>
|
35
|
+
.expandable-document {
|
36
|
+
width: 100%;
|
37
|
+
border: 1px solid #f0f0f0;
|
38
|
+
border-radius: 8px;
|
39
|
+
|
40
|
+
:deep(.document-header) {
|
41
|
+
font-weight: 500;
|
42
|
+
border-radius: 8px;
|
43
|
+
|
44
|
+
.q-icon {
|
45
|
+
color: var(--q-primary);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
</style>
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as ExpandableDocument } from './ExpandableDocument.vue'
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as MeetInfoCard } from './ui/MeetInfoCard.vue'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
<template lang="pug">
|
2
|
+
div
|
3
|
+
div.row.q-mb-sm
|
4
|
+
div.col-12
|
5
|
+
div.text-h5.q-mb-xs.full-width.text-center Общее собрание № {{ meet.processing?.meet?.id }}
|
6
|
+
|
7
|
+
|
8
|
+
div.row.justify-around.q-mt-md
|
9
|
+
div.col-xs-12.col-md-5
|
10
|
+
|
11
|
+
div.row.q-mb-sm.items-baseline
|
12
|
+
div.col-xs-12.col-sm-5.card-label Председатель:
|
13
|
+
div.col-xs-12.col-sm-7.card-value {{ getNameFromCertificate(meet.processing?.meet?.presider_certificate) }}
|
14
|
+
|
15
|
+
div.row.q-mb-sm.items-baseline
|
16
|
+
div.col-xs-12.col-sm-5.card-label Секретарь:
|
17
|
+
div.col-xs-12.col-sm-7.card-value {{ getNameFromCertificate(meet.processing?.meet?.secretary_certificate) }}
|
18
|
+
|
19
|
+
div.row.q-mb-sm.items-baseline
|
20
|
+
div.col-xs-12.col-sm-5.card-label Открытие:
|
21
|
+
div.col-xs-12.col-sm-7.card-value {{ meetStatus.formattedOpenDate }} ({{ timezoneLabel }})
|
22
|
+
|
23
|
+
div.col-xs-12.col-md-5
|
24
|
+
div.row.q-mb-sm.items-baseline
|
25
|
+
div.col-xs-12.col-sm-5.card-label Кворум:
|
26
|
+
div.col-xs-12.col-sm-7.card-value {{ meet.processing?.meet?.quorum_percent }}%
|
27
|
+
|
28
|
+
div.row.q-mb-sm.items-baseline
|
29
|
+
div.col-xs-12.col-sm-5.card-label Явка:
|
30
|
+
div.col-xs-12.col-sm-7.card-value {{ (Math.round((meet.processing?.meet?.current_quorum_percent ?? 0) * 10) / 10).toFixed(1) }}%
|
31
|
+
|
32
|
+
|
33
|
+
div.row.q-mb-sm.items-baseline
|
34
|
+
div.col-xs-12.col-sm-5.card-label Закрытие:
|
35
|
+
div.col-xs-12.col-sm-7.card-value {{ meetStatus.formattedCloseDate }} ({{ timezoneLabel }})
|
36
|
+
|
37
|
+
div.row.justify-around.q-mt-lg
|
38
|
+
MeetStatusBanner(:meet="meet")
|
39
|
+
|
40
|
+
|
41
|
+
</template>
|
42
|
+
|
43
|
+
<script setup lang="ts">
|
44
|
+
import type { IMeet } from 'src/entities/Meet'
|
45
|
+
import { useMeetStatus } from 'src/shared/lib/composables'
|
46
|
+
import { getNameFromCertificate } from 'src/shared/lib/utils/getNameFromCertificate'
|
47
|
+
import { MeetStatusBanner } from 'src/shared/ui/MeetStatusBanner'
|
48
|
+
import { getTimezoneLabel } from 'src/shared/lib/utils/dates/timezone'
|
49
|
+
|
50
|
+
const props = defineProps<{
|
51
|
+
meet: IMeet
|
52
|
+
}>()
|
53
|
+
|
54
|
+
// Название часового пояса для отображения в лейблах
|
55
|
+
const timezoneLabel = getTimezoneLabel()
|
56
|
+
|
57
|
+
const meetStatus = useMeetStatus(props.meet)
|
58
|
+
</script>
|
59
|
+
|
60
|
+
<style lang="scss" scoped>
|
61
|
+
@import 'src/shared/ui/CardStyles/index.scss';
|
62
|
+
</style>
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as MeetStatusBanner } from './ui/MeetStatusBanner.vue'
|
@@ -0,0 +1,94 @@
|
|
1
|
+
<template lang="pug">
|
2
|
+
// Баннер с информацией о статусе собрания
|
3
|
+
div.full-width
|
4
|
+
q-banner(
|
5
|
+
v-if="extendedStatus && extendedStatus !== 'NONE'",
|
6
|
+
rounded,
|
7
|
+
:class="bannerClasses"
|
8
|
+
:style="bannerStyle"
|
9
|
+
).q-pa-md
|
10
|
+
template(v-slot:avatar)
|
11
|
+
q-icon(:name="bannerConfig.icon" :color="iconColor")
|
12
|
+
div {{ statusText }} {{ timeText }}
|
13
|
+
|
14
|
+
|
15
|
+
</template>
|
16
|
+
|
17
|
+
<script setup lang="ts">
|
18
|
+
import { computed } from 'vue'
|
19
|
+
import type { IMeet } from 'src/entities/Meet'
|
20
|
+
import { EXTENDED_STATUS_MAP, STATUS_BANNER_CONFIG } from 'src/shared/lib/consts'
|
21
|
+
import { formatDateFromNow } from 'src/shared/lib/utils/dates/timezone'
|
22
|
+
|
23
|
+
const props = defineProps<{
|
24
|
+
meet: IMeet
|
25
|
+
}>()
|
26
|
+
|
27
|
+
// Получаем расширенный статус собрания
|
28
|
+
const extendedStatus = computed(() => {
|
29
|
+
return props.meet?.processing?.extendedStatus || 'NONE'
|
30
|
+
})
|
31
|
+
|
32
|
+
// Текст статуса собрания
|
33
|
+
const statusText = computed(() => {
|
34
|
+
if (!props.meet?.processing?.extendedStatus) return 'Неизвестный статус'
|
35
|
+
return EXTENDED_STATUS_MAP[props.meet.processing.extendedStatus] || 'Неизвестный статус'
|
36
|
+
})
|
37
|
+
|
38
|
+
// Конфигурация баннера
|
39
|
+
const bannerConfig = computed(() => {
|
40
|
+
if (!props.meet?.processing?.extendedStatus) {
|
41
|
+
return STATUS_BANNER_CONFIG['NONE']
|
42
|
+
}
|
43
|
+
return (
|
44
|
+
STATUS_BANNER_CONFIG[props.meet.processing.extendedStatus] || STATUS_BANNER_CONFIG['NONE']
|
45
|
+
)
|
46
|
+
})
|
47
|
+
|
48
|
+
const bannerClasses = computed(() => {
|
49
|
+
const config = bannerConfig.value
|
50
|
+
if (config.outline) {
|
51
|
+
return 'bg-grey-1 outlined-banner'
|
52
|
+
}
|
53
|
+
return `bg-${config.color} text-white`
|
54
|
+
})
|
55
|
+
|
56
|
+
const bannerStyle = computed(() => {
|
57
|
+
const config = bannerConfig.value
|
58
|
+
if (config.outline) {
|
59
|
+
return { borderColor: `var(--q-color-${config.color})` }
|
60
|
+
}
|
61
|
+
return {}
|
62
|
+
})
|
63
|
+
|
64
|
+
const iconColor = computed(() => {
|
65
|
+
const config = bannerConfig.value
|
66
|
+
return config.outline ? config.color : 'white'
|
67
|
+
})
|
68
|
+
|
69
|
+
// Форматированное время до открытия/закрытия с учетом часового пояса
|
70
|
+
const timeText = computed(() => {
|
71
|
+
if (!bannerConfig.value.needTime) return ''
|
72
|
+
|
73
|
+
// Для статуса WAITING_FOR_OPENING
|
74
|
+
if (props.meet?.processing?.extendedStatus === 'WAITING_FOR_OPENING') {
|
75
|
+
if (!props.meet?.processing?.meet?.open_at) return ''
|
76
|
+
return formatDateFromNow(props.meet.processing.meet.open_at)
|
77
|
+
}
|
78
|
+
|
79
|
+
// Для статуса VOTING_IN_PROGRESS
|
80
|
+
if (props.meet?.processing?.extendedStatus === 'VOTING_IN_PROGRESS') {
|
81
|
+
if (!props.meet?.processing?.meet?.close_at) return ''
|
82
|
+
return formatDateFromNow(props.meet.processing.meet.close_at)
|
83
|
+
}
|
84
|
+
|
85
|
+
return ''
|
86
|
+
})
|
87
|
+
</script>
|
88
|
+
|
89
|
+
<style lang="scss" scoped>
|
90
|
+
.outlined-banner {
|
91
|
+
border-width: 1px;
|
92
|
+
border-style: solid;
|
93
|
+
}
|
94
|
+
</style>
|
package/src/shared/ui/index.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<template lang="pug">
|
2
|
-
div.scroll-area(style="height:
|
2
|
+
div.scroll-area(style="height: calc(100% - $toolbar-min-height); overflow-y: auto;")
|
3
3
|
q-table(
|
4
4
|
ref="tableRef"
|
5
5
|
flat
|
@@ -45,7 +45,7 @@ div.scroll-area(style="height: 90vh; overflow-y: auto;")
|
|
45
45
|
color="primary"
|
46
46
|
round
|
47
47
|
dense
|
48
|
-
:icon="expanded.get(props.row?.id || props.row?.statement?.action?.global_sequence) ? '
|
48
|
+
:icon="expanded.get(props.row?.id || props.row?.statement?.action?.global_sequence) ? 'expand_more' : 'chevron_right'"
|
49
49
|
@click="toggleExpand(props.row?.id || props.row?.statement?.action?.global_sequence)"
|
50
50
|
)
|
51
51
|
|
@@ -160,4 +160,4 @@ const toggleExpand = (id: any) => {
|
|
160
160
|
.documents-table .q-table__top{
|
161
161
|
padding: 0px !important;
|
162
162
|
}
|
163
|
-
</style>
|
163
|
+
</style>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<template lang="pug">
|
2
2
|
div.row.justify-center
|
3
3
|
div.col-12
|
4
|
-
div.scroll-area(style="height:
|
4
|
+
div.scroll-area(style="height: calc(100% - $toolbar-min-height); overflow-y: auto;")
|
5
5
|
q-table(
|
6
6
|
v-if="payments && payments.items"
|
7
7
|
ref="tableRef"
|
@@ -48,7 +48,7 @@
|
|
48
48
|
color="primary"
|
49
49
|
round
|
50
50
|
dense
|
51
|
-
:icon="expanded.get(props.row.id) ? '
|
51
|
+
:icon="expanded.get(props.row.id) ? 'expand_more' : 'chevron_right'"
|
52
52
|
@click="toggleExpand(props.row.id)"
|
53
53
|
)
|
54
54
|
q-td {{props.row.id}}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<template lang="pug">
|
2
2
|
div.row.justify-center
|
3
3
|
div.col-12
|
4
|
-
div.scroll-area(style="height:
|
4
|
+
div.scroll-area(style="height: calc(100% - $toolbar-min-height); overflow-y: auto;")
|
5
5
|
q-table(
|
6
6
|
v-if="payments && payments.items"
|
7
7
|
ref="tableRef"
|
@@ -47,7 +47,7 @@
|
|
47
47
|
color="primary"
|
48
48
|
round
|
49
49
|
dense
|
50
|
-
:icon="expanded.get(props.row.id) ? '
|
50
|
+
:icon="expanded.get(props.row.id) ? 'expand_more' : 'chevron_right'"
|
51
51
|
@click="toggleExpand(props.row.id)"
|
52
52
|
)
|
53
53
|
q-td(style="max-width: 150px; word-wrap: break-word; white-space: normal;") {{ getName(props.row.account) }}
|
@@ -53,99 +53,91 @@ div
|
|
53
53
|
div.btn-font.text-center {{ item.title }}
|
54
54
|
</template>
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
import { useDesktopStore } from 'src/entities/Desktop/model'
|
62
|
-
import { useSessionStore } from 'src/entities/Session'
|
56
|
+
<script setup lang="ts">
|
57
|
+
import { ref, computed, onMounted, watch } from 'vue'
|
58
|
+
import { useRouter } from 'vue-router'
|
59
|
+
import { useCurrentUserStore } from 'src/entities/User'
|
60
|
+
import { useDesktopStore } from 'src/entities/Desktop/model'
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
const session = useSessionStore()
|
68
|
-
const desktop = useDesktopStore()
|
69
|
-
const { info } = system
|
62
|
+
const router = useRouter()
|
63
|
+
const user = useCurrentUserStore()
|
64
|
+
const desktop = useDesktopStore()
|
70
65
|
|
71
|
-
|
72
|
-
|
66
|
+
const slideIndex = ref(0)
|
67
|
+
const showDialog = ref(false)
|
73
68
|
|
74
|
-
|
75
|
-
|
69
|
+
// workspaceMenus – список рабочих столов из store
|
70
|
+
const workspaceMenus = computed(() => desktop.workspaceMenus)
|
76
71
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
const headerClass = (item: any) => {
|
86
|
-
return desktop?.activeWorkspaceName === item.workspaceName ? 'text-white bg-teal' : ''
|
87
|
-
}
|
88
|
-
|
89
|
-
|
90
|
-
// Функция навигации: переходим в рамках маршрутов рабочего стола
|
91
|
-
const open = (route: any) => {
|
92
|
-
if (route && route.children && route.children.length)
|
93
|
-
router.push({ name: route.children[0].name, params: { coopname: info.coopname } })
|
94
|
-
else if (route)
|
95
|
-
router.push({ name: route.name, params: { coopname: info.coopname } })
|
96
|
-
}
|
72
|
+
// Фильтрация по ролям (если требуется)
|
73
|
+
const menuWorkspaces = computed(() => {
|
74
|
+
const userRole = user.userAccount?.role || 'user'
|
75
|
+
return workspaceMenus.value.filter(item =>
|
76
|
+
item.meta.roles?.includes(userRole) || !item.meta.roles || item.meta.roles.length === 0
|
77
|
+
)
|
78
|
+
})
|
97
79
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
} else {
|
102
|
-
slideIndex.value = index
|
103
|
-
// Обновляем активный рабочий стол
|
104
|
-
desktop.selectWorkspace(item.workspaceName)
|
105
|
-
if (item.mainRoute) open(item.mainRoute)
|
106
|
-
}
|
107
|
-
}
|
80
|
+
const headerClass = (item: any) => {
|
81
|
+
return desktop?.activeWorkspaceName === item.workspaceName ? 'text-white bg-teal' : ''
|
82
|
+
}
|
108
83
|
|
109
|
-
|
110
|
-
|
84
|
+
const handleClick = (item: any, index: number) => {
|
85
|
+
if (slideIndex.value === index) {
|
86
|
+
showDialog.value = true
|
87
|
+
} else {
|
111
88
|
slideIndex.value = index
|
112
|
-
|
89
|
+
// Обновляем активный рабочий стол
|
113
90
|
desktop.selectWorkspace(item.workspaceName)
|
114
|
-
|
91
|
+
// Переходим на маршрут по умолчанию для выбранного рабочего стола
|
92
|
+
desktop.goToDefaultPage(router)
|
115
93
|
}
|
94
|
+
}
|
116
95
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
96
|
+
const selectFromDialog = (index: number) => {
|
97
|
+
showDialog.value = false
|
98
|
+
slideIndex.value = index
|
99
|
+
const item = menuWorkspaces.value[index]
|
100
|
+
desktop.selectWorkspace(item.workspaceName)
|
101
|
+
// Переходим на маршрут по умолчанию для выбранного рабочего стола
|
102
|
+
desktop.goToDefaultPage(router)
|
103
|
+
}
|
125
104
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
105
|
+
onMounted(() => {
|
106
|
+
// Находим индекс активного рабочего стола
|
107
|
+
const activeWorkspaceName = desktop.activeWorkspaceName
|
108
|
+
if (activeWorkspaceName) {
|
109
|
+
const activeIndex = menuWorkspaces.value.findIndex(
|
110
|
+
item => item.workspaceName === activeWorkspaceName
|
111
|
+
)
|
112
|
+
if (activeIndex !== -1) {
|
113
|
+
slideIndex.value = activeIndex
|
132
114
|
}
|
133
|
-
})
|
134
|
-
</script>
|
135
|
-
|
136
|
-
<style lang="scss">
|
137
|
-
.btn-menu {
|
138
|
-
height: 100px;
|
139
|
-
width: 100px;
|
140
|
-
border-radius: 0 !important;
|
141
|
-
}
|
142
|
-
.btn-icon {
|
143
|
-
font-size: 20px !important;
|
144
115
|
}
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
116
|
+
})
|
117
|
+
|
118
|
+
// При изменении slideIndex обновляем активный рабочий стол
|
119
|
+
watch(slideIndex, (newIndex) => {
|
120
|
+
const item = menuWorkspaces.value[newIndex]
|
121
|
+
if (item) {
|
122
|
+
desktop.selectWorkspace(item.workspaceName)
|
123
|
+
desktop.goToDefaultPage(router)
|
150
124
|
}
|
151
|
-
|
125
|
+
})
|
126
|
+
</script>
|
127
|
+
|
128
|
+
<style lang="scss">
|
129
|
+
.btn-menu {
|
130
|
+
height: 100px;
|
131
|
+
width: 100px;
|
132
|
+
border-radius: 0 !important;
|
133
|
+
}
|
134
|
+
.btn-icon {
|
135
|
+
font-size: 20px !important;
|
136
|
+
}
|
137
|
+
.btn-font {
|
138
|
+
font-size: 8px !important;
|
139
|
+
}
|
140
|
+
.workspace-menu .q-carousel__slide {
|
141
|
+
padding: 0px !important;
|
142
|
+
}
|
143
|
+
</style>
|
@@ -11,7 +11,7 @@ q-header(bordered).bg-gradient-dark
|
|
11
11
|
active-class="bg-teal"
|
12
12
|
active-bg-color="teal"
|
13
13
|
active-color="white"
|
14
|
-
indicator-color="
|
14
|
+
indicator-color="primary"
|
15
15
|
class="header-tab-container"
|
16
16
|
)
|
17
17
|
q-route-tab(name="Совет" label="Совет" :to="{name: 'members'}" )
|
@@ -11,7 +11,7 @@ q-header(bordered).bg-gradient-dark
|
|
11
11
|
active-class="bg-teal"
|
12
12
|
active-bg-color="teal"
|
13
13
|
active-color="white"
|
14
|
-
indicator-color="
|
14
|
+
indicator-color="primary"
|
15
15
|
class="header-tab-container"
|
16
16
|
)
|
17
17
|
q-route-tab(name="Все приложения" label="Все приложения" :to="{name: 'extstore-showcase'}" )
|
@@ -6,6 +6,9 @@ q-header(bordered :class="headerClass").header
|
|
6
6
|
BackButton(v-if="loggedIn")
|
7
7
|
q-toolbar-title()
|
8
8
|
|
9
|
+
// Добавляем компонент уведомлений, если пользователь авторизован
|
10
|
+
NotificationCenter(v-if="loggedIn && isClient")
|
11
|
+
|
9
12
|
SettingsDropdown(:isMobile="isMobile" :isChairman="isChairman" :isMember="isMember")
|
10
13
|
|
11
14
|
template(v-if="!loggedIn")
|
@@ -40,6 +43,7 @@ import config from 'src/app/config'
|
|
40
43
|
import { useWindowSize } from 'src/shared/hooks'
|
41
44
|
import { SettingsDropdown } from 'src/widgets/Header/SettingsDropdown'
|
42
45
|
import { BackButton } from 'src/widgets/Header/BackButton'
|
46
|
+
import { NotificationCenter } from 'src/widgets/NotificationCenter'
|
43
47
|
import './HeaderStyles.scss'
|
44
48
|
// import { env } from 'src/shared/config'
|
45
49
|
|
@@ -50,6 +54,8 @@ const session = useSessionStore()
|
|
50
54
|
const { isMobile } = useWindowSize()
|
51
55
|
const emit = defineEmits(['toggle-left-drawer'])
|
52
56
|
|
57
|
+
const isClient = computed(() => typeof process !== 'undefined' && process.env.CLIENT)
|
58
|
+
|
53
59
|
// Получаем информацию для навигации назад
|
54
60
|
// const coopTitle = computed(() => env.COOP_SHORT_NAME)
|
55
61
|
|
@@ -11,7 +11,7 @@ q-header(bordered).flex.bg-gradient-dark
|
|
11
11
|
active-class="bg-teal"
|
12
12
|
active-bg-color="teal"
|
13
13
|
active-color="white"
|
14
|
-
indicator-color="
|
14
|
+
indicator-color="primary"
|
15
15
|
class="header-tab-container"
|
16
16
|
)
|
17
17
|
q-route-tab(name="Реквизиты" label="Реквизиты" :to="{name: 'user-payment-methods'}" )
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as MeetCardsList } from './ui/MeetCardsList.vue'
|