Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8d0eaa9

Browse files
authored
Merge pull request#1443 from lowcoder-org/feat/query_triggers
Feat/query triggers
2 parents4ced9ee +9ce2172 commit8d0eaa9

File tree

3 files changed

+155
-29
lines changed

3 files changed

+155
-29
lines changed

‎client/packages/lowcoder/src/comps/queries/queryComp.tsx

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,25 @@ interface AfterExecuteQueryAction {
9797
result:QueryResult;
9898
}
9999

100-
constTriggerTypeOptions=[
100+
constCommonTriggerOptions=[
101+
{label:trans("query.triggerTypeInputChange"),value:"onInputChange"},
102+
{label:trans("query.triggerTypeQueryExec"),value:"onQueryExecution"},
103+
{label:trans("query.triggerTypeTimeout"),value:"onTimeout"},
104+
]
105+
106+
exportconstTriggerTypeOptions=[
107+
{label:trans("query.triggerTypePageLoad"),value:"onPageLoad"},
108+
...CommonTriggerOptions,
101109
{label:trans("query.triggerTypeAuto"),value:"automatic"},
102110
{label:trans("query.triggerTypeManual"),value:"manual"},
103111
]asconst;
112+
113+
exportconstJSTriggerTypeOptions=[
114+
...CommonTriggerOptions,
115+
{label:trans("query.triggerTypePageLoad"),value:"automatic"},
116+
{label:trans("query.triggerTypeManual"),value:"manual"},
117+
];
118+
104119
exporttypeTriggerType=ValueFromOption<typeofTriggerTypeOptions>;
105120

106121
constEventOptions=[
@@ -151,6 +166,13 @@ const childrenMap = {
151166
},
152167
}),
153168
cancelPrevious:withDefault(BoolPureControl,false),
169+
// use only for onQueryExecution trigger
170+
depQueryName:SimpleNameComp,
171+
// use only for onTimeout trigger, triggers query after x time passed on page load
172+
delayTime:millisecondsControl({
173+
left:0,
174+
defaultValue:5*1000,
175+
})
154176
};
155177

