bx-rest 0.22.0 → 0.24.4
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 +24 -0
- package/esm2022/map/calendar/event.mjs +29 -15
- package/esm2022/map/calendar/section.mjs +13 -6
- package/esm2022/map/crm/calllist.mjs +16 -9
- package/esm2022/request-navvy/calendar/event.mjs +20 -8
- package/esm2022/request-navvy/calendar/section.mjs +10 -4
- package/esm2022/request-navvy/crm/calllist/index.mjs +9 -5
- package/esm2022/request-navvy/disk/operation/storage.mjs +1 -19
- package/esm2022/request-navvy/disk/storage.mjs +1 -19
- package/esm2022/request-navvy/user.mjs +6 -91
- package/esm2022/services/base.mjs +163 -6
- package/esm2022/typification/rest/calendar/event/get.mjs +1 -1
- package/esm2022/typification/rest/user/update.mjs +2 -0
- package/esm2022/typification/rest/user.mjs +2 -1
- package/fesm2022/bx-rest.mjs +258 -171
- package/fesm2022/bx-rest.mjs.map +1 -1
- package/map/calendar/event.d.ts +13 -3
- package/map/calendar/section.d.ts +9 -2
- package/map/crm/calllist.d.ts +11 -4
- package/package.json +2 -3
- package/request-navvy/calendar/event.d.ts +11 -5
- package/request-navvy/calendar/section.d.ts +8 -2
- package/request-navvy/crm/calllist/index.d.ts +6 -2
- package/request-navvy/user.d.ts +5 -1
- package/services/base.d.ts +27 -3
- package/typification/rest/calendar/event/get.d.ts +2 -2
- package/typification/rest/user/update.d.ts +58 -0
- package/typification/rest/user.d.ts +1 -0
package/fesm2022/bx-rest.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DateTime } from 'luxon';
|
|
2
1
|
import { switchMap, map, catchError, take, mergeMap as mergeMap$1 } from 'rxjs/operators';
|
|
3
2
|
import { Subscription, of, throwError, from, forkJoin, last, shareReplay, mergeMap, concatMap, toArray, map as map$1, tap } from 'rxjs';
|
|
4
3
|
import clone from 'just-clone';
|
|
@@ -102,8 +101,154 @@ class ToNumError extends Error {
|
|
|
102
101
|
].join('\n');
|
|
103
102
|
}
|
|
104
103
|
}
|
|
104
|
+
/** Соответствие токенов формата регулярным группам захвата. Порядок важен: длинные токены проверяются раньше коротких */
|
|
105
|
+
const DATE_FORMAT_TOKENS = [
|
|
106
|
+
['yyyy', '(?<yyyy>\\d{4})'],
|
|
107
|
+
['yy', '(?<yy>\\d{2})'],
|
|
108
|
+
['MM', '(?<MM>\\d{2})'],
|
|
109
|
+
['M', '(?<M>\\d{1,2})'],
|
|
110
|
+
['dd', '(?<dd>\\d{2})'],
|
|
111
|
+
['d', '(?<d>\\d{1,2})'],
|
|
112
|
+
['HH', '(?<HH>\\d{2})'],
|
|
113
|
+
['H', '(?<H>\\d{1,2})'],
|
|
114
|
+
['mm', '(?<mm>\\d{2})'],
|
|
115
|
+
['m', '(?<m>\\d{1,2})'],
|
|
116
|
+
['ss', '(?<ss>\\d{2})'],
|
|
117
|
+
['s', '(?<s>\\d{1,2})'],
|
|
118
|
+
];
|
|
119
|
+
const DATE_FORMAT_TOKEN_REGEX = new RegExp(DATE_FORMAT_TOKENS.map(([token]) => token).join('|'), 'g');
|
|
120
|
+
const TIME_ONLY_TOKENS = new Set(['HH', 'H', 'mm', 'm', 'ss', 's']);
|
|
105
121
|
/**
|
|
106
|
-
*
|
|
122
|
+
* Выводит формат "только дата" из формата даты-и-времени — отрезает время и разделитель перед
|
|
123
|
+
* ним (например, `'dd.MM.yyyy HH:mm:ss'` → `'dd.MM.yyyy'`). Порядок день/месяц/год у полей
|
|
124
|
+
* "дата" и "дата-время" на одном портале Bitrix24 всегда согласован — различается только
|
|
125
|
+
* наличие `HH:mm:ss`, поэтому нет смысла заставлять вызывающего передавать оба формата и
|
|
126
|
+
* держать их в синхроне вручную.
|
|
127
|
+
*/
|
|
128
|
+
function deriveDateOnlyFormat(dateTimeFormat) {
|
|
129
|
+
DATE_FORMAT_TOKEN_REGEX.lastIndex = 0;
|
|
130
|
+
let match;
|
|
131
|
+
while ((match = DATE_FORMAT_TOKEN_REGEX.exec(dateTimeFormat)) !== null) {
|
|
132
|
+
if (TIME_ONLY_TOKENS.has(match[0])) {
|
|
133
|
+
// Отрезаем любой разделитель перед временем, включая буквенный (например 'T' в ISO-стиле
|
|
134
|
+
// 'dd.MM.yyyyTHH:mm:ss'), а не только пунктуацию — останавливаемся на последнем символе,
|
|
135
|
+
// который реально относится к токенам даты (y/M/d).
|
|
136
|
+
const datePart = dateTimeFormat.slice(0, match.index).replace(/[^yMd]+$/, '');
|
|
137
|
+
return datePart || dateTimeFormat;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return dateTimeFormat;
|
|
141
|
+
}
|
|
142
|
+
function escapeRegExp(str) {
|
|
143
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Форматы дат, которые Bitrix24 реально присылает в разных методах REST и на разных
|
|
147
|
+
* порталах — формат даты/времени в ответе зависит от настроек портала (Настройки → формат
|
|
148
|
+
* даты и времени), поэтому один захардкоженный шаблон не универсален. Если явный `format`,
|
|
149
|
+
* переданный в toDate(), не совпал со значением, перед тем как считать строку невалидной,
|
|
150
|
+
* пробуем эти варианты по очереди — они не пересекаются по разделителям/порядку токенов,
|
|
151
|
+
* так что ложных совпадений не будет.
|
|
152
|
+
*/
|
|
153
|
+
const FALLBACK_DATE_FORMATS = [
|
|
154
|
+
'dd.MM.yyyy HH:mm:ss',
|
|
155
|
+
'yyyy-MM-dd HH:mm:ss',
|
|
156
|
+
'dd.MM.yyyy',
|
|
157
|
+
'yyyy-MM-dd',
|
|
158
|
+
];
|
|
159
|
+
/**
|
|
160
|
+
* Разбирает строку даты по простому шаблону (yyyy, MM, dd, HH, mm, ss и их однобуквенные
|
|
161
|
+
* варианты, например 'dd.MM.yyyy HH:mm:ss'). Разделители между токенами берутся из шаблона
|
|
162
|
+
* как есть. Не поддерживает локали, названия месяцев и часовые пояса — для REST-ответов
|
|
163
|
+
* Bitrix24 они не требуются, значения всегда приходят в фиксированном числовом виде.
|
|
164
|
+
*/
|
|
165
|
+
function parseDateWithFormat(val, format) {
|
|
166
|
+
const tokenMap = new Map(DATE_FORMAT_TOKENS);
|
|
167
|
+
let pattern = '';
|
|
168
|
+
let lastIndex = 0;
|
|
169
|
+
let match;
|
|
170
|
+
DATE_FORMAT_TOKEN_REGEX.lastIndex = 0;
|
|
171
|
+
while ((match = DATE_FORMAT_TOKEN_REGEX.exec(format)) !== null) {
|
|
172
|
+
pattern += escapeRegExp(format.slice(lastIndex, match.index));
|
|
173
|
+
pattern += tokenMap.get(match[0]);
|
|
174
|
+
lastIndex = match.index + match[0].length;
|
|
175
|
+
}
|
|
176
|
+
pattern += escapeRegExp(format.slice(lastIndex));
|
|
177
|
+
const result = new RegExp(`^${pattern}$`).exec(val);
|
|
178
|
+
if (!result?.groups) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const g = result.groups;
|
|
182
|
+
const year = g['yyyy'] ? Number(g['yyyy']) : g['yy'] ? 2000 + Number(g['yy']) : new Date().getFullYear();
|
|
183
|
+
const month = Number(g['MM'] ?? g['M'] ?? 1);
|
|
184
|
+
const day = Number(g['dd'] ?? g['d'] ?? 1);
|
|
185
|
+
const hour = Number(g['HH'] ?? g['H'] ?? 0);
|
|
186
|
+
const minute = Number(g['mm'] ?? g['m'] ?? 0);
|
|
187
|
+
const second = Number(g['ss'] ?? g['s'] ?? 0);
|
|
188
|
+
// Токены — это просто "N цифр", без проверки диапазона (regex не отличит "13" месяца от
|
|
189
|
+
// "13" дня). Без этой проверки new Date() молча "перекатывает" переполнение на соседний
|
|
190
|
+
// месяц/год (например, месяц=13 → январь следующего года) вместо того, чтобы считать
|
|
191
|
+
// строку невалидной.
|
|
192
|
+
if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
196
|
+
return isNaN(date.getTime()) ? null : date;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Последний резервный разбор — без знания конкретного формата. Работает только для чисто
|
|
200
|
+
* числовых дат (никаких названий месяцев/дней — для этого нужны locale-таблицы, а это как
|
|
201
|
+
* раз тот вес, ради ухода от которого luxon был убран из зависимостей).
|
|
202
|
+
*
|
|
203
|
+
* Идея: год — единственный сегмент длиной ровно 4 цифры, поэтому его позиция (первый или
|
|
204
|
+
* последний из трёх сегментов даты) однозначно опознаётся при любом разделителе (`.`, `-`,
|
|
205
|
+
* `/`, пробел...). Месяц по всем распространённым в мире соглашениям (ISO `yyyy-MM-dd` и
|
|
206
|
+
* европейское `dd.MM.yyyy`) стоит между годом и днём, поэтому берётся как средний сегмент.
|
|
207
|
+
* Время, если есть, всегда идёт как `HH:mm:ss` — этот порядок универсален.
|
|
208
|
+
*
|
|
209
|
+
* Не решает и не пытается решить неоднозначность день/месяц в чисто числовых форматах вида
|
|
210
|
+
* `MM/dd/yyyy` (США), где оба сегмента могут быть ≤12 — угадывать это без знания локали
|
|
211
|
+
* значило бы иногда молча путать день с месяцем, что хуже явной ошибки.
|
|
212
|
+
*/
|
|
213
|
+
function parseDateHeuristically(val) {
|
|
214
|
+
const parts = val.match(/\d+/g);
|
|
215
|
+
if (!parts || parts.length < 3 || parts.length > 6) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
const [d0, d1, d2, ...timeParts] = parts;
|
|
219
|
+
const dateParts = [d0, d1, d2];
|
|
220
|
+
const yearIdx = dateParts.findIndex(p => p.length === 4);
|
|
221
|
+
// Год должен быть однозначно найден (ровно 4 цифры) и стоять с края, а не в середине —
|
|
222
|
+
// иначе позиция месяца/дня не определить безопасно.
|
|
223
|
+
if (yearIdx !== 0 && yearIdx !== 2) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const year = Number(dateParts[yearIdx]);
|
|
227
|
+
const month = Number(dateParts[1]);
|
|
228
|
+
const day = Number(dateParts[yearIdx === 0 ? 2 : 0]);
|
|
229
|
+
if (month < 1 || month > 12 || day < 1 || day > 31) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
const [hh, mm, ss] = timeParts;
|
|
233
|
+
const hour = hh !== undefined ? Number(hh) : 0;
|
|
234
|
+
const minute = mm !== undefined ? Number(mm) : 0;
|
|
235
|
+
const second = ss !== undefined ? Number(ss) : 0;
|
|
236
|
+
if (hour > 23 || minute > 59 || second > 59) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
240
|
+
return isNaN(date.getTime()) ? null : date;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Преобразует значение в дату.
|
|
244
|
+
*
|
|
245
|
+
* Если передан `format`, но значение ему не соответствует (см. FALLBACK_DATE_FORMATS —
|
|
246
|
+
* актуально для полей, где Bitrix24 отдаёт дату в формате, настроенном на портале, а не в
|
|
247
|
+
* том, что захардкожен в маппере), перед тем как считать значение невалидным, делаются ещё
|
|
248
|
+
* две попытки: другие распространённые форматы Bitrix24, а затем — позиционная эвристика
|
|
249
|
+
* (см. parseDateHeuristically), которая распознаёт практически любой чисто числовой формат
|
|
250
|
+
* даты независимо от разделителя. Если приложению точно известен формат конкретного портала,
|
|
251
|
+
* его стоит передавать явным `format` — это всегда приоритетнее угадывания.
|
|
107
252
|
*/
|
|
108
253
|
function toDate(val, format, opt, throwError = true) {
|
|
109
254
|
if (val instanceof Date) {
|
|
@@ -111,10 +256,22 @@ function toDate(val, format, opt, throwError = true) {
|
|
|
111
256
|
}
|
|
112
257
|
else if (typeof val === 'string') {
|
|
113
258
|
if (format) {
|
|
114
|
-
|
|
115
|
-
|
|
259
|
+
const parsed = parseDateWithFormat(val, format);
|
|
260
|
+
if (parsed) {
|
|
261
|
+
return parsed;
|
|
262
|
+
}
|
|
263
|
+
for (const fallbackFormat of FALLBACK_DATE_FORMATS) {
|
|
264
|
+
if (fallbackFormat === format)
|
|
265
|
+
continue;
|
|
266
|
+
const fallbackParsed = parseDateWithFormat(val, fallbackFormat);
|
|
267
|
+
if (fallbackParsed) {
|
|
268
|
+
return fallbackParsed;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const heuristicParsed = parseDateHeuristically(val);
|
|
272
|
+
if (heuristicParsed) {
|
|
273
|
+
return heuristicParsed;
|
|
116
274
|
}
|
|
117
|
-
return DateTime.fromFormat(val, format).toJSDate();
|
|
118
275
|
}
|
|
119
276
|
else {
|
|
120
277
|
return new Date(val);
|
|
@@ -255,6 +412,7 @@ var base = /*#__PURE__*/Object.freeze({
|
|
|
255
412
|
__proto__: null,
|
|
256
413
|
ToNumError: ToNumError,
|
|
257
414
|
cropUrl: cropUrl,
|
|
415
|
+
deriveDateOnlyFormat: deriveDateOnlyFormat,
|
|
258
416
|
getBase64File: getBase64File,
|
|
259
417
|
getBase64FileLikeStr: getBase64FileLikeStr,
|
|
260
418
|
getBaseUrlHttps: getBaseUrlHttps,
|
|
@@ -3493,34 +3651,12 @@ class BXRestNavvyUser {
|
|
|
3493
3651
|
current() {
|
|
3494
3652
|
return this.Navvy.simple(this.url.current, undefined, BXRestMapUser.current);
|
|
3495
3653
|
}
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
ID: user.ID,
|
|
3502
|
-
}
|
|
3503
|
-
const userBX = this.BXRestUserMap.BXtoHttp(user)
|
|
3504
|
-
for (const field of fieldUpdate) {
|
|
3505
|
-
if (userBX[field]) {
|
|
3506
|
-
sendData[field] = userBX[field]
|
|
3507
|
-
} else {
|
|
3508
|
-
return throwError(() => 'One sent field is empty')
|
|
3509
|
-
}
|
|
3510
|
-
}
|
|
3511
|
-
return this.http.post<iBXRestUserHttp[]>(
|
|
3512
|
-
this.url.update,
|
|
3513
|
-
sendData
|
|
3514
|
-
)
|
|
3515
|
-
} else {
|
|
3516
|
-
return throwError(() => 'All sent field for edit is empty')
|
|
3517
|
-
}
|
|
3518
|
-
return this.Navvy.simple(
|
|
3519
|
-
this.BXRestUser.update(user, fieldUpdate),
|
|
3520
|
-
'Не удалось обновить пользователя с ID' + user.ID
|
|
3521
|
-
)
|
|
3654
|
+
/**
|
|
3655
|
+
* Обновляет данные пользователя. Доступно только пользователю с правами приглашения пользователей.
|
|
3656
|
+
*/
|
|
3657
|
+
update(param) {
|
|
3658
|
+
return this.Navvy.simple(this.url.update, param);
|
|
3522
3659
|
}
|
|
3523
|
-
*/
|
|
3524
3660
|
search(params) {
|
|
3525
3661
|
return this.Navvy.pagNav(this.url.search, params, BXRestMapUser.get);
|
|
3526
3662
|
}
|
|
@@ -3542,69 +3678,6 @@ class BXRestNavvyUser {
|
|
|
3542
3678
|
fields() {
|
|
3543
3679
|
return this.Navvy.simple(this.url.fields);
|
|
3544
3680
|
}
|
|
3545
|
-
// getAll(params: iBXGetParam = {}): Observable<iBXRestUser [] | undefined> {
|
|
3546
|
-
// if (!Object.keys(params).length) {
|
|
3547
|
-
// params = clone(this.def.params)
|
|
3548
|
-
// }
|
|
3549
|
-
//
|
|
3550
|
-
// const saveAllUser = compare(params, this.def.params)
|
|
3551
|
-
// return this.user$.pipe(
|
|
3552
|
-
// take(1),
|
|
3553
|
-
// mergeMap(v => {
|
|
3554
|
-
// if (v.load.all) {
|
|
3555
|
-
// if (compare(this.def.params, params)) {
|
|
3556
|
-
// return of(clone(v.data))
|
|
3557
|
-
// }
|
|
3558
|
-
// }
|
|
3559
|
-
//
|
|
3560
|
-
// return this.getEndArray(params).pipe(
|
|
3561
|
-
// take(1),
|
|
3562
|
-
// map(v => {
|
|
3563
|
-
// if (v && v.result) {
|
|
3564
|
-
// let cl = clone(v.result)
|
|
3565
|
-
// return this.saveArrUser(cl)
|
|
3566
|
-
// }
|
|
3567
|
-
// return undefined
|
|
3568
|
-
// }),
|
|
3569
|
-
// )
|
|
3570
|
-
// }),
|
|
3571
|
-
// tap(v => {
|
|
3572
|
-
// if (v && v.length && saveAllUser) {
|
|
3573
|
-
// this.store.dispatch(loadAll({load: true}))
|
|
3574
|
-
// }
|
|
3575
|
-
// params.start = this.def.params.start
|
|
3576
|
-
// })
|
|
3577
|
-
// )
|
|
3578
|
-
// }
|
|
3579
|
-
// private saveArrUser(users: iBXRestUserHttp[]) {
|
|
3580
|
-
// let result: iBXRestUser [] = []
|
|
3581
|
-
// for (const user of users) {
|
|
3582
|
-
// result.push(this.userMap.HttpToBX(user))
|
|
3583
|
-
// }
|
|
3584
|
-
// this.store.dispatch(saveArr({arr: result}))
|
|
3585
|
-
//
|
|
3586
|
-
// return result
|
|
3587
|
-
// }
|
|
3588
|
-
// getEndArray(params: UserFilter = {}): Observable<iHttpAnswerBX<iBXRestUserHttp[]> | undefined> {
|
|
3589
|
-
// return this.get(params).pipe(
|
|
3590
|
-
// mergeMap(items => {
|
|
3591
|
-
// if (items && items.result && typeof items.result === 'object') {
|
|
3592
|
-
// if (items.next) {
|
|
3593
|
-
// params.start = items.next
|
|
3594
|
-
// return this.getEndArray(params).pipe(map(vEnd => {
|
|
3595
|
-
// if (vEnd && items.result && vEnd.result) {
|
|
3596
|
-
// return {result: [...items.result, ...vEnd.result]}
|
|
3597
|
-
// }
|
|
3598
|
-
// return (items) ? items : undefined
|
|
3599
|
-
// }))
|
|
3600
|
-
// }
|
|
3601
|
-
// return of(items)
|
|
3602
|
-
// } else {
|
|
3603
|
-
// return of(undefined)
|
|
3604
|
-
// }
|
|
3605
|
-
// }),
|
|
3606
|
-
// )
|
|
3607
|
-
// }
|
|
3608
3681
|
/**
|
|
3609
3682
|
* Дополняет параметры запроса пользователей значениями по умолчанию (ACTIVE, start).
|
|
3610
3683
|
*/
|
|
@@ -6100,24 +6173,6 @@ class BXRestNavvyOperationDiskStorage {
|
|
|
6100
6173
|
}), shareReplay(1));
|
|
6101
6174
|
}
|
|
6102
6175
|
}
|
|
6103
|
-
/*
|
|
6104
|
-
private getforappEnd(){
|
|
6105
|
-
console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage.getforapp())
|
|
6106
|
-
let res = SessionStorage.getItem<iBXRestFolderInfo>(this.constructor.name + this.getforapp.name)
|
|
6107
|
-
if(res){
|
|
6108
|
-
return of({result: res})
|
|
6109
|
-
} else {
|
|
6110
|
-
console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage, this.BXRestDiskStorage.getforapp())
|
|
6111
|
-
return this.BXRestDiskStorage.getforapp().pipe(
|
|
6112
|
-
tap(v => {
|
|
6113
|
-
if(v){
|
|
6114
|
-
SessionStorage.setItem(this.constructor.name + this.getforapp.name, v)
|
|
6115
|
-
}
|
|
6116
|
-
})
|
|
6117
|
-
)
|
|
6118
|
-
}
|
|
6119
|
-
}
|
|
6120
|
-
*/
|
|
6121
6176
|
/**
|
|
6122
6177
|
* Возвращает список файлов и папок в хранилище приложения.
|
|
6123
6178
|
*/
|
|
@@ -6164,24 +6219,6 @@ class BXRestNavvyDiskStorage {
|
|
|
6164
6219
|
getForApp() {
|
|
6165
6220
|
return this.Navvy.simple(this.url.getForApp);
|
|
6166
6221
|
}
|
|
6167
|
-
/*
|
|
6168
|
-
private getforappEnd(){
|
|
6169
|
-
console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage.getforapp())
|
|
6170
|
-
let res = SessionStorage.getItem<iBXRestFolderInfo>(this.constructor.name + this.getforapp.name)
|
|
6171
|
-
if(res){
|
|
6172
|
-
return of({result: res})
|
|
6173
|
-
} else {
|
|
6174
|
-
console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage, this.BXRestDiskStorage.getforapp())
|
|
6175
|
-
return this.BXRestDiskStorage.getforapp().pipe(
|
|
6176
|
-
tap(v => {
|
|
6177
|
-
if(v){
|
|
6178
|
-
SessionStorage.setItem(this.constructor.name + this.getforapp.name, v)
|
|
6179
|
-
}
|
|
6180
|
-
})
|
|
6181
|
-
)
|
|
6182
|
-
}
|
|
6183
|
-
}
|
|
6184
|
-
*/
|
|
6185
6222
|
/**
|
|
6186
6223
|
* Возвращает список файлов и папок в корне хранилища.
|
|
6187
6224
|
*/
|
|
@@ -6904,13 +6941,24 @@ class BXRestNavvyLog {
|
|
|
6904
6941
|
}
|
|
6905
6942
|
|
|
6906
6943
|
class BXRestMapCalendarEvent {
|
|
6907
|
-
|
|
6908
|
-
|
|
6944
|
+
/**
|
|
6945
|
+
* @param item
|
|
6946
|
+
* @param dateTimeFormat Формат полей с датой и временем (`DATE_CREATE`, `DATE_FROM`, `DATE_TO`, `TIMESTAMP_X`
|
|
6947
|
+
* и т.д.). По умолчанию — распространённый на многих порталах `'dd.MM.yyyy HH:mm:ss'`, но реальный формат
|
|
6948
|
+
* зависит от настроек портала (Настройки → формат даты и времени) — если он известен, передавайте его явно.
|
|
6949
|
+
* Формат для полей только с датой (`EXDATE`, `RRULE.UNTIL`) выводится из этого же значения
|
|
6950
|
+
* (отбрасыванием `HH:mm:ss`) — передавать его отдельно не нужно.
|
|
6951
|
+
*/
|
|
6952
|
+
static getById(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
|
|
6953
|
+
return (item) ? BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item, dateTimeFormat) : undefined;
|
|
6909
6954
|
}
|
|
6910
|
-
|
|
6911
|
-
|
|
6955
|
+
/** @see getById */
|
|
6956
|
+
static get(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
|
|
6957
|
+
return (item) ? item.map(i => BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(i, dateTimeFormat)) : undefined;
|
|
6912
6958
|
}
|
|
6913
|
-
|
|
6959
|
+
/** @see getById */
|
|
6960
|
+
static CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
|
|
6961
|
+
const dateFormat = deriveDateOnlyFormat(dateTimeFormat);
|
|
6914
6962
|
return {
|
|
6915
6963
|
...item,
|
|
6916
6964
|
ID: toNum(item.ID),
|
|
@@ -6923,24 +6971,27 @@ class BXRestMapCalendarEvent {
|
|
|
6923
6971
|
TZ_OFFSET_FROM: toNum(item.TZ_OFFSET_FROM),
|
|
6924
6972
|
TZ_OFFSET_TO: toNum(item.TZ_OFFSET_TO),
|
|
6925
6973
|
VERSION: toNum(item.VERSION),
|
|
6926
|
-
DATE_CREATE: toDate(item.DATE_CREATE,
|
|
6927
|
-
DATE_FROM: toDate(item.DATE_FROM,
|
|
6974
|
+
DATE_CREATE: toDate(item.DATE_CREATE, dateTimeFormat),
|
|
6975
|
+
DATE_FROM: toDate(item.DATE_FROM, dateTimeFormat),
|
|
6928
6976
|
ORIGINAL_DATE_FROM: (item.ORIGINAL_DATE_FROM)
|
|
6929
|
-
? toDate(item.ORIGINAL_DATE_FROM,
|
|
6977
|
+
? toDate(item.ORIGINAL_DATE_FROM, dateTimeFormat)
|
|
6930
6978
|
: null,
|
|
6931
|
-
DATE_TO: toDate(item.DATE_TO,
|
|
6932
|
-
TIMESTAMP_X: toDate(item.TIMESTAMP_X,
|
|
6979
|
+
DATE_TO: toDate(item.DATE_TO, dateTimeFormat),
|
|
6980
|
+
TIMESTAMP_X: toDate(item.TIMESTAMP_X, dateTimeFormat),
|
|
6933
6981
|
DATE_FROM_TS_UTC: toNum(item.DATE_FROM_TS_UTC),
|
|
6934
6982
|
DATE_TO_TS_UTC: toNum(item.DATE_TO_TS_UTC),
|
|
6935
6983
|
DELETED: item.DELETED === 'Y',
|
|
6936
6984
|
DT_LENGTH: toNum(item.DT_LENGTH),
|
|
6937
6985
|
DT_SKIP_TIME: item.DT_SKIP_TIME === 'Y',
|
|
6938
6986
|
MEETING_STATUS: item.MEETING_STATUS === 'Y',
|
|
6939
|
-
EXDATE
|
|
6987
|
+
// EXDATE и RRULE.UNTIL/'~UNTIL' у Bitrix нередко приходят пустой строкой (нет исключённых
|
|
6988
|
+
// дат повторения / правило повторения ограничено через COUNT, а не датой) — пустую строку
|
|
6989
|
+
// toDate() распарсить не может ни при каком формате, поэтому такие поля пропускаем до вызова
|
|
6990
|
+
EXDATE: item.EXDATE ? item.EXDATE.split(';').filter(Boolean).map(dateStr => toDate(dateStr, dateFormat)) : [],
|
|
6940
6991
|
RRULE: (item.RRULE && typeof item.RRULE !== 'string') ? {
|
|
6941
6992
|
...item.RRULE,
|
|
6942
|
-
UNTIL: toDate(item.RRULE.UNTIL,
|
|
6943
|
-
'~UNTIL': toDate(item.RRULE['~UNTIL'],
|
|
6993
|
+
UNTIL: item.RRULE.UNTIL ? toDate(item.RRULE.UNTIL, dateFormat) : null,
|
|
6994
|
+
'~UNTIL': item.RRULE['~UNTIL'] ? toDate(item.RRULE['~UNTIL'], dateFormat) : null
|
|
6944
6995
|
} : null,
|
|
6945
6996
|
ATTENDEE_LIST: (item.ATTENDEE_LIST) ? item.ATTENDEE_LIST.map(i => {
|
|
6946
6997
|
return { id: i.id, entryId: toNum(i.entryId), status: i.status };
|
|
@@ -6976,10 +7027,16 @@ class BXRestNavvyRestCalendarEvent {
|
|
|
6976
7027
|
// )
|
|
6977
7028
|
// }
|
|
6978
7029
|
this.get = Object.assign(
|
|
6979
|
-
/**
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
7030
|
+
/**
|
|
7031
|
+
* Возвращает список событий календаря, всегда весь список, паганации в методе нет да и не нужна.
|
|
7032
|
+
*
|
|
7033
|
+
* @param param
|
|
7034
|
+
* @param dateTimeFormat Формат полей с датой и временем в ответе (см. {@link BXRestMapCalendarEvent.get}).
|
|
7035
|
+
* Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
|
|
7036
|
+
*/
|
|
7037
|
+
(param, dateTimeFormat) => this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCalendarEvent.get(raw, dateTimeFormat)), {
|
|
7038
|
+
/** Метод получает список будущих событий. @see get */
|
|
7039
|
+
nearest: (param, dateTimeFormat) => this.Navvy.simple(this.url.get.nearest, param, (raw) => BXRestMapCalendarEvent.get(raw, dateTimeFormat)),
|
|
6983
7040
|
});
|
|
6984
7041
|
}
|
|
6985
7042
|
/** Добавляет событие в календарь */
|
|
@@ -6994,24 +7051,37 @@ class BXRestNavvyRestCalendarEvent {
|
|
|
6994
7051
|
update(param) {
|
|
6995
7052
|
return this.Navvy.simple(this.url.update, param);
|
|
6996
7053
|
}
|
|
6997
|
-
/**
|
|
6998
|
-
|
|
6999
|
-
|
|
7054
|
+
/**
|
|
7055
|
+
* Метод получает информацию о событии календаря по идентификатору.
|
|
7056
|
+
*
|
|
7057
|
+
* @param param
|
|
7058
|
+
* @param dateTimeFormat Формат полей с датой и временем в ответе (см. {@link BXRestMapCalendarEvent.getById}).
|
|
7059
|
+
* Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
|
|
7060
|
+
*/
|
|
7061
|
+
getById(param, dateTimeFormat) {
|
|
7062
|
+
return this.Navvy.simple(this.url.getById, param, (raw) => BXRestMapCalendarEvent.getById(raw, dateTimeFormat));
|
|
7000
7063
|
}
|
|
7001
7064
|
}
|
|
7002
7065
|
|
|
7003
7066
|
class BXRestMapCalendarSection {
|
|
7004
|
-
|
|
7005
|
-
|
|
7067
|
+
/**
|
|
7068
|
+
* @param item
|
|
7069
|
+
* @param dateTimeFormat Формат полей `DATE_CREATE`/`TIMESTAMP_X`. По умолчанию — распространённый на многих
|
|
7070
|
+
* порталах `'dd.MM.yyyy HH:mm:ss'`, но реальный формат зависит от настроек портала (Настройки → формат
|
|
7071
|
+
* даты и времени) — если он известен, передавайте его явно.
|
|
7072
|
+
*/
|
|
7073
|
+
static get(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
|
|
7074
|
+
return (item) ? item.map(i => BXRestMapCalendarSection.CalendarSectionGetHttpToCalendarSectionGetHttp(i, dateTimeFormat)) : undefined;
|
|
7006
7075
|
}
|
|
7007
|
-
|
|
7076
|
+
/** @see get */
|
|
7077
|
+
static CalendarSectionGetHttpToCalendarSectionGetHttp(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
|
|
7008
7078
|
return {
|
|
7009
7079
|
...item,
|
|
7010
7080
|
ID: toNum(item.ID),
|
|
7011
7081
|
OWNER_ID: toNum(item.OWNER_ID),
|
|
7012
7082
|
CREATED_BY: toNum(item.CREATED_BY),
|
|
7013
|
-
DATE_CREATE: toDate(item.DATE_CREATE,
|
|
7014
|
-
TIMESTAMP_X: toDate(item.TIMESTAMP_X,
|
|
7083
|
+
DATE_CREATE: toDate(item.DATE_CREATE, dateTimeFormat),
|
|
7084
|
+
TIMESTAMP_X: toDate(item.TIMESTAMP_X, dateTimeFormat)
|
|
7015
7085
|
};
|
|
7016
7086
|
}
|
|
7017
7087
|
}
|
|
@@ -7030,9 +7100,15 @@ class BXRestNavvyRestCalendarSection {
|
|
|
7030
7100
|
};
|
|
7031
7101
|
this.Navvy = new Navvy();
|
|
7032
7102
|
}
|
|
7033
|
-
/**
|
|
7034
|
-
|
|
7035
|
-
|
|
7103
|
+
/**
|
|
7104
|
+
* Возвращает описание разделов, всегда весь список, паганации в методе нет да и не нужна.
|
|
7105
|
+
*
|
|
7106
|
+
* @param param
|
|
7107
|
+
* @param dateTimeFormat Формат полей `DATE_CREATE`/`TIMESTAMP_X` в ответе (см. {@link BXRestMapCalendarSection.get}).
|
|
7108
|
+
* Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
|
|
7109
|
+
*/
|
|
7110
|
+
get(param, dateTimeFormat) {
|
|
7111
|
+
return this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCalendarSection.get(raw, dateTimeFormat));
|
|
7036
7112
|
}
|
|
7037
7113
|
/** Добавляет новый раздел */
|
|
7038
7114
|
add(param) {
|
|
@@ -9430,22 +9506,29 @@ class BXRestMapCrmStatus {
|
|
|
9430
9506
|
}
|
|
9431
9507
|
|
|
9432
9508
|
class BXRestMapCrmCallList {
|
|
9433
|
-
/**
|
|
9434
|
-
|
|
9435
|
-
|
|
9509
|
+
/**
|
|
9510
|
+
* Преобразует данные списка обзвона из формата Bitrix24 в локальный формат.
|
|
9511
|
+
*
|
|
9512
|
+
* @param value
|
|
9513
|
+
* @param dateTimeFormat Формат поля `DATE_CREATE`. По умолчанию — `'yyyy-MM-dd HH:mm:ss'`, но реальный
|
|
9514
|
+
* формат зависит от настроек портала (Настройки → формат даты и времени) — если он известен,
|
|
9515
|
+
* передавайте его явно.
|
|
9516
|
+
*/
|
|
9517
|
+
static get(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
|
|
9518
|
+
return this.mapItem(value, dateTimeFormat);
|
|
9436
9519
|
}
|
|
9437
|
-
/** Преобразует список обзвонов с учетом полей, выбранных через `SELECT`. */
|
|
9438
|
-
static list(value) {
|
|
9439
|
-
return value?.map(item => this.mapItem(item));
|
|
9520
|
+
/** Преобразует список обзвонов с учетом полей, выбранных через `SELECT`. @see get */
|
|
9521
|
+
static list(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
|
|
9522
|
+
return value?.map(item => this.mapItem(item, dateTimeFormat));
|
|
9440
9523
|
}
|
|
9441
|
-
static mapItem(value) {
|
|
9524
|
+
static mapItem(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
|
|
9442
9525
|
if (!value)
|
|
9443
9526
|
return undefined;
|
|
9444
9527
|
const result = clone(value);
|
|
9445
9528
|
if (value.ID !== undefined)
|
|
9446
9529
|
result.ID = toNum(value.ID);
|
|
9447
9530
|
if (value.DATE_CREATE !== undefined) {
|
|
9448
|
-
result.DATE_CREATE = toDate(value.DATE_CREATE,
|
|
9531
|
+
result.DATE_CREATE = toDate(value.DATE_CREATE, dateTimeFormat);
|
|
9449
9532
|
}
|
|
9450
9533
|
if (value.CREATED_BY_ID !== undefined)
|
|
9451
9534
|
result.CREATED_BY_ID = toNum(value.CREATED_BY_ID);
|
|
@@ -11452,10 +11535,12 @@ class BXRestNavvyCrmCallList {
|
|
|
11452
11535
|
* Участников можно получить через `items.get()`.
|
|
11453
11536
|
*
|
|
11454
11537
|
* @param param Идентификатор списка обзвона.
|
|
11538
|
+
* @param dateTimeFormat Формат поля `DATE_CREATE` в ответе (см. {@link BXRestMapCrmCallList.get}).
|
|
11539
|
+
* Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
|
|
11455
11540
|
* @see https://apidocs.bitrix24.ru/api-reference/crm/call-list/crm-calllist-get.html
|
|
11456
11541
|
*/
|
|
11457
|
-
get(param) {
|
|
11458
|
-
return this.Navvy.simple(this.url.get, param, BXRestMapCrmCallList.get);
|
|
11542
|
+
get(param, dateTimeFormat) {
|
|
11543
|
+
return this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCrmCallList.get(raw, dateTimeFormat));
|
|
11459
11544
|
}
|
|
11460
11545
|
/**
|
|
11461
11546
|
* Возвращает списки обзвона с выборкой полей, фильтрацией и сортировкой.
|
|
@@ -11463,10 +11548,12 @@ class BXRestNavvyCrmCallList {
|
|
|
11463
11548
|
* Набор полей каждого элемента результата зависит от `SELECT`.
|
|
11464
11549
|
*
|
|
11465
11550
|
* @param param Выбираемые поля, фильтр и порядок сортировки.
|
|
11551
|
+
* @param dateTimeFormat Формат поля `DATE_CREATE` в ответе (см. {@link BXRestMapCrmCallList.list}).
|
|
11552
|
+
* Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
|
|
11466
11553
|
* @see https://apidocs.bitrix24.ru/api-reference/crm/call-list/crm-calllist-list.html
|
|
11467
11554
|
*/
|
|
11468
|
-
list(param = {}) {
|
|
11469
|
-
return this.Navvy.simple(this.url.list, param, BXRestMapCrmCallList.list);
|
|
11555
|
+
list(param = {}, dateTimeFormat) {
|
|
11556
|
+
return this.Navvy.simple(this.url.list, param, (raw) => BXRestMapCrmCallList.list(raw, dateTimeFormat));
|
|
11470
11557
|
}
|
|
11471
11558
|
/**
|
|
11472
11559
|
* Возвращает справочник статусов обзвона.
|