@gingkoo/pandora-metabase 1.0.0-alpha.2 → 1.0.0-alpha.4

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.
@@ -2,7 +2,7 @@ import { UnionEnum } from '../../store/enum';
2
2
  interface PropsType {
3
3
  store?: any;
4
4
  meta: any;
5
- operator: UnionEnum;
5
+ union: UnionEnum;
6
6
  groupIndex: number;
7
7
  }
8
8
  declare const RowLimit: (props: PropsType) => import("react/jsx-runtime").JSX.Element;
@@ -11,6 +11,7 @@ export declare function generateTrigger(PortalComponent: any): {
11
11
  getCurrentNodePos: () => {
12
12
  x: number;
13
13
  y: number;
14
+ t: number;
14
15
  h: any;
15
16
  };
16
17
  getContainer: () => HTMLSpanElement;
@@ -54,6 +55,7 @@ declare const _default: {
54
55
  getCurrentNodePos: () => {
55
56
  x: number;
56
57
  y: number;
58
+ t: number;
57
59
  h: any;
58
60
  };
59
61
  getContainer: () => HTMLSpanElement;
package/lib/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @gingkoo/pandora-metabase v1.0.0-alpha.2
2
+ * @gingkoo/pandora-metabase v1.0.0-alpha.4
3
3
  */
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import * as React from 'react';
@@ -89,7 +89,7 @@ var TypeEnum;
89
89
  TypeEnum["summarize"] = "summarize";
90
90
  TypeEnum["sort"] = "sort";
91
91
  TypeEnum["rowLimit"] = "rowLimit";
92
- TypeEnum["group"] = "group";
92
+ TypeEnum["union"] = "union";
93
93
  })(TypeEnum || (TypeEnum = {}));
94
94
  var JoinEnum;
95
95
  (function (JoinEnum) {
@@ -869,6 +869,86 @@ const changeFieldAlias = (list, curObj) => {
869
869
  });
870
870
  return newList;
871
871
  };
872
+ function splitByUnion(data) {
873
+ const original = cloneDeep(data);
874
+ const result = [];
875
+ let i = 0;
876
+ while (i < original.length) {
877
+ const item = original[i];
878
+ if (item.type === 'group') {
879
+ // group.list 中每一项原样推入结果
880
+ for (const subItem of item.list) {
881
+ result.push(subItem);
882
+ }
883
+ i++;
884
+ } else if (item.type === 'union') {
885
+ const {
886
+ list,
887
+ ...otehr
888
+ } = item;
889
+ // 查找下一个 group,并将其 list 转成 subquery
890
+ const nextItem = original[i + 1];
891
+ if (nextItem && nextItem.type === 'group') {
892
+ result.push({
893
+ ...otehr,
894
+ subquery: nextItem.list.map(subItem => subItem)
895
+ });
896
+ i += 2;
897
+ } else {
898
+ result.push({
899
+ ...otehr,
900
+ subquery: []
901
+ });
902
+ i++;
903
+ }
904
+ }
905
+ }
906
+ return result;
907
+ }
908
+ function reassembleByUnion(target) {
909
+ const result = [];
910
+ let i = 0;
911
+ const len = target.length;
912
+ // 如果没有任何 union,直接放入一个 group.list
913
+ const hasUnion = target.some(item => item.type === 'union');
914
+ if (!hasUnion) {
915
+ return [{
916
+ type: 'group',
917
+ name: 'default',
918
+ list: [...target]
919
+ }];
920
+ }
921
+ // 否则正常处理
922
+ while (i < len) {
923
+ const item = target[i];
924
+ if (item.type !== 'union') {
925
+ // 收集连续非 union 的 item,统一放入一个 group.list
926
+ const groupList = [];
927
+ while (i < len && target[i].type !== 'union') {
928
+ groupList.push(target[i]);
929
+ i++;
930
+ }
931
+ result.push({
932
+ type: 'group',
933
+ name: 'default',
934
+ list: groupList
935
+ });
936
+ } else {
937
+ // 处理 union
938
+ result.push({
939
+ type: 'union',
940
+ name: 'union',
941
+ union: item.union ?? 'UNION',
942
+ list: []
943
+ });
944
+ const subquery = item.subquery || [];
945
+ const convertedSubquery = reassembleByUnion(subquery);
946
+ result.push(...convertedSubquery);
947
+ i++; // 跳过当前 union
948
+ }
949
+ }
950
+ return result;
951
+ }
872
952
 