156178
letQueryCompTmp=withTypeAndChildren<typeofQueryMap,ToInstanceType<typeofchildrenMap>>(
@@ -174,6 +196,7 @@ export type QueryChildrenType = InstanceType<typeof QueryCompTmp> extends MultiB
174196
?X
175197
:never;
176198

199+
letblockInputChangeQueries=true;
177200
/**
178201
* Logic to automatically trigger execution
179202
*/
@@ -222,11 +245,17 @@ QueryCompTmp = class extends QueryCompTmp {
222245
constisJsQuery=this.children.compType.getView()==="js";
223246
constnotExecuted=this.children.lastQueryStartTime.getView()===-1;
224247
constisAutomatic=getTriggerType(this)==="automatic";
248+
constisPageLoadTrigger=getTriggerType(this)==="onPageLoad";
249+
constisInputChangeTrigger=getTriggerType(this)==="onInputChange";
225250

226251
if(
227-
action.type===CompActionTypes.UPDATE_NODES_V2&&
228-
isAutomatic&&
229-
(!isJsQuery||(isJsQuery&&notExecuted))// query which has deps can be executed on page load(first time)
252+
action.type===CompActionTypes.UPDATE_NODES_V2
253+
&&(
254+
isAutomatic
255+
||isInputChangeTrigger
256+
||(isPageLoadTrigger&&notExecuted)
257+
)
258+
// && (!isJsQuery || (isJsQuery && notExecuted)) // query which has deps can be executed on page load(first time)
230259
){
231260
constnext=super.reduce(action);
232261
constdepends=this.children.comp.node()?.dependValues();
@@ -250,6 +279,18 @@ QueryCompTmp = class extends QueryCompTmp {
250279
constdependsChanged=!_.isEqual(preDepends,depends);
251280
constdslNotChanged=_.isEqual(preDsl,dsl);
252281

282+
if(isInputChangeTrigger&&blockInputChangeQueries&&dependsChanged){
283+
// block executing input change queries initially on page refresh
284+
setTimeout(()=>{
285+
blockInputChangeQueries=false;
286+
},500)
287+
288+
returnsetFieldsNoTypeCheck(next,{
289+
[lastDependsKey]:depends,
290+
[lastDslKey]:dsl,
291+
});
292+
}
293+
253294
// If the dsl has not changed, but the dependent node value has changed, then trigger the query execution
254295
// FIXME, this should be changed to a reference judgement, but for unknown reasons if the reference is modified once, it will change twice.
255296
if(dependsChanged){
@@ -277,24 +318,33 @@ function QueryView(props: QueryViewProps) {
277318
useEffect(()=>{
278319
// Automatically load when page load
279320
if(
280-
getTriggerType(comp)==="automatic"&&
321+
(
322+
getTriggerType(comp)==="automatic"
323+
||getTriggerType(comp)==="onPageLoad"
324+
)&&
281325
(compasany).isDepReady&&
282326
!comp.children.isNewCreate.value
283327
){
284328
setTimeout(()=>{
285329
comp.dispatch(deferAction(executeQueryAction({})));
286330
},300);
287331
}
332+
333+
if(getTriggerType(comp)==="onTimeout"){
334+
setTimeout(()=>{
335+
comp.dispatch(deferAction(executeQueryAction({})));
336+
},comp.children.delayTime.getView());
337+
}
288338
},[]);
289339

290340
useFixedDelay(
291341
()=>
292342
getPromiseAfterDispatch(comp.dispatch,executeQueryAction({}),{
293343
notHandledError:trans("query.fixedDelayError"),
294344
}),
295-
getTriggerType(comp)==="automatic"&&comp.children.periodic.getView()
296-
?comp.children.periodicTime.getView()
297-
:null
345+
getTriggerType(comp)==="automatic"&&comp.children.periodic.getView()
346+
?comp.children.periodicTime.getView()
347+
:null
298348
);
299349

300350
returnnull;
@@ -609,6 +659,29 @@ export const QueryComp = withExposingConfigs(QueryCompTmp, [
609659
constQueryListTmpComp=list(QueryComp);
610660

611661
classQueryListCompextendsQueryListTmpCompimplementsBottomResListComp{
662+
overridereduce(action:CompAction): this{
663+
if(isCustomAction<AfterExecuteQueryAction>(action,"afterExecQuery")){
664+
if(action.path?.length===1&&!isNaN(parseInt(action.path[0]))){
665+
constqueryIdx=parseInt(action.path[0]);
666+
constqueryComps=this.getView();
667+
constqueryName=queryComps?.[queryIdx]?.children.name.getView();
668+
constdependentQueries=queryComps.filter((query,idx)=>{
669+
if(queryIdx===idx)returnfalse;
670+
if(
671+
getTriggerType(query)==='onQueryExecution'
672+
&&query.children.depQueryName.getView()===queryName
673+
){
674+
returntrue;
675+
}
676+
})
677+
dependentQueries?.forEach((query)=>{
678+
query.dispatch(deferAction(executeQueryAction({})));
679+
})
680+
}
681+
}
682+
returnsuper.reduce(action);
683+
}
684+
612685
nameAndExposingInfo():NameAndExposingInfo{
613686
constresult:NameAndExposingInfo={};
614687
Object.values(this.children).forEach((comp)=>{

‎client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { useSelector } from "react-redux";
2626
import{getDataSource,getDataSourceTypes}from"redux/selectors/datasourceSelectors";
2727
import{BottomResTypeEnum}from"types/bottomRes";
2828
import{EditorContext}from"../../editorState";
29-
import{QueryComp}from"../queryComp";
29+
import{JSTriggerTypeOptions,QueryComp,TriggerType,TriggerTypeOptions}from"../queryComp";
3030
import{ResourceDropdown}from"../resourceDropdown";
3131
import{NOT_SUPPORT_GUI_SQL_QUERY,SQLQuery}from"../sqlQuery/SQLQuery";
3232
import{StreamQuery}from"../httpQuery/streamQuery";
@@ -37,6 +37,7 @@ import styled from "styled-components";
3737
import{DataSourceButton}from"pages/datasource/pluginPanel";
3838
import{Tooltip,Divider}from"antd";
3939
import{uiCompRegistry}from"comps/uiCompRegistry";
40+
import{InputTypeEnum}from"@lowcoder-ee/comps/comps/moduleContainerComp/ioComp/inputListItemComp";
4041

4142
constWrapper=styled.div`
4243
width: 100%;
@@ -226,6 +227,42 @@ export const QueryGeneralPropertyView = (props: {
226227
comp.children.datasourceId.dispatchChangeValueAction(QUICK_REST_API_ID);
227228
}
228229

230+
consttriggerOptions=useMemo(()=>{
231+
if(datasourceType==="js"||datasourceType==="streamApi"){
232+
returnJSTriggerTypeOptions;
233+
}
234+
returnTriggerTypeOptions;
235+
},[datasourceType]);
236+
237+
constgetQueryOptions=useMemo(()=>{
238+
constoptions:{label:string;value:string}[]=
239+
editorState
240+
?.queryCompInfoList()
241+
.map((info)=>({
242+
label:info.name,
243+
value:info.name,
244+
}))
245+
.filter((option)=>{
246+
// Filter out the current query under query
247+
if(editorState.selectedBottomResType===BottomResTypeEnum.Query){
248+
returnoption.value!==editorState.selectedBottomResName;
249+
}
250+
returntrue;
251+
})||[];
252+
253+
// input queries
254+
editorState
255+
?.getModuleLayoutComp()
256+
?.getInputs()
257+
.forEach((i)=>{
258+
const{ name, type}=i.getView();
259+
if(type===InputTypeEnum.Query){
260+
options.push({label:name,value:name});
261+
}
262+
});
263+
returnoptions;
264+
},[editorState]);
265+
229266
return(
230267
<QueryPropertyViewWrapper>
231268
<QuerySectionWrapper>
@@ -329,26 +366,38 @@ export const QueryGeneralPropertyView = (props: {
329366
</QueryConfigWrapper>
330367

331368
{placement==="editor"&&(
332-
<TriggerTypeStyled>
333-
<Dropdown
334-
placement={"bottom"}
335-
label={trans("query.triggerType")}
336-
options={
337-
[
338-
{
339-
label:
340-
(children.compType.getView()==="js"||children.compType.getView()==="streamApi")
341-
?trans("query.triggerTypePageLoad")
342-
:trans("query.triggerTypeAuto"),
343-
value:"automatic",
344-
},
345-
{label:trans("query.triggerTypeManual"),value:"manual"},
346-
]asconst
347-
}
348-
value={children.triggerType.getView()}
349-
onChange={(value)=>children.triggerType.dispatchChangeValueAction(value)}
350-
/>
351-
</TriggerTypeStyled>
369+
<>
370+
<TriggerTypeStyled>
371+
<Dropdown
372+
placement={"bottom"}
373+
label={trans("query.triggerType")}
374+
options={triggerOptions}
375+
value={children.triggerType.getView()}
376+
onChange={(value)=>children.triggerType.dispatchChangeValueAction(valueasTriggerType)}
377+
/>
378+
</TriggerTypeStyled>
379+
{children.triggerType.getView()==='onQueryExecution'&&(
380+
<TriggerTypeStyled>
381+
<Dropdown
382+
showSearch={true}
383+
placement={"bottom"}
384+
value={children.depQueryName.getView()}
385+
options={getQueryOptions}
386+
label={trans("eventHandler.selectQuery")}
387+
onChange={(value)=>children.depQueryName.dispatchChangeValueAction(value)}
388+
/>
389+
</TriggerTypeStyled>
390+
)}
391+
{children.triggerType.getView()==='onTimeout'&&(
392+
<TriggerTypeStyled>
393+
{children.delayTime.propertyView({
394+
label:trans("query.delayTime"),
395+
placeholder:"5s",
396+
placement:"bottom",
397+
})}
398+
</TriggerTypeStyled>
399+
)}
400+
</>
352401
)}
353402
</QuerySectionWrapper>
354403

‎client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,10 @@ export const en = {
738738
"triggerTypeAuto":"Inputs Change or On Page Load",
739739
"triggerTypePageLoad":"When the Application (Page) loads",
740740
"triggerTypeManual":"Only when you trigger it manually",
741+
"triggerTypeInputChange":"When Inputs Change",
742+
"triggerTypeQueryExec":"After Query Execution",
743+
"triggerTypeTimeout":"After the Timeout Interval",
744+
"delayTime":"Delay Time",
741745
"chooseDataSource":"Choose Data Source",
742746
"method":"Method",
743747
"updateExceptionDataSourceTitle":"Update Failing Data Source",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp