@gingkoo/pandora-metabase 1.0.93 → 1.0.95

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.
@@ -30,6 +30,14 @@ export declare const patchData: (metas: MetaListType[]) => MetaListType[];
30
30
  export declare function reassembleByUnion(target?: any[]): any[];
31
31
  export declare const buildSqlQuery: (data: MetaListType[] | undefined, type: string) => string;
32
32
  export declare const isError: (item: AtomsItem | AtomsItem[], data: DataType[]) => boolean;
33
+ /**
34
+ * 在嵌套结构 root 中查找是否存在一个对象,使得 target 是该对象的子集
35
+ * @param root 可能包含任意层数组/对象的根数据
36
+ * @param target 目标对象(可能只包含部分字段)
37
+ * @returns 是否存在
38
+ */
39
+ export declare function containsSubset(root: unknown, target: Record<string, unknown>): boolean;
40
+ export declare const isExistsError: (meta: any[], errorList: any[]) => boolean;
33
41
  export declare const changeCopyField: (items: AtomsItem[], data: any[]) => AtomsItem[];
34
42
  export declare const changeExistsCopyField: (list: MetaListType[], data: any[]) => MetaListType[];
35
43
  export declare const metaIsCheck: (data: any[], item: any) => boolean;
package/lib/cjs/utils.js CHANGED
@@ -4,11 +4,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.isError = exports.isCanPaste = exports.getSubColumns = exports.getMetaTabels = exports.getHelper = exports.getColumnsTables = exports.findMetaKey = exports.findIndex = exports.changeTableAlias = exports.changeFieldAlias = exports.changeExistsCopyField = exports.changeCopyField = exports.buildSqlQuery = void 0;
7
+ exports.changeTableAlias = exports.changeFieldAlias = exports.changeExistsCopyField = exports.changeCopyField = exports.buildSqlQuery = void 0;
8
+ exports.containsSubset = containsSubset;
9
+ exports.isExistsError = exports.isError = exports.isCanPaste = exports.getSubColumns = exports.getMetaTabels = exports.getHelper = exports.getColumnsTables = exports.findMetaKey = exports.findIndex = void 0;
8
10
  exports.isValidSQLAlias = isValidSQLAlias;
9
11
  exports.patchData = exports.metaIsCheck = void 0;
10
12
  exports.reassembleByUnion = reassembleByUnion;
11
13
  exports.splitByUnion = splitByUnion;
14
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/typeof"));
12
15
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
13
16
  var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/createForOfIteratorHelper"));
14
17
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
@@ -778,14 +781,101 @@ var _isError = exports.isError = function isError(item, data) {
778
781
  }
779
782
  return false; // 其他类型默认无错误
780
783
  };