873
953
  let metaKey = 1;
874
954
  const SummarizeAlias = 'source';
@@ -893,9 +973,9 @@ const useStore = () => {
893
973
  list: defaultMetaList
894
974
  }];
895
975
  const defaultOperator = {
896
- type: 'group',
897
- name: 'group',
898
- operator: UnionEnum.union,
976
+ type: 'union',
977
+ name: 'union',
978
+ union: UnionEnum.union,
899
979
  list: []
900
980
  };
901
981
  const [showFields, setShowFields] = useState(true); //显示字段
@@ -1053,7 +1133,8 @@ const useStore = () => {
1053
1133
  return {
1054
1134
  name: item.name || 'default',
1055
1135
  list: newList.length < 1 ? defaultMetaList : newList,
1056
- type: item.type || 'group'
1136
+ type: item.type || 'group',
1137
+ union: item.union
1057
1138
  };
1058
1139
  });
1059
1140
  const validMetaKeys = _metaList.flatMap(group => group.list).map(v => Number(v.metaKey)).filter(num => !isNaN(num));
@@ -1161,7 +1242,7 @@ const useStore = () => {
1161
1242
  }
1162
1243
  };
1163
1244
  }
1164
- if (type === TypeEnum.group) {
1245
+ if (type === TypeEnum.union) {
1165
1246
  // 添加分组
1166
1247
  let newMetaList = metaList.slice();
1167
1248
  newMetaList.splice(groupIndex + 1, 0, defaultOperator, ...defaultMeta);
@@ -1732,6 +1813,7 @@ const getComputedTranslate = obj => {
1732
1813
  };
1733
1814
  // 获取元素距离浏览器顶部的距离
1734
1815
  const getElementTop = elem => {
1816
+ if (!elem) return 0;
1735
1817
  let elemTop = elem.offsetTop;
1736
1818
  let pElem = elem.offsetParent;
1737
1819
  while (pElem != null) {
@@ -1745,6 +1827,7 @@ const getElementTop = elem => {
1745
1827
  };
1746
1828
  // 获取元素距离浏览器顶部的距离
1747
1829
  const getElementLeft = elem => {
1830
+ if (!elem) return 0;
1748
1831
  let elemLeft = elem.offsetLeft;
1749
1832
  let pElem = elem.offsetParent;
1750
1833
  while (pElem != null) {
@@ -1756,8 +1839,23 @@ const getElementLeft = elem => {
1756
1839
  }
1757
1840
  return elemLeft;
1758
1841
  };
1759
- const getScrollTop = () => {
1760
- return document.documentElement.scrollTop;
1842
+ // 获取元素可见范围内高度
1843
+ const getContainerVisibleHeight = container => {
1844
+ if (!container) return 0;
1845
+ const rect = container.getBoundingClientRect();
1846
+ const windowHeight = window.innerHeight || document.documentElement.clientHeight;
1847
+ // 元素顶部在视口上方 -> 不可见
1848
+ if (rect.bottom < 0) return 0;
1849
+ // 元素底部在视口下方 -> 不可见
1850
+ if (rect.top > windowHeight) return 0;
1851
+ // 可见区域的 top 和 bottom
1852
+ const visibleTop = Math.max(rect.top, 0);
1853
+ const visibleBottom = Math.min(rect.bottom, windowHeight);
1854
+ // 可见高度
1855
+ return visibleBottom - visibleTop;
1856
+ };
1857
+ const getScrollTop = elem => {
1858
+ return elem?.scrollTop || document.documentElement.scrollTop;
1761
1859
  };
1762
1860
  // 浏览器可视宽高
1763
1861
  const getWindowSize = () => {
@@ -2236,7 +2334,7 @@ const List = [{
2236
2334
  const RowLimit$1 = props => {
2237
2335
  const {
2238
2336
  meta,
2239
- operator,
2337
+ union,
2240
2338
  groupIndex
2241
2339
  } = props;
2242
2340
  const store = useStore$1();
@@ -2246,10 +2344,10 @@ const RowLimit$1 = props => {
2246
2344
  node: e.currentTarget,
2247
2345
  content: jsx(SelectList, {
2248
2346
  list: List,
2249
- value: operator,
2347
+ value: union,
2250
2348
  onChange: type => {
2251
2349
  let newMeta = store.metaList.slice();
2252
- newMeta[groupIndex].operator = type;
2350
+ newMeta[groupIndex].union = type;
2253
2351
  store._setMeta(newMeta);
2254
2352
  store.setPopup({
2255
2353
  visible: false
@@ -2272,7 +2370,7 @@ const RowLimit$1 = props => {
2272
2370
  children: jsx("div", {
2273
2371
  className: `Sqb-TableName`,
2274
2372
  onClick: e => selectOperator(e),
2275
- children: operator
2373
+ children: union
2276
2374
  })
2277
2375
  })
2278
2376
  })]
@@ -3364,7 +3462,7 @@ function generateTrigger(PortalComponent) {
3364
3462
  this.props.visible && this.props.closable && this.props.hideVisible();
3365
3463
  };
3366
3464
  attachParent = popupContainer => {
3367
- let mountNode = returnDocument().body;
3465
+ let mountNode = this.props.container || returnDocument().body;
3368
3466
  mountNode.appendChild(popupContainer);
3369
3467
  };
3370
3468
  getCurrentNodePos = () => {
@@ -3373,8 +3471,9 @@ function generateTrigger(PortalComponent) {
3373
3471
  container
3374
3472
  } = this.props;
3375
3473
  return {
3376
- x: getElementLeft(node),
3377
- y: getElementTop(node) - (container?.scrollTop || 0),
3474
+ x: getElementLeft(node) - getElementLeft(container),
3475
+ y: getElementTop(node) - getElementTop(container),
3476
+ t: getElementTop(container),
3378
3477
  h: node.offsetHeight
3379
3478
  };
3380
3479
  };
@@ -3417,19 +3516,21 @@ function generateTrigger(PortalComponent) {
3417
3516
  didUpdate = () => {
3418
3517
  if (!this.props.node) return false;
3419
3518
  let {
3420
- innerSpacing = 10
3519
+ innerSpacing = 10,
3520
+ container
3421
3521
  } = this.props;
3422
3522
  let pos = this.getCurrentNodePos();
3423
- let posY = pos.y - getScrollTop();
3523
+ let posY = pos.y - getScrollTop(container);
3424
3524
  if (!this.ref) return false;
3425
3525
  let realHeight = this.ref?.current?.childNodes?.[0]?.offsetHeight || 0;
3426
3526
  if (!realHeight) return false;
3427
3527
  let {
3428
3528
  height: winH
3429
3529
  } = getWindowSize();
3430
- let downH = winH - posY - pos.h; // 元素下面可用高度
3530
+ let containerH = getContainerVisibleHeight(container);
3531
+ let downH = (containerH || winH) - posY - pos.h; // 元素下面可用高度
3431
3532
  let maxHeight = 0;
3432
- let topHeight = getScrollTop();
3533
+ let topHeight = getScrollTop(container);
3433
3534
  if (downH >= posY || realHeight <= downH - innerSpacing - outSpacing) {
3434
3535
  // 下面比上面宽敞 或 下面足够放下所有 放下面
3435
3536
  maxHeight = Math.min(realHeight, downH - innerSpacing - outSpacing);
@@ -5015,17 +5116,17 @@ const IconTypeMap = new Map([[TypeEnum.filter, {
5015
5116
  name: __('SqlQueryBuilder.rowLimit'),
5016
5117
  icon: jsx(RowLimitIcon, {}),
5017
5118
  className: 'rowLimit'
5018
- }], [TypeEnum.group, {
5119
+ }], [TypeEnum.union, {
5019
5120
  name: __('SqlQueryBuilder.union'),
5020
5121
  icon: jsx(GroupIcon, {}),
5021
5122
  className: 'union'
5022
5123
  }]]);
5023
5124
  // 前端展示的icon顺序 随便改不影响逻辑
5024
- const DisplayOrder = [TypeEnum.filter, TypeEnum.summarize, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.group];
5125
+ const DisplayOrder = [TypeEnum.filter, TypeEnum.summarize, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.union];
5025
5126
  // js逻辑顺序 正常顺序
5026
- const OrderType = [TypeEnum.data, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.group];
5127
+ const OrderType = [TypeEnum.data, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.union];
5027
5128
  // js逻辑顺序 聚合下面的顺序是这个样子
5028
- const OrderNewType = [TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.group];
5129
+ const OrderNewType = [TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.joinData, TypeEnum.permissionTable, TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.union];
5029
5130
  const metaIcon = (size, handleClick) => {
5030
5131
  return ({
5031
5132
  type
@@ -5130,7 +5231,7 @@ const findNextIcon = (store, props) => {
5130
5231
  if (meta.table2.name) {
5131
5232
  available = OrderType.slice(curLocation + 1);
5132
5233
  } else {
5133
- available = [TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.group];
5234
+ available = [TypeEnum.customColumn, TypeEnum.filter, TypeEnum.summarize, TypeEnum.union];
5134
5235
  }
5135
5236
  } else {
5136
5237
  if (isLast) {
@@ -5152,7 +5253,7 @@ const findNextIcon = (store, props) => {
5152
5253
  if (meta.customColumn.length || ~joinIndex && prevList[joinIndex].table2.name) {
5153
5254
  available = OrderType.slice(curLocation + 1);
5154
5255
  } else {
5155
- available = [TypeEnum.filter, TypeEnum.summarize, TypeEnum.group];
5256
+ available = [TypeEnum.filter, TypeEnum.summarize, TypeEnum.union];
5156
5257
  }
5157
5258
  } else {
5158
5259
  if (isLast) {
@@ -5185,7 +5286,7 @@ const findNextIcon = (store, props) => {
5185
5286
  if (isLast) {
5186
5287
  if (!ExistAboveGroupBy) {
5187
5288
  if (meta.group.length && !meta.by.length) ; else if (!meta.group.length && !meta.by.length) {
5188
- available = [TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.group];
5289
+ available = [TypeEnum.sort, TypeEnum.rowLimit, TypeEnum.union];
5189
5290
  } else {
5190
5291
  available = OrderNewType;
5191
5292
  }
@@ -8545,21 +8646,16 @@ const Metabase = props => {
8545
8646
  }, [store.popupData2]);
8546
8647
  const onSave = async () => {
8547
8648
  let intercept = false; // 是否返回
8649
+ const _metaList = splitByUnion(store.metaList);
8548
8650
  store.metaList.map(v => {
8549
- if (v.type !== 'group' && !(v.list?.[0]).table.name) {
8651
+ if (v.type !== 'union' && !(v.list?.[0]).table.name) {
8550
8652
  intercept = true;
8551
8653
  return Toast.warning(__('data.pleaseSelectDataTable'));
8552
8654
  }
8553
8655
  });
8554
8656
  if (saveLoading || intercept) return null;
8555
8657
  setSaveLoading(true);
8556
- if (store.toolbar.includes('group')) {
8557
- // 分组
8558
- await onOk?.(store.metaList);
8559
- } else {
8560
- // 非分组
8561
- await onOk?.(store.metaList[0].list);
8562
- }
8658
+ await onOk?.(_metaList);
8563
8659
  setSaveLoading(false);
8564
8660
  };
8565
8661
  let zIndex = popupContainer.current ? getMaxZIndexInParents(popupContainer.current) : null;
@@ -8570,15 +8666,15 @@ const Metabase = props => {
8570
8666
  children: jsxs("div", {
8571
8667
  className: 'Sqb',
8572
8668
  children: [store.metaList.map((v, index) => {
8573
- if (v.type === 'group' && v.operator) {
8669
+ if (v.type === 'union' && v.union) {
8574
8670
  return jsx("div", {
8575
8671
  className: cx(`Sqb-list`),
8576
8672
  children: jsx(RowLimit$1, {
8577
- operator: v.operator,
8673
+ union: v.union,
8578
8674
  meta: v,
8579
8675
  groupIndex: index
8580
8676
  })
8581
- }, 'group' + index);
8677
+ }, 'union' + index);
8582
8678
  }
8583
8679
  return jsx("div", {
8584
8680
  className: cx(`Sqb-list`),
@@ -8665,15 +8761,9 @@ const SqlVisionBuilder = /*#__PURE__*/React__default.forwardRef((props, ref) =>
8665
8761
  store.setProps(props);
8666
8762
  }, [props]);
8667
8763
  useEffect(() => {
8668
- if (toolbar.includes('group')) {
8669
- store.setPreData(value);
8670
- } else {
8671
- store.setPreData([{
8672
- name: 'default',
8673
- list: value
8674
- }]);
8675
- }
8676
- }, [value, toolbar]);
8764
+ const _value = reassembleByUnion(value);
8765
+ store.setPreData(_value);
8766
+ }, [value]);
8677
8767
  useEffect(() => {
8678
8768
  store.setSourceList(sourceList);
8679
8769
  }, [sourceList]);