@datawheel/bespoke 0.2.0 → 0.2.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/dist/index.js +158 -109
- package/dist/server.js +394 -885
- package/package.json +8 -8
package/dist/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { initAuth0 } from '@auth0/nextjs-auth0';
|
|
2
|
+
import auth0 from 'auth0';
|
|
2
3
|
import * as pg from 'pg';
|
|
3
4
|
import { Sequelize, Error as Error$1, fn, col, Op, DataTypes, QueryTypes, Model } from 'sequelize';
|
|
4
5
|
import yn3 from 'yn';
|
|
@@ -19,7 +20,6 @@ import FlickrSDK from 'flickr-sdk';
|
|
|
19
20
|
import sharp from 'sharp';
|
|
20
21
|
import { createApi } from 'unsplash-js';
|
|
21
22
|
import fs from 'fs';
|
|
22
|
-
import auth0 from 'auth0';
|
|
23
23
|
import NextCors from 'nextjs-cors';
|
|
24
24
|
import formidable from 'formidable';
|
|
25
25
|
import toposort from 'toposort';
|
|
@@ -66,6 +66,232 @@ var handleAuth_default = getAuth_default.handleAuth({
|
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
// api/lib.ts
|
|
70
|
+
var BackendError = class extends Error {
|
|
71
|
+
constructor(code, message) {
|
|
72
|
+
super(message);
|
|
73
|
+
this.code = code;
|
|
74
|
+
}
|
|
75
|
+
toJSON() {
|
|
76
|
+
return failureResult(this);
|
|
77
|
+
}
|
|
78
|
+
static is(obj) {
|
|
79
|
+
return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code === "number";
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function successResult(result) {
|
|
83
|
+
return { ok: true, status: 200, data: result };
|
|
84
|
+
}
|
|
85
|
+
function failureResult(err) {
|
|
86
|
+
return { ok: false, status: BackendError.is(err) ? err.code : 500, error: err.message };
|
|
87
|
+
}
|
|
88
|
+
function resultWrapper(method) {
|
|
89
|
+
return (param) => method(param).then(successResult, failureResult);
|
|
90
|
+
}
|
|
91
|
+
function pickMethod(api, operation, entity) {
|
|
92
|
+
const name = `${operation}${capitalize(entity)}`;
|
|
93
|
+
return api[name];
|
|
94
|
+
}
|
|
95
|
+
function capitalize(str) {
|
|
96
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// types/auth.ts
|
|
100
|
+
var CMS_ROLES = {
|
|
101
|
+
ADMIN: "Admin",
|
|
102
|
+
EDITOR: "Editor",
|
|
103
|
+
WRITER: "Writer"
|
|
104
|
+
};
|
|
105
|
+
var CMS_ROLES_TYPES = {
|
|
106
|
+
APP: "App",
|
|
107
|
+
USER: "User"
|
|
108
|
+
};
|
|
109
|
+
var addRoleTypes = (roles) => {
|
|
110
|
+
const systemRoles = Object.values(CMS_ROLES);
|
|
111
|
+
return roles ? roles.map((r) => {
|
|
112
|
+
return {
|
|
113
|
+
...r,
|
|
114
|
+
type: systemRoles.includes(r.name) ? CMS_ROLES_TYPES.APP : CMS_ROLES_TYPES.USER
|
|
115
|
+
};
|
|
116
|
+
}) : [];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// api/db/users/auth0.ts
|
|
120
|
+
var auth0ConfigObject = {
|
|
121
|
+
domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
|
|
122
|
+
clientId: process.env.AUTH0_CLIENT_ID,
|
|
123
|
+
clientSecret: process.env.AUTH0_CLIENT_SECRET
|
|
124
|
+
};
|
|
125
|
+
var managementClient = new auth0.ManagementClient(auth0ConfigObject);
|
|
126
|
+
function dbSearchRole() {
|
|
127
|
+
return async () => {
|
|
128
|
+
try {
|
|
129
|
+
const roles = await managementClient.roles.getAll({
|
|
130
|
+
include_totals: true,
|
|
131
|
+
per_page: 100
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
roles: addRoleTypes(roles.roles)
|
|
135
|
+
};
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error("AuthZeroError", err);
|
|
138
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function dbSearchUser() {
|
|
143
|
+
return async (filters) => {
|
|
144
|
+
try {
|
|
145
|
+
let users;
|
|
146
|
+
if (filters) {
|
|
147
|
+
const pagination = {
|
|
148
|
+
include_totals: true,
|
|
149
|
+
per_page: 10,
|
|
150
|
+
page: filters.page || 0
|
|
151
|
+
};
|
|
152
|
+
if (filters.role_id && filters.role_id !== "") {
|
|
153
|
+
const paramsByRole = {
|
|
154
|
+
...pagination,
|
|
155
|
+
id: filters.role_id
|
|
156
|
+
};
|
|
157
|
+
users = await managementClient.roles.getUsers(paramsByRole);
|
|
158
|
+
} else {
|
|
159
|
+
const paramsSearch = {
|
|
160
|
+
...pagination,
|
|
161
|
+
q: filters.query
|
|
162
|
+
};
|
|
163
|
+
users = await managementClient.users.getAll(paramsSearch);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return users;
|
|
167
|
+
} catch (err) {
|
|
168
|
+
console.error("AuthZeroError", err);
|
|
169
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function dbReadUser() {
|
|
174
|
+
return async (userId) => {
|
|
175
|
+
try {
|
|
176
|
+
if (userId) {
|
|
177
|
+
const userData = await Promise.all([
|
|
178
|
+
managementClient.users.get({ id: userId }),
|
|
179
|
+
managementClient.users.getRoles({ id: userId })
|
|
180
|
+
]);
|
|
181
|
+
return {
|
|
182
|
+
...userData[0],
|
|
183
|
+
roles: userData[1]
|
|
184
|
+
};
|
|
185
|
+
} else {
|
|
186
|
+
throw new BackendError(404, "User ID required");
|
|
187
|
+
}
|
|
188
|
+
} catch (err) {
|
|
189
|
+
console.error("AuthZeroError", err);
|
|
190
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function dbUpdateUser() {
|
|
195
|
+
return async (user) => {
|
|
196
|
+
try {
|
|
197
|
+
if (user.user_id) {
|
|
198
|
+
if (user.app_metadata) {
|
|
199
|
+
await updateUserMetadata(user.user_id, user.app_metadata);
|
|
200
|
+
}
|
|
201
|
+
if (user.roles) {
|
|
202
|
+
const currentRoles = await managementClient.users.getRoles({ id: user.user_id });
|
|
203
|
+
const oldRoles = currentRoles.map((r) => r.id);
|
|
204
|
+
const newRoles = user.roles.map((r) => r.id);
|
|
205
|
+
const rolesToAssign = newRoles.filter((role) => !oldRoles.includes(role));
|
|
206
|
+
const rolesToDelete = oldRoles.filter((role) => !newRoles.includes(role));
|
|
207
|
+
if (rolesToAssign.length > 0) {
|
|
208
|
+
await managementClient.users.assignRoles({ id: user.user_id }, { roles: rolesToAssign });
|
|
209
|
+
}
|
|
210
|
+
if (rolesToDelete.length > 0) {
|
|
211
|
+
await managementClient.users.removeRoles({ id: user.user_id }, { roles: rolesToDelete });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return "User updated!";
|
|
215
|
+
} else {
|
|
216
|
+
throw new BackendError(404, "user_id is required");
|
|
217
|
+
}
|
|
218
|
+
} catch (err) {
|
|
219
|
+
console.error("AuthZeroError", err);
|
|
220
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function dbAddNewReportToCurrentUser() {
|
|
225
|
+
return async (params) => {
|
|
226
|
+
try {
|
|
227
|
+
return "NOT USED SERVICE";
|
|
228
|
+
} catch (err) {
|
|
229
|
+
console.error("AuthZeroError", err);
|
|
230
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
async function updateUserMetadata(userId, newMetadata) {
|
|
235
|
+
return await managementClient.users.updateAppMetadata({ id: userId }, newMetadata);
|
|
236
|
+
}
|
|
237
|
+
async function searchUsersByMetadata(key, value) {
|
|
238
|
+
try {
|
|
239
|
+
const users = await managementClient.getUsers({
|
|
240
|
+
search_engine: "v3",
|
|
241
|
+
q: `app_metadata.${key}:"${value}"`
|
|
242
|
+
});
|
|
243
|
+
for (let index = 0; index < users.length; index++) {
|
|
244
|
+
const u = users[index];
|
|
245
|
+
u.bespoke_app_metadata = u.app_metadata || {};
|
|
246
|
+
delete u.app_metadata;
|
|
247
|
+
u.bespoke_roles = (await managementClient.users.getRoles({ id: u.user_id })).map((r) => r.name);
|
|
248
|
+
}
|
|
249
|
+
return users;
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.error(error);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// api/auth/updateCurrentUserMetadata.tsx
|
|
256
|
+
var updateCurrentUserMetadata = (req, res, newMetadata) => {
|
|
257
|
+
return new Promise((resolve, reject) => {
|
|
258
|
+
const updateMetadata = async () => {
|
|
259
|
+
try {
|
|
260
|
+
const session = await getAuth_default.getSession(req, res);
|
|
261
|
+
if (!session || !session.user) {
|
|
262
|
+
throw new Error("not_authenticated");
|
|
263
|
+
} else {
|
|
264
|
+
const { user } = session;
|
|
265
|
+
const oldMetadata = session.user.bespoke_app_metadata || {};
|
|
266
|
+
const latestMetadata = {
|
|
267
|
+
...oldMetadata,
|
|
268
|
+
...newMetadata
|
|
269
|
+
};
|
|
270
|
+
await updateUserMetadata(session.user.sub, latestMetadata);
|
|
271
|
+
await getAuth_default.updateSession(req, res, {
|
|
272
|
+
...session,
|
|
273
|
+
user: {
|
|
274
|
+
...user,
|
|
275
|
+
bespoke_app_metadata: latestMetadata
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
resolve({
|
|
279
|
+
error: "",
|
|
280
|
+
description: `Settings updated for user ${session.user.email}`
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
} catch (error) {
|
|
284
|
+
reject({
|
|
285
|
+
error: error.message,
|
|
286
|
+
description: "The user does not have an active session or is not authenticated"
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
updateMetadata();
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
var updateCurrentUserMetadata_default = updateCurrentUserMetadata;
|
|
294
|
+
|
|
69
295
|
// libs/js/arrayUtils.ts
|
|
70
296
|
var keyDiver = (obj, str) => !str ? obj : typeof str === "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
|
|
71
297
|
function arrContainsAnyItem(arr1, arr2) {
|
|
@@ -95,6 +321,32 @@ var withApiRoleAuthRequired = (apiRoute, allowedRoles) => {
|
|
|
95
321
|
};
|
|
96
322
|
};
|
|
97
323
|
var withApiRoleAuthRequired_default = withApiRoleAuthRequired;
|
|
324
|
+
|
|
325
|
+
// api/auth/searchUsersByMetadata.tsx
|
|
326
|
+
var searchUsersByMetadata2 = (key, value) => {
|
|
327
|
+
return new Promise((resolve, reject) => {
|
|
328
|
+
const searchUsers = async () => {
|
|
329
|
+
try {
|
|
330
|
+
if (key && value && key !== "" && value !== "") {
|
|
331
|
+
const users = await searchUsersByMetadata(key, value);
|
|
332
|
+
resolve(users);
|
|
333
|
+
} else {
|
|
334
|
+
reject({
|
|
335
|
+
error: "empty_params",
|
|
336
|
+
description: "key or value params are empty"
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
} catch (error) {
|
|
340
|
+
reject({
|
|
341
|
+
error: error.message,
|
|
342
|
+
description: "Error "
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
searchUsers();
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
var searchUsersByMetadata_default = searchUsersByMetadata2;
|
|
98
350
|
var getLogging_default = (env = process.env) => yn3(env.REPORTS_LOGGING);
|
|
99
351
|
var BlockModel = class extends Model {
|
|
100
352
|
getContent(locale) {
|
|
@@ -448,687 +700,62 @@ var libraries = {
|
|
|
448
700
|
titleCase
|
|
449
701
|
},
|
|
450
702
|
stats: stats_default
|
|
451
|
-
};
|
|
452
|
-
var declaredFormatters = {};
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
REPORT: "report",
|
|
474
|
-
STORY: "story"
|
|
475
|
-
};
|
|
476
|
-
var REPORT_MODES = {
|
|
477
|
-
UNILATERAL: "uni",
|
|
478
|
-
MULTILATERAL: "multi"
|
|
479
|
-
};
|
|
480
|
-
var SELECTOR_TYPES = {
|
|
481
|
-
SINGLE: "single",
|
|
482
|
-
MULTI: "multi"
|
|
483
|
-
};
|
|
484
|
-
var REPORT_FIELDS = {
|
|
485
|
-
TITLE: "title",
|
|
486
|
-
SUBTITLE: "subtitle",
|
|
487
|
-
LABEL: "label"
|
|
488
|
-
};
|
|
489
|
-
({
|
|
490
|
-
[REPORT_TYPES.REPORT]: Object.values(REPORT_FIELDS),
|
|
491
|
-
[REPORT_TYPES.STORY]: Object.values(REPORT_FIELDS)
|
|
492
|
-
});
|
|
493
|
-
var BLOCK_CONTENT_TYPES = {
|
|
494
|
-
// AUTHOR: "author",
|
|
495
|
-
// FOOTNOTE: "footnote",
|
|
496
|
-
IMAGE: "image",
|
|
497
|
-
PARAGRAPH: "paragraph",
|
|
498
|
-
SELECTOR: "selector",
|
|
499
|
-
// todo1.0 - move to logic types
|
|
500
|
-
STAT: "stat",
|
|
501
|
-
SUBTITLE: "subtitle",
|
|
502
|
-
TITLE: "title",
|
|
503
|
-
NAV: "nav",
|
|
504
|
-
// todo1.0, how to put custom blocks in here?
|
|
505
|
-
RESET_BUTTON: "reset_button"
|
|
506
|
-
};
|
|
507
|
-
var BLOCK_LOGIC_TYPES = {
|
|
508
|
-
GENERATOR: "generator",
|
|
509
|
-
RELATED: "related",
|
|
510
|
-
VIZ: "visualization"
|
|
511
|
-
};
|
|
512
|
-
var BLOCK_LOGIC_LOCALE = "logic";
|
|
513
|
-
var BLOCK_TYPES = { ...BLOCK_CONTENT_TYPES, ...BLOCK_LOGIC_TYPES };
|
|
514
|
-
var FORMATTER_TYPES = {
|
|
515
|
-
FORMATTER: "formatter",
|
|
516
|
-
FUNCTION: "function"
|
|
517
|
-
};
|
|
518
|
-
var FORMATTER_INPUT_TYPES = {
|
|
519
|
-
STRING: "string",
|
|
520
|
-
NUMBER: "number",
|
|
521
|
-
OBJECT: "object",
|
|
522
|
-
DATE: "date"
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
// libs/formatters/index.ts
|
|
526
|
-
var formatters_exports = {};
|
|
527
|
-
__export(formatters_exports, {
|
|
528
|
-
abbreviate: () => abbreviate_default,
|
|
529
|
-
abs: () => abs_default,
|
|
530
|
-
bucket: () => bucket_default,
|
|
531
|
-
commas: () => commas_default,
|
|
532
|
-
date: () => date_default,
|
|
533
|
-
dollar: () => dollar_default,
|
|
534
|
-
formatFieldName: () => formatFieldName_default,
|
|
535
|
-
grewTo: () => grewTo_default,
|
|
536
|
-
grewWord: () => grewWord_default,
|
|
537
|
-
growing: () => growing_default,
|
|
538
|
-
growth: () => growth_default,
|
|
539
|
-
growthPct: () => growthPct_default,
|
|
540
|
-
growthWord: () => growthWord_default,
|
|
541
|
-
highWord: () => highWord_default,
|
|
542
|
-
increaseWord: () => increaseWord_default,
|
|
543
|
-
increasedWord: () => increasedWord_default,
|
|
544
|
-
increasing: () => increasing_default,
|
|
545
|
-
largerThan: () => largerThan_default,
|
|
546
|
-
list: () => list_default,
|
|
547
|
-
longWord: () => longWord_default,
|
|
548
|
-
lowerCaseFirst: () => lowerCaseFirst_default,
|
|
549
|
-
moreFewerWord: () => moreFewerWord_default,
|
|
550
|
-
moreLess: () => moreLess_default,
|
|
551
|
-
moreWord: () => moreWord_default,
|
|
552
|
-
olderWord: () => olderWord_default,
|
|
553
|
-
olderYounger: () => olderYounger_default,
|
|
554
|
-
plural: () => plural_default,
|
|
555
|
-
pxToInt: () => pxToInt_default,
|
|
556
|
-
salary: () => salary_default,
|
|
557
|
-
stripEntities: () => stripEntities_default,
|
|
558
|
-
stripHTML: () => stripHTML_default,
|
|
559
|
-
stripOL: () => stripOL_default,
|
|
560
|
-
stripP: () => stripP_default,
|
|
561
|
-
stripUL: () => stripUL_default,
|
|
562
|
-
toKebabCase: () => toKebabCase_default,
|
|
563
|
-
toSpacedCase: () => toSpacedCase_default,
|
|
564
|
-
upperCaseFirst: () => upperCaseFirst_default
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
// libs/formatters/abbreviate.js
|
|
568
|
-
var abbreviate_default = declareFormatter({
|
|
569
|
-
name: "abbreviate",
|
|
570
|
-
description: "Abbreviates a number into a smaller more human-readable number.",
|
|
571
|
-
logicFactory(libs) {
|
|
572
|
-
return (n) => libs.d3plus.formatAbbreviate(n);
|
|
573
|
-
},
|
|
574
|
-
inputType: "number",
|
|
575
|
-
testValue: "123456",
|
|
576
|
-
type: "formatter"
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
// libs/formatters/abs.js
|
|
580
|
-
var abs_default = declareFormatter({
|
|
581
|
-
name: "abs",
|
|
582
|
-
description: "Simple Absolute Value.",
|
|
583
|
-
logicFactory(libs) {
|
|
584
|
-
return (n) => Math.abs(n);
|
|
585
|
-
},
|
|
586
|
-
inputType: "number",
|
|
587
|
-
testValue: "-123",
|
|
588
|
-
type: "formatter"
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
// libs/formatters/bucket.js
|
|
592
|
-
var logicFactory = () => function bucket(n) {
|
|
593
|
-
const re = new RegExp(/([\$0-9\,]+)[A-z\-\s\&]*([\$0-9\,]*)/g);
|
|
594
|
-
let nums = re.exec(n);
|
|
595
|
-
if (nums) {
|
|
596
|
-
nums = nums.slice(1).filter((d) => d.length).map((d) => {
|
|
597
|
-
if (d.includes(",")) {
|
|
598
|
-
if (d.indexOf(",") === d.length - 4) {
|
|
599
|
-
d = d.replace(/,000$/g, "k").replace(/([0-9]+)(,999$)/g, (n2) => `${parseInt(n2) + 1}k`);
|
|
600
|
-
} else if (d.indexOf(",") === d.length - 8) {
|
|
601
|
-
d = d.replace(/,000,000$/g, "M").replace(/([0-9]+)(,999,999$)/g, (n2) => `${parseInt(n2) + 1}M`);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return d;
|
|
605
|
-
});
|
|
606
|
-
if (nums.length === 2)
|
|
607
|
-
return nums.join(" - ");
|
|
608
|
-
if (n.toLowerCase().match(/under|less|\</g))
|
|
609
|
-
return `< ${nums[0]}`;
|
|
610
|
-
if (n.toLowerCase().match(/over|more|\+|\>/g))
|
|
611
|
-
return `${nums[0]}+`;
|
|
612
|
-
return `${nums[0]}`;
|
|
613
|
-
}
|
|
614
|
-
return "None";
|
|
615
|
-
};
|
|
616
|
-
var bucket_default = declareFormatter({
|
|
617
|
-
name: "bucket",
|
|
618
|
-
description: "Sanitizes bucket strings to '< n', 'n1 - n2', and 'n+'",
|
|
619
|
-
logicFactory,
|
|
620
|
-
inputType: "number",
|
|
621
|
-
testValue: "1234",
|
|
622
|
-
type: "formatter"
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
// libs/formatters/commas.js
|
|
626
|
-
var commas_default = declareFormatter({
|
|
627
|
-
name: "commas",
|
|
628
|
-
description: "* Rounds to nearest whole number and adds commas.",
|
|
629
|
-
logicFactory(libs) {
|
|
630
|
-
return (n) => libs.d3.format(",")(Math.round(n));
|
|
631
|
-
},
|
|
632
|
-
inputType: "number",
|
|
633
|
-
testValue: "1234.6",
|
|
634
|
-
type: "formatter"
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
// libs/formatters/date.js
|
|
638
|
-
var date_default = declareFormatter({
|
|
639
|
-
name: "date",
|
|
640
|
-
description: "Formats a date into '%B %d, %Y' format.",
|
|
641
|
-
logicFactory(libs) {
|
|
642
|
-
return (n) => {
|
|
643
|
-
if (typeof n === "string") {
|
|
644
|
-
n = libs.d3plus.date(n);
|
|
645
|
-
}
|
|
646
|
-
return libs.d3.timeFormat("%B %d, %Y")(n);
|
|
647
|
-
};
|
|
648
|
-
},
|
|
649
|
-
inputType: "date",
|
|
650
|
-
testValue: "2022-01-01",
|
|
651
|
-
type: "formatter"
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
// libs/formatters/dollar.js
|
|
655
|
-
var dollar_default = declareFormatter({
|
|
656
|
-
name: "dollar",
|
|
657
|
-
description: "Adds a US dollar sign to the beginning of a String or Number.",
|
|
658
|
-
logicFactory(libs) {
|
|
659
|
-
return (n) => {
|
|
660
|
-
if (typeof n === "number")
|
|
661
|
-
n = libs.d3plus.formatAbbreviate(n);
|
|
662
|
-
return n.charAt(0) === "-" ? n.replace("-", "-$") : `$${n}`;
|
|
663
|
-
};
|
|
664
|
-
},
|
|
665
|
-
inputType: "number",
|
|
666
|
-
testValue: "123",
|
|
667
|
-
type: "formatter"
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
// libs/formatters/formatFieldName.js
|
|
671
|
-
var formatFieldName_default = declareFormatter({
|
|
672
|
-
name: "formatFieldName",
|
|
673
|
-
description: "Based on field name returns a string",
|
|
674
|
-
logicFactory(libs) {
|
|
675
|
-
return (n) => {
|
|
676
|
-
if (n.contentType.toLowerCase() === "stat") {
|
|
677
|
-
if (n.field === "title")
|
|
678
|
-
return "Stat label";
|
|
679
|
-
if (n.field === "value")
|
|
680
|
-
return "Stat value";
|
|
681
|
-
if (n.field === "subtitle")
|
|
682
|
-
return "Stat subtitle";
|
|
683
|
-
if (n.field === "tooltip")
|
|
684
|
-
return "Tooltip text";
|
|
685
|
-
}
|
|
686
|
-
if (n.contentType.toLowerCase() === "section") {
|
|
687
|
-
if (n.field === "short")
|
|
688
|
-
return "Short title";
|
|
689
|
-
}
|
|
690
|
-
if (n.contentType.toLowerCase() === "description") {
|
|
691
|
-
if (n.field === "description")
|
|
692
|
-
return "Paragraph";
|
|
693
|
-
}
|
|
694
|
-
return n.field;
|
|
695
|
-
};
|
|
696
|
-
},
|
|
697
|
-
inputType: "object",
|
|
698
|
-
testValue: '{"field":"title","contentType":"stat"}',
|
|
699
|
-
type: "formatter"
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
// libs/formatters/grewTo.js
|
|
703
|
-
var grewTo_default = declareFormatter({
|
|
704
|
-
name: "grewTo",
|
|
705
|
-
description: "Returns the text with grow direction: 'declined from', 'grew to' o 'stayed at'",
|
|
706
|
-
logicFactory(libs) {
|
|
707
|
-
return (n) => n < 0 ? "declined from" : n > 0 ? "grew to" : "stayed at";
|
|
708
|
-
},
|
|
709
|
-
inputType: "number",
|
|
710
|
-
testValue: "-1234",
|
|
711
|
-
type: "formatter"
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
// libs/formatters/grewWord.js
|
|
715
|
-
var grewWord_default = declareFormatter({
|
|
716
|
-
name: "grewWord",
|
|
717
|
-
description: "Returns either 'grew', 'declined', or 'stayed' depending on the provided number's sign.",
|
|
718
|
-
logicFactory(libs) {
|
|
719
|
-
return (n) => n < 0 ? "declined" : n > 0 ? "grew" : "stayed";
|
|
720
|
-
},
|
|
721
|
-
inputType: "number",
|
|
722
|
-
testValue: "-1234",
|
|
723
|
-
type: "formatter"
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
// libs/formatters/growing.js
|
|
727
|
-
var growing_default = declareFormatter({
|
|
728
|
-
name: "growing",
|
|
729
|
-
description: "Returns either 'declining', 'growing' depending on the provided number's sign.",
|
|
730
|
-
logicFactory(libs) {
|
|
731
|
-
return (n) => n < 0 ? "declining" : "growing";
|
|
732
|
-
},
|
|
733
|
-
inputType: "number",
|
|
734
|
-
testValue: "-1234",
|
|
735
|
-
type: "formatter"
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
// libs/formatters/growth.js
|
|
739
|
-
var logicFactory2 = () => function growth(n) {
|
|
740
|
-
const {
|
|
741
|
-
curr,
|
|
742
|
-
currMoe = 0,
|
|
743
|
-
prev,
|
|
744
|
-
prevMoe = 0
|
|
745
|
-
} = n;
|
|
746
|
-
let value;
|
|
747
|
-
if (currMoe || prevMoe) {
|
|
748
|
-
const f1 = (-prev / curr ** 2) ** 2 * currMoe ** 2;
|
|
749
|
-
const f2 = (1 / curr) ** 2 * prevMoe ** 2;
|
|
750
|
-
value = Math.sqrt(f1 + f2);
|
|
751
|
-
} else
|
|
752
|
-
value = (curr - prev) / prev;
|
|
753
|
-
return value * 100;
|
|
754
|
-
};
|
|
755
|
-
var growth_default = declareFormatter({
|
|
756
|
-
name: "growth",
|
|
757
|
-
// eslint-disable-next-line max-len
|
|
758
|
-
description: "Calculates the growth percentage between two numbers provided the following object format: {curr, prev}. Also supports calculating the growth between two margin of errors using this format: {curr, currMoe, prev, prevMoe}",
|
|
759
|
-
logicFactory: logicFactory2,
|
|
760
|
-
inputType: "object",
|
|
761
|
-
testValue: '{"curr":10,"currMoe":0,"prev":13,"prevMoe":0}',
|
|
762
|
-
type: "formatter"
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
// libs/formatters/growthPct.js
|
|
766
|
-
var growthPct_default = declareFormatter({
|
|
767
|
-
name: "growthPct",
|
|
768
|
-
description: "Abbreviates a growth value, turns it absolute, and adds a percent sign.",
|
|
769
|
-
logicFactory(libs) {
|
|
770
|
-
return (n) => `${libs.d3plus.formatAbbreviate(Math.abs(n))}%`;
|
|
771
|
-
},
|
|
772
|
-
inputType: "number",
|
|
773
|
-
testValue: "12345",
|
|
774
|
-
type: "formatter"
|
|
775
|
-
});
|
|
776
|
-
|
|
777
|
-
// libs/formatters/growthWord.js
|
|
778
|
-
var growthWord_default = declareFormatter({
|
|
779
|
-
name: "growthWord",
|
|
780
|
-
description: "Returns either 'growth' or 'decline' depending on the provided number's sign.",
|
|
781
|
-
logicFactory(libs) {
|
|
782
|
-
return (n) => n < 0 ? "decline" : "growth";
|
|
783
|
-
},
|
|
784
|
-
inputType: "number",
|
|
785
|
-
testValue: "-1234",
|
|
786
|
-
type: "formatter"
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
// libs/formatters/highWord.js
|
|
790
|
-
var highWord_default = declareFormatter({
|
|
791
|
-
name: "highWord",
|
|
792
|
-
// eslint-disable-next-line max-len
|
|
793
|
-
description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign.",
|
|
794
|
-
logicFactory(libs) {
|
|
795
|
-
return (n) => n < 0 ? "lower than" : n > 0 ? "higher than" : "approximately the same as";
|
|
796
|
-
},
|
|
797
|
-
inputType: "number",
|
|
798
|
-
testValue: "0",
|
|
799
|
-
type: "formatter"
|
|
800
|
-
});
|
|
801
|
-
|
|
802
|
-
// libs/formatters/increaseWord.js
|
|
803
|
-
var increaseWord_default = declareFormatter({
|
|
804
|
-
name: "increaseWord",
|
|
805
|
-
// eslint-disable-next-line max-len
|
|
806
|
-
description: "Returns either 'increase', 'decrease', or 'change' depending on the provided number's sign.",
|
|
807
|
-
logicFactory(libs) {
|
|
808
|
-
return (n) => n < 0 ? "decrease" : n > 0 ? "increase" : "change";
|
|
809
|
-
},
|
|
810
|
-
inputType: "number",
|
|
811
|
-
testValue: "1234",
|
|
812
|
-
type: "formatter"
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
// libs/formatters/increasedWord.js
|
|
816
|
-
var increasedWord_default = declareFormatter({
|
|
817
|
-
name: "increasedWord",
|
|
818
|
-
// eslint-disable-next-line max-len
|
|
819
|
-
description: "Returns either 'increased', 'decreased', or 'remained the same' depending on the provided number's sign.",
|
|
820
|
-
logicFactory(libs) {
|
|
821
|
-
return (n) => n < 0 ? "decreased" : n > 0 ? "increased" : "remained the same";
|
|
822
|
-
},
|
|
823
|
-
inputType: "number",
|
|
824
|
-
testValue: "0",
|
|
825
|
-
type: "formatter"
|
|
826
|
-
});
|
|
827
|
-
|
|
828
|
-
// libs/formatters/increasing.js
|
|
829
|
-
var increasing_default = declareFormatter({
|
|
830
|
-
name: "increasing",
|
|
831
|
-
description: "Returns either 'decreasing', 'increasing' or 'maintaining' depending on the provided number's sign.",
|
|
832
|
-
logicFactory(libs) {
|
|
833
|
-
return (n) => n < 0 ? "decreasing" : n > 0 ? "increasing" : "maintaining";
|
|
834
|
-
},
|
|
835
|
-
inputType: "number",
|
|
836
|
-
testValue: "-1234",
|
|
837
|
-
type: "formatter"
|
|
838
|
-
});
|
|
839
|
-
|
|
840
|
-
// libs/formatters/largerThan.js
|
|
841
|
-
var largerThan_default = declareFormatter({
|
|
842
|
-
name: "largerThan",
|
|
843
|
-
// eslint-disable-next-line max-len
|
|
844
|
-
description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign",
|
|
845
|
-
logicFactory(libs) {
|
|
846
|
-
return (n) => n < 0 ? "smaller than" : n > 0 ? "larger than" : "the same as";
|
|
847
|
-
},
|
|
848
|
-
inputType: "number",
|
|
849
|
-
testValue: "-1234",
|
|
850
|
-
type: "formatter"
|
|
851
|
-
});
|
|
852
|
-
|
|
853
|
-
// libs/formatters/list.js
|
|
854
|
-
var list_default = declareFormatter({
|
|
855
|
-
name: "list",
|
|
856
|
-
// eslint-disable-next-line max-len
|
|
857
|
-
description: "Joins an array of strings together, adding commas and 'and' when necessary.",
|
|
858
|
-
logicFactory(libs) {
|
|
859
|
-
return (n) => n.reduce((str, item, i) => {
|
|
860
|
-
if (!i)
|
|
861
|
-
str += item;
|
|
862
|
-
else if (i === n.length - 1 && i === 1)
|
|
863
|
-
str += ` and ${item}`;
|
|
864
|
-
else if (i === n.length - 1)
|
|
865
|
-
str += `, and ${item}`;
|
|
866
|
-
else
|
|
867
|
-
str += `, ${item}`;
|
|
868
|
-
return str;
|
|
869
|
-
}, "");
|
|
870
|
-
},
|
|
871
|
-
inputType: "object",
|
|
872
|
-
testValue: '["foo","bar","bee"]',
|
|
873
|
-
type: "formatter"
|
|
874
|
-
});
|
|
875
|
-
|
|
876
|
-
// libs/formatters/longWord.js
|
|
877
|
-
var longWord_default = declareFormatter({
|
|
878
|
-
name: "longWord",
|
|
879
|
-
description: "",
|
|
880
|
-
logicFactory(libs) {
|
|
881
|
-
return (n) => n < 0 ? "shorter" : n > 0 ? "longer" : "similar";
|
|
882
|
-
},
|
|
883
|
-
inputType: "number",
|
|
884
|
-
testValue: "5",
|
|
885
|
-
type: "formatter"
|
|
886
|
-
});
|
|
887
|
-
|
|
888
|
-
// libs/formatters/lowerCaseFirst.js
|
|
889
|
-
var lowerCaseFirst_default = declareFormatter({
|
|
890
|
-
name: "lowerCaseFirst",
|
|
891
|
-
description: "Converts the first letter of a string to lowercase",
|
|
892
|
-
logicFactory(libs) {
|
|
893
|
-
return (n) => typeof n === "string" ? n.charAt(0).toLowerCase() + n.slice(1) : n;
|
|
894
|
-
},
|
|
895
|
-
inputType: "string",
|
|
896
|
-
testValue: "foo",
|
|
897
|
-
type: "formatter"
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
// libs/formatters/moreFewerWord.js
|
|
901
|
-
var moreFewerWord_default = declareFormatter({
|
|
902
|
-
name: "moreFewerWord",
|
|
903
|
-
description: "",
|
|
904
|
-
logicFactory(libs) {
|
|
905
|
-
return (n) => n < 0 ? "fewer" : "more";
|
|
906
|
-
},
|
|
907
|
-
inputType: "number",
|
|
908
|
-
testValue: "-5",
|
|
909
|
-
type: "formatter"
|
|
910
|
-
});
|
|
911
|
-
|
|
912
|
-
// libs/formatters/moreLess.js
|
|
913
|
-
var moreLess_default = declareFormatter({
|
|
914
|
-
name: "moreLess",
|
|
915
|
-
description: "Returns either 'more' or 'less' depending on the provided number's sign.",
|
|
916
|
-
logicFactory(libs) {
|
|
917
|
-
return (n) => n < 0 ? "less" : "more";
|
|
918
|
-
},
|
|
919
|
-
inputType: "number",
|
|
920
|
-
testValue: "-5",
|
|
921
|
-
type: "formatter"
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
// libs/formatters/moreWord.js
|
|
925
|
-
var moreWord_default = declareFormatter({
|
|
926
|
-
name: "moreLess",
|
|
927
|
-
// eslint-disable-next-line max-len
|
|
928
|
-
description: "Returns either 'more than', 'less than', or 'approximately the same' depending on the provided number's sign.",
|
|
929
|
-
logicFactory(libs) {
|
|
930
|
-
return (n) => n < 0 ? "less than" : n > 0 ? "more than" : "approximately the same";
|
|
931
|
-
},
|
|
932
|
-
inputType: "number",
|
|
933
|
-
testValue: "-5",
|
|
934
|
-
type: "formatter"
|
|
935
|
-
});
|
|
936
|
-
|
|
937
|
-
// libs/formatters/olderWord.js
|
|
938
|
-
var olderWord_default = declareFormatter({
|
|
939
|
-
name: "olderWord",
|
|
940
|
-
description: "",
|
|
941
|
-
logicFactory(libs) {
|
|
942
|
-
return (n) => n < 0 ? "getting younger" : n > 0 ? "getting older" : "staying the same age";
|
|
943
|
-
},
|
|
944
|
-
inputType: "number",
|
|
945
|
-
testValue: "-5",
|
|
946
|
-
type: "formatter"
|
|
947
|
-
});
|
|
948
|
-
|
|
949
|
-
// libs/formatters/olderYounger.js
|
|
950
|
-
var olderYounger_default = declareFormatter({
|
|
951
|
-
name: "olderYounger",
|
|
952
|
-
description: "",
|
|
953
|
-
logicFactory(libs) {
|
|
954
|
-
return (n) => n < 0 ? "younger than" : n > 0 ? "older than" : "the same age as";
|
|
955
|
-
},
|
|
956
|
-
inputType: "number",
|
|
957
|
-
testValue: "-5",
|
|
958
|
-
type: "formatter"
|
|
959
|
-
});
|
|
960
|
-
|
|
961
|
-
// libs/formatters/plural.js
|
|
962
|
-
var plural_default = declareFormatter({
|
|
963
|
-
name: "plural",
|
|
964
|
-
description: "Pluralizes a word.",
|
|
965
|
-
logicFactory(libs) {
|
|
966
|
-
return (n) => n.replace(/\w$/g, (chr) => chr === "y" ? "ies" : `${chr}s`);
|
|
967
|
-
},
|
|
968
|
-
inputType: "string",
|
|
969
|
-
testValue: "Foo",
|
|
970
|
-
type: "formatter"
|
|
971
|
-
});
|
|
972
|
-
|
|
973
|
-
// libs/formatters/pxToInt.js
|
|
974
|
-
var pxToInt_default = declareFormatter({
|
|
975
|
-
name: "pxToInt",
|
|
976
|
-
description: "Takes a pixel value and converts it to an integer",
|
|
977
|
-
logicFactory(libs) {
|
|
978
|
-
return (n) => parseInt(n.replace(/\D+/g, ""), 10);
|
|
979
|
-
},
|
|
980
|
-
inputType: "string",
|
|
981
|
-
testValue: "12px",
|
|
982
|
-
type: "formatter"
|
|
983
|
-
});
|
|
984
|
-
|
|
985
|
-
// libs/formatters/salary.js
|
|
986
|
-
var salary_default = declareFormatter({
|
|
987
|
-
name: "salary",
|
|
988
|
-
description: "Displays salary values with proper precision (ie. '$74,200' instead of '$74.2k')",
|
|
989
|
-
logicFactory(libs) {
|
|
990
|
-
return (n) => {
|
|
991
|
-
let str;
|
|
992
|
-
if (n < 1e6) {
|
|
993
|
-
str = libs.d3.format(",")(n.toFixed(0));
|
|
994
|
-
} else
|
|
995
|
-
str = libs.d3plus.formatAbbreviate(n);
|
|
996
|
-
return `$${str}`;
|
|
997
|
-
};
|
|
998
|
-
},
|
|
999
|
-
inputType: "number",
|
|
1000
|
-
testValue: "1000000",
|
|
1001
|
-
type: "formatter"
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
|
-
// libs/formatters/stripEntities.js
|
|
1005
|
-
var stripEntities_default = declareFormatter({
|
|
1006
|
-
name: "stripEntities",
|
|
1007
|
-
description: "Removes non breaking spaces & other html entities from a string",
|
|
1008
|
-
logicFactory(libs) {
|
|
1009
|
-
return (n) => typeof n === "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
|
|
1010
|
-
},
|
|
1011
|
-
inputType: "string",
|
|
1012
|
-
testValue: "<b>MyText</b>",
|
|
1013
|
-
type: "formatter"
|
|
1014
|
-
});
|
|
1015
|
-
|
|
1016
|
-
// libs/formatters/stripHTML.js
|
|
1017
|
-
var stripHTML_default = declareFormatter({
|
|
1018
|
-
name: "stripHTML",
|
|
1019
|
-
description: "Converts html tags to spaces, then removes redundant spaces",
|
|
1020
|
-
logicFactory(libs) {
|
|
1021
|
-
return (n) => {
|
|
1022
|
-
const entities = {
|
|
1023
|
-
"&": "&",
|
|
1024
|
-
"<": "<",
|
|
1025
|
-
">": ">",
|
|
1026
|
-
""": '"',
|
|
1027
|
-
"'": "'",
|
|
1028
|
-
"`": "`",
|
|
1029
|
-
" ": ""
|
|
1030
|
-
};
|
|
1031
|
-
const source = `(?:${Object.keys(entities).join("|")})`;
|
|
1032
|
-
const testRegexp = RegExp(source);
|
|
1033
|
-
const replaceRegexp = RegExp(source, "g");
|
|
1034
|
-
const s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
1035
|
-
return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
|
|
1036
|
-
};
|
|
1037
|
-
},
|
|
1038
|
-
inputType: "string",
|
|
1039
|
-
testValue: "<b>My text</b>",
|
|
1040
|
-
type: "formatter"
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
// libs/formatters/stripOL.js
|
|
1044
|
-
var stripOL_default = declareFormatter({
|
|
1045
|
-
name: "stripOL",
|
|
1046
|
-
description: "Removes ordered list wrapper tags from a string.",
|
|
1047
|
-
logicFactory(libs) {
|
|
1048
|
-
return (n) => n.replace(/<ol>/g, "").replace(/<\/ol>/g, "");
|
|
1049
|
-
},
|
|
1050
|
-
inputType: "string",
|
|
1051
|
-
testValue: "<ol><li>My list</li></ol>",
|
|
1052
|
-
type: "formatter"
|
|
1053
|
-
});
|
|
1054
|
-
|
|
1055
|
-
// libs/formatters/stripP.js
|
|
1056
|
-
var stripP_default = declareFormatter({
|
|
1057
|
-
name: "stripP",
|
|
1058
|
-
description: "Removes all paragraph tags from a string.",
|
|
1059
|
-
logicFactory(libs) {
|
|
1060
|
-
return (n) => n.replace(/<p>/g, "").replace(/<\/p>/g, "");
|
|
1061
|
-
},
|
|
1062
|
-
inputType: "string",
|
|
1063
|
-
testValue: "<p>My p</p>",
|
|
1064
|
-
type: "formatter"
|
|
1065
|
-
});
|
|
1066
|
-
|
|
1067
|
-
// libs/formatters/stripUL.js
|
|
1068
|
-
var stripUL_default = declareFormatter({
|
|
1069
|
-
name: "stripUL",
|
|
1070
|
-
description: "Removes unordered list wrapper tags from a string.",
|
|
1071
|
-
logicFactory(libs) {
|
|
1072
|
-
return (n) => n.replace(/<ul>/g, "").replace(/<\/ul>/g, "");
|
|
1073
|
-
},
|
|
1074
|
-
inputType: "string",
|
|
1075
|
-
testValue: "<ul><li>My list</li></ul>",
|
|
1076
|
-
type: "formatter"
|
|
1077
|
-
});
|
|
1078
|
-
|
|
1079
|
-
// libs/formatters/toKebabCase.js
|
|
1080
|
-
var toKebabCase_default = declareFormatter({
|
|
1081
|
-
name: "toKebabCase",
|
|
1082
|
-
description: "Takes a camelCase or PascalCase string and converts it to kebab-case.",
|
|
1083
|
-
logicFactory(libs) {
|
|
1084
|
-
return (n) => {
|
|
1085
|
-
if (typeof n === "string") {
|
|
1086
|
-
n = n.charAt(0).toLowerCase() + n.substring(1);
|
|
1087
|
-
return n.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1088
|
-
}
|
|
1089
|
-
return "invalid string passed to toKebabCase()";
|
|
1090
|
-
};
|
|
1091
|
-
},
|
|
1092
|
-
inputType: "string",
|
|
1093
|
-
testValue: "camelCaseText",
|
|
1094
|
-
type: "formatter"
|
|
1095
|
-
});
|
|
1096
|
-
|
|
1097
|
-
// libs/formatters/toSpacedCase.js
|
|
1098
|
-
var toSpacedCase_default = declareFormatter({
|
|
1099
|
-
name: "toSpacedCase",
|
|
1100
|
-
// eslint-disable-next-line max-len
|
|
1101
|
-
description: "Takes a camelCase or PascalCase string and adds spaces (I know Spaced Case isn't a thing, deal with it).",
|
|
1102
|
-
logicFactory(libs) {
|
|
1103
|
-
return (n) => {
|
|
1104
|
-
if (typeof n === "string") {
|
|
1105
|
-
return n.replace(/([A-Z])/g, " $1").toLowerCase().trim();
|
|
1106
|
-
}
|
|
1107
|
-
return "invalid string passed to toSpacedCase()";
|
|
1108
|
-
};
|
|
1109
|
-
},
|
|
1110
|
-
inputType: "string",
|
|
1111
|
-
testValue: "camelCaseText",
|
|
1112
|
-
type: "formatter"
|
|
1113
|
-
});
|
|
1114
|
-
|
|
1115
|
-
// libs/formatters/upperCaseFirst.js
|
|
1116
|
-
var upperCaseFirst_default = declareFormatter({
|
|
1117
|
-
name: "upperCaseFirst",
|
|
1118
|
-
// eslint-disable-next-line max-len
|
|
1119
|
-
description: "Converts the first letter of a string to uppercase",
|
|
1120
|
-
logicFactory(libs) {
|
|
1121
|
-
return (n) => n.charAt(0).toUpperCase() + n.slice(1);
|
|
1122
|
-
},
|
|
1123
|
-
inputType: "string",
|
|
1124
|
-
testValue: "my name",
|
|
1125
|
-
type: "formatter"
|
|
703
|
+
};
|
|
704
|
+
var declaredFormatters = {};
|
|
705
|
+
var REPORT_TYPES = {
|
|
706
|
+
REPORT: "report",
|
|
707
|
+
STORY: "story"
|
|
708
|
+
};
|
|
709
|
+
var REPORT_MODES = {
|
|
710
|
+
UNILATERAL: "uni",
|
|
711
|
+
MULTILATERAL: "multi"
|
|
712
|
+
};
|
|
713
|
+
var SELECTOR_TYPES = {
|
|
714
|
+
SINGLE: "single",
|
|
715
|
+
MULTI: "multi"
|
|
716
|
+
};
|
|
717
|
+
var REPORT_FIELDS = {
|
|
718
|
+
TITLE: "title",
|
|
719
|
+
SUBTITLE: "subtitle",
|
|
720
|
+
LABEL: "label"
|
|
721
|
+
};
|
|
722
|
+
({
|
|
723
|
+
[REPORT_TYPES.REPORT]: Object.values(REPORT_FIELDS),
|
|
724
|
+
[REPORT_TYPES.STORY]: Object.values(REPORT_FIELDS)
|
|
1126
725
|
});
|
|
726
|
+
var BLOCK_CONTENT_TYPES = {
|
|
727
|
+
// AUTHOR: "author",
|
|
728
|
+
// FOOTNOTE: "footnote",
|
|
729
|
+
IMAGE: "image",
|
|
730
|
+
PARAGRAPH: "paragraph",
|
|
731
|
+
SELECTOR: "selector",
|
|
732
|
+
// todo1.0 - move to logic types
|
|
733
|
+
STAT: "stat",
|
|
734
|
+
SUBTITLE: "subtitle",
|
|
735
|
+
TITLE: "title",
|
|
736
|
+
NAV: "nav",
|
|
737
|
+
// todo1.0, how to put custom blocks in here?
|
|
738
|
+
RESET_BUTTON: "reset_button"
|
|
739
|
+
};
|
|
740
|
+
var BLOCK_LOGIC_TYPES = {
|
|
741
|
+
GENERATOR: "generator",
|
|
742
|
+
RELATED: "related",
|
|
743
|
+
VIZ: "visualization"
|
|
744
|
+
};
|
|
745
|
+
var BLOCK_LOGIC_LOCALE = "logic";
|
|
746
|
+
var BLOCK_TYPES = { ...BLOCK_CONTENT_TYPES, ...BLOCK_LOGIC_TYPES };
|
|
747
|
+
var FORMATTER_TYPES = {
|
|
748
|
+
FORMATTER: "formatter",
|
|
749
|
+
FUNCTION: "function"
|
|
750
|
+
};
|
|
751
|
+
var FORMATTER_INPUT_TYPES = {
|
|
752
|
+
STRING: "string",
|
|
753
|
+
NUMBER: "number",
|
|
754
|
+
OBJECT: "object",
|
|
755
|
+
DATE: "date"
|
|
756
|
+
};
|
|
1127
757
|
|
|
1128
758
|
// db/models/formatter.ts
|
|
1129
|
-
var verbose = getLogging_default();
|
|
1130
|
-
if (verbose)
|
|
1131
|
-
console.log(`Loaded formatters: ${Object.keys(formatters_exports)}`);
|
|
1132
759
|
var FormatterModel = class extends Model {
|
|
1133
760
|
};
|
|
1134
761
|
function initModel4(sequelize) {
|
|
@@ -1654,7 +1281,7 @@ var modelFactoryMap = {
|
|
|
1654
1281
|
};
|
|
1655
1282
|
|
|
1656
1283
|
// db/index.ts
|
|
1657
|
-
var
|
|
1284
|
+
var verbose = getLogging_default();
|
|
1658
1285
|
var connectionString = process.env.REPORTS_DB_CONNECTION || "";
|
|
1659
1286
|
var shouldWipe = yn3(process.env.REPORTS_DB_WIPE);
|
|
1660
1287
|
if (!connectionString) {
|
|
@@ -1665,7 +1292,7 @@ if (!connectionString) {
|
|
|
1665
1292
|
}
|
|
1666
1293
|
var getDB = () => {
|
|
1667
1294
|
if (!global.sequelize) {
|
|
1668
|
-
if (
|
|
1295
|
+
if (verbose)
|
|
1669
1296
|
console.log("\u{1F511} INITIALIZING DB CONNECTION");
|
|
1670
1297
|
let sequelize;
|
|
1671
1298
|
try {
|
|
@@ -1708,42 +1335,12 @@ var getDB = () => {
|
|
|
1708
1335
|
})
|
|
1709
1336
|
);
|
|
1710
1337
|
} else {
|
|
1711
|
-
if (
|
|
1338
|
+
if (verbose)
|
|
1712
1339
|
console.log("\u267B\uFE0F RE-UTILIZING DB CONNECTION");
|
|
1713
1340
|
}
|
|
1714
1341
|
return global.sequelize;
|
|
1715
1342
|
};
|
|
1716
1343
|
|
|
1717
|
-
// api/lib.ts
|
|
1718
|
-
var BackendError = class extends Error {
|
|
1719
|
-
constructor(code, message) {
|
|
1720
|
-
super(message);
|
|
1721
|
-
this.code = code;
|
|
1722
|
-
}
|
|
1723
|
-
toJSON() {
|
|
1724
|
-
return failureResult(this);
|
|
1725
|
-
}
|
|
1726
|
-
static is(obj) {
|
|
1727
|
-
return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code === "number";
|
|
1728
|
-
}
|
|
1729
|
-
};
|
|
1730
|
-
function successResult(result) {
|
|
1731
|
-
return { ok: true, status: 200, data: result };
|
|
1732
|
-
}
|
|
1733
|
-
function failureResult(err) {
|
|
1734
|
-
return { ok: false, status: BackendError.is(err) ? err.code : 500, error: err.message };
|
|
1735
|
-
}
|
|
1736
|
-
function resultWrapper(method) {
|
|
1737
|
-
return (param) => method(param).then(successResult, failureResult);
|
|
1738
|
-
}
|
|
1739
|
-
function pickMethod(api, operation, entity) {
|
|
1740
|
-
const name = `${operation}${capitalize(entity)}`;
|
|
1741
|
-
return api[name];
|
|
1742
|
-
}
|
|
1743
|
-
function capitalize(str) {
|
|
1744
|
-
return str[0].toUpperCase() + str.slice(1);
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
1344
|
// libs/configs/getLocales.ts
|
|
1748
1345
|
var getLocales_default = () => {
|
|
1749
1346
|
const localeDefault11 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en";
|
|
@@ -2137,25 +1734,25 @@ var whitelist = [
|
|
|
2137
1734
|
"vi",
|
|
2138
1735
|
"zh"
|
|
2139
1736
|
];
|
|
2140
|
-
var
|
|
1737
|
+
var verbose2 = getLogging_default();
|
|
2141
1738
|
var { locales } = getLocales_default();
|
|
2142
1739
|
var enabledLocales = locales.filter((d) => whitelist.includes(d));
|
|
2143
1740
|
var initializing = false;
|
|
2144
1741
|
var getSearchIndexByLocale = async (db, forceRegenerate = false) => {
|
|
2145
1742
|
if (forceRegenerate) {
|
|
2146
|
-
if (
|
|
1743
|
+
if (verbose2)
|
|
2147
1744
|
console.log("0\uFE0F\u20E3 CLEARING SEARCH INDEX");
|
|
2148
1745
|
global.lunrsearch = void 0;
|
|
2149
1746
|
initializing = false;
|
|
2150
1747
|
}
|
|
2151
1748
|
if (global.lunrsearch) {
|
|
2152
|
-
if (
|
|
1749
|
+
if (verbose2)
|
|
2153
1750
|
console.log("\u{1F501} RE-UTILIZING SEARCH INDEX");
|
|
2154
1751
|
return global.lunrsearch;
|
|
2155
1752
|
}
|
|
2156
1753
|
try {
|
|
2157
1754
|
if (!initializing) {
|
|
2158
|
-
if (
|
|
1755
|
+
if (verbose2)
|
|
2159
1756
|
console.log("1\uFE0F\u20E3 INITIALIZING SEARCH INDEX");
|
|
2160
1757
|
initializing = true;
|
|
2161
1758
|
global.lunrsearch = await newSearchIndex(db);
|
|
@@ -2178,7 +1775,7 @@ async function newSearchIndex(db) {
|
|
|
2178
1775
|
const lunrLang = (await import(`lunr-languages/lunr.${locale}`)).default;
|
|
2179
1776
|
lunrLang(lunr);
|
|
2180
1777
|
lunrStemmer(lunr);
|
|
2181
|
-
if (
|
|
1778
|
+
if (verbose2)
|
|
2182
1779
|
console.log(`\u{1F3F3}\uFE0F INITIALIZING SEARCH ${locale} LOCALE`);
|
|
2183
1780
|
}
|
|
2184
1781
|
return [
|
|
@@ -3041,26 +2638,6 @@ function normalizeList(value) {
|
|
|
3041
2638
|
return value.toString().split(",");
|
|
3042
2639
|
}
|
|
3043
2640
|
|
|
3044
|
-
// types/auth.ts
|
|
3045
|
-
var CMS_ROLES = {
|
|
3046
|
-
ADMIN: "Admin",
|
|
3047
|
-
EDITOR: "Editor",
|
|
3048
|
-
WRITER: "Writer"
|
|
3049
|
-
};
|
|
3050
|
-
var CMS_ROLES_TYPES = {
|
|
3051
|
-
APP: "App",
|
|
3052
|
-
USER: "User"
|
|
3053
|
-
};
|
|
3054
|
-
var addRoleTypes = (roles) => {
|
|
3055
|
-
const systemRoles = Object.values(CMS_ROLES);
|
|
3056
|
-
return roles ? roles.map((r) => {
|
|
3057
|
-
return {
|
|
3058
|
-
...r,
|
|
3059
|
-
type: systemRoles.includes(r.name) ? CMS_ROLES_TYPES.APP : CMS_ROLES_TYPES.USER
|
|
3060
|
-
};
|
|
3061
|
-
}) : [];
|
|
3062
|
-
};
|
|
3063
|
-
|
|
3064
2641
|
// api/endpoints/member.ts
|
|
3065
2642
|
var { localeDefault: localeDefault3 } = getLocales_default();
|
|
3066
2643
|
function endpointMemberFactory(operations) {
|
|
@@ -3725,120 +3302,6 @@ function dbReadPrivateBlocksFactory(db) {
|
|
|
3725
3302
|
};
|
|
3726
3303
|
}
|
|
3727
3304
|
}
|
|
3728
|
-
var auth0ConfigObject = {
|
|
3729
|
-
domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
|
|
3730
|
-
clientId: process.env.AUTH0_CLIENT_ID,
|
|
3731
|
-
clientSecret: process.env.AUTH0_CLIENT_SECRET
|
|
3732
|
-
};
|
|
3733
|
-
var managementClient = new auth0.ManagementClient(auth0ConfigObject);
|
|
3734
|
-
function dbSearchRole() {
|
|
3735
|
-
return async () => {
|
|
3736
|
-
try {
|
|
3737
|
-
const roles = await managementClient.roles.getAll({
|
|
3738
|
-
include_totals: true,
|
|
3739
|
-
per_page: 100
|
|
3740
|
-
});
|
|
3741
|
-
return {
|
|
3742
|
-
roles: addRoleTypes(roles.roles)
|
|
3743
|
-
};
|
|
3744
|
-
} catch (err) {
|
|
3745
|
-
console.error("AuthZeroError", err);
|
|
3746
|
-
throw new BackendError(err.response?.status || 500, err.message);
|
|
3747
|
-
}
|
|
3748
|
-
};
|
|
3749
|
-
}
|
|
3750
|
-
function dbSearchUser() {
|
|
3751
|
-
return async (filters) => {
|
|
3752
|
-
try {
|
|
3753
|
-
let users;
|
|
3754
|
-
if (filters) {
|
|
3755
|
-
const pagination = {
|
|
3756
|
-
include_totals: true,
|
|
3757
|
-
per_page: 10,
|
|
3758
|
-
page: filters.page || 0
|
|
3759
|
-
};
|
|
3760
|
-
if (filters.role_id && filters.role_id !== "") {
|
|
3761
|
-
const paramsByRole = {
|
|
3762
|
-
...pagination,
|
|
3763
|
-
id: filters.role_id
|
|
3764
|
-
};
|
|
3765
|
-
users = await managementClient.roles.getUsers(paramsByRole);
|
|
3766
|
-
} else {
|
|
3767
|
-
const paramsSearch = {
|
|
3768
|
-
...pagination,
|
|
3769
|
-
q: filters.query
|
|
3770
|
-
};
|
|
3771
|
-
users = await managementClient.users.getAll(paramsSearch);
|
|
3772
|
-
}
|
|
3773
|
-
}
|
|
3774
|
-
return users;
|
|
3775
|
-
} catch (err) {
|
|
3776
|
-
console.error("AuthZeroError", err);
|
|
3777
|
-
throw new BackendError(err.response?.status || 500, err.message);
|
|
3778
|
-
}
|
|
3779
|
-
};
|
|
3780
|
-
}
|
|
3781
|
-
function dbReadUser() {
|
|
3782
|
-
return async (userId) => {
|
|
3783
|
-
try {
|
|
3784
|
-
if (userId) {
|
|
3785
|
-
const userData = await Promise.all([
|
|
3786
|
-
managementClient.users.get({ id: userId }),
|
|
3787
|
-
managementClient.users.getRoles({ id: userId })
|
|
3788
|
-
]);
|
|
3789
|
-
return {
|
|
3790
|
-
...userData[0],
|
|
3791
|
-
roles: userData[1]
|
|
3792
|
-
};
|
|
3793
|
-
} else {
|
|
3794
|
-
throw new BackendError(404, "User ID required");
|
|
3795
|
-
}
|
|
3796
|
-
} catch (err) {
|
|
3797
|
-
console.error("AuthZeroError", err);
|
|
3798
|
-
throw new BackendError(err.response?.status || 500, err.message);
|
|
3799
|
-
}
|
|
3800
|
-
};
|
|
3801
|
-
}
|
|
3802
|
-
function dbUpdateUser() {
|
|
3803
|
-
return async (user) => {
|
|
3804
|
-
try {
|
|
3805
|
-
if (user.user_id) {
|
|
3806
|
-
if (user.app_metadata) {
|
|
3807
|
-
await managementClient.users.updateAppMetadata({ id: user.user_id }, user.app_metadata);
|
|
3808
|
-
}
|
|
3809
|
-
if (user.roles) {
|
|
3810
|
-
const currentRoles = await managementClient.users.getRoles({ id: user.user_id });
|
|
3811
|
-
const oldRoles = currentRoles.map((r) => r.id);
|
|
3812
|
-
const newRoles = user.roles.map((r) => r.id);
|
|
3813
|
-
const rolesToAssign = newRoles.filter((role) => !oldRoles.includes(role));
|
|
3814
|
-
const rolesToDelete = oldRoles.filter((role) => !newRoles.includes(role));
|
|
3815
|
-
if (rolesToAssign.length > 0) {
|
|
3816
|
-
await managementClient.users.assignRoles({ id: user.user_id }, { roles: rolesToAssign });
|
|
3817
|
-
}
|
|
3818
|
-
if (rolesToDelete.length > 0) {
|
|
3819
|
-
await managementClient.users.removeRoles({ id: user.user_id }, { roles: rolesToDelete });
|
|
3820
|
-
}
|
|
3821
|
-
}
|
|
3822
|
-
return "User updated!";
|
|
3823
|
-
} else {
|
|
3824
|
-
throw new BackendError(404, "user_id is required");
|
|
3825
|
-
}
|
|
3826
|
-
} catch (err) {
|
|
3827
|
-
console.error("AuthZeroError", err);
|
|
3828
|
-
throw new BackendError(err.response?.status || 500, err.message);
|
|
3829
|
-
}
|
|
3830
|
-
};
|
|
3831
|
-
}
|
|
3832
|
-
function dbAddNewReportToCurrentUser() {
|
|
3833
|
-
return async (params) => {
|
|
3834
|
-
try {
|
|
3835
|
-
return "NOT USED SERVICE";
|
|
3836
|
-
} catch (err) {
|
|
3837
|
-
console.error("AuthZeroError", err);
|
|
3838
|
-
throw new BackendError(err.response?.status || 500, err.message);
|
|
3839
|
-
}
|
|
3840
|
-
};
|
|
3841
|
-
}
|
|
3842
3305
|
|
|
3843
3306
|
// api/db/index.ts
|
|
3844
3307
|
function useDatabaseApi(_, __, api) {
|
|
@@ -3988,7 +3451,6 @@ function parseSearchReportParams(query) {
|
|
|
3988
3451
|
}
|
|
3989
3452
|
|
|
3990
3453
|
// api/endpoints/urlProxy.ts
|
|
3991
|
-
getLogging_default();
|
|
3992
3454
|
function endpointUrlProxyFactory(operations) {
|
|
3993
3455
|
const { urlProxy: urlProxy3 } = operations;
|
|
3994
3456
|
return endpoint("GET", "url/proxy", (req) => {
|
|
@@ -4196,7 +3658,7 @@ function endpointAddNewReportToCurrentUserFactory(operations) {
|
|
|
4196
3658
|
}
|
|
4197
3659
|
|
|
4198
3660
|
// api/endpoints/index.ts
|
|
4199
|
-
var
|
|
3661
|
+
var verbose3 = getLogging_default();
|
|
4200
3662
|
function endpointKey(method, path) {
|
|
4201
3663
|
return `${method.toUpperCase()} ${path.toLowerCase()}`;
|
|
4202
3664
|
}
|
|
@@ -4273,7 +3735,7 @@ async function endpointNextJsHandlerFactory(req, res) {
|
|
|
4273
3735
|
}
|
|
4274
3736
|
}
|
|
4275
3737
|
}).catch((err) => {
|
|
4276
|
-
if (
|
|
3738
|
+
if (verbose3)
|
|
4277
3739
|
console.trace("Backend Error", err);
|
|
4278
3740
|
res.status(err.code).json({ error: err.message });
|
|
4279
3741
|
});
|
|
@@ -4466,7 +3928,7 @@ function parseBlockContext(context) {
|
|
|
4466
3928
|
locale: context.locale || localeDefault6
|
|
4467
3929
|
};
|
|
4468
3930
|
}
|
|
4469
|
-
var
|
|
3931
|
+
var verbose4 = yn3(process.env.REPORTS_LOGGING);
|
|
4470
3932
|
var mortarEval_default = mortarEval;
|
|
4471
3933
|
function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attributes = void 0, blockContext) {
|
|
4472
3934
|
const vars = {};
|
|
@@ -4479,7 +3941,7 @@ function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attr
|
|
|
4479
3941
|
if (isInSet(prop, "log", "debug", "info", "warn", "error")) {
|
|
4480
3942
|
return (...args) => {
|
|
4481
3943
|
log.push(`${prop} ${Date.now()} - ${args.join(" ")}`);
|
|
4482
|
-
if (
|
|
3944
|
+
if (verbose4)
|
|
4483
3945
|
target[prop](...args);
|
|
4484
3946
|
};
|
|
4485
3947
|
}
|
|
@@ -4679,7 +4141,6 @@ var getRootBlocksForSection_default = getRootBlocksForSection;
|
|
|
4679
4141
|
|
|
4680
4142
|
// libs/consts.ts
|
|
4681
4143
|
var apiSeparator = "|||";
|
|
4682
|
-
var verbose7 = getLogging_default();
|
|
4683
4144
|
var debug = yn3(process.env.NEXT_PUBLIC_REPORTS_DEBUG);
|
|
4684
4145
|
var ORIGIN = process.env.REPORTS_ORIGIN || "";
|
|
4685
4146
|
axios5.interceptors.request.use((config) => ({
|
|
@@ -4700,12 +4161,15 @@ var { urlProxy } = apiFactory2("/api/cms");
|
|
|
4700
4161
|
function isResult(response) {
|
|
4701
4162
|
return response.ok !== void 0;
|
|
4702
4163
|
}
|
|
4164
|
+
function ApiFetchException(message) {
|
|
4165
|
+
this.message = message;
|
|
4166
|
+
this.name = "ApiFetchException";
|
|
4167
|
+
}
|
|
4168
|
+
var apiFetchTimeout = process.env.NEXT_PUBLIC_REPORTS_API_FETCH_TIMEOUT || 0;
|
|
4703
4169
|
async function apiFetch(url, settings, readMemberFn, locale = "en") {
|
|
4704
4170
|
const start = Date.now();
|
|
4705
4171
|
let finalUrl = url;
|
|
4706
4172
|
let finalData;
|
|
4707
|
-
if (verbose7)
|
|
4708
|
-
console.log("apiFetch", url);
|
|
4709
4173
|
const parsedUrl = new URL(url);
|
|
4710
4174
|
const parsedQuery = parsedUrl.searchParams;
|
|
4711
4175
|
if (parsedQuery.has("bespoke_slugs")) {
|
|
@@ -4714,11 +4178,26 @@ async function apiFetch(url, settings, readMemberFn, locale = "en") {
|
|
|
4714
4178
|
}
|
|
4715
4179
|
const useProxy = settings && settings.useProxy && settings.useProxy === "true" ? true : false;
|
|
4716
4180
|
if (typeof window === "object" && useProxy) {
|
|
4717
|
-
const result = await urlProxy({ url: finalUrl });
|
|
4718
|
-
|
|
4181
|
+
const result = await urlProxy({ url: finalUrl, timeout: apiFetchTimeout });
|
|
4182
|
+
if (result.ok === true) {
|
|
4183
|
+
finalData = result.data;
|
|
4184
|
+
} else {
|
|
4185
|
+
throw new ApiFetchException(result?.error);
|
|
4186
|
+
}
|
|
4719
4187
|
} else {
|
|
4720
|
-
|
|
4721
|
-
|
|
4188
|
+
try {
|
|
4189
|
+
const response = await axios5({
|
|
4190
|
+
url: finalUrl,
|
|
4191
|
+
timeout: apiFetchTimeout
|
|
4192
|
+
});
|
|
4193
|
+
if (response.status === 200) {
|
|
4194
|
+
finalData = response.data;
|
|
4195
|
+
} else {
|
|
4196
|
+
throw new ApiFetchException("No response");
|
|
4197
|
+
}
|
|
4198
|
+
} catch (e) {
|
|
4199
|
+
throw new ApiFetchException(e.message);
|
|
4200
|
+
}
|
|
4722
4201
|
}
|
|
4723
4202
|
if (parsedQuery.has("bespoke_slugs")) {
|
|
4724
4203
|
const slugStrings = parsedQuery.get("bespoke_slugs");
|
|
@@ -4772,6 +4251,10 @@ async function apiFetch(url, settings, readMemberFn, locale = "en") {
|
|
|
4772
4251
|
requestDuration: Date.now() - start
|
|
4773
4252
|
};
|
|
4774
4253
|
}
|
|
4254
|
+
function BlockException(message) {
|
|
4255
|
+
this.name = "BlockException";
|
|
4256
|
+
this.message = message;
|
|
4257
|
+
}
|
|
4775
4258
|
async function runSingleBlock(block, formatterFunctions, blockContext, readMemberFn) {
|
|
4776
4259
|
const { locale, variables, query } = parseBlockContext(blockContext);
|
|
4777
4260
|
const allowed = isBlockAllowed(block, blockContext, variables, formatterFunctions);
|
|
@@ -4803,18 +4286,30 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
|
|
|
4803
4286
|
block.settings,
|
|
4804
4287
|
readMemberFn,
|
|
4805
4288
|
locale
|
|
4806
|
-
).
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
})
|
|
4289
|
+
).catch(
|
|
4290
|
+
(e) => {
|
|
4291
|
+
throw new BlockException(` Excecution of ${block.type}-${block.id} in section ${block.section_id} in report ${variables.report_name} (${variables.report_id}) failed.
|
|
4292
|
+
Error fetching ${apiUrl}.
|
|
4293
|
+
Message: ${e.message}.
|
|
4294
|
+
`);
|
|
4295
|
+
}
|
|
4296
|
+
)
|
|
4815
4297
|
);
|
|
4816
4298
|
}
|
|
4817
|
-
const apiResponses = await Promise.all(apiPromisesList)
|
|
4299
|
+
const apiResponses = await Promise.all(apiPromisesList).catch((e) => {
|
|
4300
|
+
return e.message;
|
|
4301
|
+
});
|
|
4302
|
+
if (typeof apiResponses === "string") {
|
|
4303
|
+
if (apiResponses) {
|
|
4304
|
+
return {
|
|
4305
|
+
outputVariables: {},
|
|
4306
|
+
renderVariables: {},
|
|
4307
|
+
status: {
|
|
4308
|
+
error: apiResponses
|
|
4309
|
+
}
|
|
4310
|
+
};
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4818
4313
|
resp = apiResponses.length === 1 ? apiResponses[0].data : apiResponses.map((r) => r.data);
|
|
4819
4314
|
responseSize = apiResponses.reduce((acc, r) => acc + JSON.stringify(r.data).length / 1024, 0);
|
|
4820
4315
|
duration = Math.max(...apiResponses.map((ar) => ar.requestDuration));
|
|
@@ -5062,6 +4557,16 @@ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockCont
|
|
|
5062
4557
|
},
|
|
5063
4558
|
readMemberFn
|
|
5064
4559
|
).then(({ outputVariables, status }) => {
|
|
4560
|
+
if (status.error) {
|
|
4561
|
+
if (typeof window === "undefined") {
|
|
4562
|
+
throw new Error(`Run consumers failed with message: ${status.error}`);
|
|
4563
|
+
} else {
|
|
4564
|
+
statusById[bid2] = {
|
|
4565
|
+
allowed: false,
|
|
4566
|
+
error: status.error
|
|
4567
|
+
};
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
5065
4570
|
if (
|
|
5066
4571
|
// store output variables for block that:
|
|
5067
4572
|
(block.consumers.length > 0 || [BLOCK_TYPES.GENERATOR, BLOCK_TYPES.RELATED].includes(block.type)) && status.allowed && Object.keys(outputVariables).length > 0
|
|
@@ -5855,17 +5360,21 @@ function recalculateVariables(resource, params) {
|
|
|
5855
5360
|
};
|
|
5856
5361
|
const section = state.records.entities.section[sid];
|
|
5857
5362
|
const readMemberFn = async (innerParams) => dispatch(readMember(innerParams));
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5363
|
+
try {
|
|
5364
|
+
const data = await runConsumersV2(
|
|
5365
|
+
blocks,
|
|
5366
|
+
section && [section],
|
|
5367
|
+
bid,
|
|
5368
|
+
formatterFunctions,
|
|
5369
|
+
blockContext,
|
|
5370
|
+
void 0,
|
|
5371
|
+
readMemberFn
|
|
5372
|
+
);
|
|
5373
|
+
const { variables, status } = data;
|
|
5374
|
+
dispatch(variablesActions.setVariableChange({ attributes, variables, status }));
|
|
5375
|
+
} catch (error) {
|
|
5376
|
+
console.log("Error in runConsumers client side: recalculateVariables", error);
|
|
5377
|
+
}
|
|
5869
5378
|
};
|
|
5870
5379
|
}
|
|
5871
5380
|
function readMetadata(filters) {
|
|
@@ -6194,4 +5703,4 @@ function getSlugSegments(slugs = []) {
|
|
|
6194
5703
|
};
|
|
6195
5704
|
}
|
|
6196
5705
|
|
|
6197
|
-
export { getSession_default as BespokeGetSession, handleAuth_default as BespokeHandleAuth, BespokeManagerServerSideProps, BespokeRendererStaticPaths, BespokeRendererStaticProps, withApiRoleAuthRequired_default as BespokeWithApiRoleAuthRequired, crosswalk_default as ReportCrosswalkHandler, apiFactory as dbApiFactory, endpointKey, endpointNextJsHandlerFactory, getDB, useDatabaseApi };
|
|
5706
|
+
export { getSession_default as BespokeGetSession, handleAuth_default as BespokeHandleAuth, BespokeManagerServerSideProps, BespokeRendererStaticPaths, BespokeRendererStaticProps, searchUsersByMetadata_default as BespokeSearchUsersByMetadata, updateCurrentUserMetadata_default as BespokeUpdateCurrentUserMetadata, withApiRoleAuthRequired_default as BespokeWithApiRoleAuthRequired, crosswalk_default as ReportCrosswalkHandler, apiFactory as dbApiFactory, endpointKey, endpointNextJsHandlerFactory, getDB, useDatabaseApi };
|