784
+ /**
785
+ * 深度判断 sub 是否是 obj 的子集(递归比较所有可枚举自有属性)
786
+ * @param sub 可能包含部分属性的对象
787
+ * @param obj 待比较的对象
788
+ * @param visited 用于处理循环引用的 WeakSet
789
+ */
790
+ function isSubset(sub, obj) {
791
+ var visited = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new WeakSet();
792
+ // 基本类型或引用相同
793
+ if (sub === obj) return true;
794
+ // 如果任一不是对象/数组,或者为 null,则不相等(sub 为基本类型时,上面已经比较过,这里只处理对象不等的情况)
795
+ if ((0, _typeof2["default"])(sub) !== 'object' || sub === null || (0, _typeof2["default"])(obj) !== 'object' || obj === null) {
796
+ return false;
797
+ }
798
+ // 避免循环引用
799
+ if (visited.has(sub) || visited.has(obj)) return false;
800
+ visited.add(sub);
801
+ visited.add(obj);
802
+ // 处理数组
803
+ if (Array.isArray(sub)) {
804
+ if (!Array.isArray(obj) || sub.length !== obj.length) return false;
805
+ for (var i = 0; i < sub.length; i++) {
806
+ if (!isSubset(sub[i], obj[i], visited)) return false;
807
+ }
808
+ return true;
809
+ }
810
+ // 普通对象:遍历 sub 的每个键
811
+ for (var key in sub) {
812
+ if (Object.prototype.hasOwnProperty.call(sub, key)) {
813
+ // obj 必须包含该键
814
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) return false;
815
+ // 递归比较值
816
+ if (!isSubset(sub[key], obj[key], visited)) return false;
817
+ }
818
+ }
819
+ return true;
820
+ }
821
+ /**
822
+ * 在嵌套结构 root 中查找是否存在一个对象,使得 target 是该对象的子集
823
+ * @param root 可能包含任意层数组/对象的根数据
824
+ * @param target 目标对象(可能只包含部分字段)
825
+ * @returns 是否存在
826
+ */
827
+ function containsSubset(root, target) {
828
+ var visited = new WeakSet();
829
+ function search(current) {
830
+ if (current && (0, _typeof2["default"])(current) === 'object') {
831
+ // 避免循环引用
832
+ if (visited.has(current)) return false;
833
+ visited.add(current);
834
+ // 如果是普通对象(非数组),先检查是否包含 target 子集
835
+ if (!Array.isArray(current) && isSubset(target, current)) {
836
+ return true;
837
+ }
838
+ // 继续深入遍历子元素
839
+ if (Array.isArray(current)) {
840
+ var _iterator2 = (0, _createForOfIteratorHelper2["default"])(current),
841
+ _step2;
842
+ try {
843
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
844
+ var item = _step2.value;
845
+ if (search(item)) return true;
846
+ }
847
+ } catch (err) {
848
+ _iterator2.e(err);
849
+ } finally {
850
+ _iterator2.f();
851
+ }
852
+ } else {
853
+ for (var key in current) {
854
+ if (Object.prototype.hasOwnProperty.call(current, key)) {
855
+ if (search(current[key])) return true;
856
+ }
857
+ }
858
+ }
859
+ }
860
+ return false;
861
+ }
862
+ return search(root);
863
+ }
864
+ // 判断当前meta中是否含有errorList
865
+ var isExistsError = exports.isExistsError = function isExistsError(meta, errorList) {
866
+ var _meta = (0, _cloneDeep3["default"])(meta);
867
+ return errorList.some(function (error) {
868
+ return containsSubset(_meta, error);
869
+ });
870
+ };
781
871
  // 设置新字段信息
