mirror of
https://github.com/nocobase/nocobase
synced 2024-11-14 16:34:14 +00:00
fix(plugin-file-manager): fix upload and destroy file record within an association (#5493)
Some checks are pending
Build docker image / build-and-push (push) Waiting to run
Build pro image / build-and-push (push) Waiting to run
Deploy client docs / Build (push) Waiting to run
E2E / Build (push) Waiting to run
E2E / Core and plugins (push) Blocked by required conditions
E2E / plugin-workflow (push) Blocked by required conditions
E2E / plugin-workflow-approval (push) Blocked by required conditions
E2E / plugin-data-source-main (push) Blocked by required conditions
E2E / Comment on PR (push) Blocked by required conditions
NocoBase backend test / sqlite-test (20, false) (push) Waiting to run
NocoBase backend test / sqlite-test (20, true) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, nocobase, false) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, nocobase, true) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, public, false) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, public, true) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, nocobase, false) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, nocobase, true) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, public, false) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, public, true) (push) Waiting to run
NocoBase backend test / mysql-test (20, false) (push) Waiting to run
NocoBase backend test / mysql-test (20, true) (push) Waiting to run
NocoBase backend test / mariadb-test (20, false) (push) Waiting to run
NocoBase backend test / mariadb-test (20, true) (push) Waiting to run
NocoBase frontEnd test / frontend-test (18) (push) Waiting to run
Test on Windows / build (push) Waiting to run
Some checks are pending
Build docker image / build-and-push (push) Waiting to run
Build pro image / build-and-push (push) Waiting to run
Deploy client docs / Build (push) Waiting to run
E2E / Build (push) Waiting to run
E2E / Core and plugins (push) Blocked by required conditions
E2E / plugin-workflow (push) Blocked by required conditions
E2E / plugin-workflow-approval (push) Blocked by required conditions
E2E / plugin-data-source-main (push) Blocked by required conditions
E2E / Comment on PR (push) Blocked by required conditions
NocoBase backend test / sqlite-test (20, false) (push) Waiting to run
NocoBase backend test / sqlite-test (20, true) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, nocobase, false) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, nocobase, true) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, public, false) (push) Waiting to run
NocoBase backend test / postgres-test (public, 20, public, true) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, nocobase, false) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, nocobase, true) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, public, false) (push) Waiting to run
NocoBase backend test / postgres-test (user_schema, 20, public, true) (push) Waiting to run
NocoBase backend test / mysql-test (20, false) (push) Waiting to run
NocoBase backend test / mysql-test (20, true) (push) Waiting to run
NocoBase backend test / mariadb-test (20, false) (push) Waiting to run
NocoBase backend test / mariadb-test (20, true) (push) Waiting to run
NocoBase frontEnd test / frontend-test (18) (push) Waiting to run
Test on Windows / build (push) Waiting to run
This commit is contained in:
parent
e0c7e765dd
commit
af600e3e4f
@ -10,3 +10,4 @@
|
||||
export * from './data-blocks/details-multi';
|
||||
export * from './data-blocks/details-single';
|
||||
export * from './useActionAvailable';
|
||||
export * from './useSourceId';
|
||||
|
@ -12,26 +12,29 @@ import {
|
||||
useActionContext,
|
||||
useBlockRequestContext,
|
||||
useCollection,
|
||||
useDataBlockProps,
|
||||
useDataBlockRequest,
|
||||
useSourceId,
|
||||
useSourceIdFromParentRecord,
|
||||
} from '@nocobase/client';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { useStorageRules } from './useStorageRules';
|
||||
|
||||
export const useUploadFiles = () => {
|
||||
const { service } = useBlockRequestContext();
|
||||
const service = useDataBlockRequest();
|
||||
const { association } = useDataBlockProps();
|
||||
const { setVisible } = useActionContext();
|
||||
const { props: blockProps } = useBlockRequestContext();
|
||||
const collection = useCollection();
|
||||
const sourceId = useSourceIdFromParentRecord();
|
||||
const sourceId = useSourceId();
|
||||
const rules = useStorageRules(collection?.getOption('storage'));
|
||||
const action = useMemo(() => {
|
||||
let action = `${collection.name}:create`;
|
||||
if (blockProps?.association) {
|
||||
const [s, t] = blockProps.association.split('.');
|
||||
if (association) {
|
||||
const [s, t] = association.split('.');
|
||||
action = `${s}/${sourceId}/${t}:create`;
|
||||
}
|
||||
return action;
|
||||
}, [collection.name, blockProps?.association, sourceId]);
|
||||
}, [collection.name, association, sourceId]);
|
||||
const { setSelectedRows } = useContext(RecordPickerContext) || {};
|
||||
const uploadingFiles = {};
|
||||
|
||||
|
@ -457,6 +457,26 @@ describe('action', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('association', () => {
|
||||
it('has-many', async () => {
|
||||
const UserRepo = db.getRepository('users');
|
||||
const user = await UserRepo.findOne();
|
||||
const FileRepo = db.getRepository('users.files', user.id);
|
||||
const f1s = await FileRepo.count();
|
||||
expect(f1s).toBe(0);
|
||||
const { body } = await agent.resource('users.files', 1).create({
|
||||
[FILE_FIELD_NAME]: path.resolve(__dirname, './files/text.txt'),
|
||||
});
|
||||
const f2s = await FileRepo.find({});
|
||||
expect(f2s.length).toBe(1);
|
||||
expect(f2s[0].userId).toBe(user.id);
|
||||
|
||||
await agent.resource('users.files', 1).destroy({ filterByTk: body.data.id });
|
||||
const f3s = await FileRepo.count();
|
||||
expect(f3s).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('storage actions', () => {
|
||||
describe('getRules', () => {
|
||||
it('get rules without key as default storage', async () => {
|
||||
|
@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'files',
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
template: 'file',
|
||||
fields: [
|
||||
{
|
||||
interface: 'input',
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("Title")}}`,
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
// '系统文件名(含扩展名)',
|
||||
{
|
||||
interface: 'input',
|
||||
type: 'string',
|
||||
name: 'filename',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("File name")}}`,
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// '扩展名(含“.”)',
|
||||
{
|
||||
interface: 'input',
|
||||
type: 'string',
|
||||
name: 'extname',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("Extension name")}}`,
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// '文件体积(字节)',
|
||||
{
|
||||
interface: 'integer',
|
||||
type: 'integer',
|
||||
name: 'size',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'number',
|
||||
title: `{{t("Size")}}`,
|
||||
'x-component': 'InputNumber',
|
||||
'x-read-pretty': true,
|
||||
'x-component-props': {
|
||||
stringMode: true,
|
||||
step: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
interface: 'input',
|
||||
type: 'string',
|
||||
name: 'mimetype',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("MIME type")}}`,
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// '相对路径(含“/”前缀)',
|
||||
{
|
||||
interface: 'input',
|
||||
type: 'string',
|
||||
name: 'path',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("Path")}}`,
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// 文件的可访问地址
|
||||
{
|
||||
interface: 'url',
|
||||
type: 'string',
|
||||
name: 'url',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("URL")}}`,
|
||||
'x-component': 'Input.URL',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// 用于预览
|
||||
{
|
||||
interface: 'url',
|
||||
type: 'string',
|
||||
name: 'preview',
|
||||
field: 'url', // 直接引用 url 字段
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("Preview")}}`,
|
||||
'x-component': 'Preview',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
{
|
||||
comment: '存储引擎',
|
||||
type: 'belongsTo',
|
||||
name: 'storage',
|
||||
target: 'storages',
|
||||
foreignKey: 'storageId',
|
||||
deletable: false,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: `{{t("Storage")}}`,
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
// '其他文件信息(如图片的宽高)',
|
||||
{
|
||||
type: 'jsonb',
|
||||
name: 'meta',
|
||||
deletable: false,
|
||||
defaultValue: {},
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
},
|
||||
],
|
||||
};
|
@ -21,6 +21,10 @@ export default {
|
||||
name: 'avatar',
|
||||
target: 'attachments',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'files',
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'pubkeys',
|
@ -30,7 +30,7 @@ export async function getApp(options = {}): Promise<MockServer> {
|
||||
});
|
||||
|
||||
await app.db.import({
|
||||
directory: path.resolve(__dirname, './tables'),
|
||||
directory: path.resolve(__dirname, './collections'),
|
||||
});
|
||||
|
||||
await app.db.sync();
|
||||
|
@ -131,14 +131,14 @@ export async function createMiddleware(ctx: Context, next: Next) {
|
||||
}
|
||||
|
||||
export async function destroyMiddleware(ctx: Context, next: Next) {
|
||||
const { resourceName, actionName } = ctx.action;
|
||||
const { resourceName, actionName, sourceId } = ctx.action;
|
||||
const collection = ctx.db.getCollection(resourceName);
|
||||
|
||||
if (collection?.options?.template !== 'file' || actionName !== 'destroy') {
|
||||
return next();
|
||||
}
|
||||
|
||||
const repository = ctx.db.getRepository(resourceName);
|
||||
const repository = ctx.db.getRepository(resourceName, sourceId);
|
||||
|
||||
const { filterByTk, filter } = ctx.action.params;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user