diff --git a/client/packages/lowcoder/src/comps/queries/queryComp.tsx b/client/packages/lowcoder/src/comps/queries/queryComp.tsx index 1937bf289f..e90bf8d195 100644 --- a/client/packages/lowcoder/src/comps/queries/queryComp.tsx +++ b/client/packages/lowcoder/src/comps/queries/queryComp.tsx @@ -97,10 +97,25 @@ interface AfterExecuteQueryAction { result: QueryResult; } -const TriggerTypeOptions = [ +const CommonTriggerOptions = [ + { label: trans("query.triggerTypeInputChange"), value: "onInputChange"}, + { label: trans("query.triggerTypeQueryExec"), value: "onQueryExecution"}, + { label: trans("query.triggerTypeTimeout"), value: "onTimeout"}, +] + +export const TriggerTypeOptions = [ + { label: trans("query.triggerTypePageLoad"), value: "onPageLoad"}, + ...CommonTriggerOptions, { label: trans("query.triggerTypeAuto"), value: "automatic" }, { label: trans("query.triggerTypeManual"), value: "manual" }, ] as const; + +export const JSTriggerTypeOptions = [ + ...CommonTriggerOptions, + { label: trans("query.triggerTypePageLoad"), value: "automatic" }, + { label: trans("query.triggerTypeManual"), value: "manual" }, +]; + export type TriggerType = ValueFromOption; const EventOptions = [ @@ -151,6 +166,13 @@ const childrenMap = { }, }), cancelPrevious: withDefault(BoolPureControl, false), + // use only for onQueryExecution trigger + depQueryName: SimpleNameComp, + // use only for onTimeout trigger, triggers query after x time passed on page load + delayTime: millisecondsControl({ + left: 0, + defaultValue: 5 * 1000, + }) }; let QueryCompTmp = withTypeAndChildren>( @@ -174,6 +196,7 @@ export type QueryChildrenType = InstanceType extends MultiB ? X : never; +let blockInputChangeQueries = true; /** * Logic to automatically trigger execution */ @@ -222,11 +245,17 @@ QueryCompTmp = class extends QueryCompTmp { const isJsQuery = this.children.compType.getView() === "js"; const notExecuted = this.children.lastQueryStartTime.getView() === -1; const isAutomatic = getTriggerType(this) === "automatic"; + const isPageLoadTrigger = getTriggerType(this) === "onPageLoad"; + const isInputChangeTrigger = getTriggerType(this) === "onInputChange"; if ( - action.type === CompActionTypes.UPDATE_NODES_V2 && - isAutomatic && - (!isJsQuery || (isJsQuery && notExecuted)) // query which has deps can be executed on page load(first time) + action.type === CompActionTypes.UPDATE_NODES_V2 + && ( + isAutomatic + || isInputChangeTrigger + || (isPageLoadTrigger && notExecuted) + ) + // && (!isJsQuery || (isJsQuery && notExecuted)) // query which has deps can be executed on page load(first time) ) { const next = super.reduce(action); const depends = this.children.comp.node()?.dependValues(); @@ -250,6 +279,18 @@ QueryCompTmp = class extends QueryCompTmp { const dependsChanged = !_.isEqual(preDepends, depends); const dslNotChanged = _.isEqual(preDsl, dsl); + if(isInputChangeTrigger && blockInputChangeQueries && dependsChanged) { + // block executing input change queries initially on page refresh + setTimeout(() => { + blockInputChangeQueries = false; + }, 500) + + return setFieldsNoTypeCheck(next, { + [lastDependsKey]: depends, + [lastDslKey]: dsl, + }); + } + // If the dsl has not changed, but the dependent node value has changed, then trigger the query execution // FIXME, this should be changed to a reference judgement, but for unknown reasons if the reference is modified once, it will change twice. if (dependsChanged) { @@ -277,7 +318,10 @@ function QueryView(props: QueryViewProps) { useEffect(() => { // Automatically load when page load if ( - getTriggerType(comp) === "automatic" && + ( + getTriggerType(comp) === "automatic" + || getTriggerType(comp) === "onPageLoad" + ) && (comp as any).isDepReady && !comp.children.isNewCreate.value ) { @@ -285,6 +329,12 @@ function QueryView(props: QueryViewProps) { comp.dispatch(deferAction(executeQueryAction({}))); }, 300); } + + if(getTriggerType(comp) === "onTimeout") { + setTimeout(() => { + comp.dispatch(deferAction(executeQueryAction({}))); + }, comp.children.delayTime.getView()); + } }, []); useFixedDelay( @@ -292,9 +342,9 @@ function QueryView(props: QueryViewProps) { getPromiseAfterDispatch(comp.dispatch, executeQueryAction({}), { notHandledError: trans("query.fixedDelayError"), }), - getTriggerType(comp) === "automatic" && comp.children.periodic.getView() - ? comp.children.periodicTime.getView() - : null + getTriggerType(comp) === "automatic" && comp.children.periodic.getView() + ? comp.children.periodicTime.getView() + : null ); return null; @@ -609,6 +659,29 @@ export const QueryComp = withExposingConfigs(QueryCompTmp, [ const QueryListTmpComp = list(QueryComp); class QueryListComp extends QueryListTmpComp implements BottomResListComp { + override reduce(action: CompAction): this { + if (isCustomAction(action, "afterExecQuery")) { + if (action.path?.length === 1 && !isNaN(parseInt(action.path[0]))) { + const queryIdx = parseInt(action.path[0]); + const queryComps = this.getView(); + const queryName = queryComps?.[queryIdx]?.children.name.getView(); + const dependentQueries = queryComps.filter((query, idx) => { + if (queryIdx === idx) return false; + if ( + getTriggerType(query) === 'onQueryExecution' + && query.children.depQueryName.getView() === queryName + ) { + return true; + } + }) + dependentQueries?.forEach((query) => { + query.dispatch(deferAction(executeQueryAction({}))); + }) + } + } + return super.reduce(action); + } + nameAndExposingInfo(): NameAndExposingInfo { const result: NameAndExposingInfo = {}; Object.values(this.children).forEach((comp) => { diff --git a/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx b/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx index 910365185c..07f4ef1e04 100644 --- a/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx +++ b/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx @@ -26,7 +26,7 @@ import { useSelector } from "react-redux"; import { getDataSource, getDataSourceTypes } from "redux/selectors/datasourceSelectors"; import { BottomResTypeEnum } from "types/bottomRes"; import { EditorContext } from "../../editorState"; -import { QueryComp } from "../queryComp"; +import { JSTriggerTypeOptions, QueryComp, TriggerType, TriggerTypeOptions } from "../queryComp"; import { ResourceDropdown } from "../resourceDropdown"; import { NOT_SUPPORT_GUI_SQL_QUERY, SQLQuery } from "../sqlQuery/SQLQuery"; import { StreamQuery } from "../httpQuery/streamQuery"; @@ -37,6 +37,7 @@ import styled from "styled-components"; import { DataSourceButton } from "pages/datasource/pluginPanel"; import { Tooltip, Divider } from "antd"; import { uiCompRegistry } from "comps/uiCompRegistry"; +import { InputTypeEnum } from "@lowcoder-ee/comps/comps/moduleContainerComp/ioComp/inputListItemComp"; const Wrapper = styled.div` width: 100%; @@ -226,6 +227,42 @@ export const QueryGeneralPropertyView = (props: { comp.children.datasourceId.dispatchChangeValueAction(QUICK_REST_API_ID); } + const triggerOptions = useMemo(() => { + if (datasourceType === "js" || datasourceType === "streamApi") { + return JSTriggerTypeOptions; + } + return TriggerTypeOptions; + }, [datasourceType]); + + const getQueryOptions = useMemo(() => { + const options: { label: string; value: string }[] = + editorState + ?.queryCompInfoList() + .map((info) => ({ + label: info.name, + value: info.name, + })) + .filter((option) => { + // Filter out the current query under query + if (editorState.selectedBottomResType === BottomResTypeEnum.Query) { + return option.value !== editorState.selectedBottomResName; + } + return true; + }) || []; + + // input queries + editorState + ?.getModuleLayoutComp() + ?.getInputs() + .forEach((i) => { + const { name, type } = i.getView(); + if (type === InputTypeEnum.Query) { + options.push({ label: name, value: name }); + } + }); + return options; + }, [editorState]); + return ( @@ -329,26 +366,38 @@ export const QueryGeneralPropertyView = (props: { {placement === "editor" && ( - - children.triggerType.dispatchChangeValueAction(value)} - /> - + <> + + children.triggerType.dispatchChangeValueAction(value as TriggerType)} + /> + + {children.triggerType.getView() === 'onQueryExecution' && ( + + children.depQueryName.dispatchChangeValueAction(value)} + /> + + )} + {children.triggerType.getView() === 'onTimeout' && ( + + {children.delayTime.propertyView({ + label: trans("query.delayTime"), + placeholder: "5s", + placement: "bottom", + })} + + )} + )} diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index baef755e83..be0378e20c 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -738,6 +738,10 @@ export const en = { "triggerTypeAuto": "Inputs Change or On Page Load", "triggerTypePageLoad": "When the Application (Page) loads", "triggerTypeManual": "Only when you trigger it manually", + "triggerTypeInputChange": "When Inputs Change", + "triggerTypeQueryExec": "After Query Execution", + "triggerTypeTimeout": "After the Timeout Interval", + "delayTime": "Delay Time", "chooseDataSource": "Choose Data Source", "method": "Method", "updateExceptionDataSourceTitle": "Update Failing Data Source", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy