@coopenomics/desktop 2025.11.9-alpha-1 → 2025.11.9-alpha-2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coopenomics/desktop",
3
- "version": "2025.11.9-alpha-1",
3
+ "version": "2025.11.9-alpha-2",
4
4
  "description": "A Desktop Project",
5
5
  "productName": "Desktop App",
6
6
  "author": "Alex Ant <dacom.dark.sun@gmail.com>",
@@ -25,9 +25,9 @@
25
25
  "start": "node -r ./alias-resolver.js dist/ssr/index.js"
26
26
  },
27
27
  "dependencies": {
28
- "@coopenomics/controller": "2025.11.9-alpha-1",
29
- "@coopenomics/notifications": "2025.11.9-alpha-1",
30
- "@coopenomics/sdk": "2025.11.9-alpha-1",
28
+ "@coopenomics/controller": "2025.11.9-alpha-2",
29
+ "@coopenomics/notifications": "2025.11.9-alpha-2",
30
+ "@coopenomics/sdk": "2025.11.9-alpha-2",
31
31
  "@dicebear/collection": "^9.0.1",
32
32
  "@dicebear/core": "^9.0.1",
33
33
  "@editorjs/code": "^2.9.3",
@@ -59,7 +59,7 @@
59
59
  "@wharfkit/wallet-plugin-privatekey": "^1.1.0",
60
60
  "axios": "^1.2.1",
61
61
  "compression": "^1.7.4",
62
- "cooptypes": "2025.11.9-alpha-1",
62
+ "cooptypes": "2025.11.9-alpha-2",
63
63
  "dompurify": "^3.1.7",
64
64
  "dotenv": "^16.4.5",
65
65
  "email-regex": "^5.0.0",
@@ -123,5 +123,5 @@
123
123
  "npm": ">= 6.13.4",
124
124
  "yarn": ">= 1.21.1"
125
125
  },
126
- "gitHead": "8270801711836de12cce027677732785fab42dd1"
126
+ "gitHead": "5acd7ae2c437ce54f356113b5474700114f586ab"
127
127
  }
