mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 08:55:33 +00:00
Merge branch 'next' into mobile-subpage
This commit is contained in:
commit
9d6d18ad8a
18
CHANGELOG.md
18
CHANGELOG.md
@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
## [v1.2.25-alpha](https://github.com/nocobase/nocobase/compare/v1.2.24-alpha...v1.2.25-alpha) - 2024-07-27
|
||||
|
||||
### Merged
|
||||
|
||||
- fix(plugin-workflow): hide condition configuration in destroy collection event [`#4952`](https://github.com/nocobase/nocobase/pull/4952)
|
||||
- fix(plugin-workflow): fix schedule event on date field [`#4953`](https://github.com/nocobase/nocobase/pull/4953)
|
||||
- refactor(client): allow select to show null option as tag in read pretty mode if configured [`#4950`](https://github.com/nocobase/nocobase/pull/4950)
|
||||
- fix: clear default value immediately after field deletion [`#4915`](https://github.com/nocobase/nocobase/pull/4915)
|
||||
- fix: autoGenId default value should be false when adding collection [`#4942`](https://github.com/nocobase/nocobase/pull/4942)
|
||||
- refactor: migrate DataBlockCollector to DataBlockProvider [`#4938`](https://github.com/nocobase/nocobase/pull/4938)
|
||||
- fix(action-import): import with createdBy & updatedBy field [`#4939`](https://github.com/nocobase/nocobase/pull/4939)
|
||||
|
||||
### Commits
|
||||
|
||||
- chore(versions): 😊 publish v1.2.25-alpha [`306035c`](https://github.com/nocobase/nocobase/commit/306035c607d2d8d22b540e5653cd9095abf906f0)
|
||||
- chore: update changelog [`b2f82a2`](https://github.com/nocobase/nocobase/commit/b2f82a26dfc113db7a8bad9e2c21ddcad4d71a0b)
|
||||
- Update LICENSE.txt [`027d54d`](https://github.com/nocobase/nocobase/commit/027d54dc8785a01c0af0d7e7a33aedb0af166e4e)
|
||||
|
||||
## [v1.2.24-alpha](https://github.com/nocobase/nocobase/compare/v1.2.23-alpha...v1.2.24-alpha) - 2024-07-23
|
||||
|
||||
### Merged
|
||||
|
12
packages/core/cli/templates/plugin/src/client/locale.ts
Normal file
12
packages/core/cli/templates/plugin/src/client/locale.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import pkg from './../../package.json';
|
||||
|
||||
export function usePluginTranslation() {
|
||||
return useTranslation([pkg.name, 'client'], { nsMode: 'fallback' });
|
||||
}
|
||||
|
||||
export function generatePluginTranslationTemplate(key: string) {
|
||||
return `{{t('${key}', { ns: ['${pkg.name}', 'client'], nsMode: 'fallback' })}}`;
|
||||
}
|
1
packages/core/cli/templates/plugin/src/locale/en-US.json
Normal file
1
packages/core/cli/templates/plugin/src/locale/en-US.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
1
packages/core/cli/templates/plugin/src/locale/zh-CN.json
Normal file
1
packages/core/cli/templates/plugin/src/locale/zh-CN.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -47,10 +47,6 @@ export interface CustomToken extends AliasToken {
|
||||
marginBlock: number;
|
||||
/** 区块的圆角 */
|
||||
borderRadiusBlock: number;
|
||||
/** 区块的 boxShadow */
|
||||
boxShadowBlock: string;
|
||||
/** 区块的下边框 */
|
||||
borderBottomBlock: string;
|
||||
}
|
||||
|
||||
export interface ThemeConfig extends _ThemeConfig {
|
||||
|
@ -15,10 +15,6 @@ const useStyles = genStyleHook('nb-card-item', (token) => {
|
||||
return {
|
||||
[componentCls]: {
|
||||
marginBottom: token.marginBlock,
|
||||
'> .ant-card': {
|
||||
boxShadow: token.boxShadowBlock,
|
||||
borderBottom: token.borderBottomBlock,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -31,16 +31,16 @@ export const ReadPretty = observer(
|
||||
(props: SelectReadPrettyProps) => {
|
||||
const fieldNames = { ...defaultFieldNames, ...props.fieldNames };
|
||||
const field = useField<any>();
|
||||
const collectionField = useCollectionField();
|
||||
const dataSource = field.dataSource || props.options || collectionField?.uiSchema.enum || [];
|
||||
const currentOptions = getCurrentOptions(field.value, dataSource, fieldNames);
|
||||
|
||||
if (!isValid(props.value)) {
|
||||
if (!isValid(props.value) && !currentOptions.length) {
|
||||
return <div />;
|
||||
}
|
||||
if (isArrayField(field) && field?.value?.length === 0) {
|
||||
return <div />;
|
||||
}
|
||||
const collectionField = useCollectionField();
|
||||
const dataSource = field.dataSource || props.options || collectionField?.uiSchema.enum || [];
|
||||
const currentOptions = getCurrentOptions(field.value, dataSource, fieldNames);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { mockApp } from '@nocobase/client/demo-utils';
|
||||
import { SchemaComponent, Plugin, ISchema } from '@nocobase/client';
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '福建',
|
||||
value: 'FuJian',
|
||||
children: [
|
||||
{ label: '{{t("福州")}}', value: 'FZ' },
|
||||
{ label: '莆田', value: 'PT' },
|
||||
],
|
||||
},
|
||||
{ label: '江苏', value: 'XZ' },
|
||||
{ label: '浙江', value: 'ZX' },
|
||||
{ lable: '未选择', value: null },
|
||||
];
|
||||
|
||||
const schema: ISchema = {
|
||||
type: 'void',
|
||||
name: 'root',
|
||||
'x-decorator': 'FormV2',
|
||||
'x-component': 'ShowFormData',
|
||||
properties: {
|
||||
test: {
|
||||
type: 'string',
|
||||
title: 'Test',
|
||||
enum: options,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
const Demo = () => {
|
||||
return <SchemaComponent schema={schema} />;
|
||||
};
|
||||
|
||||
class DemoPlugin extends Plugin {
|
||||
async load() {
|
||||
this.app.router.add('root', { path: '/', Component: Demo });
|
||||
}
|
||||
}
|
||||
|
||||
const app = mockApp({
|
||||
plugins: [DemoPlugin],
|
||||
});
|
||||
|
||||
export default app.getRootComponent();
|
@ -43,11 +43,9 @@ function flatData(data: any[], fieldNames: FieldNames): any[] {
|
||||
return newArr;
|
||||
}
|
||||
|
||||
export function getCurrentOptions(values: string | string[], dataSource: any[], fieldNames: FieldNames): Option[] {
|
||||
export function getCurrentOptions(values: any | any[], dataSource: any[], fieldNames: FieldNames): Option[] {
|
||||
const result = flatData(dataSource, fieldNames);
|
||||
const arrValues = castArray(values)
|
||||
.filter((item) => item != null)
|
||||
.map((val) => (isPlainObject(val) ? val[fieldNames.value] : val)) as string[];
|
||||
const arrValues = castArray(values).map((val) => (isPlainObject(val) ? val[fieldNames.value] : val)) as any[];
|
||||
|
||||
function findOptions(options: any[]): Option[] {
|
||||
if (!options) return [];
|
||||
|
@ -123,10 +123,10 @@ function getTypedConstantOption(type: string, types: true | string[], fieldNames
|
||||
Object.keys(item).reduce(
|
||||
(result, key) =>
|
||||
fieldNames[key] in item
|
||||
? result
|
||||
: Object.assign(result, {
|
||||
? Object.assign(result, {
|
||||
[fieldNames[key]]: item[key],
|
||||
}),
|
||||
})
|
||||
: result,
|
||||
item,
|
||||
),
|
||||
);
|
||||
@ -397,9 +397,9 @@ export function Input(props: VariableInputProps) {
|
||||
<div style={{ flex: 1 }}>
|
||||
{children && isFieldValue ? (
|
||||
children
|
||||
) : (
|
||||
) : ConstantComponent ? (
|
||||
<ConstantComponent role="button" aria-label="variable-constant" value={value} onChange={onChange} />
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
<Cascader
|
||||
|
@ -76,7 +76,6 @@ export class SyncRunner {
|
||||
|
||||
try {
|
||||
const beforeColumns = await this.queryInterface.describeTable(this.tableName, options);
|
||||
await this.checkAutoIncrementField(beforeColumns, options);
|
||||
await this.handlePrimaryKeyBeforeSync(beforeColumns, options);
|
||||
await this.handleUniqueFieldBeforeSync(beforeColumns, options);
|
||||
} catch (e) {
|
||||
@ -95,20 +94,6 @@ export class SyncRunner {
|
||||
return syncResult;
|
||||
}
|
||||
|
||||
async checkAutoIncrementField(beforeColumns, options) {
|
||||
// if there is auto increment field, throw error
|
||||
if (!this.database.isMySQLCompatibleDialect()) {
|
||||
return;
|
||||
}
|
||||
const autoIncrFields = Object.keys(this.rawAttributes).filter((key) => {
|
||||
return this.rawAttributes[key].autoIncrement;
|
||||
});
|
||||
|
||||
if (autoIncrFields.length > 1) {
|
||||
throw new Error(`Auto increment field can't be more than one: ${autoIncrFields.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
async handleUniqueFieldBeforeSync(beforeColumns, options) {
|
||||
if (!this.database.inDialect('sqlite')) {
|
||||
return;
|
||||
|
@ -52,7 +52,7 @@
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "8.1.0",
|
||||
"@nocobase/server": "1.3.0-alpha",
|
||||
"@playwright/test": "^1.44.0",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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 function beforeCreateCheckFieldInMySQL(db) {
|
||||
return async (model, { transaction }) => {
|
||||
if (!db.isMySQLCompatibleDialect()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldOptions = model.get();
|
||||
if (fieldOptions.autoIncrement) {
|
||||
const collection = db.getCollection(fieldOptions.collectionName);
|
||||
|
||||
if (!collection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rawAttributes = collection.model.rawAttributes;
|
||||
|
||||
const fields = Object.keys(rawAttributes);
|
||||
|
||||
for (const key of fields) {
|
||||
if (key === fieldOptions.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const field = rawAttributes[key];
|
||||
if (field.autoIncrement) {
|
||||
throw new Error(
|
||||
`Can not add field ${
|
||||
fieldOptions.name
|
||||
}, autoIncrement field ${key} is already in a table ${collection.getTableNameWithSchemaAsString()}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -30,6 +30,7 @@ import viewResourcer from './resourcers/views';
|
||||
import { FieldNameExistsError } from './errors/field-name-exists-error';
|
||||
import { beforeDestoryField } from './hooks/beforeDestoryField';
|
||||
import { FieldIsDependedOnByOtherError } from './errors/field-is-depended-on-by-other';
|
||||
import { beforeCreateCheckFieldInMySQL } from './hooks/beforeCreateCheckFieldInMySQL';
|
||||
|
||||
export class PluginDataSourceMainServer extends Plugin {
|
||||
public schema: string;
|
||||
@ -115,6 +116,8 @@ export class PluginDataSourceMainServer extends Plugin {
|
||||
});
|
||||
|
||||
// 要在 beforeInitOptions 之前处理
|
||||
this.app.db.on('fields.beforeCreate', beforeCreateCheckFieldInMySQL(this.app.db));
|
||||
|
||||
this.app.db.on('fields.beforeCreate', beforeCreateForReverseField(this.app.db));
|
||||
|
||||
this.app.db.on('fields.beforeCreate', async (model, options) => {
|
||||
|
@ -40,9 +40,11 @@ export const getAntChart = (Component: React.FC<any>) => (props: any) => {
|
||||
observer.observe(el);
|
||||
return () => observer.disconnect();
|
||||
}, [service.loading, fixedHeight, size.type, size.ratio?.width, size.ratio?.height]);
|
||||
const chartHeight = fixedHeight || height;
|
||||
|
||||
return (
|
||||
<div ref={chartRef} style={height ? { height: `${fixedHeight || height}px` } : {}}>
|
||||
<Component {...props} {...(height ? { height: fixedHeight || height } : {})} />
|
||||
<div ref={chartRef} style={chartHeight ? { height: `${chartHeight}px` } : {}}>
|
||||
<Component {...props} {...(chartHeight ? { height: chartHeight } : {})} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ export const Mobile = () => {
|
||||
token: {
|
||||
marginBlock: 18,
|
||||
borderRadiusBlock: 0,
|
||||
boxShadowBlock: 'none',
|
||||
boxShadowTertiary: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
@ -262,7 +262,7 @@ const category: TokenTree<keyof AliasToken | string> = [
|
||||
nameEn: 'Shadow',
|
||||
desc: '',
|
||||
descEn: '',
|
||||
mapToken: ['boxShadow', 'boxShadowSecondary', 'boxShadowBlock'],
|
||||
mapToken: ['boxShadow', 'boxShadowSecondary'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -1759,21 +1759,5 @@
|
||||
"descEn": "Used to set the radius of the block",
|
||||
"type": "number",
|
||||
"source": "map"
|
||||
},
|
||||
"boxShadowBlock": {
|
||||
"name": "区块的阴影",
|
||||
"nameEn": "Shadow of block",
|
||||
"desc": "用于设置区块的阴影",
|
||||
"descEn": "Used to set the shadow of the block",
|
||||
"type": "string",
|
||||
"source": "map"
|
||||
},
|
||||
"borderBottomBlock": {
|
||||
"name": "区块的底边框",
|
||||
"nameEn": "Bottom border of block",
|
||||
"desc": "用于设置区块的底边框",
|
||||
"descEn": "Used to set the bottom border of the block",
|
||||
"type": "string",
|
||||
"source": "map"
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ export class CreateWorkFlow {
|
||||
readonly page: Page;
|
||||
name: Locator;
|
||||
triggerType: Locator;
|
||||
synchronouslyRadio: Locator;
|
||||
asynchronouslyRadio: Locator;
|
||||
description: Locator;
|
||||
autoDeleteHistory: Locator;
|
||||
submitButton: Locator;
|
||||
@ -20,6 +22,8 @@ export class CreateWorkFlow {
|
||||
this.page = page;
|
||||
this.name = page.getByLabel('block-item-CollectionField-workflows-Name').getByRole('textbox');
|
||||
this.triggerType = page.getByTestId('select-single');
|
||||
this.synchronouslyRadio = page.getByLabel('Synchronously', { exact: true });
|
||||
this.asynchronouslyRadio = page.getByLabel('Asynchronously', { exact: true });
|
||||
this.description = page.getByTestId('description-item').getByRole('textbox');
|
||||
this.autoDeleteHistory = page.getByTestId('select-multiple');
|
||||
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
||||
@ -365,6 +369,30 @@ export class FormEventTriggerNode {
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomActionEventTriggerNode {
|
||||
readonly page: Page;
|
||||
node: Locator;
|
||||
nodeTitle: Locator;
|
||||
nodeConfigure: Locator;
|
||||
collectionDropDown: Locator;
|
||||
relationalDataDropdown: Locator;
|
||||
submitButton: Locator;
|
||||
cancelButton: Locator;
|
||||
addNodeButton: Locator;
|
||||
constructor(page: Page, triggerName: string, collectionName: string) {
|
||||
this.page = page;
|
||||
this.node = page.getByLabel(`Trigger-${triggerName}`);
|
||||
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
|
||||
this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
|
||||
this.collectionDropDown = page
|
||||
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
||||
.locator('.ant-select-selection-search-input');
|
||||
this.relationalDataDropdown = page.getByTestId('select-field-Preload associations');
|
||||
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
||||
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
||||
this.addNodeButton = page.getByLabel('add-button', { exact: true });
|
||||
}
|
||||
}
|
||||
export class CalculationNode {
|
||||
readonly page: Page;
|
||||
node: Locator;
|
||||
@ -746,4 +774,5 @@ export default module.exports = {
|
||||
SQLNode,
|
||||
ParallelBranchNode,
|
||||
ApprovalBranchModeNode,
|
||||
CustomActionEventTriggerNode,
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { request, Browser } from '@nocobase/test/e2e';
|
||||
import { Browser, request } from '@nocobase/test/e2e';
|
||||
|
||||
const PORT = process.env.APP_PORT || 20000;
|
||||
const APP_BASE_URL = process.env.APP_BASE_URL || `http://localhost:${PORT}`;
|
||||
@ -808,6 +808,57 @@ export const apiCreateRecordTriggerActionEvent = async (
|
||||
return (await result.json()).data;
|
||||
};
|
||||
|
||||
// 添加业务表单条数据触发工作流表单事件,triggerWorkflows=key1!field,key2,key3!field.subfield
|
||||
export const apiTriggerCustomActionEvent = async (collectionName: string, triggerWorkflows: string, data: any) => {
|
||||
const api = await request.newContext({
|
||||
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
||||
});
|
||||
const state = await api.storageState();
|
||||
const headers = getHeaders(state);
|
||||
/*
|
||||
{
|
||||
"title": "a11",
|
||||
"enabled": true,
|
||||
"description": null
|
||||
}
|
||||
*/
|
||||
const result = await api.post(`/api/${collectionName}:trigger?triggerWorkflows=${triggerWorkflows}`, {
|
||||
headers,
|
||||
data,
|
||||
});
|
||||
|
||||
if (!result.ok()) {
|
||||
throw new Error(await result.text());
|
||||
}
|
||||
/*
|
||||
{
|
||||
"data": {
|
||||
"id": 1,
|
||||
"createdAt": "2023-12-12T02:43:53.793Z",
|
||||
"updatedAt": "2023-12-12T05:41:33.300Z",
|
||||
"key": "fzk3j2oj4el",
|
||||
"title": "a11",
|
||||
"enabled": true,
|
||||
"description": null
|
||||
},
|
||||
"meta": {
|
||||
"allowedActions": {
|
||||
"view": [
|
||||
1
|
||||
],
|
||||
"update": [
|
||||
1
|
||||
],
|
||||
"destroy": [
|
||||
1
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return (await result.json()).data;
|
||||
};
|
||||
|
||||
// 审批中心发起审批
|
||||
export const apiApplyApprovalEvent = async (data: any) => {
|
||||
const api = await request.newContext({
|
||||
@ -1021,4 +1072,5 @@ export default module.exports = {
|
||||
apiApplyApprovalEvent,
|
||||
userLogin,
|
||||
apiCreateField,
|
||||
apiTriggerCustomActionEvent,
|
||||
};
|
||||
|
@ -160,10 +160,10 @@ export default class extends Trigger {
|
||||
'x-component-props': {},
|
||||
'x-reactions': [
|
||||
{
|
||||
dependencies: ['collection'],
|
||||
dependencies: ['collection', 'mode'],
|
||||
fulfill: {
|
||||
state: {
|
||||
visible: '{{!!$deps[0]}}',
|
||||
visible: `{{!!$deps[0] && !($deps[1] & ${COLLECTION_TRIGGER_MODE.DELETED})}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -434,6 +434,29 @@ describe('workflow > triggers > collection', () => {
|
||||
expect(executions.length).toBe(1);
|
||||
expect(executions[0].context.data.title).toBe('t1');
|
||||
});
|
||||
|
||||
it('condition will not effect destroy', async () => {
|
||||
const workflow = await WorkflowModel.create({
|
||||
enabled: true,
|
||||
type: 'collection',
|
||||
config: {
|
||||
mode: 4,
|
||||
collection: 'posts',
|
||||
condition: {
|
||||
title: 't1',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const post1 = await PostRepo.create({ values: { title: 't1' } });
|
||||
await PostRepo.destroy({ filterByTk: post1.id });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const executions = await workflow.getExecutions();
|
||||
expect(executions.length).toBe(1);
|
||||
expect(executions[0].context.data.title).toBe('t1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('config.appends', () => {
|
||||
|
@ -377,5 +377,30 @@ describe('workflow > triggers > schedule > date field mode', () => {
|
||||
const e2c = await workflow.countExecutions();
|
||||
expect(e2c).toBe(2);
|
||||
});
|
||||
|
||||
it('empty endsOn as no end', async () => {
|
||||
const workflow = await WorkflowModel.create({
|
||||
enabled: true,
|
||||
type: 'schedule',
|
||||
config: {
|
||||
mode: 1,
|
||||
collection: 'posts',
|
||||
startsOn: {
|
||||
field: 'createdAt',
|
||||
},
|
||||
repeat: 1000,
|
||||
endsOn: {},
|
||||
},
|
||||
});
|
||||
|
||||
await sleepToEvenSecond();
|
||||
|
||||
const post = await PostRepo.create({ values: { title: 't1' } });
|
||||
|
||||
await sleep(1700);
|
||||
|
||||
const e1c = await workflow.countExecutions();
|
||||
expect(e1c).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ async function handler(this: CollectionTrigger, workflow: WorkflowModel, data: M
|
||||
}
|
||||
|
||||
// NOTE: if no configured condition, or not match, do not trigger
|
||||
if (isValidFilter(condition)) {
|
||||
if (isValidFilter(condition) && !(mode & MODE_BITMAP.DESTROY)) {
|
||||
// TODO: change to map filter format to calculation format
|
||||
// const calculation = toCalculation(condition);
|
||||
const count = await repository.count({
|
||||
|
@ -54,7 +54,7 @@ function getDataOptionTime(record, on, dir = 1) {
|
||||
}
|
||||
case 'object': {
|
||||
const { field, offset = 0, unit = 1000 } = on;
|
||||
if (!record.get(field)) {
|
||||
if (!field || !record.get(field)) {
|
||||
return null;
|
||||
}
|
||||
const second = new Date(record.get(field).getTime());
|
||||
|
@ -30,7 +30,6 @@
|
||||
"packages/**/dist",
|
||||
"packages/**/public",
|
||||
"packages/core/build/bin",
|
||||
"packages/core/cli/**/*",
|
||||
"packages/**/lib",
|
||||
"packages/**/es"
|
||||
]
|
||||
|
28
yarn.lock
28
yarn.lock
@ -5053,12 +5053,12 @@
|
||||
picocolors "^1.0.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@playwright/test@^1.44.0":
|
||||
version "1.44.0"
|
||||
resolved "https://registry.npmmirror.com/@playwright/test/-/test-1.44.0.tgz#ac7a764b5ee6a80558bdc0fcbc525fcb81f83465"
|
||||
integrity sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==
|
||||
"@playwright/test@^1.45.3":
|
||||
version "1.45.3"
|
||||
resolved "https://registry.npmmirror.com/@playwright/test/-/test-1.45.3.tgz#22e9c38b3081d6674b28c6e22f784087776c72e5"
|
||||
integrity sha512-UKF4XsBfy+u3MFWEH44hva1Q8Da28G6RFtR2+5saw+jgAFQV5yYnB1fu68Mz7fO+5GJF3wgwAIs0UelU8TxFrA==
|
||||
dependencies:
|
||||
playwright "1.44.0"
|
||||
playwright "1.45.3"
|
||||
|
||||
"@pm2/agent@~2.0.0":
|
||||
version "2.0.3"
|
||||
@ -20886,17 +20886,17 @@ platform@^1.3.1:
|
||||
resolved "https://registry.npmmirror.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
|
||||
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
|
||||
|
||||
playwright-core@1.44.0:
|
||||
version "1.44.0"
|
||||
resolved "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.44.0.tgz#316c4f0bca0551ffb88b6eb1c97bc0d2d861b0d5"
|
||||
integrity sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==
|
||||
playwright-core@1.45.3:
|
||||
version "1.45.3"
|
||||
resolved "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.45.3.tgz#e77bc4c78a621b96c3e629027534ee1d25faac93"
|
||||
integrity sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==
|
||||
|
||||
playwright@1.44.0:
|
||||
version "1.44.0"
|
||||
resolved "https://registry.npmmirror.com/playwright/-/playwright-1.44.0.tgz#22894e9b69087f6beb639249323d80fe2b5087ff"
|
||||
integrity sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==
|
||||
playwright@1.45.3:
|
||||
version "1.45.3"
|
||||
resolved "https://registry.npmmirror.com/playwright/-/playwright-1.45.3.tgz#75143f73093a6e1467f7097083d2f0846fb8dd2f"
|
||||
integrity sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==
|
||||
dependencies:
|
||||
playwright-core "1.44.0"
|
||||
playwright-core "1.45.3"
|
||||
optionalDependencies:
|
||||
fsevents "2.3.2"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user