@tachybase/plugin-block-charts 0.23.47 → 0.23.58

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.
@@ -17,7 +17,7 @@
17
17
  > .ant-formily-item-label {
18
18
  display: none;
19
19
  }
20
- `]:r===!1}),[r]),o=(n==null?void 0:n["x-data-source"])||Y.DEFAULT_DATA_SOURCE_KEY,s=(n==null?void 0:n["x-collection-field"])||"",[l]=s.split(".");return H.jsx(Y.BlockItem,{className:"tb-form-item",children:H.jsx(Y.CollectionManagerProvider,{dataSource:o,children:H.jsx(Y.CollectionProvider,{name:l,allowNull:!l,children:H.jsx(Y.CollectionFieldProvider,{name:n.name,allowNull:!n["x-collection-field"],children:H.jsx(Y.ACLCollectionFieldProvider,{children:H.jsx(r_,{onError:f=>{var d;console.log(f),(d=window==null?void 0:window.Sentry)==null||d.captureException(f)},FallbackComponent:Q6,children:H.jsx(It.FormItem,Oe(ce({className:a},e),{extra:i}))})})})})})})},{displayName:"ChartFilterFormItem"}),p_=K.memo(e=>{const{locale:t}=K.useContext(Me.ConfigProvider.ConfigContext),{t:n}=mt(),r=zi.useMemoizedFn(n),{scope:i,components:a}=K.useContext(he.SchemaOptionsContext),{theme:o}=Y.useGlobalTheme(),{insert:s}=e,l=Y.useSchemaInitializerItem(),c=Y.useDataSourceManager(),u=d_(),{options:f,values:d}=h_(),{collections:h,getCollectionFields:p}=Y.useCollectionManager_deprecated(),v=Y.useCompile(),y=h.map(m=>({label:m.getOption("title"),value:m.getOption("name")})),g=K.useCallback(()=>$r(this,null,function*(){var k,E;const m=yield Y.FormDialog(r("Add custom field"),()=>H.jsx(Y.SchemaComponentOptions,{scope:Oe(ce({},i),{useChartFilterSourceFields:d_,useCollectionField(M){var P;return(P=p(M))==null?void 0:P.map(A=>({label:v(A.uiSchema.title),value:A.name}))}}),components:Oe(ce({},a),{FieldComponentProps:Z6}),children:H.jsxs(It.FormLayout,{layout:"vertical",children:[H.jsx(Me.Alert,{type:"info",message:r('To filter with custom fields, use "Current filter" variables in the chart configuration.'),style:{marginBottom:16}}),H.jsx(Me.ConfigProvider,{locale:t,children:H.jsx(Y.SchemaComponent,{schema:{properties:{name:{type:"string",required:!0},title:{type:"string",title:r("Field title"),"x-component":"Input","x-decorator":"FormItem",required:!0},source:{type:"string",title:r("Field source"),"x-decorator":"FormItem","x-component":"Cascader",enum:u,description:r("Select a source field to use metadata of the field")},component:{type:"string",title:r("Field component"),"x-component":"Select","x-decorator":"FormItem",required:!0,enum:f},props:{type:"object",title:r("Component properties"),"x-component":"FieldComponentProps","x-component-props":{allCollection:y}}}}})})]})}),o).open({values:{name:`f_${he.uid()}`},effects(){he.onFieldValueChange("source",M=>{if(!M.value)return;const[P,...A]=M.value,L=c.getDataSource(P);if(!L)return;const N=L.collectionManager,T=A.join("."),I=N.getCollectionField(T);if(!I)return;const C=I.uiSchema||{};let j;if(d.includes(C["x-component"])){j=C["x-component"];const F=C["x-component-props"]||{};C.enum&&(F.options=C.enum),M.query(".props").take().setValue(F)}else d.includes(I.interface)&&(j=I.interface);if(!j)return;M.query(".component").take().setValue(j)})}}),{name:b,title:x,component:w,props:O}=m,S=((E=(k=c.collectionFieldInterfaceManager.getFieldInterface(w))==null?void 0:k.default)==null?void 0:E.uiSchema)||{};s(Y.gridRowColWrap(Oe(ce({"x-component":w},S),{type:"string",title:x,name:`custom.${b}`,required:!1,"x-designer":"ChartFilterItemDesigner","x-decorator":"ChartFilterFormItem","x-component-props":Oe(ce(ce({},S["x-component-props"]),O),{chartCascader:!0})})))}),[o]);return H.jsx(Y.SchemaInitializerItem,Oe(ce(ce({},l),e),{onClick:g}))});p_.displayName="ChartFilterCustomItemInitializer";const e$={name:"chartFilterForm:configureFields","data-testid":"configure-fields-button-of-chart-filter-item",wrap:Y.gridRowColWrap,icon:"SettingOutlined",title:'{{ t("Configure fields") }}',items:[{type:"itemGroup",name:"displayFields",title:'{{ t("Display fields") }}',useChildren:()=>{const{t:e}=mt(),{chartCollections:t,showDataSource:n}=U0(),{getChartFilterFields:r}=is(),i=Y.useDataSourceManager(),a=i.collectionFieldInterfaceManager;return K.useMemo(()=>{var s;const o=Object.entries(t).map(([l,c])=>{const u=i.getDataSource(l);return{name:u.key,title:he.Schema.compile(u.displayName,{t:e}),type:"subMenu",children:c.map(f=>{const d=u.collectionManager,h=d.getCollection(f),p=r({dataSource:l,collection:h,cm:d,fim:a});return{name:h.key,title:he.Schema.compile(h.title,{t:e}),type:"subMenu",children:p}})}});return n?o:((s=o[0])==null?void 0:s.children)||[]},[t,n])}},{name:"divider",type:"divider"},{name:"custom",type:"item",title:Ve("Custom"),Component:()=>{const{insertAdjacent:e}=Y.useDesignable();return H.jsx(p_,{insert:t=>e("beforeEnd",t)})}}]},t$=new Y.SchemaInitializer(e$),n$=()=>{const{filter:e}=is();return{onClick:e}},r$=()=>{const e=he.useForm(),{filter:t}=is();return{onClick:()=>$r(this,null,function*(){e.reset(),yield t()})}},i$=()=>{const{collapse:{collapsed:e},setCollapse:t}=K.useContext(zr),{t:n}=mt();return{onClick:()=>t({collapsed:!e}),title:H.jsxs(H.Fragment,{children:[H.jsx(Sr.DownOutlined,{rotate:e?0:180})," ",n(e?"Expand":"Collapse")]})}},a$=e=>{const{t}=mt();return H.jsx(Y.GeneralSchemaDesigner,Oe(ce({},e),{disableInitializer:!0,children:H.jsx(Y.SchemaSettingsRemove,{breakRemoveOn:n=>n["x-component"]==="Space"||n["x-component"].endsWith("ActionBar"),confirm:{title:t("Delete action")}})}))},o$=e=>{const i=e,{buttonEditorProps:t}=i,n=L8(i,["buttonEditorProps"]),{t:r}=mt();return H.jsxs(Y.GeneralSchemaDesigner,Oe(ce({},n),{disableInitializer:!0,children:[H.jsx(Y.Action.Designer.ButtonEditor,ce({},t)),H.jsx(Y.SchemaSettingsDivider,{}),H.jsx(Y.SchemaSettingsRemove,{breakRemoveOn:a=>a["x-component"]==="Space"||a["x-component"].endsWith("ActionBar"),confirm:{title:r("Delete action")}})]}))},s$=e=>{const t={title:'{{ t("Filter") }}',"x-action":"submit","x-component":"Action","x-use-component-props":"useChartFilterActionProps","x-designer":"ChartFilterActionDesigner","x-component-props":{htmlType:"submit",type:"primary"}};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},l$=e=>{const t={title:'{{ t("Reset") }}',"x-action":"reset","x-component":"Action","x-use-component-props":"useChartFilterResetProps","x-designer":"ChartFilterActionDesigner"};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},c$=e=>{const t={title:'{{ t("Collapse") }}',"x-action":"collapse","x-component":"Action","x-use-component-props":"useChartFilterCollapseProps","x-component-props":{type:"link"},"x-designer":"ChartFilterCollapseDesigner"};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},u$=new Y.SchemaInitializer({name:"chartFilterForm:configureActions","data-testid":"configure-actions-button-of-chart-filter",title:'{{t("Configure actions")}}',icon:"SettingOutlined",items:[{name:"enbaleActions",type:"itemGroup",title:'{{t("Enable actions")}}',children:[{name:"filter",type:"item",title:'{{t("Filter")}}',component:s$,schema:{"x-action-settings":{}}},{name:"reset",type:"item",title:'{{t("Reset")}}',component:l$,schema:{"x-action-settings":{}}},{name:"collapse",type:"item",title:'{{t("Collapse")}}',component:c$,schema:{"x-action-settings":{}}}]}]}),f$=e=>{var h;const{value:t,onChange:n,fieldSchema:r}=e,{currentUserSettings:i}=Y.useCurrentUserVariable({collectionField:{uiSchema:r},uiSchema:r}),{datetimeSettings:a}=Y.useDatetimeVariable({operator:(h=r["x-component-props"])==null?void 0:h["filter-operator"],schema:r,noDisabled:!0}),o=K.useMemo(()=>[i,a].filter(Boolean),[a,i]),s=Oe(ce({},r),{"x-component":r["x-component"]||"Input","x-decorator":"",title:"",name:"value",default:""}),l=r["x-component-props"]||{},c=zi.useMemoizedFn(n);K.useEffect(()=>{r.default&&c({value:r.default})},[r.default,c]);const u=(s==null?void 0:s["x-data-source"])||Y.DEFAULT_DATA_SOURCE_KEY,f=(s==null?void 0:s["x-collection-field"])||"",[d]=f.split(".");return H.jsx(Y.CollectionManagerProvider,{dataSource:u,children:H.jsx(Y.CollectionProvider,{name:d,allowNull:!d,children:H.jsx(Y.CollectionFieldProvider,{name:s["x-collection-field"],allowNull:!s["x-collection-field"],children:H.jsx(Y.VariableScopeProvider,{scope:o,children:H.jsx(Y.VariableInput,Oe(ce({},l),{renderSchemaComponent:()=>H.jsx(Y.SchemaComponent,{schema:s}),fieldNames:{},value:t==null?void 0:t.value,scope:o,onChange:p=>{n({value:p})},shouldChange:Y.getShouldChange({})}))})})})})},{Text:d$}=Me.Typography,h$=()=>{const e=he.useField(),t=he.useFieldSchema(),{t:n}=mt(),{dn:r}=Y.useDesignable(),{setField:i}=K.useContext(zr);return H.jsx(Y.SchemaSettingsModalItem,{title:n("Edit field title"),schema:{type:"object",title:n("Edit field title"),properties:{title:{title:n("Field title"),default:e==null?void 0:e.title,required:!0,"x-decorator":"FormItem","x-component":"Input","x-component-props":{}}}},onSubmit:({title:a})=>{a&&(e.title=a,t.title=a,r.emit("patch",{schema:{"x-uid":t["x-uid"],title:t.title}}),i(t.name,{title:a})),r.refresh()}},"edit-field-title")},p$=()=>{var g,m,b,x;const e=Y.useCompile(),t=he.useFieldSchema(),n=he.useField(),{t:r}=mt(),{dn:i}=Y.useDesignable(),{setField:a}=K.useContext(zr),o=t["x-collection-field"],s=t["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,{cm:l,fim:c}=nu(s);if(!l)return null;const u=w=>{var k;let O=w==null?void 0:w.interface;O==="formula"&&(O=r6(w.dataType)||w.dataType);const _=c.getFieldInterface(O);return{operatorList:((k=_==null?void 0:_.filterable)==null?void 0:k.operators)||[],interfaceConfig:_}};let f=l.getCollectionField(o),{operatorList:d,interfaceConfig:h}=u(f);if(!d.length){const w=o.split("."),O=w.pop();if(f=l.getCollectionField(w.join(".")),!f)return null;const _=u(f);if(d=_.operatorList,h=_.interfaceConfig,!h)return null;const k=((h==null?void 0:h.filterable.children)||[]).find(E=>E.name===O);d=(k==null?void 0:k.operators)||[]}if(!d.length)return null;const p=((m=(g=h==null?void 0:h.default)==null?void 0:g.uiSchema)==null?void 0:m["x-component"])||"Input",v=(b=t["x-component-props"])==null?void 0:b["filter-operator"],y=(w,O,_={})=>{const S=n.componentProps||{};n.component=O,n.componentProps=ce(Oe(ce({},S),{"filter-operator":w}),_),t["x-component"]=O,t["x-component-props"]=ce(Oe(ce({},t["x-component-props"]),{"filter-operator":w}),_),i.emit("patch",{schema:{"x-uid":t["x-uid"],"x-component":O,"x-component-props":ce(Oe(ce({},t["x-component-props"]),{"filter-operator":w}),_)}})};return H.jsx(Y.SchemaSettingsSelectItem,{title:r("Operator"),value:(v==null?void 0:v.value)||((x=d[0])==null?void 0:x.value),options:e(d),onChange:w=>{var _;const O=d.find(S=>S.value===w);O.noValue?y(O,"ChartFilterCheckbox",{content:he.Schema.compile(O.label,{t:r})}):(_=O.schema)!=null&&_["x-component"]?y(O,O.schema["x-component"]):y(O,p),a(t.name,{operator:O}),i.refresh()}},"operator")},v$=()=>{const{t:e}=mt(),{dn:t}=Y.useDesignable(),n=he.useField(),r=he.useFieldSchema(),i=H0(r["x-component"]);return H.jsx(Y.SchemaSettingsModalItem,{title:e("Edit field properties"),schema:ce({title:e("Edit field properties")},i),initialValues:n.componentProps,onSubmit:a=>{n.reset(),n.componentProps=a,r["x-component-props"]=a,t.emit("patch",{schema:{"x-uid":r["x-uid"],"x-component-props":a}}),t.refresh()}},"edit-field-props")},g$=()=>{const{t:e}=mt(),{dn:t}=Y.useDesignable(),n=K.useContext(Y.VariablesContext),r=he.useField(),i=he.useFieldSchema(),{getTranslatedTitle:a}=is(),o=a(i.title);return H.jsx(Y.SchemaSettingsModalItem,{title:e("Set default value"),components:{ChartFilterVariableInput:f$},schema:{type:"void",title:e("Set default value"),properties:{default:{title:o,"x-decorator":"FormItem","x-component":"ChartFilterVariableInput","x-component-props":{fieldSchema:i}}}},onSubmit:({default:{value:s}})=>{r.setInitialValue(s),i.default=s,t.emit("patch",{schema:{"x-uid":i["x-uid"],default:s}}),t.refresh(),u_(r,n)}},"set field default value")},y$=()=>{var f,d,h;const{getCollectionFields:e,getCollectionJoinField:t,getInterface:n}=Y.useCollectionManager_deprecated(),r=he.useField(),i=he.useFieldSchema(),{t:a}=mt(),{dn:o}=Y.useDesignable(),s=Y.useCompile(),l=t(i["x-collection-field"]),u=(l!=null&&l.target?e(l==null?void 0:l.target):(f=e(l==null?void 0:l.targetCollection))!=null?f:[]).filter(p=>{if(p!=null&&p.target||p.type==="boolean")return!1;const v=n(p==null?void 0:p.interface);return v==null?void 0:v.titleUsable}).map(p=>{var v;return{value:p==null?void 0:p.name,label:s((v=p==null?void 0:p.uiSchema)==null?void 0:v.title)||(p==null?void 0:p.name)}});return u.length>0&&i["x-component"]==="CollectionField"?H.jsx(Y.SchemaSettingsSelectItem,{title:a("Title field"),options:u,value:(h=(d=r==null?void 0:r.componentProps)==null?void 0:d.fieldNames)==null?void 0:h.label,onChange:p=>{var g,m;const v={"x-uid":i["x-uid"]},y=Oe(ce(ce({},(m=(g=l==null?void 0:l.uiSchema)==null?void 0:g["x-component-props"])==null?void 0:m.fieldNames),r.componentProps.fieldNames),{label:p});i["x-component-props"]=i["x-component-props"]||{},i["x-component-props"].fieldNames=y,v["x-component-props"]=i["x-component-props"],r.componentProps.fieldNames=i["x-component-props"].fieldNames,o.emit("patch",{schema:v}),o.refresh()}},"title-field"):null},m$=()=>{var c,u;const{form:e}=Y.useFormBlockContext(),t=he.useFieldSchema(),n=t["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,{cm:r}=nu(n),i=he.useField(),{dn:a}=Y.useDesignable(),o=r.getCollectionField(t["x-collection-field"]),s=((u=(c=t==null?void 0:t["x-component-props"])==null?void 0:c.params)==null?void 0:u.filter)||{},l=({filter:f})=>{f=Y.removeNullCondition(f),B.set(i.componentProps,"service.params.filter",f),t["x-component-props"]=i.componentProps,a.emit("patch",{schema:{"x-uid":t["x-uid"],"x-component-props":t["x-component-props"]}})};return o?H.jsx(Y.SchemaSettingsDataScope,{form:e,collectionName:o.target,defaultFilter:s,onSubmit:l}):null},b$=()=>{const{getCollectionJoinField:e}=Y.useCollectionManager_deprecated(),{getField:t}=Y.useCollection_deprecated(),{t:n}=mt(),r=he.useFieldSchema(),i=r.name,a=r["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,o=t(i)||e(r["x-collection-field"]),s=i.startsWith("custom."),l=H0(r["x-component"]),c=F6(a,i),u=Y.useIsAssociationField();return H.jsxs(Y.GeneralSchemaDesigner,{disableInitializer:!0,children:[!s&&H.jsxs(H.Fragment,{children:[H.jsx(Y.SchemaSettingsItem,{title:i,children:H.jsxs(d$,{type:"secondary",children:[n("Original field"),": ",c]})}),H.jsx(Y.SchemaSettingsDivider,{})]}),H.jsx(h$,{}),H.jsx(Y.EditDescription,{}),u&&H.jsx(m$,{}),l&&s&&H.jsx(v$,{}),!s&&H.jsx(p$,{}),H.jsx(y$,{}),H.jsx(g$,{}),H.jsx(Y.SchemaSettingsSortingRule,{}),o?H.jsx(Y.SchemaSettingsDivider,{}):null,H.jsx(Y.SchemaSettingsRemove,{confirm:{title:n("Delete field")},breakRemoveOn:{"x-component":"Grid"}},"remove")]})},x$=()=>{const e={},t=Y.useSchemaInitializerItem();return H.jsx(Y.InitializerWithSwitch,Oe(ce({},t),{item:t,schema:e,type:"name"}))},w$=he.connect(e=>{const{content:t}=e,n=he.useField(),r=()=>{n.setValue(!n.value)};return H.jsx(Me.Checkbox,{onClick:r,checked:n.value,children:t})}),v_=K.memo(e=>{const{setField:t,removeField:n,setForm:r}=K.useContext(zr),{getTranslatedTitle:i}=is(),a=K.useRef(null);a.current=K.useContext(Y.VariablesContext);const o=K.useMemo(()=>he.createForm({effects(){const s=l=>{if(l.displayName!=="Field")return null;const{name:c}=l.props||{};return c};he.onFieldInit("*",l=>{s(l)&&l.setValue(null)}),he.onFieldMount("*",l=>$r(this,null,function*(){const c=s(l);c&&(t(c,{title:l.title,operator:l.componentProps["filter-operator"]}),l.title.includes("/")&&(l.title=i(l.title)),u_(l,a.current))})),he.onFieldUnmount("*",l=>{const c=s(l);c&&n(c)})}}),[t,i,n,a]);return K.useEffect(()=>r(o),[o,r]),H.jsx(Y.FormV2,Oe(ce({},e),{form:o}))});v_.displayName="ChartFilterForm";const O$=e=>{const{t}=mt(),{setEnabled:n}=K.useContext(zr);return K.useEffect(()=>{n(!0)},[n]),H.jsx("div",{className:Y.css`
20
+ `]:r===!1}),[r]),o=(n==null?void 0:n["x-data-source"])||Y.DEFAULT_DATA_SOURCE_KEY,s=(n==null?void 0:n["x-collection-field"])||"",[l]=s.split(".");return H.jsx(Y.BlockItem,{className:"tb-form-item",children:H.jsx(Y.CollectionManagerProvider,{dataSource:o,children:H.jsx(Y.CollectionProvider,{name:l,allowNull:!l,children:H.jsx(Y.CollectionFieldProvider,{name:n.name,allowNull:!n["x-collection-field"],children:H.jsx(Y.ACLCollectionFieldProvider,{children:H.jsx(r_,{onError:f=>{var d;console.log(f),(d=window==null?void 0:window.Sentry)==null||d.captureException(f)},FallbackComponent:Q6,children:H.jsx(It.FormItem,Oe(ce({className:a},e),{extra:i}))})})})})})})},{displayName:"ChartFilterFormItem"}),p_=K.memo(e=>{const{locale:t}=K.useContext(Me.ConfigProvider.ConfigContext),{t:n}=mt(),r=zi.useMemoizedFn(n),{scope:i,components:a}=K.useContext(he.SchemaOptionsContext),{theme:o}=Y.useGlobalTheme(),{insert:s}=e,l=Y.useSchemaInitializerItem(),c=Y.useDataSourceManager(),u=d_(),{options:f,values:d}=h_(),{collections:h,getCollectionFields:p}=Y.useCollectionManager_deprecated(),v=Y.useCompile(),y=h.map(m=>({label:m.getOption("title"),value:m.getOption("name")})),g=K.useCallback(()=>$r(this,null,function*(){var k,E;const m=yield Y.FormDialog(r("Add custom field"),()=>H.jsx(Y.SchemaComponentOptions,{scope:Oe(ce({},i),{useChartFilterSourceFields:d_,useCollectionField(M){var P;return(P=p(M))==null?void 0:P.map(A=>({label:v(A.uiSchema.title),value:A.name}))}}),components:Oe(ce({},a),{FieldComponentProps:Z6}),children:H.jsxs(It.FormLayout,{layout:"vertical",children:[H.jsx(Me.Alert,{type:"info",message:r('To filter with custom fields, use "Current filter" variables in the chart configuration.'),style:{marginBottom:16}}),H.jsx(Me.ConfigProvider,{locale:t,children:H.jsx(Y.SchemaComponent,{schema:{properties:{name:{type:"string",required:!0},title:{type:"string",title:r("Field title"),"x-component":"Input","x-decorator":"FormItem",required:!0},source:{type:"string",title:r("Field source"),"x-decorator":"FormItem","x-component":"Cascader",enum:u,description:r("Select a source field to use metadata of the field")},component:{type:"string",title:r("Field component"),"x-component":"Select","x-decorator":"FormItem",required:!0,enum:f},props:{type:"object",title:r("Component properties"),"x-component":"FieldComponentProps","x-component-props":{allCollection:y}}}}})})]})}),o).open({values:{name:`f_${he.uid()}`},effects(){he.onFieldValueChange("source",M=>{if(!M.value)return;const[P,...A]=M.value,L=c.getDataSource(P);if(!L)return;const N=L.collectionManager,T=A.join("."),I=N.getCollectionField(T);if(!I)return;const C=I.uiSchema||{};let j;if(d.includes(C["x-component"])){j=C["x-component"];const F=C["x-component-props"]||{};C.enum&&(F.options=C.enum),M.query(".props").take().setValue(F)}else d.includes(I.interface)&&(j=I.interface);if(!j)return;M.query(".component").take().setValue(j)})}}),{name:b,title:x,component:w,props:O}=m,S=((E=(k=c.collectionFieldInterfaceManager.getFieldInterface(w))==null?void 0:k.default)==null?void 0:E.uiSchema)||{};s(Y.gridRowColWrap(Oe(ce({"x-component":w},S),{type:"string",title:x,name:`custom.${b}`,required:!1,"x-designer":"ChartFilterItemDesigner","x-decorator":"ChartFilterFormItem","x-component-props":Oe(ce(ce({},S["x-component-props"]),O),{chartCascader:!0})})))}),[o]);return H.jsx(Y.SchemaInitializerItem,Oe(ce(ce({},l),e),{onClick:g}))});p_.displayName="ChartFilterCustomItemInitializer";const e$={name:"chartFilterForm:configureFields","data-testid":"configure-fields-button-of-chart-filter-item",wrap:Y.gridRowColWrap,icon:"SettingOutlined",title:'{{ t("Configure fields") }}',items:[{type:"itemGroup",name:"displayFields",title:'{{ t("Display fields") }}',useChildren:()=>{const{t:e}=mt(),{chartCollections:t,showDataSource:n}=U0(),{getChartFilterFields:r}=is(),i=Y.useDataSourceManager(),a=i.collectionFieldInterfaceManager;return K.useMemo(()=>{var s;const o=Object.entries(t).map(([l,c])=>{const u=i.getDataSource(l);return{name:u.key,title:he.Schema.compile(u.displayName,{t:e}),type:"subMenu",children:c.map(f=>{const d=u.collectionManager,h=d.getCollection(f),p=r({dataSource:l,collection:h,cm:d,fim:a});return{name:h.key,title:he.Schema.compile(h.title,{t:e}),type:"subMenu",children:p}})}});return n?o:((s=o[0])==null?void 0:s.children)||[]},[t,n])}},{name:"divider",type:"divider"},{name:"custom",type:"item",title:Ve("Custom"),Component:()=>{const{insertAdjacent:e}=Y.useDesignable();return H.jsx(p_,{insert:t=>e("beforeEnd",t)})}}]},t$=new Y.SchemaInitializer(e$),n$=()=>{const{filter:e}=is();return{onClick:e}},r$=()=>{const e=he.useForm(),{filter:t}=is();return{onClick:()=>$r(this,null,function*(){e.reset(),yield t()})}},i$=()=>{const{collapse:{collapsed:e},setCollapse:t}=K.useContext(zr),{t:n}=mt();return{onClick:()=>t({collapsed:!e}),title:H.jsxs(H.Fragment,{children:[H.jsx(Sr.DownOutlined,{rotate:e?0:180})," ",n(e?"Expand":"Collapse")]})}},a$=e=>{const{t}=mt();return H.jsx(Y.GeneralSchemaDesigner,Oe(ce({},e),{disableInitializer:!0,children:H.jsx(Y.SchemaSettingsRemove,{breakRemoveOn:n=>n["x-component"]==="Space"||n["x-component"].endsWith("ActionBar"),confirm:{title:t("Delete action")}})}))},o$=e=>{const i=e,{buttonEditorProps:t}=i,n=L8(i,["buttonEditorProps"]),{t:r}=mt();return H.jsxs(Y.GeneralSchemaDesigner,Oe(ce({},n),{disableInitializer:!0,children:[H.jsx(Y.Action.Designer.ButtonEditor,ce({},t)),H.jsx(Y.SchemaSettingsDivider,{}),H.jsx(Y.SchemaSettingsRemove,{breakRemoveOn:a=>a["x-component"]==="Space"||a["x-component"].endsWith("ActionBar"),confirm:{title:r("Delete action")}})]}))},s$=e=>{const t={title:'{{ t("Filter") }}',"x-action":"submit","x-component":"Action","x-use-component-props":"useChartFilterActionProps","x-designer":"ChartFilterActionDesigner","x-component-props":{htmlType:"submit",type:"primary"}};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},l$=e=>{const t={title:'{{ t("Reset") }}',"x-action":"reset","x-component":"Action","x-use-component-props":"useChartFilterResetProps","x-designer":"ChartFilterActionDesigner"};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},c$=e=>{const t={title:'{{ t("Collapse") }}',"x-action":"collapse","x-component":"Action","x-use-component-props":"useChartFilterCollapseProps","x-component-props":{type:"link"},"x-designer":"ChartFilterCollapseDesigner"};return H.jsx(Y.ActionInitializer,Oe(ce({},e),{schema:t}))},u$=new Y.SchemaInitializer({name:"chartFilterForm:configureActions","data-testid":"configure-actions-button-of-chart-filter",title:'{{t("Configure actions")}}',icon:"SettingOutlined",items:[{name:"enbaleActions",type:"itemGroup",title:'{{t("Enable actions")}}',children:[{name:"filter",type:"item",title:'{{t("Filter")}}',component:s$,schema:{"x-action-settings":{}}},{name:"reset",type:"item",title:'{{t("Reset")}}',component:l$,schema:{"x-action-settings":{}}},{name:"collapse",type:"item",title:'{{t("Collapse")}}',component:c$,schema:{"x-action-settings":{}}}]}]}),f$=e=>{var h;const{value:t,onChange:n,fieldSchema:r}=e,{currentUserSettings:i}=Y.useCurrentUserVariable({collectionField:{uiSchema:r},uiSchema:r}),{datetimeSettings:a}=Y.useDatetimeVariable({operator:(h=r["x-component-props"])==null?void 0:h["filter-operator"],schema:r,noDisabled:!0}),o=K.useMemo(()=>[i,a].filter(Boolean),[a,i]),s=Oe(ce({},r),{"x-component":r["x-component"]||"Input","x-decorator":"",title:"",name:"value",default:""}),l=r["x-component-props"]||{},c=zi.useMemoizedFn(n);K.useEffect(()=>{r.default&&c({value:r.default})},[r.default,c]);const u=(s==null?void 0:s["x-data-source"])||Y.DEFAULT_DATA_SOURCE_KEY,f=(s==null?void 0:s["x-collection-field"])||"",[d]=f.split(".");return H.jsx(Y.CollectionManagerProvider,{dataSource:u,children:H.jsx(Y.CollectionProvider,{name:d,allowNull:!d,children:H.jsx(Y.CollectionFieldProvider,{name:s["x-collection-field"],allowNull:!s["x-collection-field"],children:H.jsx(Y.VariableScopeProvider,{scope:o,children:H.jsx(Y.VariableInput,Oe(ce({},l),{renderSchemaComponent:()=>H.jsx(Y.SchemaComponent,{schema:s}),fieldNames:{},value:t==null?void 0:t.value,scope:o,onChange:p=>{n({value:p})},shouldChange:Y.getShouldChange({})}))})})})})},{Text:d$}=Me.Typography,h$=()=>{const e=he.useField(),t=he.useFieldSchema(),{t:n}=mt(),{dn:r}=Y.useDesignable(),{setField:i}=K.useContext(zr);return H.jsx(Y.SchemaSettingsModalItem,{title:n("Edit field title"),schema:{type:"object",title:n("Edit field title"),properties:{title:{title:n("Field title"),default:e==null?void 0:e.title,required:!0,"x-decorator":"FormItem","x-component":"Input","x-component-props":{}}}},onSubmit:({title:a})=>{a&&(e.title=a,t.title=a,r.emit("patch",{schema:{"x-uid":t["x-uid"],title:t.title}}),i(t.name,{title:a})),r.refresh()}},"edit-field-title")},p$=()=>{var g,m,b,x,w;const e=Y.useCompile(),t=he.useFieldSchema(),n=he.useField(),{t:r}=mt(),{dn:i}=Y.useDesignable(),{setField:a}=K.useContext(zr),o=(g=t["x-collection-field"])!=null?g:"",s=t["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,{cm:l,fim:c}=nu(s);if(!l)return null;const u=O=>{var E;let _=O==null?void 0:O.interface;_==="formula"&&(_=r6(O.dataType)||O.dataType);const S=c.getFieldInterface(_);return{operatorList:((E=S==null?void 0:S.filterable)==null?void 0:E.operators)||[],interfaceConfig:S}};let f=l.getCollectionField(o),{operatorList:d,interfaceConfig:h}=u(f);if(!d.length){const O=o.split("."),_=O.pop();if(f=l.getCollectionField(O.join(".")),!f)return null;const S=u(f);if(d=S.operatorList,h=S.interfaceConfig,!h)return null;const E=((h==null?void 0:h.filterable.children)||[]).find(M=>M.name===_);d=(E==null?void 0:E.operators)||[]}if(!d.length)return null;const p=((b=(m=h==null?void 0:h.default)==null?void 0:m.uiSchema)==null?void 0:b["x-component"])||"Input",v=(x=t["x-component-props"])==null?void 0:x["filter-operator"],y=(O,_,S={})=>{const k=n.componentProps||{};n.component=_,n.componentProps=ce(Oe(ce({},k),{"filter-operator":O}),S),t["x-component"]=_,t["x-component-props"]=ce(Oe(ce({},t["x-component-props"]),{"filter-operator":O}),S),i.emit("patch",{schema:{"x-uid":t["x-uid"],"x-component":_,"x-component-props":ce(Oe(ce({},t["x-component-props"]),{"filter-operator":O}),S)}})};return H.jsx(Y.SchemaSettingsSelectItem,{title:r("Operator"),value:(v==null?void 0:v.value)||((w=d[0])==null?void 0:w.value),options:e(d),onChange:O=>{var S;const _=d.find(k=>k.value===O);_.noValue?y(_,"ChartFilterCheckbox",{content:he.Schema.compile(_.label,{t:r})}):(S=_.schema)!=null&&S["x-component"]?y(_,_.schema["x-component"]):y(_,p),a(t.name,{operator:_}),i.refresh()}},"operator")},v$=()=>{const{t:e}=mt(),{dn:t}=Y.useDesignable(),n=he.useField(),r=he.useFieldSchema(),i=H0(r["x-component"]);return H.jsx(Y.SchemaSettingsModalItem,{title:e("Edit field properties"),schema:ce({title:e("Edit field properties")},i),initialValues:n.componentProps,onSubmit:a=>{n.reset(),n.componentProps=a,r["x-component-props"]=a,t.emit("patch",{schema:{"x-uid":r["x-uid"],"x-component-props":a}}),t.refresh()}},"edit-field-props")},g$=()=>{const{t:e}=mt(),{dn:t}=Y.useDesignable(),n=K.useContext(Y.VariablesContext),r=he.useField(),i=he.useFieldSchema(),{getTranslatedTitle:a}=is(),o=a(i.title);return H.jsx(Y.SchemaSettingsModalItem,{title:e("Set default value"),components:{ChartFilterVariableInput:f$},schema:{type:"void",title:e("Set default value"),properties:{default:{title:o,"x-decorator":"FormItem","x-component":"ChartFilterVariableInput","x-component-props":{fieldSchema:i}}}},onSubmit:({default:{value:s}})=>{r.setInitialValue(s),i.default=s,t.emit("patch",{schema:{"x-uid":i["x-uid"],default:s}}),t.refresh(),u_(r,n)}},"set field default value")},y$=()=>{var f,d,h;const{getCollectionFields:e,getCollectionJoinField:t,getInterface:n}=Y.useCollectionManager_deprecated(),r=he.useField(),i=he.useFieldSchema(),{t:a}=mt(),{dn:o}=Y.useDesignable(),s=Y.useCompile(),l=t(i["x-collection-field"]),u=(l!=null&&l.target?e(l==null?void 0:l.target):(f=e(l==null?void 0:l.targetCollection))!=null?f:[]).filter(p=>{if(p!=null&&p.target||p.type==="boolean")return!1;const v=n(p==null?void 0:p.interface);return v==null?void 0:v.titleUsable}).map(p=>{var v;return{value:p==null?void 0:p.name,label:s((v=p==null?void 0:p.uiSchema)==null?void 0:v.title)||(p==null?void 0:p.name)}});return u.length>0&&i["x-component"]==="CollectionField"?H.jsx(Y.SchemaSettingsSelectItem,{title:a("Title field"),options:u,value:(h=(d=r==null?void 0:r.componentProps)==null?void 0:d.fieldNames)==null?void 0:h.label,onChange:p=>{var g,m;const v={"x-uid":i["x-uid"]},y=Oe(ce(ce({},(m=(g=l==null?void 0:l.uiSchema)==null?void 0:g["x-component-props"])==null?void 0:m.fieldNames),r.componentProps.fieldNames),{label:p});i["x-component-props"]=i["x-component-props"]||{},i["x-component-props"].fieldNames=y,v["x-component-props"]=i["x-component-props"],r.componentProps.fieldNames=i["x-component-props"].fieldNames,o.emit("patch",{schema:v}),o.refresh()}},"title-field"):null},m$=()=>{var c,u;const{form:e}=Y.useFormBlockContext(),t=he.useFieldSchema(),n=t["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,{cm:r}=nu(n),i=he.useField(),{dn:a}=Y.useDesignable(),o=r.getCollectionField(t["x-collection-field"]),s=((u=(c=t==null?void 0:t["x-component-props"])==null?void 0:c.params)==null?void 0:u.filter)||{},l=({filter:f})=>{f=Y.removeNullCondition(f),B.set(i.componentProps,"service.params.filter",f),t["x-component-props"]=i.componentProps,a.emit("patch",{schema:{"x-uid":t["x-uid"],"x-component-props":t["x-component-props"]}})};return o?H.jsx(Y.SchemaSettingsDataScope,{form:e,collectionName:o.target,defaultFilter:s,onSubmit:l}):null},b$=()=>{const{getCollectionJoinField:e}=Y.useCollectionManager_deprecated(),{getField:t}=Y.useCollection_deprecated(),{t:n}=mt(),r=he.useFieldSchema(),i=r.name,a=r["x-data-source"]||Y.DEFAULT_DATA_SOURCE_KEY,o=t(i)||e(r["x-collection-field"]),s=i.startsWith("custom."),l=H0(r["x-component"]),c=F6(a,i),u=Y.useIsAssociationField();return H.jsxs(Y.GeneralSchemaDesigner,{disableInitializer:!0,children:[!s&&H.jsxs(H.Fragment,{children:[H.jsx(Y.SchemaSettingsItem,{title:i,children:H.jsxs(d$,{type:"secondary",children:[n("Original field"),": ",c]})}),H.jsx(Y.SchemaSettingsDivider,{})]}),H.jsx(h$,{}),H.jsx(Y.EditDescription,{}),u&&H.jsx(m$,{}),l&&s&&H.jsx(v$,{}),!s&&H.jsx(p$,{}),H.jsx(y$,{}),H.jsx(g$,{}),H.jsx(Y.SchemaSettingsSortingRule,{}),o?H.jsx(Y.SchemaSettingsDivider,{}):null,H.jsx(Y.SchemaSettingsRemove,{confirm:{title:n("Delete field")},breakRemoveOn:{"x-component":"Grid"}},"remove")]})},x$=()=>{const e={},t=Y.useSchemaInitializerItem();return H.jsx(Y.InitializerWithSwitch,Oe(ce({},t),{item:t,schema:e,type:"name"}))},w$=he.connect(e=>{const{content:t}=e,n=he.useField(),r=()=>{n.setValue(!n.value)};return H.jsx(Me.Checkbox,{onClick:r,checked:n.value,children:t})}),v_=K.memo(e=>{const{setField:t,removeField:n,setForm:r}=K.useContext(zr),{getTranslatedTitle:i}=is(),a=K.useRef(null);a.current=K.useContext(Y.VariablesContext);const o=K.useMemo(()=>he.createForm({effects(){const s=l=>{if(l.displayName!=="Field")return null;const{name:c}=l.props||{};return c};he.onFieldInit("*",l=>{s(l)&&l.setValue(null)}),he.onFieldMount("*",l=>$r(this,null,function*(){const c=s(l);c&&(t(c,{title:l.title,operator:l.componentProps["filter-operator"]}),l.title.includes("/")&&(l.title=i(l.title)),u_(l,a.current))})),he.onFieldUnmount("*",l=>{const c=s(l);c&&n(c)})}}),[t,i,n,a]);return K.useEffect(()=>r(o),[o,r]),H.jsx(Y.FormV2,Oe(ce({},e),{form:o}))});v_.displayName="ChartFilterForm";const O$=e=>{const{t}=mt(),{setEnabled:n}=K.useContext(zr);return K.useEffect(()=>{n(!0)},[n]),H.jsx("div",{className:Y.css`
21
21
  .ant-card {
22
22
  box-shadow: none;
23
23
  border: none;
@@ -1,18 +1,18 @@
1
1
  module.exports = {
2
- "@tachybase/client": "0.23.47",
3
- "@tachybase/schema": "0.23.47",
2
+ "@tachybase/client": "0.23.58",
3
+ "@tachybase/schema": "0.23.58",
4
4
  "lodash": "4.17.21",
5
- "@tachybase/cache": "0.23.47",
6
- "@tachybase/server": "0.23.47",
7
- "@tachybase/utils": "0.23.47",
5
+ "@tachybase/cache": "0.23.58",
6
+ "@tachybase/server": "0.23.58",
7
+ "@tachybase/utils": "0.23.58",
8
8
  "react": "18.3.1",
9
9
  "@ant-design/icons": "5.3.7",
10
10
  "ahooks": "3.8.4",
11
11
  "antd": "5.22.5",
12
12
  "dayjs": "1.11.13",
13
- "@tachybase/components": "0.23.47",
13
+ "@tachybase/components": "0.23.58",
14
14
  "react-i18next": "15.2.0",
15
15
  "sequelize": "6.37.5",
16
- "@tachybase/actions": "0.23.47",
17
- "@tachybase/database": "0.23.47"
16
+ "@tachybase/actions": "0.23.58",
17
+ "@tachybase/database": "0.23.58"
18
18
  };
@@ -1 +1 @@
1
- {"name":"fs-extra","version":"11.2.0","description":"fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as recursive mkdir, copy, and remove.","engines":{"node":">=14.14"},"homepage":"https://github.com/jprichardson/node-fs-extra","repository":{"type":"git","url":"https://github.com/jprichardson/node-fs-extra"},"keywords":["fs","file","file system","copy","directory","extra","mkdirp","mkdir","mkdirs","recursive","json","read","write","extra","delete","remove","touch","create","text","output","move","promise"],"author":"JP Richardson <jprichardson@gmail.com>","license":"MIT","dependencies":{"graceful-fs":"^4.2.0","jsonfile":"^6.0.1","universalify":"^2.0.0"},"devDependencies":{"klaw":"^2.1.1","klaw-sync":"^3.0.2","minimist":"^1.1.1","mocha":"^10.1.0","nyc":"^15.0.0","proxyquire":"^2.0.1","read-dir-files":"^0.1.1","standard":"^17.0.0"},"main":"./lib/index.js","exports":{".":"./lib/index.js","./esm":"./lib/esm.mjs"},"files":["lib/","!lib/**/__tests__/"],"scripts":{"lint":"standard","test-find":"find ./lib/**/__tests__ -name *.test.js | xargs mocha","test":"npm run lint && npm run unit && npm run unit-esm","unit":"nyc node test.js","unit-esm":"node test.mjs"},"sideEffects":false,"_lastModified":"2025-02-21T02:29:18.382Z"}
1
+ {"name":"fs-extra","version":"11.2.0","description":"fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as recursive mkdir, copy, and remove.","engines":{"node":">=14.14"},"homepage":"https://github.com/jprichardson/node-fs-extra","repository":{"type":"git","url":"https://github.com/jprichardson/node-fs-extra"},"keywords":["fs","file","file system","copy","directory","extra","mkdirp","mkdir","mkdirs","recursive","json","read","write","extra","delete","remove","touch","create","text","output","move","promise"],"author":"JP Richardson <jprichardson@gmail.com>","license":"MIT","dependencies":{"graceful-fs":"^4.2.0","jsonfile":"^6.0.1","universalify":"^2.0.0"},"devDependencies":{"klaw":"^2.1.1","klaw-sync":"^3.0.2","minimist":"^1.1.1","mocha":"^10.1.0","nyc":"^15.0.0","proxyquire":"^2.0.1","read-dir-files":"^0.1.1","standard":"^17.0.0"},"main":"./lib/index.js","exports":{".":"./lib/index.js","./esm":"./lib/esm.mjs"},"files":["lib/","!lib/**/__tests__/"],"scripts":{"lint":"standard","test-find":"find ./lib/**/__tests__ -name *.test.js | xargs mocha","test":"npm run lint && npm run unit && npm run unit-esm","unit":"nyc node test.js","unit-esm":"node test.mjs"},"sideEffects":false,"_lastModified":"2025-03-06T10:00:58.692Z"}
@@ -1 +1 @@
1
- {"name":"koa-compose","description":"compose Koa middleware","repository":"koajs/compose","version":"4.1.0","keywords":["koa","middleware","compose"],"files":["index.js"],"dependencies":{},"devDependencies":{"codecov":"^3.0.0","jest":"^21.0.0","matcha":"^0.7.0","standard":"^10.0.3"},"scripts":{"bench":"matcha bench/bench.js","lint":"standard --fix .","test":"jest --forceExit --coverage"},"jest":{"testEnvironment":"node"},"license":"MIT","_lastModified":"2025-02-21T02:29:18.031Z"}
1
+ {"name":"koa-compose","description":"compose Koa middleware","repository":"koajs/compose","version":"4.1.0","keywords":["koa","middleware","compose"],"files":["index.js"],"dependencies":{},"devDependencies":{"codecov":"^3.0.0","jest":"^21.0.0","matcha":"^0.7.0","standard":"^10.0.3"},"scripts":{"bench":"matcha bench/bench.js","lint":"standard --fix .","test":"jest --forceExit --coverage"},"jest":{"testEnvironment":"node"},"license":"MIT","_lastModified":"2025-03-06T10:00:58.356Z"}
@@ -201,23 +201,36 @@ const parseFieldAndAssociations = async (ctx, next) => {
201
201
  collection
202
202
  });