@@ -0,0 +1,12 @@
1
+ import { client } from 'src/shared/api/client';
2
+ import { Queries } from '@coopenomics/sdk';
3
+
4
+ /**
5
+ * Получить подписки пользователя у провайдера
6
+ */
7
+ export async function loadProviderSubscriptions() {
8
+ const { [Queries.System.GetProviderSubscriptions.name]: subscriptions } =
9
+ await client.Query(Queries.System.GetProviderSubscriptions.query);
10
+
11
+ return subscriptions;
12
+ }
@@ -0,0 +1 @@
1
+ export * from './model';
@@ -0,0 +1,105 @@
1
+ import { ref, computed } from 'vue';
2
+ import { loadProviderSubscriptions } from '../api';
3
+ import { useSystemStore } from 'src/entities/System/model';
4
+ import { Queries } from '@coopenomics/sdk';
5
+
6
+ /**
7
+ * Специфичные данные для подписки на хостинг
8
+ */
9
+ export interface HostingSubscriptionData {
10
+ subscription_type_id: 1;
11
+ progress: number;
12
+ is_valid: boolean;
13
+ }
14
+
15
+ /**
16
+ * Специфичные данные подписки (union тип для всех типов подписок)
17
+ */
18
+ export type SubscriptionSpecificData = HostingSubscriptionData | null;
19
+
20
+ /**
21
+ * Тип подписки провайдера из GraphQL API
22
+ */
23
+ export type ProviderSubscription = Queries.System.GetProviderSubscriptions.IOutput[typeof Queries.System.GetProviderSubscriptions.name][number];
24
+
25
+ /**
26
+ * Composable для работы с подписками провайдера
27
+ */
28
+ export function useProviderSubscriptions() {
29
+ const system = useSystemStore();
30
+ const subscriptions = ref<ProviderSubscription[]>([]);
31
+ const isLoading = ref(false);
32
+ const error = ref<string | null>(null);
33
+
34
+ // Получить подписку на хостинг (id=1)
35
+ const hostingSubscription = computed(() =>
36
+ subscriptions.value.find(sub => sub.subscription_type_id === 1)
37
+ );
38
+
39
+ // Статус валидности домена для хостинг подписки (из specific_data)
40
+ const domainValid = computed(() => {
41
+ const specificData = hostingSubscription.value?.specific_data as SubscriptionSpecificData;
42
+ return specificData?.is_valid ?? null;
43
+ });
44
+
45
+ // Прогресс установки для хостинг подписки (из specific_data)
46
+ const installationProgress = computed(() => {
47
+ const specificData = hostingSubscription.value?.specific_data as SubscriptionSpecificData;
48
+ return specificData?.progress ?? null;
49
+ });
50
+
51
+ // Статус инстанса для хостинг подписки (пока оставляем как есть, может поле будет добавлено позже)
52
+ const instanceStatus = computed(() =>
53
+ hostingSubscription.value?.instance_status ?? null
54
+ );
55
+
56
+ /**
57
+ * Загрузить подписки пользователя
58
+ */
59
+ const loadSubscriptions = async () => {
60
+ // Проверяем доступность провайдера
61
+ if (!system.info.is_providered) {
62
+ error.value = 'Функционал провайдера не доступен';
63
+ return;
64
+ }
65
+
66
+ try {
67
+ isLoading.value = true;
68
+ error.value = null;
69
+ subscriptions.value = await loadProviderSubscriptions();
70
+ } catch (err: any) {
71
+ error.value = err.message || 'Ошибка загрузки подписок';
72
+ console.error('Error loading provider subscriptions:', err);
73
+ } finally {
74
+ isLoading.value = false;
75
+ }
76
+ };
77
+
78
+ /**
79
+ * Автоматическая загрузка с интервалом
80
+ */
81
+ const startAutoRefresh = (intervalMs = 60000) => { // 1 минута по умолчанию
82
+ loadSubscriptions(); // Первая загрузка
83
+
84
+ const interval = setInterval(() => {
85
+ loadSubscriptions();
86
+ }, intervalMs);
87
+
88
+ // Функция для остановки автообновления
89
+ const stop = () => clearInterval(interval);
90
+
91
+ return stop;
92
+ };
93
+
94
+ return {
95
+ subscriptions,
96
+ isLoading,
97
+ error,
98
+ hostingSubscription,
99
+ domainValid,
100
+ installationProgress,
101
+ instanceStatus,
102
+ loadSubscriptions,
103
+ startAutoRefresh,
104
+ };
105
+ }
@@ -1,21 +1,22 @@
1
1
  <template lang="pug">
2
2
  div.row.justify-center.q-pa-md
3
3
  div.col-md-8.col-xs-12
4
- div(v-if="is_finish == false")
5
- div(v-if="!signedDocument")
6
- div(v-if="html")
7
- DocumentHtmlReader(:html="html")
8
- q-btn(@click="sign" color="primary") подписать
4
+ div(v-if="system.info.is_providered")
5
+ div(v-if="is_finish == false")
6
+ div(v-if="!signedDocument")
7
+ div(v-if="html")
8
+ DocumentHtmlReader(:html="html")
9
+ q-btn(@click="sign" color="primary") подписать
9
10
 
10
- div(v-else)
11
- Loader(:text='`Готовим соглашение...`')
11
+ div(v-else)
12
+ Loader(:text='`Готовим соглашение...`')
12
13
 
13
- div(v-else)
14
- p.text-h6 Предварительная настройка
15
- p Пожалуйста, укажите домен для установки MONO. Также, укажите суммы вступительных и минимальных паевых взносов для физических лиц, юридических лиц и индивидуальных предпринимателей:
14
+ div(v-else)
15
+ p.text-h6 Предварительная настройка
16
+ p Пожалуйста, укажите домен для установки MONO. Также, укажите суммы вступительных и минимальных паевых взносов для физических лиц, юридических лиц и индивидуальных предпринимателей:
16
17
 