782
872
  function setNewField(field, data) {
783
873
  console.log('🚀 ~ setNewField ~ field:', field);
784
- var _iterator2 = (0, _createForOfIteratorHelper2["default"])(data),
785
- _step2;
874
+ var _iterator3 = (0, _createForOfIteratorHelper2["default"])(data),
875
+ _step3;
786
876
  try {
787
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
788
- var table = _step2.value;
877
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
878
+ var table = _step3.value;
789
879
  // 第一步:判断表名是否一致
790
880
  if (table.name !== field.tableName) {
791
881
  continue;
@@ -813,9 +903,9 @@ function setNewField(field, data) {
813
903
  break;
814
904
  }
815
905
  } catch (err) {
816
- _iterator2.e(err);
906
+ _iterator3.e(err);
817
907
  } finally {
818
- _iterator2.f();
908
+ _iterator3.f();
819
909
  }
820
910
  console.log('🚀 ~ setNewField ~ field:', field);
821
911
  return field;
@@ -9,8 +9,9 @@ import './index.less';
9
9
  import FormulaList from '../formula-list';
10
10
  import { AddIcon, CloseIcon } from '../../icons';
11
11
  import { isOk } from '../formula-list/utils';
12
+ import ItemName from '../../modules/components/item-name';
12
13
  import { __ } from '../../../locale';
13
- import { getTemArgs, getObjTem, getParamActions, getQuotes } from './utils';
14
+ import { getTemArgs, getObjTem, getParamActions, getQuotes, formulaName, formulaIsError } from './utils';
14
15
  import Styled from 'styled-components';
15
16
  // import { OptionsTypeEnum, customTypes, otherList, operatorList, functionList } from './enum';
16
17
  import { AtomsTypeEnum, FormulaTypeEnum } from '../../../store/types';
@@ -126,36 +127,39 @@ var CaseEditor = React.forwardRef(function (props, ref) {
126
127
  children: "\u8BF7\u5148\u9009\u62E9\u516C\u5F0F\uFF0C\u5207\u6362\u516C\u5F0F\u65F6\u4F1A\u91CD\u7F6E\u53C2\u6570"
127
128
  }), _jsx("div", {
128
129
  className: 'Sqb-NotebookCell formula-name',
129
- children: _jsx(Select, {
130
- triggerProps: {
131
- clickToClose: true
132
- },
133
- value: fun.id || fun.name,
134
- triggerElement: function triggerElement(value) {
135
- var _formulaList$fun$id;
136
- return _jsx("div", {
137
- className: cx("Sqb-TableName Sqb-TableName-OPERATOR", {
138
- notSelected: !fun.name
139
- }),
140
- children: fun.id ? (_formulaList$fun$id = formulaList[fun.id]) === null || _formulaList$fun$id === void 0 ? void 0 : _formulaList$fun$id.name : __('customColumn.selectFormula')
141
- });
142
- },
143
- onChange: function onChange(val) {
144
- handleFunName(val);
145
- },
146
- children: (_store$formulaTemplat = store.formulaTemplates) === null || _store$formulaTemplat === void 0 ? void 0 : _store$formulaTemplat.map(function (options, index) {
147
- return _jsx(Select.OptGroup, {
148
- label: options.name,
149
- children: Array.from(options.children || []).map(function (option, ind) {
150
- return _jsx(Select.Option, {
151
- value: option.id,
152
- children: option.name
153
- }, option.id || String(option.name + ind));
154
- })
155
- }, index);
156
- // <Select.Option key={index} value={option.name}>
157
- // {option.name}
158
- // </Select.Option>
130
+ children: _jsx(ItemName, {
131
+ isError: formulaIsError(fun, formulaList),
132
+ message: '公式丢失',
133
+ children: _jsx(Select, {
134
+ triggerProps: {
135
+ clickToClose: true
136
+ },
137
+ value: fun.id || fun.name,
138
+ triggerElement: function triggerElement(value) {
139
+ return _jsx("div", {
140
+ className: cx("Sqb-TableName Sqb-TableName-OPERATOR", {
141
+ notSelected: !fun.name
142
+ }),
143
+ children: formulaName(fun, formulaList) || __('customColumn.selectFormula')
144
+ });
145
+ },
146
+ onChange: function onChange(val) {
147
+ handleFunName(val);
148
+ },
149
+ children: (_store$formulaTemplat = store.formulaTemplates) === null || _store$formulaTemplat === void 0 ? void 0 : _store$formulaTemplat.map(function (options, index) {
150
+ return _jsx(Select.OptGroup, {
151
+ label: options.name,
152
+ children: Array.from(options.children || []).map(function (option, ind) {
153
+ return _jsx(Select.Option, {
154
+ value: option.id,
155
+ children: option.name
156
+ }, option.id || String(option.name + ind));
157
+ })
158
+ }, index);
159
+ // <Select.Option key={index} value={option.name}>
160
+ // {option.name}
161
+ // </Select.Option>
162
+ })
159
163
  })
160
164
  })
161
165
  }), fun.name && _jsxs("div", {
@@ -5,4 +5,6 @@ export declare function getParamActions(params: AtomsItem[], arity?: Arity): {
5
5
  canAdd: boolean;
6
6
  canDel: boolean;
7
7
  };
8
+ export declare const formulaName: (fun: any, formulaList: any) => any;
8
9
  export declare const getQuotes: (fun: any, _args: AtomsItem[], formulaList: any) => string;
10
+ export declare const formulaIsError: (fun: any, formulaList: any) => boolean;
@@ -56,8 +56,12 @@ export function getParamActions(params, arity) {
56
56
  canDel: len > effectiveMin // 大于 min 才能删
57
57
  };
58
58
  }
59
+ // 获取公式名称 如果找不到 用传入的name
60
+ export var formulaName = function formulaName(fun, formulaList) {
61
+ var obj = formulaList[fun.id] || formulaList[fun.name];
62
+ return (obj === null || obj === void 0 ? void 0 : obj.name) || fun.name;
63
+ };
59
64
  export var getQuotes = function getQuotes(fun, _args, formulaList) {
60
- var _formulaList$fun$id;
61
65
  var quotes = _args === null || _args === void 0 ? void 0 : _args.map(function (v) {
62
66
  var quotes = v.list.map(function (vv, i) {
63
67
  if (vv !== null && vv !== void 0 && vv.quotes) {
@@ -70,5 +74,10 @@ export var getQuotes = function getQuotes(fun, _args, formulaList) {
70
74
  }).join(' ');
71
75
  return quotes;
72
76
  }).join(' , ');
73
- return ((_formulaList$fun$id = formulaList[fun.id]) === null || _formulaList$fun$id === void 0 ? void 0 : _formulaList$fun$id.name) + ' ( ' + quotes + ' ) ';
77
+ // let obj = formulaList[fun.id] || formulaList[fun.name];
78
+ return formulaName(fun, formulaList) + ' ( ' + quotes + ' ) ';
79
+ };
80
+ export var formulaIsError = function formulaIsError(fun, formulaList) {
81
+ var obj = fun.id ? formulaList[fun.id] : formulaList[fun.name];
82
+ return !(obj !== null && obj !== void 0 && obj.name);
74
83
  };
@@ -15,12 +15,12 @@ import cx from 'classnames';
15
15
  import Metabase from '../../../index';
16
16
  import { __ } from '../../../locale';
17
17
  import isEqual from 'lodash/isEqual';
18
- import { getObjTem, getQuotes } from '../formula/utils';
18
+ import { getObjTem, getQuotes, formulaIsError } from '../formula/utils';
19
19
  import { AtomsTypeEnum, FormulaTypeEnum } from '../../../store/types';
20
20
  import { ColumnsPopupThemeEnum } from '../../../store/enum';
21
21
  import { Select, Input, Modal2, Modal, InputNumber, Radio, Space, Button, Checkbox, Tooltip } from '@gingkoo/pandora';
22
22
  import cloneDeep from 'lodash/cloneDeep';
23
- import { buildSqlQuery, isError, changeCopyField } from '../../../utils';
23
+ import { buildSqlQuery, isError, changeCopyField, isExistsError } from '../../../utils';
24
24
  import Formula from '../formula';
25
25
  import { AddIcon, CloseIcon } from '../../icons';
26
26
  import { Expression, SelectColumnMultiple } from '../../dialog';
@@ -32,7 +32,7 @@ import ItemName from '../../modules/components/item-name';
32
32
  import DiffViewer from '../diff-viewer';
33
33
  import storage from '../../../utils/storage';
34
34
  var FormulaList = forwardRef(function (props, ref) {
35
- var _storage$_metabaseCop, _store$operatorList, _caseList2;
35
+ var _storage$_metabaseCop, _caseList2;
36
36
  // 响应 storage._metabaseCopyItems 变化,保证粘贴按钮能实时显示
37
37
  var _useState = useState((storage === null || storage === void 0 || (_storage$_metabaseCop = storage._metabaseCopyItems) === null || _storage$_metabaseCop === void 0 ? void 0 : _storage$_metabaseCop.length) || 0),
38
38
  _useState2 = _slicedToArray(_useState, 2),
@@ -59,8 +59,6 @@ var FormulaList = forwardRef(function (props, ref) {
59
59
  onChange = props.onChange,
60
60
  _props$customTypes = props.customTypes,
61
61
  _customTypes = _props$customTypes === void 0 ? customTypes : _props$customTypes,
62
- _props$operatorList = props.operatorList,
63
- _operatorList = _props$operatorList === void 0 ? ((_store$operatorList = store.operatorList) === null || _store$operatorList === void 0 ? void 0 : _store$operatorList.length) > 0 ? store.operatorList : __operatorList : _props$operatorList,
64
62
  _props$isCustom = props.isCustom,
65
63
  isCustom = _props$isCustom === void 0 ? false : _props$isCustom,
66
64
  _props$showPreview = props.showPreview,
@@ -615,20 +613,23 @@ var FormulaList = forwardRef(function (props, ref) {
615
613
  var itemDom = function itemDom(v, index) {
616
614
  var type = v.type;
617
615
  if (v.type === AtomsTypeEnum.NOT_EXISTS || v.type === AtomsTypeEnum.EXISTS) {
618
- return _jsxs("div", {
619
- className: "Sqb-TableName purple-name",
620
- onClick: function onClick(e) {
621
- return showNotExists(index);
622
- },
623
- children: [v.type, " ( * )", _jsx("span", {
624
- style: {
625
- fontSize: 0
626
- },
616
+ return _jsx(ItemName, {
617
+ isError: isExistsError(v.notExists, store.existsError),
618
+ children: _jsxs("div", {
619
+ className: "Sqb-TableName purple-name",
627
620
  onClick: function onClick(e) {
628
- return handleDel(e, index);
621
+ return showNotExists(index);
629
622
  },
630
- children: _jsx(CloseIcon, {})
631
- })]
623
+ children: [v.type, " ( * )", _jsx("span", {
624
+ style: {
625
+ fontSize: 0
626
+ },
627
+ onClick: function onClick(e) {
628
+ return handleDel(e, index);
629
+ },
630
+ children: _jsx(CloseIcon, {})
631
+ })]
632
+ }, index)
632
633
  }, index);
633
634
  } else if (v.type === AtomsTypeEnum.SUB_QUERY) {
634
635
  return _jsxs("div", {
@@ -738,7 +739,7 @@ var FormulaList = forwardRef(function (props, ref) {
738
739
  onChange: function onChange(val) {
739
740
  handleConstant(val, index);
740
741
  },
741
- children: _operatorList.map(function (option, index) {
742
+ children: operatorList.map(function (option, index) {
742
743
  return _jsx(Select.Option, {
743
744
  value: option,
744
745
  children: option
@@ -748,8 +749,8 @@ var FormulaList = forwardRef(function (props, ref) {
748
749
  } else if (type === AtomsTypeEnum.CONSTANT) {
749
750
  //常量
750
751
  return _jsx(ItemName, {
751
- isError: !getConstantLabel(store.constantList, v.id || v.val),
752
- message: "\u5E38\u91CF\u5B57\u6BB5\u672A\u80FD\u6B63\u786E\u5BF9\u5E94",
752
+ isError: (v.id || v.val) && !getConstantLabel(store.constantList, v.id || v.val),
753
+ message: "\u5E38\u91CF\u4E22\u5931",
753
754
  children: _jsxs("div", {
754
755
  className: cx("Sqb-TableName", {
755
756
  notSelected: !v.val
@@ -769,7 +770,7 @@ var FormulaList = forwardRef(function (props, ref) {
769
770
  })
770
771
  }, index);
771
772
  } else if (type === AtomsTypeEnum.EXPRESSION) {
772
- if (v.condition === '早于' && v.rhs.length === 2) {
773
+ if (~['早于', '晚于', ''].indexOf(v.condition) && v.rhs.length > 1) {
773
774
  var _caseList$index$quote;
774
775
  var _caseList = caseList.slice();
775
776
  _caseList[index].rhs = [_caseList[index].rhs[0]];
@@ -800,7 +801,8 @@ var FormulaList = forwardRef(function (props, ref) {
800
801
  } else if (type === AtomsTypeEnum.FORMULA) {
801
802
  // 公式
802
803
  return _jsx(ItemName, {
803
- isError: isError(v, data),
804
+ isError: isError(v, data) || formulaIsError(v, formulaList),
805
+ message: formulaIsError(v, formulaList) ? '公式丢失' : '',
804
806
  children: _jsxs("div", {
805
807
  className: cx("Sqb-TableName gray-name"),
806
808
  onClick: function onClick(e) {