diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5506e2ae37..d7c6ed9c8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -152,6 +152,7 @@ jobs: uses: docker/build-push-action@v3 with: context: ./docker/nocobase + file: ./docker/nocobase/Dockerfile platforms: linux/amd64,linux/arm64 push: true tags: nocobase/nocobase:main,nocobase/nocobase:latest,${{ steps.meta.outputs.tags }},${{ secrets.ALI_DOCKER_PUBLIC_REGISTRY }}/nocobase/nocobase:main,${{ secrets.ALI_DOCKER_PUBLIC_REGISTRY }}/nocobase/nocobase:latest,${{ secrets.ALI_DOCKER_PUBLIC_REGISTRY }}/${{ steps.meta.outputs.tags }} @@ -160,6 +161,7 @@ jobs: uses: docker/build-push-action@v3 with: context: ./docker/nocobase + file: ./docker/nocobase/Dockerfile.next platforms: linux/amd64,linux/arm64 push: true tags: nocobase/nocobase:next,${{ steps.meta.outputs.tags }},${{ secrets.ALI_DOCKER_PUBLIC_REGISTRY }}/nocobase/nocobase:next,${{ secrets.ALI_DOCKER_PUBLIC_REGISTRY }}/${{ steps.meta.outputs.tags }} diff --git a/docker/nocobase/Dockerfile b/docker/nocobase/Dockerfile index db96d07fa9..3c78b4ba8e 100644 --- a/docker/nocobase/Dockerfile +++ b/docker/nocobase/Dockerfile @@ -27,7 +27,7 @@ RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ esac \ && set -ex \ # libatomic1 for arm - && apt-get update && apt-get install -y nginx + && apt-get update && apt-get install -y nginx libaio1 RUN rm -rf /etc/nginx/sites-enabled/default COPY --from=builder /app/nocobase.tar.gz /app/nocobase.tar.gz diff --git a/docker/nocobase/Dockerfile.next b/docker/nocobase/Dockerfile.next new file mode 100644 index 0000000000..6f13b09dad --- /dev/null +++ b/docker/nocobase/Dockerfile.next @@ -0,0 +1,43 @@ +FROM node:18-bullseye-slim as builder + +WORKDIR /app + +RUN cd /app \ + && yarn config set network-timeout 600000 -g \ + && npx -y create-nocobase-app@next my-nocobase-app -a -e APP_ENV=production \ + && cd /app/my-nocobase-app \ + && yarn install --production + +RUN cd /app \ + && rm -rf nocobase.tar.gz \ + && tar -zcf ./nocobase.tar.gz -C /app/my-nocobase-app . + +FROM node:18-bullseye-slim + +# COPY ./sources.list /etc/apt/sources.list +RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ + && case "${dpkgArch##*-}" in \ + amd64) ARCH='x64';; \ + ppc64el) ARCH='ppc64le';; \ + s390x) ARCH='s390x';; \ + arm64) ARCH='arm64';; \ + armhf) ARCH='armv7l';; \ + i386) ARCH='x86';; \ + *) echo "unsupported architecture"; exit 1 ;; \ + esac \ + && set -ex \ + # libatomic1 for arm + && apt-get update && apt-get install -y nginx libaio1 + +RUN rm -rf /etc/nginx/sites-enabled/default +COPY --from=builder /app/nocobase.tar.gz /app/nocobase.tar.gz + +WORKDIR /app/nocobase + +COPY docker-entrypoint.sh /app/ +# COPY docker-entrypoint.sh /usr/local/bin/ +# ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 80/tcp + +CMD ["/app/docker-entrypoint.sh"] diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/subTable.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/subTable.test.ts new file mode 100644 index 0000000000..d40d6003ae --- /dev/null +++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/subTable.test.ts @@ -0,0 +1,65 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { expect, test } from '@nocobase/test/e2e'; +import { subTableDefaultValue } from './templatesOfBug'; + +test.describe('subTable', () => { + test('defaultValue', async ({ page, mockPage }) => { + // Default values have been set as: + // staff: {{ $user }} + // timeStart: 2024-11-07 + // timeEnd: {{ $iteration.timeStart }} + await mockPage(subTableDefaultValue).goto(); + + // 1. Click "Add new" to add a row, default values should display correctly + await page.getByRole('button', { name: 'Add new' }).click(); + await expect(page.getByTestId('select-object-single').getByText('Super Admin')).toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').getByPlaceholder('Select date'), + ).toHaveValue('2024-11-07'); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').getByPlaceholder('Select date'), + ).toHaveValue('2024-11-07'); + + // 2. Click "Add new" again to add another row, default values should display correctly + await page.getByRole('button', { name: 'Add new' }).click(); + await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(1)).toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(1).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-07'); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(1).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-07'); + + // 3. After modifying timeStart in both first and second rows, their corresponding timeEnd should stay synchronized + await page.getByPlaceholder('Select date').first().click(); + await page.getByRole('cell', { name: '8', exact: true }).click(); + await page.getByPlaceholder('Select date').nth(2).click(); + await page.getByRole('cell', { name: '8', exact: true }).click(); + + // First row + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(0).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-08'); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(0).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-08'); + await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(0)).toBeVisible(); + + // Second row + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(1).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-08'); + await expect( + page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(1).getByPlaceholder('Select date'), + ).toHaveValue('2024-11-08'); + await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(1)).toBeVisible(); + }); +}); diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts index 72ba397b28..2216aa5c42 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts @@ -7926,3 +7926,318 @@ export const differentURL_DifferentPopupContent = { 'x-index': 1, }, }; +export const subTableDefaultValue = { + collections: [ + { + name: 'people', + fields: [ + { + name: 'group', + interface: 'o2m', + target: 'group', + targetKey: 'id', + }, + ], + }, + { + name: 'group', + fields: [ + { + name: 'staff', + interface: 'm2o', + target: 'users', + targetKey: 'id', + }, + { + name: 'timeStart', + interface: 'datetime', + }, + { + name: 'timeEnd', + interface: 'datetime', + }, + ], + }, + ], + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + gxs8yrx2r0h: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + '823g8sd0un5': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.3.46-beta', + properties: { + s8gra6scztq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.3.46-beta', + properties: { + k0hmoift98n: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-acl-action': 'people:create', + 'x-decorator': 'FormBlockProvider', + 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps', + 'x-decorator-props': { + dataSource: 'main', + collection: 'people', + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:createForm', + 'x-component': 'CardItem', + 'x-app-version': '1.3.46-beta', + properties: { + qj7mcan7daw: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'FormV2', + 'x-use-component-props': 'useCreateFormBlockProps', + 'x-app-version': '1.3.46-beta', + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'form:configureFields', + 'x-app-version': '1.3.46-beta', + properties: { + zx4nzvdjpzq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.3.46-beta', + properties: { + osnr82axoai: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.3.46-beta', + properties: { + group: { + 'x-uid': '001ix5hsr0t', + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'people.group', + 'x-component-props': { + fieldNames: { + label: 'id', + value: 'id', + }, + mode: 'SubTable', + }, + 'x-app-version': '1.3.46-beta', + default: null, + properties: { + '2go92pz3q7s': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'AssociationField.SubTable', + 'x-initializer': 'table:configureColumns', + 'x-initializer-props': { + action: false, + }, + 'x-index': 1, + 'x-app-version': '1.3.46-beta', + properties: { + '9e59ms847h0': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-toolbar': 'TableColumnSchemaToolbar', + 'x-settings': 'fieldSettings:TableColumn', + 'x-component': 'TableV2.Column', + 'x-app-version': '1.3.46-beta', + properties: { + staff: { + 'x-uid': 'qfin4x5otua', + _isJSONSchemaObject: true, + version: '2.0', + 'x-collection-field': 'group.staff', + 'x-component': 'CollectionField', + 'x-component-props': { + fieldNames: { + label: 'nickname', + value: 'id', + }, + ellipsis: true, + size: 'small', + }, + 'x-decorator': 'FormItem', + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + 'x-app-version': '1.3.46-beta', + default: '{{$user}}', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'gg09b3sv8p7', + 'x-async': false, + 'x-index': 1, + }, + kd80mzx281w: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-toolbar': 'TableColumnSchemaToolbar', + 'x-settings': 'fieldSettings:TableColumn', + 'x-component': 'TableV2.Column', + 'x-app-version': '1.3.46-beta', + properties: { + timeStart: { + 'x-uid': 'sm3t7czuvu1', + _isJSONSchemaObject: true, + version: '2.0', + 'x-collection-field': 'group.timeStart', + 'x-component': 'CollectionField', + 'x-component-props': {}, + 'x-decorator': 'FormItem', + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + 'x-app-version': '1.3.46-beta', + default: '2024-11-06T16:00:00.000Z', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ojxw1dbkoi0', + 'x-async': false, + 'x-index': 2, + }, + st8bezxhvax: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-toolbar': 'TableColumnSchemaToolbar', + 'x-settings': 'fieldSettings:TableColumn', + 'x-component': 'TableV2.Column', + 'x-app-version': '1.3.46-beta', + properties: { + timeEnd: { + 'x-uid': '0nks9kfq38u', + _isJSONSchemaObject: true, + version: '2.0', + 'x-collection-field': 'group.timeEnd', + 'x-component': 'CollectionField', + 'x-component-props': {}, + 'x-decorator': 'FormItem', + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + 'x-app-version': '1.3.46-beta', + default: '{{$iteration.timeStart}}', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8lynj1uxlbv', + 'x-async': false, + 'x-index': 3, + }, + }, + 'x-uid': 'bsd9l4pl5by', + 'x-async': false, + }, + }, + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 't9bhhahpuln', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'm94ti0kcqqh', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9po3njajeii', + 'x-async': false, + 'x-index': 1, + }, + gr2fjadfkef: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'createForm:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + layout: 'one-column', + }, + 'x-app-version': '1.3.46-beta', + 'x-uid': 'v5zhsmloels', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'o9fcw2oo6vi', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '7361xvr7amv', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'an5bhgxdio8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0hixaaou1xh', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'nfot2l93mkp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '3lfdt8s5cay', + 'x-async': true, + 'x-index': 1, + }, +}; diff --git a/packages/core/client/src/schema-component/antd/form-item/__tests__/hooks/useSpecialCase.test.ts b/packages/core/client/src/schema-component/antd/form-item/__tests__/hooks/useSpecialCase.test.ts index 4c741aef8e..0020c1e56f 100644 --- a/packages/core/client/src/schema-component/antd/form-item/__tests__/hooks/useSpecialCase.test.ts +++ b/packages/core/client/src/schema-component/antd/form-item/__tests__/hooks/useSpecialCase.test.ts @@ -72,7 +72,7 @@ describe('isSpecialCaseField', () => { type: 'hasOne', }; const fieldSchema: any = { - default: '', + default: '{{ $context }}', }; const getCollectionField = vi.fn().mockReturnValue(null); @@ -92,7 +92,7 @@ describe('isSpecialCaseField', () => { }, }; const fieldSchema: any = { - default: '', + default: '{{ $context }}', parent: parentFieldSchema, }; @@ -116,7 +116,7 @@ describe('isSpecialCaseField', () => { }, }; const fieldSchema: any = { - default: '', + default: '{{ $context }}', parent: parentFieldSchema, }; const getCollectionField = vi.fn().mockReturnValue({ diff --git a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts index 703b2a43b8..10c5a79152 100644 --- a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts +++ b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts @@ -16,8 +16,9 @@ import { useCallback, useEffect } from 'react'; import { useRecordIndex } from '../../../../../src/record-provider'; import { useOperators } from '../../../../block-provider/CollectOperators'; import { useFormBlockContext } from '../../../../block-provider/FormBlockProvider'; -import { InheritanceCollectionMixin, useCollection_deprecated } from '../../../../collection-manager'; +import { InheritanceCollectionMixin } from '../../../../collection-manager'; import { useCollectionRecord } from '../../../../data-source/collection-record/CollectionRecordProvider'; +import { useCollection } from '../../../../data-source/collection/CollectionProvider'; import { DataSourceManager } from '../../../../data-source/data-source/DataSourceManager'; import { useDataSourceManager } from '../../../../data-source/data-source/DataSourceManagerProvider'; import { useFlag } from '../../../../flag-provider'; @@ -40,7 +41,7 @@ const useParseDefaultValue = () => { const record = useCollectionRecord(); const { isInAssignFieldValues, isInSetDefaultValueDialog, isInFormDataTemplate, isInSubTable, isInSubForm } = useFlag() || {}; - const { getField } = useCollection_deprecated(); + const collection = useCollection(); const { isSpecialCase, setDefaultValue } = useSpecialCase(); const index = useRecordIndex(); const { type, form } = useFormBlockContext(); @@ -92,7 +93,7 @@ const useParseDefaultValue = () => { } field.loading = true; - const collectionField = !fieldSchema.name.toString().includes('.') && getField(fieldSchema.name); + const collectionField = !fieldSchema.name.toString().includes('.') && collection?.getField(fieldSchema.name); if (process.env.NODE_ENV !== 'production') { if (!collectionField) { @@ -191,7 +192,7 @@ const useParseDefaultValue = () => { // 解决子表格(或子表单)中新增一行数据时,默认值不生效的问题 field.setValue(fieldSchema.default); } - }, [fieldSchema.default, localVariables, type, getOperator, dm]); + }, [fieldSchema.default, localVariables, type, getOperator, dm, collection]); }; export default useParseDefaultValue; diff --git a/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts b/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts index 4cff8dd9ac..1327f0d2f1 100644 --- a/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts +++ b/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts @@ -92,8 +92,8 @@ export function isSpecialCaseField({ fieldSchema: Schema; getCollectionField: (name: string) => CollectionFieldOptions_deprecated; }) { - // 排除掉“当前对象”这个变量 - if (fieldSchema.default.includes('$iteration')) { + // 只针对“表格选中记录”变量有效 + if (!fieldSchema.default || !fieldSchema.default.includes('$context')) { return false; } diff --git a/release.sh b/release.sh index a15da199ec..b3b6bf45e5 100755 --- a/release.sh +++ b/release.sh @@ -3,8 +3,7 @@ IFS='.-' read -r major minor patch label pre <<< "$current_version" if [ "$label" == 'beta' ]; then if [ "$1" == '--is-feat' ]; then - new_minor=$((minor + 1)) - new_version="$major.$new_minor.0-beta" + new_version="$major.$minor.0-beta" echo $new_version; else new_patch=$((patch + 1))