17
- AddCooperativeForm(:document="signedDocument" @finish="finish").q-pt-md
18
- div(v-if="is_finish == true && coop")
18
+ AddCooperativeForm(:document="signedDocument" @finish="finish").q-pt-md
19
+ div(v-if="is_finish == true && coop")
19
20
 
20
21
  p.text-h6 Кооператив на подключении
21
22
  p Статус:
@@ -27,6 +28,89 @@ div.row.justify-center.q-pa-md
27
28
  q-icon(name="refresh")
28
29
  span обновить
29
30
 
31
+ div(v-else)
32
+ //- Заглушка для недоступного провайдера
33
+ q-banner(
34
+ :class="'text-white bg-blue-500'"
35
+ rounded
36
+ )
37
+ template(v-slot:avatar)
38
+ q-icon(name="info" color="white")
39
+ span Для подключения к Кооперативной Экономике обратитесь в ПК ВОСХОД
40
+ q-btn(
41
+ flat
42
+ color="white"
43
+ label="Перейти на сайт"
44
+ @click="openProviderWebsite"
45
+ size="sm"
46
+ ).q-ml-md
47
+
48
+ div(v-if="system.info.is_providered").q-mt-md
49
+ p.text-subtitle1 Статус подписки на хостинг:
50
+
51
+ //- Статус подписки (только если провайдер доступен)
52
+ div
53
+ div(
54
+ v-if="subscriptionsError"
55
+ ).q-mb-md
56
+ q-banner(
57
+ :class="'text-white bg-red-500'"
58
+ rounded
59
+ )
60
+ template(v-slot:avatar)
61
+ q-icon(name="error" color="white")
62
+ span {{ subscriptionsError }}
63
+
64
+ div.flex.items-center.q-gutter-sm
65
+ div
66
+ span.text-body2 Валидность домена:
67
+ q-badge(
68
+ v-if="domainValid === true"
69
+ color="green"
70
+ ).q-ml-sm валиден
71
+ q-badge(
72
+ v-if="domainValid === false"
73
+ color="red"
74
+ ).q-ml-sm не валиден
75
+ q-badge(
76
+ v-if="domainValid === null && !subscriptionsLoading"
77
+ color="grey"
78
+ ).q-ml-sm неизвестно
79
+ q-badge(
80
+ v-if="subscriptionsLoading"
81
+ color="blue"
82
+ ).q-ml-sm загрузка...
83
+
84
+ div
85
+ span.text-body2 Прогресс установки:
86
+ q-badge(
87
+ v-if="installationProgress !== null"
88
+ :color="installationProgress === 100 ? 'green' : 'orange'"
89
+ ).q-ml-sm {{ installationProgress }}%
90
+ q-badge(
91
+ v-if="installationProgress === null && !subscriptionsLoading"
92
+ color="grey"
93
+ ).q-ml-sm неизвестно
94
+ q-badge(
95
+ v-if="subscriptionsLoading"
96
+ color="blue"
97
+ ).q-ml-sm загрузка...
98
+
99
+ div
100
+ span.text-body2 Статус сервера:
101
+ q-badge(
102
+ v-if="instanceStatus"
103
+ :color="instanceStatus === 'active' ? 'green' : instanceStatus === 'error' ? 'red' : 'orange'"
104
+ ).q-ml-sm {{ instanceStatus }}
105
+ q-badge(
106
+ v-if="!instanceStatus && !subscriptionsLoading"
107
+ color="grey"
108
+ ).q-ml-sm неизвестно
109
+ q-badge(
110
+ v-if="subscriptionsLoading"
111
+ color="blue"
112
+ ).q-ml-sm загрузка...
113
+
30
114
  p Пожалуйста, перешлите инструкцию ниже вашему техническому специалисту. После её выполнения, мы автоматически выполним запуск. Далее, Вам необходимо завершить установку уже на Вашем сайте следуя инструкциям, представленным там.
31
115
 
32
116
  q-card(flat bordered).q-pa-sm
@@ -39,18 +123,29 @@ div.row.justify-center.q-pa-md
39
123
  <script setup lang="ts">
40
124
  import { DigitalDocument } from 'src/shared/lib/document';
