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
skip-token-revoke: true
- id: get-plugins
name: Get plugins
shell: bash
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"
echo "custom-plugins=$(gh search repos "props.plugin-type:custom" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT"
echo "rc-plugins=$(gh search repos "props.plugin-type:rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT"
echo "beta-plugins=$(gh search repos "props.plugin-type:beta,rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT"
echo "alpha-plugins=$(gh search repos "props.plugin-type:alpha,beta,rc" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT"
echo "unreleased-plugins=$(gh search repos "props.plugin-type:unreleased" --owner=nocobase --json name | jq -r 'map(.name) | tostring')" >> "$GITHUB_OUTPUT"
function retry() {
local i=0
local plugins="[]"
until [ "$i" -ge 2 ]
do
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:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

View File

@ -81,8 +81,7 @@ const handleChangeOnFilter = (value, picker, showTime) => {
}
return value;
};
const handleChangeOnForm = (value, dateOnly, utc, picker, showTime, gmt) => {
export const handleDateChangeOnForm = (value, dateOnly, utc, picker, showTime, gmt) => {
const format = showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
if (!value) {
return value;
@ -120,7 +119,7 @@ export const mapDatePicker = function () {
if (underFilter) {
onChange(handleChangeOnFilter(value, picker, showTime));
} 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
*/
@ -183,6 +191,7 @@ export abstract class Plugin<O = any> implements PluginInterface {
}
const directory = resolve(basePath, 'server/collections');
if (await fsExists(directory)) {
this.app.log.trace(`load plugin collections [${this.name}]`);
await this.db.import({
directory,
from: this.options.packageName,

View File

@ -8,7 +8,7 @@
*/
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import { RecursionField, Schema, useFieldSchema } from '@formily/react';
import { RecursionField, Schema, observer, useFieldSchema, useField } from '@formily/react';
import {
PopupContextProvider,
RecordProvider,
@ -21,13 +21,21 @@ import {
useProps,
useToken,
withDynamicSchemaProps,
withSkeletonComponent,
useACLRoleContext,
useDesignable,
ActionContextProvider,
useActionContext,
CollectionProvider,
SchemaComponentOptions,
useFormBlockContext,
handleDateChangeOnForm,
} from '@nocobase/client';
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import { get } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import type { View } from 'react-big-calendar';
import { get, cloneDeep } from 'lodash';
import React, { useMemo, useState, useEffect, useCallback } from 'react';
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 { CalendarRecordViewer, findEventSchema } from './CalendarRecordViewer';
import Header from './components/Header';
@ -37,7 +45,7 @@ import { useCalenderHeight } from './hook';
import useStyle from './style';
import type { ToolbarProps } from './types';
import { formatDate } from './utils';
import { addNew } from './schema';
interface Event {
id: string;
colorFieldValue: string;
@ -222,17 +230,25 @@ const useEvents = (
]);
};
function findCreateSchema(schema): Schema {
return schema.reduceProperties((buf, current) => {
if (current['x-component'].endsWith('Action') && current['x-action'] === 'create') {
return current;
}
if (current['x-component'].endsWith('.ActionBar')) {
return findCreateSchema(current);
export const useInsertSchema = (component) => {
const fieldSchema = useFieldSchema();
const { insertAfterBegin } = useDesignable();
const insert = useCallback(
(ss) => {
const schema = fieldSchema.reduceProperties((buf, s) => {
if (s['x-component'] === 'AssociationField.' + component) {
return s;
}
return buf;
}, null);
}
if (!schema) {
insertAfterBegin(cloneDeep(ss));
}
},
[component],
);
return insert;
};
export const Calendar: any = withDynamicSchemaProps(
withSkeletonComponent(
@ -268,15 +284,18 @@ export const Calendar: any = withDynamicSchemaProps(
const { wrapSSR, hashId, componentCls: containerClassName } = useStyle();
const parentRecordData = useCollectionParentRecordData();
const fieldSchema = useFieldSchema();
const field = useField();
const { token } = useToken();
//nint deal with slot select to show create popup
const { parseAction } = useACLRoleContext();
const collection = useCollection();
const canCreate = parseAction(`${collection.name}:create`);
const createActionSchema: Schema = useMemo(() => findCreateSchema(fieldSchema), [fieldSchema]);
const startFieldName = fieldNames?.start?.[0];
const endFieldName = fieldNames?.end?.[0];
const insertAddNewer = useInsertSchema('AddNewer');
const ctx = useActionContext();
const [visibleAddNewer, setVisibleAddNewer] = useState(false);
const [currentSelectDate, setCurrentSelectDate] = useState(undefined);
useEffect(() => {
setView(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;
return wrapSSR(
@ -351,15 +420,10 @@ export const Calendar: any = withDynamicSchemaProps(
onNavigate={setDate}
onView={setView}
onSelectSlot={(slotInfo) => {
//nint show create popup
if (canCreate && createActionSchema) {
const record = {};
record[startFieldName] = slotInfo.start;
record[endFieldName] = slotInfo.end;
openPopup({
recordData: record,
customActionSchema: createActionSchema,
});
setCurrentSelectDate(slotInfo);
if (canCreate) {
insertAddNewer(addNew);
setVisibleAddNewer(true);
}
}}
onDoubleClickEvent={() => {
@ -397,6 +461,20 @@ export const Calendar: any = withDynamicSchemaProps(
localizer={localizer}
/>
</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>,
);
},

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 };