@blinkk/root-cms 3.1.5 → 3.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +1 -1
- package/dist/{chunk-ETHWZSNM.js → chunk-PLSNGCYU.js} +196 -22
- package/dist/{chunk-MUXSUGFF.js → chunk-U4TMO2LI.js} +2 -2
- package/dist/{chunk-6CTCV2PN.js → chunk-Z2CTQVYR.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/client.js +1 -1
- package/dist/core/client.d.ts +30 -2
- package/dist/core/cron-schedule.d.ts +63 -0
- package/dist/core/plugin.d.ts +6 -1
- package/dist/core.js +1 -1
- package/dist/functions.js +2 -2
- package/dist/plugin.js +7 -5
- package/dist/richtext.js +1 -1
- package/dist/shared/embed-protocol.d.ts +19 -0
- package/dist/ui/{AIPage-25WICIOT.js → AIPage-EO5WH25R.js} +1 -1
- package/dist/ui/{AssetsPage-WKTM2J2G.js → AssetsPage-ESLB4R3I.js} +1 -1
- package/dist/ui/{CollectionPage-5ZOVG7IG.js → CollectionPage-MXN7XKUX.js} +1 -1
- package/dist/ui/{ComparePage-DDIFYYTK.js → ComparePage-TY7VJVE3.js} +1 -1
- package/dist/ui/{DataPage-RFNGSDDN.js → DataPage-YEIS7HBN.js} +1 -1
- package/dist/ui/{DataSourcePage-U46CDIH2.js → DataSourcePage-VD6YBDRW.js} +1 -1
- package/dist/ui/{DocTranslationsPage-BFCM2PE3.js → DocTranslationsPage-6XLREBPQ.js} +1 -1
- package/dist/ui/DocumentPage-2HNNEGRI.js +1 -0
- package/dist/ui/{EditDataSourcePage-NKKIF6AD.js → EditDataSourcePage-E4PSKSG3.js} +1 -1
- package/dist/ui/{EditReleasePage-TKNOUT7A.js → EditReleasePage-DOMXJXCU.js} +1 -1
- package/dist/ui/{EmbeddedAIPage-4AX7VO3T.js → EmbeddedAIPage-U5LONYH2.js} +1 -1
- package/dist/ui/EmbeddedDocumentPage-HYV5GPK6.js +1 -0
- package/dist/ui/{LogsPage-SCECIAZH.js → LogsPage-6KV3CQLH.js} +1 -1
- package/dist/ui/{NewDataSourcePage-FAOPK2RZ.js → NewDataSourcePage-NJJDHGPX.js} +1 -1
- package/dist/ui/{NewReleasePage-HD6T6UV2.js → NewReleasePage-FXHPFUVG.js} +1 -1
- package/dist/ui/{NotFoundPage-JRYFUENW.js → NotFoundPage-CA7XVXUO.js} +1 -1
- package/dist/ui/{ProjectPage-2WIMWCSX.js → ProjectPage-XUBJSCWB.js} +1 -1
- package/dist/ui/{ReleasePage-GUMEMLF6.js → ReleasePage-NLGRYJX7.js} +1 -1
- package/dist/ui/{ReleasesPage-AW6PICTQ.js → ReleasesPage-OY7OKC3C.js} +1 -1
- package/dist/ui/{SettingsPage-KFLNZ356.js → SettingsPage-5EQUY52A.js} +1 -1
- package/dist/ui/SidebarToolsPage-FWG6TIDI.js +1 -0
- package/dist/ui/TaskPage-APNRUOYG.js +1 -0
- package/dist/ui/{TasksPage-G3GBTV3L.js → TasksPage-FTEELXVZ.js} +1 -1
- package/dist/ui/{TranslationsArbPage-K272JEAA.js → TranslationsArbPage-PG5USRYB.js} +1 -1
- package/dist/ui/{TranslationsEditPage-XWXPNKRQ.js → TranslationsEditPage-GV3ZJXTY.js} +1 -1
- package/dist/ui/{TranslationsPage-7KUHVTLK.js → TranslationsPage-3AKSMCNF.js} +1 -1
- package/dist/ui/{chunk-VPZHG7JL.js → chunk-235TRWJF.js} +1 -1
- package/dist/ui/{chunk-IGZDFHVM.js → chunk-3LEYSXZP.js} +1 -1
- package/dist/ui/chunk-56NMZYX6.js +19 -0
- package/dist/ui/{chunk-T5BJNOWE.js → chunk-6WJQBFN5.js} +1 -1
- package/dist/ui/{chunk-OWBT6YUM.js → chunk-A7IZAHBZ.js} +1 -1
- package/dist/ui/{chunk-WC7KMPEQ.js → chunk-C5FRMXDS.js} +1 -1
- package/dist/ui/{chunk-UPN3EMUS.js → chunk-EYJ6GKZR.js} +1 -1
- package/dist/ui/{chunk-TNW2GNUR.js → chunk-G5647K25.js} +1 -1
- package/dist/ui/chunk-LAXQZPE3.js +31 -0
- package/dist/ui/chunk-MYPLMHFW.js +1 -0
- package/dist/ui/{chunk-XUBZH4ON.js → chunk-O7ESOZQO.js} +1 -1
- package/dist/ui/{chunk-5KSGCGYY.js → chunk-QGAPMQEJ.js} +1 -1
- package/dist/ui/{chunk-7UHZS56B.js → chunk-ST6QNIWT.js} +53 -53
- package/dist/ui/{chunk-DWV5J2W7.js → chunk-U7LSFUHT.js} +1 -1
- package/dist/ui/chunk-UOKVF54Y.js +3 -0
- package/dist/ui/{chunk-FVWSVOOY.js → chunk-VJRMR2JM.js} +1 -1
- package/dist/ui/chunk-Z2CRNO3I.js +1 -0
- package/dist/ui/{chunk-N5RJIILP.js → chunk-ZAJPNVYS.js} +1 -1
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +1 -1
- package/package.json +3 -3
- package/dist/ui/DocumentPage-OTBXM55S.js +0 -1
- package/dist/ui/EmbeddedDocumentPage-2CNQJTW5.js +0 -1
- package/dist/ui/SidebarToolsPage-3R7BQ2F7.js +0 -1
- package/dist/ui/TaskPage-GZGPKIL5.js +0 -1
- package/dist/ui/chunk-2FQMT5AB.js +0 -3
- package/dist/ui/chunk-GCSN3YEC.js +0 -31
- package/dist/ui/chunk-NXWYS4HG.js +0 -19
- package/dist/ui/chunk-RN4XVVWD.js +0 -1
- /package/dist/ui/{chunk-VPZHG7JL.js.LEGAL.txt → chunk-235TRWJF.js.LEGAL.txt} +0 -0
- /package/dist/ui/{chunk-7UHZS56B.js.LEGAL.txt → chunk-ST6QNIWT.js.LEGAL.txt} +0 -0
package/dist/app.js
CHANGED
|
@@ -9,6 +9,155 @@ import {
|
|
|
9
9
|
Timestamp as Timestamp2
|
|
10
10
|
} from "firebase-admin/firestore";
|
|
11
11
|
|
|
12
|
+
// core/cron-schedule.ts
|
|
13
|
+
var ONE_MINUTE_MS = 60 * 1e3;
|
|
14
|
+
var MAX_LOOKBACK_MS = 366 * 24 * 60 * 60 * 1e3;
|
|
15
|
+
var FIELD_RANGES = [
|
|
16
|
+
{ min: 0, max: 59 },
|
|
17
|
+
// minute
|
|
18
|
+
{ min: 0, max: 23 },
|
|
19
|
+
// hour
|
|
20
|
+
{ min: 1, max: 31 },
|
|
21
|
+
// day of month
|
|
22
|
+
{ min: 1, max: 12 },
|
|
23
|
+
// month
|
|
24
|
+
{ min: 0, max: 7 }
|
|
25
|
+
// day of week (0 and 7 both mean Sunday)
|
|
26
|
+
];
|
|
27
|
+
function parseField(field, range) {
|
|
28
|
+
const values = /* @__PURE__ */ new Set();
|
|
29
|
+
const parts = field.split(",");
|
|
30
|
+
for (const part of parts) {
|
|
31
|
+
const trimmed = part.trim();
|
|
32
|
+
if (!trimmed) {
|
|
33
|
+
throw new Error(`invalid cron field: "${field}"`);
|
|
34
|
+
}
|
|
35
|
+
let rangePart = trimmed;
|
|
36
|
+
let step = 1;
|
|
37
|
+
if (trimmed.includes("/")) {
|
|
38
|
+
const [rangeStr, stepStr] = trimmed.split("/");
|
|
39
|
+
rangePart = rangeStr;
|
|
40
|
+
step = Number(stepStr);
|
|
41
|
+
if (!Number.isInteger(step) || step <= 0) {
|
|
42
|
+
throw new Error(`invalid cron step: "${trimmed}"`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let start;
|
|
46
|
+
let end;
|
|
47
|
+
if (rangePart === "*") {
|
|
48
|
+
start = range.min;
|
|
49
|
+
end = range.max;
|
|
50
|
+
} else if (rangePart.includes("-")) {
|
|
51
|
+
const [startStr, endStr] = rangePart.split("-");
|
|
52
|
+
start = Number(startStr);
|
|
53
|
+
end = Number(endStr);
|
|
54
|
+
} else {
|
|
55
|
+
start = Number(rangePart);
|
|
56
|
+
end = start;
|
|
57
|
+
}
|
|
58
|
+
if (!Number.isInteger(start) || !Number.isInteger(end) || start < range.min || end > range.max || start > end) {
|
|
59
|
+
throw new Error(`invalid cron field: "${field}"`);
|
|
60
|
+
}
|
|
61
|
+
for (let value = start; value <= end; value += step) {
|
|
62
|
+
values.add(value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return values;
|
|
66
|
+
}
|
|
67
|
+
function parseCronExpression(expression) {
|
|
68
|
+
const fields = expression.trim().split(/\s+/);
|
|
69
|
+
if (fields.length !== 5) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`invalid cron expression: "${expression}" (expected 5 fields)`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = fields;
|
|
75
|
+
const parsedDayOfWeek = parseField(dayOfWeek, FIELD_RANGES[4]);
|
|
76
|
+
if (parsedDayOfWeek.has(7)) {
|
|
77
|
+
parsedDayOfWeek.delete(7);
|
|
78
|
+
parsedDayOfWeek.add(0);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
minute: parseField(minute, FIELD_RANGES[0]),
|
|
82
|
+
hour: parseField(hour, FIELD_RANGES[1]),
|
|
83
|
+
dayOfMonth: parseField(dayOfMonth, FIELD_RANGES[2]),
|
|
84
|
+
month: parseField(month, FIELD_RANGES[3]),
|
|
85
|
+
dayOfWeek: parsedDayOfWeek,
|
|
86
|
+
dayOfMonthRestricted: dayOfMonth.trim() !== "*",
|
|
87
|
+
dayOfWeekRestricted: dayOfWeek.trim() !== "*"
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function getZonedFields(date, timeZone) {
|
|
91
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
92
|
+
timeZone,
|
|
93
|
+
hour12: false,
|
|
94
|
+
year: "numeric",
|
|
95
|
+
month: "2-digit",
|
|
96
|
+
day: "2-digit",
|
|
97
|
+
hour: "2-digit",
|
|
98
|
+
minute: "2-digit"
|
|
99
|
+
});
|
|
100
|
+
const parts = {};
|
|
101
|
+
for (const part of dtf.formatToParts(date)) {
|
|
102
|
+
parts[part.type] = part.value;
|
|
103
|
+
}
|
|
104
|
+
const year = Number(parts.year);
|
|
105
|
+
const month = Number(parts.month);
|
|
106
|
+
const day = Number(parts.day);
|
|
107
|
+
let hour = Number(parts.hour);
|
|
108
|
+
if (hour === 24) {
|
|
109
|
+
hour = 0;
|
|
110
|
+
}
|
|
111
|
+
const minute = Number(parts.minute);
|
|
112
|
+
const dayOfWeek = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
|
|
113
|
+
return { minute, hour, dayOfMonth: day, month, dayOfWeek };
|
|
114
|
+
}
|
|
115
|
+
function matchesCron(parsed, fields) {
|
|
116
|
+
if (!parsed.minute.has(fields.minute)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (!parsed.hour.has(fields.hour)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (!parsed.month.has(fields.month)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const domMatch = parsed.dayOfMonth.has(fields.dayOfMonth);
|
|
126
|
+
const dowMatch = parsed.dayOfWeek.has(fields.dayOfWeek);
|
|
127
|
+
if (parsed.dayOfMonthRestricted && parsed.dayOfWeekRestricted) {
|
|
128
|
+
return domMatch || dowMatch;
|
|
129
|
+
}
|
|
130
|
+
if (parsed.dayOfMonthRestricted) {
|
|
131
|
+
return domMatch;
|
|
132
|
+
}
|
|
133
|
+
if (parsed.dayOfWeekRestricted) {
|
|
134
|
+
return dowMatch;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
function isCronDue(options) {
|
|
139
|
+
const { expression, now } = options;
|
|
140
|
+
const timezone = options.timezone || "UTC";
|
|
141
|
+
const parsed = parseCronExpression(expression);
|
|
142
|
+
let lastSyncMs = options.lastSyncMs;
|
|
143
|
+
if (lastSyncMs > now) {
|
|
144
|
+
lastSyncMs = now;
|
|
145
|
+
}
|
|
146
|
+
const nowMinute = Math.floor(now / ONE_MINUTE_MS) * ONE_MINUTE_MS;
|
|
147
|
+
let lowerBound;
|
|
148
|
+
if (lastSyncMs > 0) {
|
|
149
|
+
lowerBound = Math.max(lastSyncMs, now - MAX_LOOKBACK_MS);
|
|
150
|
+
} else {
|
|
151
|
+
lowerBound = nowMinute - ONE_MINUTE_MS;
|
|
152
|
+
}
|
|
153
|
+
for (let t = nowMinute; t > lowerBound; t -= ONE_MINUTE_MS) {
|
|
154
|
+
if (matchesCron(parsed, getZonedFields(new Date(t), timezone))) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
12
161
|
// core/translations-manager.ts
|
|
13
162
|
import {
|
|
14
163
|
FieldValue,
|
|
@@ -1302,32 +1451,35 @@ ${errorMessages}`);
|
|
|
1302
1451
|
for (const snapshot of querySnapshot.docs) {
|
|
1303
1452
|
const dataSource = snapshot.data();
|
|
1304
1453
|
const cron = dataSource.cron;
|
|
1305
|
-
if (!cron || !cron.enabled
|
|
1306
|
-
continue;
|
|
1307
|
-
}
|
|
1308
|
-
const interval = Number(cron.interval);
|
|
1309
|
-
if (!Number.isFinite(interval) || interval <= 0 || !Number.isInteger(interval)) {
|
|
1454
|
+
if (!cron || !cron.enabled) {
|
|
1310
1455
|
continue;
|
|
1311
1456
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
case "days":
|
|
1321
|
-
intervalMs *= 24 * 60 * 60 * 1e3;
|
|
1322
|
-
break;
|
|
1323
|
-
default:
|
|
1457
|
+
const lastSyncMs = dataSource.syncedAt ? dataSource.syncedAt.toMillis() : 0;
|
|
1458
|
+
const schedule = cron.schedule || "interval";
|
|
1459
|
+
let due;
|
|
1460
|
+
if (schedule === "interval") {
|
|
1461
|
+
due = isIntervalDue(cron, lastSyncMs, now);
|
|
1462
|
+
} else {
|
|
1463
|
+
const expression = (cron.expression || "").trim();
|
|
1464
|
+
if (!expression) {
|
|
1324
1465
|
continue;
|
|
1466
|
+
}
|
|
1467
|
+
try {
|
|
1468
|
+
due = isCronDue({
|
|
1469
|
+
expression,
|
|
1470
|
+
timezone: cron.timezone,
|
|
1471
|
+
lastSyncMs,
|
|
1472
|
+
now
|
|
1473
|
+
});
|
|
1474
|
+
} catch (err) {
|
|
1475
|
+
console.error(
|
|
1476
|
+
`cron: invalid cron expression for data source ${dataSource.id}: "${expression}":`,
|
|
1477
|
+
String(err)
|
|
1478
|
+
);
|
|
1479
|
+
continue;
|
|
1480
|
+
}
|
|
1325
1481
|
}
|
|
1326
|
-
|
|
1327
|
-
if (lastSyncMs > now) {
|
|
1328
|
-
lastSyncMs = now;
|
|
1329
|
-
}
|
|
1330
|
-
if (now - lastSyncMs < intervalMs) {
|
|
1482
|
+
if (!due) {
|
|
1331
1483
|
continue;
|
|
1332
1484
|
}
|
|
1333
1485
|
try {
|
|
@@ -2151,6 +2303,28 @@ function unmarshalArray(arrObject) {
|
|
|
2151
2303
|
function isObject(data) {
|
|
2152
2304
|
return typeof data === "object" && !Array.isArray(data) && data !== null;
|
|
2153
2305
|
}
|
|
2306
|
+
function isIntervalDue(cron, lastSyncMs, now) {
|
|
2307
|
+
const interval = Number(cron.interval);
|
|
2308
|
+
if (!cron.unit || !Number.isFinite(interval) || interval <= 0 || !Number.isInteger(interval)) {
|
|
2309
|
+
return false;
|
|
2310
|
+
}
|
|
2311
|
+
let intervalMs = interval;
|
|
2312
|
+
switch (cron.unit) {
|
|
2313
|
+
case "minutes":
|
|
2314
|
+
intervalMs *= 60 * 1e3;
|
|
2315
|
+
break;
|
|
2316
|
+
case "hours":
|
|
2317
|
+
intervalMs *= 60 * 60 * 1e3;
|
|
2318
|
+
break;
|
|
2319
|
+
case "days":
|
|
2320
|
+
intervalMs *= 24 * 60 * 60 * 1e3;
|
|
2321
|
+
break;
|
|
2322
|
+
default:
|
|
2323
|
+
return false;
|
|
2324
|
+
}
|
|
2325
|
+
const normalizedLastSyncMs = lastSyncMs > now ? now : lastSyncMs;
|
|
2326
|
+
return now - normalizedLastSyncMs >= intervalMs;
|
|
2327
|
+
}
|
|
2154
2328
|
function parseSpreadsheetUrl(url) {
|
|
2155
2329
|
if (!url.startsWith("https://docs.google.com/spreadsheets/d/")) {
|
|
2156
2330
|
return null;
|
|
@@ -552,7 +552,7 @@ async function generateImage(rootConfig, options) {
|
|
|
552
552
|
// package.json
|
|
553
553
|
var package_default = {
|
|
554
554
|
name: "@blinkk/root-cms",
|
|
555
|
-
version: "3.1.
|
|
555
|
+
version: "3.1.6",
|
|
556
556
|
author: "s@blinkk.com",
|
|
557
557
|
license: "MIT",
|
|
558
558
|
engines: {
|
|
@@ -727,7 +727,7 @@ var package_default = {
|
|
|
727
727
|
yjs: "13.6.27"
|
|
728
728
|
},
|
|
729
729
|
peerDependencies: {
|
|
730
|
-
"@blinkk/root": "3.1.
|
|
730
|
+
"@blinkk/root": "3.1.6",
|
|
731
731
|
"firebase-admin": ">=11",
|
|
732
732
|
"firebase-functions": ">=4"
|
|
733
733
|
},
|
package/dist/cli.js
CHANGED
package/dist/client.js
CHANGED
package/dist/core/client.d.ts
CHANGED
|
@@ -39,10 +39,38 @@ export type DocMode = 'draft' | 'published';
|
|
|
39
39
|
export type UserRole = 'ADMIN' | 'EDITOR' | 'CONTRIBUTOR' | 'VIEWER';
|
|
40
40
|
export type HttpMethod = 'GET' | 'POST';
|
|
41
41
|
export type CronUnit = 'minutes' | 'hours' | 'days';
|
|
42
|
+
/**
|
|
43
|
+
* Data source sync schedule type.
|
|
44
|
+
*
|
|
45
|
+
* - `interval`: sync every N minutes/hours/days (uses `interval` + `unit`).
|
|
46
|
+
* - `daily` / `weekly` / `custom`: sync on a specific cron schedule (uses
|
|
47
|
+
* `expression` + `timezone`). `daily` and `weekly` are UI presets that are
|
|
48
|
+
* stored as standard cron expressions; `custom` allows an arbitrary
|
|
49
|
+
* expression.
|
|
50
|
+
*/
|
|
51
|
+
export type CronScheduleType = 'interval' | 'daily' | 'weekly' | 'custom';
|
|
42
52
|
export interface DataSourceCron {
|
|
43
53
|
enabled: boolean;
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Scheduling mode. Defaults to `interval` when unset (for backwards
|
|
56
|
+
* compatibility with data sources created before specific schedules were
|
|
57
|
+
* supported).
|
|
58
|
+
*/
|
|
59
|
+
schedule?: CronScheduleType;
|
|
60
|
+
/** Interval value, used when `schedule` is `interval`. */
|
|
61
|
+
interval?: number;
|
|
62
|
+
/** Interval unit, used when `schedule` is `interval`. */
|
|
63
|
+
unit?: CronUnit;
|
|
64
|
+
/**
|
|
65
|
+
* Standard 5-field cron expression, used when `schedule` is `daily`,
|
|
66
|
+
* `weekly`, or `custom`, e.g. `0 19 * * *` for "every day at 7pm".
|
|
67
|
+
*/
|
|
68
|
+
expression?: string;
|
|
69
|
+
/**
|
|
70
|
+
* IANA timezone used to evaluate `expression`, e.g. `America/New_York`.
|
|
71
|
+
* Defaults to UTC when unset.
|
|
72
|
+
*/
|
|
73
|
+
timezone?: string;
|
|
46
74
|
autoPublish?: boolean;
|
|
47
75
|
}
|
|
48
76
|
export interface DataSource {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for evaluating standard cron expressions for data source
|
|
3
|
+
* scheduling.
|
|
4
|
+
*
|
|
5
|
+
* Supports the standard 5-field cron format:
|
|
6
|
+
*
|
|
7
|
+
* ┌───────────── minute (0 - 59)
|
|
8
|
+
* │ ┌───────────── hour (0 - 23)
|
|
9
|
+
* │ │ ┌───────────── day of month (1 - 31)
|
|
10
|
+
* │ │ │ ┌───────────── month (1 - 12)
|
|
11
|
+
* │ │ │ │ ┌───────────── day of week (0 - 6, where 0 and 7 are Sunday)
|
|
12
|
+
* │ │ │ │ │
|
|
13
|
+
* * * * * *
|
|
14
|
+
*
|
|
15
|
+
* Each field supports `*`, single values, ranges (`a-b`), lists (`a,b,c`),
|
|
16
|
+
* steps (`* /n`, `a-b/n`), and combinations thereof. Expressions are evaluated
|
|
17
|
+
* against a specific IANA timezone so that schedules like "every day at 7pm"
|
|
18
|
+
* fire at the expected wall-clock time.
|
|
19
|
+
*/
|
|
20
|
+
interface ParsedCron {
|
|
21
|
+
minute: Set<number>;
|
|
22
|
+
hour: Set<number>;
|
|
23
|
+
dayOfMonth: Set<number>;
|
|
24
|
+
month: Set<number>;
|
|
25
|
+
dayOfWeek: Set<number>;
|
|
26
|
+
/** Whether the day-of-month field was restricted (not `*`). */
|
|
27
|
+
dayOfMonthRestricted: boolean;
|
|
28
|
+
/** Whether the day-of-week field was restricted (not `*`). */
|
|
29
|
+
dayOfWeekRestricted: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parses a standard 5-field cron expression. Throws if the expression is
|
|
33
|
+
* malformed.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseCronExpression(expression: string): ParsedCron;
|
|
36
|
+
/**
|
|
37
|
+
* Returns true if the given cron expression is syntactically valid.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isValidCronExpression(expression: string): boolean;
|
|
40
|
+
export interface IsCronDueOptions {
|
|
41
|
+
/** Standard 5-field cron expression, e.g. "0 19 * * *". */
|
|
42
|
+
expression: string;
|
|
43
|
+
/** IANA timezone used to evaluate the expression. Defaults to "UTC". */
|
|
44
|
+
timezone?: string;
|
|
45
|
+
/** Timestamp (ms) of the last successful sync, or 0 if never synced. */
|
|
46
|
+
lastSyncMs: number;
|
|
47
|
+
/** Current time (ms). */
|
|
48
|
+
now: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Determines whether a cron-scheduled data source is due for sync.
|
|
52
|
+
*
|
|
53
|
+
* Uses catch-up semantics: the source is due if there is any scheduled minute
|
|
54
|
+
* in the window `(lastSyncMs, now]` that matches the cron expression. This
|
|
55
|
+
* ensures a missed cron tick (e.g. the scheduler was briefly down at the
|
|
56
|
+
* scheduled minute) still triggers a sync on a later tick.
|
|
57
|
+
*
|
|
58
|
+
* When the source has never synced (`lastSyncMs <= 0`), only the current minute
|
|
59
|
+
* is considered so that enabling a schedule does not trigger an unexpected
|
|
60
|
+
* immediate backfill — the source will first sync at its next scheduled time.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isCronDue(options: IsCronDueOptions): boolean;
|
|
63
|
+
export {};
|
package/dist/core/plugin.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { App } from 'firebase-admin/app';
|
|
|
3
3
|
import { Firestore } from 'firebase-admin/firestore';
|
|
4
4
|
import { type AiConfig } from './ai.js';
|
|
5
5
|
import { type CMSCheck } from './checks.js';
|
|
6
|
-
import { Action } from './client.js';
|
|
6
|
+
import { Action, UserRole } from './client.js';
|
|
7
7
|
import { type CMSNotificationService } from './services-notifications.js';
|
|
8
8
|
import { type CMSTranslationService } from './translations.js';
|
|
9
9
|
export type { AiConfig, AiModelConfig, AiProvider } from './ai.js';
|
|
@@ -19,6 +19,11 @@ export type { CMSTranslationService, RootLocale, TranslationExportResult, Transl
|
|
|
19
19
|
export type CMSBuiltInSidebarTool = 'home' | 'content' | 'releases' | 'data' | 'assets' | 'translations' | 'ai' | 'settings';
|
|
20
20
|
export interface CMSUser {
|
|
21
21
|
email: string;
|
|
22
|
+
/**
|
|
23
|
+
* The user's role within the project's ACL, or `null` if unassigned. This is
|
|
24
|
+
* populated on `req.user` for every authenticated request.
|
|
25
|
+
*/
|
|
26
|
+
role?: UserRole | null;
|
|
22
27
|
}
|
|
23
28
|
/**
|
|
24
29
|
* @deprecated The `experiments.ai` flag is now used only as a sidebar toggle.
|
package/dist/core.js
CHANGED
package/dist/functions.js
CHANGED
package/dist/plugin.js
CHANGED
|
@@ -12,16 +12,16 @@ import {
|
|
|
12
12
|
serializeAiConfig,
|
|
13
13
|
summarizeDiff,
|
|
14
14
|
translateString
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-U4TMO2LI.js";
|
|
16
16
|
import {
|
|
17
17
|
SearchIndexService,
|
|
18
18
|
runCronJobs
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-Z2CTQVYR.js";
|
|
20
20
|
import {
|
|
21
21
|
RootCMSClient,
|
|
22
22
|
parseDocId,
|
|
23
23
|
unmarshalData
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-PLSNGCYU.js";
|
|
25
25
|
import "./chunk-J72JK4KR.js";
|
|
26
26
|
import "./chunk-MLKGABMK.js";
|
|
27
27
|
|
|
@@ -1389,7 +1389,8 @@ function cmsPlugin(options) {
|
|
|
1389
1389
|
console.log("session failed: user is not in the firestore acl list");
|
|
1390
1390
|
return null;
|
|
1391
1391
|
}
|
|
1392
|
-
|
|
1392
|
+
const role = await cmsClient.getUserRole(jwt.email).catch(() => null);
|
|
1393
|
+
return { email: jwt.email, role };
|
|
1393
1394
|
}
|
|
1394
1395
|
try {
|
|
1395
1396
|
const jwt = await auth.verifySessionCookie(sessionCookie, true);
|
|
@@ -1416,7 +1417,8 @@ function cmsPlugin(options) {
|
|
|
1416
1417
|
console.log("session failed: user is not in the firestore acl list");
|
|
1417
1418
|
return null;
|
|
1418
1419
|
}
|
|
1419
|
-
|
|
1420
|
+
const role = await cmsClient.getUserRole(jwt.email).catch(() => null);
|
|
1421
|
+
return { email: jwt.email, role };
|
|
1420
1422
|
} catch (err) {
|
|
1421
1423
|
console.error("failed to verify jwt token");
|
|
1422
1424
|
console.error(err);
|
package/dist/richtext.js
CHANGED
|
@@ -63,7 +63,7 @@ var ALLOWED_ATTRIBUTES = {
|
|
|
63
63
|
img: ["src", "alt", "title", "width", "height"]
|
|
64
64
|
};
|
|
65
65
|
var COMMON_OPTIONS = {
|
|
66
|
-
allowedSchemes: ["http", "https", "mailto"],
|
|
66
|
+
allowedSchemes: ["http", "https", "mailto", "tel", "sms"],
|
|
67
67
|
allowedSchemesByTag: {
|
|
68
68
|
img: ["http", "https", "data"]
|
|
69
69
|
},
|
|
@@ -44,6 +44,23 @@ export interface RootEmbedMessage {
|
|
|
44
44
|
error?: string;
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Posted from an iframed sidebar tool to the parent CMS window to report the
|
|
49
|
+
* tool's current location. The CMS mirrors this into its own address bar so
|
|
50
|
+
* the tool's sub-path, query params, and hash survive a refresh and can be
|
|
51
|
+
* deep-linked/shared.
|
|
52
|
+
*
|
|
53
|
+
* Same-origin tools are synced automatically (the CMS reads
|
|
54
|
+
* `contentWindow.location` directly), so this message only needs to be posted
|
|
55
|
+
* by cross-origin tools, which the browser prevents the CMS from reading.
|
|
56
|
+
*/
|
|
57
|
+
export interface RootToolLocationMessage {
|
|
58
|
+
rootTool: {
|
|
59
|
+
type: 'locationchange';
|
|
60
|
+
/** The tool's current URL, absolute or relative to the tool's origin. */
|
|
61
|
+
url: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
47
64
|
/** Requests that the doc editor scroll to (focus) a specific field. */
|
|
48
65
|
export interface ScrollToDeeplinkMessage {
|
|
49
66
|
scrollToDeeplink: {
|
|
@@ -66,6 +83,8 @@ export interface HighlightNodeMessage {
|
|
|
66
83
|
}
|
|
67
84
|
/** Returns whether a postMessage payload is a {@link RootEmbedMessage}. */
|
|
68
85
|
export declare function isRootEmbedMessage(data: unknown): data is RootEmbedMessage;
|
|
86
|
+
/** Returns whether a postMessage payload is a {@link RootToolLocationMessage}. */
|
|
87
|
+
export declare function isRootToolLocationMessage(data: unknown): data is RootToolLocationMessage;
|
|
69
88
|
/** Returns whether a postMessage payload is a {@link ScrollToDeeplinkMessage}. */
|
|
70
89
|
export declare function isScrollToDeeplinkMessage(data: unknown): data is ScrollToDeeplinkMessage;
|
|
71
90
|
/** Returns whether a postMessage payload is a {@link HighlightNodeMessage}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a}from"./chunk-
|
|
1
|
+
import{a}from"./chunk-56NMZYX6.js";import"./chunk-LAXQZPE3.js";import"./chunk-QWB6MAPJ.js";import"./chunk-235TRWJF.js";import"./chunk-AAR7DBEN.js";import"./chunk-YDO2EDVY.js";import"./chunk-5MV6XVGA.js";import{a as i}from"./chunk-QLIIVG5Q.js";import{c as o}from"./chunk-A7IZAHBZ.js";import"./chunk-AAHM6RYJ.js";import"./chunk-ISUGBMXC.js";import"./chunk-DZYYWCHX.js";import"./chunk-XOWWPE7X.js";import"./chunk-WASID5UU.js";import{Ga as t}from"./chunk-WRA24P66.js";import"./chunk-KUCVLANF.js";import"./chunk-7SK47HHZ.js";import"./chunk-DTMZLUNY.js";import"./chunk-PVAE643M.js";function n(r){return i("AI"),t(o,{children:t(a,{variant:"page",initialChatId:r.chatId})})}export{n as AIPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as p}from"./chunk-RB23LLKL.js";import{a as i}from"./chunk-JBLSUM6W.js";import"./chunk-2RRM4HEQ.js";import{a as n}from"./chunk-HXSB6YB2.js";import"./chunk-PLYSJ7W5.js";import"./chunk-H37RXS4R.js";import"./chunk-W5DOO6ID.js";import"./chunk-YBHFGQ3Z.js";import"./chunk-2PTLQRTU.js";import"./chunk-PIJ3E47R.js";import{a as d}from"./chunk-NCZD5IWS.js";import{a as g}from"./chunk-QLIIVG5Q.js";import{c as m}from"./chunk-
|
|
1
|
+
import{a as p}from"./chunk-RB23LLKL.js";import{a as i}from"./chunk-JBLSUM6W.js";import"./chunk-2RRM4HEQ.js";import{a as n}from"./chunk-HXSB6YB2.js";import"./chunk-PLYSJ7W5.js";import"./chunk-H37RXS4R.js";import"./chunk-W5DOO6ID.js";import"./chunk-YBHFGQ3Z.js";import"./chunk-2PTLQRTU.js";import"./chunk-PIJ3E47R.js";import{a as d}from"./chunk-NCZD5IWS.js";import{a as g}from"./chunk-QLIIVG5Q.js";import{c as m}from"./chunk-A7IZAHBZ.js";import"./chunk-AAHM6RYJ.js";import"./chunk-ISUGBMXC.js";import"./chunk-DZYYWCHX.js";import"./chunk-XOWWPE7X.js";import{d as o}from"./chunk-WASID5UU.js";import{Ga as e,a as t,c as r,j as h}from"./chunk-WRA24P66.js";import"./chunk-KUCVLANF.js";import"./chunk-7SK47HHZ.js";import"./chunk-DTMZLUNY.js";import"./chunk-PVAE643M.js";h();function k(){g("Asset Library");let[l,u]=p("folder",""),{query:c,route:f}=o(),[a]=t(c.asset||"");return r(()=>{if(a){let s=new URL(window.location.href);s.searchParams.delete("asset"),f(s.pathname+s.search,!0)}},[]),e(m,{children:e("div",{className:"AssetsPage","data-testid":"assets-page",children:[e("div",{className:"AssetsPage__header",children:[e(n,{size:"h1",children:"Asset Library"}),e(d,{as:"p",children:"The asset library can be used to store and organize files used throughout the project. Replacing a file in the asset library automatically updates all draft docs that use it (requires re-publishing)."})]}),e(i,{className:"AssetsPage__browser",mode:"manage",folder:l,onFolderChange:u,initialAssetId:a})]})})}export{k as AssetsPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as ne}from"./chunk-44ZU5WMI.js";import{a as _e}from"./chunk-OWYV43BT.js";import{h as O}from"./chunk-N5RJIILP.js";import{a as oe,e as te,j as le}from"./chunk-UPN3EMUS.js";import"./chunk-HV3JJ5UT.js";import{b as F,c as H,d as S,f as A}from"./chunk-TNW2GNUR.js";import"./chunk-FVWSVOOY.js";import{a as x}from"./chunk-QFDU6FXP.js";import"./chunk-JDW4UORS.js";import{a as B}from"./chunk-UJX25CXD.js";import"./chunk-RN4XVVWD.js";import"./chunk-QRAFYIAW.js";import"./chunk-ATTW36EM.js";import"./chunk-YDO2EDVY.js";import{b as C}from"./chunk-5MV6XVGA.js";import"./chunk-PLYSJ7W5.js";import"./chunk-H37RXS4R.js";import{b as ee}from"./chunk-W5DOO6ID.js";import{a as Q}from"./chunk-YBHFGQ3Z.js";import"./chunk-2PTLQRTU.js";import"./chunk-PIJ3E47R.js";import"./chunk-NCZD5IWS.js";import{a as ce}from"./chunk-QLIIVG5Q.js";import{c as ie}from"./chunk-OWBT6YUM.js";import"./chunk-AAHM6RYJ.js";import"./chunk-ISUGBMXC.js";import"./chunk-DZYYWCHX.js";import{B as Y,z as Z}from"./chunk-XOWWPE7X.js";import{d as V,e as w}from"./chunk-WASID5UU.js";import{$a as q,Ca as X,Fa as k,Ga as e,Ta as K,Ua as W,V as I,W as M,a as U,ab as G,ba as $,c as E,cb as J,da as D,fb as z,j as me,qa as P,za as j}from"./chunk-WRA24P66.js";import{d as N}from"./chunk-KUCVLANF.js";import"./chunk-7SK47HHZ.js";import"./chunk-DTMZLUNY.js";import"./chunk-PVAE643M.js";me();var R=[{value:"comfortable",label:"Comfortable",Icon:K},{value:"compact",label:"Compact",Icon:W}];function L(o){let{route:i}=V(),l=window.__ROOT_CTX.rootConfig.projectId;ce(o.collection?o.collection:"Content"),E(()=>{let c=window.__ROOT_CTX.collections,n=`root-cms::${l}::last_collection`;if(o.collection)window.localStorage.setItem(n,o.collection);else{let a=window.localStorage.getItem(n);if(a&&c[a]){i(`/cms/content/${a}`);return}if(window.__ROOT_CTX.collections.Pages){i("/cms/content/Pages");return}let s=Object.keys(window.__ROOT_CTX.collections)||[];if(s.length>0){let h=s[0];i(`/cms/content/${h}`);return}console.warn("no collections")}},[o.collection,l]);let _=window.__ROOT_CTX.collections;return e(ie,{children:e("div",{className:"CollectionPage",children:e("div",{className:"CollectionPage__layout",children:[e("div",{className:"CollectionPage__side",children:e(ne,{collections:_,activeCollectionId:o.collection,projectId:l})}),e("div",{className:"CollectionPage__main",children:o.collection&&e(L.Collection,{collection:o.collection},o.collection)})]})})})}L.Collection=o=>{let{roles:i}=Q(),l=window.firebase.user.email||"",_=ee(i,l),[c,n]=x(`root::CollectionPage:${o.collection}:orderBy`,"modifiedAt"),[a,s]=x(`root::CollectionPage:${o.collection}:showArchived`,!1),[h,m]=U(!1),t=window.__ROOT_CTX.collections[o.collection];if(!t)return route("/cms/content"),e(N,{});let d=!!t.viewOptions?.compact,[r,p]=x("root::CollectionPage:density","comfortable"),g=d?"compact":r,f=g==="compact",v=[{value:"slug",label:"A-Z"},{value:"slugDesc",label:"Z-A"},{value:"title",label:"Title (A-Z)"},{value:"titleDesc",label:"Title (Z-A)"},{value:"newest",label:"Newest"},{value:"oldest",label:"Oldest"},{value:"modifiedAt",label:"Last modified"},{value:"modifiedAtAsc",label:"Least recently modified"},...t.sortOptions?.map(u=>({value:u.id,label:u.label}))||[]],[b,de,T]=te(o.collection,{orderBy:c,includeArchived:a}),re=b&&T.length===0,ge=!b&&T.length===0;return e(N,{children:[e(le,{collection:o.collection,opened:h,onClose:()=>m(!1)}),e("div",{className:"CollectionPage__collection",children:e("div",{className:"CollectionPage__collection__docsTab",children:[e("div",{className:"CollectionPage__collection__docsTab__header",children:[e("div",{className:"CollectionPage__collection__docsTab__header__title",children:t.name||o.collection}),e("div",{className:"CollectionPage__collection__docsTab__controls",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__showArchived",children:e(X,{size:"sm",color:"dark",label:"Show archived:",checked:a,onChange:u=>s(!!u.currentTarget.checked)})}),e("div",{className:"CollectionPage__collection__docsTab__controls__sort",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__sort__label",children:"Sort:"}),e(j,{size:"xs",value:c,onChange:u=>n(u||"modifiedAt"),data:v})]}),e(pe,{density:g,locked:d,onChange:p}),e("div",{className:"CollectionPage__collection__docsTab__controls__newDoc",children:e(B,{label:"You don't have access to create new documents",condition:!_,children:e(D,{color:"dark",size:"xs",leftIcon:e(z,{size:16}),onClick:()=>m(!0),disabled:!_,children:"New"})})})]})]}),e(_e,{className:"CollectionPage__collection__docsTab__content",children:re?e("div",{className:"CollectionPage__collection__docsTab__content__loading",children:e(I,{color:"gray",size:"xl"})}):ge?e("div",{class:"CollectionPage__collection__docsEmpty",children:[e("div",{class:"CollectionPage__collection__docsEmpty__title",children:"Collection is empty."}),e("div",{class:"CollectionPage__collection__docsEmpty__button",children:e(B,{label:"You don't have access to create new documents",condition:!_,children:e(D,{color:"dark",size:"xs",leftIcon:e(z,{size:16}),onClick:()=>m(!0),disabled:!_,children:"New"})})})]}):e("div",{className:"CollectionPage__collection__docsTab__content__list",children:[b&&e("div",{className:"CollectionPage__collection__docsTab__content__reloading",children:e(I,{color:"gray",size:"md"})}),e("div",{className:w("CollectionPage__collection__docsTab__content__items",b&&"CollectionPage__collection__docsTab__content__items--loading"),children:e(L.DocsList,{collection:o.collection,docs:T,compact:f,orderBy:c,onSort:n,reloadDocs:()=>de()})})]})})]})})]})};function pe(o){let l=(R.find(c=>c.value===o.density)||R[0]).Icon,_=e(M,{variant:"default",color:"gray",size:30,disabled:o.locked,"aria-label":"Change view density",children:e(l,{size:16})});return e("div",{className:"CollectionPage__collection__docsTab__controls__density",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__density__label",children:"View:"}),o.locked?e(k,{label:"This collection is locked to the compact view",transition:"pop",withArrow:!0,children:_}):e(P,{position:"bottom",placement:"end",control:_,children:[e(P.Label,{children:"View density"}),R.map(c=>{let n=c.Icon,a=c.value===o.density;return e(P.Item,{icon:e(n,{size:18}),rightSection:a?e(q,{size:14,stroke:2.5}):void 0,onClick:()=>o.onChange(c.value),children:c.label},c.value)})]})]})}var se={slug:{asc:"slug",desc:"slugDesc",defaultDir:"asc"},title:{asc:"title",desc:"titleDesc",defaultDir:"asc"},created:{asc:"oldest",desc:"newest",defaultDir:"desc"},modified:{asc:"modifiedAtAsc",desc:"modifiedAt",defaultDir:"desc"}};function fe(o,i){let l=se[o];return!l||!i?null:i===l.asc?"asc":i===l.desc?"desc":null}function y(o){let i=se[o.column],l=fe(o.column,o.orderBy),_=l!==null;function c(){if(!o.onSort)return;let n;l==="asc"?n="desc":l==="desc"?n="asc":n=i.defaultDir,o.onSort(i[n])}return e("button",{type:"button",className:w("CollectionPage__collection__docsList__header__cell","CollectionPage__collection__docsList__header__cell--sortable",_&&"CollectionPage__collection__docsList__header__cell--active"),onClick:c,"aria-label":`Sort by ${o.label}`,children:[e("span",{children:o.label}),_&&(l==="asc"?e(J,{size:12,stroke:2.5}):e(G,{size:12,stroke:2.5}))]})}L.DocsList=o=>{let i=o.collection,l=window.__ROOT_CTX.collections[o.collection];if(!l)throw new Error(`could not find collection: ${i}`);let _=!!l.url,c=!!o.compact,n=o.docs||[],{getReleasesForDoc:a}=F(),s=c&&n.some(t=>a(t.id).length>0);function h(t){return _?oe({collectionId:i,slug:t}):""}function m(t){(t.action==="archive"||t.action==="copy"||t.action==="unarchive"||t.action==="delete"||t.action==="unpublish"||t.action==="locked"||t.action==="unlocked")&&o.reloadDocs()}return c?e("div",{className:w("CollectionPage__collection__docsList","CollectionPage__collection__docsList--compact",s&&"CollectionPage__collection__docsList--withRelease"),children:[e("div",{className:"CollectionPage__collection__docsList__header",children:[e("div",{className:"CollectionPage__collection__docsList__header__image"}),e(y,{column:"slug",label:"Slug",orderBy:o.orderBy,onSort:o.onSort}),e(y,{column:"title",label:"Title",orderBy:o.orderBy,onSort:o.onSort}),e("div",{className:"CollectionPage__collection__docsList__header__cell",children:"Status"}),s&&e("div",{className:"CollectionPage__collection__docsList__header__cell",children:"Release"}),e(y,{column:"created",label:"Created",orderBy:o.orderBy,onSort:o.onSort}),e(y,{column:"modified",label:"Modified",orderBy:o.orderBy,onSort:o.onSort}),e("div",{className:"CollectionPage__collection__docsList__header__controls"})]}),n.map(t=>{let d=`/cms/content/${i}/${t.slug}`,r=t.fields||{},p=C(r,l.preview?.title||"meta.title"),g=C(r,l.preview?.image||"meta.image")||l.preview?.defaultImage,f=s?a(t.id):[];return e("div",{className:"CollectionPage__collection__docsList__doc",children:[e("a",{className:"CollectionPage__collection__docsList__doc__image",href:d,children:e(A,{file:g,width:48,height:36,withPlaceholder:!g?.src})}),e("a",{className:"CollectionPage__collection__docsList__doc__docId",href:d,children:t.slug}),e("a",{className:"CollectionPage__collection__docsList__doc__title",href:d,children:p||"[UNTITLED]"}),e("div",{className:"CollectionPage__collection__docsList__doc__badges",children:e(S,{doc:t,hideReleases:!0})}),s&&e("div",{className:"CollectionPage__collection__docsList__doc__releases",children:f.map(v=>e(k,{transition:"pop",label:`In release: ${v.id}`,children:e($,{component:"a",href:`/cms/releases/${v.id}`,size:"xs",variant:"gradient",gradient:{from:"violet",to:"grape"},style:{cursor:"pointer"},children:v.id})},v.id))}),e("div",{className:"CollectionPage__collection__docsList__doc__timestamp",children:ae(t?.sys?.createdAt,t?.sys?.createdBy)}),e("div",{className:"CollectionPage__collection__docsList__doc__timestamp",children:ae(t?.sys?.modifiedAt,t?.sys?.modifiedBy)}),e("div",{className:"CollectionPage__collection__docsList__doc__controls",children:e(O,{docId:t.id,data:t,onAction:m})})]},t.id)})]}):e("div",{className:"CollectionPage__collection__docsList",children:n.map(t=>{let d=`/cms/content/${i}/${t.slug}`,r=h(t.slug),p=t.fields||{},g=C(p,l.preview?.title||"meta.title"),f=C(p,l.preview?.image||"meta.image")||l.preview?.defaultImage;return e("div",{className:"CollectionPage__collection__docsList__doc",children:[e("div",{className:"CollectionPage__collection__docsList__doc__image",children:e("a",{href:d,children:e(A,{file:f,width:120,height:90,withPlaceholder:!f?.src})})}),e("a",{className:"CollectionPage__collection__docsList__doc__content",href:d,children:[e("div",{className:"CollectionPage__collection__docsList__doc__content__header",children:[e("div",{className:"CollectionPage__collection__docsList__doc__content__header__docId",children:t.id}),e(S,{doc:t})]}),e("div",{className:"CollectionPage__collection__docsList__doc__content__title",children:g||"[UNTITLED]"}),_&&r&&e("div",{className:"CollectionPage__collection__docsList__doc__content__url",children:r})]}),e("div",{className:"CollectionPage__collection__docsList__doc__controls",children:e(O,{docId:t.id,data:t,onAction:m})})]},t.id)})})};function ae(o,i){return!o||typeof o.toMillis!="function"?e("span",{className:"CollectionPage__collection__docsList__doc__timestamp__value",children:"\u2014"}):e(H,{message:Y(o),user:i,children:e("span",{className:"CollectionPage__collection__docsList__doc__timestamp__value",children:Z(o.toMillis())})})}export{L as CollectionPage};
|
|
1
|
+
import{a as ne}from"./chunk-44ZU5WMI.js";import{a as _e}from"./chunk-OWYV43BT.js";import{h as O}from"./chunk-ZAJPNVYS.js";import{a as oe,e as te,j as le}from"./chunk-EYJ6GKZR.js";import"./chunk-HV3JJ5UT.js";import{b as F,c as H,d as S,f as A}from"./chunk-G5647K25.js";import"./chunk-VJRMR2JM.js";import{a as x}from"./chunk-QFDU6FXP.js";import"./chunk-JDW4UORS.js";import{a as B}from"./chunk-UJX25CXD.js";import"./chunk-Z2CRNO3I.js";import"./chunk-QRAFYIAW.js";import"./chunk-ATTW36EM.js";import"./chunk-YDO2EDVY.js";import{b as C}from"./chunk-5MV6XVGA.js";import"./chunk-PLYSJ7W5.js";import"./chunk-H37RXS4R.js";import{b as ee}from"./chunk-W5DOO6ID.js";import{a as Q}from"./chunk-YBHFGQ3Z.js";import"./chunk-2PTLQRTU.js";import"./chunk-PIJ3E47R.js";import"./chunk-NCZD5IWS.js";import{a as ce}from"./chunk-QLIIVG5Q.js";import{c as ie}from"./chunk-A7IZAHBZ.js";import"./chunk-AAHM6RYJ.js";import"./chunk-ISUGBMXC.js";import"./chunk-DZYYWCHX.js";import{B as Y,z as Z}from"./chunk-XOWWPE7X.js";import{d as V,e as w}from"./chunk-WASID5UU.js";import{$a as q,Ca as X,Fa as k,Ga as e,Ta as K,Ua as W,V as I,W as M,a as U,ab as G,ba as $,c as E,cb as J,da as D,fb as z,j as me,qa as P,za as j}from"./chunk-WRA24P66.js";import{d as N}from"./chunk-KUCVLANF.js";import"./chunk-7SK47HHZ.js";import"./chunk-DTMZLUNY.js";import"./chunk-PVAE643M.js";me();var R=[{value:"comfortable",label:"Comfortable",Icon:K},{value:"compact",label:"Compact",Icon:W}];function L(o){let{route:i}=V(),l=window.__ROOT_CTX.rootConfig.projectId;ce(o.collection?o.collection:"Content"),E(()=>{let c=window.__ROOT_CTX.collections,n=`root-cms::${l}::last_collection`;if(o.collection)window.localStorage.setItem(n,o.collection);else{let a=window.localStorage.getItem(n);if(a&&c[a]){i(`/cms/content/${a}`);return}if(window.__ROOT_CTX.collections.Pages){i("/cms/content/Pages");return}let s=Object.keys(window.__ROOT_CTX.collections)||[];if(s.length>0){let h=s[0];i(`/cms/content/${h}`);return}console.warn("no collections")}},[o.collection,l]);let _=window.__ROOT_CTX.collections;return e(ie,{children:e("div",{className:"CollectionPage",children:e("div",{className:"CollectionPage__layout",children:[e("div",{className:"CollectionPage__side",children:e(ne,{collections:_,activeCollectionId:o.collection,projectId:l})}),e("div",{className:"CollectionPage__main",children:o.collection&&e(L.Collection,{collection:o.collection},o.collection)})]})})})}L.Collection=o=>{let{roles:i}=Q(),l=window.firebase.user.email||"",_=ee(i,l),[c,n]=x(`root::CollectionPage:${o.collection}:orderBy`,"modifiedAt"),[a,s]=x(`root::CollectionPage:${o.collection}:showArchived`,!1),[h,m]=U(!1),t=window.__ROOT_CTX.collections[o.collection];if(!t)return route("/cms/content"),e(N,{});let d=!!t.viewOptions?.compact,[r,p]=x("root::CollectionPage:density","comfortable"),g=d?"compact":r,f=g==="compact",v=[{value:"slug",label:"A-Z"},{value:"slugDesc",label:"Z-A"},{value:"title",label:"Title (A-Z)"},{value:"titleDesc",label:"Title (Z-A)"},{value:"newest",label:"Newest"},{value:"oldest",label:"Oldest"},{value:"modifiedAt",label:"Last modified"},{value:"modifiedAtAsc",label:"Least recently modified"},...t.sortOptions?.map(u=>({value:u.id,label:u.label}))||[]],[b,de,T]=te(o.collection,{orderBy:c,includeArchived:a}),re=b&&T.length===0,ge=!b&&T.length===0;return e(N,{children:[e(le,{collection:o.collection,opened:h,onClose:()=>m(!1)}),e("div",{className:"CollectionPage__collection",children:e("div",{className:"CollectionPage__collection__docsTab",children:[e("div",{className:"CollectionPage__collection__docsTab__header",children:[e("div",{className:"CollectionPage__collection__docsTab__header__title",children:t.name||o.collection}),e("div",{className:"CollectionPage__collection__docsTab__controls",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__showArchived",children:e(X,{size:"sm",color:"dark",label:"Show archived:",checked:a,onChange:u=>s(!!u.currentTarget.checked)})}),e("div",{className:"CollectionPage__collection__docsTab__controls__sort",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__sort__label",children:"Sort:"}),e(j,{size:"xs",value:c,onChange:u=>n(u||"modifiedAt"),data:v})]}),e(pe,{density:g,locked:d,onChange:p}),e("div",{className:"CollectionPage__collection__docsTab__controls__newDoc",children:e(B,{label:"You don't have access to create new documents",condition:!_,children:e(D,{color:"dark",size:"xs",leftIcon:e(z,{size:16}),onClick:()=>m(!0),disabled:!_,children:"New"})})})]})]}),e(_e,{className:"CollectionPage__collection__docsTab__content",children:re?e("div",{className:"CollectionPage__collection__docsTab__content__loading",children:e(I,{color:"gray",size:"xl"})}):ge?e("div",{class:"CollectionPage__collection__docsEmpty",children:[e("div",{class:"CollectionPage__collection__docsEmpty__title",children:"Collection is empty."}),e("div",{class:"CollectionPage__collection__docsEmpty__button",children:e(B,{label:"You don't have access to create new documents",condition:!_,children:e(D,{color:"dark",size:"xs",leftIcon:e(z,{size:16}),onClick:()=>m(!0),disabled:!_,children:"New"})})})]}):e("div",{className:"CollectionPage__collection__docsTab__content__list",children:[b&&e("div",{className:"CollectionPage__collection__docsTab__content__reloading",children:e(I,{color:"gray",size:"md"})}),e("div",{className:w("CollectionPage__collection__docsTab__content__items",b&&"CollectionPage__collection__docsTab__content__items--loading"),children:e(L.DocsList,{collection:o.collection,docs:T,compact:f,orderBy:c,onSort:n,reloadDocs:()=>de()})})]})})]})})]})};function pe(o){let l=(R.find(c=>c.value===o.density)||R[0]).Icon,_=e(M,{variant:"default",color:"gray",size:30,disabled:o.locked,"aria-label":"Change view density",children:e(l,{size:16})});return e("div",{className:"CollectionPage__collection__docsTab__controls__density",children:[e("div",{className:"CollectionPage__collection__docsTab__controls__density__label",children:"View:"}),o.locked?e(k,{label:"This collection is locked to the compact view",transition:"pop",withArrow:!0,children:_}):e(P,{position:"bottom",placement:"end",control:_,children:[e(P.Label,{children:"View density"}),R.map(c=>{let n=c.Icon,a=c.value===o.density;return e(P.Item,{icon:e(n,{size:18}),rightSection:a?e(q,{size:14,stroke:2.5}):void 0,onClick:()=>o.onChange(c.value),children:c.label},c.value)})]})]})}var se={slug:{asc:"slug",desc:"slugDesc",defaultDir:"asc"},title:{asc:"title",desc:"titleDesc",defaultDir:"asc"},created:{asc:"oldest",desc:"newest",defaultDir:"desc"},modified:{asc:"modifiedAtAsc",desc:"modifiedAt",defaultDir:"desc"}};function fe(o,i){let l=se[o];return!l||!i?null:i===l.asc?"asc":i===l.desc?"desc":null}function y(o){let i=se[o.column],l=fe(o.column,o.orderBy),_=l!==null;function c(){if(!o.onSort)return;let n;l==="asc"?n="desc":l==="desc"?n="asc":n=i.defaultDir,o.onSort(i[n])}return e("button",{type:"button",className:w("CollectionPage__collection__docsList__header__cell","CollectionPage__collection__docsList__header__cell--sortable",_&&"CollectionPage__collection__docsList__header__cell--active"),onClick:c,"aria-label":`Sort by ${o.label}`,children:[e("span",{children:o.label}),_&&(l==="asc"?e(J,{size:12,stroke:2.5}):e(G,{size:12,stroke:2.5}))]})}L.DocsList=o=>{let i=o.collection,l=window.__ROOT_CTX.collections[o.collection];if(!l)throw new Error(`could not find collection: ${i}`);let _=!!l.url,c=!!o.compact,n=o.docs||[],{getReleasesForDoc:a}=F(),s=c&&n.some(t=>a(t.id).length>0);function h(t){return _?oe({collectionId:i,slug:t}):""}function m(t){(t.action==="archive"||t.action==="copy"||t.action==="unarchive"||t.action==="delete"||t.action==="unpublish"||t.action==="locked"||t.action==="unlocked")&&o.reloadDocs()}return c?e("div",{className:w("CollectionPage__collection__docsList","CollectionPage__collection__docsList--compact",s&&"CollectionPage__collection__docsList--withRelease"),children:[e("div",{className:"CollectionPage__collection__docsList__header",children:[e("div",{className:"CollectionPage__collection__docsList__header__image"}),e(y,{column:"slug",label:"Slug",orderBy:o.orderBy,onSort:o.onSort}),e(y,{column:"title",label:"Title",orderBy:o.orderBy,onSort:o.onSort}),e("div",{className:"CollectionPage__collection__docsList__header__cell",children:"Status"}),s&&e("div",{className:"CollectionPage__collection__docsList__header__cell",children:"Release"}),e(y,{column:"created",label:"Created",orderBy:o.orderBy,onSort:o.onSort}),e(y,{column:"modified",label:"Modified",orderBy:o.orderBy,onSort:o.onSort}),e("div",{className:"CollectionPage__collection__docsList__header__controls"})]}),n.map(t=>{let d=`/cms/content/${i}/${t.slug}`,r=t.fields||{},p=C(r,l.preview?.title||"meta.title"),g=C(r,l.preview?.image||"meta.image")||l.preview?.defaultImage,f=s?a(t.id):[];return e("div",{className:"CollectionPage__collection__docsList__doc",children:[e("a",{className:"CollectionPage__collection__docsList__doc__image",href:d,children:e(A,{file:g,width:48,height:36,withPlaceholder:!g?.src})}),e("a",{className:"CollectionPage__collection__docsList__doc__docId",href:d,children:t.slug}),e("a",{className:"CollectionPage__collection__docsList__doc__title",href:d,children:p||"[UNTITLED]"}),e("div",{className:"CollectionPage__collection__docsList__doc__badges",children:e(S,{doc:t,hideReleases:!0})}),s&&e("div",{className:"CollectionPage__collection__docsList__doc__releases",children:f.map(v=>e(k,{transition:"pop",label:`In release: ${v.id}`,children:e($,{component:"a",href:`/cms/releases/${v.id}`,size:"xs",variant:"gradient",gradient:{from:"violet",to:"grape"},style:{cursor:"pointer"},children:v.id})},v.id))}),e("div",{className:"CollectionPage__collection__docsList__doc__timestamp",children:ae(t?.sys?.createdAt,t?.sys?.createdBy)}),e("div",{className:"CollectionPage__collection__docsList__doc__timestamp",children:ae(t?.sys?.modifiedAt,t?.sys?.modifiedBy)}),e("div",{className:"CollectionPage__collection__docsList__doc__controls",children:e(O,{docId:t.id,data:t,onAction:m})})]},t.id)})]}):e("div",{className:"CollectionPage__collection__docsList",children:n.map(t=>{let d=`/cms/content/${i}/${t.slug}`,r=h(t.slug),p=t.fields||{},g=C(p,l.preview?.title||"meta.title"),f=C(p,l.preview?.image||"meta.image")||l.preview?.defaultImage;return e("div",{className:"CollectionPage__collection__docsList__doc",children:[e("div",{className:"CollectionPage__collection__docsList__doc__image",children:e("a",{href:d,children:e(A,{file:f,width:120,height:90,withPlaceholder:!f?.src})})}),e("a",{className:"CollectionPage__collection__docsList__doc__content",href:d,children:[e("div",{className:"CollectionPage__collection__docsList__doc__content__header",children:[e("div",{className:"CollectionPage__collection__docsList__doc__content__header__docId",children:t.id}),e(S,{doc:t})]}),e("div",{className:"CollectionPage__collection__docsList__doc__content__title",children:g||"[UNTITLED]"}),_&&r&&e("div",{className:"CollectionPage__collection__docsList__doc__content__url",children:r})]}),e("div",{className:"CollectionPage__collection__docsList__doc__controls",children:e(O,{docId:t.id,data:t,onAction:m})})]},t.id)})})};function ae(o,i){return!o||typeof o.toMillis!="function"?e("span",{className:"CollectionPage__collection__docsList__doc__timestamp__value",children:"\u2014"}):e(H,{message:Y(o),user:i,children:e("span",{className:"CollectionPage__collection__docsList__doc__timestamp__value",children:Z(o.toMillis())})})}export{L as CollectionPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as s}from"./chunk-
|
|
1
|
+
import{b as s}from"./chunk-6WJQBFN5.js";import"./chunk-QWB6MAPJ.js";import"./chunk-235TRWJF.js";import"./chunk-5MV6XVGA.js";import"./chunk-NCZD5IWS.js";import{a as m}from"./chunk-QLIIVG5Q.js";import{c as d}from"./chunk-A7IZAHBZ.js";import"./chunk-AAHM6RYJ.js";import"./chunk-ISUGBMXC.js";import"./chunk-DZYYWCHX.js";import"./chunk-XOWWPE7X.js";import{d as t}from"./chunk-WASID5UU.js";import{Ga as a,g as i,j as p}from"./chunk-WRA24P66.js";import"./chunk-KUCVLANF.js";import"./chunk-7SK47HHZ.js";import"./chunk-DTMZLUNY.js";import"./chunk-PVAE643M.js";p();function h(){let{query:r}=t();m("Compare");let o=i(()=>n(r.left||""),[r.left]),e=i(()=>n(r.right||""),[r.right]);return a(d,{children:a("div",{className:"ComparePage",children:o&&e?a(s,{className:"ComparePage__diff",left:o,right:e}):a("div",{className:"ComparePage__error",children:"Invalid params, double check query params."})})})}function n(r){let[o,e]=String(r).split("@");return o&&e?{docId:o,versionId:e}:null}export{h as ComparePage};
|