@coopenomics/desktop 2025.11.16-alpha-1 → 2025.11.17-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.16-alpha-1",
3
+ "version": "2025.11.17-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.16-alpha-1",
29
- "@coopenomics/notifications": "2025.11.16-alpha-1",
30
- "@coopenomics/sdk": "2025.11.16-alpha-1",
28
+ "@coopenomics/controller": "2025.11.17-alpha-2",
29
+ "@coopenomics/notifications": "2025.11.17-alpha-2",
30
+ "@coopenomics/sdk": "2025.11.17-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.16-alpha-1",
62
+ "cooptypes": "2025.11.17-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": "8ed8af1b9ce9fbbfc01c9221cdd46230e6f56662"
126
+ "gitHead": "31e65ac2e3978e747ef9282a523c380b9975e0a6"
127
127
  }
@@ -69,18 +69,18 @@ export const useCmdkMenuStore = defineStore(namespace, () => {
69
69
  return shortcuts[pageName];
70
70
  };
71
71
 
72
+ // Вычисляем роль пользователя
73
+ const userRole = computed(() =>
74
+ user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
75
+ );
76
+
72
77
  // Группировка воркспейсов с их страницами
73
78
  const groupedItems = computed<GroupedItem[]>(() => {
74
- const userRole = user.isChairman
75
- ? 'chairman'
76
- : user.isMember
77
- ? 'member'
78
- : 'user';
79
79
 
80
80
  return desktop.workspaceMenus
81
81
  .filter(
82
82
  (item) =>
83
- item.meta?.roles?.includes(userRole) ||
83
+ item.meta?.roles?.includes(userRole.value) ||
84
84
  item.meta?.roles === undefined ||
85
85
  item.meta?.roles.length === 0
86
86
  )
@@ -93,14 +93,14 @@ const groupedItems = computed<GroupedItem[]>(() => {
93
93
  .filter((page: any) => {
94
94
  // Фильтрация по ролям, условиям и скрытым страницам
95
95
  const rolesMatch =
96
- page.meta?.roles?.includes(user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user') ||
96
+ page.meta?.roles?.includes(userRole.value) ||
97
97
  !page.meta?.roles ||
98
98
  page.meta.roles.length === 0;
99
99
  const conditionMatch = page.meta?.conditions
100
- ? evaluateCondition(page.meta.conditions, {
100
+ ? evaluateCondition(page.meta.conditions, {
101
101
  isCoop: user.privateAccount.value?.type === 'organization' &&
102
102
  user.privateAccount.value?.organization_data?.type?.toUpperCase() === 'COOP',
103
- userRole: user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user',
103
+ userRole: userRole.value,
104
104
  userAccount: user.privateAccount.value,
105
105
  coopname: info.coopname,
106
106
  })
@@ -4,7 +4,7 @@ q-dialog(v-model="show" persistent :maximized="true" )
4
4
  div(style="padding-bottom: 50px; padding-top: 50px;").row.justify-center
5
5
  q-card(flat).col-md-8.col-col-xs-12
6
6
  Loader(v-if="isLoading" :text='`Формируем документ...`')
7
- Form(:handler-submit="sign" :is-submitting="isSubmitting" :showSubmit="!isLoading" :showCancel="false" :button-submit-txt="'Подписать и отправить'" @cancel="clear").q-pa-lg
7
+ Form(:handler-submit="sign" :is-submitting="isSubmitting" :showSubmit="!isLoading" :showCancel="false" :button-submit-txt="'Подписать'" @cancel="clear").q-pa-lg
8
8
  slot
9
9
  </template>
10
10
 
@@ -6,8 +6,8 @@ div
6
6
  div.text-h6 Наименование
7
7
  div
8
8
  q-badge.q-mr-sm.q-mb-md ОПФ+
9
- | - основа наименования (ОПФ + цель деятельности)
10
- .text-caption.text-grey Например: "Потребительский Кооператив Социального Комплекса" или просто "Потребительский Кооператив"
9
+ | - основа наименования
10
+ .text-caption.text-grey Например: "Потребительский Кооператив Социального Комплекса" или "Потребительский Кооператив"
11
11
 
12
12
  q-input(
13
13
  autofocus
@@ -15,9 +15,9 @@ div
15
15
  label="Собственное название организации"
16
16
  placeholder="Ромашка"
17
17
  standout="bg-teal text-white"
18
+ hint="Название без кавычек, которое будет добавляться к основе"
18
19
  :rules="[val => notEmpty(val)]"
19
20
  )
20
- .text-caption.text-grey Название без кавычек, которое будет добавляться к основе
21
21
 
22
22
  q-input.q-mt-md(
23
23
  v-model="installStore.vars.full_abbr"
@@ -46,8 +46,8 @@ div
46
46
 
47
47
  q-input.q-mt-md(
48
48
  v-model="installStore.vars.short_abbr"
49
- label="Краткая аббревиатура ОПФ"
50
- placeholder="ПК"
49
+ label="Краткая аббревиатура основы наименования"
50
+ placeholder="ПКСК"
51
51
  standout="bg-teal text-white"
52
52
  :rules="[val => notEmpty(val)]"
53
53
  )
@@ -22,7 +22,7 @@ const route = useRoute();
22
22
  const coopname = computed(() => route.params.coopname as string);
23
23
  const meetStore = useMeetStore();
24
24
 
25
- const { isChairman, isMember } = useCurrentUser();
25
+ const currentUser = useCurrentUser();
26
26
 
27
27
  // Данные напрямую из стора
28
28
  const meets = computed(() => meetStore.meets);
@@ -45,7 +45,7 @@ const loadMeets = async () => {
45
45
 
46
46
  // Проверка разрешений
47
47
  const canCreateMeet = computed(() => {
48
- return isMember || isChairman;
48
+ return currentUser.isMember || currentUser.isChairman;
49
49
  });
50
50
 
51
51
  // Функция для регистрации кнопки
@@ -55,7 +55,7 @@ const registerCreateMeetButton = () => {
55
55
  id: CREATE_MEET_BUTTON_ID,
56
56
  component: CreateMeetButton,
57
57
  props: {
58
- isChairman: isChairman,
58
+ isChairman: currentUser.isChairman,
59
59
  },
60
60
  order: 1,
61
61
  });
@@ -4,7 +4,7 @@ q-step(
4
4
  title='Оплатите вступительный взнос',
5
5
  :done='store.isStepDone("PayInitial")'
6
6
  )
7
- div(v-if='payment?.payment_details?.amount_without_fee')
7
+ div(v-if='payment?.payment_details?.amount_without_fee').q-pa-sm
8
8
  p Пожалуйста, совершите оплату регистрационного взноса {{ payment.payment_details.amount_without_fee }}. Комиссия провайдера {{ payment.payment_details.fact_fee_percent }}%, всего к оплате: {{ payment.payment_details.amount_plus_fee }}.
9
9
  .q-mt-md
10
10
  span.text-bold Внимание!
@@ -13,26 +13,26 @@ div
13
13
  div(ref='statementDiv' v-if='!isLoading' v-html='html').store.statement
14
14
 
15
15
  div(v-if='!isLoading').q-gutter-sm
16
- q-checkbox(v-model='store.state.agreements.digital_signature' full-width)
16
+ q-checkbox(v-model='store.state.agreements.digital_signature').full-width
17
17
  | Я прочитал и принимаю
18
18
  ReadAgreementDialog(v-if="signatureAgreement" :agreement="signatureAgreement" v-model:agree="store.state.agreements.digital_signature" text="положение о порядке и правилах использования простой электронной подписи")
19
19
  AgreementReader(:agreement="signatureAgreement").q-mb-lg
20
20
 
21
- q-checkbox(v-model='store.state.agreements.wallet' full-width)
21
+ q-checkbox(v-model='store.state.agreements.wallet').full-width
22
22
  | Я прочитал и принимаю
23
23
  ReadAgreementDialog(v-if="walletAgreement" :agreement="walletAgreement" v-model:agree="store.state.agreements.wallet" text="положение о целевой потребительской программе 'Цифровой Кошелёк'")
24
24
  AgreementReader(:agreement="walletAgreement").q-mb-lg
25
25
 
26
- q-checkbox(v-model='store.state.agreements.user' full-width)
26
+ q-checkbox(v-model='store.state.agreements.user').full-width
27
27
  | Я прочитал и принимаю
28
28
  ReadAgreementDialog(v-if="userAgreement" :agreement="userAgreement" v-model:agree="store.state.agreements.user" text="пользовательское соглашение")
29
29
  AgreementReader(:agreement="userAgreement").q-mb-lg
30
30
 
31
- q-checkbox(v-model='store.state.agreements.ustav' full-width)
31
+ q-checkbox(v-model='store.state.agreements.ustav').full-width
32
32
  | Я прочитал и принимаю
33
33
 
34
34
  a(v-if='hasStatuteLink' @click.stop='(event) => event.stopPropagation()' :href='statuteLink' target='_blank').q-ml-xs Устав кооператива
35
- p(v-else).q-ml-xs Устав кооператива
35
+ span(v-else).q-ml-xs Устав кооператива
36
36
 
37
37
  div(v-if="!isLoading").q-mt-lg
38
38
  q-btn.col-md-6.col-xs-12(flat @click='back')
@@ -105,23 +105,54 @@ const init = async () => {
105
105
  return;
106
106
  }
107
107
  console.log('SYSTEM.info.is_unioned', system.info.is_unioned, connectionAgreement.isInitialized);
108
+
109
+ // Запускаем автообновление инстанса каждые 30 секунд (включает начальную загрузку)
110
+ stopInstanceRefresh = await connectionAgreement.startInstanceAutoRefresh(30000);
111
+
112
+ // Ждем загрузки данных инстанса перед определением шага
113
+ if (connectionAgreement.currentInstance === null) {
114
+ await new Promise<void>((resolve) => {
115
+ const unwatch = watch(
116
+ () => connectionAgreement.currentInstance,
117
+ (instance) => {
118
+ if (instance !== null) {
119
+ unwatch();
120
+ resolve();
121
+ }
122
+ }
123
+ );
124
+ });
125
+ }
126
+
108
127
  // Инициализируем persistent store если он еще не инициализирован
109
128
  if (!connectionAgreement.isInitialized) {
110
129
  connectionAgreement.setInitialized(true);
130
+ }
111
131
 
112
- // Устанавливаем начальный шаг в зависимости от членства в союзе
113
- if (system.info.is_unioned) {
114
- // Если кооператив не является членом союза, начинаем с нулевого шага
115
- connectionAgreement.setCurrentStep(0);
116
- } else {
117
- // Если кооператив уже член союза, начинаем с первого шага
118
- connectionAgreement.setCurrentStep(1);
132
+ const instance = connectionAgreement.currentInstance;
133
+
134
+ // Определяем шаг на основе текущего прогресса установки (при каждом заходе)
135
+ if (instance && typeof instance.progress === 'number') {
136
+ if (instance.progress > 0) {
137
+ // Если установка уже идет (прогресс > 0), переходим к шагу установки
138
+ console.log('🔄 Установка уже идет, прогресс:', instance.progress, '→ шаг 6');
139
+ connectionAgreement.setCurrentStep(6);
140
+ } else if (instance.progress === 0) {
141
+ // Если установки еще нет, начинаем с начала
142
+ if (system.info.is_unioned) {
143
+ // Если кооператив не является членом союза, начинаем с нулевого шага
144
+ connectionAgreement.setCurrentStep(0);
145
+ } else {
146
+ // Если кооператив уже член союза, начинаем с первого шага
147
+ connectionAgreement.setCurrentStep(1);
148
+ }
119
149
  }
150
+ } else {
151
+ // Если данные еще не загружены, начинаем с шага 1 по умолчанию
152
+ console.log('⏳ Данные инстанса еще не загружены, устанавливаем шаг 1 по умолчанию');
153
+ connectionAgreement.setCurrentStep(1);
120
154
  }
121
155
 
122
- // Запускаем автообновление инстанса каждые 30 секунд (включает начальную загрузку)
123
- stopInstanceRefresh = await connectionAgreement.startInstanceAutoRefresh(30000);
124
-
125
156
  // Скрываем лоадер после загрузки данных
126
157
  isLoading.value = false;
127
158
  };
@@ -55,7 +55,7 @@
55
55
  span.q-ml-xs {{ instance?.is_delegated ? 'Делегирован' : 'Ожидаем делегирования' }}
56
56
 
57
57
  .instruction-footer
58
- | Платформа Кооперативной Экономики автоматически проверит домен и активирует подключение вашего Цифрового Кооператива
58
+ | Мы автоматически проверим домен и активируем установку вашего Цифрового Кооператива
59
59
 
60
60
  //- Навигация
61
61
  q-stepper-navigation.q-gutter-sm
@@ -69,11 +69,6 @@ q-step(
69
69
  .form-title {
70
70
  font-weight: 700;
71
71
  letter-spacing: -0.5px;
72
- background: linear-gradient(135deg, var(--q-primary) 0%, rgba(25, 118, 210, 0.8) 100%);
73
- -webkit-background-clip: text;
74
- -webkit-text-fill-color: transparent;
75
- background-clip: text;
76
- text-shadow: 0 2px 4px rgba(25, 118, 210, 0.3);
77
72
  }
78
73
 
79
74
  /* Адаптивность */
@@ -40,7 +40,7 @@ q-step(
40
40
  //- Основная информационная карточка
41
41
  .membership-info-card.q-mb-xl
42
42
  .card-header
43
- .text-h6.membership-title Членство в Союзе Потребительских Обществ Русь
43
+ .text-h6.membership-title Членство в Союзе Потребительских Обществ
44
44
  .subtitle.text-body2.text-grey-7.q-mt-sm
45
45
  | Необходимый шаг для полноценной работы на платформе Кооперативной Экономики
46
46
 
@@ -70,7 +70,7 @@ q-step(
70
70
  .text-subtitle1.text-weight-medium Необходимость вступления в союз
71
71
 
72
72
  .requirement-description.text-body2.q-mt-sm
73
- | Для работы на платформе и обеспечения базового документооборота ваш кооператив должен быть членом Союза Потребительских Обществ Русь. Это обязательное условие для всех участников Кооперативной Экономики.
73
+ | Для работы на платформе и обеспечения базового документооборота ваш кооператив должен быть членом Союза Потребительских Обществ. Это обязательное условие для всех участников Кооперативной Экономики.
74
74
 
75
75
  .union-link-section.q-mt-md
76
76
  .text-body2.q-mb-sm Для вступления в союз перейдите по официальной ссылке:
@@ -84,10 +84,12 @@ q-step(
84
84
  class="q-mt-sm"
85
85
  )
86
86
  q-icon(name="open_in_new" size="16px").q-ml-xs
87
+
87
88
  span(v-else).text-grey-6.q-mt-sm Ссылка временно недоступна
88
89
 
89
90
  //- Навигация
90
- q-stepper-navigation.q-gutter-sm
91
+
92
+ q-stepper-navigation.q-gutter-sm.q-pa-md
91
93
  q-btn(
92
94
  v-if="isActive"
93
95
  color="primary"
@@ -113,7 +115,6 @@ q-step(
113
115
  0 2px 8px rgba(0, 0, 0, 0.04);
114
116
  position: relative;
115
117
  overflow: hidden;
116
- background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 250, 252, 0.95) 100%);
117
118
  }
118
119
 
119
120
  .membership-info-card::before {
@@ -141,11 +142,6 @@ q-step(
141
142
  .membership-title {
142
143
  font-weight: 700;
143
144
  letter-spacing: -0.5px;
144
- background: linear-gradient(135deg, var(--q-primary) 0%, rgba(25, 118, 210, 0.8) 100%);
145
- -webkit-background-clip: text;
146
- -webkit-text-fill-color: transparent;
147
- background-clip: text;
148
- text-shadow: 0 2px 4px rgba(25, 118, 210, 0.3);
149
145
  }
150
146
 
151
147
  /* Секции преимуществ */
@@ -225,14 +221,12 @@ q-step(
225
221
 
226
222
  .requirement-description {
227
223
  line-height: 1.6;
228
- color: #555;
229
224
  }
230
225
 
231
226
  /* Секция ссылки на союз */
232
227
  .union-link-section {
233
228
  padding: 1rem;
234
229
  border-radius: 12px;
235
- background: rgba(255, 255, 255, 0.5);
236
230
  border: 1px solid rgba(0, 0, 0, 0.05);
237
231
  }
238
232
 
@@ -243,12 +237,10 @@ q-step(
243
237
  border-radius: 12px;
244
238
  font-weight: 500;
245
239
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
246
- box-shadow: 0 2px 8px rgba(25, 118, 210, 0.1);
247
240
  }
248
241
 
249
242
  .union-link-btn:hover {
250
243
  transform: translateY(-1px);
251
- box-shadow: 0 4px 16px rgba(25, 118, 210, 0.2);
252
244
  }
253
245
 
254
246
  /* Адаптивность */
@@ -49,6 +49,11 @@ const evaluateCondition = (
49
49
  }
50
50
  };
51
51
 
52
+ // Вычисляем роль пользователя
53
+ const userRole = computed(() =>
54
+ user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
55
+ );
56
+
52
57
  // Контекст для evaluateCondition и проверки ролей
53
58
  const context = computed(() => {
54
59
  const isCoop =
@@ -58,15 +63,9 @@ const context = computed(() => {
58
63
  user.privateAccount.value.organization_data.type.toUpperCase() ===
59
64
  Zeus.OrganizationType.COOP;
60
65
 
61
- // Роль берем из computed свойств session
62
- const userRole = user.isChairman
63
- ? 'chairman'
64
- : user.isMember
65
- ? 'member'
66
- : 'user';
67
66
  return {
68
67
  isCoop,
69
- userRole,
68
+ userRole: userRole.value,
70
69
  userAccount: user.privateAccount.value,
71
70
  coopname: info.coopname,
72
71
  };
@@ -148,17 +148,17 @@ const isActive = (workspaceName: string): boolean => {
148
148
  // workspaceMenus – список рабочих столов из store
149
149
  const workspaceMenus = computed(() => desktop.workspaceMenus);
150
150
 
151
+ // Вычисляем роль пользователя
152
+ const userRole = computed(() =>
153
+ user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
154
+ );
155
+
151
156
  // Фильтрация по ролям
152
157
  const menuWorkspaces = computed(() => {
153
- const userRole = user.isChairman
154
- ? 'chairman'
155
- : user.isMember
156
- ? 'member'
157
- : 'user';
158
158
  return workspaceMenus.value
159
159
  .filter(
160
160
  (item) =>
161
- item.meta.roles?.includes(userRole) ||
161
+ item.meta.roles?.includes(userRole.value) ||
162
162
  item.meta.roles === undefined ||
163
163
  item.meta.roles.length === 0
164
164
  )
package/src-ssr/server.ts CHANGED
@@ -39,6 +39,11 @@ export const create = ssrCreate((/* { ... } */) => {
39
39
  app.use(compression());
40
40
  }
41
41
 
42
+ // Health check endpoint for load balancer and monitoring
43
+ app.get('/health', (req, res) => {
44
+ res.status(200).send('OK');
45
+ });
46
+
42
47
  return app;
43
48
  });
44
49