Merge branch 'next' into develop

This commit is contained in:
katherinehhh 2024-11-29 14:05:13 +08:00
commit 5458829e43
5 changed files with 209 additions and 37 deletions

View File

@ -38,13 +38,52 @@ jobs:
owner: nocobase owner: nocobase
skip-token-revoke: true skip-token-revoke: true
- id: get-plugins - id: get-plugins
name: Get plugins
shell: bash shell: bash
run: | run: |
echo "all-plugins=$(gh search repos "props.plugin-type:custom,rc,beta,alpha,unreleased" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" function retry() {
echo "custom-plugins=$(gh search repos "props.plugin-type:custom" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" local i=0
echo "rc-plugins=$(gh search repos "props.plugin-type:rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" local plugins="[]"
echo "beta-plugins=$(gh search repos "props.plugin-type:beta,rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" until [ "$i" -ge 2 ]
echo "alpha-plugins=$(gh search repos "props.plugin-type:alpha,beta,rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" do
echo "unreleased-plugins=$(gh search repos "props.plugin-type:unreleased" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT" plugins=$(gh search repos "props.plugin-type:$1" --owner=nocobase --json name | jq -r 'map(.name) | tostring') && [[ "$plugins" != "[]" ]] && break
i=$((i+1))
sleep 10
done
echo $plugins
}
allPlugins=$(retry custom,rc,beta,alpha,unreleased)
if [[ "$allPlugins" == "[]" ]]; then
echo "Get all plugins empty"
exit 1
fi
customPlugins=$(retry custom)
if [[ "$customPlugins" == "[]" ]]; then
echo "Get custom plugins empty"
exit 1
fi
rcPlugins=$(retry rc)
rcPlugins=$(retry custom)
if [[ "$rcPlugins" == "[]" ]]; then
echo "Get rc plugins empty"
exit 1
fi
betaPlugins=$(retry beta,rc)
if [[ "$betaPlugins" == "[]" ]]; then
echo "Get beta plugins empty"
exit 1
fi
alphaPlugins=$(retry alpha,beta,rc)
if [[ "$alphaPlugins" == "[]" ]]; then
echo "Get alpha plugins empty"
exit 1
fi
unreleasedPlugins=$(retry unreleased)
echo "all-plugins=$allPlugins" >> "$GITHUB_OUTPUT"
echo "custom-plugins=$customPlugins" >> "$GITHUB_OUTPUT"
echo "rc-plugins=$rcPlugins" >> "$GITHUB_OUTPUT"
echo "beta-plugins=$betaPlugins" >> "$GITHUB_OUTPUT"
echo "alpha-plugins=$alphaPlugins" >> "$GITHUB_OUTPUT"
echo "unreleased-plugins=$unreleasedPlugins" >> "$GITHUB_OUTPUT"
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token }} GH_TOKEN: ${{ steps.app-token.outputs.token }}

View File

