feat: filter with variable (#574)
This commit is contained in:
parent
ec7bc2bc8b
commit
e3b6c0513a
@ -1,12 +1,12 @@
|
||||
import { Action } from '@nocobase/resourcer';
|
||||
import EventEmitter from 'events';
|
||||
import parse from 'json-templates';
|
||||
import compose from 'koa-compose';
|
||||
import lodash from 'lodash';
|
||||
import { AclAvailableAction, AvailableActionOptions } from './acl-available-action';
|
||||
import { ACLAvailableStrategy, AvailableStrategyOptions, predicate } from './acl-available-strategy';
|
||||
import { ACLRole, RoleActionParams } from './acl-role';
|
||||
import { AllowManager } from './allow-manager';
|
||||
const parse = require('json-templates');
|
||||
|
||||
interface CanResult {
|
||||
role: string;
|
||||
|
@ -70,6 +70,14 @@ export const number = [
|
||||
export const id = [
|
||||
{ label: '{{t("is")}}', value: '$eq', selected: true },
|
||||
{ label: '{{t("is not")}}', value: '$ne' },
|
||||
{
|
||||
label: '{{t("is variable")}}',
|
||||
value: '$isVar',
|
||||
schema: {
|
||||
'x-component': 'VariableCascader',
|
||||
'x-component-props': {},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '{{t("is current logged-in user")}}',
|
||||
value: '$isCurrentUser',
|
||||
|
@ -1,10 +1,52 @@
|
||||
import { createForm, onFieldValueChange } from '@formily/core';
|
||||
import { FieldContext, FormContext } from '@formily/react';
|
||||
import { connect, FieldContext, FormContext } from '@formily/react';
|
||||
import { merge } from '@formily/shared';
|
||||
import { Cascader } from 'antd';
|
||||
import React, { useContext, useMemo } from 'react';
|
||||
import { SchemaComponent } from '../../core';
|
||||
import { useComponent } from '../../hooks';
|
||||
import { useCompile, useComponent } from '../../hooks';
|
||||
import { FilterContext } from './context';
|
||||
import { useFilterOptions } from './useFilterActionProps';
|
||||
|
||||
const VariableCascader = connect((props) => {
|
||||
const fields = useFilterOptions('users');
|
||||
const compile = useCompile();
|
||||
const { value, onChange } = props;
|
||||
return (
|
||||
<Cascader
|
||||
value={value ? value.split('.') : []}
|
||||
fieldNames={{
|
||||
label: 'title',
|
||||
value: 'name',
|
||||
children: 'children',
|
||||
}}
|
||||
onChange={(value) => {
|
||||
onChange(value ? value.join('.') : null);
|
||||
}}
|
||||
options={compile([
|
||||
{
|
||||
title: '{{t("Current user")}}',
|
||||
name: 'currentUser',
|
||||
children: fields
|
||||
.filter((field) => {
|
||||
if (!field.target) {
|
||||
return true;
|
||||
}
|
||||
return field.type === 'belongsTo';
|
||||
})
|
||||
.map((field) => {
|
||||
if (field.children) {
|
||||
field.children = field.children.filter((child) => {
|
||||
return !child.target;
|
||||
});
|
||||
}
|
||||
return field;
|
||||
}),
|
||||
},
|
||||
])}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const DynamicComponent = (props) => {
|
||||
const { dynamicComponent } = useContext(FilterContext);
|
||||
@ -38,6 +80,9 @@ export const DynamicComponent = (props) => {
|
||||
'x-validator': undefined,
|
||||
'x-decorator': undefined,
|
||||
}}
|
||||
components={{
|
||||
VariableCascader,
|
||||
}}
|
||||
/>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
|
@ -24,6 +24,8 @@ export const useFilterOptions = (collectionName: string) => {
|
||||
const { nested, children, operators } = fieldInterface.filterable;
|
||||
const option = {
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
target: field.target,
|
||||
title: field?.uiSchema?.title || field.name,
|
||||
schema: field?.uiSchema,
|
||||
operators:
|
||||
|
@ -14,7 +14,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/test": "0.7.1-alpha.7",
|
||||
"@types/jsonwebtoken": "^8.5.8"
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"json-templates": "^4.2.0"
|
||||
},
|
||||
"gitHead": "7e9556e489007577fc0ed89063b3a9ce2f9aae53"
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ export function parseToken(options?: { plugin: UsersPlugin }) {
|
||||
return async function parseToken(ctx: Context, next: Next) {
|
||||
const user = await findUserByToken(ctx, options.plugin);
|
||||
if (user) {
|
||||
console.log('appends', user.toJSON());
|
||||
ctx.state.currentUser = user;
|
||||
setCurrentRole(ctx);
|
||||
}
|
||||
@ -45,12 +46,18 @@ async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
||||
|
||||
try {
|
||||
const { userId } = await plugin.jwtService.decode(token);
|
||||
|
||||
const collection = ctx.db.getCollection('users');
|
||||
const appends = ['roles'];
|
||||
for (const [, field] of collection.fields) {
|
||||
if (field.type === 'belongsTo') {
|
||||
appends.push(field.name);
|
||||
}
|
||||
}
|
||||
return await ctx.db.getRepository('users').findOne({
|
||||
appends,
|
||||
filter: {
|
||||
id: userId,
|
||||
},
|
||||
appends: ['roles'],
|
||||
});
|
||||
} catch (error) {
|
||||
return null;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Collection, Op } from '@nocobase/database';
|
||||
import { Plugin } from '@nocobase/server';
|
||||
import parse from 'json-templates';
|
||||
import { resolve } from 'path';
|
||||
import { namespace } from './';
|
||||
import * as actions from './actions/users';
|
||||
@ -35,6 +36,12 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
||||
[Op.eq]: ctx?.app?.ctx?.state?.currentUser?.id || -1,
|
||||
};
|
||||
},
|
||||
$isVar(val, ctx) {
|
||||
const obj = parse({ val: `{{${val}}}` })(JSON.parse(JSON.stringify(ctx?.app?.ctx?.state)));
|
||||
return {
|
||||
[Op.eq]: obj.val,
|
||||
};
|
||||
},
|
||||
});
|
||||
this.db.registerModels({ UserModel });
|
||||
this.db.on('users.afterCreateWithAssociations', async (model, options) => {
|
||||
|
Loading…
Reference in New Issue
Block a user