mirror of
https://github.com/nocobase/nocobase.git
synced 2026-09-21 05:44:51 +08:00
fix(plugin-file-manager): hide attachment from v2 add field (#10018)
* fix(plugin-file-manager): hide attachment from v2 add field * chore: rerun ci for attachment v2 PR
This commit is contained in:
@@ -115,6 +115,7 @@ export abstract class CollectionFieldInterface {
|
||||
titleUsable?: boolean;
|
||||
usePathOptions?(field: any): any;
|
||||
hidden?: boolean;
|
||||
creatable?: boolean;
|
||||
|
||||
addComponentOption(componentOption: CollectionFieldInterfaceComponentOption) {
|
||||
if (!this.componentOptions) {
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ interface FieldInterfaceLike {
|
||||
title?: ReactNode;
|
||||
group?: string;
|
||||
order?: number;
|
||||
creatable?: boolean;
|
||||
isAssociation?: boolean;
|
||||
supportDataSourceType?: string[];
|
||||
notSupportDataSourceType?: string[];
|
||||
|
||||
+30
-27
@@ -101,23 +101,23 @@ function filterFieldInterfacesByTemplate(
|
||||
fieldInterfaces: FieldInterfaceOption[],
|
||||
collection: Record<string, any>,
|
||||
ctx: any,
|
||||
mode: 'create' | 'edit',
|
||||
databaseDialect?: string,
|
||||
) {
|
||||
if (mode !== 'create') {
|
||||
return fieldInterfaces;
|
||||
}
|
||||
const plugin = ctx.app.pm.get(PluginDataSourceManagerClientV2);
|
||||
const template = plugin?.getCollectionTemplate?.(collection.template || 'general');
|
||||
const templateFieldInterfaces = filterFieldInterfacesByCollectionTemplate<FieldInterfaceOption>(
|
||||
fieldInterfaces,
|
||||
template,
|
||||
collection,
|
||||
{
|
||||
databaseDialect,
|
||||
},
|
||||
);
|
||||
return filterCreateFieldInterfacesByCollectionTemplate(templateFieldInterfaces, template);
|
||||
return filterFieldInterfacesByCollectionTemplate<FieldInterfaceOption>(fieldInterfaces, template, collection, {
|
||||
databaseDialect,
|
||||
});
|
||||
}
|
||||
|
||||
function filterCreateFieldInterfacesByTemplate(
|
||||
fieldInterfaces: FieldInterfaceOption[],
|
||||
collection: Record<string, any>,
|
||||
ctx: any,
|
||||
) {
|
||||
const plugin = ctx.app.pm.get(PluginDataSourceManagerClientV2);
|
||||
const template = plugin?.getCollectionTemplate?.(collection.template || 'general');
|
||||
return filterCreateFieldInterfacesByCollectionTemplate(fieldInterfaces, template);
|
||||
}
|
||||
|
||||
function normalizeListResponse(response: any) {
|
||||
@@ -1712,19 +1712,22 @@ export function FieldForm(props: FieldFormProps) {
|
||||
const lastInitialValuesKeyRef = useRef<string>();
|
||||
const dataSource = ctx.dataSourceManager.getDataSource(props.dataSourceKey);
|
||||
const databaseDialect = getAppInfoDatabaseDialect(appInfo);
|
||||
const fieldInterfaces = useMemo(
|
||||
const fieldInterfaces = useMemo(() => {
|
||||
const allFieldInterfaces = getFieldInterfaces(ctx, dataSource?.options?.type);
|
||||
if (props.mode !== 'create') {
|
||||
return allFieldInterfaces;
|
||||
}
|
||||
return filterFieldInterfacesByTemplate(allFieldInterfaces, props.collection, ctx, databaseDialect);
|
||||
}, [databaseDialect, ctx, dataSource?.options?.type, props.collection, props.mode]);
|
||||
const creatableFieldInterfaces = useMemo(
|
||||
() =>
|
||||
filterFieldInterfacesByTemplate(
|
||||
getFieldInterfaces(ctx, dataSource?.options?.type),
|
||||
props.collection,
|
||||
ctx,
|
||||
props.mode,
|
||||
databaseDialect,
|
||||
),
|
||||
[databaseDialect, ctx, dataSource?.options?.type, props.collection, props.mode],
|
||||
props.mode === 'create'
|
||||
? filterCreateFieldInterfacesByTemplate(fieldInterfaces, props.collection, ctx)
|
||||
: fieldInterfaces,
|
||||
[ctx, fieldInterfaces, props.collection, props.mode],
|
||||
);
|
||||
const [interfaceName, setInterfaceName] = useState(
|
||||
props.field?.interface || props.interfaceName || fieldInterfaces[0]?.name,
|
||||
props.field?.interface || props.interfaceName || creatableFieldInterfaces[0]?.name,
|
||||
);
|
||||
const fieldInterface = useMemo(
|
||||
() => fieldInterfaces.find((item) => item.name === interfaceName),
|
||||
@@ -1910,10 +1913,10 @@ export function FieldForm(props: FieldFormProps) {
|
||||
setInterfaceName(props.interfaceName);
|
||||
return;
|
||||
}
|
||||
if (!interfaceName && fieldInterfaces[0]?.name) {
|
||||
setInterfaceName(fieldInterfaces[0].name);
|
||||
if (!interfaceName && creatableFieldInterfaces[0]?.name) {
|
||||
setInterfaceName(creatableFieldInterfaces[0].name);
|
||||
}
|
||||
}, [fieldInterfaces, interfaceName, props.interfaceName]);
|
||||
}, [creatableFieldInterfaces, interfaceName, props.interfaceName]);
|
||||
|
||||
const handleInterfaceChange = useCallback(
|
||||
(nextInterface: string) => {
|
||||
@@ -2072,7 +2075,7 @@ export function FieldForm(props: FieldFormProps) {
|
||||
{!props.interfaceName && props.mode === 'create' ? (
|
||||
<Form.Item name="interface" label={t('Field interface')} rules={[{ required: true }]}>
|
||||
<Select
|
||||
options={fieldInterfaces.map((item) => ({
|
||||
options={creatableFieldInterfaces.map((item) => ({
|
||||
value: item.name,
|
||||
label: compileLegacyTemplate(item.title || item.name, t),
|
||||
}))}
|
||||
|
||||
+1
@@ -54,6 +54,7 @@ type FieldInterfaceOption = {
|
||||
name: string;
|
||||
title?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
creatable?: boolean;
|
||||
group?: string;
|
||||
order?: number;
|
||||
hidden?: boolean;
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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 { describe, expect, it } from 'vitest';
|
||||
import { filterCreateFieldInterfacesByCollectionTemplate } from '../collectionTemplateFieldInterfaces';
|
||||
|
||||
describe('filterCreateFieldInterfacesByCollectionTemplate', () => {
|
||||
it('excludes field interfaces marked as not creatable', () => {
|
||||
const fieldInterfaces = [{ name: 'input' }, { name: 'attachment', creatable: false }];
|
||||
|
||||
expect(
|
||||
filterCreateFieldInterfacesByCollectionTemplate(fieldInterfaces, undefined).map((item) => item.name),
|
||||
).toEqual(['input']);
|
||||
});
|
||||
|
||||
it('does not allow template includes to restore not creatable field interfaces', () => {
|
||||
const fieldInterfaces = [{ name: 'input' }, { name: 'attachment', creatable: false }];
|
||||
const template = {
|
||||
fieldInterfaces: {
|
||||
create: {
|
||||
include: ['attachment'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(filterCreateFieldInterfacesByCollectionTemplate(fieldInterfaces, template).map((item) => item.name)).toEqual(
|
||||
[],
|
||||
);
|
||||
});
|
||||
});
|
||||
+4
@@ -21,6 +21,7 @@ type FieldInterfacePolicy = {
|
||||
};
|
||||
|
||||
type FieldInterfaceLike = {
|
||||
creatable?: boolean;
|
||||
group?: string;
|
||||
name: string;
|
||||
};
|
||||
@@ -74,6 +75,9 @@ export function filterCreateFieldInterfacesByCollectionTemplate<T extends FieldI
|
||||
const hasIncludes = Array.isArray(include) && include.length > 0;
|
||||
|
||||
return fieldInterfaces.filter((fieldInterface) => {
|
||||
if (fieldInterface.creatable === false) {
|
||||
return false;
|
||||
}
|
||||
if (hasIncludes) {
|
||||
return isIncludedFieldInterface(include, fieldInterface.name);
|
||||
}
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ describe('AttachmentFieldInterface', () => {
|
||||
|
||||
expect(fieldInterface).toBeInstanceOf(AttachmentFieldInterface);
|
||||
expect(fieldInterface.group).toBe('media');
|
||||
expect(fieldInterface.creatable).toBe(false);
|
||||
expect(fieldInterface.default).toMatchObject({
|
||||
interface: 'attachment',
|
||||
type: 'belongsToMany',
|
||||
|
||||
@@ -17,6 +17,7 @@ export class AttachmentFieldInterface extends CollectionFieldInterface {
|
||||
group = 'media';
|
||||
title = tExpr('Attachment');
|
||||
isAssociation = true;
|
||||
creatable = false;
|
||||
default = {
|
||||
interface: 'attachment',
|
||||
type: 'belongsToMany',
|
||||
|
||||
Reference in New Issue
Block a user