@coopenomics/desktop 2025.11.26-alpha-3 → 2025.11.27-alpha-1
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/extensions/chatcoop/install.ts +5 -3
- package/extensions/chatcoop/pages/ChatCoopPage/ui/ChatCoopPage.vue +22 -15
- package/extensions/chatcoop/widgets/MatrixRegistration/ui/MatrixRegistration.vue +1 -1
- package/package.json +6 -6
- package/src/entities/ConnectionAgreement/model/store.ts +9 -5
- package/src/entities/Desktop/model/store.ts +42 -3
- package/src/entities/Session/model/store.ts +16 -7
- package/src/features/Extension/InstallExtension/ui/InstallButton.vue +9 -0
- package/src/features/Installer/ui/SetVariablesForm/SetVariablesForm.vue +7 -7
- package/src/pages/Union/ConnectionAgreement/ConnectionAgreementPage.vue +12 -12
- package/src/processes/init-installed-extensions/index.ts +21 -3
- package/src/shared/ui/Loader/WindowLoader.vue +6 -1
- package/src/widgets/ConnectionAgreementStepper/Steps/ApprovalWaitingStep.vue +2 -3
- package/src/widgets/Desktop/CmdkMenu/CmdkMenu.vue +1 -0
- package/src/widgets/Desktop/SecondLevelMenuList/SecondLevelMenuList.vue +58 -16
|
@@ -4,6 +4,7 @@ import { agreementsBase } from 'src/shared/lib/consts/workspaces';
|
|
|
4
4
|
import type { IWorkspaceConfig } from 'src/shared/lib/types/workspace';
|
|
5
5
|
|
|
6
6
|
export default async function (): Promise<IWorkspaceConfig[]> {
|
|
7
|
+
console.log('📨 [ChatCoop Install] Extension install function called');
|
|
7
8
|
return [{
|
|
8
9
|
workspace: 'chatcoop',
|
|
9
10
|
extension_name: 'chatcoop',
|
|
@@ -15,7 +16,7 @@ export default async function (): Promise<IWorkspaceConfig[]> {
|
|
|
15
16
|
meta: {
|
|
16
17
|
title: 'Кооперативный мессенджер',
|
|
17
18
|
icon: 'fa-solid fa-comments',
|
|
18
|
-
roles: ['
|
|
19
|
+
roles: ['chairman', 'member', 'user'],
|
|
19
20
|
},
|
|
20
21
|
path: '/:coopname/chatcoop',
|
|
21
22
|
name: 'chatcoop',
|
|
@@ -27,7 +28,7 @@ export default async function (): Promise<IWorkspaceConfig[]> {
|
|
|
27
28
|
meta: {
|
|
28
29
|
title: 'Быстрый клиент',
|
|
29
30
|
icon: 'fa-solid fa-comments',
|
|
30
|
-
roles: ['
|
|
31
|
+
roles: ['chairman', 'member', 'user'],
|
|
31
32
|
agreements: agreementsBase,
|
|
32
33
|
requiresAuth: true,
|
|
33
34
|
},
|
|
@@ -40,7 +41,7 @@ export default async function (): Promise<IWorkspaceConfig[]> {
|
|
|
40
41
|
meta: {
|
|
41
42
|
title: 'Мобильный клиент',
|
|
42
43
|
icon: 'fa-solid fa-mobile-alt',
|
|
43
|
-
roles: ['
|
|
44
|
+
roles: ['chairman', 'member', 'user'],
|
|
44
45
|
agreements: agreementsBase,
|
|
45
46
|
requiresAuth: true,
|
|
46
47
|
},
|
|
@@ -50,4 +51,5 @@ export default async function (): Promise<IWorkspaceConfig[]> {
|
|
|
50
51
|
},
|
|
51
52
|
],
|
|
52
53
|
}];
|
|
54
|
+
|
|
53
55
|
}
|
|
@@ -28,8 +28,9 @@ div
|
|
|
28
28
|
class="matrix-iframe",
|
|
29
29
|
frameborder="0",
|
|
30
30
|
width="100%",
|
|
31
|
-
:style="{ height: 'calc(100vh -
|
|
31
|
+
:style="{ height: 'calc(100vh - 51px)' }"
|
|
32
32
|
@load="onIframeLoaded"
|
|
33
|
+
allow="camera; microphone; display-capture"
|
|
33
34
|
)
|
|
34
35
|
</template>
|
|
35
36
|
|
|
@@ -43,21 +44,25 @@ const chatcoopStore = useChatCoopChatStore();
|
|
|
43
44
|
const isIframeLoading = ref(true);
|
|
44
45
|
let iframeLoadTimeout: number | null = null;
|
|
45
46
|
|
|
47
|
+
function startIframeLoading() {
|
|
48
|
+
if (!chatcoopStore.accountStatus?.iframeUrl) return;
|
|
49
|
+
|
|
50
|
+
isIframeLoading.value = true;
|
|
51
|
+
|
|
52
|
+
// Очищаем предыдущий таймаут
|
|
53
|
+
if (iframeLoadTimeout) {
|
|
54
|
+
clearTimeout(iframeLoadTimeout);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Устанавливаем таймаут на 5 секунд как fallback
|
|
58
|
+
iframeLoadTimeout = window.setTimeout(() => {
|
|
59
|
+
isIframeLoading.value = false;
|
|
60
|
+
}, 5000);
|
|
61
|
+
}
|
|
62
|
+
|
|
46
63
|
// Сбрасываем состояние загрузки iframe при изменении URL
|
|
47
64
|
watch(() => chatcoopStore.accountStatus?.iframeUrl, () => {
|
|
48
|
-
|
|
49
|
-
isIframeLoading.value = true;
|
|
50
|
-
|
|
51
|
-
// Очищаем предыдущий таймаут
|
|
52
|
-
if (iframeLoadTimeout) {
|
|
53
|
-
clearTimeout(iframeLoadTimeout);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Устанавливаем таймаут на 5 секунд как fallback
|
|
57
|
-
iframeLoadTimeout = window.setTimeout(() => {
|
|
58
|
-
isIframeLoading.value = false;
|
|
59
|
-
}, 5000);
|
|
60
|
-
}
|
|
65
|
+
startIframeLoading();
|
|
61
66
|
});
|
|
62
67
|
|
|
63
68
|
function onIframeLoaded() {
|
|
@@ -81,6 +86,8 @@ async function handleAccountCreated() {
|
|
|
81
86
|
|
|
82
87
|
onMounted(async () => {
|
|
83
88
|
await chatcoopStore.loadAccountStatus();
|
|
89
|
+
// Инициализируем загрузку iframe после получения статуса аккаунта
|
|
90
|
+
startIframeLoading();
|
|
84
91
|
});
|
|
85
92
|
</script>
|
|
86
93
|
|
|
@@ -96,7 +103,7 @@ onMounted(async () => {
|
|
|
96
103
|
flex-direction: column;
|
|
97
104
|
align-items: center;
|
|
98
105
|
justify-content: center;
|
|
99
|
-
height: calc(100vh -
|
|
106
|
+
height: calc(100vh - 51px);
|
|
100
107
|
text-align: center;
|
|
101
108
|
padding: 2rem;
|
|
102
109
|
}
|
|
@@ -196,7 +196,7 @@ const handleSubmit = async () => {
|
|
|
196
196
|
padding: 3rem 2.5rem;
|
|
197
197
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
198
198
|
width: 100%;
|
|
199
|
-
max-width:
|
|
199
|
+
max-width: 500px;
|
|
200
200
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
201
201
|
transition: all 0.3s ease;
|
|
202
202
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coopenomics/desktop",
|
|
3
|
-
"version": "2025.11.
|
|
3
|
+
"version": "2025.11.27-alpha-1",
|
|
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.
|
|
29
|
-
"@coopenomics/notifications": "2025.11.
|
|
30
|
-
"@coopenomics/sdk": "2025.11.
|
|
28
|
+
"@coopenomics/controller": "2025.11.27-alpha-1",
|
|
29
|
+
"@coopenomics/notifications": "2025.11.27-alpha-1",
|
|
30
|
+
"@coopenomics/sdk": "2025.11.27-alpha-1",
|
|
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.
|
|
62
|
+
"cooptypes": "2025.11.27-alpha-1",
|
|
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": "
|
|
126
|
+
"gitHead": "66d36e034e4cbb0dcd5625d32dba8464268f78e9"
|
|
127
127
|
}
|
|
@@ -12,7 +12,7 @@ const namespace = 'connection-agreement'
|
|
|
12
12
|
|
|
13
13
|
export const useConnectionAgreementStore = defineStore(namespace, () => {
|
|
14
14
|
// State
|
|
15
|
-
const currentStep = ref<number>(
|
|
15
|
+
const currentStep = ref<number>(0)
|
|
16
16
|
const selectedTariff = ref<ITariff | null>(null)
|
|
17
17
|
const isInitialized = ref<boolean>(false)
|
|
18
18
|
const document = ref<any>(null)
|
|
@@ -137,10 +137,9 @@ export const useConnectionAgreementStore = defineStore(namespace, () => {
|
|
|
137
137
|
try {
|
|
138
138
|
currentInstanceLoading.value = true
|
|
139
139
|
currentInstanceError.value = null
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// При успешной загрузке сбрасываем флаг Bad Gateway
|
|
140
|
+
// Сбрасываем флаг Bad Gateway при начале каждой загрузки
|
|
143
141
|
isBadGateway.value = false
|
|
142
|
+
const freshInstance = await getCurrentInstance()
|
|
144
143
|
|
|
145
144
|
// Обновляем данные только если получили свежие данные
|
|
146
145
|
// При ошибке оставляем старые данные в currentInstance (они могут быть из localStorage)
|
|
@@ -150,9 +149,14 @@ export const useConnectionAgreementStore = defineStore(namespace, () => {
|
|
|
150
149
|
|
|
151
150
|
console.log('Текущий инстанс загружен:', currentInstance.value)
|
|
152
151
|
} catch (error: any) {
|
|
153
|
-
isBadGateway.value = true
|
|
154
152
|
|
|
155
153
|
currentInstanceError.value = extractGraphQLErrorMessages(error)
|
|
154
|
+
|
|
155
|
+
// Не устанавливаем Bad Gateway для ошибки "Инстанс не найден"
|
|
156
|
+
if (!currentInstanceError.value?.includes('Инстанс не найден')) {
|
|
157
|
+
isBadGateway.value = true
|
|
158
|
+
}
|
|
159
|
+
|
|
156
160
|
// НЕ очищаем старые данные при ошибке - они остаются актуальными из localStorage
|
|
157
161
|
// currentInstance.value остается как есть
|
|
158
162
|
console.warn('Ошибка при загрузке текущего инстанса:', error)
|
|
@@ -51,7 +51,13 @@ export const useDesktopStore = defineStore(namespace, () => {
|
|
|
51
51
|
const leftDrawerOpen = ref<boolean>(true);
|
|
52
52
|
|
|
53
53
|
async function loadDesktop(): Promise<void> {
|
|
54
|
+
console.log('🏠 [DesktopStore] Loading desktop from API...');
|
|
54
55
|
const newDesktop = await api.getDesktop();
|
|
56
|
+
console.log('🏠 [DesktopStore] Desktop loaded from API:', {
|
|
57
|
+
workspacesCount: newDesktop.workspaces?.length,
|
|
58
|
+
workspaces: newDesktop.workspaces?.map(ws => ({ name: ws.name, title: ws.title }))
|
|
59
|
+
});
|
|
60
|
+
|
|
55
61
|
// Если уже есть расширения, мерджим маршруты
|
|
56
62
|
if (currentDesktop.value && currentDesktop.value.workspaces) {
|
|
57
63
|
newDesktop.workspaces.forEach((newWs) => {
|
|
@@ -59,27 +65,43 @@ export const useDesktopStore = defineStore(namespace, () => {
|
|
|
59
65
|
(ws) => ws.name === newWs.name,
|
|
60
66
|
);
|
|
61
67
|
if (oldWs && (oldWs as any).routes) {
|
|
68
|
+
console.log('🏠 [DesktopStore] Merging routes for workspace:', newWs.name);
|
|
62
69
|
(newWs as any).routes = (oldWs as any).routes;
|
|
63
70
|
}
|
|
64
71
|
});
|
|
65
72
|
}
|
|
73
|
+
|
|
66
74
|
// Добавляем поле backNavigationButton если оно отсутствует
|
|
67
75
|
currentDesktop.value = {
|
|
68
76
|
...newDesktop,
|
|
69
77
|
backNavigationButton: currentDesktop.value?.backNavigationButton || null,
|
|
70
78
|
};
|
|
79
|
+
|
|
80
|
+
console.log('🏠 [DesktopStore] Desktop updated, active workspace:', activeWorkspaceName.value);
|
|
71
81
|
// Сбрасываем состояние загрузки после загрузки рабочего стола
|
|
72
82
|
isWorkspaceChanging.value = false;
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
|
|
76
86
|
function setRoutes(workspaceName: string, routes: RouteRecordRaw[]): void {
|
|
77
|
-
if (!currentDesktop.value)
|
|
87
|
+
if (!currentDesktop.value) {
|
|
88
|
+
console.warn('🏠 [DesktopStore] Cannot set routes: no current desktop');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
78
92
|
const ws = currentDesktop.value.workspaces.find(
|
|
79
93
|
(w) => w.name === workspaceName,
|
|
80
94
|
);
|
|
95
|
+
|
|
81
96
|
if (ws) {
|
|
97
|
+
console.log('🏠 [DesktopStore] Setting routes for workspace:', {
|
|
98
|
+
workspaceName,
|
|
99
|
+
routesCount: routes.length,
|
|
100
|
+
routes: routes.map(r => ({ name: r.name, path: r.path, meta: r.meta }))
|
|
101
|
+
});
|
|
82
102
|
(ws as any).routes = routes;
|
|
103
|
+
} else {
|
|
104
|
+
console.warn('🏠 [DesktopStore] Workspace not found for setting routes:', workspaceName);
|
|
83
105
|
}
|
|
84
106
|
}
|
|
85
107
|
|
|
@@ -111,10 +133,12 @@ export const useDesktopStore = defineStore(namespace, () => {
|
|
|
111
133
|
const activeWorkspaceName = ref<string | null>(null);
|
|
112
134
|
|
|
113
135
|
function selectWorkspace(name: string) {
|
|
136
|
+
console.log('🏠 [DesktopStore] Selecting workspace:', name);
|
|
114
137
|
isWorkspaceChanging.value = true;
|
|
115
138
|
activeWorkspaceName.value = name;
|
|
116
139
|
// Сохраняем выбранный рабочий стол в localStorage (SSR-safe)
|
|
117
140
|
safeLocalStorageSetItem(STORAGE_KEY_WORKSPACE, name);
|
|
141
|
+
console.log('🏠 [DesktopStore] Workspace selected, active now:', activeWorkspaceName.value);
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
// Функция для определения и выбора дефолтного рабочего стола
|
|
@@ -166,13 +190,28 @@ export const useDesktopStore = defineStore(namespace, () => {
|
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
const activeSecondLevelRoutes = computed((): RouteRecordRaw[] => {
|
|
169
|
-
if (!activeWorkspaceName.value)
|
|
193
|
+
if (!activeWorkspaceName.value) {
|
|
194
|
+
console.log('🏠 [DesktopStore] No active workspace name for second level routes');
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
|
|
170
198
|
const ws = workspaceMenus.value.find(
|
|
171
199
|
(menu) => menu.workspaceName === activeWorkspaceName.value,
|
|
172
200
|
);
|
|
173
|
-
|
|
201
|
+
|
|
202
|
+
const routes = ws && ws.mainRoute && ws.mainRoute.children
|
|
174
203
|
? (ws.mainRoute.children as RouteRecordRaw[])
|
|
175
204
|
: [];
|
|
205
|
+
|
|
206
|
+
console.log('🏠 [DesktopStore] Active second level routes computed:', {
|
|
207
|
+
activeWorkspaceName: activeWorkspaceName.value,
|
|
208
|
+
workspaceFound: !!ws,
|
|
209
|
+
mainRouteExists: !!ws?.mainRoute,
|
|
210
|
+
routesCount: routes.length,
|
|
211
|
+
routes: routes.map(r => ({ name: r.name, path: r.path, meta: r.meta }))
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
return routes;
|
|
176
215
|
});
|
|
177
216
|
|
|
178
217
|
function registerWorkspaceMenus(router: Router): void {
|
|
@@ -41,8 +41,13 @@ export const useSessionStore = defineStore('session', (): ISessionStore => {
|
|
|
41
41
|
const session = ref();
|
|
42
42
|
|
|
43
43
|
const setCurrentUserAccount = (account: IAccount | undefined) => {
|
|
44
|
+
console.log('👤 [SessionStore] Setting current user account:', {
|
|
45
|
+
hasAccount: !!account,
|
|
46
|
+
providerRole: account?.provider_account?.role,
|
|
47
|
+
isChairman: account?.provider_account?.role === 'chairman',
|
|
48
|
+
isMember: account?.provider_account?.role === 'member'
|
|
49
|
+
});
|
|
44
50
|
currentUserAccount.value = account;
|
|
45
|
-
console.log('account', account)
|
|
46
51
|
};
|
|
47
52
|
|
|
48
53
|
const clearAccount = () => {
|
|
@@ -91,13 +96,17 @@ export const useSessionStore = defineStore('session', (): ISessionStore => {
|
|
|
91
96
|
),
|
|
92
97
|
);
|
|
93
98
|
|
|
94
|
-
const isChairman = computed(
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
const isChairman = computed(() => {
|
|
100
|
+
const chairman = currentUserAccount.value?.provider_account?.role === 'chairman';
|
|
101
|
+
console.log('👤 [SessionStore] isChairman computed:', chairman, 'role:', currentUserAccount.value?.provider_account?.role);
|
|
102
|
+
return chairman;
|
|
103
|
+
});
|
|
97
104
|
|
|
98
|
-
const isMember = computed(
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
const isMember = computed(() => {
|
|
106
|
+
const member = currentUserAccount.value?.provider_account?.role === 'member';
|
|
107
|
+
console.log('👤 [SessionStore] isMember computed:', member, 'role:', currentUserAccount.value?.provider_account?.role);
|
|
108
|
+
return member;
|
|
109
|
+
});
|
|
101
110
|
|
|
102
111
|
// Удобные геттеры для различных типов данных
|
|
103
112
|
const userAccount = computed(() => currentUserAccount.value?.user_account);
|
|
@@ -40,11 +40,20 @@ const install = async () => {
|
|
|
40
40
|
isInstalling.value = true;
|
|
41
41
|
|
|
42
42
|
try {
|
|
43
|
+
console.log('🔧 [InstallExtension] Starting extension installation:', props.extensionName);
|
|
43
44
|
await installExtension(props.extensionName, true, props.config);
|
|
45
|
+
console.log('🔧 [InstallExtension] Extension installed on backend');
|
|
46
|
+
|
|
44
47
|
// Сначала загружаем обновленный desktop с сервера
|
|
48
|
+
console.log('🔧 [InstallExtension] Loading desktop from server...');
|
|
45
49
|
await desktop.loadDesktop();
|
|
50
|
+
console.log('🔧 [InstallExtension] Desktop loaded, current workspaces:', desktop.currentDesktop?.workspaces?.map(ws => ({ name: ws.name, title: ws.title })));
|
|
51
|
+
|
|
46
52
|
// Затем динамически загружаем маршруты для установленного расширения
|
|
53
|
+
console.log('🔧 [InstallExtension] Loading extension routes...');
|
|
47
54
|
await loadExtensionRoutes(props.extensionName, router);
|
|
55
|
+
console.log('🔧 [InstallExtension] Extension routes loaded');
|
|
56
|
+
|
|
48
57
|
router.push({ name: 'one-extension' });
|
|
49
58
|
SuccessAlert('Расширение установлено');
|
|
50
59
|
} catch (e: unknown) {
|
|
@@ -15,23 +15,23 @@ div
|
|
|
15
15
|
label="Собственное название организации"
|
|
16
16
|
placeholder="Ромашка"
|
|
17
17
|
standout="bg-teal text-white"
|
|
18
|
-
hint="Название без кавычек, которое будет добавляться к
|
|
18
|
+
hint="Название кооператива без кавычек, которое будет добавляться к ОПФ+"
|
|
19
19
|
:rules="[val => notEmpty(val)]"
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
q-input.q-mt-md(
|
|
23
23
|
v-model="installStore.vars.full_abbr"
|
|
24
|
-
label="
|
|
25
|
-
|
|
24
|
+
label="ОПФ+ в именительном падеже"
|
|
25
|
+
hint="Например: Потребительский Кооператив Социального Комплекса"
|
|
26
26
|
standout="bg-teal text-white"
|
|
27
27
|
:rules="[val => notEmpty(val)]"
|
|
28
28
|
)
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
|
|
31
31
|
q-input.q-mt-md(
|
|
32
32
|
v-model="installStore.vars.full_abbr_genitive"
|
|
33
33
|
label="Основа наименования в родительном падеже"
|
|
34
|
-
|
|
34
|
+
hint="Например: Потребительского Кооператива Социального Комплекса"
|
|
35
35
|
standout="bg-teal text-white"
|
|
36
36
|
:rules="[val => notEmpty(val)]"
|
|
37
37
|
)
|
|
@@ -39,7 +39,7 @@ div
|
|
|
39
39
|
q-input.q-mt-md(
|
|
40
40
|
v-model="installStore.vars.full_abbr_dative"
|
|
41
41
|
label="Основа наименования в дательном падеже"
|
|
42
|
-
|
|
42
|
+
hint="Например: Потребительскому Кооперативу Социального Комплекса"
|
|
43
43
|
standout="bg-teal text-white"
|
|
44
44
|
:rules="[val => notEmpty(val)]"
|
|
45
45
|
)
|
|
@@ -47,7 +47,7 @@ div
|
|
|
47
47
|
q-input.q-mt-md(
|
|
48
48
|
v-model="installStore.vars.short_abbr"
|
|
49
49
|
label="Краткая аббревиатура основы наименования"
|
|
50
|
-
|
|
50
|
+
hint="Например: ПКСК"
|
|
51
51
|
standout="bg-teal text-white"
|
|
52
52
|
:rules="[val => notEmpty(val)]"
|
|
53
53
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
div.row.q-pa-md
|
|
3
3
|
div.col-md-12.col-xs-12
|
|
4
|
+
|
|
4
5
|
// Лоадер пока идет загрузка данных или технические работы у провайдера
|
|
5
6
|
WindowLoader(
|
|
6
7
|
v-if="isLoading || connectionAgreement.isBadGateway",
|
|
@@ -108,7 +109,6 @@ const init = async () => {
|
|
|
108
109
|
isLoading.value = false;
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
|
-
console.log('SYSTEM.info.is_unioned', system.info.is_unioned, connectionAgreement.isInitialized);
|
|
112
112
|
|
|
113
113
|
// Запускаем автообновление инстанса каждые 30 секунд (включает начальную загрузку)
|
|
114
114
|
// Ждем завершения первой загрузки, чтобы корректно определить состояние isBadGateway
|
|
@@ -135,29 +135,29 @@ const init = async () => {
|
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
// Определяем шаг на основе текущего состояния
|
|
139
|
+
let targetStep: number;
|
|
140
|
+
|
|
138
141
|
if (hasInstanceError) {
|
|
139
|
-
// Если есть ошибка загрузки инстанса,
|
|
140
|
-
|
|
141
|
-
console.log('❌ Ошибка загрузки инстанса, устанавливаем шаг 1 по умолчанию');
|
|
142
|
-
connectionAgreement.setCurrentStep(1);
|
|
142
|
+
// Если есть ошибка загрузки инстанса, определяем шаг на основе членства в союзе
|
|
143
|
+
targetStep = system.info.is_unioned ? 0 : 1;
|
|
143
144
|
} else if (instance && typeof instance.progress === 'number' && instance.progress > 0) {
|
|
144
145
|
// Если установка уже идет (прогресс > 0), переходим к шагу установки
|
|
145
|
-
|
|
146
|
-
connectionAgreement.setCurrentStep(6);
|
|
146
|
+
targetStep = 6;
|
|
147
147
|
} else {
|
|
148
148
|
// Если инстанса нет ИЛИ его прогресс = 0, определяем шаг на основе членства в союзе
|
|
149
|
-
const hasNoInstance = instance === null;
|
|
150
149
|
if (system.info.is_unioned) {
|
|
151
150
|
// Если кооператив не является членом союза, начинаем с нулевого шага
|
|
152
|
-
|
|
153
|
-
connectionAgreement.setCurrentStep(0);
|
|
151
|
+
targetStep = 0;
|
|
154
152
|
} else {
|
|
155
153
|
// Если кооператив уже член союза, начинаем с первого шага
|
|
156
|
-
|
|
157
|
-
connectionAgreement.setCurrentStep(1);
|
|
154
|
+
targetStep = 1;
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
|
|
158
|
+
// Устанавливаем определенный шаг
|
|
159
|
+
connectionAgreement.setCurrentStep(targetStep);
|
|
160
|
+
|
|
161
161
|
// Скрываем лоадер после загрузки данных
|
|
162
162
|
isLoading.value = false;
|
|
163
163
|
};
|
|
@@ -40,6 +40,8 @@ export async function loadExtensionRoutes(
|
|
|
40
40
|
const store = useDesktopStore();
|
|
41
41
|
|
|
42
42
|
try {
|
|
43
|
+
console.log('📦 [LoadExtensionRoutes] Starting to load routes for extension:', extensionName);
|
|
44
|
+
|
|
43
45
|
// Получаем все доступные модули расширений
|
|
44
46
|
const allModules = import.meta.glob(
|
|
45
47
|
'../../../extensions/**/install.{ts,js}',
|
|
@@ -54,22 +56,35 @@ export async function loadExtensionRoutes(
|
|
|
54
56
|
});
|
|
55
57
|
|
|
56
58
|
if (!modulePath) {
|
|
57
|
-
console.warn(
|
|
59
|
+
console.warn(`📦 [LoadExtensionRoutes] No module found for extension "${extensionName}"`);
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
console.log('📦 [LoadExtensionRoutes] Found module path:', modulePath);
|
|
64
|
+
|
|
61
65
|
const module = await allModules[modulePath]();
|
|
62
66
|
if (module?.default) {
|
|
63
67
|
const result = await module.default();
|
|
68
|
+
console.log('📦 [LoadExtensionRoutes] Module loaded, result:', result);
|
|
64
69
|
|
|
65
70
|
// Поддержка обоих форматов: массив или одиночный объект (для обратной совместимости)
|
|
66
71
|
const workspaceConfigs: IWorkspaceConfig[] = Array.isArray(result) ? result : [result];
|
|
67
72
|
|
|
73
|
+
console.log('📦 [LoadExtensionRoutes] Processing workspace configs:', workspaceConfigs.length);
|
|
74
|
+
|
|
68
75
|
// Обрабатываем каждый workspace из расширения
|
|
69
76
|
for (const config of workspaceConfigs) {
|
|
77
|
+
console.log('📦 [LoadExtensionRoutes] Processing workspace config:', {
|
|
78
|
+
workspace: config.workspace,
|
|
79
|
+
routesCount: config.routes?.length,
|
|
80
|
+
routes: config.routes?.map(r => ({ name: r.name, meta: r.meta }))
|
|
81
|
+
});
|
|
82
|
+
|
|
70
83
|
if (config?.workspace && config?.routes?.length) {
|
|
71
84
|
// Записываем маршруты в соответствующий workspace
|
|
85
|
+
console.log('📦 [LoadExtensionRoutes] Setting routes for workspace:', config.workspace);
|
|
72
86
|
store.setRoutes(config.workspace, config.routes as any);
|
|
87
|
+
|
|
73
88
|
// Регистрируем маршруты в router
|
|
74
89
|
const baseRoute = router.getRoutes().find((r) => r.name === 'base');
|
|
75
90
|
if (baseRoute) {
|
|
@@ -79,7 +94,10 @@ export async function loadExtensionRoutes(
|
|
|
79
94
|
.getRoutes()
|
|
80
95
|
.find((route) => route.name === r.name);
|
|
81
96
|
if (!existingRoute) {
|
|
97
|
+
console.log('📦 [LoadExtensionRoutes] Adding route to router:', r.name);
|
|
82
98
|
router.addRoute('base', r);
|
|
99
|
+
} else {
|
|
100
|
+
console.log('📦 [LoadExtensionRoutes] Route already exists, skipping:', r.name);
|
|
83
101
|
}
|
|
84
102
|
});
|
|
85
103
|
}
|
|
@@ -87,12 +105,12 @@ export async function loadExtensionRoutes(
|
|
|
87
105
|
}
|
|
88
106
|
|
|
89
107
|
console.log(
|
|
90
|
-
|
|
108
|
+
`📦 [LoadExtensionRoutes] Routes for extension "${extensionName}" loaded successfully (${workspaceConfigs.length} workspace(s))`,
|
|
91
109
|
);
|
|
92
110
|
}
|
|
93
111
|
} catch (error) {
|
|
94
112
|
console.error(
|
|
95
|
-
|
|
113
|
+
`📦 [LoadExtensionRoutes] Failed to load routes for extension "${extensionName}":`,
|
|
96
114
|
error,
|
|
97
115
|
);
|
|
98
116
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
.absolute-full.flex.flex-center.z-
|
|
2
|
+
.absolute-full.flex.flex-center.z-plus
|
|
3
3
|
Loader(size='50px', color='grey', style='margin: auto', :text='text')
|
|
4
4
|
</template>
|
|
5
5
|
|
|
@@ -14,3 +14,8 @@ defineProps({
|
|
|
14
14
|
},
|
|
15
15
|
});
|
|
16
16
|
</script>
|
|
17
|
+
<style>
|
|
18
|
+
.z-plus {
|
|
19
|
+
z-index: 100;
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
@@ -25,9 +25,8 @@
|
|
|
25
25
|
.status-info.q-mt-lg
|
|
26
26
|
.status-description.text-body1.text-on-surface
|
|
27
27
|
| Все технические подготовки завершены. Ваш Цифровой Кооператив готов к установке и подключению к платформе Кооперативной Экономики.
|
|
28
|
-
|
|
29
|
-
|
|
|
30
|
-
|
|
28
|
+
| Теперь мы ожидаем официального подтверждения от союза о вашем активном членстве.
|
|
29
|
+
| Когда оно будет получено - установка продолжится автоматически.
|
|
31
30
|
|
|
32
31
|
//- Навигация
|
|
33
32
|
q-stepper-navigation.q-gutter-sm
|
|
@@ -50,9 +50,17 @@ const evaluateCondition = (
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
// Вычисляем роль пользователя
|
|
53
|
-
const userRole = computed(() =>
|
|
54
|
-
session.isChairman ? 'chairman' : session.isMember ? 'member' : 'user'
|
|
55
|
-
|
|
53
|
+
const userRole = computed(() => {
|
|
54
|
+
const role = session.isChairman ? 'chairman' : session.isMember ? 'member' : 'user';
|
|
55
|
+
console.log('🔍 [SecondLevelMenuList] User role computed:', {
|
|
56
|
+
role,
|
|
57
|
+
isChairman: session.isChairman,
|
|
58
|
+
isMember: session.isMember,
|
|
59
|
+
isAuth: session.isAuth,
|
|
60
|
+
currentUserAccount: session.currentUserAccount?.provider_account?.role
|
|
61
|
+
});
|
|
62
|
+
return role;
|
|
63
|
+
});
|
|
56
64
|
|
|
57
65
|
// Контекст для evaluateCondition и проверки ролей
|
|
58
66
|
const context = computed(() => {
|
|
@@ -63,28 +71,62 @@ const context = computed(() => {
|
|
|
63
71
|
session.currentUserAccount?.private_account?.organization_data.type.toUpperCase() ===
|
|
64
72
|
Zeus.OrganizationType.COOP;
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
const ctx = {
|
|
67
75
|
isCoop,
|
|
68
76
|
userRole: userRole.value,
|
|
69
77
|
userAccount: session.currentUserAccount?.private_account,
|
|
70
78
|
coopname: info.coopname,
|
|
71
79
|
};
|
|
80
|
+
|
|
81
|
+
console.log('🔍 [SecondLevelMenuList] Context computed:', ctx);
|
|
82
|
+
return ctx;
|
|
72
83
|
});
|
|
73
84
|
|
|
74
85
|
// Используем активный второй уровень из store
|
|
75
86
|
const filteredRoutes = computed<IRoute[]>(() => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
const activeRoutes = desktop.activeSecondLevelRoutes as unknown as IRoute[];
|
|
88
|
+
|
|
89
|
+
console.log('🔍 [SecondLevelMenuList] Active second level routes:', {
|
|
90
|
+
activeWorkspaceName: desktop.activeWorkspaceName,
|
|
91
|
+
activeRoutesCount: activeRoutes.length,
|
|
92
|
+
activeRoutes: activeRoutes.map(r => ({
|
|
93
|
+
name: r.name,
|
|
94
|
+
meta: r.meta,
|
|
95
|
+
path: r.path
|
|
96
|
+
}))
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const filtered = activeRoutes.filter((r) => {
|
|
100
|
+
const rolesMatch =
|
|
101
|
+
r.meta?.roles?.includes(context.value.userRole) ||
|
|
102
|
+
(r.meta?.roles && r.meta.roles.length === 0);
|
|
103
|
+
const conditionMatch = r.meta?.conditions
|
|
104
|
+
? evaluateCondition(r.meta.conditions, context.value)
|
|
105
|
+
: true;
|
|
106
|
+
const hiddenMatch = r.meta?.hidden ? !r.meta.hidden : true;
|
|
107
|
+
|
|
108
|
+
const result = rolesMatch && conditionMatch && hiddenMatch;
|
|
109
|
+
|
|
110
|
+
console.log('🔍 [SecondLevelMenuList] Route filtering:', {
|
|
111
|
+
routeName: r.name,
|
|
112
|
+
userRole: context.value.userRole,
|
|
113
|
+
routeRoles: r.meta?.roles,
|
|
114
|
+
rolesMatch,
|
|
115
|
+
conditionMatch,
|
|
116
|
+
hiddenMatch,
|
|
117
|
+
result,
|
|
118
|
+
routeMeta: r.meta
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log('🔍 [SecondLevelMenuList] Filtered routes result:', {
|
|
125
|
+
filteredCount: filtered.length,
|
|
126
|
+
filteredRoutes: filtered.map(r => r.name)
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return filtered;
|
|
88
130
|
});
|
|
89
131
|
|
|
90
132
|
// Функция для получения паттерна группы маршрутов
|