41
125
  import { useSessionStore } from 'src/entities/Session';
126
+ import { useSystemStore } from 'src/entities/System/model';
42
127
  import { DocumentHtmlReader } from 'src/shared/ui/DocumentHtmlReader';
43
- import { computed, ref } from 'vue';
128
+ import { computed, ref, onMounted, onUnmounted } from 'vue';
44
129
  import { Loader } from 'src/shared/ui/Loader';
45
130
  import { AddCooperativeForm } from 'src/features/Union/AddCooperative';
46
131
  import { useLoadCooperatives } from 'src/features/Union/LoadCooperatives';
132
+ import { useProviderSubscriptions } from 'src/features/Provider';
47
133
  import { copyToClipboard } from 'quasar';
48
134
  import { SuccessAlert } from 'src/shared/api';
49
135
  import { Cooperative } from 'cooptypes';
50
136
 
51
137
  const session = useSessionStore()
138
+ const system = useSystemStore()
52
139
  const document = ref(new DigitalDocument())
53
140
  const {loadOneCooperative} = useLoadCooperatives()
141
+ const {
142
+ domainValid,
143
+ installationProgress,
144
+ instanceStatus,
145
+ isLoading: subscriptionsLoading,
146
+ error: subscriptionsError,
147
+ startAutoRefresh
148
+ } = useProviderSubscriptions()
54
149
 
55
150
  const coop = ref()
56
151
  const instruction = computed(() => `Создайте A-запись домена ${coop.value?.announce} на IP-адрес: 51.250.114.13`)
@@ -59,6 +154,9 @@ const html = computed(() => document.value?.data?.html)
59
154
  const signedDocument = computed(() => document.value?.signedDocument)
60
155
  const is_finish = ref(false)
61
156
 
157
+ // Остановка автообновления при размонтировании компонента
158
+ let stopRefresh: (() => void) | null = null
159
+
62
160
  const copy = () => {
63
161
  copyToClipboard(instruction.value)
64
162
  .then(() => {
@@ -69,18 +167,36 @@ const copy = () => {
69
167
  })
70
168
  }
71
169
 
170
+ const openProviderWebsite = () => {
171
+ window.open('https://цифровой-кооператив.рф', '_blank')
172
+ }
173
+
72
174
 
73
175
  const finish = () => {
176
+ // Эта функция имеет смысл только если провайдер доступен
177
+ if (!system.info.is_providered) return
178
+
74
179
  is_finish.value = true
75
180
  reload()
181
+
182
+ // Запускаем автообновление подписок каждую минуту
183
+ if (!stopRefresh) {
184
+ stopRefresh = startAutoRefresh(60000) // 1 минута
185
+ }
76
186
  }
77
187
 
78
188
  //todo loadCooperative by username and check status
79
189
  const reload = async() => {
80
- coop.value = await loadOneCooperative(session.username)
190
+ // Загружаем кооператив только если провайдер доступен
191
+ if (system.info.is_providered) {
192
+ coop.value = await loadOneCooperative(session.username)
193
+ }
81
194
  }
82
195
 
83
196
  const init = async () => {
197
+ // Инициализация имеет смысл только если провайдер доступен
198
+ if (!system.info.is_providered) return
199
+
84
200
  coop.value = await loadOneCooperative(session.username)
85
201
 
86
202
  if (!coop.value)
@@ -96,6 +212,23 @@ const sign = async() => {
96
212
  await document.value.sign(session.username)
97
213
  }
98
214
 
215
+ // Lifecycle хуки
216
+ onMounted(() => {
217
+ // Если провайдер доступен - делаем полную инициализацию
218
+ if (system.info.is_providered) {
219
+ init()
220
+ }
221
+ // Если провайдер недоступен - ничего не делаем, показываем заглушку
222
+ })
223
+
224
+ onUnmounted(() => {
225
+ // Останавливаем автообновление при размонтировании компонента
226
+ if (stopRefresh) {
227
+ stopRefresh()
228
+ stopRefresh = null
229
+ }
230
+ })
231
+
99
232
  init()
100
233
 
101
234