@gingkoo/pandora-metabase 1.0.0-alpha.3 → 1.0.0-alpha.5
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/lib/es/components/popup.d.ts +8 -2
- package/lib/es/index.js +80 -25
- package/lib/es/index.js.map +1 -1
- package/lib/es/utils/helper-dom.d.ts +4 -3
- package/package.json +1 -1
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export declare function generateTrigger(PortalComponent: any): {
|
|
3
3
|
new (props: PropsType): {
|
|
4
|
+
resizeObserver: ResizeObserver | null;
|
|
4
5
|
resetId: number;
|
|
5
6
|
ref: any;
|
|
6
7
|
componentDidMount(): void;
|
|
8
|
+
componentDidUpdate(prevProps: PropsType): void;
|
|
7
9
|
componentWillUnmount(): void;
|
|
10
|
+
initResizeObserver: () => void;
|
|
8
11
|
bindEvent: () => void;
|
|
9
12
|
closePopup: () => void;
|
|
10
13
|
attachParent: (popupContainer: HTMLSpanElement) => void;
|
|
11
14
|
getCurrentNodePos: () => {
|
|
12
15
|
x: number;
|
|
13
16
|
y: number;
|
|
17
|
+
t: number;
|
|
14
18
|
h: any;
|
|
15
19
|
};
|
|
16
20
|
getContainer: () => HTMLSpanElement;
|
|
@@ -28,7 +32,6 @@ export declare function generateTrigger(PortalComponent: any): {
|
|
|
28
32
|
shouldComponentUpdate?(nextProps: Readonly<PropsType>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
29
33
|
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
30
34
|
getSnapshotBeforeUpdate?(prevProps: Readonly<PropsType>, prevState: Readonly<{}>): any;
|
|
31
|
-
componentDidUpdate?(prevProps: Readonly<PropsType>, prevState: Readonly<{}>, snapshot?: any): void;
|
|
32
35
|
componentWillMount?(): void;
|
|
33
36
|
UNSAFE_componentWillMount?(): void;
|
|
34
37
|
componentWillReceiveProps?(nextProps: Readonly<PropsType>, nextContext: any): void;
|
|
@@ -44,16 +47,20 @@ export declare function generateTrigger(PortalComponent: any): {
|
|
|
44
47
|
};
|
|
45
48
|
declare const _default: {
|
|
46
49
|
new (props: PropsType): {
|
|
50
|
+
resizeObserver: ResizeObserver | null;
|
|
47
51
|
resetId: number;
|
|
48
52
|
ref: any;
|
|
49
53
|
componentDidMount(): void;
|
|
54
|
+
componentDidUpdate(prevProps: PropsType): void;
|
|
50
55
|
componentWillUnmount(): void;
|
|
56
|
+
initResizeObserver: () => void;
|
|
51
57
|
bindEvent: () => void;
|
|
52
58
|
closePopup: () => void;
|
|
53
59
|
attachParent: (popupContainer: HTMLSpanElement) => void;
|
|
54
60
|
getCurrentNodePos: () => {
|
|
55
61
|
x: number;
|
|
56
62
|
y: number;
|
|
63
|
+
t: number;
|
|
57
64
|
h: any;
|
|
58
65
|
};
|
|
59
66
|
getContainer: () => HTMLSpanElement;
|
|
@@ -71,7 +78,6 @@ declare const _default: {
|
|
|
71
78
|
shouldComponentUpdate?(nextProps: Readonly<PropsType>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
72
79
|
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
73
80
|
getSnapshotBeforeUpdate?(prevProps: Readonly<PropsType>, prevState: Readonly<{}>): any;
|
|
74
|
-
componentDidUpdate?(prevProps: Readonly<PropsType>, prevState: Readonly<{}>, snapshot?: any): void;
|
|
75
81
|
componentWillMount?(): void;
|
|
76
82
|
UNSAFE_componentWillMount?(): void;
|
|
77
83
|
componentWillReceiveProps?(nextProps: Readonly<PropsType>, nextContext: any): void;
|
package/lib/es/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @gingkoo/pandora-metabase v1.0.0-alpha.
|
|
2
|
+
* @gingkoo/pandora-metabase v1.0.0-alpha.5
|
|
3
3
|
*/
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import * as React from 'react';
|
|
@@ -278,7 +278,6 @@ const summarizeToSql = (arr, record) => {
|
|
|
278
278
|
condition,
|
|
279
279
|
alias,
|
|
280
280
|
name,
|
|
281
|
-
fieldAlias,
|
|
282
281
|
realName = ''
|
|
283
282
|
} = record;
|
|
284
283
|
let index = arr.indexOf(record);
|
|
@@ -339,7 +338,7 @@ const summarizeToSql = (arr, record) => {
|
|
|
339
338
|
count++;
|
|
340
339
|
}
|
|
341
340
|
});
|
|
342
|
-
as =
|
|
341
|
+
as = as + (count ? '_' + (count + 1) : '');
|
|
343
342
|
return {
|
|
344
343
|
sql: sql + ' AS ' + as,
|
|
345
344
|
fieldAlias: as
|
|
@@ -1001,6 +1000,8 @@ const useStore = () => {
|
|
|
1001
1000
|
}); //弹窗
|
|
1002
1001
|
const [popupClosable, setClosable] = useState(true); //是否可关闭 如果弹框里面再弹框 则不可关闭
|
|
1003
1002
|
const [popupClosable2, setClosable2] = useState(true); //是否可关闭 如果弹框里面再弹框 则不可关闭
|
|
1003
|
+
// 外层ref
|
|
1004
|
+
const popupContainer = useRef();
|
|
1004
1005
|
// const [fetchDatasetFn, setFetchDatasetFn] = useState<(id: string) => Promise<any>>(
|
|
1005
1006
|
// async () => {},
|
|
1006
1007
|
// ); //fn
|
|
@@ -1411,7 +1412,8 @@ const useStore = () => {
|
|
|
1411
1412
|
_setShowSubquery,
|
|
1412
1413
|
constantList,
|
|
1413
1414
|
setConstantList,
|
|
1414
|
-
changeAlias
|
|
1415
|
+
changeAlias,
|
|
1416
|
+
popupContainer
|
|
1415
1417
|
};
|
|
1416
1418
|
};
|
|
1417
1419
|
|
|
@@ -1813,6 +1815,7 @@ const getComputedTranslate = obj => {
|
|
|
1813
1815
|
};
|
|
1814
1816
|
// 获取元素距离浏览器顶部的距离
|
|
1815
1817
|
const getElementTop = elem => {
|
|
1818
|
+
if (!elem) return 0;
|
|
1816
1819
|
let elemTop = elem.offsetTop;
|
|
1817
1820
|
let pElem = elem.offsetParent;
|
|
1818
1821
|
while (pElem != null) {
|
|
@@ -1826,6 +1829,7 @@ const getElementTop = elem => {
|
|
|
1826
1829
|
};
|
|
1827
1830
|
// 获取元素距离浏览器顶部的距离
|
|
1828
1831
|
const getElementLeft = elem => {
|
|
1832
|
+
if (!elem) return 0;
|
|
1829
1833
|
let elemLeft = elem.offsetLeft;
|
|
1830
1834
|
let pElem = elem.offsetParent;
|
|
1831
1835
|
while (pElem != null) {
|
|
@@ -1837,8 +1841,23 @@ const getElementLeft = elem => {
|
|
|
1837
1841
|
}
|
|
1838
1842
|
return elemLeft;
|
|
1839
1843
|
};
|
|
1840
|
-
|
|
1841
|
-
|
|
1844
|
+
// 获取元素可见范围内高度
|
|
1845
|
+
const getContainerVisibleHeight = container => {
|
|
1846
|
+
if (!container) return 0;
|
|
1847
|
+
const rect = container.getBoundingClientRect();
|
|
1848
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
1849
|
+
// 元素顶部在视口上方 -> 不可见
|
|
1850
|
+
if (rect.bottom < 0) return 0;
|
|
1851
|
+
// 元素底部在视口下方 -> 不可见
|
|
1852
|
+
if (rect.top > windowHeight) return 0;
|
|
1853
|
+
// 可见区域的 top 和 bottom
|
|
1854
|
+
const visibleTop = Math.max(rect.top, 0);
|
|
1855
|
+
const visibleBottom = Math.min(rect.bottom, windowHeight);
|
|
1856
|
+
// 可见高度
|
|
1857
|
+
return visibleBottom - visibleTop;
|
|
1858
|
+
};
|
|
1859
|
+
const getScrollTop = elem => {
|
|
1860
|
+
return elem?.scrollTop || document.documentElement.scrollTop;
|
|
1842
1861
|
};
|
|
1843
1862
|
// 浏览器可视宽高
|
|
1844
1863
|
const getWindowSize = () => {
|
|
@@ -3409,6 +3428,7 @@ function returnDocument(element) {
|
|
|
3409
3428
|
const outSpacing = 10;
|
|
3410
3429
|
function generateTrigger(PortalComponent) {
|
|
3411
3430
|
class Trigger extends React.Component {
|
|
3431
|
+
resizeObserver = null; // 显式声明 resizeObserver 属性
|
|
3412
3432
|
resetId = -1; // 监听窗口改变事件id 用于组件销毁的时候清除事件
|
|
3413
3433
|
static defaultProps = {
|
|
3414
3434
|
visible: false,
|
|
@@ -3423,11 +3443,39 @@ function generateTrigger(PortalComponent) {
|
|
|
3423
3443
|
this.resetId = winResetEvent.addEvent(this.didUpdate, this, 300);
|
|
3424
3444
|
this.props.container && this.props.container.addEventListener('scroll', this.didUpdate);
|
|
3425
3445
|
this.bindEvent();
|
|
3446
|
+
// 延迟绑定 ResizeObserver 到 ensure the element is ready
|
|
3447
|
+
this.initResizeObserver();
|
|
3448
|
+
}
|
|
3449
|
+
componentDidUpdate(prevProps) {
|
|
3450
|
+
// 如果 children 发生变化,重新初始化观察器
|
|
3451
|
+
if (prevProps.children !== this.props.children) {
|
|
3452
|
+
this.initResizeObserver();
|
|
3453
|
+
}
|
|
3426
3454
|
}
|
|
3427
3455
|
componentWillUnmount() {
|
|
3428
3456
|
winResetEvent.removeEvent(this.resetId);
|
|
3429
3457
|
this.props.container && this.props.container.removeEventListener('scroll', this.didUpdate);
|
|
3458
|
+
if (this.resizeObserver) {
|
|
3459
|
+
this.resizeObserver.disconnect();
|
|
3460
|
+
this.resizeObserver = null;
|
|
3461
|
+
}
|
|
3430
3462
|
}
|
|
3463
|
+
// children高度变化后,从新计算高度
|
|
3464
|
+
initResizeObserver = () => {
|
|
3465
|
+
const targetNode = this.ref.current;
|
|
3466
|
+
if (!targetNode) return;
|
|
3467
|
+
// 如果已经存在 ResizeObserver,先断开连接
|
|
3468
|
+
if (this.resizeObserver) {
|
|
3469
|
+
this.resizeObserver.disconnect();
|
|
3470
|
+
}
|
|
3471
|
+
// 初始化 ResizeObserver 并开始观察目标节点
|
|
3472
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
3473
|
+
entries.forEach(entry => {
|
|
3474
|
+
this.didUpdate();
|
|
3475
|
+
});
|
|
3476
|
+
});
|
|
3477
|
+
this.resizeObserver.observe(targetNode);
|
|
3478
|
+
};
|
|
3431
3479
|
bindEvent = () => {
|
|
3432
3480
|
let that = this;
|
|
3433
3481
|
returnDocument().body.addEventListener('click', function (e) {
|
|
@@ -3445,7 +3493,7 @@ function generateTrigger(PortalComponent) {
|
|
|
3445
3493
|
this.props.visible && this.props.closable && this.props.hideVisible();
|
|
3446
3494
|
};
|
|
3447
3495
|
attachParent = popupContainer => {
|
|
3448
|
-
let mountNode = returnDocument().body;
|
|
3496
|
+
let mountNode = this.props.container || returnDocument().body;
|
|
3449
3497
|
mountNode.appendChild(popupContainer);
|
|
3450
3498
|
};
|
|
3451
3499
|
getCurrentNodePos = () => {
|
|
@@ -3454,8 +3502,9 @@ function generateTrigger(PortalComponent) {
|
|
|
3454
3502
|
container
|
|
3455
3503
|
} = this.props;
|
|
3456
3504
|
return {
|
|
3457
|
-
x: getElementLeft(node),
|
|
3458
|
-
y: getElementTop(node) - (container
|
|
3505
|
+
x: getElementLeft(node) - getElementLeft(container),
|
|
3506
|
+
y: getElementTop(node) - getElementTop(container),
|
|
3507
|
+
t: getElementTop(container),
|
|
3459
3508
|
h: node.offsetHeight
|
|
3460
3509
|
};
|
|
3461
3510
|
};
|
|
@@ -3498,19 +3547,21 @@ function generateTrigger(PortalComponent) {
|
|
|
3498
3547
|
didUpdate = () => {
|
|
3499
3548
|
if (!this.props.node) return false;
|
|
3500
3549
|
let {
|
|
3501
|
-
innerSpacing = 10
|
|
3550
|
+
innerSpacing = 10,
|
|
3551
|
+
container
|
|
3502
3552
|
} = this.props;
|
|
3503
3553
|
let pos = this.getCurrentNodePos();
|
|
3504
|
-
let posY = pos.y - getScrollTop();
|
|
3554
|
+
let posY = pos.y - getScrollTop(container);
|
|
3505
3555
|
if (!this.ref) return false;
|
|
3506
3556
|
let realHeight = this.ref?.current?.childNodes?.[0]?.offsetHeight || 0;
|
|
3507
3557
|
if (!realHeight) return false;
|
|
3508
3558
|
let {
|
|
3509
3559
|
height: winH
|
|
3510
3560
|
} = getWindowSize();
|
|
3511
|
-
let
|
|
3561
|
+
let containerH = getContainerVisibleHeight(container);
|
|
3562
|
+
let downH = (containerH || winH) - posY - pos.h; // 元素下面可用高度
|
|
3512
3563
|
let maxHeight = 0;
|
|
3513
|
-
let topHeight = getScrollTop();
|
|
3564
|
+
let topHeight = getScrollTop(container);
|
|
3514
3565
|
if (downH >= posY || realHeight <= downH - innerSpacing - outSpacing) {
|
|
3515
3566
|
// 下面比上面宽敞 或 下面足够放下所有 放下面
|
|
3516
3567
|
maxHeight = Math.min(realHeight, downH - innerSpacing - outSpacing);
|
|
@@ -5983,10 +6034,11 @@ const JoinData = props => {
|
|
|
5983
6034
|
let oldList = cloneDeep(newMeta[index].subquery);
|
|
5984
6035
|
let _toolbar = subToolbar || toolbar;
|
|
5985
6036
|
_toolbar = _toolbar.filter(v => v !== 'group'); // 子查询不需要分组
|
|
6037
|
+
let zIndex = store.popupContainer.current ? getMaxZIndexInParents(store.popupContainer.current) : 0;
|
|
5986
6038
|
let o = Modal2.openModal({
|
|
5987
6039
|
title: __('SqlQueryBuilder.subquery'),
|
|
5988
6040
|
transparentMask: true,
|
|
5989
|
-
zIndex:
|
|
6041
|
+
zIndex: Number(zIndex),
|
|
5990
6042
|
content: jsx(Fragment, {
|
|
5991
6043
|
children: jsx(SqlVisionBuilder, {
|
|
5992
6044
|
...other,
|
|
@@ -7026,10 +7078,11 @@ const CustomColumn = props => {
|
|
|
7026
7078
|
const showSubQuery = (e, i) => {
|
|
7027
7079
|
let newMeta = store.metaList[groupIndex].list.slice();
|
|
7028
7080
|
const _value = newMeta[index].customColumn[i] || [];
|
|
7081
|
+
let zIndex = store.popupContainer.current ? getMaxZIndexInParents(store.popupContainer.current) : 0;
|
|
7029
7082
|
let o = Modal2.openModal({
|
|
7030
7083
|
title: __('SqlQueryBuilder.customExpression'),
|
|
7031
7084
|
transparentMask: true,
|
|
7032
|
-
zIndex:
|
|
7085
|
+
zIndex: Number(zIndex),
|
|
7033
7086
|
content: jsx(Fragment, {
|
|
7034
7087
|
children: jsx(Provider, {
|
|
7035
7088
|
value: store,
|
|
@@ -7401,10 +7454,11 @@ const Filter = props => {
|
|
|
7401
7454
|
let oldList = position ? [] : cloneDeep(newMeta[index].filter[i]?.subquery || []);
|
|
7402
7455
|
let _toolbar = subToolbar || toolbar;
|
|
7403
7456
|
_toolbar = _toolbar.filter(v => v !== 'group'); // 子查询不需要分组
|
|
7457
|
+
let zIndex = store.popupContainer.current ? getMaxZIndexInParents(store.popupContainer.current) : null;
|
|
7404
7458
|
let o = Modal2.openModal({
|
|
7405
7459
|
title: 'NOT EXISTS',
|
|
7406
7460
|
transparentMask: true,
|
|
7407
|
-
zIndex:
|
|
7461
|
+
zIndex: Number(zIndex),
|
|
7408
7462
|
content: jsx(Fragment, {
|
|
7409
7463
|
children: jsx(SqlVisionBuilder, {
|
|
7410
7464
|
...other,
|
|
@@ -7740,7 +7794,7 @@ const GroupBy = props => {
|
|
|
7740
7794
|
newMeta[index].by.splice(i, 1, data);
|
|
7741
7795
|
// @ts-ignore
|
|
7742
7796
|
newMeta[index].by = newMeta[index].by.map(v => {
|
|
7743
|
-
const fieldAlias =
|
|
7797
|
+
const fieldAlias = `${v.alias}__${v.name}`;
|
|
7744
7798
|
return {
|
|
7745
7799
|
...v,
|
|
7746
7800
|
sql: `${v.alias}.${v.realName || v.name} AS ${fieldAlias}`,
|
|
@@ -7792,7 +7846,7 @@ const GroupBy = props => {
|
|
|
7792
7846
|
newMeta[index].by.push(data);
|
|
7793
7847
|
// @ts-ignore
|
|
7794
7848
|
newMeta[index].by = newMeta[index].by.map(v => {
|
|
7795
|
-
const fieldAlias =
|
|
7849
|
+
const fieldAlias = `${v.alias}__${v.name}`;
|
|
7796
7850
|
return {
|
|
7797
7851
|
...v,
|
|
7798
7852
|
sql: `${v.alias}.${v.realName || v.name} AS ${fieldAlias}`,
|
|
@@ -8607,7 +8661,8 @@ const Metabase = props => {
|
|
|
8607
8661
|
} = props;
|
|
8608
8662
|
const store = useStore$1();
|
|
8609
8663
|
const [saveLoading, setSaveLoading] = useState(false);
|
|
8610
|
-
const popupContainer = useRef();
|
|
8664
|
+
// const popupContainer = useRef();
|
|
8665
|
+
// store.setPopupContainer(popupContainer);
|
|
8611
8666
|
const popupContent = useMemo(() => {
|
|
8612
8667
|
let {
|
|
8613
8668
|
visible,
|
|
@@ -8638,11 +8693,11 @@ const Metabase = props => {
|
|
|
8638
8693
|
await onOk?.(_metaList);
|
|
8639
8694
|
setSaveLoading(false);
|
|
8640
8695
|
};
|
|
8641
|
-
let zIndex = popupContainer.current ? getMaxZIndexInParents(popupContainer.current) : null;
|
|
8696
|
+
let zIndex = store.popupContainer.current ? getMaxZIndexInParents(store.popupContainer.current) : null;
|
|
8642
8697
|
return (
|
|
8643
8698
|
// @ts-ignore
|
|
8644
8699
|
jsx(VisualBox, {
|
|
8645
|
-
ref: popupContainer,
|
|
8700
|
+
ref: store.popupContainer,
|
|
8646
8701
|
children: jsxs("div", {
|
|
8647
8702
|
className: 'Sqb',
|
|
8648
8703
|
children: [store.metaList.map((v, index) => {
|
|
@@ -8679,8 +8734,8 @@ const Metabase = props => {
|
|
|
8679
8734
|
disabled: saveLoading,
|
|
8680
8735
|
onClick: onSave,
|
|
8681
8736
|
children: btnText || __('SqlQueryBuilder.visualize')
|
|
8682
|
-
}) : null, popupContainer.current && jsx(Popup, {
|
|
8683
|
-
container: popupContainer.current,
|
|
8737
|
+
}) : null, store.popupContainer.current && jsx(Popup, {
|
|
8738
|
+
container: store.popupContainer.current,
|
|
8684
8739
|
visible: store.popupData.visible,
|
|
8685
8740
|
node: store.popupData.node,
|
|
8686
8741
|
closable: store.popupClosable,
|
|
@@ -8691,8 +8746,8 @@ const Metabase = props => {
|
|
|
8691
8746
|
});
|
|
8692
8747
|
},
|
|
8693
8748
|
children: popupContent
|
|
8694
|
-
}), popupContainer.current && jsx(Popup, {
|
|
8695
|
-
container: popupContainer.current,
|
|
8749
|
+
}), store.popupContainer.current && jsx(Popup, {
|
|
8750
|
+
container: store.popupContainer.current,
|
|
8696
8751
|
visible: store.popupData2.visible,
|
|
8697
8752
|
node: store.popupData2.node,
|
|
8698
8753
|
closable: store.popupClosable2,
|