mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 05:29:26 +08:00
Merge branch 'main' into next
This commit is contained in:
commit
42a9d5a6cb
@ -821,6 +821,7 @@
|
|||||||
"File size should not exceed {{size}}.": "文件大小不能超过 {{size}}",
|
"File size should not exceed {{size}}.": "文件大小不能超过 {{size}}",
|
||||||
"File size exceeds the limit": "文件大小超过限制",
|
"File size exceeds the limit": "文件大小超过限制",
|
||||||
"File type is not allowed": "文件类型不允许",
|
"File type is not allowed": "文件类型不允许",
|
||||||
|
"Uploading": "上传中",
|
||||||
"Incomplete uploading files need to be resolved": "未完成上传的文件需要处理",
|
"Incomplete uploading files need to be resolved": "未完成上传的文件需要处理",
|
||||||
"Default title for each record": "用作数据的默认标题",
|
"Default title for each record": "用作数据的默认标题",
|
||||||
"If collection inherits, choose inherited collections as templates": "当前表有继承关系时,可选择继承链路上的表作为模板来源",
|
"If collection inherits, choose inherited collections as templates": "当前表有继承关系时,可选择继承链路上的表作为模板来源",
|
||||||
|
@ -42,6 +42,8 @@ function InputInner(props: NocoBaseInputProps) {
|
|||||||
return <AntdInput {...others} onChange={handleChange} />;
|
return <AntdInput {...others} onChange={handleChange} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputInner.Password = AntdInput.Password;
|
||||||
|
|
||||||
export const Input: ComposedInput = Object.assign(
|
export const Input: ComposedInput = Object.assign(
|
||||||
connect(
|
connect(
|
||||||
InputInner,
|
InputInner,
|
||||||
|
@ -799,7 +799,7 @@ export function useDesignable() {
|
|||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
const c = get(components, component);
|
const c = get(components, component);
|
||||||
return c[LAZY_COMPONENT_KEY] ?? c;
|
return c?.[LAZY_COMPONENT_KEY] ?? c;
|
||||||
},
|
},
|
||||||
[get],
|
[get],
|
||||||
),
|
),
|
||||||
|
@ -15,3 +15,4 @@ export * from './datetime-interface';
|
|||||||
export * from './datetime-no-tz-interface';
|
export * from './datetime-no-tz-interface';
|
||||||
export * from './boolean-interface';
|
export * from './boolean-interface';
|
||||||
export * from './date-interface';
|
export * from './date-interface';
|
||||||
|
export * from './time-interface';
|
||||||
|
26
packages/core/database/src/interfaces/time-interface.ts
Normal file
26
packages/core/database/src/interfaces/time-interface.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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 dayjs from 'dayjs';
|
||||||
|
import { BaseInterface } from './base-interface';
|
||||||
|
|
||||||
|
export class TimeInterface extends BaseInterface {
|
||||||
|
toValue(value: any, ctx?: any) {
|
||||||
|
if (this.validate(value)) {
|
||||||
|
const result = dayjs.utc(value).format('HH:mm:ss');
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
validate(value) {
|
||||||
|
const result = dayjs(value).isValid();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import {
|
|||||||
MultipleSelectInterface,
|
MultipleSelectInterface,
|
||||||
PercentInterface,
|
PercentInterface,
|
||||||
SelectInterface,
|
SelectInterface,
|
||||||
|
TimeInterface,
|
||||||
} from './index';
|
} from './index';
|
||||||
import { ManyToOneInterface } from './many-to-one-interface';
|
import { ManyToOneInterface } from './many-to-one-interface';
|
||||||
import { ManyToManyInterface } from './many-to-many-interface';
|
import { ManyToManyInterface } from './many-to-many-interface';
|
||||||
@ -50,6 +51,7 @@ const interfaces = {
|
|||||||
o2m: OneToManyInterface,
|
o2m: OneToManyInterface,
|
||||||
m2o: ManyToOneInterface,
|
m2o: ManyToOneInterface,
|
||||||
m2m: ManyToManyInterface,
|
m2m: ManyToManyInterface,
|
||||||
|
time: TimeInterface,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function registerInterfaces(db: Database) {
|
export function registerInterfaces(db: Database) {
|
||||||
|
@ -2155,4 +2155,53 @@ describe('xlsx importer', () => {
|
|||||||
|
|
||||||
expect(await Post.repository.count()).toBe(1);
|
expect(await Post.repository.count()).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should import time field successfully', async () => {
|
||||||
|
const TimeCollection = app.db.collection({
|
||||||
|
name: 'time_tests',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'time',
|
||||||
|
name: 'brithtime',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.db.sync();
|
||||||
|
const templateCreator = new TemplateCreator({
|
||||||
|
collection: TimeCollection,
|
||||||
|
explain: 'test',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
dataIndex: ['birthtime'],
|
||||||
|
defaultTitle: '出生时间',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const template = (await templateCreator.run({ returnXLSXWorkbook: true })) as XLSX.WorkBook;
|
||||||
|
|
||||||
|
const worksheet = template.Sheets[template.SheetNames[0]];
|
||||||
|
|
||||||
|
XLSX.utils.sheet_add_aoa(worksheet, [['12:12:12']], {
|
||||||
|
origin: 'A3',
|
||||||
|
});
|
||||||
|
|
||||||
|
const importer = new XlsxImporter({
|
||||||
|
collectionManager: app.mainDataSource.collectionManager,
|
||||||
|
collection: TimeCollection,
|
||||||
|
explain: 'test',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
dataIndex: ['brithtime'],
|
||||||
|
defaultTitle: '出生时间',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
workbook: template,
|
||||||
|
});
|
||||||
|
|
||||||
|
await importer.run();
|
||||||
|
const count = await TimeCollection.repository.count();
|
||||||
|
expect(count).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -36,6 +36,7 @@ async function importXlsxAction(ctx: Context, next: Next) {
|
|||||||
const workbook = XLSX.read(ctx.file.buffer, {
|
const workbook = XLSX.read(ctx.file.buffer, {
|
||||||
type: 'buffer',
|
type: 'buffer',
|
||||||
sheetRows: readLimit,
|
sheetRows: readLimit,
|
||||||
|
cellDates: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const repository = ctx.getCurrentRepository() as Repository;
|
const repository = ctx.getCurrentRepository() as Repository;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { useField, useFieldSchema, useForm } from '@formily/react';
|
import { useField, useFieldSchema, useForm } from '@formily/react';
|
||||||
import { FormLayout } from '@formily/antd-v5';
|
import { FormLayout } from '@formily/antd-v5';
|
||||||
import { Button, Card, ConfigProvider, Descriptions, Space, Spin, Tag } from 'antd';
|
import { Button, Card, ConfigProvider, Descriptions, Space, Spin, Tag } from 'antd';
|
||||||
@ -47,7 +48,6 @@ import WorkflowPlugin, {
|
|||||||
useAvailableUpstreams,
|
useAvailableUpstreams,
|
||||||
useFlowContext,
|
useFlowContext,
|
||||||
EXECUTION_STATUS,
|
EXECUTION_STATUS,
|
||||||
JOB_STATUS,
|
|
||||||
WorkflowTitle,
|
WorkflowTitle,
|
||||||
TASK_STATUS,
|
TASK_STATUS,
|
||||||
usePopupRecordContext,
|
usePopupRecordContext,
|
||||||
@ -56,8 +56,7 @@ import WorkflowPlugin, {
|
|||||||
import { NAMESPACE, useLang } from '../locale';
|
import { NAMESPACE, useLang } from '../locale';
|
||||||
import { FormBlockProvider } from './instruction/FormBlockProvider';
|
import { FormBlockProvider } from './instruction/FormBlockProvider';
|
||||||
import { ManualFormType, manualFormTypes } from './instruction/SchemaConfig';
|
import { ManualFormType, manualFormTypes } from './instruction/SchemaConfig';
|
||||||
import { TaskStatusOptionsMap } from '../common/constants';
|
import { TaskStatusOptionsMap, TASK_STATUS } from '../common/constants';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
function TaskStatusColumn(props) {
|
function TaskStatusColumn(props) {
|
||||||
const recordData = useCollectionRecordData();
|
const recordData = useCollectionRecordData();
|
||||||
@ -654,11 +653,11 @@ function TaskItem() {
|
|||||||
|
|
||||||
const StatusFilterMap = {
|
const StatusFilterMap = {
|
||||||
pending: {
|
pending: {
|
||||||
status: JOB_STATUS.PENDING,
|
status: TASK_STATUS.PENDING,
|
||||||
'execution.status': EXECUTION_STATUS.STARTED,
|
'execution.status': EXECUTION_STATUS.STARTED,
|
||||||
},
|
},
|
||||||
completed: {
|
completed: {
|
||||||
status: JOB_STATUS.RESOLVED,
|
status: [TASK_STATUS.RESOLVED, TASK_STATUS.REJECTED],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export const MANUAL_TASK_TYPE = 'manual';
|
|||||||
export const TASK_STATUS = {
|
export const TASK_STATUS = {
|
||||||
PENDING: 0,
|
PENDING: 0,
|
||||||
RESOLVED: 1,
|
RESOLVED: 1,
|
||||||
REJECTED: -1,
|
REJECTED: -5,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TaskStatusOptions = [
|
export const TaskStatusOptions = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user