feat/feat-apiselected (#1132)

Reviewed-on: daoyoucloud/tachybase#1132
Co-authored-by: bai.zixv <bai.zixv@foxmail.com>
Co-committed-by: bai.zixv <bai.zixv@foxmail.com>
This commit is contained in:
bai.zixv 2024-06-06 11:48:27 +08:00 committed by sealday
parent 6df452378f
commit 03a1dfdf1e
12 changed files with 61 additions and 47 deletions

View File

@ -32,17 +32,17 @@ export const ActionAreaStub = () => {
export const ActionAreaPlayer = ({ children }) => {
const { visible, setVisible } = useActionContext();
const { prevSetVisible, setPrevSetVisible, ref } = useContext(ActionAreaContext);
const { prevSetVisible, setPrevSetVisible, ref = { current: null } } = useContext(ActionAreaContext);
useEffect(() => {
if (visible) {
setPrevSetVisible(() => {
setPrevSetVisible?.(() => {
prevSetVisible?.(false);
return setVisible;
});
}
}, [visible]);
return visible ? createPortal(children, ref.current) : null;
return visible && ref.current ? createPortal(children, ref.current) : null;
};
export const ActionArea: ComposedActionDrawer = observer(

View File

@ -19,9 +19,9 @@ const schema = {
'x-acl-action-props': {
skipScopeCheck: true,
},
'x-action': 'customize:APIRegular',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:APIRegular',
'x-action': 'customize:APIRegular',
'x-action-settings': {
bindWorkflow: false,
updateMode: 'selected',

View File

@ -54,6 +54,12 @@ export const usePropsAPIRegular = () => {
updateMode,
} = actionSchema?.['x-action-settings'] ?? {};
const isUpdateSelected = updateMode === 'selected';
const updateData = {
primaryKey: rowKey || 'id',
targetKeys: selectedRecordKeys,
};
actionField.data = field.data || {};
actionField.data.loading = true;
@ -86,15 +92,14 @@ export const usePropsAPIRegular = () => {
await Promise.all(waitList);
modal.confirm({
title: lang('Bulk update', { ns: 'client' }),
content:
updateMode === 'selected'
? lang('Update selected data?', { ns: 'client' })
: lang('Update all data?', { ns: 'client' }),
title: lang('Confirm', { ns: 'client' }),
content: lang('Trigger workflow?', { ns: 'client' }),
async onOk() {
run({
const params = {
filterByTk: bindWorkflow,
});
updateData: encodeURIComponent(JSON.stringify(updateData)),
};
run(params);
actionField.data.loading = false;
},
async onCancel() {
@ -104,21 +109,3 @@ export const usePropsAPIRegular = () => {
},
};
};
function updateData() {
// const updateData: { filter?: any; values: any; forceUpdate: boolean } = {
// values,
// filter,
// forceUpdate: false,
// };
// if (updateMode === 'selected') {
// if (!selectedRecordKeys?.length) {
// message.error(t('Please select the records to be updated'));
// return;
// }
// updateData.filter = { $and: [{ [rowKey || 'id']: { $in: selectedRecordKeys } }] };
// }
// if (!updateData.filter) {
// updateData.forceUpdate = true;
// }
}

View File

@ -2,8 +2,8 @@ import { Plugin, useCollection } from '@tachybase/client';
import { tval } from '../../../locale';
import { APIRegularInitializer } from './APIRegular.schema';
import { APIRegularActionSettings } from './BulkUpdateAction.Settings';
import { usePropsAPIRegular } from './utils';
import { APIRegularActionSettings } from './APIRegular.setting';
import { usePropsAPIRegular } from './hooks';
export class KitAPIRegularUsage extends Plugin {
async load() {

View File

@ -77,7 +77,8 @@ function useUpdateAction() {
},
});
ctx.setFormValueChanged(false);
ctx.setVisible(false);
// ctx.setVisible(false);
message.success('success');
refresh();
},
};
@ -410,7 +411,7 @@ export function NodeDefaultView(props) {
? null
: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
'x-component': 'ActionArea.Footer',
properties: {
cancel: {
title: '{{t("Cancel")}}',

View File

@ -42,6 +42,7 @@ const useStyles = createStyles(({ css, token }) => {
}
.workflow-operator-area {
overflow-y: scroll;
padding: 8px;
background-color: white;
width: 800px;

View File

@ -46,7 +46,8 @@ function useUpdateConfigAction() {
},
});
ctx.setFormValueChanged(false);
ctx.setVisible(false);
// ctx.setVisible(false);
message.success('success');
refresh();
},
};
@ -298,7 +299,7 @@ export const TriggerConfig = () => {
? {}
: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
'x-component': 'ActionArea.Footer',
properties: {
cancel: {
title: '{{t("Cancel")}}',

View File

@ -164,10 +164,17 @@ export async function sync(context: Context, next) {
export async function trigger(ctx: Context) {
const plugin = ctx.app.getPlugin(Plugin) as Plugin;
const workflow = (await ctx.db.getRepository('workflows').findById(ctx.action.params.filterByTk)) as WorkflowModel;
// NOTE: 这里的updateData是通过前端传过来的需要 decodeURIComponent,
// updateData 的约定结构是形如: updateData: { primaryKey: "id", targetKeys: []}
const updateData = JSON.parse(decodeURIComponent(ctx.action.params?.updateData || ''));
plugin.trigger(
workflow,
{
data: {},
data: {
updateData,
httpContext: ctx,
user: ctx?.auth?.user,
},
},
{ httpContext: ctx },
);

View File

@ -1,11 +1,12 @@
import { get } from 'lodash';
import { BelongsTo, HasOne } from 'sequelize';
import { Context as ActionContext, Next } from '@tachybase/actions';
import { parseCollectionName } from '@tachybase/data-source-manager';
import { Model, modelAssociationByKey } from '@tachybase/database';
import Application, { DefaultContext } from '@tachybase/server';
import { Context as ActionContext, Next } from '@tachybase/actions';
import WorkflowPlugin, { Trigger, WorkflowModel, toJSON } from '../..';
import { parseCollectionName } from '@tachybase/data-source-manager';
import { get } from 'lodash';
import { BelongsTo, HasOne } from 'sequelize';
import WorkflowPlugin, { toJSON, Trigger, WorkflowModel } from '../..';
interface Context extends ActionContext, DefaultContext {}

View File

@ -15,7 +15,7 @@ interface Context extends ActionContext, DefaultContext {}
export class APIRegularTrigger extends Trigger {
constructor(workflow: WorkflowPlugin) {
super(workflow);
workflow.app.use(this.middleware, { after: 'dataSource' });
// workflow.app.use(this.middleware, { after: 'dataSource' });
}
async middleware(context: Context, next: Next) {

View File

@ -1,4 +1,5 @@
import axios, { AxiosRequestConfig } from 'axios';
import _ from 'lodash';
import { FlowNodeModel, Instruction, JOB_STATUS, Processor } from '../..';
@ -12,10 +13,14 @@ export type RequestConfig = Pick<AxiosRequestConfig, 'url' | 'method' | 'params'
ignoreFail: boolean;
};
async function request(config) {
async function request(config, context) {
// default headers
const { url, method = 'POST', data, timeout = 5000 } = config;
const headers = (config.headers ?? []).reduce((result, header) => {
const { token, origin } = context;
const { url: originUrl, method = 'POST', data, timeout = 5000 } = config;
const url = originUrl.startsWith('http') ? originUrl : `${origin}${originUrl}`;
let headers = (config.headers ?? []).reduce((result, header) => {
if (header.name.toLowerCase() === 'content-type') {
return result;
}
@ -29,6 +34,11 @@ async function request(config) {
// TODO(feat): only support JSON type for now, should support others in future
headers['Content-Type'] = 'application/json';
// let temp = context.get('headers');
headers = {
Authorization: 'Bearer ' + token,
...headers,
};
return axios.request({
url,
method,
@ -41,13 +51,19 @@ async function request(config) {
export default class extends Instruction {
async run(node: FlowNodeModel, prevJob, processor: Processor) {
const httpContext = _.get(processor, 'execution.dataValues.context.data.httpContext', {});
const userId = _.get(processor, 'execution.dataValues.context.data.user.id', 1);
const origin = _.get(httpContext, 'request.header.origin', '');
const token = this.workflow.app.authManager.jwt.sign({ userId });
const context = { token, origin };
const config = processor.getParsedValue(node.config, node.id) as RequestConfig;
const { workflow } = processor.execution;
const sync = this.workflow.isWorkflowSync(workflow);
if (sync) {
try {
const response = await request(config);
const response = await request(config, context);
return {
status: JOB_STATUS.RESOLVED,
@ -69,7 +85,7 @@ export default class extends Instruction {
});
// eslint-disable-next-line promise/catch-or-return
request(config)
request(config, context)
.then((response) => {
job.set({
status: JOB_STATUS.RESOLVED,