@ -81,8 +81,7 @@ const handleChangeOnFilter = (value, picker, showTime) => {
} }
return value; return value;
}; };
export const handleDateChangeOnForm = (value, dateOnly, utc, picker, showTime, gmt) => {
const handleChangeOnForm = (value, dateOnly, utc, picker, showTime, gmt) => {
const format = showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'; const format = showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
if (!value) { if (!value) {
return value; return value;
@ -120,7 +119,7 @@ export const mapDatePicker = function () {
if (underFilter) { if (underFilter) {
onChange(handleChangeOnFilter(value, picker, showTime)); onChange(handleChangeOnFilter(value, picker, showTime));
} else { } else {
onChange(handleChangeOnForm(value, dateOnly, utc, picker, showTime, gmt)); onChange(handleDateChangeOnForm(value, dateOnly, utc, picker, showTime, gmt));
} }
} }
}, },

View File

@ -173,6 +173,14 @@ export abstract class Plugin<O = any> implements PluginInterface {
}); });
} }
private async getPluginBasePath() {
if (!this.options.packageName) {
this.app.log.trace(`plugin '${this.name}' is missing packageName`);
return;
}
return getPluginBasePath(this.options.packageName);
}
/** /**
* @internal * @internal
*/ */
@ -183,6 +191,7 @@ export abstract class Plugin<O = any> implements PluginInterface {
} }
const directory = resolve(basePath, 'server/collections'); const directory = resolve(basePath, 'server/collections');
if (await fsExists(directory)) { if (await fsExists(directory)) {
this.app.log.trace(`load plugin collections [${this.name}]`);
await this.db.import({ await this.db.import({
directory, directory,
from: this.options.packageName, from: this.options.packageName,

View File

@ -8,7 +8,7 @@
*/ */
import { LeftOutlined, RightOutlined } from '@ant-design/icons'; import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import { RecursionField, Schema, useFieldSchema } from '@formily/react'; import { RecursionField, Schema, observer, useFieldSchema, useField } from '@formily/react';
import { import {
PopupContextProvider, PopupContextProvider,
RecordProvider, RecordProvider,
@ -21,13 +21,21 @@ import {
useProps, useProps,
useToken, useToken,
withDynamicSchemaProps, withDynamicSchemaProps,
withSkeletonComponent, useACLRoleContext,
useDesignable,
ActionContextProvider,
useActionContext,
CollectionProvider,
SchemaComponentOptions,
useFormBlockContext,
handleDateChangeOnForm,
} from '@nocobase/client'; } from '@nocobase/client';
import type { Dayjs } from 'dayjs'; import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { get } from 'lodash'; import { get, cloneDeep } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react'; import React, { useMemo, useState, useEffect, useCallback } from 'react';
import type { View } from 'react-big-calendar'; import { Calendar as BigCalendar, View, dayjsLocalizer } from 'react-big-calendar';
import * as dates from 'react-big-calendar/lib/utils/dates';
import { i18nt, useTranslation } from '../../locale'; import { i18nt, useTranslation } from '../../locale';
import { CalendarRecordViewer, findEventSchema } from './CalendarRecordViewer'; import { CalendarRecordViewer, findEventSchema } from './CalendarRecordViewer';
import Header from './components/Header'; import Header from './components/Header';
@ -37,7 +45,7 @@ import { useCalenderHeight } from './hook';
import useStyle from './style'; import useStyle from './style';
import type { ToolbarProps } from './types'; import type { ToolbarProps } from './types';
import { formatDate } from './utils'; import { formatDate } from './utils';
import { addNew } from './schema';
interface Event { interface Event {
id: string; id: string;
colorFieldValue: string; colorFieldValue: string;
@ -222,17 +230,25 @@ const useEvents = (
]); ]);
}; };
function findCreateSchema(schema): Schema { export const useInsertSchema = (component) => {
return schema.reduceProperties((buf, current) => { const fieldSchema = useFieldSchema();
if (current['x-component'].endsWith('Action') && current['x-action'] === 'create') { const { insertAfterBegin } = useDesignable();
return current; const insert = useCallback(
} (ss) => {
if (current['x-component'].endsWith('.ActionBar')) { const schema = fieldSchema.reduceProperties((buf, s) => {
return findCreateSchema(current); if (s['x-component'] === 'AssociationField.' + component) {
return s;
} }
return buf; return buf;
}, null); }, null);
} if (!schema) {
insertAfterBegin(cloneDeep(ss));
}
},
[component],
);
return insert;
};
export const Calendar: any = withDynamicSchemaProps( export const Calendar: any = withDynamicSchemaProps(
withSkeletonComponent( withSkeletonComponent(
@ -268,15 +284,18 @@ export const Calendar: any = withDynamicSchemaProps(
const { wrapSSR, hashId, componentCls: containerClassName } = useStyle(); const { wrapSSR, hashId, componentCls: containerClassName } = useStyle();
const parentRecordData = useCollectionParentRecordData(); const parentRecordData = useCollectionParentRecordData();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const field = useField();
const { token } = useToken(); const { token } = useToken();
//nint deal with slot select to show create popup //nint deal with slot select to show create popup
const { parseAction } = useACLRoleContext(); const { parseAction } = useACLRoleContext();
const collection = useCollection(); const collection = useCollection();
const canCreate = parseAction(`${collection.name}:create`); const canCreate = parseAction(`${collection.name}:create`);
const createActionSchema: Schema = useMemo(() => findCreateSchema(fieldSchema), [fieldSchema]);
const startFieldName = fieldNames?.start?.[0]; const startFieldName = fieldNames?.start?.[0];
const endFieldName = fieldNames?.end?.[0]; const endFieldName = fieldNames?.end?.[0];
const insertAddNewer = useInsertSchema('AddNewer');
const ctx = useActionContext();
const [visibleAddNewer, setVisibleAddNewer] = useState(false);
const [currentSelectDate, setCurrentSelectDate] = useState(undefined);
useEffect(() => { useEffect(() => {
setView(props.defaultView); setView(props.defaultView);
}, [props.defaultView]); }, [props.defaultView]);
@ -327,7 +346,57 @@ export const Calendar: any = withDynamicSchemaProps(
}; };
} }
}; };
// 快速创建行程
const useCreateFormBlockProps = () => {
const ctx = useFormBlockContext();
let startDateValue = currentSelectDate.start;
let endDataValue = currentSelectDate.end;
const startCollectionField = collection.getField(startFieldName);
const endCollectionField = collection.getField(endFieldName);
useEffect(() => {
const form = ctx.form;
if (!form || ctx.service?.loading) {
return;
}
if (currentSelectDate) {
const startFieldProps = {
...startCollectionField.uiSchema?.['x-component-props'],
...ctx.form?.query(startFieldName).take()?.componentProps,
};
const endFieldProps = {
...endCollectionField.uiSchema?.['x-component-props'],
...ctx.form?.query(endFieldName).take()?.componentProps,
};
startDateValue = handleDateChangeOnForm(
currentSelectDate.start,
startFieldProps.dateOnly,
startFieldProps.utc,
startFieldProps.picker,
startFieldProps.showTime,
startFieldProps.gtm,
);
endDataValue = handleDateChangeOnForm(
currentSelectDate.end,
endFieldProps.dateOnly,
endFieldProps.utc,
endFieldProps.picker,
endFieldProps.showTime,
endFieldProps.gtm,
);
if (!form.initialValues[startFieldName]) {
form.setInitialValuesIn([startFieldName], startDateValue);
}
if (!form.initialValues[endFieldName]) {
form.setInitialValuesIn([endFieldName], endDataValue);
}
}
}, [ctx.form, ctx.service?.data?.data, ctx.service?.loading]);
return {
form: ctx.form,
};
};
const BigCalendar = reactBigCalendar?.BigCalendar; const BigCalendar = reactBigCalendar?.BigCalendar;
return wrapSSR( return wrapSSR(
@ -351,15 +420,10 @@ export const Calendar: any = withDynamicSchemaProps(
onNavigate={setDate} onNavigate={setDate}
onView={setView} onView={setView}
onSelectSlot={(slotInfo) => { onSelectSlot={(slotInfo) => {
//nint show create popup setCurrentSelectDate(slotInfo);
if (canCreate && createActionSchema) { if (canCreate) {
const record = {}; insertAddNewer(addNew);
record[startFieldName] = slotInfo.start; setVisibleAddNewer(true);
record[endFieldName] = slotInfo.end;
openPopup({
recordData: record,
customActionSchema: createActionSchema,
});
} }
}} }}
onDoubleClickEvent={() => { onDoubleClickEvent={() => {
@ -397,6 +461,20 @@ export const Calendar: any = withDynamicSchemaProps(
localizer={localizer} localizer={localizer}
/> />
</PopupContextProvider> </PopupContextProvider>
<ActionContextProvider value={{ ...ctx, visible: visibleAddNewer, setVisible: setVisibleAddNewer }}>
<CollectionProvider name={collection.name}>
<SchemaComponentOptions scope={{ useCreateFormBlockProps }}>
<RecursionField
onlyRenderProperties
basePath={field?.address}
schema={fieldSchema}
filterProperties={(s) => {
return s['x-component'] === 'AssociationField.AddNewer';
}}
/>
</SchemaComponentOptions>
</CollectionProvider>
</ActionContextProvider>
</div>, </div>,
); );
}, },

View File

@ -0,0 +1,47 @@
/**
* 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.
*/
const addNew = {
type: 'void',
'x-component': 'AssociationField.AddNewer',
'x-action': 'create',
title: '{{ t("Add record") }}',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'popup:addTab',
'x-initializer-props': {
gridInitializer: 'popup:addNew:addBlock',
},
properties: {
tab1: {
type: 'void',
title: '{{t("Add new")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
type: 'void',
'x-component': 'Grid',
'x-initializer': 'popup:addNew:addBlock',
properties: {},
},
},
},
},
},
},
};
export { addNew };