mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 21:49:25 +08:00
Merge branch 'next' into develop
This commit is contained in:
commit
5458829e43
51
.github/workflows/get-plugins.yml
vendored
51
.github/workflows/get-plugins.yml
vendored
@ -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 }}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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,
|
||||||
|
@ -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>,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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 };
|
Loading…
x
Reference in New Issue
Block a user