@malloydata/malloy-explorer 0.0.278-dev250515234639 → 0.0.282-dev250527225235
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/@flowtypes/components/MalloyExplorerProvider.flow.js +3 -1
- package/dist/cjs/index.cjs +372 -168
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +373 -169
- package/dist/esm/index.js.map +1 -1
- package/dist/types/components/MalloyExplorerProvider.d.ts +4 -2
- package/dist/types/components/MalloyQueryFocusProvider.d.ts +18 -0
- package/dist/types/components/QueryPanel/FocusableView.d.ts +7 -0
- package/dist/types/components/SourcePanel/hooks/useOperations.d.ts +4 -0
- package/dist/types/components/contexts/NestViewPathContext.d.ts +2 -0
- package/dist/types/components/utils/segment.d.ts +4 -0
- package/dist/types/contexts/QueryEditorContext.d.ts +2 -13
- package/package.json +9 -6
package/dist/esm/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
|
17
17
|
import * as React from "react";
|
|
18
18
|
import React__default, { useLayoutEffect, useEffect, useMemo, useState, useRef, createElement, useContext, useCallback, createContext, memo, useReducer } from "react";
|
|
19
19
|
import * as QB from "@malloydata/malloy-query-builder";
|
|
20
|
-
import { ASTArrowQueryDefinition, ASTSegmentViewDefinition, ASTRefinementViewDefinition, ASTOrderByViewOperation,
|
|
20
|
+
import { ASTArrowQueryDefinition, ASTArrowViewDefinition, ASTSegmentViewDefinition, ASTNestViewOperation, ASTRefinementViewDefinition, ASTOrderByViewOperation, ASTGroupByViewOperation, ASTAggregateViewOperation, ASTLimitViewOperation, ASTTimeTruncationExpression, ASTFilterWithFilterString, ASTWhereViewOperation, ASTHavingViewOperation, ASTDrillViewOperation } from "@malloydata/malloy-query-builder";
|
|
21
21
|
import { Tag } from "@malloydata/malloy-tag";
|
|
22
22
|
import { TemporalFilterExpression, BooleanFilterExpression, NumberFilterExpression, StringFilterExpression } from "@malloydata/malloy-filter";
|
|
23
23
|
import "@malloydata/render/webcomponent";
|
|
@@ -3324,29 +3324,105 @@ function useQueryBuilder(source, query) {
|
|
|
3324
3324
|
}
|
|
3325
3325
|
}, [source, query]);
|
|
3326
3326
|
}
|
|
3327
|
+
const MalloyQueryFocusContext = /* @__PURE__ */ React.createContext({
|
|
3328
|
+
focusMainView: () => {
|
|
3329
|
+
},
|
|
3330
|
+
isMainViewFocused: true,
|
|
3331
|
+
focusNestView: () => {
|
|
3332
|
+
},
|
|
3333
|
+
isNestViewFocused: () => false,
|
|
3334
|
+
focusedNestView: null
|
|
3335
|
+
});
|
|
3336
|
+
function MalloyQueryFocusProvider({
|
|
3337
|
+
rootQuery,
|
|
3338
|
+
focusedNestViewPath,
|
|
3339
|
+
onFocusedNestViewPathChange,
|
|
3340
|
+
children
|
|
3341
|
+
}) {
|
|
3342
|
+
const focusedNestView = React.useMemo(() => {
|
|
3343
|
+
if (focusedNestViewPath.length === 0) {
|
|
3344
|
+
return null;
|
|
3345
|
+
}
|
|
3346
|
+
if (rootQuery) {
|
|
3347
|
+
const queryDef = rootQuery.definition;
|
|
3348
|
+
if (queryDef instanceof ASTArrowQueryDefinition) {
|
|
3349
|
+
return findNestView(queryDef.view, [...focusedNestViewPath].reverse());
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
return null;
|
|
3353
|
+
}, [rootQuery, focusedNestViewPath]);
|
|
3354
|
+
const focusMainView = React.useCallback(() => {
|
|
3355
|
+
onFocusedNestViewPathChange([]);
|
|
3356
|
+
}, [onFocusedNestViewPathChange]);
|
|
3357
|
+
const focusNestView = React.useCallback((path) => {
|
|
3358
|
+
onFocusedNestViewPathChange([...path]);
|
|
3359
|
+
}, [onFocusedNestViewPathChange]);
|
|
3360
|
+
const isNestViewFocused = React.useCallback((path) => {
|
|
3361
|
+
return JSON.stringify(path) === JSON.stringify(focusedNestViewPath);
|
|
3362
|
+
}, [focusedNestViewPath]);
|
|
3363
|
+
const isMainViewFocused = focusedNestViewPath.length === 0;
|
|
3364
|
+
return /* @__PURE__ */ jsx(MalloyQueryFocusContext.Provider, {
|
|
3365
|
+
value: {
|
|
3366
|
+
focusMainView,
|
|
3367
|
+
isMainViewFocused,
|
|
3368
|
+
focusNestView,
|
|
3369
|
+
isNestViewFocused,
|
|
3370
|
+
focusedNestView
|
|
3371
|
+
},
|
|
3372
|
+
children
|
|
3373
|
+
});
|
|
3374
|
+
}
|
|
3375
|
+
function useQueryFocus() {
|
|
3376
|
+
return React.useContext(MalloyQueryFocusContext);
|
|
3377
|
+
}
|
|
3378
|
+
const findNestView = (currentView, remainingPath) => {
|
|
3379
|
+
if (remainingPath.length === 0) {
|
|
3380
|
+
return null;
|
|
3381
|
+
}
|
|
3382
|
+
if (currentView instanceof ASTArrowViewDefinition) {
|
|
3383
|
+
return findNestView(currentView.view, remainingPath);
|
|
3384
|
+
}
|
|
3385
|
+
if (currentView instanceof ASTSegmentViewDefinition) {
|
|
3386
|
+
const currentNestName = remainingPath.pop();
|
|
3387
|
+
const currentNestOperation = currentView.operations.items.find((operation) => operation instanceof ASTNestViewOperation && operation.name === currentNestName);
|
|
3388
|
+
if (currentNestOperation === void 0) {
|
|
3389
|
+
remainingPath.push(currentNestName);
|
|
3390
|
+
return null;
|
|
3391
|
+
} else if (remainingPath.length === 0) {
|
|
3392
|
+
return currentNestOperation.view;
|
|
3393
|
+
} else {
|
|
3394
|
+
return findNestView(currentNestOperation.view.definition, remainingPath);
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
if (currentView instanceof ASTRefinementViewDefinition) {
|
|
3398
|
+
return findNestView(currentView.refinement, remainingPath);
|
|
3399
|
+
}
|
|
3400
|
+
return null;
|
|
3401
|
+
};
|
|
3327
3402
|
function MalloyExplorerProvider({
|
|
3328
3403
|
source,
|
|
3329
3404
|
query,
|
|
3330
|
-
|
|
3405
|
+
onQueryChange,
|
|
3406
|
+
focusedNestViewPath,
|
|
3407
|
+
onFocusedNestViewPathChange,
|
|
3331
3408
|
children,
|
|
3332
3409
|
topValues
|
|
3333
3410
|
}) {
|
|
3334
3411
|
const rootQuery = useQueryBuilder(source, query);
|
|
3335
|
-
const [currentNestView, setCurrentNestView] = React.useState(null);
|
|
3336
|
-
const [currentNestQueryPanel, setCurrentNestQueryPanel] = React.useState(null);
|
|
3337
3412
|
return /* @__PURE__ */ jsx(TooltipProvider, {
|
|
3338
|
-
children: /* @__PURE__ */ jsx(
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3413
|
+
children: /* @__PURE__ */ jsx(MalloyQueryFocusProvider, {
|
|
3414
|
+
rootQuery,
|
|
3415
|
+
focusedNestViewPath,
|
|
3416
|
+
onFocusedNestViewPathChange,
|
|
3417
|
+
children: /* @__PURE__ */ jsx(QueryEditorContext.Provider, {
|
|
3418
|
+
value: {
|
|
3419
|
+
source,
|
|
3420
|
+
rootQuery,
|
|
3421
|
+
setQuery: onQueryChange,
|
|
3422
|
+
topValues
|
|
3423
|
+
},
|
|
3424
|
+
children
|
|
3425
|
+
})
|
|
3350
3426
|
})
|
|
3351
3427
|
});
|
|
3352
3428
|
}
|
|
@@ -25863,13 +25939,14 @@ function QueryActionBar({
|
|
|
25863
25939
|
const {
|
|
25864
25940
|
rootQuery,
|
|
25865
25941
|
setQuery,
|
|
25866
|
-
source
|
|
25867
|
-
onCurrentNestQueryPanelChange,
|
|
25868
|
-
onCurrentNestViewChange
|
|
25942
|
+
source
|
|
25869
25943
|
} = useContext(QueryEditorContext);
|
|
25870
25944
|
const {
|
|
25871
25945
|
onCollapse
|
|
25872
25946
|
} = useContext(ResizableCollapsiblePanelContext);
|
|
25947
|
+
const {
|
|
25948
|
+
focusMainView
|
|
25949
|
+
} = useQueryFocus();
|
|
25873
25950
|
const isQueryEmpty = !rootQuery || rootQuery.isEmpty();
|
|
25874
25951
|
const isRunEnabled = rootQuery == null ? void 0 : rootQuery.isRunnable();
|
|
25875
25952
|
const onRunQuery = () => {
|
|
@@ -25877,10 +25954,6 @@ function QueryActionBar({
|
|
|
25877
25954
|
runQuery(source, rootQuery.build());
|
|
25878
25955
|
}
|
|
25879
25956
|
};
|
|
25880
|
-
const focusMainQueryPanel = () => {
|
|
25881
|
-
onCurrentNestViewChange == null ? void 0 : onCurrentNestViewChange(null);
|
|
25882
|
-
onCurrentNestQueryPanelChange == null ? void 0 : onCurrentNestQueryPanelChange(null);
|
|
25883
|
-
};
|
|
25884
25957
|
return /* @__PURE__ */ jsxs("div", {
|
|
25885
25958
|
...{
|
|
25886
25959
|
className: "mly78zum5 mly1qughib mly6s0dn4 mlye8ttls"
|
|
@@ -25901,7 +25974,7 @@ function QueryActionBar({
|
|
|
25901
25974
|
},
|
|
25902
25975
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
25903
25976
|
onClick: () => {
|
|
25904
|
-
|
|
25977
|
+
focusMainView();
|
|
25905
25978
|
setQuery == null ? void 0 : setQuery(void 0);
|
|
25906
25979
|
},
|
|
25907
25980
|
isDisabled: !rootQuery || (rootQuery == null ? void 0 : rootQuery.isEmpty()),
|
|
@@ -29932,6 +30005,11 @@ function getViewDefinition(parent) {
|
|
|
29932
30005
|
return parent instanceof ASTArrowQueryDefinition ? parent.view : parent.definition;
|
|
29933
30006
|
}
|
|
29934
30007
|
function getInputSchemaFromViewParent(parent) {
|
|
30008
|
+
if (!parent) {
|
|
30009
|
+
return {
|
|
30010
|
+
fields: []
|
|
30011
|
+
};
|
|
30012
|
+
}
|
|
29935
30013
|
const definition = getViewDefinition(parent);
|
|
29936
30014
|
return definition.getInputSchema();
|
|
29937
30015
|
}
|
|
@@ -32382,12 +32460,54 @@ const styles$g = {
|
|
|
32382
32460
|
$$css: true
|
|
32383
32461
|
}
|
|
32384
32462
|
};
|
|
32463
|
+
function toFullName(path, name) {
|
|
32464
|
+
return [...path || [], name].join(".");
|
|
32465
|
+
}
|
|
32385
32466
|
function segmentHasLimit(segment) {
|
|
32386
32467
|
return segment.operations.items.find((operation) => operation instanceof ASTLimitViewOperation) !== void 0;
|
|
32387
32468
|
}
|
|
32388
32469
|
function segmentHasOrderBy(segment, name) {
|
|
32389
32470
|
return segment.operations.items.find((operation) => operation instanceof ASTOrderByViewOperation && operation.name === name) !== void 0;
|
|
32390
32471
|
}
|
|
32472
|
+
function getOutputNameToInputNameMap(segment) {
|
|
32473
|
+
const nameMap = /* @__PURE__ */ new Map();
|
|
32474
|
+
for (const operation of segment.operations.items) {
|
|
32475
|
+
if (operation instanceof ASTGroupByViewOperation || operation instanceof ASTAggregateViewOperation) {
|
|
32476
|
+
const reference = operation.field.getReference();
|
|
32477
|
+
if (reference) {
|
|
32478
|
+
nameMap.set(operation.name, toFullName(reference.path, reference.name));
|
|
32479
|
+
}
|
|
32480
|
+
}
|
|
32481
|
+
}
|
|
32482
|
+
return nameMap;
|
|
32483
|
+
}
|
|
32484
|
+
function segmentHasOrderBySourceField(segment, path, name) {
|
|
32485
|
+
const nameMap = getOutputNameToInputNameMap(segment);
|
|
32486
|
+
const fullInputName = toFullName(path, name);
|
|
32487
|
+
return !!segment.operations.items.find((operation) => {
|
|
32488
|
+
if (operation instanceof ASTOrderByViewOperation && nameMap.has(operation.name)) {
|
|
32489
|
+
return fullInputName === nameMap.get(operation.name);
|
|
32490
|
+
}
|
|
32491
|
+
return false;
|
|
32492
|
+
});
|
|
32493
|
+
}
|
|
32494
|
+
function areReferencesEqual(path1, name1, path2, name2) {
|
|
32495
|
+
return name1 === name2 && (path1 || []).join(".") === (path2 || []).join(".");
|
|
32496
|
+
}
|
|
32497
|
+
function segmentHasFieldInOutputSpace(segment, path, name) {
|
|
32498
|
+
const match = segment.operations.items.find((operation) => {
|
|
32499
|
+
if (operation instanceof ASTGroupByViewOperation || operation instanceof ASTAggregateViewOperation) {
|
|
32500
|
+
const reference = operation.field.getReference();
|
|
32501
|
+
if (reference) {
|
|
32502
|
+
return areReferencesEqual(path, name, reference.path, reference.name);
|
|
32503
|
+
} else {
|
|
32504
|
+
return false;
|
|
32505
|
+
}
|
|
32506
|
+
}
|
|
32507
|
+
return false;
|
|
32508
|
+
});
|
|
32509
|
+
return !!match;
|
|
32510
|
+
}
|
|
32391
32511
|
function segmentNestNo(segment, name) {
|
|
32392
32512
|
return segment.operations.items.reduce((acc, operation) => {
|
|
32393
32513
|
if (operation instanceof ASTNestViewOperation) {
|
|
@@ -32442,6 +32562,19 @@ function addNest(view, field) {
|
|
|
32442
32562
|
}
|
|
32443
32563
|
segment.addNest(field.name, rename);
|
|
32444
32564
|
}
|
|
32565
|
+
function addOrderByFromSource(view, path, name, direction = "desc") {
|
|
32566
|
+
const fullInputName = toFullName(path, name);
|
|
32567
|
+
let orderByName = name;
|
|
32568
|
+
const segment = view.getOrAddDefaultSegment();
|
|
32569
|
+
const nameMap = getOutputNameToInputNameMap(segment);
|
|
32570
|
+
for (const entry of nameMap.entries()) {
|
|
32571
|
+
if (entry[1] === fullInputName) {
|
|
32572
|
+
orderByName = entry[0];
|
|
32573
|
+
break;
|
|
32574
|
+
}
|
|
32575
|
+
}
|
|
32576
|
+
segment.addOrderBy(orderByName, direction);
|
|
32577
|
+
}
|
|
32445
32578
|
function addOrderBy(view, field, direction = "desc") {
|
|
32446
32579
|
const segment = view.getOrAddDefaultSegment();
|
|
32447
32580
|
segment.addOrderBy(field.name, direction);
|
|
@@ -32455,6 +32588,9 @@ function addFilter(view, field, path, filter) {
|
|
|
32455
32588
|
}
|
|
32456
32589
|
}
|
|
32457
32590
|
function getSegmentIfPresent(parent) {
|
|
32591
|
+
if (!parent) {
|
|
32592
|
+
return void 0;
|
|
32593
|
+
}
|
|
32458
32594
|
const definition = getViewDefinition(parent);
|
|
32459
32595
|
if (definition instanceof ASTSegmentViewDefinition) {
|
|
32460
32596
|
return definition;
|
|
@@ -33083,11 +33219,12 @@ function SortableOperation({
|
|
|
33083
33219
|
operation,
|
|
33084
33220
|
color
|
|
33085
33221
|
}) {
|
|
33222
|
+
var _a2;
|
|
33086
33223
|
const {
|
|
33087
33224
|
setQuery
|
|
33088
33225
|
} = useContext(QueryEditorContext);
|
|
33089
33226
|
const fieldInfo = operation.getFieldInfo();
|
|
33090
|
-
const path = operation.field.getReference().path ?? NULL_PATH;
|
|
33227
|
+
const path = ((_a2 = operation.field.getReference()) == null ? void 0 : _a2.path) ?? NULL_PATH;
|
|
33091
33228
|
const {
|
|
33092
33229
|
attributes,
|
|
33093
33230
|
listeners,
|
|
@@ -33288,28 +33425,62 @@ const parsedToLabels = (parsed, filterString) => {
|
|
|
33288
33425
|
value = stringClause.escaped_values.join(", ");
|
|
33289
33426
|
break;
|
|
33290
33427
|
case "=":
|
|
33291
|
-
|
|
33292
|
-
|
|
33428
|
+
{
|
|
33429
|
+
const {
|
|
33430
|
+
not,
|
|
33431
|
+
values
|
|
33432
|
+
} = stringClause;
|
|
33433
|
+
op = not ? "is not" : "is";
|
|
33434
|
+
value = values.join(", ");
|
|
33435
|
+
}
|
|
33293
33436
|
break;
|
|
33294
33437
|
case "contains":
|
|
33295
|
-
|
|
33296
|
-
|
|
33438
|
+
{
|
|
33439
|
+
const {
|
|
33440
|
+
not,
|
|
33441
|
+
values
|
|
33442
|
+
} = stringClause;
|
|
33443
|
+
op = not ? "does not contain" : "contains";
|
|
33444
|
+
value = values.join(", ");
|
|
33445
|
+
}
|
|
33297
33446
|
break;
|
|
33298
33447
|
case "starts":
|
|
33299
|
-
|
|
33300
|
-
|
|
33448
|
+
{
|
|
33449
|
+
const {
|
|
33450
|
+
not,
|
|
33451
|
+
values
|
|
33452
|
+
} = stringClause;
|
|
33453
|
+
op = not ? "does not start with" : "starts with";
|
|
33454
|
+
value = values.join(", ");
|
|
33455
|
+
}
|
|
33301
33456
|
break;
|
|
33302
33457
|
case "ends":
|
|
33303
|
-
|
|
33304
|
-
|
|
33458
|
+
{
|
|
33459
|
+
const {
|
|
33460
|
+
not,
|
|
33461
|
+
values
|
|
33462
|
+
} = stringClause;
|
|
33463
|
+
op = not ? "does not end with" : "ends with";
|
|
33464
|
+
value = values.join(", ");
|
|
33465
|
+
}
|
|
33305
33466
|
break;
|
|
33306
33467
|
case "empty":
|
|
33307
|
-
|
|
33308
|
-
|
|
33468
|
+
{
|
|
33469
|
+
const {
|
|
33470
|
+
not
|
|
33471
|
+
} = stringClause;
|
|
33472
|
+
op = not ? "is not empty" : "is empty";
|
|
33473
|
+
value = "";
|
|
33474
|
+
}
|
|
33309
33475
|
break;
|
|
33310
33476
|
case "null":
|
|
33311
|
-
|
|
33312
|
-
|
|
33477
|
+
{
|
|
33478
|
+
const {
|
|
33479
|
+
not
|
|
33480
|
+
} = stringClause;
|
|
33481
|
+
op = not ? "is not" : "is";
|
|
33482
|
+
value = "null";
|
|
33483
|
+
}
|
|
33313
33484
|
break;
|
|
33314
33485
|
}
|
|
33315
33486
|
}
|
|
@@ -33473,22 +33644,27 @@ function SingleFilterOperation({
|
|
|
33473
33644
|
rootQuery,
|
|
33474
33645
|
filterOperation
|
|
33475
33646
|
}) {
|
|
33647
|
+
const {
|
|
33648
|
+
setQuery
|
|
33649
|
+
} = useContext(QueryEditorContext);
|
|
33650
|
+
const setFilter = useCallback((filter2) => {
|
|
33651
|
+
if (filterOperation.filter instanceof ASTFilterWithFilterString) {
|
|
33652
|
+
filterOperation.filter.setFilter(filter2);
|
|
33653
|
+
}
|
|
33654
|
+
setQuery == null ? void 0 : setQuery(rootQuery.build());
|
|
33655
|
+
}, [filterOperation.filter, rootQuery, setQuery]);
|
|
33656
|
+
if (!(filterOperation.filter instanceof ASTFilterWithFilterString)) {
|
|
33657
|
+
return null;
|
|
33658
|
+
}
|
|
33476
33659
|
const {
|
|
33477
33660
|
fieldReference,
|
|
33478
33661
|
filterString
|
|
33479
33662
|
} = filterOperation.filter;
|
|
33480
33663
|
const filter = filterOperation.filter.getFilter();
|
|
33481
33664
|
const fieldInfo = fieldReference.getFieldInfo();
|
|
33482
|
-
const {
|
|
33483
|
-
setQuery
|
|
33484
|
-
} = useContext(QueryEditorContext);
|
|
33485
33665
|
if (fieldInfo.kind !== "dimension" && fieldInfo.kind !== "measure") {
|
|
33486
33666
|
throw new Error(`Invalid filter field kind: ${fieldInfo.kind}`);
|
|
33487
33667
|
}
|
|
33488
|
-
const setFilter = useCallback((filter2) => {
|
|
33489
|
-
filterOperation.filter.setFilter(filter2);
|
|
33490
|
-
setQuery == null ? void 0 : setQuery(rootQuery.build());
|
|
33491
|
-
}, [filterOperation.filter, rootQuery, setQuery]);
|
|
33492
33668
|
const {
|
|
33493
33669
|
op,
|
|
33494
33670
|
value
|
|
@@ -34099,6 +34275,35 @@ const styles$d = {
|
|
|
34099
34275
|
$$css: true
|
|
34100
34276
|
}
|
|
34101
34277
|
};
|
|
34278
|
+
const NestViewPathContext = /* @__PURE__ */ React__default.createContext([]);
|
|
34279
|
+
function FocusableView({
|
|
34280
|
+
children,
|
|
34281
|
+
nest
|
|
34282
|
+
}) {
|
|
34283
|
+
const {
|
|
34284
|
+
focusNestView,
|
|
34285
|
+
focusMainView
|
|
34286
|
+
} = useQueryFocus();
|
|
34287
|
+
const parentNestViewPath = useContext(NestViewPathContext);
|
|
34288
|
+
return /* @__PURE__ */ jsx("div", {
|
|
34289
|
+
onPointerDown: (e) => {
|
|
34290
|
+
e.stopPropagation();
|
|
34291
|
+
if (nest) {
|
|
34292
|
+
focusNestView([...parentNestViewPath, nest.name]);
|
|
34293
|
+
} else {
|
|
34294
|
+
focusMainView();
|
|
34295
|
+
}
|
|
34296
|
+
},
|
|
34297
|
+
children: nest ? /* @__PURE__ */ jsx(NestViewPathContext.Provider, {
|
|
34298
|
+
value: [...parentNestViewPath, nest.name],
|
|
34299
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
34300
|
+
children
|
|
34301
|
+
})
|
|
34302
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
34303
|
+
children
|
|
34304
|
+
})
|
|
34305
|
+
});
|
|
34306
|
+
}
|
|
34102
34307
|
function NestOperations({
|
|
34103
34308
|
rootQuery,
|
|
34104
34309
|
view,
|
|
@@ -34122,31 +34327,14 @@ function NestOperation({
|
|
|
34122
34327
|
nest
|
|
34123
34328
|
}) {
|
|
34124
34329
|
const {
|
|
34125
|
-
setQuery
|
|
34126
|
-
currentNestQueryPanel,
|
|
34127
|
-
onCurrentNestQueryPanelChange,
|
|
34128
|
-
onCurrentNestViewChange
|
|
34330
|
+
setQuery
|
|
34129
34331
|
} = useContext(QueryEditorContext);
|
|
34130
34332
|
const [renameOpen, setRenameOpen] = useState(false);
|
|
34131
|
-
const
|
|
34132
|
-
const
|
|
34133
|
-
|
|
34134
|
-
|
|
34135
|
-
|
|
34136
|
-
}
|
|
34137
|
-
}, [nest, isCurrentNestQueryPanelFocused, onCurrentNestViewChange]);
|
|
34138
|
-
const focusCurrentNestQueryPanel = () => {
|
|
34139
|
-
onCurrentNestQueryPanelChange == null ? void 0 : onCurrentNestQueryPanelChange(panelRef.current);
|
|
34140
|
-
onCurrentNestViewChange == null ? void 0 : onCurrentNestViewChange(nest.view);
|
|
34141
|
-
};
|
|
34142
|
-
const focusParentQueryPanel = () => {
|
|
34143
|
-
const currentPanel = panelRef.current;
|
|
34144
|
-
const parent = findParentNestQueryPanel(currentPanel);
|
|
34145
|
-
onCurrentNestQueryPanelChange == null ? void 0 : onCurrentNestQueryPanelChange(parent);
|
|
34146
|
-
if (parent === null) {
|
|
34147
|
-
onCurrentNestViewChange == null ? void 0 : onCurrentNestViewChange(null);
|
|
34148
|
-
}
|
|
34149
|
-
};
|
|
34333
|
+
const parentNestViewPath = useContext(NestViewPathContext);
|
|
34334
|
+
const {
|
|
34335
|
+
focusNestView,
|
|
34336
|
+
isNestViewFocused
|
|
34337
|
+
} = useQueryFocus();
|
|
34150
34338
|
const getControls = (nest2) => /* @__PURE__ */ jsxs(Fragment, {
|
|
34151
34339
|
children: [/* @__PURE__ */ jsxs(DropdownMenu, {
|
|
34152
34340
|
trigger: /* @__PURE__ */ jsx(Button, {
|
|
@@ -34159,7 +34347,7 @@ function NestOperation({
|
|
|
34159
34347
|
icon: "clear",
|
|
34160
34348
|
label: "Delete Query",
|
|
34161
34349
|
onClick: () => {
|
|
34162
|
-
|
|
34350
|
+
focusNestView([...parentNestViewPath]);
|
|
34163
34351
|
nest2.delete();
|
|
34164
34352
|
setQuery == null ? void 0 : setQuery(rootQuery.build());
|
|
34165
34353
|
}
|
|
@@ -34174,21 +34362,19 @@ function NestOperation({
|
|
|
34174
34362
|
view: nest2.view
|
|
34175
34363
|
})]
|
|
34176
34364
|
});
|
|
34177
|
-
return /* @__PURE__ */ jsx(
|
|
34178
|
-
|
|
34179
|
-
className: "mlyj3b58b mly1yf7rl7 mly1xmf6yo mlyh8yej3"
|
|
34180
|
-
},
|
|
34365
|
+
return /* @__PURE__ */ jsx(FocusableView, {
|
|
34366
|
+
nest,
|
|
34181
34367
|
children: /* @__PURE__ */ jsxs("div", {
|
|
34182
|
-
|
|
34183
|
-
|
|
34184
|
-
|
|
34368
|
+
...{
|
|
34369
|
+
className: "mlyj3b58b mly1yf7rl7 mly1xmf6yo mlyh8yej3"
|
|
34370
|
+
},
|
|
34185
34371
|
children: [/* @__PURE__ */ jsx(CollapsiblePanel, {
|
|
34186
34372
|
title: nest.name,
|
|
34187
34373
|
icon: viewToVisualizationIcon(nest.view),
|
|
34188
34374
|
defaultOpen: true,
|
|
34189
34375
|
controls: getControls(nest),
|
|
34190
34376
|
collapsedControls: getControls(nest),
|
|
34191
|
-
isFocused:
|
|
34377
|
+
isFocused: isNestViewFocused([...parentNestViewPath, nest.name]),
|
|
34192
34378
|
children: /* @__PURE__ */ jsx(View, {
|
|
34193
34379
|
rootQuery,
|
|
34194
34380
|
view: nest.view
|
|
@@ -34200,14 +34386,8 @@ function NestOperation({
|
|
|
34200
34386
|
open: renameOpen,
|
|
34201
34387
|
setOpen: setRenameOpen
|
|
34202
34388
|
})]
|
|
34203
|
-
})
|
|
34204
|
-
}
|
|
34205
|
-
}
|
|
34206
|
-
function findParentNestQueryPanel(element2) {
|
|
34207
|
-
if (!element2 || !element2.parentElement) return null;
|
|
34208
|
-
const parentElement = element2.parentElement;
|
|
34209
|
-
if (parentElement.dataset.nestPanel !== void 0) return parentElement;
|
|
34210
|
-
return findParentNestQueryPanel(parentElement);
|
|
34389
|
+
}, nest.name)
|
|
34390
|
+
});
|
|
34211
34391
|
}
|
|
34212
34392
|
function Operations({
|
|
34213
34393
|
rootQuery,
|
|
@@ -34237,7 +34417,8 @@ function Operations({
|
|
|
34237
34417
|
orderBys.push(operation);
|
|
34238
34418
|
} else if (operation instanceof ASTNestViewOperation) {
|
|
34239
34419
|
nests.push(operation);
|
|
34240
|
-
} else
|
|
34420
|
+
} else if (operation instanceof ASTDrillViewOperation) ;
|
|
34421
|
+
else {
|
|
34241
34422
|
limit = operation;
|
|
34242
34423
|
}
|
|
34243
34424
|
});
|
|
@@ -34376,19 +34557,13 @@ function Query({
|
|
|
34376
34557
|
setQuery
|
|
34377
34558
|
}) {
|
|
34378
34559
|
const {
|
|
34379
|
-
|
|
34380
|
-
|
|
34381
|
-
|
|
34382
|
-
|
|
34383
|
-
const focusMainQueryPanel = () => {
|
|
34384
|
-
onCurrentNestQueryPanelChange == null ? void 0 : onCurrentNestQueryPanelChange(null);
|
|
34385
|
-
onCurrentNestViewChange == null ? void 0 : onCurrentNestViewChange(null);
|
|
34386
|
-
};
|
|
34387
|
-
return /* @__PURE__ */ jsx("div", {
|
|
34388
|
-
onPointerDownCapture: focusMainQueryPanel,
|
|
34560
|
+
focusMainView,
|
|
34561
|
+
isMainViewFocused
|
|
34562
|
+
} = useQueryFocus();
|
|
34563
|
+
return /* @__PURE__ */ jsx(FocusableView, {
|
|
34389
34564
|
children: /* @__PURE__ */ jsxs(CollapsiblePanel, {
|
|
34390
34565
|
title: "Main query",
|
|
34391
|
-
isFocused:
|
|
34566
|
+
isFocused: isMainViewFocused,
|
|
34392
34567
|
controls: /* @__PURE__ */ jsxs(Fragment, {
|
|
34393
34568
|
children: [/* @__PURE__ */ jsx(DropdownMenu, {
|
|
34394
34569
|
trigger: /* @__PURE__ */ jsx(Button, {
|
|
@@ -34402,7 +34577,7 @@ function Query({
|
|
|
34402
34577
|
icon: "clear",
|
|
34403
34578
|
label: "Clear query",
|
|
34404
34579
|
onClick: () => {
|
|
34405
|
-
|
|
34580
|
+
focusMainView();
|
|
34406
34581
|
setQuery == null ? void 0 : setQuery(void 0);
|
|
34407
34582
|
},
|
|
34408
34583
|
disabled: rootQuery.isEmpty()
|
|
@@ -35896,62 +36071,83 @@ const FIELD_KIND_TO_TITLE = {
|
|
|
35896
36071
|
dimension: "Dimensions"
|
|
35897
36072
|
};
|
|
35898
36073
|
function useOperations(view, field, path) {
|
|
35899
|
-
const
|
|
36074
|
+
const fullName = toFullName(path, field.name);
|
|
36075
|
+
const flattenedFields = useMemo(() => {
|
|
35900
36076
|
const {
|
|
35901
36077
|
fields
|
|
35902
36078
|
} = getInputSchemaFromViewParent(view);
|
|
35903
|
-
|
|
35904
|
-
|
|
35905
|
-
|
|
35906
|
-
|
|
35907
|
-
|
|
35908
|
-
|
|
35909
|
-
const
|
|
35910
|
-
const {
|
|
35911
|
-
fields
|
|
35912
|
-
} = getInputSchemaFromViewParent(view);
|
|
35913
|
-
return new Set(flattenFieldsTree(fields).filter(({
|
|
35914
|
-
field: field2
|
|
35915
|
-
}) => field2.kind === "measure").map(({
|
|
35916
|
-
field: field2
|
|
35917
|
-
}) => field2.name));
|
|
35918
|
-
}, [view]);
|
|
35919
|
-
const isGroupByAllowed = useMemo(() => {
|
|
35920
|
-
if (!view) {
|
|
35921
|
-
return false;
|
|
35922
|
-
}
|
|
36079
|
+
const inputPath = path.join(".");
|
|
36080
|
+
return flattenFieldsTree(fields).filter((fieldItem) => {
|
|
36081
|
+
return fieldItem.path.join(".") === inputPath;
|
|
36082
|
+
});
|
|
36083
|
+
}, [path, view]);
|
|
36084
|
+
const matchingFieldItem = flattenedFields.find((fieldItem) => field.name === fieldItem.field.name);
|
|
36085
|
+
const groupByDisabledReason = useMemo(() => {
|
|
35923
36086
|
const segment = getSegmentIfPresent(view);
|
|
35924
|
-
|
|
35925
|
-
|
|
35926
|
-
|
|
35927
|
-
if (
|
|
35928
|
-
return
|
|
36087
|
+
if ((matchingFieldItem == null ? void 0 : matchingFieldItem.field.kind) !== "dimension") {
|
|
36088
|
+
return "Grouping is only available on a dimenion.";
|
|
36089
|
+
}
|
|
36090
|
+
if (segment == null ? void 0 : segment.hasField(field.name, path)) {
|
|
36091
|
+
return "Cannot group by a field already in the view.";
|
|
36092
|
+
}
|
|
36093
|
+
if (!isNotAnnotatedFilteredField(field)) {
|
|
36094
|
+
return "This field is annotated with #NO_UI.";
|
|
36095
|
+
}
|
|
36096
|
+
return "";
|
|
36097
|
+
}, [view, matchingFieldItem == null ? void 0 : matchingFieldItem.field.kind, field, path]);
|
|
36098
|
+
const aggregateDisabledReason = useMemo(() => {
|
|
36099
|
+
if ((matchingFieldItem == null ? void 0 : matchingFieldItem.field.kind) !== "measure") {
|
|
36100
|
+
return "Aggregation only supports measure fields.";
|
|
35929
36101
|
}
|
|
35930
36102
|
const segment = getSegmentIfPresent(view);
|
|
35931
|
-
|
|
35932
|
-
|
|
35933
|
-
const isFilterAllowed = useMemo(() => {
|
|
35934
|
-
if (!view) {
|
|
35935
|
-
return false;
|
|
36103
|
+
if (segment == null ? void 0 : segment.hasField(field.name, path)) {
|
|
36104
|
+
return "This field is already used in the query.";
|
|
35936
36105
|
}
|
|
35937
|
-
|
|
35938
|
-
|
|
35939
|
-
|
|
35940
|
-
|
|
35941
|
-
|
|
35942
|
-
|
|
35943
|
-
|
|
36106
|
+
if (!isNotAnnotatedFilteredField(field)) {
|
|
36107
|
+
return "This field is annotated with #NO_UI.";
|
|
36108
|
+
}
|
|
36109
|
+
return "";
|
|
36110
|
+
}, [matchingFieldItem == null ? void 0 : matchingFieldItem.field.kind, view, field, path]);
|
|
36111
|
+
const filterDisabledReason = useMemo(() => {
|
|
36112
|
+
if (!matchingFieldItem) {
|
|
36113
|
+
return `Unexpected Error: Could not find a field ${fullName}.`;
|
|
36114
|
+
}
|
|
36115
|
+
if (!["dimension", "measure"].includes(matchingFieldItem.field.kind)) {
|
|
36116
|
+
return `Filtering is only available for a dimension or measure.`;
|
|
36117
|
+
}
|
|
36118
|
+
if (!FILTERABLE_TYPES.includes(matchingFieldItem.field.type.kind)) {
|
|
36119
|
+
return "Filtering only supports string, boolean, number, date and time fields.";
|
|
36120
|
+
}
|
|
36121
|
+
return "";
|
|
36122
|
+
}, [fullName, matchingFieldItem]);
|
|
36123
|
+
const orderByDisabledReason = useMemo(() => {
|
|
36124
|
+
if (!matchingFieldItem) {
|
|
36125
|
+
return `Unexpected Error: Could not find a field ${fullName}.`;
|
|
35944
36126
|
}
|
|
35945
|
-
const fieldName = field.name;
|
|
35946
|
-
const outputSchemaFields = view.getOutputSchema().fields;
|
|
35947
36127
|
const segment = getSegmentIfPresent(view);
|
|
35948
|
-
|
|
35949
|
-
|
|
36128
|
+
if (segment && segmentHasOrderBySourceField(segment, path, field.name)) {
|
|
36129
|
+
return "Query is already ordered by this field.";
|
|
36130
|
+
}
|
|
36131
|
+
if (!segment || !segmentHasFieldInOutputSpace(segment, path, field.name)) {
|
|
36132
|
+
return "Order by is only available for fields in the output.";
|
|
36133
|
+
}
|
|
36134
|
+
if (!["dimension", "measure"].includes(matchingFieldItem.field.kind)) {
|
|
36135
|
+
return "Order By is only available for dimension or measure fields.";
|
|
36136
|
+
}
|
|
36137
|
+
if (!ORDERABLE_TYPES.includes(matchingFieldItem.field.type.kind)) {
|
|
36138
|
+
return "Order By only supports string, boolean, number, date and time fields.";
|
|
36139
|
+
}
|
|
36140
|
+
return "";
|
|
36141
|
+
}, [matchingFieldItem, view, path, field.name, fullName]);
|
|
35950
36142
|
return {
|
|
35951
|
-
isGroupByAllowed,
|
|
35952
|
-
|
|
35953
|
-
|
|
35954
|
-
|
|
36143
|
+
isGroupByAllowed: !groupByDisabledReason,
|
|
36144
|
+
groupByDisabledReason,
|
|
36145
|
+
isAggregateAllowed: !aggregateDisabledReason,
|
|
36146
|
+
aggregateDisabledReason,
|
|
36147
|
+
isFilterAllowed: !filterDisabledReason,
|
|
36148
|
+
filterDisabledReason,
|
|
36149
|
+
isOrderByAllowed: !orderByDisabledReason,
|
|
36150
|
+
orderByDisabledReason
|
|
35955
36151
|
};
|
|
35956
36152
|
}
|
|
35957
36153
|
const FILTERABLE_TYPES = ["string_type", "boolean_type", "number_type", "date_type", "timestamp_type"];
|
|
@@ -35963,27 +36159,29 @@ function FieldTokenWithActions({
|
|
|
35963
36159
|
}) {
|
|
35964
36160
|
const {
|
|
35965
36161
|
rootQuery,
|
|
35966
|
-
setQuery
|
|
35967
|
-
currentNestView
|
|
36162
|
+
setQuery
|
|
35968
36163
|
} = React__default.useContext(QueryEditorContext);
|
|
35969
|
-
const view = currentNestView ?? viewDef;
|
|
35970
36164
|
const {
|
|
35971
|
-
|
|
35972
|
-
|
|
35973
|
-
|
|
35974
|
-
|
|
36165
|
+
focusedNestView
|
|
36166
|
+
} = useQueryFocus();
|
|
36167
|
+
const view = focusedNestView ?? viewDef;
|
|
36168
|
+
const {
|
|
36169
|
+
groupByDisabledReason,
|
|
36170
|
+
aggregateDisabledReason,
|
|
36171
|
+
filterDisabledReason,
|
|
36172
|
+
orderByDisabledReason
|
|
35975
36173
|
} = useOperations(view, field, path);
|
|
35976
36174
|
const [isFilterPopoverOpen, setIsFilterPopoverOpen] = useState();
|
|
35977
36175
|
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
|
|
35978
36176
|
const handleAddOperationAction = (operation, filter) => {
|
|
35979
36177
|
if (field.kind === "dimension" || field.kind === "measure") {
|
|
35980
|
-
if (operation === "groupBy" &&
|
|
36178
|
+
if (operation === "groupBy" && !groupByDisabledReason) {
|
|
35981
36179
|
addGroupBy(view, field, path);
|
|
35982
|
-
} else if (operation === "aggregate" &&
|
|
36180
|
+
} else if (operation === "aggregate" && !aggregateDisabledReason) {
|
|
35983
36181
|
addAggregate(view, field, path);
|
|
35984
|
-
} else if (operation === "orderBy" &&
|
|
35985
|
-
|
|
35986
|
-
} else if (operation === "filter" &&
|
|
36182
|
+
} else if (operation === "orderBy" && !orderByDisabledReason) {
|
|
36183
|
+
addOrderByFromSource(view, path, field.name);
|
|
36184
|
+
} else if (operation === "filter" && !filterDisabledReason && filter) {
|
|
35987
36185
|
addFilter(view, field, path, filter);
|
|
35988
36186
|
}
|
|
35989
36187
|
setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
|
|
@@ -36008,7 +36206,7 @@ function FieldTokenWithActions({
|
|
|
36008
36206
|
icon: "insert",
|
|
36009
36207
|
disabled: !(rootQuery == null ? void 0 : rootQuery.isEmpty()),
|
|
36010
36208
|
onClick: handleSetView,
|
|
36011
|
-
tooltip: "Add view",
|
|
36209
|
+
tooltip: !(rootQuery == null ? void 0 : rootQuery.isEmpty()) ? "Can only add a view to an empty query." : "Add view",
|
|
36012
36210
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36013
36211
|
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
36014
36212
|
icon: "nest",
|
|
@@ -36019,8 +36217,8 @@ function FieldTokenWithActions({
|
|
|
36019
36217
|
}) : field.kind === "measure" ? /* @__PURE__ */ jsxs(Fragment, {
|
|
36020
36218
|
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
36021
36219
|
icon: "aggregate",
|
|
36022
|
-
tooltip: "Add as aggregate",
|
|
36023
|
-
disabled:
|
|
36220
|
+
tooltip: aggregateDisabledReason || "Add as aggregate",
|
|
36221
|
+
disabled: !!aggregateDisabledReason,
|
|
36024
36222
|
onClick: () => handleAddOperationAction("aggregate"),
|
|
36025
36223
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36026
36224
|
}), /* @__PURE__ */ jsx(FilterPopover, {
|
|
@@ -36029,23 +36227,23 @@ function FieldTokenWithActions({
|
|
|
36029
36227
|
setFilter: (filter) => handleAddOperationAction("filter", filter),
|
|
36030
36228
|
trigger: /* @__PURE__ */ jsx(ActionButton, {
|
|
36031
36229
|
icon: "filter",
|
|
36032
|
-
tooltip: "Add as filter",
|
|
36033
|
-
disabled:
|
|
36230
|
+
tooltip: filterDisabledReason || "Add as filter",
|
|
36231
|
+
disabled: !!filterDisabledReason,
|
|
36034
36232
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36035
36233
|
}),
|
|
36036
36234
|
onOpenChange: setIsFilterPopoverOpen
|
|
36037
36235
|
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
36038
36236
|
icon: "orderBy",
|
|
36039
|
-
tooltip: "Add as order by",
|
|
36040
|
-
disabled:
|
|
36237
|
+
tooltip: orderByDisabledReason || "Add as order by",
|
|
36238
|
+
disabled: !!orderByDisabledReason,
|
|
36041
36239
|
onClick: () => handleAddOperationAction("orderBy"),
|
|
36042
36240
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36043
36241
|
})]
|
|
36044
36242
|
}) : field.kind === "dimension" ? /* @__PURE__ */ jsxs(Fragment, {
|
|
36045
36243
|
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
36046
36244
|
icon: "groupBy",
|
|
36047
|
-
tooltip: "Add as group by",
|
|
36048
|
-
disabled:
|
|
36245
|
+
tooltip: groupByDisabledReason || "Add as group by",
|
|
36246
|
+
disabled: !!groupByDisabledReason,
|
|
36049
36247
|
onClick: () => handleAddOperationAction("groupBy"),
|
|
36050
36248
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36051
36249
|
}), /* @__PURE__ */ jsx(FilterPopover, {
|
|
@@ -36054,20 +36252,26 @@ function FieldTokenWithActions({
|
|
|
36054
36252
|
setFilter: (filter) => handleAddOperationAction("filter", filter),
|
|
36055
36253
|
trigger: /* @__PURE__ */ jsx(ActionButton, {
|
|
36056
36254
|
icon: "filter",
|
|
36057
|
-
tooltip: "Add as filter",
|
|
36058
|
-
disabled:
|
|
36255
|
+
tooltip: filterDisabledReason || "Add as filter",
|
|
36256
|
+
disabled: !!filterDisabledReason,
|
|
36059
36257
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36060
36258
|
}),
|
|
36061
36259
|
onOpenChange: setIsFilterPopoverOpen
|
|
36062
36260
|
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
36063
36261
|
icon: "orderBy",
|
|
36064
|
-
tooltip: "Add as order by",
|
|
36065
|
-
disabled:
|
|
36262
|
+
tooltip: orderByDisabledReason || "Add as order by",
|
|
36263
|
+
disabled: !!orderByDisabledReason,
|
|
36066
36264
|
onClick: () => handleAddOperationAction("orderBy"),
|
|
36067
36265
|
onTooltipOpenChange: setIsTooltipOpen
|
|
36068
36266
|
})]
|
|
36069
36267
|
}) : null,
|
|
36070
|
-
onClick: field.kind === "dimension" &&
|
|
36268
|
+
onClick: field.kind === "dimension" && !groupByDisabledReason ? () => handleAddOperationAction("groupBy") : field.kind === "measure" && !aggregateDisabledReason ? () => handleAddOperationAction("aggregate") : field.kind === "view" ? () => {
|
|
36269
|
+
if (rootQuery == null ? void 0 : rootQuery.isEmpty()) {
|
|
36270
|
+
handleSetView();
|
|
36271
|
+
} else {
|
|
36272
|
+
handleAddView();
|
|
36273
|
+
}
|
|
36274
|
+
} : void 0,
|
|
36071
36275
|
hoverActionsVisible: isFilterPopoverOpen || isTooltipOpen,
|
|
36072
36276
|
tooltip: /* @__PURE__ */ jsx(FieldHoverCard, {
|
|
36073
36277
|
field,
|