@haiiro/docuflow 0.0.11 → 0.0.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/README.md +45 -9
- package/manifest.json +117 -16
- package/package.json +6 -3
- package/public/app/docflow-app.css +2 -0
- package/public/app/docflow-app.js +94 -0
- package/src/front-components/docflow-documents.front-component.mjs +42 -42
- package/src/front-components/docflow-documents.front-component.tsx +336 -128
- package/src/front-components/docflow-processes.front-component.mjs +35 -35
- package/src/front-components/docflow-processes.front-component.tsx +527 -131
- package/src/front-components/docflow-tasks.front-component.mjs +46 -41
- package/src/front-components/docflow-tasks.front-component.tsx +489 -132
- package/src/front-components/launch-process.front-component.mjs +75 -0
- package/src/front-components/launch-process.front-component.tsx +270 -0
- package/src/front-components/process-steps.front-component.mjs +25 -25
- package/src/front-components/process-steps.front-component.tsx +55 -10
- package/src/front-components/task-form.front-component.mjs +46 -41
- package/src/logic-functions/bitrix-app.logic-function.mjs +424 -198
- package/src/logic-functions/bitrix-app.logic-function.ts +54 -82
- package/src/logic-functions/bitrix-install.logic-function.mjs +0 -11
- package/src/logic-functions/bitrix-install.logic-function.ts +0 -3
- package/src/logic-functions/capture-file.logic-function.mjs +2 -1
- package/src/logic-functions/docflow-app-session.logic-function.mjs +60043 -0
- package/src/logic-functions/docflow-app-session.logic-function.ts +54 -0
- package/src/logic-functions/docflow-app.logic-function.mjs +60122 -0
- package/src/logic-functions/docflow-app.logic-function.ts +37 -0
- package/src/logic-functions/hand-out-form-step.logic-function.mjs +2 -1
- package/src/logic-functions/launch-process.logic-function.mjs +113 -29
- package/src/logic-functions/launch-process.logic-function.ts +83 -22
- package/src/logic-functions/on-workflow-run-updated.logic-function.mjs +2 -1
- package/src/logic-functions/publish-process.logic-function.mjs +119519 -0
- package/src/logic-functions/publish-process.logic-function.ts +91 -0
- package/src/logic-functions/save-launch-fields.logic-function.mjs +178 -10
- package/src/logic-functions/save-launch-fields.logic-function.ts +24 -6
|
@@ -1,68 +1,26 @@
|
|
|
1
1
|
import { defineLogicFunction } from 'twenty-sdk/define';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type LogicFunctionExecutionContext,
|
|
4
|
+
type RoutePayload,
|
|
5
|
+
} from 'twenty-sdk/logic-function';
|
|
3
6
|
|
|
4
|
-
import { restAnd, restEq, restIsNull, restNeq, restOr } from 'src/shared/api/rest-filter.util';
|
|
5
|
-
import { readRestList } from 'src/shared/api/rest-response.util';
|
|
6
7
|
import { BitrixError, callBitrix, isBitrixConfigured } from 'src/shared/bitrix/bitrix-client';
|
|
8
|
+
import { type BitrixUserProfile } from 'src/shared/bitrix/bitrix-user.util';
|
|
7
9
|
import { parseBitrixRequest } from 'src/shared/bitrix/bitrix.util';
|
|
8
|
-
import {
|
|
10
|
+
import { readDocflowAppSection } from 'src/shared/app/docflow-app.util';
|
|
11
|
+
import { findOrCreateWorkspaceMemberFromBitrix } from 'src/server/bitrix-member';
|
|
9
12
|
import { proveAndLinkBitrixPortal } from 'src/server/bitrix-portal';
|
|
10
|
-
import { renderBitrixPage
|
|
13
|
+
import { renderBitrixPage } from 'src/server/bitrix-page';
|
|
14
|
+
import { getCrmUrl } from 'src/server/crm-url';
|
|
15
|
+
import { renderDocflowAppPage } from 'src/server/docflow-app-page';
|
|
11
16
|
import { htmlResponse } from 'src/server/http-response';
|
|
12
|
-
import { restClient } from 'src/server/records';
|
|
13
17
|
import { BITRIX_APP_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER } from 'src/universal-identifiers';
|
|
14
18
|
|
|
15
|
-
const TASKS_SHOWN_IN_PORTAL = 20;
|
|
16
|
-
|
|
17
|
-
const getCrmUrl = (): string | undefined => {
|
|
18
|
-
const value = process.env.CRM_PUBLIC_URL?.trim();
|
|
19
|
-
|
|
20
|
-
return value !== undefined && /^https?:\/\//.test(value)
|
|
21
|
-
? value.replace(/\/$/, '')
|
|
22
|
-
: undefined;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// The person is found by the e-mail of their Bitrix24 account; their open
|
|
26
|
-
// docflow tasks are listed with links into the CRM.
|
|
27
|
-
const findMyTasks = async (
|
|
28
|
-
email: string,
|
|
29
|
-
crmUrl: string | undefined,
|
|
30
|
-
): Promise<BitrixPageTask[] | undefined> => {
|
|
31
|
-
const [member] = readRestList<{ id: string }>(
|
|
32
|
-
await restClient('application').get('/rest/workspaceMembers', {
|
|
33
|
-
query: { filter: restEq('userEmail', email), limit: 1 },
|
|
34
|
-
}),
|
|
35
|
-
).records;
|
|
36
|
-
|
|
37
|
-
if (member === undefined) {
|
|
38
|
-
return undefined;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return readRestList<{ id: string; title?: string | null; dueAt?: string | null }>(
|
|
42
|
-
await restClient('application').get('/rest/tasks', {
|
|
43
|
-
query: {
|
|
44
|
-
filter: restAnd(
|
|
45
|
-
restEq('smbSection', DOCFLOW_SECTION),
|
|
46
|
-
restEq('assigneeId', member.id),
|
|
47
|
-
restOr(restNeq('status', TASK_DONE_STATUS), restIsNull('status')),
|
|
48
|
-
),
|
|
49
|
-
order_by: 'dueAt[AscNullsLast]',
|
|
50
|
-
limit: TASKS_SHOWN_IN_PORTAL,
|
|
51
|
-
},
|
|
52
|
-
}),
|
|
53
|
-
).records.map((task) => ({
|
|
54
|
-
title: task.title?.trim() || 'Без названия',
|
|
55
|
-
url: crmUrl !== undefined ? `${crmUrl}/object/task/${task.id}` : undefined,
|
|
56
|
-
dueAt:
|
|
57
|
-
typeof task.dueAt === 'string'
|
|
58
|
-
? new Date(task.dueAt).toLocaleDateString('ru-RU')
|
|
59
|
-
: undefined,
|
|
60
|
-
}));
|
|
61
|
-
};
|
|
62
|
-
|
|
63
19
|
// "Путь вашего обработчика" of the local Bitrix24 application: the page a
|
|
64
|
-
// person sees when they open the app in the portal.
|
|
65
|
-
|
|
20
|
+
// person sees when they open the app in the portal. After the portal and the
|
|
21
|
+
// person are checked it is the standalone docflow page; it signs in to the
|
|
22
|
+
// CRM itself (the portal frame gets no CRM cookie).
|
|
23
|
+
const handler = async (event: RoutePayload, context: LogicFunctionExecutionContext) => {
|
|
66
24
|
const crmUrl = getCrmUrl();
|
|
67
25
|
|
|
68
26
|
if (!isBitrixConfigured()) {
|
|
@@ -72,7 +30,6 @@ const handler = async (event: RoutePayload) => {
|
|
|
72
30
|
title: 'Документооборот',
|
|
73
31
|
message: 'В настройках приложения в CRM не указаны BITRIX_CLIENT_ID и BITRIX_CLIENT_SECRET.',
|
|
74
32
|
crmUrl,
|
|
75
|
-
tasks: [],
|
|
76
33
|
isInstall: false,
|
|
77
34
|
}),
|
|
78
35
|
);
|
|
@@ -86,43 +43,58 @@ const handler = async (event: RoutePayload) => {
|
|
|
86
43
|
|
|
87
44
|
try {
|
|
88
45
|
const portal = await proveAndLinkBitrixPortal(request);
|
|
89
|
-
const user = await callBitrix<
|
|
46
|
+
const user = await callBitrix<BitrixUserProfile>({
|
|
90
47
|
restEndpoint: portal.restEndpoint,
|
|
91
48
|
accessToken: request.authId ?? portal.accessToken,
|
|
92
49
|
method: 'user.current',
|
|
93
50
|
params: {},
|
|
94
51
|
});
|
|
95
|
-
const
|
|
96
|
-
typeof user.EMAIL === 'string' && user.EMAIL.length > 0
|
|
97
|
-
? await findMyTasks(user.EMAIL, crmUrl)
|
|
98
|
-
: undefined;
|
|
52
|
+
const member = await findOrCreateWorkspaceMemberFromBitrix(user);
|
|
99
53
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
54
|
+
if (member === undefined) {
|
|
55
|
+
return htmlResponse(
|
|
56
|
+
200,
|
|
57
|
+
renderBitrixPage({
|
|
58
|
+
title: 'Документооборот',
|
|
59
|
+
message: 'В профиле Битрикс24 нет почты — без неё нельзя найти или создать сотрудника в CRM.',
|
|
60
|
+
crmUrl,
|
|
61
|
+
isInstall: false,
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return renderDocflowAppPage({
|
|
67
|
+
workspaceId: context.workspaceId,
|
|
68
|
+
config: {
|
|
69
|
+
mode: 'bitrix',
|
|
70
|
+
crmUrl: crmUrl ?? '',
|
|
71
|
+
section: readDocflowAppSection(event.queryStringParameters.section),
|
|
72
|
+
expectedWorkspaceMemberId: member.id,
|
|
73
|
+
portalDomain: portal.portalDomain,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
115
76
|
} catch (error) {
|
|
77
|
+
if (error instanceof BitrixError) {
|
|
78
|
+
return htmlResponse(
|
|
79
|
+
403,
|
|
80
|
+
renderBitrixPage({
|
|
81
|
+
title: 'Документооборот',
|
|
82
|
+
message: `Запрос портала не подтверждён: ${error.message}`,
|
|
83
|
+
crmUrl,
|
|
84
|
+
isInstall: false,
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
116
89
|
return htmlResponse(
|
|
117
|
-
|
|
90
|
+
200,
|
|
118
91
|
renderBitrixPage({
|
|
119
92
|
title: 'Документооборот',
|
|
120
93
|
message:
|
|
121
|
-
error instanceof
|
|
122
|
-
?
|
|
123
|
-
: '
|
|
94
|
+
error instanceof Error
|
|
95
|
+
? error.message
|
|
96
|
+
: 'Не удалось открыть документооборот для вашего профиля Битрикс24.',
|
|
124
97
|
crmUrl,
|
|
125
|
-
tasks: [],
|
|
126
98
|
isInstall: false,
|
|
127
99
|
}),
|
|
128
100
|
);
|
|
@@ -119538,7 +119538,6 @@ var renderBitrixPage = ({
|
|
|
119538
119538
|
title,
|
|
119539
119539
|
message,
|
|
119540
119540
|
crmUrl,
|
|
119541
|
-
tasks,
|
|
119542
119541
|
isInstall
|
|
119543
119542
|
}) => `<!doctype html>
|
|
119544
119543
|
<html lang="ru">
|
|
@@ -119552,19 +119551,12 @@ var renderBitrixPage = ({
|
|
|
119552
119551
|
h1 { font-size: 20px; margin: 0 0 8px; }
|
|
119553
119552
|
p { color: #666; margin: 0 0 16px; }
|
|
119554
119553
|
a.button { display: inline-block; padding: 8px 16px; border-radius: 8px; background: #1961ed; color: #fff; text-decoration: none; }
|
|
119555
|
-
ul { list-style: none; padding: 0; margin: 16px 0 0; }
|
|
119556
|
-
li { padding: 8px 0; border-top: 1px solid #eee; display: flex; justify-content: space-between; gap: 16px; }
|
|
119557
|
-
li a { color: #1961ed; text-decoration: none; }
|
|
119558
|
-
.due { color: #999; white-space: nowrap; }
|
|
119559
119554
|
</style>
|
|
119560
119555
|
</head>
|
|
119561
119556
|
<body>
|
|
119562
119557
|
<h1>${escapeHtml(title)}</h1>
|
|
119563
119558
|
<p>${escapeHtml(message)}</p>
|
|
119564
119559
|
${crmUrl !== void 0 ? `<a class="button" href="${escapeHtml(crmUrl)}" target="_blank" rel="noopener">\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u043E\u043E\u0431\u043E\u0440\u043E\u0442</a>` : ""}
|
|
119565
|
-
${tasks.length > 0 ? `<ul>${tasks.map(
|
|
119566
|
-
(task) => `<li>${task.url !== void 0 ? `<a href="${escapeHtml(task.url)}" target="_blank" rel="noopener">${escapeHtml(task.title)}</a>` : escapeHtml(task.title)}<span class="due">${escapeHtml(task.dueAt ?? "")}</span></li>`
|
|
119567
|
-
).join("")}</ul>` : ""}
|
|
119568
119560
|
${isInstall ? "<script>if (window.BX24) { BX24.init(function () { BX24.installFinish(); }); }</script>" : ""}
|
|
119569
119561
|
</body>
|
|
119570
119562
|
</html>`;
|
|
@@ -119586,7 +119578,6 @@ var handler = async (event) => {
|
|
|
119586
119578
|
renderBitrixPage({
|
|
119587
119579
|
title: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u043E\u043E\u0431\u043E\u0440\u043E\u0442",
|
|
119588
119580
|
message: "\u0412 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F \u0432 CRM \u043D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D\u044B BITRIX_CLIENT_ID \u0438 BITRIX_CLIENT_SECRET.",
|
|
119589
|
-
tasks: [],
|
|
119590
119581
|
isInstall: false
|
|
119591
119582
|
})
|
|
119592
119583
|
);
|
|
@@ -119613,7 +119604,6 @@ var handler = async (event) => {
|
|
|
119613
119604
|
renderBitrixPage({
|
|
119614
119605
|
title: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u043E\u043E\u0431\u043E\u0440\u043E\u0442 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0451\u043D",
|
|
119615
119606
|
message: `\u041F\u043E\u0440\u0442\u0430\u043B ${portal.portalDomain} \u0441\u0432\u044F\u0437\u0430\u043D \u0441 CRM.`,
|
|
119616
|
-
tasks: [],
|
|
119617
119607
|
isInstall: true
|
|
119618
119608
|
})
|
|
119619
119609
|
);
|
|
@@ -119623,7 +119613,6 @@ var handler = async (event) => {
|
|
|
119623
119613
|
renderBitrixPage({
|
|
119624
119614
|
title: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u043E\u043E\u0431\u043E\u0440\u043E\u0442",
|
|
119625
119615
|
message: error instanceof BitrixError ? `\u041F\u043E\u0440\u0442\u0430\u043B \u043D\u0435 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D: ${error.message}` : "\u041F\u043E\u0440\u0442\u0430\u043B \u043D\u0435 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D.",
|
|
119626
|
-
tasks: [],
|
|
119627
119616
|
isInstall: false
|
|
119628
119617
|
})
|
|
119629
119618
|
);
|
|
@@ -17,7 +17,6 @@ const handler = async (event: RoutePayload) => {
|
|
|
17
17
|
renderBitrixPage({
|
|
18
18
|
title: 'Документооборот',
|
|
19
19
|
message: 'В настройках приложения в CRM не указаны BITRIX_CLIENT_ID и BITRIX_CLIENT_SECRET.',
|
|
20
|
-
tasks: [],
|
|
21
20
|
isInstall: false,
|
|
22
21
|
}),
|
|
23
22
|
);
|
|
@@ -47,7 +46,6 @@ const handler = async (event: RoutePayload) => {
|
|
|
47
46
|
renderBitrixPage({
|
|
48
47
|
title: 'Документооборот подключён',
|
|
49
48
|
message: `Портал ${portal.portalDomain} связан с CRM.`,
|
|
50
|
-
tasks: [],
|
|
51
49
|
isInstall: true,
|
|
52
50
|
}),
|
|
53
51
|
);
|
|
@@ -60,7 +58,6 @@ const handler = async (event: RoutePayload) => {
|
|
|
60
58
|
error instanceof BitrixError
|
|
61
59
|
? `Портал не подтверждён: ${error.message}`
|
|
62
60
|
: 'Портал не подтверждён.',
|
|
63
|
-
tasks: [],
|
|
64
61
|
isInstall: false,
|
|
65
62
|
}),
|
|
66
63
|
);
|
|
@@ -42,7 +42,8 @@ var readRestList = (response) => {
|
|
|
42
42
|
const value = readDataValue(response);
|
|
43
43
|
return {
|
|
44
44
|
records: Array.isArray(value) ? value : [],
|
|
45
|
-
pageInfo: response?.pageInfo ?? {}
|
|
45
|
+
pageInfo: response?.pageInfo ?? {},
|
|
46
|
+
totalCount: response?.totalCount
|
|
46
47
|
};
|
|
47
48
|
};
|
|
48
49
|
var readRestRecord = (response) => {
|