@lotics/app-sdk 0.118.1 → 0.119.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/dist/{chunk-XL5LZFGB.js → chunk-UFWVZOJE.js} +28 -1
- package/dist/index.js +22 -34
- package/dist/router.js +1 -1
- package/dist/rpc.d.ts +6 -0
- package/dist/viewer.d.ts +5 -0
- package/docs/members_and_options.md +5 -0
- package/package.json +1 -1
|
@@ -174,6 +174,30 @@ function transportErrorMessage(status, parsed) {
|
|
|
174
174
|
return status < 500 || authored ? jsonMessage : gatewayErrorMessage(status);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
// ../shared/src/utils.ts
|
|
178
|
+
function decimalPlaces(value) {
|
|
179
|
+
if (Number.isInteger(value)) return 0;
|
|
180
|
+
const [mantissa = "", exponent = "0"] = String(value).split("e");
|
|
181
|
+
const fraction = mantissa.split(".")[1]?.length ?? 0;
|
|
182
|
+
return Math.max(0, fraction - Number(exponent));
|
|
183
|
+
}
|
|
184
|
+
function sumDecimal(values, divisor = 1) {
|
|
185
|
+
const float = values.reduce((total2, value) => total2 + value, 0) / divisor;
|
|
186
|
+
if (!values.every(Number.isFinite)) return float;
|
|
187
|
+
const factor = 10 ** values.reduce((places, value) => Math.max(places, decimalPlaces(value)), 0);
|
|
188
|
+
const scaled = values.map((value) => Math.round(value * factor));
|
|
189
|
+
const total = scaled.reduce((sum, value) => sum + value, 0);
|
|
190
|
+
const exact = Number.isSafeInteger(total) && scaled.every((one, index) => Number.isSafeInteger(one) && one / factor === values[index]);
|
|
191
|
+
return exact ? total / (factor * divisor) : float;
|
|
192
|
+
}
|
|
193
|
+
function sample(arr) {
|
|
194
|
+
if (arr.length === 0) return void 0;
|
|
195
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
196
|
+
}
|
|
197
|
+
function assertNever(value) {
|
|
198
|
+
throw new Error(`Unhandled union member: ${JSON.stringify(value)}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
177
201
|
// ../shared/src/schemas/read_row.ts
|
|
178
202
|
var RECORD_ID_COLUMN = "__source_record_id";
|
|
179
203
|
|
|
@@ -205,7 +229,7 @@ function aggregateRows(rows, aggregate) {
|
|
|
205
229
|
...Object.fromEntries(by.map((column) => [column, first2?.[column] ?? null])),
|
|
206
230
|
...day === void 0 ? {} : { [AGGREGATE_DAY_COLUMN]: dayOf(first2?.[day]) },
|
|
207
231
|
[AGGREGATE_COUNT_COLUMN]: members.length,
|
|
208
|
-
...sum === void 0 ? {} : { [AGGREGATE_SUM_COLUMN]: figures.length === 0 ? null : figures
|
|
232
|
+
...sum === void 0 ? {} : { [AGGREGATE_SUM_COLUMN]: figures.length === 0 ? null : sumDecimal(figures) }
|
|
209
233
|
};
|
|
210
234
|
});
|
|
211
235
|
}
|
|
@@ -1200,6 +1224,9 @@ async function standaloneUpload(file, fidelity, place) {
|
|
|
1200
1224
|
|
|
1201
1225
|
export {
|
|
1202
1226
|
__export,
|
|
1227
|
+
sumDecimal,
|
|
1228
|
+
sample,
|
|
1229
|
+
assertNever,
|
|
1203
1230
|
AGGREGATE_COUNT_COLUMN,
|
|
1204
1231
|
AGGREGATE_SUM_COLUMN,
|
|
1205
1232
|
aggregateRows,
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
aggregateRows,
|
|
7
7
|
anyRecordingLive,
|
|
8
8
|
applyPatch,
|
|
9
|
+
assertNever,
|
|
9
10
|
decodeAll,
|
|
10
11
|
encodePatch,
|
|
11
12
|
getUrlParams,
|
|
@@ -20,12 +21,14 @@ import {
|
|
|
20
21
|
rpc,
|
|
21
22
|
rpcAgentRun,
|
|
22
23
|
rpcAgentRunContinue,
|
|
24
|
+
sample,
|
|
23
25
|
setUrlParams,
|
|
24
26
|
subscribeQueriesChanged,
|
|
25
27
|
subscribeRecordings,
|
|
26
28
|
subscribeUrlParams,
|
|
29
|
+
sumDecimal,
|
|
27
30
|
urlParam
|
|
28
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-UFWVZOJE.js";
|
|
29
32
|
|
|
30
33
|
// src/mount.tsx
|
|
31
34
|
import { createRoot } from "react-dom/client";
|
|
@@ -1723,15 +1726,6 @@ var customRandom = (alphabet, defaultSize, getRandom) => {
|
|
|
1723
1726
|
};
|
|
1724
1727
|
var customAlphabet = (alphabet, size2 = 21) => customRandom(alphabet, size2 | 0, random);
|
|
1725
1728
|
|
|
1726
|
-
// ../shared/src/utils.ts
|
|
1727
|
-
function sample(arr) {
|
|
1728
|
-
if (arr.length === 0) return void 0;
|
|
1729
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
1730
|
-
}
|
|
1731
|
-
function assertNever(value) {
|
|
1732
|
-
throw new Error(`Unhandled union member: ${JSON.stringify(value)}`);
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
1729
|
// ../shared/src/expression_array.ts
|
|
1736
1730
|
var expression_array_exports = {};
|
|
1737
1731
|
__export(expression_array_exports, {
|
|
@@ -1790,6 +1784,9 @@ function getField(obj, field) {
|
|
|
1790
1784
|
}
|
|
1791
1785
|
return value;
|
|
1792
1786
|
}
|
|
1787
|
+
function addends(values2) {
|
|
1788
|
+
return values2.map((value) => typeof value === "number" ? value : 0);
|
|
1789
|
+
}
|
|
1793
1790
|
function countInto(result, key) {
|
|
1794
1791
|
defineOwn(result, key, (Object.hasOwn(result, key) ? result[key] : 0) + 1);
|
|
1795
1792
|
}
|
|
@@ -1847,14 +1844,10 @@ function sumBy(arr, fieldOrCb) {
|
|
|
1847
1844
|
if (typeof fieldOrCb !== "string") {
|
|
1848
1845
|
throw new Error("sumBy: second arg must be a function or field path string");
|
|
1849
1846
|
}
|
|
1850
|
-
return arr.
|
|
1851
|
-
const val = getField(item, fieldOrCb);
|
|
1852
|
-
return sum2 + (typeof val === "number" ? val : 0);
|
|
1853
|
-
}, 0);
|
|
1847
|
+
return sumDecimal(addends(arr.map((item) => getField(item, fieldOrCb))));
|
|
1854
1848
|
}
|
|
1855
1849
|
async function sumByCallback(arr, cb) {
|
|
1856
|
-
|
|
1857
|
-
return values2.reduce((sum2, val) => sum2 + (typeof val === "number" ? val : 0), 0);
|
|
1850
|
+
return sumDecimal(addends(await callEach(arr, cb)));
|
|
1858
1851
|
}
|
|
1859
1852
|
function meanBy(arr, fieldOrCb) {
|
|
1860
1853
|
if (!Array.isArray(arr)) {
|
|
@@ -1865,19 +1858,13 @@ function meanBy(arr, fieldOrCb) {
|
|
|
1865
1858
|
}
|
|
1866
1859
|
if (isCallback(fieldOrCb)) {
|
|
1867
1860
|
assertCallbackInput("meanBy", arr);
|
|
1868
|
-
return callEach(arr, fieldOrCb).then(
|
|
1869
|
-
(vals) => vals.reduce((acc, v) => acc + (typeof v === "number" ? v : 0), 0) / arr.length
|
|
1870
|
-
);
|
|
1861
|
+
return callEach(arr, fieldOrCb).then((values2) => sumDecimal(addends(values2), arr.length));
|
|
1871
1862
|
}
|
|
1872
1863
|
const field = fieldOrCb;
|
|
1873
1864
|
if (typeof field !== "string") {
|
|
1874
1865
|
throw new Error("meanBy: second arg must be a function or field path string");
|
|
1875
1866
|
}
|
|
1876
|
-
|
|
1877
|
-
const val = getField(item, field);
|
|
1878
|
-
return acc + (typeof val === "number" ? val : 0);
|
|
1879
|
-
}, 0);
|
|
1880
|
-
return sum2 / arr.length;
|
|
1867
|
+
return sumDecimal(addends(arr.map((item) => getField(item, field))), arr.length);
|
|
1881
1868
|
}
|
|
1882
1869
|
function minBy(arr, fieldOrCb) {
|
|
1883
1870
|
if (!Array.isArray(arr)) {
|
|
@@ -2842,9 +2829,7 @@ function mean(arr) {
|
|
|
2842
2829
|
if (present.length === 0) {
|
|
2843
2830
|
return null;
|
|
2844
2831
|
}
|
|
2845
|
-
const
|
|
2846
|
-
const total = numArr.reduce((a, b) => a + b, 0);
|
|
2847
|
-
const result = total / numArr.length;
|
|
2832
|
+
const result = present.every((item) => typeof item === "number") ? sumDecimal(present, present.length) : NaN;
|
|
2848
2833
|
if (isNaN(result)) {
|
|
2849
2834
|
throw new Error("mean: array contains non-numeric values");
|
|
2850
2835
|
}
|
|
@@ -2923,7 +2908,11 @@ function sum(arr) {
|
|
|
2923
2908
|
if (!Array.isArray(arr)) {
|
|
2924
2909
|
throw new Error("sum: expected array, got " + typeof arr);
|
|
2925
2910
|
}
|
|
2926
|
-
|
|
2911
|
+
const present = arr.filter((item) => item != null);
|
|
2912
|
+
if (!present.every((item) => typeof item === "number")) {
|
|
2913
|
+
throw new Error("sum: array contains non-numeric values");
|
|
2914
|
+
}
|
|
2915
|
+
return sumDecimal(present);
|
|
2927
2916
|
}
|
|
2928
2917
|
function abs(n) {
|
|
2929
2918
|
if (n == null) return null;
|
|
@@ -21239,19 +21228,17 @@ function aggregateNumberField(values2, operation) {
|
|
|
21239
21228
|
}
|
|
21240
21229
|
switch (operation) {
|
|
21241
21230
|
case "sum": {
|
|
21242
|
-
|
|
21243
|
-
return { result: sum2 };
|
|
21231
|
+
return { result: sumDecimal(numericValues) };
|
|
21244
21232
|
}
|
|
21245
21233
|
case "avg": {
|
|
21246
|
-
const
|
|
21247
|
-
const average = sum2 / numericValues.length;
|
|
21234
|
+
const average = sumDecimal(numericValues, numericValues.length);
|
|
21248
21235
|
return { result: average };
|
|
21249
21236
|
}
|
|
21250
21237
|
case "median": {
|
|
21251
21238
|
const sorted = [...numericValues].sort((a, b) => a - b);
|
|
21252
21239
|
const middle = Math.floor(sorted.length / 2);
|
|
21253
21240
|
if (sorted.length % 2 === 0) {
|
|
21254
|
-
const median = (sorted[middle - 1]
|
|
21241
|
+
const median = sumDecimal([sorted[middle - 1], sorted[middle]], 2);
|
|
21255
21242
|
return { result: median };
|
|
21256
21243
|
} else {
|
|
21257
21244
|
return { result: sorted[middle] };
|
|
@@ -21268,7 +21255,7 @@ function aggregateNumberField(values2, operation) {
|
|
|
21268
21255
|
case "range": {
|
|
21269
21256
|
const min3 = Math.min(...numericValues);
|
|
21270
21257
|
const max3 = Math.max(...numericValues);
|
|
21271
|
-
const range2 = max3 -
|
|
21258
|
+
const range2 = sumDecimal([max3, -min3]);
|
|
21272
21259
|
return { result: range2 };
|
|
21273
21260
|
}
|
|
21274
21261
|
default:
|
|
@@ -28984,6 +28971,7 @@ function useAppContext() {
|
|
|
28984
28971
|
memberId: data?.member_id ?? null,
|
|
28985
28972
|
groupIds: data?.group_ids ?? null,
|
|
28986
28973
|
absences: data?.absences ?? null,
|
|
28974
|
+
openableApps: data?.openable_apps ?? null,
|
|
28987
28975
|
commentsEnabled: data?.comments_enabled ?? false,
|
|
28988
28976
|
recordingEnabled: data?.recording_enabled === true,
|
|
28989
28977
|
timezone: data?.timezone,
|
package/dist/router.js
CHANGED
package/dist/rpc.d.ts
CHANGED
|
@@ -77,6 +77,12 @@ export interface AppContext {
|
|
|
77
77
|
/** Who in the organization is away, or will be, and who stands in — absent from an older host and for a visitor from
|
|
78
78
|
* outside the organization. */
|
|
79
79
|
absences?: AppAbsence[];
|
|
80
|
+
/** The apps of the workspace the viewer can open, each by its id and its name — absent from an older host,
|
|
81
|
+
* for a visitor and until the host has listed them. */
|
|
82
|
+
openable_apps?: {
|
|
83
|
+
id: string;
|
|
84
|
+
name: string;
|
|
85
|
+
}[];
|
|
80
86
|
}
|
|
81
87
|
/** Whether a Lotics host embeds the app, rather than it standing alone on its own origin. */
|
|
82
88
|
export declare function isEmbedded(): boolean;
|
package/dist/viewer.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export declare function useAppContext(): {
|
|
|
14
14
|
groupIds: readonly string[] | null;
|
|
15
15
|
/** Who in the organization is away, or will be, and who stands in; `null` where the host did not say. */
|
|
16
16
|
absences: readonly AppAbsence[] | null;
|
|
17
|
+
/** The apps the viewer can open, by id and name; `null` where the host did not say. */
|
|
18
|
+
openableApps: readonly {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}[] | null;
|
|
17
22
|
commentsEnabled: boolean;
|
|
18
23
|
recordingEnabled: boolean;
|
|
19
24
|
timezone: string | undefined;
|
|
@@ -261,6 +261,11 @@ host did not say (a visitor from outside the organization, an older host). Both
|
|
|
261
261
|
context, read once as the app opens. Display only: the workflow body re-checks who may act
|
|
262
262
|
(`current_member_stands_in_for(...)`).
|
|
263
263
|
|
|
264
|
+
`openableApps` lists the workspace's apps the viewer can open, each by its `id` and its `name` — what a
|
|
265
|
+
way through to a sibling app (`openApp`) is offered by. `null` where the host did not say (standalone, a
|
|
266
|
+
render, an older host, or a page that had not listed its apps when the app opened). Display only: the
|
|
267
|
+
app opened checks the viewer itself.
|
|
268
|
+
|
|
264
269
|
## The workspace's zone at the root
|
|
265
270
|
|
|
266
271
|
An app's root draws nothing until `useAppContext()` has `settled` — where it failed, it draws
|
package/package.json
CHANGED