mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-08 06:59:26 +08:00
Merge branch 'develop' into T-1377
This commit is contained in:
commit
1ff32a987e
10
CHANGELOG.md
10
CHANGELOG.md
@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.4.23](https://github.com/nocobase/nocobase/compare/v1.4.22...v1.4.23) - 2025-01-13
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- **[client]** Fix the issue where fixed actions column are not working properly in tables ([#6048](https://github.com/nocobase/nocobase/pull/6048)) by @zhangzhonghe
|
||||||
|
|
||||||
|
- **[Users]** Disable browser autofill when setting passwords for users in user management ([#6041](https://github.com/nocobase/nocobase/pull/6041)) by @2013xile
|
||||||
|
|
||||||
|
- **[Workflow]** Fix date field based schedule event not triggers after app started ([#6042](https://github.com/nocobase/nocobase/pull/6042)) by @mytharcher
|
||||||
|
|
||||||
## [v1.4.22](https://github.com/nocobase/nocobase/compare/v1.4.21...v1.4.22) - 2025-01-10
|
## [v1.4.22](https://github.com/nocobase/nocobase/compare/v1.4.21...v1.4.22) - 2025-01-10
|
||||||
|
|
||||||
### 🚀 Improvements
|
### 🚀 Improvements
|
||||||
|
@ -5,6 +5,16 @@
|
|||||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||||
并且本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。
|
并且本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。
|
||||||
|
|
||||||
|
## [v1.4.23](https://github.com/nocobase/nocobase/compare/v1.4.22...v1.4.23) - 2025-01-13
|
||||||
|
|
||||||
|
### 🐛 修复
|
||||||
|
|
||||||
|
- **[client]** 修复在表格中固定操作列不生效的问题 ([#6048](https://github.com/nocobase/nocobase/pull/6048)) by @zhangzhonghe
|
||||||
|
|
||||||
|
- **[用户]** 在用户管理中给用户设置密码的时候关闭浏览器自动填充 ([#6041](https://github.com/nocobase/nocobase/pull/6041)) by @2013xile
|
||||||
|
|
||||||
|
- **[工作流]** 修复基于数据表字段的定时任务在启动后不执行的问题 ([#6042](https://github.com/nocobase/nocobase/pull/6042)) by @mytharcher
|
||||||
|
|
||||||
## [v1.4.22](https://github.com/nocobase/nocobase/compare/v1.4.21...v1.4.22) - 2025-01-10
|
## [v1.4.22](https://github.com/nocobase/nocobase/compare/v1.4.21...v1.4.22) - 2025-01-10
|
||||||
|
|
||||||
### 🚀 优化
|
### 🚀 优化
|
||||||
|
@ -228,7 +228,8 @@ export const SubTable: any = observer(
|
|||||||
showIndex
|
showIndex
|
||||||
dragSort={false}
|
dragSort={false}
|
||||||
showDel={
|
showDel={
|
||||||
allowAddnew !== false || allowSelectExistingRecord !== false || allowDisassociation !== false
|
field.editable &&
|
||||||
|
(allowAddnew !== false || allowSelectExistingRecord !== false || allowDisassociation !== false)
|
||||||
? (record) => {
|
? (record) => {
|
||||||
if (!field.editable) {
|
if (!field.editable) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -12,6 +12,7 @@ import { InputNumber as AntdNumber, InputNumberProps as AntdInputNumberProps } f
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { InputNumberReadPrettyProps, ReadPretty } from './ReadPretty';
|
import { InputNumberReadPrettyProps, ReadPretty } from './ReadPretty';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
type ComposedInputNumber = React.ForwardRefExoticComponent<
|
type ComposedInputNumber = React.ForwardRefExoticComponent<
|
||||||
Pick<Partial<any>, string | number | symbol> & React.RefAttributes<unknown>
|
Pick<Partial<any>, string | number | symbol> & React.RefAttributes<unknown>
|
||||||
@ -37,7 +38,14 @@ export const InputNumber: ComposedInputNumber = connect((props: AntdInputNumberP
|
|||||||
onChange(toSafeNumber(v));
|
onChange(toSafeNumber(v));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return <AntdNumber onChange={handleChange} {...others} />;
|
let inputNumberProps = {
|
||||||
|
onChange: handleChange,
|
||||||
|
...others,
|
||||||
|
};
|
||||||
|
if (others['formatStyle']) {
|
||||||
|
inputNumberProps = omit(inputNumberProps, ['addonAfter', 'addonBefore']);
|
||||||
|
}
|
||||||
|
return <AntdNumber {...inputNumberProps} />;
|
||||||
}, mapReadPretty(ReadPretty));
|
}, mapReadPretty(ReadPretty));
|
||||||
|
|
||||||
InputNumber.ReadPretty = ReadPretty;
|
InputNumber.ReadPretty = ReadPretty;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { observer } from '@formily/react';
|
import { observer } from '@formily/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SortableItem, useDesigner } from '../..';
|
import { SortableItem, useDesigner, useSchemaComponentContext } from '../..';
|
||||||
import { useFlag } from '../../../flag-provider/hooks/useFlag';
|
import { useFlag } from '../../../flag-provider/hooks/useFlag';
|
||||||
|
|
||||||
export const designerCss = ({ margin = '-18px -16px', padding = '18px 16px' } = {}) => css`
|
export const designerCss = ({ margin = '-18px -16px', padding = '18px 16px' } = {}) => css`
|
||||||
@ -53,9 +53,15 @@ export const designerCss = ({ margin = '-18px -16px', padding = '18px 16px' } =
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const TableColumnActionBar = observer(
|
export const TableColumnActionBar = observer(
|
||||||
(props) => {
|
(props: any) => {
|
||||||
const Designer = useDesigner();
|
const Designer = useDesigner();
|
||||||
const { isInSubTable } = useFlag() || {};
|
const { isInSubTable } = useFlag() || {};
|
||||||
|
const { designable } = useSchemaComponentContext();
|
||||||
|
|
||||||
|
if (!designable || Designer.isNullComponent) {
|
||||||
|
return props.children;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableItem
|
<SortableItem
|
||||||
className={designerCss({
|
className={designerCss({
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
useCompile,
|
useCompile,
|
||||||
useDesigner,
|
useDesigner,
|
||||||
useFlag,
|
useFlag,
|
||||||
|
useSchemaComponentContext,
|
||||||
} from '../../../';
|
} from '../../../';
|
||||||
import { designerCss } from './Table.Column.ActionBar';
|
import { designerCss } from './Table.Column.ActionBar';
|
||||||
import { isCollectionFieldComponent } from './utils';
|
import { isCollectionFieldComponent } from './utils';
|
||||||
@ -71,6 +72,7 @@ export const TableColumnDecorator = (props) => {
|
|||||||
const Designer = useDesigner();
|
const Designer = useDesigner();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const { fieldSchema, uiSchema, collectionField } = useColumnSchema();
|
const { fieldSchema, uiSchema, collectionField } = useColumnSchema();
|
||||||
|
const { designable } = useSchemaComponentContext();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
const { isInSubTable } = useFlag() || {};
|
const { isInSubTable } = useFlag() || {};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -84,6 +86,10 @@ export const TableColumnDecorator = (props) => {
|
|||||||
field.title = uiSchema?.title;
|
field.title = uiSchema?.title;
|
||||||
}
|
}
|
||||||
}, [uiSchema?.title]);
|
}, [uiSchema?.title]);
|
||||||
|
|
||||||
|
if (!designable || Designer.isNullComponent) {
|
||||||
|
return props.children;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<SortableItem
|
<SortableItem
|
||||||
className={designerCss({
|
className={designerCss({
|
||||||
|
@ -602,17 +602,17 @@ const InternalBodyCellComponent = React.memo<BodyCellComponentProps>((props) =>
|
|||||||
const { record, schema, rowIndex, isSubTable, ...others } = props;
|
const { record, schema, rowIndex, isSubTable, ...others } = props;
|
||||||
const styleRules = schema?.[LinkageRuleDataKeyMap['style']];
|
const styleRules = schema?.[LinkageRuleDataKeyMap['style']];
|
||||||
const [dynamicStyle, setDynamicStyle] = useState({});
|
const [dynamicStyle, setDynamicStyle] = useState({});
|
||||||
const isReadyPrettyMode =
|
const isReadPrettyMode =
|
||||||
!!schema?.properties && Object.values(schema.properties).some((item) => item['x-read-pretty'] === true);
|
!!schema?.properties && Object.values(schema.properties).some((item) => item['x-read-pretty'] === true);
|
||||||
const style = useMemo(() => ({ ...props.style, ...dynamicStyle }), [props.style, dynamicStyle]);
|
const mergedStyle = useMemo(() => ({ ...props.style, ...dynamicStyle }), [props.style, dynamicStyle]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* To improve rendering performance, do not render GetStyleRules component when no style rules are set */}
|
{/* To improve rendering performance, do not render GetStyleRules component when no style rules are set */}
|
||||||
{!_.isEmpty(styleRules) && (
|
{!_.isEmpty(styleRules) && (
|
||||||
<GetStyleRules record={record} schema={schema} onStyleChange={isReadyPrettyMode ? setDynamicStyle : _.noop} />
|
<GetStyleRules record={record} schema={schema} onStyleChange={isReadPrettyMode ? setDynamicStyle : _.noop} />
|
||||||
)}
|
)}
|
||||||
<td {...others} className={classNames(props.className, cellClass)} style={style}>
|
<td {...others} className={classNames(props.className, cellClass)} style={mergedStyle}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</td>
|
</td>
|
||||||
</>
|
</>
|
||||||
@ -750,9 +750,6 @@ const InternalNocoBaseTable = React.memo(
|
|||||||
.ant-table-cell-fix-right {
|
.ant-table-cell-fix-right {
|
||||||
padding: 8px 16px !important;
|
padding: 8px 16px !important;
|
||||||
}
|
}
|
||||||
.ant-table-thead .ant-table-cell {
|
|
||||||
padding: 8px 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ import { ActionContextProvider, SchemaComponentOptions, useActionContext, useDes
|
|||||||
import { PopupVisibleProvider } from '../../antd/page/PagePopups';
|
import { PopupVisibleProvider } from '../../antd/page/PagePopups';
|
||||||
import { usePopupUtils } from '../../antd/page/pagePopupUtils';
|
import { usePopupUtils } from '../../antd/page/pagePopupUtils';
|
||||||
import { popupSchema } from './schema';
|
import { popupSchema } from './schema';
|
||||||
|
|
||||||
import { CollectionProvider, useCollection } from '../../../data-source';
|
import { CollectionProvider, useCollection } from '../../../data-source';
|
||||||
import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField';
|
import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField';
|
||||||
|
import { VariablePopupRecordProvider } from '../../../modules/variable/variablesProvider/VariablePopupRecordProvider';
|
||||||
|
|
||||||
const useInsertSchema = () => {
|
const useInsertSchema = () => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
@ -109,12 +109,14 @@ function withPopupWrapper<T>(WrappedComponent: React.ComponentType<T>) {
|
|||||||
>
|
>
|
||||||
<CollectionProvider name={collection.name}>
|
<CollectionProvider name={collection.name}>
|
||||||
<SchemaComponentOptions>
|
<SchemaComponentOptions>
|
||||||
<NocoBaseRecursionField
|
<VariablePopupRecordProvider>
|
||||||
onlyRenderProperties
|
<NocoBaseRecursionField
|
||||||
basePath={field?.address}
|
onlyRenderProperties
|
||||||
schema={fieldSchema}
|
basePath={field?.address}
|
||||||
filterProperties={filterProperties}
|
schema={fieldSchema}
|
||||||
/>
|
filterProperties={filterProperties}
|
||||||
|
/>
|
||||||
|
</VariablePopupRecordProvider>
|
||||||
</SchemaComponentOptions>
|
</SchemaComponentOptions>
|
||||||
</CollectionProvider>
|
</CollectionProvider>
|
||||||
<a onClick={handleClick}>
|
<a onClick={handleClick}>
|
||||||
|
@ -63,7 +63,7 @@ const RecursionSchemaComponent = memo((props: ISchemaFieldProps & SchemaComponen
|
|||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
refresh: _.noop,
|
refresh: ctx.refresh || _.noop,
|
||||||
}),
|
}),
|
||||||
[ctx, distributed],
|
[ctx, distributed],
|
||||||
);
|
);
|
||||||
|
@ -13,6 +13,7 @@ import { useMemo } from 'react';
|
|||||||
import { SchemaToolbar } from '../../schema-settings';
|
import { SchemaToolbar } from '../../schema-settings';
|
||||||
|
|
||||||
const DefaultSchemaToolbar = () => null;
|
const DefaultSchemaToolbar = () => null;
|
||||||
|
DefaultSchemaToolbar.isNullComponent = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
|
@ -224,6 +224,9 @@ export class WSServer extends EventEmitter {
|
|||||||
|
|
||||||
setClientTag(clientId: string, tagKey: string, tagValue: string) {
|
setClientTag(clientId: string, tagKey: string, tagValue: string) {
|
||||||
const client = this.webSocketClients.get(clientId);
|
const client = this.webSocketClients.get(clientId);
|
||||||
|
if (!client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
client.tags.add(`${tagKey}#${tagValue}`);
|
client.tags.add(`${tagKey}#${tagValue}`);
|
||||||
console.log(`client tags: ${Array.from(client.tags)}`);
|
console.log(`client tags: ${Array.from(client.tags)}`);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,15 @@ describe('xlsx importer', () => {
|
|||||||
workbook: template,
|
workbook: template,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(importer.validate()).resolves.toBeUndefined();
|
let error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await importer.validate();
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -96,6 +96,15 @@ export class PluginClientServer extends Plugin {
|
|||||||
if (process.env['EXPORT_LIMIT']) {
|
if (process.env['EXPORT_LIMIT']) {
|
||||||
info.exportLimit = parseInt(process.env['EXPORT_LIMIT']);
|
info.exportLimit = parseInt(process.env['EXPORT_LIMIT']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env['EXPORT_AUTO_MODE_THRESHOLD']) {
|
||||||
|
info.exportAutoModeThreshold = parseInt(process.env['EXPORT_AUTO_MODE_THRESHOLD']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env['EXPORT_ATTACHMENTS_AUTO_MODE_THRESHOLD']) {
|
||||||
|
info.exportAttachmentsAutoModeThreshold = parseInt(process.env['EXPORT_ATTACHMENTS_AUTO_MODE_THRESHOLD']);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.body = info;
|
ctx.body = info;
|
||||||
await next();
|
await next();
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user