203
203
  const { where, include: filterInclude } = filterParser.toSequelizeParams();
204
- const parsedFilterInclude = filterInclude == null ? void 0 : filterInclude.map((item) => {
205
- var _a;
206
- if (((_a = fields.get(item.association)) == null ? void 0 : _a.type) === "belongsToMany") {
207
- item.through = { attributes: [] };
208
- }
209
- return item;
210
- });
204
+ addBelongsToManyThrough(filterInclude, collectionName, ctx.db);
211
205
  ctx.action.params.values = {
212
206
  ...ctx.action.params.values,
213
207
  where,
214
208
  measures: parsedMeasures,
215
209
  dimensions: parsedDimensions,
216
210
  orders: parsedOrders,
217
- include: [...include, ...parsedFilterInclude || []]
211
+ include: [...include, ...filterInclude || []]
218
212
  };
219
213
  await next();
220
214
  };
215
+ function addBelongsToManyThrough(include, collectionName, db) {
216
+ var _a, _b;
217
+ if (!include) {
218
+ return;
219
+ }
220
+ const collection = db.getCollection(collectionName);
221
+ if (!collection) {
222
+ return;
223
+ }
224
+ const fields = collection.fields;
225
+ for (const item of include) {
226
+ if (((_a = fields.get(item.association)) == null ? void 0 : _a.type) === "belongsToMany") {
227
+ item.through = { attributes: [] };
228
+ }
229
+ if (item.include) {
230
+ addBelongsToManyThrough(item.include, (_b = fields.get(item.association)) == null ? void 0 : _b.target, db);
231
+ }
232
+ }
233
+ }
221
234
  const parseVariables = async (ctx, next) => {
222
235
  const { filter } = ctx.action.params.values;
223
236
  if (!filter) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tachybase/plugin-block-charts",
3
3
  "displayName": "Block: charts",
4
- "version": "0.23.47",
4
+ "version": "0.23.58",
5
5
  "description": "Provides data visualization feature, including chart block and chart filter block, support line charts, area charts, bar charts and more than a dozen kinds of charts, you can also extend more chart types.",
6
6
  "keywords": [
7
7
  "Blocks"
@@ -23,17 +23,17 @@
23
23
  "react-error-boundary": "^4.1.2",
24
24
  "react-i18next": "^15.2.0",
25
25
  "sequelize": "^6.37.5",
26
- "@tachybase/components": "0.23.47",
27
- "@tachybase/schema": "0.23.47"
26
+ "@tachybase/components": "0.23.58",
27
+ "@tachybase/schema": "0.23.58"
28
28
  },
29
29
  "peerDependencies": {
30
- "@tachybase/actions": "0.23.47",
31
- "@tachybase/client": "0.23.47",
32
- "@tachybase/database": "0.23.47",
33
- "@tachybase/cache": "0.23.47",
34
- "@tachybase/server": "0.23.47",
35
- "@tachybase/test": "0.23.47",
36
- "@tachybase/utils": "0.23.47"
30
+ "@tachybase/actions": "0.23.58",
31
+ "@tachybase/client": "0.23.58",
32
+ "@tachybase/server": "0.23.58",
33
+ "@tachybase/test": "0.23.58",
34
+ "@tachybase/utils": "0.23.58",
35
+ "@tachybase/database": "0.23.58",
36
+ "@tachybase/cache": "0.23.58"
37
37
  },
38
38
  "description.zh-CN": "提供数据可视化功能,包含图表卡片和图表筛选卡片,支持折线图、面积图、柱状图等十几种图表,你也可以扩展更多图表类型。",
39
39
  "displayName.zh-CN": "卡片:图表",