@datawheel/bespoke 0.1.0
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 +19 -0
- package/dist/Viz-41329377.js +368 -0
- package/dist/Viz-41329377.js.map +1 -0
- package/dist/Viz-ef983f01.js +368 -0
- package/dist/Viz-ef983f01.js.map +1 -0
- package/dist/index-9c337b90.js +6680 -0
- package/dist/index-9c337b90.js.map +1 -0
- package/dist/index-cf73f4fa.js +6680 -0
- package/dist/index-cf73f4fa.js.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/server.js +2944 -0
- package/dist/server.js.map +1 -0
- package/dist/style.css +765 -0
- package/package.json +125 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,2944 @@
|
|
|
1
|
+
import * as pg from "pg";
|
|
2
|
+
import { DataTypes, Model, Sequelize, Error as Error$1, fn, col, Op, literal } from "sequelize";
|
|
3
|
+
import yn from "yn";
|
|
4
|
+
import * as d3Array from "d3-array";
|
|
5
|
+
import * as d3Collection from "d3-collection";
|
|
6
|
+
import * as d3Format from "d3-format";
|
|
7
|
+
import * as d3TimeFormat from "d3-time-format";
|
|
8
|
+
import { formatAbbreviate } from "d3plus-format";
|
|
9
|
+
import { date as date$1 } from "d3plus-axis";
|
|
10
|
+
import { assign, closest, merge } from "d3plus-common";
|
|
11
|
+
import { strip, titleCase } from "d3plus-text";
|
|
12
|
+
import axios from "axios";
|
|
13
|
+
import slugifyFn from "slugify";
|
|
14
|
+
import lunr from "lunr";
|
|
15
|
+
import Base58 from "base58";
|
|
16
|
+
import FlickrSDK from "flickr-sdk";
|
|
17
|
+
import sharp from "sharp";
|
|
18
|
+
import { createApi } from "unsplash-js";
|
|
19
|
+
import fs from "fs";
|
|
20
|
+
import NextCors from "nextjs-cors";
|
|
21
|
+
import formidable from "formidable";
|
|
22
|
+
var getLogging = (env = process.env) => yn(env.REPORTS_LOGGING), __defProp$k = Object.defineProperty, __defProps$c = Object.defineProperties, __getOwnPropDescs$c = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$q = Object.getOwnPropertySymbols, __hasOwnProp$q = Object.prototype.hasOwnProperty, __propIsEnum$q = Object.prototype.propertyIsEnumerable, __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$k = (a, b) => {
|
|
23
|
+
for (var prop in b || (b = {}))
|
|
24
|
+
__hasOwnProp$q.call(b, prop) && __defNormalProp$k(a, prop, b[prop]);
|
|
25
|
+
if (__getOwnPropSymbols$q)
|
|
26
|
+
for (var prop of __getOwnPropSymbols$q(b))
|
|
27
|
+
__propIsEnum$q.call(b, prop) && __defNormalProp$k(a, prop, b[prop]);
|
|
28
|
+
return a;
|
|
29
|
+
}, __spreadProps$c = (a, b) => __defProps$c(a, __getOwnPropDescs$c(b));
|
|
30
|
+
class BlockModel extends Model {
|
|
31
|
+
getContent(locale) {
|
|
32
|
+
const content = this.contentByLocale.find((item) => item.locale === locale);
|
|
33
|
+
if (!content)
|
|
34
|
+
throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
|
|
35
|
+
return content;
|
|
36
|
+
}
|
|
37
|
+
toJSON() {
|
|
38
|
+
const attributes = this.get({ plain: !0 });
|
|
39
|
+
delete attributes.block_input;
|
|
40
|
+
const { inputs = [], consumers = [], contentByLocale = [] } = this;
|
|
41
|
+
return __spreadProps$c(__spreadValues$k({}, attributes), {
|
|
42
|
+
inputs: inputs.map((item) => item.toJSON()),
|
|
43
|
+
consumers: consumers.map((item) => item.toJSON()),
|
|
44
|
+
contentByLocale: Object.fromEntries(
|
|
45
|
+
contentByLocale.map((content) => [content.locale, content.toJSON()])
|
|
46
|
+
)
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function initModel$b(sequelize) {
|
|
51
|
+
return BlockModel.init({
|
|
52
|
+
id: {
|
|
53
|
+
type: DataTypes.INTEGER,
|
|
54
|
+
primaryKey: !0,
|
|
55
|
+
autoIncrement: !0
|
|
56
|
+
},
|
|
57
|
+
settings: {
|
|
58
|
+
type: DataTypes.JSON,
|
|
59
|
+
defaultValue: {}
|
|
60
|
+
},
|
|
61
|
+
type: {
|
|
62
|
+
type: DataTypes.STRING,
|
|
63
|
+
defaultValue: "paragraph"
|
|
64
|
+
},
|
|
65
|
+
shared: {
|
|
66
|
+
type: DataTypes.BOOLEAN,
|
|
67
|
+
defaultValue: !1
|
|
68
|
+
},
|
|
69
|
+
blockrow: DataTypes.STRING,
|
|
70
|
+
blockcol: DataTypes.STRING,
|
|
71
|
+
section_id: {
|
|
72
|
+
type: DataTypes.INTEGER,
|
|
73
|
+
onDelete: "cascade",
|
|
74
|
+
references: {
|
|
75
|
+
model: "bespoke_reports_section",
|
|
76
|
+
key: "id"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}, {
|
|
80
|
+
sequelize,
|
|
81
|
+
modelName: "block",
|
|
82
|
+
tableName: "bespoke_reports_block",
|
|
83
|
+
freezeTableName: !0,
|
|
84
|
+
timestamps: !1
|
|
85
|
+
}), (models) => (BlockModel.hasMany(models.block_content, { foreignKey: "id", sourceKey: "id", as: "contentByLocale" }), BlockModel.belongsToMany(models.block, {
|
|
86
|
+
through: "block_input",
|
|
87
|
+
foreignKey: "block_id",
|
|
88
|
+
otherKey: "input_id",
|
|
89
|
+
as: "inputs"
|
|
90
|
+
}), BlockModel.belongsToMany(models.block, {
|
|
91
|
+
through: "block_input",
|
|
92
|
+
foreignKey: "input_id",
|
|
93
|
+
otherKey: "block_id",
|
|
94
|
+
as: "consumers"
|
|
95
|
+
}), BlockModel);
|
|
96
|
+
}
|
|
97
|
+
class BlockContentModel extends Model {
|
|
98
|
+
}
|
|
99
|
+
function initModel$a(sequelize) {
|
|
100
|
+
return BlockContentModel.init({
|
|
101
|
+
id: {
|
|
102
|
+
type: DataTypes.INTEGER,
|
|
103
|
+
primaryKey: !0,
|
|
104
|
+
onDelete: "cascade",
|
|
105
|
+
references: {
|
|
106
|
+
model: "bespoke_reports_block",
|
|
107
|
+
key: "id"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
locale: {
|
|
111
|
+
type: DataTypes.STRING,
|
|
112
|
+
primaryKey: !0
|
|
113
|
+
},
|
|
114
|
+
content: {
|
|
115
|
+
type: DataTypes.JSON,
|
|
116
|
+
defaultValue: {}
|
|
117
|
+
}
|
|
118
|
+
}, {
|
|
119
|
+
sequelize,
|
|
120
|
+
modelName: "block_content",
|
|
121
|
+
tableName: "bespoke_reports_block_content",
|
|
122
|
+
freezeTableName: !0,
|
|
123
|
+
timestamps: !1
|
|
124
|
+
}), () => BlockContentModel;
|
|
125
|
+
}
|
|
126
|
+
class BlockInputModel extends Model {
|
|
127
|
+
}
|
|
128
|
+
function initModel$9(sequelize) {
|
|
129
|
+
return BlockInputModel.init({
|
|
130
|
+
id: {
|
|
131
|
+
type: DataTypes.INTEGER,
|
|
132
|
+
primaryKey: !0,
|
|
133
|
+
autoIncrement: !0
|
|
134
|
+
},
|
|
135
|
+
block_id: {
|
|
136
|
+
type: DataTypes.INTEGER,
|
|
137
|
+
onDelete: "cascade",
|
|
138
|
+
references: {
|
|
139
|
+
model: "bespoke_reports_block",
|
|
140
|
+
key: "id"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
input_id: {
|
|
144
|
+
type: DataTypes.INTEGER,
|
|
145
|
+
onDelete: "cascade",
|
|
146
|
+
references: {
|
|
147
|
+
model: "bespoke_reports_block",
|
|
148
|
+
key: "id"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}, {
|
|
152
|
+
sequelize,
|
|
153
|
+
modelName: "block_input",
|
|
154
|
+
tableName: "bespoke_reports_block_input",
|
|
155
|
+
freezeTableName: !0,
|
|
156
|
+
timestamps: !1
|
|
157
|
+
}), () => BlockInputModel;
|
|
158
|
+
}
|
|
159
|
+
function logGamma(Z) {
|
|
160
|
+
const S = 1 + 76.18009173 / Z - 86.50532033 / (Z + 1) + 24.01409822 / (Z + 2) - 1.231739516 / (Z + 3) + 0.00120858003 / (Z + 4) - 536382e-11 / (Z + 5);
|
|
161
|
+
return (Z - 0.5) * Math.log(Z + 4.5) - (Z + 4.5) + Math.log(S * 2.50662827465);
|
|
162
|
+
}
|
|
163
|
+
function betinc(X, A, B) {
|
|
164
|
+
let A0 = 0, B0 = 1, A1 = 1, B1 = 1, M9 = 0, A2 = 0, C9;
|
|
165
|
+
for (; Math.abs((A1 - A2) / A1) > 1e-5; )
|
|
166
|
+
A2 = A1, C9 = -(A + M9) * (A + B + M9) * X / (A + 2 * M9) / (A + 2 * M9 + 1), A0 = A1 + C9 * A0, B0 = B1 + C9 * B0, M9 += 1, C9 = M9 * (B - M9) * X / (A + 2 * M9 - 1) / (A + 2 * M9), A1 = A0 + C9 * A1, B1 = B0 + C9 * B1, A0 /= B1, B0 /= B1, A1 /= B1, B1 = 1;
|
|
167
|
+
return A1 / A;
|
|
168
|
+
}
|
|
169
|
+
function binomialCdf(X, N, P) {
|
|
170
|
+
let betacdf, bincdf;
|
|
171
|
+
if (X < 0)
|
|
172
|
+
bincdf = 0;
|
|
173
|
+
else if (X >= N)
|
|
174
|
+
bincdf = 1;
|
|
175
|
+
else {
|
|
176
|
+
X = Math.floor(X);
|
|
177
|
+
const Z = P, A = X + 1, B = N - X, S = A + B, BT = Math.exp(logGamma(S) - logGamma(B) - logGamma(A) + A * Math.log(Z) + B * Math.log(1 - Z));
|
|
178
|
+
Z < (A + 1) / (S + 2) ? betacdf = BT * betinc(Z, A, B) : betacdf = 1 - BT * betinc(1 - Z, B, A), bincdf = 1 - betacdf;
|
|
179
|
+
}
|
|
180
|
+
return Math.round(bincdf * 1e5) / 1e5;
|
|
181
|
+
}
|
|
182
|
+
function criticalValue(confLevel) {
|
|
183
|
+
return {
|
|
184
|
+
0.99999: 15.137,
|
|
185
|
+
0.99: 6.635,
|
|
186
|
+
0.95: 3.841,
|
|
187
|
+
0.9: 2.706
|
|
188
|
+
}[confLevel];
|
|
189
|
+
}
|
|
190
|
+
function binP(N, p, x1, x2) {
|
|
191
|
+
const q = p / (1 - p);
|
|
192
|
+
let k = 0, v = 1, s = 0, tot = 0;
|
|
193
|
+
for (; k <= N; )
|
|
194
|
+
tot += v, k >= x1 & k <= x2 && (s += v), tot > 1e30 && (s /= 1e30, tot /= 1e30, v /= 1e30), k += 1, v = v * q * (N + 1 - k) / k;
|
|
195
|
+
return s / tot;
|
|
196
|
+
}
|
|
197
|
+
function computeMidP(vx, vN, confLevel) {
|
|
198
|
+
const vP = vx / vN, vTL = (100 - confLevel * 100) / 2;
|
|
199
|
+
let T1, T2;
|
|
200
|
+
if (vx === 0)
|
|
201
|
+
T1 = 0;
|
|
202
|
+
else {
|
|
203
|
+
let v = vP / 2, vsL = 0, vsH = vP;
|
|
204
|
+
const p = vTL / 100;
|
|
205
|
+
for (; vsH - vsL > 1e-5; )
|
|
206
|
+
binP(vN, v, vx, vx) * 0.5 + binP(vN, v, vx + 1, vN) > p ? (vsH = v, v = (vsL + v) / 2) : (vsL = v, v = (vsH + v) / 2);
|
|
207
|
+
T1 = v;
|
|
208
|
+
}
|
|
209
|
+
if (vx === vN)
|
|
210
|
+
T2 = 0;
|
|
211
|
+
else {
|
|
212
|
+
let v = (1 + vP) / 2, vsL = vP, vsH = 1;
|
|
213
|
+
const p = vTL / 100;
|
|
214
|
+
for (; vsH - vsL > 1e-5; )
|
|
215
|
+
binP(vN, v, vx, vx) * 0.5 + binP(vN, v, 0, vx - 1) < p ? (vsH = v, v = (vsL + v) / 2) : (vsL = v, v = (vsH + v) / 2);
|
|
216
|
+
T2 = v;
|
|
217
|
+
}
|
|
218
|
+
return { lci: T1, uci: T2 };
|
|
219
|
+
}
|
|
220
|
+
function smr(observedVal, expectedVal) {
|
|
221
|
+
const vx = observedVal, vN = expectedVal, Obs = vx, Exp = vN, ci = 95;
|
|
222
|
+
let v = 0.5, dv = 0.5, p = (100 - ci) / 2 / 100;
|
|
223
|
+
const vZ = Obs;
|
|
224
|
+
for (; dv > 1e-5; )
|
|
225
|
+
dv /= 2, poisP((1 + vZ) * v / (1 - v), vZ + 1, 1e10) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) > p ? v -= dv : v += dv;
|
|
226
|
+
const QL = (1 + vZ) * v / (1 - v) / Exp;
|
|
227
|
+
for (v = 0.5, dv = 0.5, p = (100 - ci) / 2 / 100; dv > 1e-5; )
|
|
228
|
+
dv /= 2, poisP((1 + vZ) * v / (1 - v), 0, vZ - 1) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) < p ? v -= dv : v += dv;
|
|
229
|
+
const QU = (1 + vZ) * v / (1 - v) / Exp;
|
|
230
|
+
return { lci: QL, uci: QU };
|
|
231
|
+
}
|
|
232
|
+
function poisP(Z, x1, x2) {
|
|
233
|
+
let q = 1, tot = 0, s = 0, k = 0;
|
|
234
|
+
for (; k < Z || q > tot * 1e-10; )
|
|
235
|
+
tot += q, k >= x1 & k <= x2 && (s += q), tot > 1e30 && (s /= 1e30, tot /= 1e30, q /= 1e30), k += 1, q = q * Z / k;
|
|
236
|
+
return s / tot;
|
|
237
|
+
}
|
|
238
|
+
var stats = {
|
|
239
|
+
binomialCdf,
|
|
240
|
+
binP,
|
|
241
|
+
computeMidP,
|
|
242
|
+
criticalValue,
|
|
243
|
+
smr
|
|
244
|
+
}, __defProp$j = Object.defineProperty, __getOwnPropSymbols$p = Object.getOwnPropertySymbols, __hasOwnProp$p = Object.prototype.hasOwnProperty, __propIsEnum$p = Object.prototype.propertyIsEnumerable, __defNormalProp$j = (obj, key, value) => key in obj ? __defProp$j(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$j = (a, b) => {
|
|
245
|
+
for (var prop in b || (b = {}))
|
|
246
|
+
__hasOwnProp$p.call(b, prop) && __defNormalProp$j(a, prop, b[prop]);
|
|
247
|
+
if (__getOwnPropSymbols$p)
|
|
248
|
+
for (var prop of __getOwnPropSymbols$p(b))
|
|
249
|
+
__propIsEnum$p.call(b, prop) && __defNormalProp$j(a, prop, b[prop]);
|
|
250
|
+
return a;
|
|
251
|
+
};
|
|
252
|
+
const libs = {
|
|
253
|
+
d3: __spreadValues$j(__spreadValues$j(__spreadValues$j(__spreadValues$j({}, d3Array), d3Collection), d3Format), d3TimeFormat),
|
|
254
|
+
d3plus: {
|
|
255
|
+
assign,
|
|
256
|
+
closest,
|
|
257
|
+
date: date$1,
|
|
258
|
+
formatAbbreviate,
|
|
259
|
+
merge,
|
|
260
|
+
strip,
|
|
261
|
+
titleCase
|
|
262
|
+
},
|
|
263
|
+
stats
|
|
264
|
+
}, declaredFormatters = {};
|
|
265
|
+
function declareFormatter(manifest) {
|
|
266
|
+
const func = manifest.logicFactory(libs);
|
|
267
|
+
return declaredFormatters[manifest.name] = {
|
|
268
|
+
description: manifest.description,
|
|
269
|
+
inputType: manifest.inputType,
|
|
270
|
+
logic: stringifyFn(func),
|
|
271
|
+
testValue: manifest.testValue,
|
|
272
|
+
type: manifest.type || "formatter"
|
|
273
|
+
}, func;
|
|
274
|
+
}
|
|
275
|
+
function stringifyFn(func) {
|
|
276
|
+
const strFunc = func.toString().trim();
|
|
277
|
+
if (strFunc.startsWith("function"))
|
|
278
|
+
return strFunc.replace(/^function(?:\s\w+)?\([^\)]\)/, "").trim().replace(/^{([\s\S]+)\}$/, "$1");
|
|
279
|
+
const noArgs = strFunc.replace(/^.+?=>/, "").trim();
|
|
280
|
+
return noArgs.startsWith("{") ? noArgs.replace(/^{([\s\S]+)\}$/, "$1") : `return ${noArgs}`;
|
|
281
|
+
}
|
|
282
|
+
var __defProp$i = Object.defineProperty, __getOwnPropSymbols$o = Object.getOwnPropertySymbols, __hasOwnProp$o = Object.prototype.hasOwnProperty, __propIsEnum$o = Object.prototype.propertyIsEnumerable, __defNormalProp$i = (obj, key, value) => key in obj ? __defProp$i(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$i = (a, b) => {
|
|
283
|
+
for (var prop in b || (b = {}))
|
|
284
|
+
__hasOwnProp$o.call(b, prop) && __defNormalProp$i(a, prop, b[prop]);
|
|
285
|
+
if (__getOwnPropSymbols$o)
|
|
286
|
+
for (var prop of __getOwnPropSymbols$o(b))
|
|
287
|
+
__propIsEnum$o.call(b, prop) && __defNormalProp$i(a, prop, b[prop]);
|
|
288
|
+
return a;
|
|
289
|
+
};
|
|
290
|
+
const REPORT_TYPES = {
|
|
291
|
+
REPORT: "report",
|
|
292
|
+
STORY: "story"
|
|
293
|
+
}, REPORT_MODES = {
|
|
294
|
+
UNILATERAL: "uni",
|
|
295
|
+
MULTILATERAL: "multi"
|
|
296
|
+
}, REPORT_FIELDS = {
|
|
297
|
+
TITLE: "title",
|
|
298
|
+
SUBTITLE: "subtitle",
|
|
299
|
+
LABEL: "label"
|
|
300
|
+
};
|
|
301
|
+
REPORT_TYPES.REPORT + "", Object.values(REPORT_FIELDS), REPORT_TYPES.STORY + "", Object.values(REPORT_FIELDS);
|
|
302
|
+
const ALLOWED = {
|
|
303
|
+
ALLOWED: "allowed",
|
|
304
|
+
ALLOWED_LOGIC: "allowedLogic"
|
|
305
|
+
};
|
|
306
|
+
__spreadValues$i({}, ALLOWED), __spreadValues$i({
|
|
307
|
+
POSITION: "position",
|
|
308
|
+
ICON: "icon"
|
|
309
|
+
}, ALLOWED);
|
|
310
|
+
const BLOCK_CONTENT_TYPES = {
|
|
311
|
+
IMAGE: "image",
|
|
312
|
+
PARAGRAPH: "paragraph",
|
|
313
|
+
SELECTOR: "selector",
|
|
314
|
+
STAT: "stat",
|
|
315
|
+
SUBTITLE: "subtitle",
|
|
316
|
+
TITLE: "title"
|
|
317
|
+
}, BLOCK_LOGIC_TYPES = {
|
|
318
|
+
GENERATOR: "generator",
|
|
319
|
+
VIZ: "visualization"
|
|
320
|
+
}, BLOCK_TYPES = __spreadValues$i(__spreadValues$i({}, BLOCK_CONTENT_TYPES), BLOCK_LOGIC_TYPES);
|
|
321
|
+
BLOCK_TYPES.GENERATOR, BLOCK_TYPES.SELECTOR, BLOCK_TYPES.VIZ, BLOCK_TYPES.IMAGE;
|
|
322
|
+
const BLOCK_FIELDS = {
|
|
323
|
+
ALT: "alt",
|
|
324
|
+
AUTHOR: "author",
|
|
325
|
+
FOOTNOTE: "footnote",
|
|
326
|
+
BIO: "bio",
|
|
327
|
+
IMAGE: "image",
|
|
328
|
+
LOGIC: "logic",
|
|
329
|
+
SIMPLE: "simple",
|
|
330
|
+
SIMPLE_ENABLED: "simpleEnabled",
|
|
331
|
+
PARAGRAPH: "paragraph",
|
|
332
|
+
SELECTOR_DEFAULT: "selectorDefault",
|
|
333
|
+
SELECTOR_DYNAMIC: "selectorDynamic",
|
|
334
|
+
SELECTOR_NAME: "selectorName",
|
|
335
|
+
SELECTOR_TYPE: "selectorType",
|
|
336
|
+
SRC: "src",
|
|
337
|
+
SLUG: "slug",
|
|
338
|
+
SUBTITLE: "subtitle",
|
|
339
|
+
TITLE: "title",
|
|
340
|
+
TOOLTIP: "tooltip",
|
|
341
|
+
TWITTER: "twitter",
|
|
342
|
+
VALUE: "value"
|
|
343
|
+
};
|
|
344
|
+
BLOCK_TYPES.IMAGE + "", BLOCK_FIELDS.SRC, BLOCK_FIELDS.ALT, BLOCK_TYPES.PARAGRAPH + "", BLOCK_TYPES.PARAGRAPH, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.SELECTOR + "", BLOCK_FIELDS.SELECTOR_DEFAULT, BLOCK_FIELDS.SELECTOR_DYNAMIC, BLOCK_FIELDS.SELECTOR_NAME, BLOCK_FIELDS.SELECTOR_TYPE, BLOCK_TYPES.STAT + "", BLOCK_FIELDS.TITLE, BLOCK_FIELDS.SUBTITLE, BLOCK_FIELDS.VALUE, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.SUBTITLE + "", BLOCK_FIELDS.SUBTITLE, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.TITLE + "", BLOCK_FIELDS.TITLE, BLOCK_FIELDS.SLUG, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.GENERATOR + "", BLOCK_TYPES.VIZ + "", __spreadValues$i({
|
|
345
|
+
NAME: "name",
|
|
346
|
+
DESCRIPTION: "description"
|
|
347
|
+
}, ALLOWED);
|
|
348
|
+
const FORMATTER_TYPES = {
|
|
349
|
+
FORMATTER: "formatter",
|
|
350
|
+
FUNCTION: "function"
|
|
351
|
+
}, FORMATTER_INPUT_TYPES = {
|
|
352
|
+
STRING: "string",
|
|
353
|
+
NUMBER: "number",
|
|
354
|
+
OBJECT: "object",
|
|
355
|
+
DATE: "date"
|
|
356
|
+
};
|
|
357
|
+
var abbreviate = declareFormatter({
|
|
358
|
+
name: "abbreviate",
|
|
359
|
+
description: "Abbreviates a number into a smaller more human-readable number.",
|
|
360
|
+
logicFactory(libs2) {
|
|
361
|
+
return (n) => libs2.d3plus.formatAbbreviate(n);
|
|
362
|
+
},
|
|
363
|
+
inputType: "number",
|
|
364
|
+
testValue: "123456",
|
|
365
|
+
type: "formatter"
|
|
366
|
+
}), abs = declareFormatter({
|
|
367
|
+
name: "abs",
|
|
368
|
+
description: "Simple Absolute Value.",
|
|
369
|
+
logicFactory(libs2) {
|
|
370
|
+
return (n) => Math.abs(n);
|
|
371
|
+
},
|
|
372
|
+
inputType: "number",
|
|
373
|
+
testValue: "-123",
|
|
374
|
+
type: "formatter"
|
|
375
|
+
});
|
|
376
|
+
const logicFactory$1 = () => function(n) {
|
|
377
|
+
let nums = new RegExp(/([\$0-9\,]+)[A-z\-\s\&]*([\$0-9\,]*)/g).exec(n);
|
|
378
|
+
return nums ? (nums = nums.slice(1).filter((d) => d.length).map((d) => (d.includes(",") && (d.indexOf(",") === d.length - 4 ? d = d.replace(/,000$/g, "k").replace(/([0-9]+)(,999$)/g, (n2) => `${parseInt(n2) + 1}k`) : d.indexOf(",") === d.length - 8 && (d = d.replace(/,000,000$/g, "M").replace(/([0-9]+)(,999,999$)/g, (n2) => `${parseInt(n2) + 1}M`))), d)), nums.length === 2 ? nums.join(" - ") : n.toLowerCase().match(/under|less|\</g) ? `< ${nums[0]}` : n.toLowerCase().match(/over|more|\+|\>/g) ? `${nums[0]}+` : `${nums[0]}`) : "None";
|
|
379
|
+
};
|
|
380
|
+
var bucket = declareFormatter({
|
|
381
|
+
name: "bucket",
|
|
382
|
+
description: "Sanitizes bucket strings to '< n', 'n1 - n2', and 'n+'",
|
|
383
|
+
logicFactory: logicFactory$1,
|
|
384
|
+
inputType: "number",
|
|
385
|
+
testValue: "1234",
|
|
386
|
+
type: "formatter"
|
|
387
|
+
}), commas = declareFormatter({
|
|
388
|
+
name: "commas",
|
|
389
|
+
description: "* Rounds to nearest whole number and adds commas.",
|
|
390
|
+
logicFactory(libs2) {
|
|
391
|
+
return (n) => libs2.d3.format(",")(Math.round(n));
|
|
392
|
+
},
|
|
393
|
+
inputType: "number",
|
|
394
|
+
testValue: "1234.6",
|
|
395
|
+
type: "formatter"
|
|
396
|
+
}), date = declareFormatter({
|
|
397
|
+
name: "date",
|
|
398
|
+
description: "Formats a date into '%B %d, %Y' format.",
|
|
399
|
+
logicFactory(libs2) {
|
|
400
|
+
return (n) => (typeof n == "string" && (n = libs2.d3plus.date(n)), libs2.d3.timeFormat("%B %d, %Y")(n));
|
|
401
|
+
},
|
|
402
|
+
inputType: "date",
|
|
403
|
+
testValue: "2022-01-01",
|
|
404
|
+
type: "formatter"
|
|
405
|
+
}), dollar = declareFormatter({
|
|
406
|
+
name: "date",
|
|
407
|
+
description: "Adds a US dollar sign to the beginning of a String or Number.",
|
|
408
|
+
logicFactory(libs2) {
|
|
409
|
+
return (n) => (typeof n == "number" && (n = libs2.d3plus.formatAbbreviate(n)), n.charAt(0) === "-" ? n.replace("-", "-$") : `$${n}`);
|
|
410
|
+
},
|
|
411
|
+
inputType: "number",
|
|
412
|
+
testValue: "123",
|
|
413
|
+
type: "formatter"
|
|
414
|
+
}), formatFieldName = declareFormatter({
|
|
415
|
+
name: "formatFieldName",
|
|
416
|
+
description: "Based on field name returns a string",
|
|
417
|
+
logicFactory(libs2) {
|
|
418
|
+
return (n) => {
|
|
419
|
+
if (n.contentType.toLowerCase() === "stat") {
|
|
420
|
+
if (n.field === "title")
|
|
421
|
+
return "Stat label";
|
|
422
|
+
if (n.field === "value")
|
|
423
|
+
return "Stat value";
|
|
424
|
+
if (n.field === "subtitle")
|
|
425
|
+
return "Stat subtitle";
|
|
426
|
+
if (n.field === "tooltip")
|
|
427
|
+
return "Tooltip text";
|
|
428
|
+
}
|
|
429
|
+
return n.contentType.toLowerCase() === "section" && n.field === "short" ? "Short title" : n.contentType.toLowerCase() === "description" && n.field === "description" ? "Paragraph" : n.field;
|
|
430
|
+
};
|
|
431
|
+
},
|
|
432
|
+
inputType: "object",
|
|
433
|
+
testValue: '{"field":"title","contentType":"stat"}',
|
|
434
|
+
type: "formatter"
|
|
435
|
+
}), grewTo = declareFormatter({
|
|
436
|
+
name: "grewTo",
|
|
437
|
+
description: "Returns the text with grow direction: 'declined from', 'grew to' o 'stayed at'",
|
|
438
|
+
logicFactory(libs2) {
|
|
439
|
+
return (n) => n < 0 ? "declined from" : n > 0 ? "grew to" : "stayed at";
|
|
440
|
+
},
|
|
441
|
+
inputType: "number",
|
|
442
|
+
testValue: "-1234",
|
|
443
|
+
type: "formatter"
|
|
444
|
+
}), grewWord = declareFormatter({
|
|
445
|
+
name: "grewWord",
|
|
446
|
+
description: "Returns either 'grew', 'declined', or 'stayed' depending on the provided number's sign.",
|
|
447
|
+
logicFactory(libs2) {
|
|
448
|
+
return (n) => n < 0 ? "declined" : n > 0 ? "grew" : "stayed";
|
|
449
|
+
},
|
|
450
|
+
inputType: "number",
|
|
451
|
+
testValue: "-1234",
|
|
452
|
+
type: "formatter"
|
|
453
|
+
}), growing = declareFormatter({
|
|
454
|
+
name: "growing",
|
|
455
|
+
description: "Returns either 'declining', 'growing' depending on the provided number's sign.",
|
|
456
|
+
logicFactory(libs2) {
|
|
457
|
+
return (n) => n < 0 ? "declining" : "growing";
|
|
458
|
+
},
|
|
459
|
+
inputType: "number",
|
|
460
|
+
testValue: "-1234",
|
|
461
|
+
type: "formatter"
|
|
462
|
+
});
|
|
463
|
+
const logicFactory = () => function(n) {
|
|
464
|
+
const {
|
|
465
|
+
curr,
|
|
466
|
+
currMoe = 0,
|
|
467
|
+
prev,
|
|
468
|
+
prevMoe = 0
|
|
469
|
+
} = n;
|
|
470
|
+
let value;
|
|
471
|
+
if (currMoe || prevMoe) {
|
|
472
|
+
const f1 = (-prev / curr ** 2) ** 2 * currMoe ** 2, f2 = (1 / curr) ** 2 * prevMoe ** 2;
|
|
473
|
+
value = Math.sqrt(f1 + f2);
|
|
474
|
+
} else
|
|
475
|
+
value = (curr - prev) / prev;
|
|
476
|
+
return value * 100;
|
|
477
|
+
};
|
|
478
|
+
var growth = declareFormatter({
|
|
479
|
+
name: "growth",
|
|
480
|
+
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}",
|
|
481
|
+
logicFactory,
|
|
482
|
+
inputType: "object",
|
|
483
|
+
testValue: '{"curr":10,"currMoe":0,"prev":13,"prevMoe":0}',
|
|
484
|
+
type: "formatter"
|
|
485
|
+
}), growthPct = declareFormatter({
|
|
486
|
+
name: "growthPct",
|
|
487
|
+
description: "Abbreviates a growth value, turns it absolute, and adds a percent sign.",
|
|
488
|
+
logicFactory(libs2) {
|
|
489
|
+
return (n) => `${libs2.d3plus.formatAbbreviate(Math.abs(n))}%`;
|
|
490
|
+
},
|
|
491
|
+
inputType: "number",
|
|
492
|
+
testValue: "12345",
|
|
493
|
+
type: "formatter"
|
|
494
|
+
}), growthWord = declareFormatter({
|
|
495
|
+
name: "growthWord",
|
|
496
|
+
description: "Returns either 'growth' or 'decline' depending on the provided number's sign.",
|
|
497
|
+
logicFactory(libs2) {
|
|
498
|
+
return (n) => n < 0 ? "decline" : "growth";
|
|
499
|
+
},
|
|
500
|
+
inputType: "number",
|
|
501
|
+
testValue: "-1234",
|
|
502
|
+
type: "formatter"
|
|
503
|
+
}), highWord = declareFormatter({
|
|
504
|
+
name: "highWord",
|
|
505
|
+
description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign.",
|
|
506
|
+
logicFactory(libs2) {
|
|
507
|
+
return (n) => n < 0 ? "lower than" : n > 0 ? "higher than" : "approximately the same as";
|
|
508
|
+
},
|
|
509
|
+
inputType: "number",
|
|
510
|
+
testValue: "0",
|
|
511
|
+
type: "formatter"
|
|
512
|
+
}), increaseWord = declareFormatter({
|
|
513
|
+
name: "increaseWord",
|
|
514
|
+
description: "Returns either 'increase', 'decrease', or 'change' depending on the provided number's sign.",
|
|
515
|
+
logicFactory(libs2) {
|
|
516
|
+
return (n) => n < 0 ? "decrease" : n > 0 ? "increase" : "change";
|
|
517
|
+
},
|
|
518
|
+
inputType: "number",
|
|
519
|
+
testValue: "1234",
|
|
520
|
+
type: "formatter"
|
|
521
|
+
}), increasedWord = declareFormatter({
|
|
522
|
+
name: "increasedWord",
|
|
523
|
+
description: "Returns either 'increased', 'decreased', or 'remained the same' depending on the provided number's sign.",
|
|
524
|
+
logicFactory(libs2) {
|
|
525
|
+
return (n) => n < 0 ? "decreased" : n > 0 ? "increased" : "remained the same";
|
|
526
|
+
},
|
|
527
|
+
inputType: "number",
|
|
528
|
+
testValue: "0",
|
|
529
|
+
type: "formatter"
|
|
530
|
+
}), increasing = declareFormatter({
|
|
531
|
+
name: "increasing",
|
|
532
|
+
description: "Returns either 'decreasing', 'increasing' or 'maintaining' depending on the provided number's sign.",
|
|
533
|
+
logicFactory(libs2) {
|
|
534
|
+
return (n) => n < 0 ? "decreasing" : n > 0 ? "increasing" : "maintaining";
|
|
535
|
+
},
|
|
536
|
+
inputType: "number",
|
|
537
|
+
testValue: "-1234",
|
|
538
|
+
type: "formatter"
|
|
539
|
+
}), largerThan = declareFormatter({
|
|
540
|
+
name: "largerThan",
|
|
541
|
+
description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign",
|
|
542
|
+
logicFactory(libs2) {
|
|
543
|
+
return (n) => n < 0 ? "smaller than" : n > 0 ? "larger than" : "the same as";
|
|
544
|
+
},
|
|
545
|
+
inputType: "number",
|
|
546
|
+
testValue: "-1234",
|
|
547
|
+
type: "formatter"
|
|
548
|
+
}), list = declareFormatter({
|
|
549
|
+
name: "list",
|
|
550
|
+
description: "Joins an array of strings together, adding commas and 'and' when necessary.",
|
|
551
|
+
logicFactory(libs2) {
|
|
552
|
+
return (n) => n.reduce((str, item, i) => (i ? i === n.length - 1 && i === 1 ? str += ` and ${item}` : i === n.length - 1 ? str += `, and ${item}` : str += `, ${item}` : str += item, str), "");
|
|
553
|
+
},
|
|
554
|
+
inputType: "object",
|
|
555
|
+
testValue: '["foo","bar","bee"]',
|
|
556
|
+
type: "formatter"
|
|
557
|
+
}), longWord = declareFormatter({
|
|
558
|
+
name: "longWord",
|
|
559
|
+
description: "",
|
|
560
|
+
logicFactory(libs2) {
|
|
561
|
+
return (n) => n < 0 ? "shorter" : n > 0 ? "longer" : "similar";
|
|
562
|
+
},
|
|
563
|
+
inputType: "number",
|
|
564
|
+
testValue: "5",
|
|
565
|
+
type: "formatter"
|
|
566
|
+
}), lowerCaseFirst = declareFormatter({
|
|
567
|
+
name: "lowerCaseFirst",
|
|
568
|
+
description: "Converts the first letter of a string to lowercase",
|
|
569
|
+
logicFactory(libs2) {
|
|
570
|
+
return (n) => typeof n == "string" ? n.charAt(0).toLowerCase() + n.slice(1) : n;
|
|
571
|
+
},
|
|
572
|
+
inputType: "string",
|
|
573
|
+
testValue: "foo",
|
|
574
|
+
type: "formatter"
|
|
575
|
+
}), moreFewerWord = declareFormatter({
|
|
576
|
+
name: "moreFewerWord",
|
|
577
|
+
description: "",
|
|
578
|
+
logicFactory(libs2) {
|
|
579
|
+
return (n) => n < 0 ? "fewer" : "more";
|
|
580
|
+
},
|
|
581
|
+
inputType: "number",
|
|
582
|
+
testValue: "-5",
|
|
583
|
+
type: "formatter"
|
|
584
|
+
}), moreLess = declareFormatter({
|
|
585
|
+
name: "moreLess",
|
|
586
|
+
description: "Returns either 'more' or 'less' depending on the provided number's sign.",
|
|
587
|
+
logicFactory(libs2) {
|
|
588
|
+
return (n) => n < 0 ? "less" : "more";
|
|
589
|
+
},
|
|
590
|
+
inputType: "number",
|
|
591
|
+
testValue: "-5",
|
|
592
|
+
type: "formatter"
|
|
593
|
+
}), moreWord = declareFormatter({
|
|
594
|
+
name: "moreLess",
|
|
595
|
+
description: "Returns either 'more than', 'less than', or 'approximately the same' depending on the provided number's sign.",
|
|
596
|
+
logicFactory(libs2) {
|
|
597
|
+
return (n) => n < 0 ? "less than" : n > 0 ? "more than" : "approximately the same";
|
|
598
|
+
},
|
|
599
|
+
inputType: "number",
|
|
600
|
+
testValue: "-5",
|
|
601
|
+
type: "formatter"
|
|
602
|
+
}), olderWord = declareFormatter({
|
|
603
|
+
name: "olderWord",
|
|
604
|
+
description: "",
|
|
605
|
+
logicFactory(libs2) {
|
|
606
|
+
return (n) => n < 0 ? "getting younger" : n > 0 ? "getting older" : "staying the same age";
|
|
607
|
+
},
|
|
608
|
+
inputType: "number",
|
|
609
|
+
testValue: "-5",
|
|
610
|
+
type: "formatter"
|
|
611
|
+
}), olderYounger = declareFormatter({
|
|
612
|
+
name: "olderYounger",
|
|
613
|
+
description: "",
|
|
614
|
+
logicFactory(libs2) {
|
|
615
|
+
return (n) => n < 0 ? "younger than" : n > 0 ? "older than" : "the same age as";
|
|
616
|
+
},
|
|
617
|
+
inputType: "number",
|
|
618
|
+
testValue: "-5",
|
|
619
|
+
type: "formatter"
|
|
620
|
+
}), plural = declareFormatter({
|
|
621
|
+
name: "plural",
|
|
622
|
+
description: "Pluralizes a word.",
|
|
623
|
+
logicFactory(libs2) {
|
|
624
|
+
return (n) => n.replace(/\w$/g, (chr) => chr === "y" ? "ies" : `${chr}s`);
|
|
625
|
+
},
|
|
626
|
+
inputType: "string",
|
|
627
|
+
testValue: "Foo",
|
|
628
|
+
type: "formatter"
|
|
629
|
+
}), pxToInt = declareFormatter({
|
|
630
|
+
name: "pxToInt",
|
|
631
|
+
description: "Takes a pixel value and converts it to an integer",
|
|
632
|
+
logicFactory(libs2) {
|
|
633
|
+
return (n) => parseInt(n.replace(/\D+/g, ""), 10);
|
|
634
|
+
},
|
|
635
|
+
inputType: "string",
|
|
636
|
+
testValue: "12px",
|
|
637
|
+
type: "formatter"
|
|
638
|
+
}), salary = declareFormatter({
|
|
639
|
+
name: "salary",
|
|
640
|
+
description: "Displays salary values with proper precision (ie. '$74,200' instead of '$74.2k')",
|
|
641
|
+
logicFactory(libs2) {
|
|
642
|
+
return (n) => {
|
|
643
|
+
let str;
|
|
644
|
+
return n < 1e6 ? str = libs2.d3.format(",")(n.toFixed(0)) : str = libs2.d3plus.formatAbbreviate(n), `$${str}`;
|
|
645
|
+
};
|
|
646
|
+
},
|
|
647
|
+
inputType: "number",
|
|
648
|
+
testValue: "1000000",
|
|
649
|
+
type: "formatter"
|
|
650
|
+
}), stripEntities$1 = declareFormatter({
|
|
651
|
+
name: "stripEntities",
|
|
652
|
+
description: "Removes non breaking spaces & other html entities from a string",
|
|
653
|
+
logicFactory(libs2) {
|
|
654
|
+
return (n) => typeof n == "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
|
|
655
|
+
},
|
|
656
|
+
inputType: "string",
|
|
657
|
+
testValue: "<b>MyText</b>",
|
|
658
|
+
type: "formatter"
|
|
659
|
+
}), stripHTML$1 = declareFormatter({
|
|
660
|
+
name: "stripHTML",
|
|
661
|
+
description: "Converts html tags to spaces, then removes redundant spaces",
|
|
662
|
+
logicFactory(libs2) {
|
|
663
|
+
return (n) => {
|
|
664
|
+
const entities = {
|
|
665
|
+
"&": "&",
|
|
666
|
+
"<": "<",
|
|
667
|
+
">": ">",
|
|
668
|
+
""": '"',
|
|
669
|
+
"'": "'",
|
|
670
|
+
"`": "`",
|
|
671
|
+
" ": ""
|
|
672
|
+
}, source = `(?:${Object.keys(entities).join("|")})`, testRegexp = RegExp(source), replaceRegexp = RegExp(source, "g"), s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
673
|
+
return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
|
|
674
|
+
};
|
|
675
|
+
},
|
|
676
|
+
inputType: "string",
|
|
677
|
+
testValue: "<b>My text</b>",
|
|
678
|
+
type: "formatter"
|
|
679
|
+
}), stripOL = declareFormatter({
|
|
680
|
+
name: "stripOL",
|
|
681
|
+
description: "Removes ordered list wrapper tags from a string.",
|
|
682
|
+
logicFactory(libs2) {
|
|
683
|
+
return (n) => n.replace(/<ol>/g, "").replace(/<\/ol>/g, "");
|
|
684
|
+
},
|
|
685
|
+
inputType: "string",
|
|
686
|
+
testValue: "<ol><li>My list</li></ol>",
|
|
687
|
+
type: "formatter"
|
|
688
|
+
}), stripP = declareFormatter({
|
|
689
|
+
name: "stripP",
|
|
690
|
+
description: "Removes all paragraph tags from a string.",
|
|
691
|
+
logicFactory(libs2) {
|
|
692
|
+
return (n) => n.replace(/<p>/g, "").replace(/<\/p>/g, "");
|
|
693
|
+
},
|
|
694
|
+
inputType: "string",
|
|
695
|
+
testValue: "<p>My p</p>",
|
|
696
|
+
type: "formatter"
|
|
697
|
+
}), stripUL = declareFormatter({
|
|
698
|
+
name: "stripUL",
|
|
699
|
+
description: "Removes unordered list wrapper tags from a string.",
|
|
700
|
+
logicFactory(libs2) {
|
|
701
|
+
return (n) => n.replace(/<ul>/g, "").replace(/<\/ul>/g, "");
|
|
702
|
+
},
|
|
703
|
+
inputType: "string",
|
|
704
|
+
testValue: "<ul><li>My list</li></ul>",
|
|
705
|
+
type: "formatter"
|
|
706
|
+
}), toKebabCase = declareFormatter({
|
|
707
|
+
name: "toKebabCase",
|
|
708
|
+
description: "Takes a camelCase or PascalCase string and converts it to kebab-case.",
|
|
709
|
+
logicFactory(libs2) {
|
|
710
|
+
return (n) => typeof n == "string" ? (n = n.charAt(0).toLowerCase() + n.substring(1), n.replace(/([A-Z])/g, "-$1").toLowerCase()) : "invalid string passed to toKebabCase()";
|
|
711
|
+
},
|
|
712
|
+
inputType: "string",
|
|
713
|
+
testValue: "camelCaseText",
|
|
714
|
+
type: "formatter"
|
|
715
|
+
}), toSpacedCase = declareFormatter({
|
|
716
|
+
name: "toSpacedCase",
|
|
717
|
+
description: "Takes a camelCase or PascalCase string and adds spaces (I know Spaced Case isn't a thing, deal with it).",
|
|
718
|
+
logicFactory(libs2) {
|
|
719
|
+
return (n) => typeof n == "string" ? n.replace(/([A-Z])/g, " $1").toLowerCase().trim() : "invalid string passed to toSpacedCase()";
|
|
720
|
+
},
|
|
721
|
+
inputType: "string",
|
|
722
|
+
testValue: "camelCaseText",
|
|
723
|
+
type: "formatter"
|
|
724
|
+
}), upperCaseFirst = declareFormatter({
|
|
725
|
+
name: "upperCaseFirst",
|
|
726
|
+
description: "Converts the first letter of a string to uppercase",
|
|
727
|
+
logicFactory(libs2) {
|
|
728
|
+
return (n) => n.charAt(0).toUpperCase() + n.slice(1);
|
|
729
|
+
},
|
|
730
|
+
inputType: "string",
|
|
731
|
+
testValue: "my name",
|
|
732
|
+
type: "formatter"
|
|
733
|
+
}), formatters = /* @__PURE__ */ Object.freeze({
|
|
734
|
+
__proto__: null,
|
|
735
|
+
abbreviate,
|
|
736
|
+
abs,
|
|
737
|
+
bucket,
|
|
738
|
+
commas,
|
|
739
|
+
date,
|
|
740
|
+
dollar,
|
|
741
|
+
formatFieldName,
|
|
742
|
+
grewTo,
|
|
743
|
+
grewWord,
|
|
744
|
+
growing,
|
|
745
|
+
growth,
|
|
746
|
+
growthPct,
|
|
747
|
+
growthWord,
|
|
748
|
+
highWord,
|
|
749
|
+
increaseWord,
|
|
750
|
+
increasedWord,
|
|
751
|
+
increasing,
|
|
752
|
+
largerThan,
|
|
753
|
+
list,
|
|
754
|
+
longWord,
|
|
755
|
+
lowerCaseFirst,
|
|
756
|
+
moreFewerWord,
|
|
757
|
+
moreLess,
|
|
758
|
+
moreWord,
|
|
759
|
+
olderWord,
|
|
760
|
+
olderYounger,
|
|
761
|
+
plural,
|
|
762
|
+
pxToInt,
|
|
763
|
+
salary,
|
|
764
|
+
stripEntities: stripEntities$1,
|
|
765
|
+
stripHTML: stripHTML$1,
|
|
766
|
+
stripOL,
|
|
767
|
+
stripP,
|
|
768
|
+
stripUL,
|
|
769
|
+
toKebabCase,
|
|
770
|
+
toSpacedCase,
|
|
771
|
+
upperCaseFirst
|
|
772
|
+
});
|
|
773
|
+
const verbose$3 = getLogging();
|
|
774
|
+
verbose$3 && console.log(`Loaded formatters: ${Object.keys(formatters)}`);
|
|
775
|
+
class FormatterModel extends Model {
|
|
776
|
+
}
|
|
777
|
+
function initModel$8(sequelize) {
|
|
778
|
+
return FormatterModel.init({
|
|
779
|
+
id: {
|
|
780
|
+
type: DataTypes.INTEGER,
|
|
781
|
+
primaryKey: !0,
|
|
782
|
+
autoIncrement: !0
|
|
783
|
+
},
|
|
784
|
+
name: {
|
|
785
|
+
type: DataTypes.STRING,
|
|
786
|
+
defaultValue: ""
|
|
787
|
+
},
|
|
788
|
+
content: {
|
|
789
|
+
type: DataTypes.JSONB,
|
|
790
|
+
defaultValue: {
|
|
791
|
+
description: "",
|
|
792
|
+
testValue: "Foo",
|
|
793
|
+
type: FORMATTER_TYPES.FORMATTER,
|
|
794
|
+
inputType: FORMATTER_INPUT_TYPES.STRING,
|
|
795
|
+
logic: "return n;"
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}, {
|
|
799
|
+
sequelize,
|
|
800
|
+
modelName: "formatter",
|
|
801
|
+
tableName: "bespoke_reports_formatter",
|
|
802
|
+
freezeTableName: !0,
|
|
803
|
+
timestamps: !1,
|
|
804
|
+
hooks: {
|
|
805
|
+
async afterSync(options) {
|
|
806
|
+
const existingFormatters = await FormatterModel.findAll();
|
|
807
|
+
if (options.force || existingFormatters.length === 0) {
|
|
808
|
+
const defaultFormatters = Object.entries(declaredFormatters).map(([name, content]) => ({ name, content }));
|
|
809
|
+
await FormatterModel.bulkCreate(defaultFormatters);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}), () => FormatterModel;
|
|
814
|
+
}
|
|
815
|
+
class ImageModel extends Model {
|
|
816
|
+
getContent(locale) {
|
|
817
|
+
const { contentByLocale } = this;
|
|
818
|
+
if (!contentByLocale)
|
|
819
|
+
throw new Error("This ImageModel entity didn't include its ImageContentModel association.");
|
|
820
|
+
const content = contentByLocale.find((item) => item.locale === locale);
|
|
821
|
+
if (!content)
|
|
822
|
+
throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
|
|
823
|
+
return content;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
function initModel$7(sequelize) {
|
|
827
|
+
return ImageModel.init({
|
|
828
|
+
id: {
|
|
829
|
+
autoIncrement: !0,
|
|
830
|
+
primaryKey: !0,
|
|
831
|
+
type: DataTypes.INTEGER
|
|
832
|
+
},
|
|
833
|
+
url: {
|
|
834
|
+
type: DataTypes.TEXT,
|
|
835
|
+
unique: !0
|
|
836
|
+
},
|
|
837
|
+
author: DataTypes.TEXT,
|
|
838
|
+
license: DataTypes.TEXT,
|
|
839
|
+
splash: DataTypes.BLOB,
|
|
840
|
+
thumb: DataTypes.BLOB
|
|
841
|
+
}, {
|
|
842
|
+
sequelize,
|
|
843
|
+
modelName: "image",
|
|
844
|
+
tableName: "bespoke_reports_image",
|
|
845
|
+
freezeTableName: !0
|
|
846
|
+
}), (models) => (ImageModel.hasMany(models.image_content, {
|
|
847
|
+
foreignKey: "id",
|
|
848
|
+
sourceKey: "id",
|
|
849
|
+
as: "contentByLocale"
|
|
850
|
+
}), ImageModel);
|
|
851
|
+
}
|
|
852
|
+
class ImageContentModel extends Model {
|
|
853
|
+
}
|
|
854
|
+
function initModel$6(sequelize) {
|
|
855
|
+
return ImageContentModel.init({
|
|
856
|
+
id: {
|
|
857
|
+
type: DataTypes.INTEGER,
|
|
858
|
+
primaryKey: !0,
|
|
859
|
+
onDelete: "cascade",
|
|
860
|
+
references: {
|
|
861
|
+
model: "bespoke_reports_image",
|
|
862
|
+
key: "id"
|
|
863
|
+
}
|
|
864
|
+
},
|
|
865
|
+
locale: {
|
|
866
|
+
type: DataTypes.STRING,
|
|
867
|
+
primaryKey: !0
|
|
868
|
+
},
|
|
869
|
+
meta: DataTypes.TEXT
|
|
870
|
+
}, {
|
|
871
|
+
sequelize,
|
|
872
|
+
modelName: "image_content",
|
|
873
|
+
tableName: "bespoke_reports_image_content",
|
|
874
|
+
freezeTableName: !0,
|
|
875
|
+
timestamps: !1
|
|
876
|
+
}), () => ImageContentModel;
|
|
877
|
+
}
|
|
878
|
+
var __defProp$h = Object.defineProperty, __defProps$b = Object.defineProperties, __getOwnPropDescs$b = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$n = Object.getOwnPropertySymbols, __hasOwnProp$n = Object.prototype.hasOwnProperty, __propIsEnum$n = Object.prototype.propertyIsEnumerable, __defNormalProp$h = (obj, key, value) => key in obj ? __defProp$h(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$h = (a, b) => {
|
|
879
|
+
for (var prop in b || (b = {}))
|
|
880
|
+
__hasOwnProp$n.call(b, prop) && __defNormalProp$h(a, prop, b[prop]);
|
|
881
|
+
if (__getOwnPropSymbols$n)
|
|
882
|
+
for (var prop of __getOwnPropSymbols$n(b))
|
|
883
|
+
__propIsEnum$n.call(b, prop) && __defNormalProp$h(a, prop, b[prop]);
|
|
884
|
+
return a;
|
|
885
|
+
}, __spreadProps$b = (a, b) => __defProps$b(a, __getOwnPropDescs$b(b));
|
|
886
|
+
class ReportModel extends Model {
|
|
887
|
+
toJSON() {
|
|
888
|
+
const attributes = this.get({ plain: !0 }), { dimensions = [], sections = [] } = this;
|
|
889
|
+
return __spreadProps$b(__spreadValues$h({}, attributes), {
|
|
890
|
+
settings: attributes.settings,
|
|
891
|
+
date: new Date(this.date || Date.now()).toISOString(),
|
|
892
|
+
dimensions: dimensions.map((item) => item.toJSON()),
|
|
893
|
+
sections: sections.map((item) => item.toJSON())
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function initModel$5(sequelize) {
|
|
898
|
+
return ReportModel.init({
|
|
899
|
+
id: {
|
|
900
|
+
type: DataTypes.INTEGER,
|
|
901
|
+
primaryKey: !0,
|
|
902
|
+
autoIncrement: !0
|
|
903
|
+
},
|
|
904
|
+
name: {
|
|
905
|
+
type: DataTypes.STRING,
|
|
906
|
+
allowNull: !1,
|
|
907
|
+
defaultValue: ""
|
|
908
|
+
},
|
|
909
|
+
visible: {
|
|
910
|
+
type: DataTypes.BOOLEAN,
|
|
911
|
+
defaultValue: !0
|
|
912
|
+
},
|
|
913
|
+
date: {
|
|
914
|
+
type: DataTypes.DATE,
|
|
915
|
+
defaultValue: DataTypes.NOW
|
|
916
|
+
},
|
|
917
|
+
type: {
|
|
918
|
+
type: DataTypes.STRING,
|
|
919
|
+
defaultValue: "report",
|
|
920
|
+
validate: {
|
|
921
|
+
isIn: [["report", "story"]]
|
|
922
|
+
}
|
|
923
|
+
},
|
|
924
|
+
settings: {
|
|
925
|
+
type: DataTypes.JSON,
|
|
926
|
+
defaultValue: {}
|
|
927
|
+
}
|
|
928
|
+
}, {
|
|
929
|
+
sequelize,
|
|
930
|
+
modelName: "report",
|
|
931
|
+
tableName: "bespoke_reports_report",
|
|
932
|
+
freezeTableName: !0,
|
|
933
|
+
timestamps: !1
|
|
934
|
+
}), (models) => (ReportModel.hasMany(models.dimension, {
|
|
935
|
+
foreignKey: "report_id",
|
|
936
|
+
sourceKey: "id",
|
|
937
|
+
as: "dimensions"
|
|
938
|
+
}), ReportModel.hasMany(models.section, {
|
|
939
|
+
foreignKey: "report_id",
|
|
940
|
+
sourceKey: "id",
|
|
941
|
+
as: "sections"
|
|
942
|
+
}), ReportModel);
|
|
943
|
+
}
|
|
944
|
+
var __defProp$g = Object.defineProperty, __defProps$a = Object.defineProperties, __getOwnPropDescs$a = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$m = Object.getOwnPropertySymbols, __hasOwnProp$m = Object.prototype.hasOwnProperty, __propIsEnum$m = Object.prototype.propertyIsEnumerable, __defNormalProp$g = (obj, key, value) => key in obj ? __defProp$g(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$g = (a, b) => {
|
|
945
|
+
for (var prop in b || (b = {}))
|
|
946
|
+
__hasOwnProp$m.call(b, prop) && __defNormalProp$g(a, prop, b[prop]);
|
|
947
|
+
if (__getOwnPropSymbols$m)
|
|
948
|
+
for (var prop of __getOwnPropSymbols$m(b))
|
|
949
|
+
__propIsEnum$m.call(b, prop) && __defNormalProp$g(a, prop, b[prop]);
|
|
950
|
+
return a;
|
|
951
|
+
}, __spreadProps$a = (a, b) => __defProps$a(a, __getOwnPropDescs$a(b));
|
|
952
|
+
class DimensionModel extends Model {
|
|
953
|
+
toJSON() {
|
|
954
|
+
const attributes = this.get({ plain: !0 }), { variants = [] } = this;
|
|
955
|
+
return __spreadProps$a(__spreadValues$g({}, attributes), {
|
|
956
|
+
variants: variants.map((item) => item.toJSON())
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function initModel$4(sequelize) {
|
|
961
|
+
return DimensionModel.init({
|
|
962
|
+
id: {
|
|
963
|
+
type: DataTypes.INTEGER,
|
|
964
|
+
primaryKey: !0,
|
|
965
|
+
autoIncrement: !0
|
|
966
|
+
},
|
|
967
|
+
report_id: {
|
|
968
|
+
type: DataTypes.INTEGER,
|
|
969
|
+
onDelete: "cascade",
|
|
970
|
+
references: {
|
|
971
|
+
model: "bespoke_reports_report",
|
|
972
|
+
key: "id"
|
|
973
|
+
}
|
|
974
|
+
},
|
|
975
|
+
name: {
|
|
976
|
+
type: DataTypes.STRING,
|
|
977
|
+
defaultValue: ""
|
|
978
|
+
},
|
|
979
|
+
settings: {
|
|
980
|
+
type: DataTypes.JSONB,
|
|
981
|
+
defaultValue: {}
|
|
982
|
+
},
|
|
983
|
+
ordering: {
|
|
984
|
+
type: DataTypes.INTEGER,
|
|
985
|
+
defaultValue: 0
|
|
986
|
+
},
|
|
987
|
+
visible: {
|
|
988
|
+
type: DataTypes.BOOLEAN,
|
|
989
|
+
defaultValue: !0
|
|
990
|
+
}
|
|
991
|
+
}, {
|
|
992
|
+
sequelize,
|
|
993
|
+
modelName: "dimension",
|
|
994
|
+
tableName: "bespoke_reports_report_dimension",
|
|
995
|
+
freezeTableName: !0,
|
|
996
|
+
timestamps: !1
|
|
997
|
+
}), (models) => (DimensionModel.hasMany(models.variant, {
|
|
998
|
+
foreignKey: "dimension_id",
|
|
999
|
+
sourceKey: "id",
|
|
1000
|
+
as: "variants",
|
|
1001
|
+
constraints: !1
|
|
1002
|
+
}), DimensionModel.belongsTo(models.report, {
|
|
1003
|
+
foreignKey: "report_id",
|
|
1004
|
+
targetKey: "id",
|
|
1005
|
+
as: "report",
|
|
1006
|
+
constraints: !1
|
|
1007
|
+
}), DimensionModel);
|
|
1008
|
+
}
|
|
1009
|
+
class VariantModel extends Model {
|
|
1010
|
+
get report() {
|
|
1011
|
+
var _a;
|
|
1012
|
+
return (_a = this.dimension) == null ? void 0 : _a.report;
|
|
1013
|
+
}
|
|
1014
|
+
toJSON() {
|
|
1015
|
+
return this.get({ plain: !0 });
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function initModel$3(sequelize) {
|
|
1019
|
+
return VariantModel.init({
|
|
1020
|
+
id: {
|
|
1021
|
+
type: DataTypes.INTEGER,
|
|
1022
|
+
primaryKey: !0,
|
|
1023
|
+
autoIncrement: !0
|
|
1024
|
+
},
|
|
1025
|
+
dimension_id: {
|
|
1026
|
+
type: DataTypes.INTEGER,
|
|
1027
|
+
onDelete: "cascade",
|
|
1028
|
+
references: {
|
|
1029
|
+
model: "bespoke_reports_report_dimension",
|
|
1030
|
+
key: "id"
|
|
1031
|
+
}
|
|
1032
|
+
},
|
|
1033
|
+
slug: {
|
|
1034
|
+
type: DataTypes.STRING,
|
|
1035
|
+
defaultValue: ""
|
|
1036
|
+
},
|
|
1037
|
+
name: {
|
|
1038
|
+
type: DataTypes.STRING,
|
|
1039
|
+
defaultValue: ""
|
|
1040
|
+
},
|
|
1041
|
+
settings: {
|
|
1042
|
+
type: DataTypes.JSONB,
|
|
1043
|
+
defaultValue: {}
|
|
1044
|
+
},
|
|
1045
|
+
config: {
|
|
1046
|
+
type: DataTypes.JSONB,
|
|
1047
|
+
defaultValue: {}
|
|
1048
|
+
},
|
|
1049
|
+
visible: {
|
|
1050
|
+
type: DataTypes.BOOLEAN,
|
|
1051
|
+
defaultValue: !0
|
|
1052
|
+
}
|
|
1053
|
+
}, {
|
|
1054
|
+
sequelize,
|
|
1055
|
+
modelName: "variant",
|
|
1056
|
+
tableName: "bespoke_reports_report_dimension_variant",
|
|
1057
|
+
freezeTableName: !0,
|
|
1058
|
+
timestamps: !1
|
|
1059
|
+
}), (models) => (VariantModel.hasMany(models.search, {
|
|
1060
|
+
foreignKey: "variant_id",
|
|
1061
|
+
sourceKey: "id",
|
|
1062
|
+
as: "members",
|
|
1063
|
+
constraints: !1
|
|
1064
|
+
}), VariantModel.belongsTo(models.dimension, {
|
|
1065
|
+
foreignKey: "dimension_id",
|
|
1066
|
+
targetKey: "id",
|
|
1067
|
+
as: "dimension",
|
|
1068
|
+
constraints: !1
|
|
1069
|
+
}), VariantModel);
|
|
1070
|
+
}
|
|
1071
|
+
class SearchModel extends Model {
|
|
1072
|
+
getContent(locale) {
|
|
1073
|
+
const { contentByLocale } = this;
|
|
1074
|
+
if (!contentByLocale)
|
|
1075
|
+
throw new Error("This SearchModel entity didn't include its SearchContentModel association.");
|
|
1076
|
+
const content = contentByLocale.find((item) => item.locale === locale);
|
|
1077
|
+
if (!content)
|
|
1078
|
+
throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
|
|
1079
|
+
return content;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
function initModel$2(sequelize) {
|
|
1083
|
+
return SearchModel.init({
|
|
1084
|
+
id: {
|
|
1085
|
+
primaryKey: !0,
|
|
1086
|
+
type: DataTypes.TEXT
|
|
1087
|
+
},
|
|
1088
|
+
zvalue: DataTypes.DOUBLE,
|
|
1089
|
+
slug: DataTypes.TEXT,
|
|
1090
|
+
image_id: {
|
|
1091
|
+
type: DataTypes.INTEGER,
|
|
1092
|
+
references: {
|
|
1093
|
+
model: "bespoke_reports_image",
|
|
1094
|
+
key: "id"
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
content_id: {
|
|
1098
|
+
autoIncrement: !0,
|
|
1099
|
+
type: DataTypes.INTEGER,
|
|
1100
|
+
unique: !0
|
|
1101
|
+
},
|
|
1102
|
+
variant_id: {
|
|
1103
|
+
primaryKey: !0,
|
|
1104
|
+
type: DataTypes.INTEGER,
|
|
1105
|
+
onDelete: "cascade",
|
|
1106
|
+
references: {
|
|
1107
|
+
model: "bespoke_reports_report_dimension_variant",
|
|
1108
|
+
key: "id"
|
|
1109
|
+
}
|
|
1110
|
+
},
|
|
1111
|
+
dimension_id: {
|
|
1112
|
+
primaryKey: !0,
|
|
1113
|
+
type: DataTypes.INTEGER,
|
|
1114
|
+
onDelete: "cascade",
|
|
1115
|
+
references: {
|
|
1116
|
+
model: "bespoke_reports_report_dimension",
|
|
1117
|
+
key: "id"
|
|
1118
|
+
}
|
|
1119
|
+
},
|
|
1120
|
+
report_id: {
|
|
1121
|
+
primaryKey: !0,
|
|
1122
|
+
type: DataTypes.INTEGER,
|
|
1123
|
+
onDelete: "cascade",
|
|
1124
|
+
references: {
|
|
1125
|
+
model: "bespoke_reports_report",
|
|
1126
|
+
key: "id"
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
visible: {
|
|
1130
|
+
type: DataTypes.BOOLEAN,
|
|
1131
|
+
defaultValue: !0
|
|
1132
|
+
}
|
|
1133
|
+
}, {
|
|
1134
|
+
sequelize,
|
|
1135
|
+
modelName: "search",
|
|
1136
|
+
tableName: "bespoke_reports_search",
|
|
1137
|
+
freezeTableName: !0,
|
|
1138
|
+
timestamps: !1
|
|
1139
|
+
}), (models) => (SearchModel.belongsTo(models.variant, {
|
|
1140
|
+
foreignKey: "variant_id",
|
|
1141
|
+
targetKey: "id",
|
|
1142
|
+
as: "variant",
|
|
1143
|
+
constraints: !1
|
|
1144
|
+
}), SearchModel.belongsTo(models.dimension, {
|
|
1145
|
+
foreignKey: "dimension_id",
|
|
1146
|
+
targetKey: "id",
|
|
1147
|
+
as: "dimension",
|
|
1148
|
+
constraints: !1
|
|
1149
|
+
}), SearchModel.belongsTo(models.report, {
|
|
1150
|
+
foreignKey: "report_id",
|
|
1151
|
+
targetKey: "id",
|
|
1152
|
+
as: "report",
|
|
1153
|
+
constraints: !1
|
|
1154
|
+
}), SearchModel.belongsTo(models.image, {
|
|
1155
|
+
foreignKey: "image_id",
|
|
1156
|
+
targetKey: "id",
|
|
1157
|
+
as: "image",
|
|
1158
|
+
constraints: !1
|
|
1159
|
+
}), SearchModel.hasMany(models.search_content, {
|
|
1160
|
+
foreignKey: "id",
|
|
1161
|
+
sourceKey: "content_id",
|
|
1162
|
+
as: "contentByLocale"
|
|
1163
|
+
}), SearchModel);
|
|
1164
|
+
}
|
|
1165
|
+
class SearchContentModel extends Model {
|
|
1166
|
+
}
|
|
1167
|
+
function initModel$1(sequelize) {
|
|
1168
|
+
return SearchContentModel.init({
|
|
1169
|
+
id: {
|
|
1170
|
+
type: DataTypes.INTEGER,
|
|
1171
|
+
primaryKey: !0,
|
|
1172
|
+
onDelete: "cascade",
|
|
1173
|
+
references: {
|
|
1174
|
+
model: "bespoke_reports_search",
|
|
1175
|
+
key: "content_id"
|
|
1176
|
+
}
|
|
1177
|
+
},
|
|
1178
|
+
locale: {
|
|
1179
|
+
type: DataTypes.STRING,
|
|
1180
|
+
primaryKey: !0
|
|
1181
|
+
},
|
|
1182
|
+
name: DataTypes.TEXT,
|
|
1183
|
+
annotations: {
|
|
1184
|
+
type: DataTypes.JSONB,
|
|
1185
|
+
defaultValue: {}
|
|
1186
|
+
},
|
|
1187
|
+
attributes: {
|
|
1188
|
+
type: DataTypes.JSONB,
|
|
1189
|
+
defaultValue: {}
|
|
1190
|
+
},
|
|
1191
|
+
keywords: DataTypes.ARRAY(DataTypes.TEXT)
|
|
1192
|
+
}, {
|
|
1193
|
+
sequelize,
|
|
1194
|
+
modelName: "search_content",
|
|
1195
|
+
tableName: "bespoke_reports_search_content",
|
|
1196
|
+
freezeTableName: !0,
|
|
1197
|
+
timestamps: !1
|
|
1198
|
+
}), () => SearchContentModel;
|
|
1199
|
+
}
|
|
1200
|
+
var __defProp$f = Object.defineProperty, __defProps$9 = Object.defineProperties, __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$l = Object.getOwnPropertySymbols, __hasOwnProp$l = Object.prototype.hasOwnProperty, __propIsEnum$l = Object.prototype.propertyIsEnumerable, __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$f = (a, b) => {
|
|
1201
|
+
for (var prop in b || (b = {}))
|
|
1202
|
+
__hasOwnProp$l.call(b, prop) && __defNormalProp$f(a, prop, b[prop]);
|
|
1203
|
+
if (__getOwnPropSymbols$l)
|
|
1204
|
+
for (var prop of __getOwnPropSymbols$l(b))
|
|
1205
|
+
__propIsEnum$l.call(b, prop) && __defNormalProp$f(a, prop, b[prop]);
|
|
1206
|
+
return a;
|
|
1207
|
+
}, __spreadProps$9 = (a, b) => __defProps$9(a, __getOwnPropDescs$9(b));
|
|
1208
|
+
class SectionModel extends Model {
|
|
1209
|
+
toJSON() {
|
|
1210
|
+
const attributes = this.get({ plain: !0 }), { blocks = [] } = this;
|
|
1211
|
+
return __spreadProps$9(__spreadValues$f({}, attributes), {
|
|
1212
|
+
blocks: blocks.map((item) => item.toJSON())
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function initModel(sequelize) {
|
|
1217
|
+
return SectionModel.init({
|
|
1218
|
+
id: {
|
|
1219
|
+
type: DataTypes.INTEGER,
|
|
1220
|
+
primaryKey: !0,
|
|
1221
|
+
autoIncrement: !0
|
|
1222
|
+
},
|
|
1223
|
+
settings: {
|
|
1224
|
+
type: DataTypes.JSON,
|
|
1225
|
+
defaultValue: {}
|
|
1226
|
+
},
|
|
1227
|
+
heading: {
|
|
1228
|
+
type: DataTypes.INTEGER,
|
|
1229
|
+
defaultValue: 1
|
|
1230
|
+
},
|
|
1231
|
+
ordering: DataTypes.STRING,
|
|
1232
|
+
report_id: {
|
|
1233
|
+
type: DataTypes.INTEGER,
|
|
1234
|
+
onDelete: "cascade",
|
|
1235
|
+
references: {
|
|
1236
|
+
model: "bespoke_reports_report",
|
|
1237
|
+
key: "id"
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}, {
|
|
1241
|
+
sequelize,
|
|
1242
|
+
modelName: "section",
|
|
1243
|
+
tableName: "bespoke_reports_section",
|
|
1244
|
+
freezeTableName: !0,
|
|
1245
|
+
timestamps: !1
|
|
1246
|
+
}), (models) => (SectionModel.hasMany(models.block, {
|
|
1247
|
+
foreignKey: "section_id",
|
|
1248
|
+
sourceKey: "id",
|
|
1249
|
+
as: "blocks"
|
|
1250
|
+
}), SectionModel);
|
|
1251
|
+
}
|
|
1252
|
+
const modelFactoryMap = {
|
|
1253
|
+
block: initModel$b,
|
|
1254
|
+
block_content: initModel$a,
|
|
1255
|
+
block_input: initModel$9,
|
|
1256
|
+
formatter: initModel$8,
|
|
1257
|
+
image: initModel$7,
|
|
1258
|
+
image_content: initModel$6,
|
|
1259
|
+
report: initModel$5,
|
|
1260
|
+
dimension: initModel$4,
|
|
1261
|
+
variant: initModel$3,
|
|
1262
|
+
search: initModel$2,
|
|
1263
|
+
search_content: initModel$1,
|
|
1264
|
+
section: initModel
|
|
1265
|
+
}, verbose$2 = getLogging(), connectionString = process.env.REPORTS_DB_CONNECTION || "", shouldWipe = yn(process.env.REPORTS_DB_WIPE);
|
|
1266
|
+
if (!connectionString)
|
|
1267
|
+
throw new Error(`
|
|
1268
|
+
Env var 'REPORTS_DB_CONNECTION' is not present.
|
|
1269
|
+
This is required to connect to a database to save the Reports CMS changes.
|
|
1270
|
+
`);
|
|
1271
|
+
function memoizeResult(factory) {
|
|
1272
|
+
let result;
|
|
1273
|
+
return (...args) => (result = result || factory(...args), result);
|
|
1274
|
+
}
|
|
1275
|
+
const getDB = memoizeResult(() => {
|
|
1276
|
+
let sequelize;
|
|
1277
|
+
try {
|
|
1278
|
+
verbose$2 && console.log("INITIALIZING DB CONNECTION"), sequelize = new Sequelize(connectionString, {
|
|
1279
|
+
logging: !1,
|
|
1280
|
+
dialectModule: pg
|
|
1281
|
+
});
|
|
1282
|
+
} catch (e) {
|
|
1283
|
+
throw new Error(`
|
|
1284
|
+
Could not connect to the database using the given connection string.
|
|
1285
|
+
Please check that the connection string 'REPORTS_DB_CONNECTION' is correct.
|
|
1286
|
+
Details:
|
|
1287
|
+
${e.message}
|
|
1288
|
+
`);
|
|
1289
|
+
}
|
|
1290
|
+
return Object.values(modelFactoryMap).map((modelFactory) => modelFactory(sequelize)).map((modelAssociator) => modelAssociator(sequelize.models)), sequelize.sync({ force: shouldWipe }).catch((err) => {
|
|
1291
|
+
throw err instanceof Error$1 && (console.error(
|
|
1292
|
+
"=".repeat(40),
|
|
1293
|
+
`
|
|
1294
|
+
Error initializing sequelize connection:
|
|
1295
|
+
`,
|
|
1296
|
+
err.stack || err.message
|
|
1297
|
+
), process.exit(1)), err;
|
|
1298
|
+
}).then(() => sequelize.models);
|
|
1299
|
+
});
|
|
1300
|
+
class BackendError extends Error {
|
|
1301
|
+
constructor(code, message) {
|
|
1302
|
+
super(message), this.code = code;
|
|
1303
|
+
}
|
|
1304
|
+
toJSON() {
|
|
1305
|
+
return failureResult(this);
|
|
1306
|
+
}
|
|
1307
|
+
static is(obj) {
|
|
1308
|
+
return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code == "number";
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
function successResult(result) {
|
|
1312
|
+
return { ok: !0, status: 200, data: result };
|
|
1313
|
+
}
|
|
1314
|
+
function failureResult(err) {
|
|
1315
|
+
return { ok: !1, status: BackendError.is(err) ? err.code : 500, error: err.message };
|
|
1316
|
+
}
|
|
1317
|
+
function resultWrapper(method) {
|
|
1318
|
+
return (param) => method(param).then(successResult, failureResult);
|
|
1319
|
+
}
|
|
1320
|
+
function pickMethod(api, operation, entity) {
|
|
1321
|
+
const name = `${operation}${capitalize(entity)}`;
|
|
1322
|
+
return api[name];
|
|
1323
|
+
}
|
|
1324
|
+
function capitalize(str) {
|
|
1325
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
1326
|
+
}
|
|
1327
|
+
var getLocales = () => {
|
|
1328
|
+
var _a;
|
|
1329
|
+
const localeDefault2 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en", locales2 = ((_a = process.env.NEXT_PUBLIC_REPORTS_LOCALES) == null ? void 0 : _a.split(",")) || [localeDefault2];
|
|
1330
|
+
return locales2.includes(localeDefault2) || locales2.push(localeDefault2), { localeDefault: localeDefault2, locales: locales2 };
|
|
1331
|
+
};
|
|
1332
|
+
const keyDiver = (obj, str) => str && typeof str == "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
|
|
1333
|
+
function stripHTML(n) {
|
|
1334
|
+
const entities = {
|
|
1335
|
+
"&": "&",
|
|
1336
|
+
"<": "<",
|
|
1337
|
+
">": ">",
|
|
1338
|
+
""": '"',
|
|
1339
|
+
"'": "'",
|
|
1340
|
+
"`": "`",
|
|
1341
|
+
" ": ""
|
|
1342
|
+
}, source = `(?:${Object.keys(entities).join("|")})`, testRegexp = RegExp(source), replaceRegexp = RegExp(source, "g"), s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
1343
|
+
return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
|
|
1344
|
+
}
|
|
1345
|
+
function stripEntities(n) {
|
|
1346
|
+
return typeof n == "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
|
|
1347
|
+
}
|
|
1348
|
+
function slugify(str) {
|
|
1349
|
+
return str ? slugifyFn(
|
|
1350
|
+
stripEntities(stripHTML(str)),
|
|
1351
|
+
{
|
|
1352
|
+
replacement: "-",
|
|
1353
|
+
remove: /[*+~.()'"!:@]/g,
|
|
1354
|
+
lower: !0,
|
|
1355
|
+
strict: !0,
|
|
1356
|
+
trim: !0
|
|
1357
|
+
}
|
|
1358
|
+
) : "";
|
|
1359
|
+
}
|
|
1360
|
+
const { localeDefault: localeDefault$3 } = getLocales();
|
|
1361
|
+
function ingestMembersFactory(db) {
|
|
1362
|
+
const { search: Search, search_content: SearchContent } = db;
|
|
1363
|
+
return ingestMembers;
|
|
1364
|
+
async function ingestMembers(variant) {
|
|
1365
|
+
const { id, config = {} } = variant, defaultLocale = config[localeDefault$3] ? localeDefault$3 : Object.keys(config)[0], {
|
|
1366
|
+
accessor,
|
|
1367
|
+
path,
|
|
1368
|
+
idKey,
|
|
1369
|
+
labelKey
|
|
1370
|
+
} = config[localeDefault$3];
|
|
1371
|
+
if (!path || !idKey || !labelKey)
|
|
1372
|
+
return;
|
|
1373
|
+
const memberFetch = await axios.get(path).catch((e) => ({ data: [], error: e })), members = keyDiver(memberFetch.data, accessor);
|
|
1374
|
+
try {
|
|
1375
|
+
await ingestDefaultMembers(variant, defaultLocale, members);
|
|
1376
|
+
} catch (error) {
|
|
1377
|
+
const errorMsg = `[ERROR] Ingesting default member items for ${defaultLocale}`;
|
|
1378
|
+
throw console.error(errorMsg, error), new BackendError(500, errorMsg);
|
|
1379
|
+
}
|
|
1380
|
+
const ingestions = Object.entries(config).map(async ([locale, config2]) => {
|
|
1381
|
+
const {
|
|
1382
|
+
path: path2,
|
|
1383
|
+
accessor: accessor2,
|
|
1384
|
+
idKey: idKey2,
|
|
1385
|
+
labelKey: labelKey2,
|
|
1386
|
+
attributes = []
|
|
1387
|
+
} = config2;
|
|
1388
|
+
if (!path2 || !idKey2 || !labelKey2)
|
|
1389
|
+
return;
|
|
1390
|
+
const memberFetch2 = await axios.get(path2).catch((e) => ({ data: [], error: e })), members2 = keyDiver(memberFetch2.data, accessor2), contentHash = await Search.findAll({ where: { variant_id: id } }).then((arr) => Object.fromEntries(
|
|
1391
|
+
arr.map((content) => [content.id, content.content_id])
|
|
1392
|
+
)), contentMembers = members2.map((d) => ({
|
|
1393
|
+
id: contentHash[d[idKey2]],
|
|
1394
|
+
locale,
|
|
1395
|
+
name: d[labelKey2],
|
|
1396
|
+
attributes: Object.fromEntries(
|
|
1397
|
+
attributes.map((attr) => [
|
|
1398
|
+
attr.name,
|
|
1399
|
+
attr.type === "constant" ? attr.value : d[attr.value] || ""
|
|
1400
|
+
])
|
|
1401
|
+
)
|
|
1402
|
+
}));
|
|
1403
|
+
try {
|
|
1404
|
+
await SearchContent.bulkCreate(contentMembers);
|
|
1405
|
+
} catch (error) {
|
|
1406
|
+
const errorMsg = `[ERROR] Ingesting search content items for ${locale}`;
|
|
1407
|
+
throw console.error(errorMsg, error), new BackendError(500, errorMsg);
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
await Promise.all(ingestions);
|
|
1411
|
+
}
|
|
1412
|
+
async function ingestDefaultMembers(variant, locale, members) {
|
|
1413
|
+
const { id, dimension_id, slug } = variant, { report_id } = variant.dimension, { idKey, labelKey } = variant.config[locale], allSlugsFromOtherMembers = await Search.findAll({
|
|
1414
|
+
attributes: ["slug", [fn("COUNT", col("variant.id")), "slugCount"]],
|
|
1415
|
+
include: {
|
|
1416
|
+
association: "variant",
|
|
1417
|
+
attributes: [],
|
|
1418
|
+
required: !1,
|
|
1419
|
+
right: !0,
|
|
1420
|
+
where: { dimension_id, slug }
|
|
1421
|
+
},
|
|
1422
|
+
group: "search.slug"
|
|
1423
|
+
}).then((arr) => Object.fromEntries(arr.map((item) => {
|
|
1424
|
+
const count = item.getDataValue("slugCount");
|
|
1425
|
+
return [item.slug, Number.parseInt(`${count}`, 10)];
|
|
1426
|
+
}))), searchMembers = members.map((member) => {
|
|
1427
|
+
const slug2 = slugify(member[labelKey]), memberId = member[idKey];
|
|
1428
|
+
return {
|
|
1429
|
+
id: memberId,
|
|
1430
|
+
slug: allSlugsFromOtherMembers[slug2] > 1 ? `${slug2}-${memberId}` : slug2,
|
|
1431
|
+
variant_id: id,
|
|
1432
|
+
dimension_id,
|
|
1433
|
+
report_id,
|
|
1434
|
+
zvalue: Math.random()
|
|
1435
|
+
};
|
|
1436
|
+
});
|
|
1437
|
+
try {
|
|
1438
|
+
await Search.destroy({ where: { variant_id: id } }), await Search.bulkCreate(searchMembers);
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
throw console.error(`[ERROR] Ingesting search members for ${locale}`, error), new Error(error);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
var __defProp$e = Object.defineProperty, __defProps$8 = Object.defineProperties, __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$k = Object.getOwnPropertySymbols, __hasOwnProp$k = Object.prototype.hasOwnProperty, __propIsEnum$k = Object.prototype.propertyIsEnumerable, __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$e = (a, b) => {
|
|
1445
|
+
for (var prop in b || (b = {}))
|
|
1446
|
+
__hasOwnProp$k.call(b, prop) && __defNormalProp$e(a, prop, b[prop]);
|
|
1447
|
+
if (__getOwnPropSymbols$k)
|
|
1448
|
+
for (var prop of __getOwnPropSymbols$k(b))
|
|
1449
|
+
__propIsEnum$k.call(b, prop) && __defNormalProp$e(a, prop, b[prop]);
|
|
1450
|
+
return a;
|
|
1451
|
+
}, __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
|
|
1452
|
+
function readMemberFactory(db) {
|
|
1453
|
+
const { search: Search } = db;
|
|
1454
|
+
return readMember;
|
|
1455
|
+
async function readMember(params) {
|
|
1456
|
+
const {
|
|
1457
|
+
mode,
|
|
1458
|
+
ids,
|
|
1459
|
+
slugs,
|
|
1460
|
+
all,
|
|
1461
|
+
locale
|
|
1462
|
+
} = params, whereClause = {
|
|
1463
|
+
content_id: []
|
|
1464
|
+
};
|
|
1465
|
+
if (mode === "ids")
|
|
1466
|
+
whereClause.content_id = ids;
|
|
1467
|
+
else if (mode === "slugs") {
|
|
1468
|
+
const entities = await Search.findAll({
|
|
1469
|
+
attributes: ["content_id"],
|
|
1470
|
+
where: {
|
|
1471
|
+
slug: slugs.map((item) => item.memberSlug)
|
|
1472
|
+
},
|
|
1473
|
+
include: {
|
|
1474
|
+
association: "variant",
|
|
1475
|
+
attributes: ["id", "name", "slug"],
|
|
1476
|
+
required: !1,
|
|
1477
|
+
where: {
|
|
1478
|
+
slug: slugs.map((item) => item.variantSlug)
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
whereClause.content_id = entities.map((item) => item.content_id);
|
|
1483
|
+
}
|
|
1484
|
+
const contentWhereClause = {
|
|
1485
|
+
locale: all ? { [Op.ne]: null } : locale
|
|
1486
|
+
}, memberSearchResults = await Search.findAll({
|
|
1487
|
+
where: whereClause,
|
|
1488
|
+
include: [{
|
|
1489
|
+
association: "report",
|
|
1490
|
+
attributes: ["id", "name"]
|
|
1491
|
+
}, {
|
|
1492
|
+
association: "dimension",
|
|
1493
|
+
attributes: ["id", "name", "ordering"]
|
|
1494
|
+
}, {
|
|
1495
|
+
association: "variant",
|
|
1496
|
+
attributes: ["id", "name", "slug"]
|
|
1497
|
+
}, {
|
|
1498
|
+
association: "image",
|
|
1499
|
+
attributes: ["id", "author", "url", "license"],
|
|
1500
|
+
include: [{
|
|
1501
|
+
association: "contentByLocale",
|
|
1502
|
+
where: contentWhereClause
|
|
1503
|
+
}]
|
|
1504
|
+
}, {
|
|
1505
|
+
association: "contentByLocale",
|
|
1506
|
+
where: contentWhereClause
|
|
1507
|
+
}]
|
|
1508
|
+
});
|
|
1509
|
+
if (memberSearchResults.length !== (mode === "ids" ? ids.length : slugs.length))
|
|
1510
|
+
throw new BackendError(404, "One of the members was not found.");
|
|
1511
|
+
memberSearchResults.sort(
|
|
1512
|
+
(a, b) => whereClause.content_id.indexOf(a.content_id) - whereClause.content_id.indexOf(b.content_id)
|
|
1513
|
+
);
|
|
1514
|
+
const normalizedResults = memberSearchResults.map((item) => {
|
|
1515
|
+
const newItem = __spreadProps$8(__spreadValues$e({}, item.toJSON()), {
|
|
1516
|
+
report_name: item.report.name,
|
|
1517
|
+
dimension_name: item.dimension.name,
|
|
1518
|
+
variant_name: item.variant.name,
|
|
1519
|
+
variant_slug: item.variant.slug
|
|
1520
|
+
});
|
|
1521
|
+
if (!all) {
|
|
1522
|
+
const localizedItem = item.getContent(locale);
|
|
1523
|
+
if (newItem.locale = localizedItem.locale, newItem.name = localizedItem.name, newItem.attributes = localizedItem.attributes, newItem.keywords = localizedItem.keywords, delete newItem.contentByLocale, item.image) {
|
|
1524
|
+
const localizedImage = item.image.getContent(locale);
|
|
1525
|
+
newItem.image = __spreadProps$8(__spreadValues$e({}, item.image), {
|
|
1526
|
+
meta: localizedImage.meta
|
|
1527
|
+
}), delete newItem.image.contentByLocale;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
return delete newItem.report, delete newItem.dimension, delete newItem.variant, newItem;
|
|
1531
|
+
});
|
|
1532
|
+
return {
|
|
1533
|
+
meta: {
|
|
1534
|
+
locale: stripHTML(locale),
|
|
1535
|
+
mode,
|
|
1536
|
+
ids,
|
|
1537
|
+
slugs
|
|
1538
|
+
},
|
|
1539
|
+
results: normalizedResults
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
function readMemberImageFactory(db) {
|
|
1544
|
+
const { search: Search } = db;
|
|
1545
|
+
return readMemberImage;
|
|
1546
|
+
async function readMemberImage(params) {
|
|
1547
|
+
const member = await Search.findOne({
|
|
1548
|
+
where: { content_id: params.member },
|
|
1549
|
+
include: [
|
|
1550
|
+
{
|
|
1551
|
+
association: "image",
|
|
1552
|
+
attributes: ["id", "author", "url", "license", params.size],
|
|
1553
|
+
include: [{
|
|
1554
|
+
association: "contentByLocale"
|
|
1555
|
+
}]
|
|
1556
|
+
},
|
|
1557
|
+
{
|
|
1558
|
+
association: "report",
|
|
1559
|
+
attributes: ["id", "name"]
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
association: "dimension",
|
|
1563
|
+
attributes: ["id", "name", "ordering"]
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
association: "variant",
|
|
1567
|
+
attributes: ["id", "name", "slug"]
|
|
1568
|
+
}
|
|
1569
|
+
]
|
|
1570
|
+
});
|
|
1571
|
+
if (member && member.image) {
|
|
1572
|
+
if (member.image[params.size])
|
|
1573
|
+
return member.image[params.size];
|
|
1574
|
+
} else
|
|
1575
|
+
return Buffer.from(
|
|
1576
|
+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkkAQAAB8AG7jymN8AAAAASUVORK5CYII=",
|
|
1577
|
+
"base64"
|
|
1578
|
+
);
|
|
1579
|
+
throw new BackendError(404, "error in image, member not found");
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
require("lunr-languages/lunr.stemmer.support")(lunr);
|
|
1583
|
+
const whitelist = ["ar", "da", "de", "du", "en", "es", "fi", "hi", "hu", "it", "ja", "jp", "nl", "no", "pt", "ro", "ru", "sv", "ta", "th", "tr", "vi", "zh"], verbose$1 = getLogging(), { locales: locales$4 } = getLocales(), enabledLocales = locales$4.filter((d) => whitelist.includes(d)), nonEnLocales = enabledLocales.filter((d) => whitelist.includes(d)).filter((d) => d !== "en");
|
|
1584
|
+
for (const locale of nonEnLocales)
|
|
1585
|
+
require(`lunr-languages/lunr.${locale}`)(lunr);
|
|
1586
|
+
let search;
|
|
1587
|
+
const getSearchIndexByLocale = async (db, forceRegenerate = !1) => {
|
|
1588
|
+
if (forceRegenerate && (verbose$1 && console.log("REGENERATING SEARCH INDEX"), search = void 0), search)
|
|
1589
|
+
return search;
|
|
1590
|
+
try {
|
|
1591
|
+
verbose$1 && console.log("INITIALIZING SEARCH INDEX");
|
|
1592
|
+
const results = await db.search.findAll({ include: [{ association: "contentByLocale" }] }).then((arr) => arr.map((d) => d.toJSON())).catch(() => []), searchIndexByLocale = {};
|
|
1593
|
+
for (const locale of enabledLocales)
|
|
1594
|
+
searchIndexByLocale[locale] = lunr(function() {
|
|
1595
|
+
locale && locale !== "en" && this.use(lunr[locale]), this.ref("content_id"), this.field("id"), this.field("name"), this.field("keywords"), this.field("attr"), this.pipeline.reset(), this.searchPipeline.reset(), results.forEach((result) => {
|
|
1596
|
+
const content = result.contentByLocale.find((d) => d.locale === locale);
|
|
1597
|
+
if (content) {
|
|
1598
|
+
const payload = {
|
|
1599
|
+
id: result.id,
|
|
1600
|
+
content_id: result.content_id,
|
|
1601
|
+
name: content.name,
|
|
1602
|
+
keywords: content.keywords,
|
|
1603
|
+
attributes: content.attributes
|
|
1604
|
+
};
|
|
1605
|
+
this.add(payload, { boost: result.zvalue });
|
|
1606
|
+
}
|
|
1607
|
+
}, this);
|
|
1608
|
+
});
|
|
1609
|
+
search = searchIndexByLocale;
|
|
1610
|
+
} catch (e) {
|
|
1611
|
+
throw new Error(`
|
|
1612
|
+
Could not initialize Lunr search engine.
|
|
1613
|
+
Details:
|
|
1614
|
+
${e.message}
|
|
1615
|
+
`);
|
|
1616
|
+
}
|
|
1617
|
+
return search;
|
|
1618
|
+
};
|
|
1619
|
+
var __defProp$d = Object.defineProperty, __defProps$7 = Object.defineProperties, __getOwnPropDescs$7 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$j = Object.getOwnPropertySymbols, __hasOwnProp$j = Object.prototype.hasOwnProperty, __propIsEnum$j = Object.prototype.propertyIsEnumerable, __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$d = (a, b) => {
|
|
1620
|
+
for (var prop in b || (b = {}))
|
|
1621
|
+
__hasOwnProp$j.call(b, prop) && __defNormalProp$d(a, prop, b[prop]);
|
|
1622
|
+
if (__getOwnPropSymbols$j)
|
|
1623
|
+
for (var prop of __getOwnPropSymbols$j(b))
|
|
1624
|
+
__propIsEnum$j.call(b, prop) && __defNormalProp$d(a, prop, b[prop]);
|
|
1625
|
+
return a;
|
|
1626
|
+
}, __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
|
|
1627
|
+
const { localeDefault: localeDefault$2 } = getLocales();
|
|
1628
|
+
function dbSearchMemberFactory(db) {
|
|
1629
|
+
const { search: Search } = db;
|
|
1630
|
+
return searchMember;
|
|
1631
|
+
async function searchMember(params) {
|
|
1632
|
+
const searchIndexByLocale = await getSearchIndexByLocale(db);
|
|
1633
|
+
let resultsIds = [];
|
|
1634
|
+
const {
|
|
1635
|
+
query,
|
|
1636
|
+
locale,
|
|
1637
|
+
limit,
|
|
1638
|
+
format,
|
|
1639
|
+
visible,
|
|
1640
|
+
variant,
|
|
1641
|
+
dimension,
|
|
1642
|
+
report,
|
|
1643
|
+
all,
|
|
1644
|
+
noImage,
|
|
1645
|
+
includes,
|
|
1646
|
+
sort,
|
|
1647
|
+
direction = "ASC"
|
|
1648
|
+
} = params;
|
|
1649
|
+
if (query && query !== "" && searchIndexByLocale[locale]) {
|
|
1650
|
+
const terms = query.split(" ").map((d) => `+${d}*`).join(" ");
|
|
1651
|
+
resultsIds = searchIndexByLocale[locale].search(terms).map((d) => parseInt(d.ref, 10));
|
|
1652
|
+
}
|
|
1653
|
+
const whereClause = __spreadValues$d(__spreadValues$d(__spreadValues$d(__spreadValues$d(__spreadValues$d({}, visible ? { visible } : {}), noImage ? { image_id: { [Op.eq]: null } } : {}), variant.length ? { variant_id: variant } : {}), dimension.length ? { dimension_id: dimension } : {}), report.length ? { report_id: report } : {}), contentWhereClause = {
|
|
1654
|
+
locale: all ? { [Op.ne]: null } : locale
|
|
1655
|
+
};
|
|
1656
|
+
query === "" && (resultsIds = (await Search.findAll({
|
|
1657
|
+
attributes: [
|
|
1658
|
+
"id",
|
|
1659
|
+
"content_id",
|
|
1660
|
+
"report_id",
|
|
1661
|
+
[literal("rank() over(partition by report_id order by zvalue desc)"), "rank"]
|
|
1662
|
+
],
|
|
1663
|
+
where: whereClause,
|
|
1664
|
+
include: [{
|
|
1665
|
+
association: "contentByLocale",
|
|
1666
|
+
where: contentWhereClause
|
|
1667
|
+
}]
|
|
1668
|
+
}).then((arr) => arr.map((d) => d.toJSON()))).filter((item) => parseInt(item.rank, 10) <= limit).map((d) => d.content_id)), whereClause.content_id = resultsIds;
|
|
1669
|
+
const includeClause = [{
|
|
1670
|
+
association: "contentByLocale",
|
|
1671
|
+
where: contentWhereClause
|
|
1672
|
+
}];
|
|
1673
|
+
includes && includeClause.push({
|
|
1674
|
+
association: "report",
|
|
1675
|
+
attributes: ["id", "name"]
|
|
1676
|
+
}, {
|
|
1677
|
+
association: "dimension",
|
|
1678
|
+
attributes: ["id", "name"]
|
|
1679
|
+
}, {
|
|
1680
|
+
association: "variant",
|
|
1681
|
+
attributes: ["id", "slug", "name"]
|
|
1682
|
+
});
|
|
1683
|
+
const orderClause = [["zvalue", "DESC NULLS LAST"]];
|
|
1684
|
+
sort && sort !== "name" && orderClause.unshift([sort, direction.toUpperCase()]);
|
|
1685
|
+
const results = await Search.findAll({
|
|
1686
|
+
limit: query ? limit : void 0,
|
|
1687
|
+
where: whereClause,
|
|
1688
|
+
include: includeClause,
|
|
1689
|
+
order: orderClause
|
|
1690
|
+
});
|
|
1691
|
+
if (sort === "name") {
|
|
1692
|
+
const sortDirection = direction.toUpperCase() === "ASC" ? 1 : -1;
|
|
1693
|
+
results.sort((a, b) => {
|
|
1694
|
+
const aValue = a.getContent(localeDefault$2), bValue = b.getContent(localeDefault$2);
|
|
1695
|
+
return aValue && bValue ? aValue.name > bValue.name ? 1 * sortDirection : -1 * sortDirection : 0;
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
const resultFormatter = format === "nested" ? nestedFormatter : plainFormatter;
|
|
1699
|
+
return {
|
|
1700
|
+
meta: __spreadValues$d({
|
|
1701
|
+
origin: "lunr"
|
|
1702
|
+
}, Object.fromEntries(
|
|
1703
|
+
Object.entries(params).map((entry) => [entry[0], stripHTML(entry[1])])
|
|
1704
|
+
)),
|
|
1705
|
+
results: results.map(resultFormatter)
|
|
1706
|
+
};
|
|
1707
|
+
function nestedFormatter(item) {
|
|
1708
|
+
return item.toJSON();
|
|
1709
|
+
}
|
|
1710
|
+
function plainFormatter(item) {
|
|
1711
|
+
const localizedItem = item.getContent(locale);
|
|
1712
|
+
return __spreadProps$7(__spreadValues$d({}, item.toJSON()), {
|
|
1713
|
+
locale: localizedItem.locale,
|
|
1714
|
+
name: localizedItem.name,
|
|
1715
|
+
attributes: localizedItem.attributes,
|
|
1716
|
+
keywords: localizedItem.keywords
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
var __defProp$c = Object.defineProperty, __getOwnPropSymbols$i = Object.getOwnPropertySymbols, __hasOwnProp$i = Object.prototype.hasOwnProperty, __propIsEnum$i = Object.prototype.propertyIsEnumerable, __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$c = (a, b) => {
|
|
1722
|
+
for (var prop in b || (b = {}))
|
|
1723
|
+
__hasOwnProp$i.call(b, prop) && __defNormalProp$c(a, prop, b[prop]);
|
|
1724
|
+
if (__getOwnPropSymbols$i)
|
|
1725
|
+
for (var prop of __getOwnPropSymbols$i(b))
|
|
1726
|
+
__propIsEnum$i.call(b, prop) && __defNormalProp$c(a, prop, b[prop]);
|
|
1727
|
+
return a;
|
|
1728
|
+
};
|
|
1729
|
+
function updateMemberFactory(db) {
|
|
1730
|
+
const {
|
|
1731
|
+
image: Image,
|
|
1732
|
+
image_content: ImageContent,
|
|
1733
|
+
search: Search,
|
|
1734
|
+
search_content: SearchContent
|
|
1735
|
+
} = db;
|
|
1736
|
+
return updateMember;
|
|
1737
|
+
async function updateMember(params) {
|
|
1738
|
+
const {
|
|
1739
|
+
content_id,
|
|
1740
|
+
contentByLocale,
|
|
1741
|
+
image,
|
|
1742
|
+
image_id
|
|
1743
|
+
} = params;
|
|
1744
|
+
let returnQuery = { where: { content_id } };
|
|
1745
|
+
const oldRecord = await Search.findOne(returnQuery);
|
|
1746
|
+
if (await Search.update(params, { where: { content_id } }), contentByLocale) {
|
|
1747
|
+
for (let index = 0; index < contentByLocale.length; index++) {
|
|
1748
|
+
const searchContent = contentByLocale[index];
|
|
1749
|
+
await SearchContent.update({
|
|
1750
|
+
name: searchContent.name,
|
|
1751
|
+
keywords: searchContent.keywords
|
|
1752
|
+
}, { where: { id: searchContent.id, locale: searchContent.locale } });
|
|
1753
|
+
}
|
|
1754
|
+
const relevantInclude = {
|
|
1755
|
+
include: [
|
|
1756
|
+
{ association: "contentByLocale", separate: !0 }
|
|
1757
|
+
]
|
|
1758
|
+
};
|
|
1759
|
+
returnQuery = __spreadValues$c(__spreadValues$c({}, returnQuery), relevantInclude);
|
|
1760
|
+
}
|
|
1761
|
+
if (image) {
|
|
1762
|
+
if (image.id && (await Image.update(__spreadValues$c({}, image), { where: { id: image.id } }), image.contentByLocale))
|
|
1763
|
+
for (let index = 0; index < image.contentByLocale.length; index++) {
|
|
1764
|
+
const imageContent = image.contentByLocale[index];
|
|
1765
|
+
await ImageContent.update({
|
|
1766
|
+
meta: imageContent.meta
|
|
1767
|
+
}, { where: { id: imageContent.id, locale: imageContent.locale } });
|
|
1768
|
+
}
|
|
1769
|
+
} else
|
|
1770
|
+
!image_id && oldRecord.image_id && (await db.search.findAll({
|
|
1771
|
+
where: { image_id: oldRecord.image_id }
|
|
1772
|
+
})).length === 0 && await Image.destroy({
|
|
1773
|
+
where: { id: oldRecord.image_id }
|
|
1774
|
+
});
|
|
1775
|
+
return Search.findOne(returnQuery);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
function dbMemberFactory(db) {
|
|
1779
|
+
return {
|
|
1780
|
+
ingestMembers: ingestMembersFactory(db),
|
|
1781
|
+
readMember: readMemberFactory(db),
|
|
1782
|
+
searchMember: dbSearchMemberFactory(db),
|
|
1783
|
+
updateMember: updateMemberFactory(db),
|
|
1784
|
+
readMemberImage: readMemberImageFactory(db)
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
var __defProp$b = Object.defineProperty, __getOwnPropSymbols$h = Object.getOwnPropertySymbols, __hasOwnProp$h = Object.prototype.hasOwnProperty, __propIsEnum$h = Object.prototype.propertyIsEnumerable, __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$b = (a, b) => {
|
|
1788
|
+
for (var prop in b || (b = {}))
|
|
1789
|
+
__hasOwnProp$h.call(b, prop) && __defNormalProp$b(a, prop, b[prop]);
|
|
1790
|
+
if (__getOwnPropSymbols$h)
|
|
1791
|
+
for (var prop of __getOwnPropSymbols$h(b))
|
|
1792
|
+
__propIsEnum$h.call(b, prop) && __defNormalProp$b(a, prop, b[prop]);
|
|
1793
|
+
return a;
|
|
1794
|
+
};
|
|
1795
|
+
const blockQuery = {
|
|
1796
|
+
include: [
|
|
1797
|
+
{ association: "contentByLocale", separate: !0 },
|
|
1798
|
+
{ association: "inputs" },
|
|
1799
|
+
{ association: "consumers" }
|
|
1800
|
+
]
|
|
1801
|
+
}, dimensionQuery = {
|
|
1802
|
+
include: [
|
|
1803
|
+
{ association: "variants", separate: !0 }
|
|
1804
|
+
]
|
|
1805
|
+
}, sectionQuery = {
|
|
1806
|
+
include: [
|
|
1807
|
+
__spreadValues$b({ association: "blocks", separate: !0 }, blockQuery)
|
|
1808
|
+
]
|
|
1809
|
+
}, reportQuery = {
|
|
1810
|
+
include: [
|
|
1811
|
+
__spreadValues$b({ association: "dimensions", separate: !0 }, dimensionQuery),
|
|
1812
|
+
__spreadValues$b({ association: "sections", separate: !0 }, sectionQuery)
|
|
1813
|
+
]
|
|
1814
|
+
}, imageQueryThumbOnly = [
|
|
1815
|
+
{
|
|
1816
|
+
association: "image",
|
|
1817
|
+
attributes: {
|
|
1818
|
+
exclude: ["splash"]
|
|
1819
|
+
},
|
|
1820
|
+
include: [
|
|
1821
|
+
{ association: "contentByLocale" }
|
|
1822
|
+
]
|
|
1823
|
+
},
|
|
1824
|
+
{ association: "contentByLocale" }
|
|
1825
|
+
];
|
|
1826
|
+
var __defProp$a = Object.defineProperty, __defProps$6 = Object.defineProperties, __getOwnPropDescs$6 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$g = Object.getOwnPropertySymbols, __hasOwnProp$g = Object.prototype.hasOwnProperty, __propIsEnum$g = Object.prototype.propertyIsEnumerable, __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$a = (a, b) => {
|
|
1827
|
+
for (var prop in b || (b = {}))
|
|
1828
|
+
__hasOwnProp$g.call(b, prop) && __defNormalProp$a(a, prop, b[prop]);
|
|
1829
|
+
if (__getOwnPropSymbols$g)
|
|
1830
|
+
for (var prop of __getOwnPropSymbols$g(b))
|
|
1831
|
+
__propIsEnum$g.call(b, prop) && __defNormalProp$a(a, prop, b[prop]);
|
|
1832
|
+
return a;
|
|
1833
|
+
}, __spreadProps$6 = (a, b) => __defProps$6(a, __getOwnPropDescs$6(b)), __objRest$6 = (source, exclude) => {
|
|
1834
|
+
var target = {};
|
|
1835
|
+
for (var prop in source)
|
|
1836
|
+
__hasOwnProp$g.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
1837
|
+
if (source != null && __getOwnPropSymbols$g)
|
|
1838
|
+
for (var prop of __getOwnPropSymbols$g(source))
|
|
1839
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$g.call(source, prop) && (target[prop] = source[prop]);
|
|
1840
|
+
return target;
|
|
1841
|
+
};
|
|
1842
|
+
function dbBlockFactory(db) {
|
|
1843
|
+
const { block: Block, block_content: BlockContent, block_input: BlockInput } = db;
|
|
1844
|
+
return {
|
|
1845
|
+
createBlock,
|
|
1846
|
+
readBlock,
|
|
1847
|
+
updateBlock,
|
|
1848
|
+
deleteBlock
|
|
1849
|
+
};
|
|
1850
|
+
async function createBlock(data) {
|
|
1851
|
+
const _a = data, { locale } = _a, blockData = __objRest$6(_a, ["locale"]);
|
|
1852
|
+
return (await Block.create(__spreadProps$6(__spreadValues$a({}, blockData), {
|
|
1853
|
+
consumers: [],
|
|
1854
|
+
inputs: [],
|
|
1855
|
+
contentByLocale: [{ locale }]
|
|
1856
|
+
}), {
|
|
1857
|
+
include: blockQuery.include
|
|
1858
|
+
})).toJSON();
|
|
1859
|
+
}
|
|
1860
|
+
async function readBlock({ id, include } = {}) {
|
|
1861
|
+
const idList = id == null ? [] : [].concat(id), entities = await Block.findAll({
|
|
1862
|
+
where: idList.length > 0 ? { id: idList } : void 0,
|
|
1863
|
+
include: include ? blockQuery.include : void 0
|
|
1864
|
+
});
|
|
1865
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
1866
|
+
return entities.map((entity) => entity.toJSON());
|
|
1867
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
1868
|
+
throw new BackendError(404, `Block(id=[${missing}]) does not exist.`);
|
|
1869
|
+
}
|
|
1870
|
+
async function updateBlock(data) {
|
|
1871
|
+
const _a = data, {
|
|
1872
|
+
id,
|
|
1873
|
+
contentByLocale,
|
|
1874
|
+
consumers,
|
|
1875
|
+
inputs,
|
|
1876
|
+
inputAction
|
|
1877
|
+
} = _a, blockData = __objRest$6(_a, [
|
|
1878
|
+
"id",
|
|
1879
|
+
"contentByLocale",
|
|
1880
|
+
"consumers",
|
|
1881
|
+
"inputs",
|
|
1882
|
+
"inputAction"
|
|
1883
|
+
]), entity = await Block.findByPk(id, {
|
|
1884
|
+
include: blockQuery.include,
|
|
1885
|
+
rejectOnEmpty: !0
|
|
1886
|
+
});
|
|
1887
|
+
if (entity.set(blockData), contentByLocale) {
|
|
1888
|
+
const contentList = Object.values(contentByLocale);
|
|
1889
|
+
await BlockContent.bulkCreate(contentList, {
|
|
1890
|
+
updateOnDuplicate: ["content"]
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
return inputAction && (inputAction.operation === "create" ? await BlockInput.create(inputAction.input) : await BlockInput.destroy({ where: inputAction.input })), await entity.save(), await entity.reload(), entity.toJSON();
|
|
1894
|
+
}
|
|
1895
|
+
async function deleteBlock(id) {
|
|
1896
|
+
const entity = await Block.findByPk(id, { rejectOnEmpty: !0 });
|
|
1897
|
+
return await entity.destroy(), { id, parentType: "section", parentId: entity.section_id };
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
var __getOwnPropSymbols$f = Object.getOwnPropertySymbols, __hasOwnProp$f = Object.prototype.hasOwnProperty, __propIsEnum$f = Object.prototype.propertyIsEnumerable, __objRest$5 = (source, exclude) => {
|
|
1901
|
+
var target = {};
|
|
1902
|
+
for (var prop in source)
|
|
1903
|
+
__hasOwnProp$f.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
1904
|
+
if (source != null && __getOwnPropSymbols$f)
|
|
1905
|
+
for (var prop of __getOwnPropSymbols$f(source))
|
|
1906
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$f.call(source, prop) && (target[prop] = source[prop]);
|
|
1907
|
+
return target;
|
|
1908
|
+
};
|
|
1909
|
+
function dbDimensionFactory(db) {
|
|
1910
|
+
const { dimension: Dimension } = db;
|
|
1911
|
+
return {
|
|
1912
|
+
createDimension,
|
|
1913
|
+
readDimension,
|
|
1914
|
+
updateDimension,
|
|
1915
|
+
deleteDimension
|
|
1916
|
+
};
|
|
1917
|
+
async function createDimension(data) {
|
|
1918
|
+
return (await Dimension.create({
|
|
1919
|
+
name: data.name,
|
|
1920
|
+
report_id: data.report_id,
|
|
1921
|
+
variants: []
|
|
1922
|
+
}, {
|
|
1923
|
+
include: dimensionQuery.include
|
|
1924
|
+
})).toJSON();
|
|
1925
|
+
}
|
|
1926
|
+
async function readDimension({ id, include } = {}) {
|
|
1927
|
+
const idList = id == null ? [] : [].concat(id), entities = await Dimension.findAll({
|
|
1928
|
+
where: idList.length > 0 ? { id: idList } : void 0,
|
|
1929
|
+
include: include ? dimensionQuery.include : void 0
|
|
1930
|
+
});
|
|
1931
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
1932
|
+
return entities.map((entity) => entity.toJSON());
|
|
1933
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
1934
|
+
throw new BackendError(404, `Dimension(id=[${missing}]) does not exist.`);
|
|
1935
|
+
}
|
|
1936
|
+
async function updateDimension(data) {
|
|
1937
|
+
const _a = data, { id, variants } = _a, dimensionData = __objRest$5(_a, ["id", "variants"]), entity = await Dimension.findByPk(id, {
|
|
1938
|
+
include: dimensionQuery.include,
|
|
1939
|
+
rejectOnEmpty: !0
|
|
1940
|
+
});
|
|
1941
|
+
return entity.set(dimensionData), await entity.save(), entity.toJSON();
|
|
1942
|
+
}
|
|
1943
|
+
async function deleteDimension(id) {
|
|
1944
|
+
const entity = await Dimension.findByPk(id, { rejectOnEmpty: !0 });
|
|
1945
|
+
return await entity.destroy(), { id, parentType: "report", parentId: entity.report_id };
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
var __getOwnPropSymbols$e = Object.getOwnPropertySymbols, __hasOwnProp$e = Object.prototype.hasOwnProperty, __propIsEnum$e = Object.prototype.propertyIsEnumerable, __objRest$4 = (source, exclude) => {
|
|
1949
|
+
var target = {};
|
|
1950
|
+
for (var prop in source)
|
|
1951
|
+
__hasOwnProp$e.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
1952
|
+
if (source != null && __getOwnPropSymbols$e)
|
|
1953
|
+
for (var prop of __getOwnPropSymbols$e(source))
|
|
1954
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$e.call(source, prop) && (target[prop] = source[prop]);
|
|
1955
|
+
return target;
|
|
1956
|
+
};
|
|
1957
|
+
function dbFormatterFactory(db) {
|
|
1958
|
+
const { formatter: Formatter } = db;
|
|
1959
|
+
return {
|
|
1960
|
+
createFormatter,
|
|
1961
|
+
readFormatter,
|
|
1962
|
+
updateFormatter,
|
|
1963
|
+
deleteFormatter
|
|
1964
|
+
};
|
|
1965
|
+
async function createFormatter(data) {
|
|
1966
|
+
return (await Formatter.create(data)).toJSON();
|
|
1967
|
+
}
|
|
1968
|
+
async function readFormatter({ id } = {}) {
|
|
1969
|
+
const idList = id == null ? [] : [].concat(id), entities = await Formatter.findAll({
|
|
1970
|
+
where: idList.length > 0 ? { id: idList } : void 0
|
|
1971
|
+
});
|
|
1972
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
1973
|
+
return entities.map((entity) => entity.toJSON());
|
|
1974
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
1975
|
+
throw new BackendError(404, `Formatter(id=[${missing}]) does not exist.`);
|
|
1976
|
+
}
|
|
1977
|
+
async function updateFormatter(data) {
|
|
1978
|
+
const _a = data, { id } = _a, formatterData = __objRest$4(_a, ["id"]), entity = await Formatter.findByPk(id, { rejectOnEmpty: !0 });
|
|
1979
|
+
return await entity.update(formatterData), entity.toJSON();
|
|
1980
|
+
}
|
|
1981
|
+
async function deleteFormatter(id) {
|
|
1982
|
+
return await (await Formatter.findByPk(id, { rejectOnEmpty: !0 })).destroy(), { id };
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
var __getOwnPropSymbols$d = Object.getOwnPropertySymbols, __hasOwnProp$d = Object.prototype.hasOwnProperty, __propIsEnum$d = Object.prototype.propertyIsEnumerable, __objRest$3 = (source, exclude) => {
|
|
1986
|
+
var target = {};
|
|
1987
|
+
for (var prop in source)
|
|
1988
|
+
__hasOwnProp$d.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
1989
|
+
if (source != null && __getOwnPropSymbols$d)
|
|
1990
|
+
for (var prop of __getOwnPropSymbols$d(source))
|
|
1991
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$d.call(source, prop) && (target[prop] = source[prop]);
|
|
1992
|
+
return target;
|
|
1993
|
+
};
|
|
1994
|
+
function dbReportFactory(db) {
|
|
1995
|
+
const { report: Report } = db;
|
|
1996
|
+
return {
|
|
1997
|
+
createReport,
|
|
1998
|
+
readReport,
|
|
1999
|
+
updateReport,
|
|
2000
|
+
deleteReport
|
|
2001
|
+
};
|
|
2002
|
+
async function createReport(data) {
|
|
2003
|
+
return (await Report.create({
|
|
2004
|
+
name: data.name,
|
|
2005
|
+
sections: [],
|
|
2006
|
+
dimensions: []
|
|
2007
|
+
}, {
|
|
2008
|
+
include: reportQuery.include
|
|
2009
|
+
})).toJSON();
|
|
2010
|
+
}
|
|
2011
|
+
async function readReport({ id, include } = {}) {
|
|
2012
|
+
const idList = id == null ? [] : [].concat(id), entities = await Report.findAll({
|
|
2013
|
+
where: idList.length > 0 ? { id: idList } : void 0,
|
|
2014
|
+
include: include ? reportQuery.include : void 0
|
|
2015
|
+
});
|
|
2016
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
2017
|
+
return entities.map((entity) => entity.toJSON());
|
|
2018
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
2019
|
+
throw new BackendError(404, `Report(id=${missing}) does not exist.`);
|
|
2020
|
+
}
|
|
2021
|
+
async function updateReport(data) {
|
|
2022
|
+
const _a = data, {
|
|
2023
|
+
id,
|
|
2024
|
+
dimensions,
|
|
2025
|
+
sections
|
|
2026
|
+
} = _a, reportData = __objRest$3(_a, [
|
|
2027
|
+
"id",
|
|
2028
|
+
"dimensions",
|
|
2029
|
+
"sections"
|
|
2030
|
+
]), entity = await Report.findByPk(id, {
|
|
2031
|
+
include: reportQuery.include,
|
|
2032
|
+
rejectOnEmpty: !0
|
|
2033
|
+
});
|
|
2034
|
+
return entity.set(reportData), await entity.save(), await entity.reload(), entity.toJSON();
|
|
2035
|
+
}
|
|
2036
|
+
async function deleteReport(id) {
|
|
2037
|
+
return await (await Report.findByPk(id, { rejectOnEmpty: !0 })).destroy(), { id };
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
var __getOwnPropSymbols$c = Object.getOwnPropertySymbols, __hasOwnProp$c = Object.prototype.hasOwnProperty, __propIsEnum$c = Object.prototype.propertyIsEnumerable, __objRest$2 = (source, exclude) => {
|
|
2041
|
+
var target = {};
|
|
2042
|
+
for (var prop in source)
|
|
2043
|
+
__hasOwnProp$c.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
2044
|
+
if (source != null && __getOwnPropSymbols$c)
|
|
2045
|
+
for (var prop of __getOwnPropSymbols$c(source))
|
|
2046
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$c.call(source, prop) && (target[prop] = source[prop]);
|
|
2047
|
+
return target;
|
|
2048
|
+
};
|
|
2049
|
+
function dbSectionFactory(db) {
|
|
2050
|
+
const { section: Section } = db;
|
|
2051
|
+
return {
|
|
2052
|
+
createSection,
|
|
2053
|
+
readSection,
|
|
2054
|
+
updateSection,
|
|
2055
|
+
deleteSection
|
|
2056
|
+
};
|
|
2057
|
+
async function createSection(data) {
|
|
2058
|
+
return (await Section.create({
|
|
2059
|
+
ordering: data.ordering,
|
|
2060
|
+
report_id: data.report_id,
|
|
2061
|
+
blocks: []
|
|
2062
|
+
}, {
|
|
2063
|
+
include: sectionQuery.include
|
|
2064
|
+
})).toJSON();
|
|
2065
|
+
}
|
|
2066
|
+
async function readSection({ id, include } = {}) {
|
|
2067
|
+
const idList = id == null ? [] : [].concat(id), entities = await Section.findAll({
|
|
2068
|
+
where: idList.length > 0 ? { id: idList } : void 0,
|
|
2069
|
+
include: include ? sectionQuery.include : void 0
|
|
2070
|
+
});
|
|
2071
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
2072
|
+
return entities.map((entity) => entity.toJSON());
|
|
2073
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
2074
|
+
throw new BackendError(404, `Section(id=${missing}) does not exist.`);
|
|
2075
|
+
}
|
|
2076
|
+
async function updateSection(data) {
|
|
2077
|
+
const _a = data, { id, blocks } = _a, sectionData = __objRest$2(_a, ["id", "blocks"]), entity = await Section.findByPk(id, {
|
|
2078
|
+
include: sectionQuery.include,
|
|
2079
|
+
rejectOnEmpty: !0
|
|
2080
|
+
});
|
|
2081
|
+
return entity.set(sectionData), await entity.save(), await entity.reload(), entity.toJSON();
|
|
2082
|
+
}
|
|
2083
|
+
async function deleteSection(id) {
|
|
2084
|
+
const entity = await Section.findByPk(id, { rejectOnEmpty: !0 });
|
|
2085
|
+
return await entity.destroy(), { id, parentType: "report", parentId: entity.report_id };
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
var __getOwnPropSymbols$b = Object.getOwnPropertySymbols, __hasOwnProp$b = Object.prototype.hasOwnProperty, __propIsEnum$b = Object.prototype.propertyIsEnumerable, __objRest$1 = (source, exclude) => {
|
|
2089
|
+
var target = {};
|
|
2090
|
+
for (var prop in source)
|
|
2091
|
+
__hasOwnProp$b.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
2092
|
+
if (source != null && __getOwnPropSymbols$b)
|
|
2093
|
+
for (var prop of __getOwnPropSymbols$b(source))
|
|
2094
|
+
exclude.indexOf(prop) < 0 && __propIsEnum$b.call(source, prop) && (target[prop] = source[prop]);
|
|
2095
|
+
return target;
|
|
2096
|
+
};
|
|
2097
|
+
function dbVariantFactory(db, crud) {
|
|
2098
|
+
const { variant: Variant } = db;
|
|
2099
|
+
return {
|
|
2100
|
+
createVariant,
|
|
2101
|
+
readVariant,
|
|
2102
|
+
updateVariant,
|
|
2103
|
+
deleteVariant,
|
|
2104
|
+
validateVariantSlug
|
|
2105
|
+
};
|
|
2106
|
+
async function createVariant(body) {
|
|
2107
|
+
const { dimension_id: dimension, name, slug } = body, validSlug = await validateVariantSlug({ dimension, slug });
|
|
2108
|
+
return (await Variant.create({
|
|
2109
|
+
dimension_id: dimension,
|
|
2110
|
+
name,
|
|
2111
|
+
slug: validSlug.valid ? validSlug.candidate : validSlug.suggestion
|
|
2112
|
+
})).toJSON();
|
|
2113
|
+
}
|
|
2114
|
+
async function readVariant({ id } = {}) {
|
|
2115
|
+
const idList = id == null ? [] : [].concat(id), entities = await Variant.findAll({
|
|
2116
|
+
where: idList.length > 0 ? { id: idList } : void 0
|
|
2117
|
+
});
|
|
2118
|
+
if (idList.length === 0 || entities.length === idList.length)
|
|
2119
|
+
return entities.map((entity) => entity.toJSON());
|
|
2120
|
+
const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
|
|
2121
|
+
throw new BackendError(404, `Variant(id=${missing}) does not exist.`);
|
|
2122
|
+
}
|
|
2123
|
+
async function updateVariant(data) {
|
|
2124
|
+
const _a = data, { id } = _a, variantData = __objRest$1(_a, ["id"]), entity = await Variant.findByPk(id, {
|
|
2125
|
+
include: [{ association: "dimension" }],
|
|
2126
|
+
rejectOnEmpty: !0
|
|
2127
|
+
});
|
|
2128
|
+
return entity.update(variantData), await crud.ingestMembers(entity), await getSearchIndexByLocale(db, !0), await entity.reload(), entity.toJSON();
|
|
2129
|
+
}
|
|
2130
|
+
async function deleteVariant(id) {
|
|
2131
|
+
const entity = await Variant.findByPk(id, { rejectOnEmpty: !0 });
|
|
2132
|
+
return await entity.destroy(), getSearchIndexByLocale(db, !0), { id, parentType: "dimension", parentId: entity.dimension_id };
|
|
2133
|
+
}
|
|
2134
|
+
async function validateVariantSlug({ dimension, slug }) {
|
|
2135
|
+
const allSlugsFromOtherDimensions = await Variant.findAll({
|
|
2136
|
+
attributes: ["slug", [fn("COUNT", col("id")), "slugCount"]],
|
|
2137
|
+
where: {
|
|
2138
|
+
dimension_id: { [Op.ne]: dimension }
|
|
2139
|
+
},
|
|
2140
|
+
group: "slug"
|
|
2141
|
+
}).then((arr) => Object.fromEntries(arr.map((item) => {
|
|
2142
|
+
const count = item.getDataValue("slugCount");
|
|
2143
|
+
return [item.slug, Number.parseInt(`${count}`, 10)];
|
|
2144
|
+
})));
|
|
2145
|
+
let suggestion = slug, iteration = 1, valid = !0;
|
|
2146
|
+
for (; allSlugsFromOtherDimensions[suggestion]; )
|
|
2147
|
+
valid = !1, suggestion = `${slug}-${iteration}`, iteration++;
|
|
2148
|
+
return {
|
|
2149
|
+
candidate: slug,
|
|
2150
|
+
dimension_id: dimension,
|
|
2151
|
+
suggestion,
|
|
2152
|
+
valid
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
var __defProp$9 = Object.defineProperty, __getOwnPropSymbols$a = Object.getOwnPropertySymbols, __hasOwnProp$a = Object.prototype.hasOwnProperty, __propIsEnum$a = Object.prototype.propertyIsEnumerable, __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$9 = (a, b) => {
|
|
2157
|
+
for (var prop in b || (b = {}))
|
|
2158
|
+
__hasOwnProp$a.call(b, prop) && __defNormalProp$9(a, prop, b[prop]);
|
|
2159
|
+
if (__getOwnPropSymbols$a)
|
|
2160
|
+
for (var prop of __getOwnPropSymbols$a(b))
|
|
2161
|
+
__propIsEnum$a.call(b, prop) && __defNormalProp$9(a, prop, b[prop]);
|
|
2162
|
+
return a;
|
|
2163
|
+
};
|
|
2164
|
+
function dbEntityFactory(dbModels) {
|
|
2165
|
+
const simpleFactories = __spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9({}, dbBlockFactory(dbModels)), dbDimensionFactory(dbModels)), dbFormatterFactory(dbModels)), dbMemberFactory(dbModels)), dbReportFactory(dbModels)), dbSectionFactory(dbModels)), crud = __spreadValues$9(__spreadValues$9({}, simpleFactories), dbVariantFactory(dbModels, simpleFactories));
|
|
2166
|
+
return {
|
|
2167
|
+
createFormatter: resultWrapper(crud.createFormatter),
|
|
2168
|
+
deleteFormatter: resultWrapper(crud.deleteFormatter),
|
|
2169
|
+
readFormatter: resultWrapper(crud.readFormatter),
|
|
2170
|
+
updateFormatter: resultWrapper(crud.updateFormatter),
|
|
2171
|
+
createReport: resultWrapper(crud.createReport),
|
|
2172
|
+
deleteReport: resultWrapper(crud.deleteReport),
|
|
2173
|
+
readReport: resultWrapper(crud.readReport),
|
|
2174
|
+
updateReport: resultWrapper(crud.updateReport),
|
|
2175
|
+
createDimension: resultWrapper(crud.createDimension),
|
|
2176
|
+
deleteDimension: resultWrapper(crud.deleteDimension),
|
|
2177
|
+
readDimension: resultWrapper(crud.readDimension),
|
|
2178
|
+
updateDimension: resultWrapper(crud.updateDimension),
|
|
2179
|
+
createVariant: resultWrapper(crud.createVariant),
|
|
2180
|
+
readVariant: resultWrapper(crud.readVariant),
|
|
2181
|
+
updateVariant: resultWrapper(crud.updateVariant),
|
|
2182
|
+
deleteVariant: resultWrapper(crud.deleteVariant),
|
|
2183
|
+
validateVariantSlug: resultWrapper(crud.validateVariantSlug),
|
|
2184
|
+
createSection: resultWrapper(crud.createSection),
|
|
2185
|
+
readSection: resultWrapper(crud.readSection),
|
|
2186
|
+
updateSection: resultWrapper(crud.updateSection),
|
|
2187
|
+
deleteSection: resultWrapper(crud.deleteSection),
|
|
2188
|
+
createBlock: resultWrapper(crud.createBlock),
|
|
2189
|
+
deleteBlock: resultWrapper(crud.deleteBlock),
|
|
2190
|
+
readBlock: resultWrapper(crud.readBlock),
|
|
2191
|
+
updateBlock: resultWrapper(crud.updateBlock),
|
|
2192
|
+
readMember: resultWrapper(crud.readMember),
|
|
2193
|
+
searchMember: resultWrapper(crud.searchMember),
|
|
2194
|
+
updateMember: resultWrapper(crud.updateMember),
|
|
2195
|
+
readMemberImage: resultWrapper(crud.readMemberImage)
|
|
2196
|
+
};
|
|
2197
|
+
}
|
|
2198
|
+
const catcher = (e) => {
|
|
2199
|
+
throw console.error("/methods/helpers/uploadImage.ts:", e), new Error(e.message);
|
|
2200
|
+
}, splashWidth = Number(process.env.NEXT_PUBLIC_IMAGE_SPLASH_WIDTH) || 1400, thumbWidth = Number(process.env.NEXT_PUBLIC_IMAGE_THUMB_WIDTH) || 400, uploadImage = async (db, id, imageData) => {
|
|
2201
|
+
const configs = [
|
|
2202
|
+
{ type: "splash", res: splashWidth },
|
|
2203
|
+
{ type: "thumb", res: thumbWidth }
|
|
2204
|
+
];
|
|
2205
|
+
for (const config of configs) {
|
|
2206
|
+
const buffer = await sharp(imageData).resize(config.res).toFormat("jpeg").jpeg({ force: !0 }).toBuffer().catch(catcher);
|
|
2207
|
+
await db.image.update({ [config.type]: buffer }, { where: { id } }).catch(catcher);
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2210
|
+
var __defProp$8 = Object.defineProperty, __getOwnPropSymbols$9 = Object.getOwnPropertySymbols, __hasOwnProp$9 = Object.prototype.hasOwnProperty, __propIsEnum$9 = Object.prototype.propertyIsEnumerable, __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$8 = (a, b) => {
|
|
2211
|
+
for (var prop in b || (b = {}))
|
|
2212
|
+
__hasOwnProp$9.call(b, prop) && __defNormalProp$8(a, prop, b[prop]);
|
|
2213
|
+
if (__getOwnPropSymbols$9)
|
|
2214
|
+
for (var prop of __getOwnPropSymbols$9(b))
|
|
2215
|
+
__propIsEnum$9.call(b, prop) && __defNormalProp$8(a, prop, b[prop]);
|
|
2216
|
+
return a;
|
|
2217
|
+
};
|
|
2218
|
+
const validLicenses = ["4", "5", "7", "8", "9", "10"], validLicensesString = validLicenses.join(), { locales: locales$3 } = getLocales();
|
|
2219
|
+
let flickr;
|
|
2220
|
+
if (process.env.FLICKR_API_KEY)
|
|
2221
|
+
try {
|
|
2222
|
+
flickr = new FlickrSDK(process.env.FLICKR_API_KEY);
|
|
2223
|
+
} catch (e) {
|
|
2224
|
+
throw console.error("Flickr ERROR:", e), new Error(e.message);
|
|
2225
|
+
}
|
|
2226
|
+
async function searchFlickrProvider(db, params) {
|
|
2227
|
+
try {
|
|
2228
|
+
const searchParams = {
|
|
2229
|
+
prompt: params.prompt || ""
|
|
2230
|
+
};
|
|
2231
|
+
if (!flickr)
|
|
2232
|
+
throw console.log("Flickr is not initialized. Check the credentials"), new Error("Flickr is not initialized. Check the credentials");
|
|
2233
|
+
const q = searchParams.prompt, photos = (await flickr.photos.search({
|
|
2234
|
+
text: q,
|
|
2235
|
+
license: validLicensesString,
|
|
2236
|
+
sort: "relevance"
|
|
2237
|
+
}).then((resp) => resp.body)).photos.photo, fetches = photos.reduce(
|
|
2238
|
+
(acc, d) => acc.concat(flickr.photos.getSizes({ photo_id: d.id })),
|
|
2239
|
+
[]
|
|
2240
|
+
), imagesResults = (await Promise.all(fetches).then((results2) => results2)).reduce((acc, d, i) => {
|
|
2241
|
+
const small = d.body.sizes.size.find((s) => s.label === "Small 320");
|
|
2242
|
+
return small && acc.push({
|
|
2243
|
+
id: photos[i].id,
|
|
2244
|
+
source: small.source
|
|
2245
|
+
}), acc;
|
|
2246
|
+
}, []);
|
|
2247
|
+
return {
|
|
2248
|
+
meta: {
|
|
2249
|
+
prompt: stripHTML(searchParams.prompt)
|
|
2250
|
+
},
|
|
2251
|
+
results: imagesResults
|
|
2252
|
+
};
|
|
2253
|
+
} catch (error) {
|
|
2254
|
+
throw console.log(error), new Error("Error in search flickr provider");
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
async function saveFlickrProvider(db, params) {
|
|
2258
|
+
try {
|
|
2259
|
+
const { content_id, image_id } = params, searchParams = {
|
|
2260
|
+
content_id: stripHTML(`${content_id}`) || "",
|
|
2261
|
+
id: stripHTML(`${image_id}`) || ""
|
|
2262
|
+
}, url = `https://flic.kr/p/${Base58.int_to_base58(image_id)}`;
|
|
2263
|
+
if (!flickr)
|
|
2264
|
+
throw new Error("Flickr API Key not configured");
|
|
2265
|
+
const info = await flickr.photos.getInfo({ photo_id: image_id }).then((resp) => resp.body);
|
|
2266
|
+
let newRow;
|
|
2267
|
+
if (info)
|
|
2268
|
+
if (validLicenses.includes(info.photo.license)) {
|
|
2269
|
+
const searchRow = await db.search.findOne({ where: { content_id } }), imageRow = await db.image.findOne({ where: { url } });
|
|
2270
|
+
if (searchRow) {
|
|
2271
|
+
if (imageRow)
|
|
2272
|
+
await db.search.update({ image_id: imageRow.id }, { where: { content_id } });
|
|
2273
|
+
else {
|
|
2274
|
+
const sizeObj = await flickr.photos.getSizes({ photo_id: image_id }).then((resp) => resp.body);
|
|
2275
|
+
let image = sizeObj.sizes.size.find(
|
|
2276
|
+
(d) => parseInt(d.width, 10) >= 1600
|
|
2277
|
+
);
|
|
2278
|
+
if (image || (image = sizeObj.sizes.size.find(
|
|
2279
|
+
(d) => parseInt(d.width, 10) >= 1e3
|
|
2280
|
+
)), image || (image = sizeObj.sizes.size.find(
|
|
2281
|
+
(d) => parseInt(d.width, 10) >= 500
|
|
2282
|
+
)), !image || !image.source)
|
|
2283
|
+
throw new Error("Flickr Source Error, try another image.");
|
|
2284
|
+
const imageData = await axios.get(image.source, { responseType: "arraybuffer" }).then((d) => d.data), currentPhotoLicense = (await flickr.photos.licenses.getInfo().then((resp) => resp.body.licenses.license)).find((l) => l.id === parseInt(info.photo.license, 10)), payload = {
|
|
2285
|
+
url,
|
|
2286
|
+
author: info.photo.owner.realname || info.photo.owner.username,
|
|
2287
|
+
license: currentPhotoLicense ? `${currentPhotoLicense.name}: ${currentPhotoLicense.url}` : ""
|
|
2288
|
+
}, newImage = await db.image.create(payload);
|
|
2289
|
+
await db.image_content.destroy({ where: { id: newImage.id } });
|
|
2290
|
+
const contentPayload = locales$3.map((locale) => ({
|
|
2291
|
+
id: newImage.id,
|
|
2292
|
+
locale,
|
|
2293
|
+
meta: info.photo.title._content
|
|
2294
|
+
}));
|
|
2295
|
+
await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
|
|
2296
|
+
}
|
|
2297
|
+
const newRow2 = await db.search.findOne({
|
|
2298
|
+
where: { content_id },
|
|
2299
|
+
include: imageQueryThumbOnly
|
|
2300
|
+
});
|
|
2301
|
+
newRow2 && newRow2.image && (newRow2.image.thumb = Boolean(newRow2.image.thumb));
|
|
2302
|
+
} else
|
|
2303
|
+
throw new Error("Error updating Search");
|
|
2304
|
+
} else
|
|
2305
|
+
throw new Error("Bad License");
|
|
2306
|
+
else
|
|
2307
|
+
throw new Error("Malformed URL");
|
|
2308
|
+
return {
|
|
2309
|
+
meta: __spreadValues$8({}, searchParams),
|
|
2310
|
+
results: newRow
|
|
2311
|
+
};
|
|
2312
|
+
} catch (error) {
|
|
2313
|
+
throw console.log(error), new Error("Error in save flickr provider");
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
function endpoint(method, path, handler) {
|
|
2317
|
+
return { method, path, handler };
|
|
2318
|
+
}
|
|
2319
|
+
function parseFiniteNumber(value) {
|
|
2320
|
+
const num = Number.parseInt(`${value || ""}`, 10);
|
|
2321
|
+
if (Number.isNaN(num) || !Number.isFinite(num))
|
|
2322
|
+
throw new BackendError(400, `Invalid numeric parameter: ${value}`);
|
|
2323
|
+
return num;
|
|
2324
|
+
}
|
|
2325
|
+
function normalizeList(value) {
|
|
2326
|
+
return value == null || value === "" ? [] : value.toString().split(",");
|
|
2327
|
+
}
|
|
2328
|
+
const { localeDefault: localeDefault$1 } = getLocales();
|
|
2329
|
+
function endpointMemberFactory(operations) {
|
|
2330
|
+
const {
|
|
2331
|
+
readMember,
|
|
2332
|
+
searchMember,
|
|
2333
|
+
updateMember,
|
|
2334
|
+
readMemberImage
|
|
2335
|
+
} = operations;
|
|
2336
|
+
return [
|
|
2337
|
+
endpoint("GET", "read/members", async (req) => {
|
|
2338
|
+
const params = parseReadMemberParams(req.query);
|
|
2339
|
+
if (params.ids.length > 1 && params.slugs.length > 1)
|
|
2340
|
+
throw new BackendError(400, "Both 'ids' and 'slugs' are filled. Pick one.");
|
|
2341
|
+
if (params.ids.length === 0 && params.slugs.length === 0)
|
|
2342
|
+
throw new BackendError(400, "Params 'ids' and 'slugs' are missing. Fill one.");
|
|
2343
|
+
if ((params.mode === "ids" ? params.ids.length : params.slugs.length) > 5)
|
|
2344
|
+
throw new BackendError(400, "Too many 'ids' and 'slugs' in the request. Try with less than 5.");
|
|
2345
|
+
return readMember(params);
|
|
2346
|
+
}),
|
|
2347
|
+
endpoint("GET", "search/members", (req) => {
|
|
2348
|
+
const params = parseSearchMemberParams(req.query);
|
|
2349
|
+
return searchMember(params);
|
|
2350
|
+
}),
|
|
2351
|
+
endpoint("POST", "update/member", (req) => {
|
|
2352
|
+
const { body } = req;
|
|
2353
|
+
return updateMember(body);
|
|
2354
|
+
}),
|
|
2355
|
+
endpoint("GET", "member/image.png", (req) => {
|
|
2356
|
+
const size = normalizeList(req.query.size)[0];
|
|
2357
|
+
return readMemberImage({
|
|
2358
|
+
member: parseFiniteNumber(req.query.member),
|
|
2359
|
+
size: size && size === "large" ? "large" : "thumb"
|
|
2360
|
+
});
|
|
2361
|
+
})
|
|
2362
|
+
];
|
|
2363
|
+
}
|
|
2364
|
+
function parseReadMemberParams(query) {
|
|
2365
|
+
const ids = normalizeList(query.ids).map(parseFiniteNumber), locale = normalizeList(query.locale)[0] || localeDefault$1 || "en", localeIsAll = locale === "all";
|
|
2366
|
+
return {
|
|
2367
|
+
all: localeIsAll,
|
|
2368
|
+
ids,
|
|
2369
|
+
locale: localeIsAll ? localeDefault$1 : locale,
|
|
2370
|
+
mode: ids.length > 0 ? "ids" : "slugs",
|
|
2371
|
+
slugs: normalizeList(query.slugs).map((token) => {
|
|
2372
|
+
const [variantSlug, memberSlug] = token.split("/");
|
|
2373
|
+
return { variantSlug, memberSlug };
|
|
2374
|
+
})
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
function parseSearchMemberParams(query) {
|
|
2378
|
+
var _a;
|
|
2379
|
+
const locale = normalizeList(query.locale)[0] || localeDefault$1 || "en", localeIsAll = locale === "all", format = normalizeList(query.format)[0], formatIsNested = format ? format === "nested" : localeIsAll;
|
|
2380
|
+
return {
|
|
2381
|
+
query: normalizeList(query.query || query.q)[0] || "",
|
|
2382
|
+
locale: localeIsAll ? localeDefault$1 : locale,
|
|
2383
|
+
limit: (_a = normalizeList(query.limit).map(parseFiniteNumber)[0]) != null ? _a : 5,
|
|
2384
|
+
format: formatIsNested ? "nested" : "plain",
|
|
2385
|
+
includes: yn(query.includes, { default: !0 }),
|
|
2386
|
+
visible: yn(query.visible, { default: !0 }),
|
|
2387
|
+
noImage: yn(query.noImage, { default: !1 }),
|
|
2388
|
+
variant: normalizeList(query.variant).map(parseFiniteNumber),
|
|
2389
|
+
dimension: normalizeList(query.dimension).map(parseFiniteNumber),
|
|
2390
|
+
report: normalizeList(query.report).map(parseFiniteNumber),
|
|
2391
|
+
all: localeIsAll,
|
|
2392
|
+
sort: normalizeList(query.sort)[0],
|
|
2393
|
+
direction: normalizeList(query.direction)[0]
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
var __defProp$7 = Object.defineProperty, __defProps$5 = Object.defineProperties, __getOwnPropDescs$5 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$8 = Object.getOwnPropertySymbols, __hasOwnProp$8 = Object.prototype.hasOwnProperty, __propIsEnum$8 = Object.prototype.propertyIsEnumerable, __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$7 = (a, b) => {
|
|
2397
|
+
for (var prop in b || (b = {}))
|
|
2398
|
+
__hasOwnProp$8.call(b, prop) && __defNormalProp$7(a, prop, b[prop]);
|
|
2399
|
+
if (__getOwnPropSymbols$8)
|
|
2400
|
+
for (var prop of __getOwnPropSymbols$8(b))
|
|
2401
|
+
__propIsEnum$8.call(b, prop) && __defNormalProp$7(a, prop, b[prop]);
|
|
2402
|
+
return a;
|
|
2403
|
+
}, __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
|
|
2404
|
+
async function searchLocalProvider(db, params) {
|
|
2405
|
+
const dbSearchMember = dbSearchMemberFactory(db), searchParams = parseSearchMemberParams({
|
|
2406
|
+
query: params.prompt,
|
|
2407
|
+
limit: "50",
|
|
2408
|
+
visible: "false"
|
|
2409
|
+
}), imagesResults = (await dbSearchMember(searchParams)).results.filter((member) => member.image_id).map((member) => ({
|
|
2410
|
+
id: member.image_id,
|
|
2411
|
+
source: `/api/cms/member/image.png?member=${member.content_id}&size=thumb`
|
|
2412
|
+
}));
|
|
2413
|
+
return {
|
|
2414
|
+
meta: {
|
|
2415
|
+
prompt: stripHTML(searchParams.query)
|
|
2416
|
+
},
|
|
2417
|
+
results: imagesResults
|
|
2418
|
+
};
|
|
2419
|
+
}
|
|
2420
|
+
async function saveLocalProvider(db, params) {
|
|
2421
|
+
const { search: Search } = db, { content_id, image_id } = params;
|
|
2422
|
+
await Search.update({ image_id }, { where: { content_id } });
|
|
2423
|
+
const item = await Search.findOne({
|
|
2424
|
+
where: { content_id },
|
|
2425
|
+
include: imageQueryThumbOnly
|
|
2426
|
+
}).then((item2) => {
|
|
2427
|
+
if (!item2)
|
|
2428
|
+
return null;
|
|
2429
|
+
const plainItem = item2.toJSON();
|
|
2430
|
+
return __spreadProps$5(__spreadValues$7({}, plainItem), {
|
|
2431
|
+
image: __spreadProps$5(__spreadValues$7({}, item2.image.toJSON()), {
|
|
2432
|
+
thumb: !!item2.image.thumb
|
|
2433
|
+
})
|
|
2434
|
+
});
|
|
2435
|
+
});
|
|
2436
|
+
return {
|
|
2437
|
+
meta: {
|
|
2438
|
+
id: image_id,
|
|
2439
|
+
content_id
|
|
2440
|
+
},
|
|
2441
|
+
results: item
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
var __defProp$6 = Object.defineProperty, __getOwnPropSymbols$7 = Object.getOwnPropertySymbols, __hasOwnProp$7 = Object.prototype.hasOwnProperty, __propIsEnum$7 = Object.prototype.propertyIsEnumerable, __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$6 = (a, b) => {
|
|
2445
|
+
for (var prop in b || (b = {}))
|
|
2446
|
+
__hasOwnProp$7.call(b, prop) && __defNormalProp$6(a, prop, b[prop]);
|
|
2447
|
+
if (__getOwnPropSymbols$7)
|
|
2448
|
+
for (var prop of __getOwnPropSymbols$7(b))
|
|
2449
|
+
__propIsEnum$7.call(b, prop) && __defNormalProp$6(a, prop, b[prop]);
|
|
2450
|
+
return a;
|
|
2451
|
+
};
|
|
2452
|
+
const { locales: locales$2 } = getLocales();
|
|
2453
|
+
let unsplash;
|
|
2454
|
+
if (process.env.UNSPLASH_API_KEY)
|
|
2455
|
+
try {
|
|
2456
|
+
unsplash = createApi({
|
|
2457
|
+
accessKey: process.env.UNSPLASH_API_KEY
|
|
2458
|
+
});
|
|
2459
|
+
} catch (e) {
|
|
2460
|
+
throw console.error("Unsplash error:", e), new Error(e.message);
|
|
2461
|
+
}
|
|
2462
|
+
async function searchUnsplashProvider(db, params) {
|
|
2463
|
+
try {
|
|
2464
|
+
const searchParams = {
|
|
2465
|
+
prompt: params.prompt || ""
|
|
2466
|
+
};
|
|
2467
|
+
if (!unsplash)
|
|
2468
|
+
throw new Error("Unsplash API Key not configured");
|
|
2469
|
+
const q = searchParams.prompt, imagesResults = (await unsplash.search.getPhotos({
|
|
2470
|
+
query: q,
|
|
2471
|
+
perPage: 30
|
|
2472
|
+
}).then((resp) => resp.response.results)).map((image) => ({
|
|
2473
|
+
id: image.id,
|
|
2474
|
+
source: image.urls.thumb
|
|
2475
|
+
}));
|
|
2476
|
+
return {
|
|
2477
|
+
meta: {
|
|
2478
|
+
prompt: stripHTML(searchParams.prompt)
|
|
2479
|
+
},
|
|
2480
|
+
results: imagesResults
|
|
2481
|
+
};
|
|
2482
|
+
} catch (error) {
|
|
2483
|
+
throw console.log(error), new Error("Error in search unsplash provider");
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
async function saveUnsplashProvider(db, params) {
|
|
2487
|
+
try {
|
|
2488
|
+
const { content_id, image_id } = params, saveParams = {
|
|
2489
|
+
content_id: stripHTML(`${content_id}`) || "",
|
|
2490
|
+
id: stripHTML(`${image_id}`) || ""
|
|
2491
|
+
};
|
|
2492
|
+
if (!unsplash)
|
|
2493
|
+
throw console.log("Unsplash is not initialized. Check the credentials"), new Error("Unsplash is not initialized. Check the credentials");
|
|
2494
|
+
const info = await unsplash.photos.get({ photoId: image_id }).then((resp) => resp.response);
|
|
2495
|
+
let newRow;
|
|
2496
|
+
if (info) {
|
|
2497
|
+
const searchRow = await db.search.findOne({ where: { content_id } }), url = info.links.html, imageRow = await db.image.findOne({ where: { url } });
|
|
2498
|
+
if (searchRow) {
|
|
2499
|
+
if (imageRow)
|
|
2500
|
+
await db.search.update({ image_id: imageRow.id }, { where: { content_id } });
|
|
2501
|
+
else {
|
|
2502
|
+
const imageData = await axios.get(info.urls.full, { responseType: "arraybuffer" }).then((d) => d.data), payload = {
|
|
2503
|
+
url,
|
|
2504
|
+
author: info.user.name || info.user.username,
|
|
2505
|
+
license: "Free Unsplash license: https://unsplash.com/license"
|
|
2506
|
+
}, newImage = await db.image.create(payload);
|
|
2507
|
+
await db.image_content.destroy({ where: { id: newImage.id } });
|
|
2508
|
+
const contentPayload = locales$2.map((locale) => ({
|
|
2509
|
+
id: newImage.id,
|
|
2510
|
+
locale,
|
|
2511
|
+
meta: info.description || info.alt_description
|
|
2512
|
+
}));
|
|
2513
|
+
await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
|
|
2514
|
+
}
|
|
2515
|
+
const newRow2 = await db.search.findOne({
|
|
2516
|
+
where: { content_id },
|
|
2517
|
+
include: imageQueryThumbOnly
|
|
2518
|
+
});
|
|
2519
|
+
newRow2 && newRow2.image && (newRow2.image.thumb = Boolean(newRow2.image.thumb));
|
|
2520
|
+
} else
|
|
2521
|
+
throw new Error("Error updating Search");
|
|
2522
|
+
} else
|
|
2523
|
+
throw new Error("Malformed URL");
|
|
2524
|
+
return {
|
|
2525
|
+
meta: __spreadValues$6({}, saveParams),
|
|
2526
|
+
results: newRow
|
|
2527
|
+
};
|
|
2528
|
+
} catch (error) {
|
|
2529
|
+
throw console.log(error), new Error("Error in save unsplash provider");
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
var __defProp$5 = Object.defineProperty, __getOwnPropSymbols$6 = Object.getOwnPropertySymbols, __hasOwnProp$6 = Object.prototype.hasOwnProperty, __propIsEnum$6 = Object.prototype.propertyIsEnumerable, __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$5 = (a, b) => {
|
|
2533
|
+
for (var prop in b || (b = {}))
|
|
2534
|
+
__hasOwnProp$6.call(b, prop) && __defNormalProp$5(a, prop, b[prop]);
|
|
2535
|
+
if (__getOwnPropSymbols$6)
|
|
2536
|
+
for (var prop of __getOwnPropSymbols$6(b))
|
|
2537
|
+
__propIsEnum$6.call(b, prop) && __defNormalProp$5(a, prop, b[prop]);
|
|
2538
|
+
return a;
|
|
2539
|
+
};
|
|
2540
|
+
const { locales: locales$1 } = getLocales();
|
|
2541
|
+
async function saveUploadProvider(db, params) {
|
|
2542
|
+
try {
|
|
2543
|
+
const { content_id, image_source, files } = params, saveParams = {
|
|
2544
|
+
content_id: stripHTML(`${content_id}`) || ""
|
|
2545
|
+
};
|
|
2546
|
+
if (await db.search.findOne({ where: { content_id } }) && files) {
|
|
2547
|
+
const imageData = await fs.readFileSync(files.file.path), payload = {
|
|
2548
|
+
url: image_source,
|
|
2549
|
+
author: "",
|
|
2550
|
+
license: ""
|
|
2551
|
+
}, newImage = await db.image.create(payload);
|
|
2552
|
+
await db.image_content.destroy({ where: { id: newImage.id } });
|
|
2553
|
+
const contentPayload = locales$1.map((locale) => ({
|
|
2554
|
+
id: newImage.id,
|
|
2555
|
+
locale,
|
|
2556
|
+
meta: ""
|
|
2557
|
+
}));
|
|
2558
|
+
await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
|
|
2559
|
+
}
|
|
2560
|
+
const newRow = await db.search.findOne({
|
|
2561
|
+
where: { content_id },
|
|
2562
|
+
include: imageQueryThumbOnly
|
|
2563
|
+
});
|
|
2564
|
+
return newRow && newRow.image && (newRow.image.thumb = Boolean(newRow.image.thumb)), {
|
|
2565
|
+
meta: __spreadValues$5({}, saveParams),
|
|
2566
|
+
results: newRow
|
|
2567
|
+
};
|
|
2568
|
+
} catch (error) {
|
|
2569
|
+
throw console.log(error), new Error("Error in save upload provider");
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
const saveProviders = {
|
|
2573
|
+
local: saveLocalProvider,
|
|
2574
|
+
flickr: saveFlickrProvider,
|
|
2575
|
+
unsplash: saveUnsplashProvider,
|
|
2576
|
+
upload: saveUploadProvider
|
|
2577
|
+
};
|
|
2578
|
+
function dbImageSaveFactory(db, provider) {
|
|
2579
|
+
const saveProvider = saveProviders[provider];
|
|
2580
|
+
if (!saveProvider)
|
|
2581
|
+
throw new BackendError(500, `Wrong provider dbImageSaveFactory.ts: ${provider}`);
|
|
2582
|
+
return resultWrapper((params) => saveProvider(db, params));
|
|
2583
|
+
}
|
|
2584
|
+
const searchProviders = {
|
|
2585
|
+
local: searchLocalProvider,
|
|
2586
|
+
flickr: searchFlickrProvider,
|
|
2587
|
+
unsplash: searchUnsplashProvider
|
|
2588
|
+
};
|
|
2589
|
+
function dbImageSearchFactory(db, provider) {
|
|
2590
|
+
const searchProvider = searchProviders[provider];
|
|
2591
|
+
if (!searchProvider)
|
|
2592
|
+
throw new BackendError(500, `Wrong provider dbImageSearchFactory.ts: ${provider}`);
|
|
2593
|
+
return resultWrapper((params) => searchProvider(db, params));
|
|
2594
|
+
}
|
|
2595
|
+
var __defProp$4 = Object.defineProperty, __defProps$4 = Object.defineProperties, __getOwnPropDescs$4 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$5 = Object.getOwnPropertySymbols, __hasOwnProp$5 = Object.prototype.hasOwnProperty, __propIsEnum$5 = Object.prototype.propertyIsEnumerable, __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$4 = (a, b) => {
|
|
2596
|
+
for (var prop in b || (b = {}))
|
|
2597
|
+
__hasOwnProp$5.call(b, prop) && __defNormalProp$4(a, prop, b[prop]);
|
|
2598
|
+
if (__getOwnPropSymbols$5)
|
|
2599
|
+
for (var prop of __getOwnPropSymbols$5(b))
|
|
2600
|
+
__propIsEnum$5.call(b, prop) && __defNormalProp$4(a, prop, b[prop]);
|
|
2601
|
+
return a;
|
|
2602
|
+
}, __spreadProps$4 = (a, b) => __defProps$4(a, __getOwnPropDescs$4(b));
|
|
2603
|
+
function dbReadMetadataFactory(db) {
|
|
2604
|
+
const { report: Report } = db;
|
|
2605
|
+
return dbReadMetadata;
|
|
2606
|
+
async function dbReadMetadata(_params) {
|
|
2607
|
+
return {
|
|
2608
|
+
data: (await Report.findAll({
|
|
2609
|
+
attributes: ["id", "name"],
|
|
2610
|
+
include: [{
|
|
2611
|
+
attributes: ["id", "name"],
|
|
2612
|
+
association: "dimensions",
|
|
2613
|
+
separate: !0,
|
|
2614
|
+
include: [
|
|
2615
|
+
{
|
|
2616
|
+
attributes: ["id", "name", "slug"],
|
|
2617
|
+
association: "variants",
|
|
2618
|
+
separate: !0
|
|
2619
|
+
}
|
|
2620
|
+
]
|
|
2621
|
+
}]
|
|
2622
|
+
})).map((report) => __spreadProps$4(__spreadValues$4({}, report.toJSON()), {
|
|
2623
|
+
mode: report.dimensions.length === 1 ? REPORT_MODES.UNILATERAL : REPORT_MODES.MULTILATERAL
|
|
2624
|
+
}))
|
|
2625
|
+
};
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
function dbRegenerateSearchFactory(db) {
|
|
2629
|
+
return async (_params) => (await getSearchIndexByLocale(db, !0), { error: !1 });
|
|
2630
|
+
}
|
|
2631
|
+
var __defProp$3 = Object.defineProperty, __defProps$3 = Object.defineProperties, __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$4 = Object.getOwnPropertySymbols, __hasOwnProp$4 = Object.prototype.hasOwnProperty, __propIsEnum$4 = Object.prototype.propertyIsEnumerable, __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$3 = (a, b) => {
|
|
2632
|
+
for (var prop in b || (b = {}))
|
|
2633
|
+
__hasOwnProp$4.call(b, prop) && __defNormalProp$3(a, prop, b[prop]);
|
|
2634
|
+
if (__getOwnPropSymbols$4)
|
|
2635
|
+
for (var prop of __getOwnPropSymbols$4(b))
|
|
2636
|
+
__propIsEnum$4.call(b, prop) && __defNormalProp$3(a, prop, b[prop]);
|
|
2637
|
+
return a;
|
|
2638
|
+
}, __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
|
|
2639
|
+
const { locales, localeDefault } = getLocales(), addProfilesData = (items, metadata) => {
|
|
2640
|
+
if (!items)
|
|
2641
|
+
return [];
|
|
2642
|
+
let profileResults = [];
|
|
2643
|
+
return metadata.forEach((report) => {
|
|
2644
|
+
const results = items.filter((result) => result.metadata.report.id === report.id);
|
|
2645
|
+
if (results.length > 0)
|
|
2646
|
+
if (report.mode === REPORT_MODES.UNILATERAL) {
|
|
2647
|
+
const dimension = report.dimensions[0];
|
|
2648
|
+
dimension.variants.forEach((variant) => {
|
|
2649
|
+
const members = results.filter(
|
|
2650
|
+
(result) => result.metadata.dimension.id === dimension.id && result.metadata.variant.id === variant.id
|
|
2651
|
+
);
|
|
2652
|
+
members.length > 0 && (profileResults = profileResults.concat(members.map((member) => ({
|
|
2653
|
+
path: `/${variant.slug}/${member.slug}`,
|
|
2654
|
+
name: member.name,
|
|
2655
|
+
report: {
|
|
2656
|
+
id: report.id,
|
|
2657
|
+
name: report.name,
|
|
2658
|
+
mode: report.mode
|
|
2659
|
+
},
|
|
2660
|
+
members: [member],
|
|
2661
|
+
id: `r-${report.id}-${[member].map((m) => `${m.id}`).join("-")}`
|
|
2662
|
+
}))));
|
|
2663
|
+
});
|
|
2664
|
+
} else
|
|
2665
|
+
report.mode;
|
|
2666
|
+
}), profileResults;
|
|
2667
|
+
}, formatNested = (items, metadata) => {
|
|
2668
|
+
if (!items)
|
|
2669
|
+
return [];
|
|
2670
|
+
let report, dimension, variant;
|
|
2671
|
+
return items.map((item) => (report = __spreadValues$3({}, metadata.find((r) => r.id === item.report_id)), dimension = __spreadValues$3({}, report.dimensions.find((d) => d.id === item.dimension_id)), variant = __spreadValues$3({}, dimension.variants.find((v) => v.id === item.variant_id)), delete report.dimensions, delete dimension.variants, {
|
|
2672
|
+
name: item.name,
|
|
2673
|
+
confidence: item.zvalue,
|
|
2674
|
+
metadata: {
|
|
2675
|
+
id: item.id,
|
|
2676
|
+
slug: item.slug,
|
|
2677
|
+
report,
|
|
2678
|
+
dimension,
|
|
2679
|
+
variant
|
|
2680
|
+
},
|
|
2681
|
+
id: item.content_id,
|
|
2682
|
+
slug: item.slug
|
|
2683
|
+
}));
|
|
2684
|
+
};
|
|
2685
|
+
function dbSearchReportFactory(db) {
|
|
2686
|
+
const dbSearchMember = dbSearchMemberFactory(db), dbReadMetadata = dbReadMetadataFactory(db);
|
|
2687
|
+
return dbSearchReport;
|
|
2688
|
+
async function dbSearchReport(params) {
|
|
2689
|
+
const format = params.format || "results", locale = locales.includes(params.locale) ? params.locale : localeDefault, memberSearchResponse = await dbSearchMember(__spreadProps$3(__spreadValues$3({}, params), {
|
|
2690
|
+
format: "plain",
|
|
2691
|
+
locale: stripHTML(locale),
|
|
2692
|
+
visible: !0
|
|
2693
|
+
}));
|
|
2694
|
+
let reportSearchResults = memberSearchResponse.results ? memberSearchResponse.results : [], tempResults;
|
|
2695
|
+
const metadata = (await dbReadMetadata()).data;
|
|
2696
|
+
switch (format) {
|
|
2697
|
+
case "profiles":
|
|
2698
|
+
tempResults = formatNested(reportSearchResults, metadata), reportSearchResults = addProfilesData(tempResults, metadata);
|
|
2699
|
+
break;
|
|
2700
|
+
}
|
|
2701
|
+
return {
|
|
2702
|
+
meta: __spreadProps$3(__spreadValues$3({}, memberSearchResponse.meta), {
|
|
2703
|
+
format
|
|
2704
|
+
}),
|
|
2705
|
+
results: reportSearchResults
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
function dbUrlProxyFactory() {
|
|
2710
|
+
return async (request) => {
|
|
2711
|
+
var _a;
|
|
2712
|
+
const config = typeof request == "string" ? { url: request } : request;
|
|
2713
|
+
try {
|
|
2714
|
+
const response = await axios.request(config);
|
|
2715
|
+
return {
|
|
2716
|
+
ok: !0,
|
|
2717
|
+
status: response.status,
|
|
2718
|
+
data: response.data
|
|
2719
|
+
};
|
|
2720
|
+
} catch (err) {
|
|
2721
|
+
throw new BackendError(((_a = err.response) == null ? void 0 : _a.status) || 500, err.message);
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
var __defProp$2 = Object.defineProperty, __defProps$2 = Object.defineProperties, __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$3 = Object.getOwnPropertySymbols, __hasOwnProp$3 = Object.prototype.hasOwnProperty, __propIsEnum$3 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$2 = (a, b) => {
|
|
2726
|
+
for (var prop in b || (b = {}))
|
|
2727
|
+
__hasOwnProp$3.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
2728
|
+
if (__getOwnPropSymbols$3)
|
|
2729
|
+
for (var prop of __getOwnPropSymbols$3(b))
|
|
2730
|
+
__propIsEnum$3.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
2731
|
+
return a;
|
|
2732
|
+
}, __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
|
|
2733
|
+
function useDatabaseApi(_, __, api) {
|
|
2734
|
+
return getDB().then((dbModels) => {
|
|
2735
|
+
Object.assign(api, apiFactory(dbModels));
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2738
|
+
function apiFactory(dbModels) {
|
|
2739
|
+
return __spreadProps$2(__spreadValues$2({}, dbEntityFactory(dbModels)), {
|
|
2740
|
+
searchReport: resultWrapper(dbSearchReportFactory(dbModels)),
|
|
2741
|
+
readMetadata: resultWrapper(dbReadMetadataFactory(dbModels)),
|
|
2742
|
+
regenerateSearch: resultWrapper(dbRegenerateSearchFactory(dbModels)),
|
|
2743
|
+
imageFlickrSearch: dbImageSearchFactory(dbModels, "flickr"),
|
|
2744
|
+
imageLocalSearch: dbImageSearchFactory(dbModels, "local"),
|
|
2745
|
+
imageUnsplashSearch: dbImageSearchFactory(dbModels, "unsplash"),
|
|
2746
|
+
imageFlickrSave: dbImageSaveFactory(dbModels, "flickr"),
|
|
2747
|
+
imageLocalSave: dbImageSaveFactory(dbModels, "local"),
|
|
2748
|
+
imageUnsplashSave: dbImageSaveFactory(dbModels, "unsplash"),
|
|
2749
|
+
imageUploadSave: dbImageSaveFactory(dbModels, "upload"),
|
|
2750
|
+
urlProxy: dbUrlProxyFactory()
|
|
2751
|
+
});
|
|
2752
|
+
}
|
|
2753
|
+
var __defProp$1 = Object.defineProperty, __defProps$1 = Object.defineProperties, __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
|
|
2754
|
+
for (var prop in b || (b = {}))
|
|
2755
|
+
__hasOwnProp$2.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
2756
|
+
if (__getOwnPropSymbols$2)
|
|
2757
|
+
for (var prop of __getOwnPropSymbols$2(b))
|
|
2758
|
+
__propIsEnum$2.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
2759
|
+
return a;
|
|
2760
|
+
}, __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
2761
|
+
async function parseBody(req) {
|
|
2762
|
+
const form = new formidable.IncomingForm();
|
|
2763
|
+
form.encoding = "utf-8";
|
|
2764
|
+
const bodyData = await new Promise((resolve, reject) => {
|
|
2765
|
+
form.parse(req, (err, fields, files) => {
|
|
2766
|
+
if (err) {
|
|
2767
|
+
reject(err);
|
|
2768
|
+
return;
|
|
2769
|
+
}
|
|
2770
|
+
resolve({ fields, files });
|
|
2771
|
+
});
|
|
2772
|
+
});
|
|
2773
|
+
return __spreadProps$1(__spreadValues$1({}, bodyData.fields), {
|
|
2774
|
+
files: bodyData.files
|
|
2775
|
+
});
|
|
2776
|
+
}
|
|
2777
|
+
function endpointCRUDFactory(api, entity) {
|
|
2778
|
+
const crudCreate = pickMethod(api, "create", entity), crudRead = pickMethod(api, "read", entity), crudUpdate = pickMethod(api, "update", entity), crudDelete = pickMethod(api, "delete", entity);
|
|
2779
|
+
return [
|
|
2780
|
+
endpoint("POST", `create/${entity}`, (req) => {
|
|
2781
|
+
const { body } = req;
|
|
2782
|
+
return crudCreate(body);
|
|
2783
|
+
}),
|
|
2784
|
+
endpoint("GET", `read/${entity}`, (req) => {
|
|
2785
|
+
const params = req.query, id = normalizeList(params.id).map(parseFiniteNumber);
|
|
2786
|
+
return crudRead({ id, include: yn(params.include) });
|
|
2787
|
+
}),
|
|
2788
|
+
endpoint("POST", `update/${entity}`, (req) => {
|
|
2789
|
+
const { body } = req;
|
|
2790
|
+
return crudUpdate(body);
|
|
2791
|
+
}),
|
|
2792
|
+
endpoint("DELETE", `delete/${entity}`, (req) => {
|
|
2793
|
+
const id = parseFiniteNumber(req.body.id);
|
|
2794
|
+
return crudDelete(id);
|
|
2795
|
+
})
|
|
2796
|
+
];
|
|
2797
|
+
}
|
|
2798
|
+
function endpointVariantCRUDFactory(api) {
|
|
2799
|
+
const { validateVariantSlug } = api;
|
|
2800
|
+
return [
|
|
2801
|
+
...endpointCRUDFactory(api, "variant"),
|
|
2802
|
+
endpoint("GET", "validate/variant", (req) => {
|
|
2803
|
+
const params = req.query, dimension = parseFiniteNumber(params.dimension);
|
|
2804
|
+
return validateVariantSlug({ dimension, slug: slugify(params.slug) });
|
|
2805
|
+
})
|
|
2806
|
+
];
|
|
2807
|
+
}
|
|
2808
|
+
function endpointImageSaveFactory(operations, provider) {
|
|
2809
|
+
const saveMethodKey = `image${capitalize(provider)}Save`, saveMethod = operations[saveMethodKey];
|
|
2810
|
+
return endpoint("POST", `images/save/${provider}`, (req) => {
|
|
2811
|
+
const params = req.body;
|
|
2812
|
+
if (!params.content_id)
|
|
2813
|
+
throw new BackendError(400, "Missing 'content_id' parameter.");
|
|
2814
|
+
if (!params.image_id)
|
|
2815
|
+
throw new BackendError(400, "Missing 'image_id' parameter.");
|
|
2816
|
+
return saveMethod(params);
|
|
2817
|
+
});
|
|
2818
|
+
}
|
|
2819
|
+
function endpointImageSearchFactory(operations, provider) {
|
|
2820
|
+
const searchMethodKey = `image${capitalize(provider)}Search`, searchMethod = operations[searchMethodKey];
|
|
2821
|
+
return endpoint("GET", `images/search/${provider}`, async (req) => {
|
|
2822
|
+
const prompt = normalizeList(req.query.prompt)[0];
|
|
2823
|
+
if (!prompt)
|
|
2824
|
+
throw new BackendError(400, "Empty 'prompt' param.");
|
|
2825
|
+
return searchMethod({ prompt });
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
function endpointReadMetadataFactory(operations) {
|
|
2829
|
+
const { readMetadata } = operations;
|
|
2830
|
+
return endpoint("GET", "read/metadata", () => readMetadata({}));
|
|
2831
|
+
}
|
|
2832
|
+
function endpointRegenerateSearchFactory(operations) {
|
|
2833
|
+
const { regenerateSearch } = operations;
|
|
2834
|
+
return endpoint("POST", "search/regenerate", () => regenerateSearch(void 0));
|
|
2835
|
+
}
|
|
2836
|
+
var __defProp = Object.defineProperty, __defProps = Object.defineProperties, __getOwnPropDescs = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
|
|
2837
|
+
for (var prop in b || (b = {}))
|
|
2838
|
+
__hasOwnProp$1.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
2839
|
+
if (__getOwnPropSymbols$1)
|
|
2840
|
+
for (var prop of __getOwnPropSymbols$1(b))
|
|
2841
|
+
__propIsEnum$1.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
2842
|
+
return a;
|
|
2843
|
+
}, __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2844
|
+
function endpointSearchReportFactory(operations) {
|
|
2845
|
+
const { searchReport } = operations;
|
|
2846
|
+
return endpoint("GET", "search/reports", (req) => {
|
|
2847
|
+
const params = parseSearchReportParams(req.query);
|
|
2848
|
+
return searchReport(params);
|
|
2849
|
+
});
|
|
2850
|
+
}
|
|
2851
|
+
function parseSearchReportParams(query) {
|
|
2852
|
+
return __spreadProps(__spreadValues({}, parseSearchMemberParams(query)), {
|
|
2853
|
+
format: normalizeList(query.format)[0]
|
|
2854
|
+
});
|
|
2855
|
+
}
|
|
2856
|
+
function endpointUrlProxyFactory(operations) {
|
|
2857
|
+
const { urlProxy } = operations;
|
|
2858
|
+
return endpoint("GET", "url/proxy", (req) => {
|
|
2859
|
+
const { url, method } = req.query;
|
|
2860
|
+
return console.log("endpointUrlProxy", url), urlProxy({
|
|
2861
|
+
url: normalizeList(url)[0],
|
|
2862
|
+
method: normalizeList(method)[0] === "POST" ? "POST" : "GET"
|
|
2863
|
+
});
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __objRest = (source, exclude) => {
|
|
2867
|
+
var target = {};
|
|
2868
|
+
for (var prop in source)
|
|
2869
|
+
__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
|
|
2870
|
+
if (source != null && __getOwnPropSymbols)
|
|
2871
|
+
for (var prop of __getOwnPropSymbols(source))
|
|
2872
|
+
exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop) && (target[prop] = source[prop]);
|
|
2873
|
+
return target;
|
|
2874
|
+
};
|
|
2875
|
+
const verbose = getLogging();
|
|
2876
|
+
function endpointKey(method, path) {
|
|
2877
|
+
return `${method.toUpperCase()} ${path.toLowerCase()}`;
|
|
2878
|
+
}
|
|
2879
|
+
function getEndpointMap(db) {
|
|
2880
|
+
const api = apiFactory(db);
|
|
2881
|
+
return Object.fromEntries([
|
|
2882
|
+
...endpointCRUDFactory(api, "block"),
|
|
2883
|
+
...endpointCRUDFactory(api, "dimension"),
|
|
2884
|
+
...endpointCRUDFactory(api, "formatter"),
|
|
2885
|
+
...endpointCRUDFactory(api, "report"),
|
|
2886
|
+
...endpointCRUDFactory(api, "section"),
|
|
2887
|
+
...endpointVariantCRUDFactory(api),
|
|
2888
|
+
...endpointMemberFactory(api),
|
|
2889
|
+
endpointSearchReportFactory(api),
|
|
2890
|
+
endpointReadMetadataFactory(api),
|
|
2891
|
+
endpointRegenerateSearchFactory(api),
|
|
2892
|
+
endpointImageSaveFactory(api, "flickr"),
|
|
2893
|
+
endpointImageSaveFactory(api, "local"),
|
|
2894
|
+
endpointImageSaveFactory(api, "unsplash"),
|
|
2895
|
+
endpointImageSaveFactory(api, "upload"),
|
|
2896
|
+
endpointImageSearchFactory(api, "flickr"),
|
|
2897
|
+
endpointImageSearchFactory(api, "local"),
|
|
2898
|
+
endpointImageSearchFactory(api, "unsplash"),
|
|
2899
|
+
endpointUrlProxyFactory(api)
|
|
2900
|
+
].map(({ handler, method, path }) => [endpointKey(method, path), handler]));
|
|
2901
|
+
}
|
|
2902
|
+
const endpointMap = getDB().then(getEndpointMap);
|
|
2903
|
+
async function endpointNextJsHandlerFactory(req, res) {
|
|
2904
|
+
await NextCors(req, res, {
|
|
2905
|
+
methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
|
2906
|
+
origin: "*"
|
|
2907
|
+
});
|
|
2908
|
+
const { query: queryParams, method } = req, _a = queryParams, { path } = _a, query = __objRest(_a, ["path"]);
|
|
2909
|
+
if (path && method) {
|
|
2910
|
+
const handler = await endpointMap.then((map) => {
|
|
2911
|
+
const pathString = [].concat(path).join("/"), key = endpointKey(method, pathString);
|
|
2912
|
+
return map[key];
|
|
2913
|
+
});
|
|
2914
|
+
if (handler)
|
|
2915
|
+
return ["POST", "DELETE"].includes(method) && (req.body = await parseBody(req)), Promise.resolve(req).then(handler).then((result) => {
|
|
2916
|
+
if ("error" in result)
|
|
2917
|
+
throw new BackendError(result.status, result.error);
|
|
2918
|
+
if (result.data instanceof Buffer) {
|
|
2919
|
+
const image = result.data;
|
|
2920
|
+
res.writeHead(result.status, { "Content-Type": "image/png" }).end(image, "binary");
|
|
2921
|
+
} else
|
|
2922
|
+
res.status(result.status).json({ data: result.data });
|
|
2923
|
+
}).catch((err) => {
|
|
2924
|
+
verbose && console.trace(err), res.status(err.code).json({ error: err.message });
|
|
2925
|
+
});
|
|
2926
|
+
} else
|
|
2927
|
+
path || await endpointMap.then(console.log);
|
|
2928
|
+
return res.status(404).json({ error: "No matching route", path, query });
|
|
2929
|
+
}
|
|
2930
|
+
const reportsCrosswalkEntrypointFn = (crosswalk) => {
|
|
2931
|
+
const crosswalkFn = crosswalk;
|
|
2932
|
+
return async function(req, res) {
|
|
2933
|
+
const response = await crosswalkFn({ test: "pala" });
|
|
2934
|
+
return res.json(response);
|
|
2935
|
+
};
|
|
2936
|
+
};
|
|
2937
|
+
export {
|
|
2938
|
+
reportsCrosswalkEntrypointFn as ReportCrosswalkHandler,
|
|
2939
|
+
apiFactory as dbApiFactory,
|
|
2940
|
+
endpointKey,
|
|
2941
|
+
endpointNextJsHandlerFactory,
|
|
2942
|
+
getDB,
|
|
2943
|
+
useDatabaseApi
|
|
2944
|
+
};
|