From c95de3f523f444101edad353ebcdfeb6a3bd381f Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:56:25 +0200 Subject: [PATCH 01/18] wip: preventing ddl and dml statements from autosubmiting --- .../dashboards/components/InfluxQLEditor.tsx | 18 +++++++------ ui/src/shared/apis/query.ts | 25 +++++++++++-------- .../TimeMachine/InfluxQLQueryMaker.tsx | 2 +- .../components/TimeMachine/TimeMachine.tsx | 4 +-- .../components/time_series/TimeSeries.tsx | 12 ++++----- ui/src/shared/utils/TimeMachineContainer.ts | 5 ++-- ui/src/types/queries.ts | 1 + ui/src/utils/queryFilter.ts | 5 ++++ ui/src/worker/jobs/proxy.ts | 2 +- 9 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 ui/src/utils/queryFilter.ts diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index f787211e1e..bba13c3322 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -26,6 +26,7 @@ import { MetaQueryTemplateOption, DropdownChildTypes, } from 'src/data_explorer/constants' +import {isExcludedStatement} from '../../utils/queryFilter' interface TempVar { tempVar: string @@ -45,7 +46,7 @@ interface State { interface Props { query: string - onUpdate: (text: string) => Promise + onUpdate: (text: string, isAutoSubmitted: boolean) => Promise config: QueryConfig templates: Template[] onMetaQuerySelected: () => void @@ -105,6 +106,7 @@ class InfluxQLEditor extends Component { isSubmitted: true, configID: props.config.id, } + console.log('Constructor: isSubmitted', this.state.isSubmitted) } public componentWillUnmount() { @@ -199,8 +201,9 @@ class InfluxQLEditor extends Component { } private handleBlurEditor = (): void => { + console.log('handleBlurEditor') this.setState({focused: false, isShowingTemplateValues: false}) - this.handleUpdate() + this.handleUpdate(true) } private handleCloseDrawer = (): void => { @@ -234,6 +237,7 @@ class InfluxQLEditor extends Component { const {templates, query} = this.props const isEditedChanged = value !== this.state.editedQueryText const isSubmitted = value.trim() === query.trim() + console.log('handleChange: isSubmitted', isSubmitted) if (!isEditedChanged || this.state.isShowingTemplateValues) { return @@ -271,23 +275,23 @@ class InfluxQLEditor extends Component { } } - private handleUpdate = async (): Promise => { + private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { const {onUpdate} = this.props if (!this.isDisabled && !this.state.isSubmitted) { const {editedQueryText} = this.state this.cancelPendingUpdates() - const update = onUpdate(editedQueryText) + const update = onUpdate(editedQueryText, isAutoSubmitted) const cancelableUpdate = makeCancelable(update) this.pendingUpdates = [...this.pendingUpdates, cancelableUpdate] try { await cancelableUpdate.promise - // prevent changing submitted status when edited while awaiting update - if (this.state.editedQueryText === editedQueryText) { + if (this.state.editedQueryText === editedQueryText && (!isAutoSubmitted || !isExcludedStatement(editedQueryText))) { this.setState({isSubmitted: true}) + console.log('handleUpdate: set isSubmitted true') } } catch (error) { if (!error.isCanceled) { @@ -443,7 +447,7 @@ class InfluxQLEditor extends Component { size={ComponentSize.ExtraSmall} color={ComponentColor.Primary} status={this.isDisabled && ComponentStatus.Disabled} - onClick={this.handleUpdate} + onClick={() => this.handleUpdate()} text="Submit Query" /> diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 17937f2590..1c5de28ef2 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -4,17 +4,18 @@ import {TEMP_VAR_INTERVAL, DEFAULT_DURATION_MS} from 'src/shared/constants' import replaceTemplates, {replaceInterval} from 'src/tempVars/utils/replace' import {proxy} from 'src/utils/queryUrlGenerator' -import {Source, Template} from 'src/types' +import {Query, Source, Template} from 'src/types' import {TimeSeriesResponse} from 'src/types/series' +import {isExcludedStatement} from '../../utils/queryFilter' // REVIEW: why is this different than the `Query` in src/types? -interface Query { - text: string - id: string - database?: string - db?: string - rp?: string -} +// interface Query { +// text: string +// id: string +// database?: string +// db?: string +// rp?: string +// } interface QueryResult { value: TimeSeriesResponse | null @@ -33,6 +34,10 @@ export function executeQueries( let counter = queries.length for (let i = 0; i < queries.length; i++) { + if(isExcludedStatement(queries[i].text) && !queries[i].queryConfig.isSubmitted) { + counter -= 1 + continue + } executeQuery(source, queries[i], templates, uuid) .then(result => (results[i] = {value: result, error: null})) .catch(result => (results[i] = {value: null, error: result})) @@ -58,9 +63,9 @@ export const executeQuery = async ( const {data} = await proxy({ source: source.links.proxy, - rp: query.rp, + rp: query.queryConfig.retentionPolicy, query: text, - db: query.db || query.database, + db: query.queryConfig.database, uuid, }) diff --git a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx index 8e46e9098f..c648a251f7 100644 --- a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx +++ b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx @@ -50,7 +50,7 @@ interface PassedProps { templates: Template[] onAddQuery: () => void onDeleteQuery: (index: number) => void - onEditRawText: (text: string) => Promise + onEditRawText: (text: string, isAutoSubmitted: boolean) => Promise onMetaQuerySelected: () => void } diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index 6a71a19b1f..01de343595 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -420,7 +420,7 @@ class TimeMachine extends PureComponent { return getDeep(queryDrafts, '0.source', '') === '' } - private handleEditRawText = async (text: string): Promise => { + private handleEditRawText = async (text: string, isAutoSubmitted: boolean): Promise => { const {templates, onUpdateQueryDrafts, queryDrafts, notify} = this.props const activeID = this.activeQuery.id const url: string = _.get(this.source, 'links.queries', '') @@ -429,6 +429,7 @@ class TimeMachine extends PureComponent { try { newQueryConfig = await getConfig(url, activeID, text, templates) + newQueryConfig.isSubmitted = !isAutoSubmitted } catch { notify(analyzeQueryFailed) return @@ -450,7 +451,6 @@ class TimeMachine extends PureComponent { }, } }) - onUpdateQueryDrafts(updatedQueryDrafts) } diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 8432cd5df7..04426f780e 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -140,12 +140,12 @@ class TimeSeries extends PureComponent { const timeRangeChanged = oldLower !== newLower || oldUpper !== newUpper const shouldExecuteQueries = - queriesDifferent || - timeRangeChanged || - templatesDifferent || - this.props.uuid !== prevProps.uuid || - this.state.fetchCount === 0 || - this.props.xPixels !== prevProps.xPixels + queriesDifferent || + timeRangeChanged || + templatesDifferent || + this.props.uuid !== prevProps.uuid || + this.state.fetchCount === 0 || + this.props.xPixels !== prevProps.xPixels if (shouldExecuteQueries) { this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) diff --git a/ui/src/shared/utils/TimeMachineContainer.ts b/ui/src/shared/utils/TimeMachineContainer.ts index b7f7e6c9a1..afafab23b5 100644 --- a/ui/src/shared/utils/TimeMachineContainer.ts +++ b/ui/src/shared/utils/TimeMachineContainer.ts @@ -27,6 +27,7 @@ import { setLocalStorage, TMLocalStorageKey, } from 'src/shared/utils/timeMachine' +import {isExcludedStatement} from '../../utils/queryFilter' // Constants import {TYPE_QUERY_CONFIG} from 'src/dashboards/constants' @@ -161,8 +162,8 @@ export class TimeMachineContainer { const queries = query.split(';') let isSavable = true for (let i = 0; i <= queries.length; i++) { - const qs = getDeep(queries, `${i}`, '').toLocaleLowerCase() - if (qs.startsWith('drop') || qs.startsWith('delete')) { + const qs = getDeep(queries, `${i}`, '') + if (isExcludedStatement(qs)) { isSavable = false } } diff --git a/ui/src/types/queries.ts b/ui/src/types/queries.ts index 229f4a56df..7c3560090c 100644 --- a/ui/src/types/queries.ts +++ b/ui/src/types/queries.ts @@ -26,6 +26,7 @@ export interface QueryConfig { lower?: string upper?: string isQuerySupportedByExplorer?: boolean // doesn't come from server -- is set in CellEditorOverlay + isSubmitted?: boolean // doesn't come from server -- is set in InfluxQLEditor originalQuery?: string } diff --git a/ui/src/utils/queryFilter.ts b/ui/src/utils/queryFilter.ts new file mode 100644 index 0000000000..86c7a24974 --- /dev/null +++ b/ui/src/utils/queryFilter.ts @@ -0,0 +1,5 @@ +const excludedStatements: string[] = ['drop', 'delete', 'alter','create','update','insert'] + +export const isExcludedStatement = (query: string): boolean => { + return excludedStatements.some((statement) => query.toLowerCase().startsWith(statement)) +} diff --git a/ui/src/worker/jobs/proxy.ts b/ui/src/worker/jobs/proxy.ts index 827ad1499c..d99720a51d 100644 --- a/ui/src/worker/jobs/proxy.ts +++ b/ui/src/worker/jobs/proxy.ts @@ -11,7 +11,7 @@ const proxy = async (msg: ProxyMsg): Promise<{data: any}> => { const { payload: {url, query, rp, db, uuid}, } = msg - + console.log('proxy', url, query) const body = {url, query, rp, db, uuid} try { const response = await fetch(url, { From 5b3fb4ac774296ead3bb414896fb0e49a91ba6c3 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:28:49 +0200 Subject: [PATCH 02/18] chore: prepare distinguishing tabs --- ui/.eslintrc | 2 +- .../dashboards/components/InfluxQLEditor.tsx | 29 +++++++++++++------ ui/src/shared/apis/query.ts | 6 +++- .../TimeMachine/InfluxQLQueryMaker.tsx | 1 + .../components/TimeMachine/TimeMachine.tsx | 5 +++- .../components/time_series/TimeSeries.tsx | 12 ++++---- ui/src/utils/queryFilter.ts | 13 +++++++-- 7 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ui/.eslintrc b/ui/.eslintrc index f0f03fdcbc..a82d933809 100644 --- a/ui/.eslintrc +++ b/ui/.eslintrc @@ -182,7 +182,7 @@ "SwitchCase": 1 } ], - "linebreak-style": [2, "unix"], + "linebreak-style": 0, "lines-around-comment": 0, "max-depth": 0, "max-len": 0, diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index bba13c3322..e638a209cb 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -50,6 +50,7 @@ interface Props { config: QueryConfig templates: Template[] onMetaQuerySelected: () => void + activeQueryIndex: number } const FIRST_TEMP_VAR = '0.tempVar' @@ -65,7 +66,9 @@ const TEMPLATE_VAR = /[:]\w+[:]/g class InfluxQLEditor extends Component { public static getDerivedStateFromProps(nextProps: Props, prevState: State) { const {isSubmitted, editedQueryText} = prevState - + console.log( + `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}` + ) const isQueryConfigChanged = nextProps.config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== nextProps.query.trim() @@ -106,7 +109,9 @@ class InfluxQLEditor extends Component { isSubmitted: true, configID: props.config.id, } - console.log('Constructor: isSubmitted', this.state.isSubmitted) + console.log( + `Constructor: ${props.activeQueryIndex}, isSubmitted ${this.state.isSubmitted}` + ) } public componentWillUnmount() { @@ -201,7 +206,9 @@ class InfluxQLEditor extends Component { } private handleBlurEditor = (): void => { - console.log('handleBlurEditor') + console.log( + `handleBlurEditor: ${this.props.activeQueryIndex}, isSubmitted: ${this.state.isSubmitted}` + ) this.setState({focused: false, isShowingTemplateValues: false}) this.handleUpdate(true) } @@ -234,10 +241,10 @@ class InfluxQLEditor extends Component { } private handleChange = (value: string): void => { - const {templates, query} = this.props + const {templates, query, activeQueryIndex} = this.props const isEditedChanged = value !== this.state.editedQueryText const isSubmitted = value.trim() === query.trim() - console.log('handleChange: isSubmitted', isSubmitted) + console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}`) if (!isEditedChanged || this.state.isShowingTemplateValues) { return @@ -249,7 +256,7 @@ class InfluxQLEditor extends Component { const isTemplating = matched && !_.isEmpty(templates) if (isTemplating) { - // maintain cursor poition + // maintain cursor position const matchedVar = {tempVar: `${matched[0]}:`} const filteredTemplates = this.filterTemplates(matched[0]) const selectedTemplate = this.selectMatchingTemplate( @@ -276,7 +283,7 @@ class InfluxQLEditor extends Component { } private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { - const {onUpdate} = this.props + const {onUpdate, activeQueryIndex} = this.props if (!this.isDisabled && !this.state.isSubmitted) { const {editedQueryText} = this.state @@ -289,9 +296,13 @@ class InfluxQLEditor extends Component { try { await cancelableUpdate.promise // prevent changing submitted status when edited while awaiting update - if (this.state.editedQueryText === editedQueryText && (!isAutoSubmitted || !isExcludedStatement(editedQueryText))) { + if ( + this.state.editedQueryText === editedQueryText && + ((!isAutoSubmitted && isExcludedStatement(editedQueryText)) || + !isExcludedStatement(editedQueryText)) + ) { this.setState({isSubmitted: true}) - console.log('handleUpdate: set isSubmitted true') + console.log(`handleUpdate: ${activeQueryIndex}, set isSubmitted true`) } } catch (error) { if (!error.isCanceled) { diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 1c5de28ef2..7c0c11c529 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -34,7 +34,11 @@ export function executeQueries( let counter = queries.length for (let i = 0; i < queries.length; i++) { - if(isExcludedStatement(queries[i].text) && !queries[i].queryConfig.isSubmitted) { + if ( + isExcludedStatement(queries[i].text) && + !queries[i].queryConfig.isSubmitted + ) { + results[i] = {value: null, error: 'skipped'} counter -= 1 continue } diff --git a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx index c648a251f7..81a4f37882 100644 --- a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx +++ b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx @@ -107,6 +107,7 @@ const QueryMaker: FunctionComponent = ({ onUpdate={onEditRawText} templates={templates} onMetaQuerySelected={onMetaQuerySelected} + activeQueryIndex={activeQueryIndex} /> { return getDeep(queryDrafts, '0.source', '') === '' } - private handleEditRawText = async (text: string, isAutoSubmitted: boolean): Promise => { + private handleEditRawText = async ( + text: string, + isAutoSubmitted: boolean + ): Promise => { const {templates, onUpdateQueryDrafts, queryDrafts, notify} = this.props const activeID = this.activeQuery.id const url: string = _.get(this.source, 'links.queries', '') diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 04426f780e..8432cd5df7 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -140,12 +140,12 @@ class TimeSeries extends PureComponent { const timeRangeChanged = oldLower !== newLower || oldUpper !== newUpper const shouldExecuteQueries = - queriesDifferent || - timeRangeChanged || - templatesDifferent || - this.props.uuid !== prevProps.uuid || - this.state.fetchCount === 0 || - this.props.xPixels !== prevProps.xPixels + queriesDifferent || + timeRangeChanged || + templatesDifferent || + this.props.uuid !== prevProps.uuid || + this.state.fetchCount === 0 || + this.props.xPixels !== prevProps.xPixels if (shouldExecuteQueries) { this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) diff --git a/ui/src/utils/queryFilter.ts b/ui/src/utils/queryFilter.ts index 86c7a24974..5b3e4d53f7 100644 --- a/ui/src/utils/queryFilter.ts +++ b/ui/src/utils/queryFilter.ts @@ -1,5 +1,14 @@ -const excludedStatements: string[] = ['drop', 'delete', 'alter','create','update','insert'] +const excludedStatements: string[] = [ + 'drop', + 'delete', + 'alter', + 'create', + 'update', + 'insert', +] export const isExcludedStatement = (query: string): boolean => { - return excludedStatements.some((statement) => query.toLowerCase().startsWith(statement)) + return excludedStatements.some(statement => + query.toLowerCase().startsWith(statement) + ) } From 61710bb0d4f266607964f5e7bcc9cdbfa6c518b9 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:32:49 +0200 Subject: [PATCH 03/18] fix: don't use deprecated image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b2c7185406..cbc94d80c8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,7 +75,7 @@ jobs: DOCKER_TAG: chronograf-20240710 GO111MODULE: "ON" machine: - image: ubuntu-2004:202201-02 + image: default steps: - checkout - run: | From f122302c230778238e194f9704e690309b92f98d Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 8 Oct 2024 15:47:23 +0200 Subject: [PATCH 04/18] fix: distinguish submitting state between tabs --- .../dashboards/components/InfluxQLEditor.tsx | 38 ++++++++++++------- ui/src/shared/utils/TimeMachineContainer.ts | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index e638a209cb..7125dc79dc 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -40,7 +40,7 @@ interface State { selectedTemplate: TempVar isShowingTemplateValues: boolean filteredTemplates: Template[] - isSubmitted: boolean + submitted: Map configID: string } @@ -65,9 +65,10 @@ const TEMPLATE_VAR = /[:]\w+[:]/g class InfluxQLEditor extends Component { public static getDerivedStateFromProps(nextProps: Props, prevState: State) { - const {isSubmitted, editedQueryText} = prevState + const {submitted, editedQueryText} = prevState + const isSubmitted = submitted.get(nextProps.activeQueryIndex)??true console.log( - `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}` + `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}, editedQueryText: ${editedQueryText}, query: ${nextProps.query}` ) const isQueryConfigChanged = nextProps.config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== nextProps.query.trim() @@ -106,11 +107,11 @@ class InfluxQLEditor extends Component { filteredTemplates: props.templates, templatingQueryText: props.query, editedQueryText: props.query, - isSubmitted: true, configID: props.config.id, + submitted: new Map(), } console.log( - `Constructor: ${props.activeQueryIndex}, isSubmitted ${this.state.isSubmitted}` + `Constructor: ${props.activeQueryIndex}, isSubmitted ${this.state.submitted}` ) } @@ -132,9 +133,10 @@ class InfluxQLEditor extends Component { filteredTemplates, isShowingTemplateValues, focused, - isSubmitted, + submitted, } = this.state + const isSubmitted = submitted.get(this.props.activeQueryIndex)??true return (
{this.dismissPreviewButton} @@ -206,8 +208,9 @@ class InfluxQLEditor extends Component { } private handleBlurEditor = (): void => { + const isSubmitted = this.state.submitted.get(this.props.activeQueryIndex)??true console.log( - `handleBlurEditor: ${this.props.activeQueryIndex}, isSubmitted: ${this.state.isSubmitted}` + `handleBlurEditor: ${this.props.activeQueryIndex}, isSubmitted: ${isSubmitted}` ) this.setState({focused: false, isShowingTemplateValues: false}) this.handleUpdate(true) @@ -242,9 +245,11 @@ class InfluxQLEditor extends Component { private handleChange = (value: string): void => { const {templates, query, activeQueryIndex} = this.props + //const {templates, activeQueryIndex} = this.props const isEditedChanged = value !== this.state.editedQueryText const isSubmitted = value.trim() === query.trim() - console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}`) + const isSubmittedState = this.state.submitted.get(activeQueryIndex)??true + console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}`) if (!isEditedChanged || this.state.isShowingTemplateValues) { return @@ -270,22 +275,29 @@ class InfluxQLEditor extends Component { selectedTemplate, filteredTemplates, editedQueryText: value, - isSubmitted, + submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) }) } else { this.setState({ isTemplating, templatingQueryText: value, editedQueryText: value, - isSubmitted, + submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) }) } + //this.setSubmitted(isSubmitted) + } + + private setSubmitted = (isSubmitted: boolean): void => { + const {activeQueryIndex} = this.props + console.log(`setSubmitted: ${activeQueryIndex}, isSubmitted ${isSubmitted}`) + this.setState({submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted)}) } private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { const {onUpdate, activeQueryIndex} = this.props - - if (!this.isDisabled && !this.state.isSubmitted) { + const isSubmitted = this.state.submitted.get(activeQueryIndex)??true + if (!this.isDisabled && !isSubmitted) { const {editedQueryText} = this.state this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) @@ -301,7 +313,7 @@ class InfluxQLEditor extends Component { ((!isAutoSubmitted && isExcludedStatement(editedQueryText)) || !isExcludedStatement(editedQueryText)) ) { - this.setState({isSubmitted: true}) + this.setSubmitted(true) console.log(`handleUpdate: ${activeQueryIndex}, set isSubmitted true`) } } catch (error) { diff --git a/ui/src/shared/utils/TimeMachineContainer.ts b/ui/src/shared/utils/TimeMachineContainer.ts index afafab23b5..9174189d64 100644 --- a/ui/src/shared/utils/TimeMachineContainer.ts +++ b/ui/src/shared/utils/TimeMachineContainer.ts @@ -148,7 +148,7 @@ export class TimeMachineContainer { state = {...state, queryDrafts} } - // prevents "DROP" or "DELETE" queries from being persisted. + // prevents DDL and DML statements from being persisted. const savable = getDeep(state, 'queryDrafts', []).filter( ({query, type}) => { if (type !== 'influxql') { From 42332aa5147611ba31c5850a474ba87fda0cae96 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:22:34 +0200 Subject: [PATCH 05/18] chore: more logs, better naming --- ui/src/dashboards/components/InfluxQLEditor.tsx | 7 ++++--- ui/src/shared/apis/query.ts | 3 ++- ui/src/shared/components/TimeMachine/TimeMachine.tsx | 2 +- ui/src/types/queries.ts | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 7125dc79dc..05c6d703c7 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -68,7 +68,7 @@ class InfluxQLEditor extends Component { const {submitted, editedQueryText} = prevState const isSubmitted = submitted.get(nextProps.activeQueryIndex)??true console.log( - `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}, editedQueryText: ${editedQueryText}, query: ${nextProps.query}` + `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}, editedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${nextProps.query.substring(0, Math.min(nextProps.query.length, 20))}` ) const isQueryConfigChanged = nextProps.config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== nextProps.query.trim() @@ -247,9 +247,10 @@ class InfluxQLEditor extends Component { const {templates, query, activeQueryIndex} = this.props //const {templates, activeQueryIndex} = this.props const isEditedChanged = value !== this.state.editedQueryText - const isSubmitted = value.trim() === query.trim() const isSubmittedState = this.state.submitted.get(activeQueryIndex)??true - console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}`) + //const isSubmitted = isExcludedStatement(value)? isSubmittedState :value.trim() === query.trim() + const isSubmitted = value.trim() === query.trim() + console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}, isEditedChanged: ${isEditedChanged}`) if (!isEditedChanged || this.state.isShowingTemplateValues) { return diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 7c0c11c529..9e4d5941e4 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -36,8 +36,9 @@ export function executeQueries( for (let i = 0; i < queries.length; i++) { if ( isExcludedStatement(queries[i].text) && - !queries[i].queryConfig.isSubmitted + !queries[i].queryConfig.isManuallySubmitted ) { + console.log('skipping query', queries[i].text) results[i] = {value: null, error: 'skipped'} counter -= 1 continue diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index 5bf264ed47..dee19201e9 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -432,7 +432,7 @@ class TimeMachine extends PureComponent { try { newQueryConfig = await getConfig(url, activeID, text, templates) - newQueryConfig.isSubmitted = !isAutoSubmitted + newQueryConfig.isManuallySubmitted = !isAutoSubmitted } catch { notify(analyzeQueryFailed) return diff --git a/ui/src/types/queries.ts b/ui/src/types/queries.ts index 7c3560090c..efc3c63fc2 100644 --- a/ui/src/types/queries.ts +++ b/ui/src/types/queries.ts @@ -26,7 +26,7 @@ export interface QueryConfig { lower?: string upper?: string isQuerySupportedByExplorer?: boolean // doesn't come from server -- is set in CellEditorOverlay - isSubmitted?: boolean // doesn't come from server -- is set in InfluxQLEditor + isManuallySubmitted?: boolean // doesn't come from server -- is set in InfluxQLEditor originalQuery?: string } From 99ec4c7dbb5c7cbb1bd6c73b7d22e37e84dbcefc Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:54:34 +0200 Subject: [PATCH 06/18] fix: fixing manually submitting not sometimes doesn't work --- ui/src/shared/components/time_series/TimeSeries.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 8432cd5df7..0580e61ad1 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -124,8 +124,8 @@ class TimeSeries extends PureComponent { } public async componentDidUpdate(prevProps: Props) { - const prevQueries = _.map(prevProps.queries, q => q.text) - const currQueries = _.map(this.props.queries, q => q.text) + const prevQueries = _.map(prevProps.queries, q => { return { text: q.text, isManuallySubmitted: q.queryConfig.isManuallySubmitted}} ) + const currQueries = _.map(this.props.queries, q => { return { text: q.text, isManuallySubmitted: q.queryConfig.isManuallySubmitted}} ) const queriesDifferent = !_.isEqual(prevQueries, currQueries) const prevTemplates = _.get(prevProps, 'templates') @@ -146,6 +146,7 @@ class TimeSeries extends PureComponent { this.props.uuid !== prevProps.uuid || this.state.fetchCount === 0 || this.props.xPixels !== prevProps.xPixels + console.log(`shouldExecuteQueries: ${shouldExecuteQueries}, queriesDifferent: ${queriesDifferent}`) if (shouldExecuteQueries) { this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) From 883ae6adc4e18842fd40f79b4d6ffb02fa57e262 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:54:37 +0200 Subject: [PATCH 07/18] fix: invalid loading state, allow submitting --- .../dashboards/components/InfluxQLEditor.tsx | 39 ++++++++++--------- ui/src/shared/apis/query.ts | 3 ++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 05c6d703c7..8fdf1ab985 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -42,6 +42,7 @@ interface State { filteredTemplates: Template[] submitted: Map configID: string + isExcluded: boolean } interface Props { @@ -66,23 +67,24 @@ const TEMPLATE_VAR = /[:]\w+[:]/g class InfluxQLEditor extends Component { public static getDerivedStateFromProps(nextProps: Props, prevState: State) { const {submitted, editedQueryText} = prevState - const isSubmitted = submitted.get(nextProps.activeQueryIndex)??true + const {query, activeQueryIndex, config, templates} = nextProps + const isSubmitted = submitted.get(activeQueryIndex)??true + const isQueryConfigChanged = config.id !== prevState.configID + const isQueryTextChanged = editedQueryText.trim() !== query.trim() console.log( - `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}, editedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${nextProps.query.substring(0, Math.min(nextProps.query.length, 20))}` + `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}\n\teditedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${query.substring(0, Math.min(query.length, 20))} +\tisQueryConfigChanged: ${isQueryConfigChanged}, isQueryTextChanged: ${isQueryTextChanged}, isManuallySubmitted: ${config.isManuallySubmitted}, isLoading: ${config.status?.loading}` ) - const isQueryConfigChanged = nextProps.config.id !== prevState.configID - const isQueryTextChanged = editedQueryText.trim() !== nextProps.query.trim() - if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { return { ...BLURRED_EDITOR_STATE, selectedTemplate: { - tempVar: getDeep(nextProps.templates, FIRST_TEMP_VAR, ''), + tempVar: getDeep(templates, FIRST_TEMP_VAR, ''), }, - filteredTemplates: nextProps.templates, - templatingQueryText: nextProps.query, - editedQueryText: nextProps.query, - configID: nextProps.config.id, + filteredTemplates: templates, + templatingQueryText: query, + editedQueryText: query, + configID: config.id, focused: isQueryConfigChanged, } } @@ -109,6 +111,7 @@ class InfluxQLEditor extends Component { editedQueryText: props.query, configID: props.config.id, submitted: new Map(), + isExcluded: false, } console.log( `Constructor: ${props.activeQueryIndex}, isSubmitted ${this.state.submitted}` @@ -279,8 +282,10 @@ class InfluxQLEditor extends Component { submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) }) } else { + const isExcluded = isExcludedStatement(value) this.setState({ isTemplating, + isExcluded, templatingQueryText: value, editedQueryText: value, submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) @@ -296,10 +301,10 @@ class InfluxQLEditor extends Component { } private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { - const {onUpdate, activeQueryIndex} = this.props - const isSubmitted = this.state.submitted.get(activeQueryIndex)??true - if (!this.isDisabled && !isSubmitted) { - const {editedQueryText} = this.state + const {onUpdate, activeQueryIndex, config} = this.props + const {editedQueryText, submitted, isExcluded} = this.state + const isSubmitted = submitted.get(activeQueryIndex)??true + if (!this.isDisabled && (!isSubmitted || !config.isManuallySubmitted)) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) const cancelableUpdate = makeCancelable(update) @@ -309,11 +314,7 @@ class InfluxQLEditor extends Component { try { await cancelableUpdate.promise // prevent changing submitted status when edited while awaiting update - if ( - this.state.editedQueryText === editedQueryText && - ((!isAutoSubmitted && isExcludedStatement(editedQueryText)) || - !isExcludedStatement(editedQueryText)) - ) { + if (this.state.editedQueryText === editedQueryText && ((!isAutoSubmitted && isExcluded) || !isExcluded)) { this.setSubmitted(true) console.log(`handleUpdate: ${activeQueryIndex}, set isSubmitted true`) } diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 9e4d5941e4..3492f625e1 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -41,6 +41,9 @@ export function executeQueries( console.log('skipping query', queries[i].text) results[i] = {value: null, error: 'skipped'} counter -= 1 + if (counter === 0) { + resolve(results) + } continue } executeQuery(source, queries[i], templates, uuid) From 53236446c73f993fe53ba91434466ccbf4ce65ef Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:02:47 +0200 Subject: [PATCH 08/18] chore: better filter keywords set --- ui/src/utils/queryFilter.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/src/utils/queryFilter.ts b/ui/src/utils/queryFilter.ts index 5b3e4d53f7..3ca5054584 100644 --- a/ui/src/utils/queryFilter.ts +++ b/ui/src/utils/queryFilter.ts @@ -3,8 +3,9 @@ const excludedStatements: string[] = [ 'delete', 'alter', 'create', - 'update', - 'insert', + 'grant', + 'revoke', + 'use', ] export const isExcludedStatement = (query: string): boolean => { From 8808fee43c83847d25502e527c7ca726ff33171f Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:03:46 +0200 Subject: [PATCH 09/18] fix: better manage states, keep unsubmited status --- .../dashboards/components/InfluxQLEditor.tsx | 79 ++++++++----------- ui/src/dashboards/utils/cellGetters.ts | 6 +- .../TimeMachine/InfluxQLQueryMaker.tsx | 1 - .../components/TimeMachine/TimeMachine.tsx | 3 +- 4 files changed, 39 insertions(+), 50 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 8fdf1ab985..ebf13ddc35 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -8,24 +8,19 @@ import ReactCodeMirror from 'src/dashboards/components/ReactCodeMirror' import TemplateDrawer from 'src/shared/components/TemplateDrawer' import QueryStatus from 'src/shared/components/QueryStatus' import {ErrorHandling} from 'src/shared/decorators/errors' -import {Dropdown, DropdownMode, ComponentStatus} from 'src/reusable_ui' -import {Button, ComponentColor, ComponentSize} from 'src/reusable_ui' +import {Button, ComponentColor, ComponentSize, ComponentStatus, Dropdown, DropdownMode} from 'src/reusable_ui' // Utils import {getDeep} from 'src/utils/wrappers' import {makeCancelable} from 'src/utils/promises' // Constants -import {MATCH_INCOMPLETE_TEMPLATES, applyMasks} from 'src/tempVars/constants' -import {METAQUERY_TEMPLATE_OPTIONS} from 'src/data_explorer/constants' +import {applyMasks, MATCH_INCOMPLETE_TEMPLATES} from 'src/tempVars/constants' +import {DropdownChildTypes, METAQUERY_TEMPLATE_OPTIONS, MetaQueryTemplateOption} from 'src/data_explorer/constants' // Types -import {Template, QueryConfig} from 'src/types' +import {QueryConfig, Template} from 'src/types' import {WrappedCancelablePromise} from 'src/types/promises' -import { - MetaQueryTemplateOption, - DropdownChildTypes, -} from 'src/data_explorer/constants' import {isExcludedStatement} from '../../utils/queryFilter' interface TempVar { @@ -40,7 +35,7 @@ interface State { selectedTemplate: TempVar isShowingTemplateValues: boolean filteredTemplates: Template[] - submitted: Map + submitted: boolean configID: string isExcluded: boolean } @@ -51,7 +46,6 @@ interface Props { config: QueryConfig templates: Template[] onMetaQuerySelected: () => void - activeQueryIndex: number } const FIRST_TEMP_VAR = '0.tempVar' @@ -67,13 +61,13 @@ const TEMPLATE_VAR = /[:]\w+[:]/g class InfluxQLEditor extends Component { public static getDerivedStateFromProps(nextProps: Props, prevState: State) { const {submitted, editedQueryText} = prevState - const {query, activeQueryIndex, config, templates} = nextProps - const isSubmitted = submitted.get(activeQueryIndex)??true + const {query, config, templates} = nextProps const isQueryConfigChanged = config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== query.trim() + // if query has been switched, set submitted state for excluded query based on the previous submitted way + const isSubmitted = isQueryConfigChanged ? (isExcludedStatement(query) ? config.isManuallySubmitted : true) : submitted console.log( - `getDerivedStateFromProps: ${nextProps.activeQueryIndex}, isSubmitted: ${isSubmitted}, submitted: ${JSON.stringify(submitted)}\n\teditedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${query.substring(0, Math.min(query.length, 20))} -\tisQueryConfigChanged: ${isQueryConfigChanged}, isQueryTextChanged: ${isQueryTextChanged}, isManuallySubmitted: ${config.isManuallySubmitted}, isLoading: ${config.status?.loading}` + `getDerivedStateFromProps: ${config.id}, isSubmitted: ${isSubmitted}, submitted: ${submitted}, wasSubmitted: ${config.isManuallySubmitted}\n\teditedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${query.substring(0, Math.min(query.length, 20))}\n\tisQueryConfigChanged: ${isQueryConfigChanged}, isQueryTextChanged: ${isQueryTextChanged}, isManuallySubmitted: ${config.isManuallySubmitted}, isLoading: ${config.status?.loading}` ) if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { return { @@ -86,6 +80,8 @@ class InfluxQLEditor extends Component { editedQueryText: query, configID: config.id, focused: isQueryConfigChanged, + submitted: isSubmitted, + isExcluded: isExcludedStatement(query), } } @@ -110,11 +106,11 @@ class InfluxQLEditor extends Component { templatingQueryText: props.query, editedQueryText: props.query, configID: props.config.id, - submitted: new Map(), + submitted: true, isExcluded: false, } console.log( - `Constructor: ${props.activeQueryIndex}, isSubmitted ${this.state.submitted}` + `Constructor: ${props.config.id}, isSubmitted ${this.state.submitted}`, ) } @@ -139,7 +135,6 @@ class InfluxQLEditor extends Component { submitted, } = this.state - const isSubmitted = submitted.get(this.props.activeQueryIndex)??true return (
{this.dismissPreviewButton} @@ -173,7 +168,7 @@ class InfluxQLEditor extends Component { {this.queryStatusButtons} @@ -197,7 +192,7 @@ class InfluxQLEditor extends Component { private handleTemplateSelection = ( selectedTemplate: TempVar, - templatingQueryText: string + templatingQueryText: string, ) => { this.setState({ selectedTemplate, @@ -211,9 +206,9 @@ class InfluxQLEditor extends Component { } private handleBlurEditor = (): void => { - const isSubmitted = this.state.submitted.get(this.props.activeQueryIndex)??true + const isSubmitted = this.state.submitted console.log( - `handleBlurEditor: ${this.props.activeQueryIndex}, isSubmitted: ${isSubmitted}` + `handleBlurEditor: ${this.state.configID}, isSubmitted: ${isSubmitted}`, ) this.setState({focused: false, isShowingTemplateValues: false}) this.handleUpdate(true) @@ -247,13 +242,13 @@ class InfluxQLEditor extends Component { } private handleChange = (value: string): void => { - const {templates, query, activeQueryIndex} = this.props + const {templates, query} = this.props //const {templates, activeQueryIndex} = this.props const isEditedChanged = value !== this.state.editedQueryText - const isSubmittedState = this.state.submitted.get(activeQueryIndex)??true + const isSubmittedState = this.state.submitted //const isSubmitted = isExcludedStatement(value)? isSubmittedState :value.trim() === query.trim() const isSubmitted = value.trim() === query.trim() - console.log(`handleChange: ${activeQueryIndex}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}, isEditedChanged: ${isEditedChanged}`) + console.log(`handleChange: ${this.state.configID}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}, isEditedChanged: ${isEditedChanged}`) if (!isEditedChanged || this.state.isShowingTemplateValues) { return @@ -270,7 +265,7 @@ class InfluxQLEditor extends Component { const filteredTemplates = this.filterTemplates(matched[0]) const selectedTemplate = this.selectMatchingTemplate( filteredTemplates, - matchedVar + matchedVar, ) this.setState({ @@ -279,32 +274,24 @@ class InfluxQLEditor extends Component { selectedTemplate, filteredTemplates, editedQueryText: value, - submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) + submitted: isSubmitted, }) } else { - const isExcluded = isExcludedStatement(value) + const isExcluded = isExcludedStatement(value) this.setState({ isTemplating, isExcluded, templatingQueryText: value, editedQueryText: value, - submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted) + submitted: isSubmitted, }) } - //this.setSubmitted(isSubmitted) - } - - private setSubmitted = (isSubmitted: boolean): void => { - const {activeQueryIndex} = this.props - console.log(`setSubmitted: ${activeQueryIndex}, isSubmitted ${isSubmitted}`) - this.setState({submitted: new Map(this.state.submitted).set(activeQueryIndex, isSubmitted)}) } private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { - const {onUpdate, activeQueryIndex, config} = this.props - const {editedQueryText, submitted, isExcluded} = this.state - const isSubmitted = submitted.get(activeQueryIndex)??true - if (!this.isDisabled && (!isSubmitted || !config.isManuallySubmitted)) { + const {onUpdate, config} = this.props + const {editedQueryText, submitted, isExcluded, configID} = this.state + if (!this.isDisabled && (!submitted || !config.isManuallySubmitted)) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) const cancelableUpdate = makeCancelable(update) @@ -314,9 +301,9 @@ class InfluxQLEditor extends Component { try { await cancelableUpdate.promise // prevent changing submitted status when edited while awaiting update - if (this.state.editedQueryText === editedQueryText && ((!isAutoSubmitted && isExcluded) || !isExcluded)) { - this.setSubmitted(true) - console.log(`handleUpdate: ${activeQueryIndex}, set isSubmitted true`) + if (this.state.editedQueryText === editedQueryText && (!isExcluded || (!isAutoSubmitted && isExcluded))) { + this.setState({submitted: true}) + console.log(`handleUpdate: ${configID}, set isSubmitted true`) } } catch (error) { if (!error.isCanceled) { @@ -324,7 +311,7 @@ class InfluxQLEditor extends Component { } } finally { this.pendingUpdates = this.pendingUpdates.filter( - p => p !== cancelableUpdate + p => p !== cancelableUpdate, ) } } @@ -339,12 +326,12 @@ class InfluxQLEditor extends Component { private selectMatchingTemplate( filteredTemplates: Template[], - defaultVar: TempVar + defaultVar: TempVar, ): TempVar { const {selectedTemplate} = this.state const found = filteredTemplates.find( - t => selectedTemplate && t.tempVar === selectedTemplate.tempVar + t => selectedTemplate && t.tempVar === selectedTemplate.tempVar, ) if (found) { diff --git a/ui/src/dashboards/utils/cellGetters.ts b/ui/src/dashboards/utils/cellGetters.ts index 5beeb1a5c2..5e3c292242 100644 --- a/ui/src/dashboards/utils/cellGetters.ts +++ b/ui/src/dashboards/utils/cellGetters.ts @@ -175,7 +175,8 @@ export const getConfig = async ( url, id: string, query: string, - templates: Template[] + templates: Template[], + isManuallySubmitted = false ): Promise => { const renderedQuery = templateReplace(query, templates) const queries = await getQueryConfigAndStatus(url, [ @@ -189,6 +190,9 @@ export const getConfig = async ( // return back the raw query queryConfig.rawText = query } + + queryConfig.isManuallySubmitted = isManuallySubmitted + return { ...queryConfig, originalQuery: query, diff --git a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx index 81a4f37882..c648a251f7 100644 --- a/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx +++ b/ui/src/shared/components/TimeMachine/InfluxQLQueryMaker.tsx @@ -107,7 +107,6 @@ const QueryMaker: FunctionComponent = ({ onUpdate={onEditRawText} templates={templates} onMetaQuerySelected={onMetaQuerySelected} - activeQueryIndex={activeQueryIndex} /> { let newQueryConfig try { - newQueryConfig = await getConfig(url, activeID, text, templates) - newQueryConfig.isManuallySubmitted = !isAutoSubmitted + newQueryConfig = await getConfig(url, activeID, text, templates, !isAutoSubmitted) } catch { notify(analyzeQueryFailed) return From d450d227493fef6469a010c118459b16a292b7e6 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:14:19 +0200 Subject: [PATCH 10/18] chore: removed logs --- ui/src/dashboards/components/InfluxQLEditor.tsx | 17 +---------------- ui/src/shared/apis/query.ts | 1 - .../components/time_series/TimeSeries.tsx | 1 - ui/src/worker/jobs/proxy.ts | 1 - 4 files changed, 1 insertion(+), 19 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index ebf13ddc35..4f4968c96a 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -66,9 +66,6 @@ class InfluxQLEditor extends Component { const isQueryTextChanged = editedQueryText.trim() !== query.trim() // if query has been switched, set submitted state for excluded query based on the previous submitted way const isSubmitted = isQueryConfigChanged ? (isExcludedStatement(query) ? config.isManuallySubmitted : true) : submitted - console.log( - `getDerivedStateFromProps: ${config.id}, isSubmitted: ${isSubmitted}, submitted: ${submitted}, wasSubmitted: ${config.isManuallySubmitted}\n\teditedQueryText: ${editedQueryText.substring(0, Math.min(editedQueryText.length, 20))}, query: ${query.substring(0, Math.min(query.length, 20))}\n\tisQueryConfigChanged: ${isQueryConfigChanged}, isQueryTextChanged: ${isQueryTextChanged}, isManuallySubmitted: ${config.isManuallySubmitted}, isLoading: ${config.status?.loading}` - ) if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { return { ...BLURRED_EDITOR_STATE, @@ -109,9 +106,6 @@ class InfluxQLEditor extends Component { submitted: true, isExcluded: false, } - console.log( - `Constructor: ${props.config.id}, isSubmitted ${this.state.submitted}`, - ) } public componentWillUnmount() { @@ -206,10 +200,6 @@ class InfluxQLEditor extends Component { } private handleBlurEditor = (): void => { - const isSubmitted = this.state.submitted - console.log( - `handleBlurEditor: ${this.state.configID}, isSubmitted: ${isSubmitted}`, - ) this.setState({focused: false, isShowingTemplateValues: false}) this.handleUpdate(true) } @@ -243,12 +233,8 @@ class InfluxQLEditor extends Component { private handleChange = (value: string): void => { const {templates, query} = this.props - //const {templates, activeQueryIndex} = this.props const isEditedChanged = value !== this.state.editedQueryText - const isSubmittedState = this.state.submitted - //const isSubmitted = isExcludedStatement(value)? isSubmittedState :value.trim() === query.trim() const isSubmitted = value.trim() === query.trim() - console.log(`handleChange: ${this.state.configID}, isSubmitted ${isSubmitted}, isSubmittedState: ${isSubmittedState}, isEditedChanged: ${isEditedChanged}`) if (!isEditedChanged || this.state.isShowingTemplateValues) { return @@ -290,7 +276,7 @@ class InfluxQLEditor extends Component { private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { const {onUpdate, config} = this.props - const {editedQueryText, submitted, isExcluded, configID} = this.state + const {editedQueryText, submitted, isExcluded} = this.state if (!this.isDisabled && (!submitted || !config.isManuallySubmitted)) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) @@ -303,7 +289,6 @@ class InfluxQLEditor extends Component { // prevent changing submitted status when edited while awaiting update if (this.state.editedQueryText === editedQueryText && (!isExcluded || (!isAutoSubmitted && isExcluded))) { this.setState({submitted: true}) - console.log(`handleUpdate: ${configID}, set isSubmitted true`) } } catch (error) { if (!error.isCanceled) { diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 3492f625e1..48953023a3 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -38,7 +38,6 @@ export function executeQueries( isExcludedStatement(queries[i].text) && !queries[i].queryConfig.isManuallySubmitted ) { - console.log('skipping query', queries[i].text) results[i] = {value: null, error: 'skipped'} counter -= 1 if (counter === 0) { diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 0580e61ad1..fb0e6d6425 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -146,7 +146,6 @@ class TimeSeries extends PureComponent { this.props.uuid !== prevProps.uuid || this.state.fetchCount === 0 || this.props.xPixels !== prevProps.xPixels - console.log(`shouldExecuteQueries: ${shouldExecuteQueries}, queriesDifferent: ${queriesDifferent}`) if (shouldExecuteQueries) { this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) diff --git a/ui/src/worker/jobs/proxy.ts b/ui/src/worker/jobs/proxy.ts index d99720a51d..a8706f734b 100644 --- a/ui/src/worker/jobs/proxy.ts +++ b/ui/src/worker/jobs/proxy.ts @@ -11,7 +11,6 @@ const proxy = async (msg: ProxyMsg): Promise<{data: any}> => { const { payload: {url, query, rp, db, uuid}, } = msg - console.log('proxy', url, query) const body = {url, query, rp, db, uuid} try { const response = await fetch(url, { From 0580c5943cc9d52c1fa41413b09f43db5a07c079 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:57:19 +0200 Subject: [PATCH 11/18] chore: eslint fixes --- .../dashboards/components/InfluxQLEditor.tsx | 46 +++++++++++++++---- .../components/TimeMachine/TimeMachine.tsx | 8 +++- .../components/time_series/TimeSeries.tsx | 14 +++++- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 4f4968c96a..6a56670c8f 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -8,7 +8,14 @@ import ReactCodeMirror from 'src/dashboards/components/ReactCodeMirror' import TemplateDrawer from 'src/shared/components/TemplateDrawer' import QueryStatus from 'src/shared/components/QueryStatus' import {ErrorHandling} from 'src/shared/decorators/errors' -import {Button, ComponentColor, ComponentSize, ComponentStatus, Dropdown, DropdownMode} from 'src/reusable_ui' +import { + Button, + ComponentColor, + ComponentSize, + ComponentStatus, + Dropdown, + DropdownMode, +} from 'src/reusable_ui' // Utils import {getDeep} from 'src/utils/wrappers' @@ -16,7 +23,11 @@ import {makeCancelable} from 'src/utils/promises' // Constants import {applyMasks, MATCH_INCOMPLETE_TEMPLATES} from 'src/tempVars/constants' -import {DropdownChildTypes, METAQUERY_TEMPLATE_OPTIONS, MetaQueryTemplateOption} from 'src/data_explorer/constants' +import { + DropdownChildTypes, + METAQUERY_TEMPLATE_OPTIONS, + MetaQueryTemplateOption, +} from 'src/data_explorer/constants' // Types import {QueryConfig, Template} from 'src/types' @@ -65,7 +76,19 @@ class InfluxQLEditor extends Component { const isQueryConfigChanged = config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== query.trim() // if query has been switched, set submitted state for excluded query based on the previous submitted way - const isSubmitted = isQueryConfigChanged ? (isExcludedStatement(query) ? config.isManuallySubmitted : true) : submitted + let isSubmitted: boolean + if (isQueryConfigChanged) { + isSubmitted = isExcludedStatement(query) + ? config.isManuallySubmitted + : true + } else { + isSubmitted = submitted + } + // const isSubmitted = isQueryConfigChanged + // ? isExcludedStatement(query) + // ? config.isManuallySubmitted + // : true + // : submitted if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { return { ...BLURRED_EDITOR_STATE, @@ -162,7 +185,7 @@ class InfluxQLEditor extends Component { {this.queryStatusButtons} @@ -186,7 +209,7 @@ class InfluxQLEditor extends Component { private handleTemplateSelection = ( selectedTemplate: TempVar, - templatingQueryText: string, + templatingQueryText: string ) => { this.setState({ selectedTemplate, @@ -251,7 +274,7 @@ class InfluxQLEditor extends Component { const filteredTemplates = this.filterTemplates(matched[0]) const selectedTemplate = this.selectMatchingTemplate( filteredTemplates, - matchedVar, + matchedVar ) this.setState({ @@ -287,7 +310,10 @@ class InfluxQLEditor extends Component { try { await cancelableUpdate.promise // prevent changing submitted status when edited while awaiting update - if (this.state.editedQueryText === editedQueryText && (!isExcluded || (!isAutoSubmitted && isExcluded))) { + if ( + this.state.editedQueryText === editedQueryText && + (!isExcluded || (!isAutoSubmitted && isExcluded)) + ) { this.setState({submitted: true}) } } catch (error) { @@ -296,7 +322,7 @@ class InfluxQLEditor extends Component { } } finally { this.pendingUpdates = this.pendingUpdates.filter( - p => p !== cancelableUpdate, + p => p !== cancelableUpdate ) } } @@ -311,12 +337,12 @@ class InfluxQLEditor extends Component { private selectMatchingTemplate( filteredTemplates: Template[], - defaultVar: TempVar, + defaultVar: TempVar ): TempVar { const {selectedTemplate} = this.state const found = filteredTemplates.find( - t => selectedTemplate && t.tempVar === selectedTemplate.tempVar, + t => selectedTemplate && t.tempVar === selectedTemplate.tempVar ) if (found) { diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index f6a972a0d6..950f9e1df9 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -431,7 +431,13 @@ class TimeMachine extends PureComponent { let newQueryConfig try { - newQueryConfig = await getConfig(url, activeID, text, templates, !isAutoSubmitted) + newQueryConfig = await getConfig( + url, + activeID, + text, + templates, + !isAutoSubmitted + ) } catch { notify(analyzeQueryFailed) return diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index fb0e6d6425..4b25c7c70f 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -124,8 +124,18 @@ class TimeSeries extends PureComponent { } public async componentDidUpdate(prevProps: Props) { - const prevQueries = _.map(prevProps.queries, q => { return { text: q.text, isManuallySubmitted: q.queryConfig.isManuallySubmitted}} ) - const currQueries = _.map(this.props.queries, q => { return { text: q.text, isManuallySubmitted: q.queryConfig.isManuallySubmitted}} ) + const prevQueries = _.map(prevProps.queries, q => { + return { + text: q.text, + isManuallySubmitted: q.queryConfig.isManuallySubmitted, + } + }) + const currQueries = _.map(this.props.queries, q => { + return { + text: q.text, + isManuallySubmitted: q.queryConfig.isManuallySubmitted, + } + }) const queriesDifferent = !_.isEqual(prevQueries, currQueries) const prevTemplates = _.get(prevProps, 'templates') From 2711c1a21327e78f4bba3e2561b5e33bd78f1c4f Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:07:22 +0200 Subject: [PATCH 12/18] fix: flux query doesn't have queryConfig --- ui/src/shared/components/time_series/TimeSeries.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 4b25c7c70f..c90d26e52f 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -127,13 +127,13 @@ class TimeSeries extends PureComponent { const prevQueries = _.map(prevProps.queries, q => { return { text: q.text, - isManuallySubmitted: q.queryConfig.isManuallySubmitted, + isManuallySubmitted: q.queryConfig?.isManuallySubmitted, } }) const currQueries = _.map(this.props.queries, q => { return { text: q.text, - isManuallySubmitted: q.queryConfig.isManuallySubmitted, + isManuallySubmitted: q.queryConfig?.isManuallySubmitted, } }) const queriesDifferent = !_.isEqual(prevQueries, currQueries) From e904a259e16b1d64d777d165d564831bd0c29db8 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:17:51 +0200 Subject: [PATCH 13/18] fix: filter excluded queries at higher level --- .../dashboards/components/InfluxQLEditor.tsx | 12 ++--- ui/src/dashboards/utils/cellGetters.ts | 5 +- ui/src/shared/apis/query.ts | 32 ++++--------- .../components/TimeMachine/TimeMachine.tsx | 11 ++--- .../components/time_series/TimeSeries.tsx | 14 +----- ui/src/utils/buildQueriesForGraphs.ts | 46 +++++++++++-------- ui/src/utils/queryFilter.ts | 2 +- 7 files changed, 49 insertions(+), 73 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 6a56670c8f..f9d4763cad 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -84,11 +84,6 @@ class InfluxQLEditor extends Component { } else { isSubmitted = submitted } - // const isSubmitted = isQueryConfigChanged - // ? isExcludedStatement(query) - // ? config.isManuallySubmitted - // : true - // : submitted if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { return { ...BLURRED_EDITOR_STATE, @@ -185,7 +180,7 @@ class InfluxQLEditor extends Component { {this.queryStatusButtons} @@ -300,7 +295,10 @@ class InfluxQLEditor extends Component { private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { const {onUpdate, config} = this.props const {editedQueryText, submitted, isExcluded} = this.state - if (!this.isDisabled && (!submitted || !config.isManuallySubmitted)) { + if ( + !this.isDisabled && + (!submitted || (!config.isManuallySubmitted && isExcluded)) + ) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) const cancelableUpdate = makeCancelable(update) diff --git a/ui/src/dashboards/utils/cellGetters.ts b/ui/src/dashboards/utils/cellGetters.ts index 5e3c292242..dc8dbd616b 100644 --- a/ui/src/dashboards/utils/cellGetters.ts +++ b/ui/src/dashboards/utils/cellGetters.ts @@ -175,8 +175,7 @@ export const getConfig = async ( url, id: string, query: string, - templates: Template[], - isManuallySubmitted = false + templates: Template[] ): Promise => { const renderedQuery = templateReplace(query, templates) const queries = await getQueryConfigAndStatus(url, [ @@ -191,8 +190,6 @@ export const getConfig = async ( queryConfig.rawText = query } - queryConfig.isManuallySubmitted = isManuallySubmitted - return { ...queryConfig, originalQuery: query, diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 48953023a3..17937f2590 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -4,18 +4,17 @@ import {TEMP_VAR_INTERVAL, DEFAULT_DURATION_MS} from 'src/shared/constants' import replaceTemplates, {replaceInterval} from 'src/tempVars/utils/replace' import {proxy} from 'src/utils/queryUrlGenerator' -import {Query, Source, Template} from 'src/types' +import {Source, Template} from 'src/types' import {TimeSeriesResponse} from 'src/types/series' -import {isExcludedStatement} from '../../utils/queryFilter' // REVIEW: why is this different than the `Query` in src/types? -// interface Query { -// text: string -// id: string -// database?: string -// db?: string -// rp?: string -// } +interface Query { + text: string + id: string + database?: string + db?: string + rp?: string +} interface QueryResult { value: TimeSeriesResponse | null @@ -34,17 +33,6 @@ export function executeQueries( let counter = queries.length for (let i = 0; i < queries.length; i++) { - if ( - isExcludedStatement(queries[i].text) && - !queries[i].queryConfig.isManuallySubmitted - ) { - results[i] = {value: null, error: 'skipped'} - counter -= 1 - if (counter === 0) { - resolve(results) - } - continue - } executeQuery(source, queries[i], templates, uuid) .then(result => (results[i] = {value: result, error: null})) .catch(result => (results[i] = {value: null, error: result})) @@ -70,9 +58,9 @@ export const executeQuery = async ( const {data} = await proxy({ source: source.links.proxy, - rp: query.queryConfig.retentionPolicy, + rp: query.rp, query: text, - db: query.queryConfig.database, + db: query.db || query.database, uuid, }) diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index 950f9e1df9..4fc3ec52c6 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -431,13 +431,7 @@ class TimeMachine extends PureComponent { let newQueryConfig try { - newQueryConfig = await getConfig( - url, - activeID, - text, - templates, - !isAutoSubmitted - ) + newQueryConfig = await getConfig(url, activeID, text, templates) } catch { notify(analyzeQueryFailed) return @@ -454,11 +448,14 @@ class TimeMachine extends PureComponent { query: text, queryConfig: { ...newQueryConfig, + isManuallySubmitted: !isAutoSubmitted, rawText: text, status: {loading: true}, }, } }) + // Update global query status to loading, skipped query will remain in this state + this.handleEditQueryStatus(activeID, {loading: true}) onUpdateQueryDrafts(updatedQueryDrafts) } diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index c90d26e52f..8432cd5df7 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -124,18 +124,8 @@ class TimeSeries extends PureComponent { } public async componentDidUpdate(prevProps: Props) { - const prevQueries = _.map(prevProps.queries, q => { - return { - text: q.text, - isManuallySubmitted: q.queryConfig?.isManuallySubmitted, - } - }) - const currQueries = _.map(this.props.queries, q => { - return { - text: q.text, - isManuallySubmitted: q.queryConfig?.isManuallySubmitted, - } - }) + const prevQueries = _.map(prevProps.queries, q => q.text) + const currQueries = _.map(this.props.queries, q => q.text) const queriesDifferent = !_.isEqual(prevQueries, currQueries) const prevTemplates = _.get(prevProps, 'templates') diff --git a/ui/src/utils/buildQueriesForGraphs.ts b/ui/src/utils/buildQueriesForGraphs.ts index 93dc188cc2..13c05a3efb 100644 --- a/ui/src/utils/buildQueriesForGraphs.ts +++ b/ui/src/utils/buildQueriesForGraphs.ts @@ -3,6 +3,7 @@ import {buildQuery} from 'src/utils/influxql' import {TYPE_QUERY_CONFIG, TYPE_SHIFTED} from 'src/dashboards/constants' import {Query, QueryConfig, TimeRange, QueryType} from 'src/types' +import {isExcludedStatement} from './queryFilter' interface Statement { queryConfig: QueryConfig @@ -15,28 +16,33 @@ const buildQueries = (queryConfigs: QueryConfig[], tR: TimeRange): Query[] => { return [] } - const statements: Statement[] = queryConfigs.map((query: QueryConfig) => { - const {rawText, range, id, shifts, database, measurement, fields} = query - const timeRange: TimeRange = range || tR - const text: string = - rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query) - const isParsable: boolean = - !_.isEmpty(database) && !_.isEmpty(measurement) && fields.length > 0 - - if (shifts && shifts.length && isParsable) { - const shiftedQueries: string[] = shifts - .filter(s => s.unit) - .map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s)) - - return { - text: `${text};${shiftedQueries.join(';')}`, - id, - queryConfig: query, + const statements: Statement[] = queryConfigs + .filter( + (query: QueryConfig) => + !isExcludedStatement(query.rawText) || query.isManuallySubmitted + ) + .map((query: QueryConfig) => { + const {rawText, range, id, shifts, database, measurement, fields} = query + const timeRange: TimeRange = range || tR + const text: string = + rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query) + const isParsable: boolean = + !_.isEmpty(database) && !_.isEmpty(measurement) && fields.length > 0 + + if (shifts && shifts.length && isParsable) { + const shiftedQueries: string[] = shifts + .filter(s => s.unit) + .map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s)) + + return { + text: `${text};${shiftedQueries.join(';')}`, + id, + queryConfig: query, + } } - } - return {text, id, queryConfig: query} - }) + return {text, id, queryConfig: query} + }) const queries: Query[] = statements .filter(s => s.text !== null) diff --git a/ui/src/utils/queryFilter.ts b/ui/src/utils/queryFilter.ts index 3ca5054584..6dc02f4314 100644 --- a/ui/src/utils/queryFilter.ts +++ b/ui/src/utils/queryFilter.ts @@ -10,6 +10,6 @@ const excludedStatements: string[] = [ export const isExcludedStatement = (query: string): boolean => { return excludedStatements.some(statement => - query.toLowerCase().startsWith(statement) + query?.toLowerCase().startsWith(statement) ) } From 630d521170c52b943278dab714ea0dcea9c5be46 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:16:57 +0200 Subject: [PATCH 14/18] fix: Filtering at lower level to filter also manual refreshing --- .../dashboards/components/InfluxQLEditor.tsx | 44 ++++++++++-------- ui/src/shared/apis/query.ts | 27 ++++++----- .../components/TimeMachine/TimeMachine.tsx | 16 +++++-- .../components/time_series/TimeSeries.tsx | 21 +++++++-- ui/src/types/queries.ts | 3 ++ ui/src/utils/buildQueriesForGraphs.ts | 46 ++++++++----------- ui/src/worker/jobs/proxy.ts | 1 + 7 files changed, 95 insertions(+), 63 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index f9d4763cad..97e2943de2 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -46,7 +46,7 @@ interface State { selectedTemplate: TempVar isShowingTemplateValues: boolean filteredTemplates: Template[] - submitted: boolean + isSubmitted: boolean configID: string isExcluded: boolean } @@ -71,20 +71,20 @@ const TEMPLATE_VAR = /[:]\w+[:]/g class InfluxQLEditor extends Component { public static getDerivedStateFromProps(nextProps: Props, prevState: State) { - const {submitted, editedQueryText} = prevState + const {isSubmitted, editedQueryText} = prevState const {query, config, templates} = nextProps const isQueryConfigChanged = config.id !== prevState.configID const isQueryTextChanged = editedQueryText.trim() !== query.trim() // if query has been switched, set submitted state for excluded query based on the previous submitted way - let isSubmitted: boolean + let submitted: boolean if (isQueryConfigChanged) { - isSubmitted = isExcludedStatement(query) - ? config.isManuallySubmitted + submitted = isExcludedStatement(query) + ? config.status?.wasManuallySubmitted : true } else { - isSubmitted = submitted + submitted = isSubmitted } - if ((isSubmitted && isQueryTextChanged) || isQueryConfigChanged) { + if ((submitted && isQueryTextChanged) || isQueryConfigChanged) { return { ...BLURRED_EDITOR_STATE, selectedTemplate: { @@ -95,7 +95,7 @@ class InfluxQLEditor extends Component { editedQueryText: query, configID: config.id, focused: isQueryConfigChanged, - submitted: isSubmitted, + isSubmitted: submitted, isExcluded: isExcludedStatement(query), } } @@ -121,8 +121,8 @@ class InfluxQLEditor extends Component { templatingQueryText: props.query, editedQueryText: props.query, configID: props.config.id, - submitted: true, - isExcluded: false, + isSubmitted: true, + isExcluded: isExcludedStatement(props.query), } } @@ -144,7 +144,8 @@ class InfluxQLEditor extends Component { filteredTemplates, isShowingTemplateValues, focused, - submitted, + isSubmitted, + isExcluded, } = this.state return ( @@ -178,9 +179,16 @@ class InfluxQLEditor extends Component {
{this.queryStatusButtons} @@ -278,7 +286,7 @@ class InfluxQLEditor extends Component { selectedTemplate, filteredTemplates, editedQueryText: value, - submitted: isSubmitted, + isSubmitted, }) } else { const isExcluded = isExcludedStatement(value) @@ -287,17 +295,17 @@ class InfluxQLEditor extends Component { isExcluded, templatingQueryText: value, editedQueryText: value, - submitted: isSubmitted, + isSubmitted, }) } } private handleUpdate = async (isAutoSubmitted?: boolean): Promise => { const {onUpdate, config} = this.props - const {editedQueryText, submitted, isExcluded} = this.state + const {editedQueryText, isSubmitted, isExcluded} = this.state if ( !this.isDisabled && - (!submitted || (!config.isManuallySubmitted && isExcluded)) + (!isSubmitted || (!config.status?.wasManuallySubmitted && isExcluded)) ) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) @@ -312,7 +320,7 @@ class InfluxQLEditor extends Component { this.state.editedQueryText === editedQueryText && (!isExcluded || (!isAutoSubmitted && isExcluded)) ) { - this.setState({submitted: true}) + this.setState({isSubmitted: true}) } } catch (error) { if (!error.isCanceled) { diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 17937f2590..7bfbd96b0e 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -4,17 +4,9 @@ import {TEMP_VAR_INTERVAL, DEFAULT_DURATION_MS} from 'src/shared/constants' import replaceTemplates, {replaceInterval} from 'src/tempVars/utils/replace' import {proxy} from 'src/utils/queryUrlGenerator' -import {Source, Template} from 'src/types' +import {Query, Source, Template} from 'src/types' import {TimeSeriesResponse} from 'src/types/series' - -// REVIEW: why is this different than the `Query` in src/types? -interface Query { - text: string - id: string - database?: string - db?: string - rp?: string -} +import {isExcludedStatement} from '../../utils/queryFilter' interface QueryResult { value: TimeSeriesResponse | null @@ -33,6 +25,17 @@ export function executeQueries( let counter = queries.length for (let i = 0; i < queries.length; i++) { + if ( + isExcludedStatement(queries[i].text) && + !queries[i].queryConfig.isManuallySubmitted + ) { + results[i] = {value: null, error: 'skipped'} + counter -= 1 + if (counter === 0) { + resolve(results) + } + continue + } executeQuery(source, queries[i], templates, uuid) .then(result => (results[i] = {value: result, error: null})) .catch(result => (results[i] = {value: null, error: result})) @@ -58,9 +61,9 @@ export const executeQuery = async ( const {data} = await proxy({ source: source.links.proxy, - rp: query.rp, + rp: query.queryConfig.retentionPolicy, query: text, - db: query.db || query.database, + db: query.queryConfig.database, uuid, }) diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index 4fc3ec52c6..6b102371f8 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -439,7 +439,13 @@ class TimeMachine extends PureComponent { const updatedQueryDrafts = queryDrafts.map(query => { if (query.queryConfig.id !== activeID) { - return query + return { + ...query, + queryConfig: { + ...query.queryConfig, + isManuallySubmitted: false, + }, + } } return { @@ -451,11 +457,15 @@ class TimeMachine extends PureComponent { isManuallySubmitted: !isAutoSubmitted, rawText: text, status: {loading: true}, + submittedQuery: isAutoSubmitted + ? query.queryConfig.submittedQuery + : text, + submittedStatus: query.queryConfig.status?.wasManuallySubmitted + ? query.queryConfig.status + : query.queryConfig.submittedStatus, }, } }) - // Update global query status to loading, skipped query will remain in this state - this.handleEditQueryStatus(activeID, {loading: true}) onUpdateQueryDrafts(updatedQueryDrafts) } diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 8432cd5df7..2c9d06cc80 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -124,8 +124,18 @@ class TimeSeries extends PureComponent { } public async componentDidUpdate(prevProps: Props) { - const prevQueries = _.map(prevProps.queries, q => q.text) - const currQueries = _.map(this.props.queries, q => q.text) + const prevQueries = _.map(prevProps.queries, q => { + return { + text: q.text, + isManuallySubmitted: q.queryConfig?.isManuallySubmitted, + } + }) + const currQueries = _.map(this.props.queries, q => { + return { + text: q.text, + isManuallySubmitted: q.queryConfig?.isManuallySubmitted, + } + }) const queriesDifferent = !_.isEqual(prevQueries, currQueries) const prevTemplates = _.get(prevProps, 'templates') @@ -335,8 +345,11 @@ class TimeSeries extends PureComponent { queryStatus = {success: 'Success!'} } } - - editQueryStatus(query.id, queryStatus) + editQueryStatus(query.id, { + ...queryStatus, + wasManuallySubmitted: query.queryConfig.isManuallySubmitted, + }) + query.queryConfig.isManuallySubmitted = false } const validQueryResults = results diff --git a/ui/src/types/queries.ts b/ui/src/types/queries.ts index efc3c63fc2..dff9d6cd79 100644 --- a/ui/src/types/queries.ts +++ b/ui/src/types/queries.ts @@ -28,6 +28,8 @@ export interface QueryConfig { isQuerySupportedByExplorer?: boolean // doesn't come from server -- is set in CellEditorOverlay isManuallySubmitted?: boolean // doesn't come from server -- is set in InfluxQLEditor originalQuery?: string + submittedQuery?: string + submittedStatus?: Status } export interface QueryStatus { @@ -87,6 +89,7 @@ export interface Namespace { export interface Status { loading?: boolean + wasManuallySubmitted?: boolean error?: string warn?: string success?: string diff --git a/ui/src/utils/buildQueriesForGraphs.ts b/ui/src/utils/buildQueriesForGraphs.ts index 13c05a3efb..93dc188cc2 100644 --- a/ui/src/utils/buildQueriesForGraphs.ts +++ b/ui/src/utils/buildQueriesForGraphs.ts @@ -3,7 +3,6 @@ import {buildQuery} from 'src/utils/influxql' import {TYPE_QUERY_CONFIG, TYPE_SHIFTED} from 'src/dashboards/constants' import {Query, QueryConfig, TimeRange, QueryType} from 'src/types' -import {isExcludedStatement} from './queryFilter' interface Statement { queryConfig: QueryConfig @@ -16,33 +15,28 @@ const buildQueries = (queryConfigs: QueryConfig[], tR: TimeRange): Query[] => { return [] } - const statements: Statement[] = queryConfigs - .filter( - (query: QueryConfig) => - !isExcludedStatement(query.rawText) || query.isManuallySubmitted - ) - .map((query: QueryConfig) => { - const {rawText, range, id, shifts, database, measurement, fields} = query - const timeRange: TimeRange = range || tR - const text: string = - rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query) - const isParsable: boolean = - !_.isEmpty(database) && !_.isEmpty(measurement) && fields.length > 0 - - if (shifts && shifts.length && isParsable) { - const shiftedQueries: string[] = shifts - .filter(s => s.unit) - .map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s)) - - return { - text: `${text};${shiftedQueries.join(';')}`, - id, - queryConfig: query, - } + const statements: Statement[] = queryConfigs.map((query: QueryConfig) => { + const {rawText, range, id, shifts, database, measurement, fields} = query + const timeRange: TimeRange = range || tR + const text: string = + rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query) + const isParsable: boolean = + !_.isEmpty(database) && !_.isEmpty(measurement) && fields.length > 0 + + if (shifts && shifts.length && isParsable) { + const shiftedQueries: string[] = shifts + .filter(s => s.unit) + .map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s)) + + return { + text: `${text};${shiftedQueries.join(';')}`, + id, + queryConfig: query, } + } - return {text, id, queryConfig: query} - }) + return {text, id, queryConfig: query} + }) const queries: Query[] = statements .filter(s => s.text !== null) diff --git a/ui/src/worker/jobs/proxy.ts b/ui/src/worker/jobs/proxy.ts index a8706f734b..827ad1499c 100644 --- a/ui/src/worker/jobs/proxy.ts +++ b/ui/src/worker/jobs/proxy.ts @@ -11,6 +11,7 @@ const proxy = async (msg: ProxyMsg): Promise<{data: any}> => { const { payload: {url, query, rp, db, uuid}, } = msg + const body = {url, query, rp, db, uuid} try { const response = await fetch(url, { From dcbaaaaef6f1411fff64c3c600aab65b5a8eba60 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:18:01 +0200 Subject: [PATCH 15/18] fix: Handling query state and auto-submitting refresh workaround --- .../components/TimeMachine/TimeMachine.tsx | 26 ++++++++++++++----- .../components/time_series/TimeSeries.tsx | 8 +++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index 6b102371f8..fa76f5a0e1 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -54,6 +54,7 @@ import { import {SourceOption} from 'src/types/sources' import {Links, ScriptStatus} from 'src/types/flux' import queryBuilderFetcher from './fluxQueryBuilder/apis/queryBuilderFetcher' +import {isExcludedStatement} from '../../../utils/queryFilter' interface ConnectedProps { script: string @@ -424,9 +425,16 @@ class TimeMachine extends PureComponent { text: string, isAutoSubmitted: boolean ): Promise => { - const {templates, onUpdateQueryDrafts, queryDrafts, notify} = this.props + const { + templates, + onUpdateQueryDrafts, + queryDrafts, + queryStatuses, + notify, + } = this.props const activeID = this.activeQuery.id const url: string = _.get(this.source, 'links.queries', '') + const isExcluded = isExcludedStatement(text) let newQueryConfig @@ -438,12 +446,17 @@ class TimeMachine extends PureComponent { } const updatedQueryDrafts = queryDrafts.map(query => { + const submittedStatus = + isExcluded && queryStatuses[String(query.id)]?.wasManuallySubmitted + ? queryStatuses[String(query.id)] + : query.queryConfig.submittedStatus if (query.queryConfig.id !== activeID) { return { ...query, queryConfig: { ...query.queryConfig, isManuallySubmitted: false, + submittedStatus, }, } } @@ -457,12 +470,11 @@ class TimeMachine extends PureComponent { isManuallySubmitted: !isAutoSubmitted, rawText: text, status: {loading: true}, - submittedQuery: isAutoSubmitted - ? query.queryConfig.submittedQuery - : text, - submittedStatus: query.queryConfig.status?.wasManuallySubmitted - ? query.queryConfig.status - : query.queryConfig.submittedStatus, + submittedQuery: + isExcluded && isAutoSubmitted + ? query.queryConfig.submittedQuery + : text, + submittedStatus, }, } }) diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 2c9d06cc80..6d46b92414 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -158,6 +158,13 @@ class TimeSeries extends PureComponent { this.props.xPixels !== prevProps.xPixels if (shouldExecuteQueries) { + if (!queriesDifferent && !this.isFluxQuery) { + this.props.queries.forEach(q => { + if (q.queryConfig) { + q.queryConfig.isManuallySubmitted = false + } + }) + } this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) } } @@ -349,7 +356,6 @@ class TimeSeries extends PureComponent { ...queryStatus, wasManuallySubmitted: query.queryConfig.isManuallySubmitted, }) - query.queryConfig.isManuallySubmitted = false } const validQueryResults = results From 1d746a13923ea3c86375e7b4104bbd829ad08146 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:35:39 +0100 Subject: [PATCH 16/18] fix: Better submitting state handling --- .../dashboards/components/InfluxQLEditor.tsx | 14 ++--- ui/src/shared/apis/query.ts | 9 ++-- .../components/TimeMachine/TimeMachine.tsx | 27 +++------- .../components/time_series/TimeSeries.tsx | 54 +++++++++++-------- ui/src/types/queries.ts | 10 ++-- 5 files changed, 60 insertions(+), 54 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index 97e2943de2..d608ca9465 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -33,6 +33,7 @@ import { import {QueryConfig, Template} from 'src/types' import {WrappedCancelablePromise} from 'src/types/promises' import {isExcludedStatement} from '../../utils/queryFilter' +import {ErrorSkipped} from '../../types/queries' interface TempVar { tempVar: string @@ -79,7 +80,7 @@ class InfluxQLEditor extends Component { let submitted: boolean if (isQueryConfigChanged) { submitted = isExcludedStatement(query) - ? config.status?.wasManuallySubmitted + ? config.status?.error !== ErrorSkipped : true } else { submitted = isSubmitted @@ -180,14 +181,15 @@ class InfluxQLEditor extends Component {
{this.queryStatusButtons} @@ -305,7 +307,7 @@ class InfluxQLEditor extends Component { const {editedQueryText, isSubmitted, isExcluded} = this.state if ( !this.isDisabled && - (!isSubmitted || (!config.status?.wasManuallySubmitted && isExcluded)) + (!isSubmitted || (isExcluded && config.status?.error === ErrorSkipped)) ) { this.cancelPendingUpdates() const update = onUpdate(editedQueryText, isAutoSubmitted) @@ -318,7 +320,7 @@ class InfluxQLEditor extends Component { // prevent changing submitted status when edited while awaiting update if ( this.state.editedQueryText === editedQueryText && - (!isExcluded || (!isAutoSubmitted && isExcluded)) + (!isExcluded || !isAutoSubmitted) ) { this.setState({isSubmitted: true}) } diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 7bfbd96b0e..0b1117927f 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -6,7 +6,7 @@ import {proxy} from 'src/utils/queryUrlGenerator' import {Query, Source, Template} from 'src/types' import {TimeSeriesResponse} from 'src/types/series' -import {isExcludedStatement} from '../../utils/queryFilter' +import {ErrorSkipped} from '../../types/queries' interface QueryResult { value: TimeSeriesResponse | null @@ -25,11 +25,12 @@ export function executeQueries( let counter = queries.length for (let i = 0; i < queries.length; i++) { + const q = queries[i] if ( - isExcludedStatement(queries[i].text) && - !queries[i].queryConfig.isManuallySubmitted + q.queryConfig.isExcluded && + !q.queryConfig.status.isManuallySubmitted ) { - results[i] = {value: null, error: 'skipped'} + results[i] = {value: null, error: ErrorSkipped} counter -= 1 if (counter === 0) { resolve(results) diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index fa76f5a0e1..f352ee92a2 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -446,19 +446,8 @@ class TimeMachine extends PureComponent { } const updatedQueryDrafts = queryDrafts.map(query => { - const submittedStatus = - isExcluded && queryStatuses[String(query.id)]?.wasManuallySubmitted - ? queryStatuses[String(query.id)] - : query.queryConfig.submittedStatus if (query.queryConfig.id !== activeID) { - return { - ...query, - queryConfig: { - ...query.queryConfig, - isManuallySubmitted: false, - submittedStatus, - }, - } + return query } return { @@ -467,17 +456,17 @@ class TimeMachine extends PureComponent { query: text, queryConfig: { ...newQueryConfig, - isManuallySubmitted: !isAutoSubmitted, rawText: text, - status: {loading: true}, - submittedQuery: - isExcluded && isAutoSubmitted - ? query.queryConfig.submittedQuery - : text, - submittedStatus, + isExcluded, }, } }) + this.handleEditQueryStatus(activeID, { + ...queryStatuses[activeID], + isManuallySubmitted: !isAutoSubmitted, + submittedStatus: queryStatuses[activeID]?.submittedStatus, + submittedQuery: queryStatuses[activeID]?.submittedQuery, + }) onUpdateQueryDrafts(updatedQueryDrafts) } diff --git a/ui/src/shared/components/time_series/TimeSeries.tsx b/ui/src/shared/components/time_series/TimeSeries.tsx index 6d46b92414..00e2dae140 100644 --- a/ui/src/shared/components/time_series/TimeSeries.tsx +++ b/ui/src/shared/components/time_series/TimeSeries.tsx @@ -124,20 +124,24 @@ class TimeSeries extends PureComponent { } public async componentDidUpdate(prevProps: Props) { - const prevQueries = _.map(prevProps.queries, q => { - return { - text: q.text, - isManuallySubmitted: q.queryConfig?.isManuallySubmitted, - } - }) - const currQueries = _.map(this.props.queries, q => { - return { - text: q.text, - isManuallySubmitted: q.queryConfig?.isManuallySubmitted, - } - }) + const prevQueries = _.map(prevProps.queries, q => q.text) + const currQueries = _.map(this.props.queries, q => q.text) const queriesDifferent = !_.isEqual(prevQueries, currQueries) + let manualSubmit = false + if (!queriesDifferent) { + for (let i = 0; i < this.props.queries.length; i++) { + const query = this.props.queries[i] + const prevQuery = prevProps.queries[i] + if ( + query.queryConfig?.status?.isManuallySubmitted && + !prevQuery.queryConfig?.status?.isManuallySubmitted + ) { + manualSubmit = true + break + } + } + } const prevTemplates = _.get(prevProps, 'templates') const newTemplates = _.get(this.props, 'templates') // templates includes dashTime and upperDashTime which capture zoomedTimeRange @@ -150,6 +154,7 @@ class TimeSeries extends PureComponent { const timeRangeChanged = oldLower !== newLower || oldUpper !== newUpper const shouldExecuteQueries = + manualSubmit || queriesDifferent || timeRangeChanged || templatesDifferent || @@ -158,13 +163,6 @@ class TimeSeries extends PureComponent { this.props.xPixels !== prevProps.xPixels if (shouldExecuteQueries) { - if (!queriesDifferent && !this.isFluxQuery) { - this.props.queries.forEach(q => { - if (q.queryConfig) { - q.queryConfig.isManuallySubmitted = false - } - }) - } this.debouncer.call(this.executeQueries, EXECUTE_QUERIES_DEBOUNCE_MS) } } @@ -325,7 +323,13 @@ class TimeSeries extends PureComponent { const {source, templates, editQueryStatus, queries} = this.props for (const query of queries) { - editQueryStatus(query.id, {loading: true}) + const prevStatus = query.queryConfig.status + editQueryStatus(query.id, { + loading: true, + isManuallySubmitted: prevStatus?.isManuallySubmitted, + submittedStatus: prevStatus?.submittedStatus, + submittedQuery: prevStatus?.submittedQuery, + }) } const results = await this.executeInfluxQLQueries( @@ -352,9 +356,17 @@ class TimeSeries extends PureComponent { queryStatus = {success: 'Success!'} } } + const shouldPreserve = + query.queryConfig.isExcluded && + !query.queryConfig.status?.isManuallySubmitted editQueryStatus(query.id, { ...queryStatus, - wasManuallySubmitted: query.queryConfig.isManuallySubmitted, + submittedStatus: shouldPreserve + ? query.queryConfig.status.submittedStatus + : queryStatus, + submittedQuery: shouldPreserve + ? query.queryConfig.status.submittedQuery + : query.text, }) } diff --git a/ui/src/types/queries.ts b/ui/src/types/queries.ts index dff9d6cd79..df98584584 100644 --- a/ui/src/types/queries.ts +++ b/ui/src/types/queries.ts @@ -1,6 +1,8 @@ // Types import {Source} from 'src/types' +export const ErrorSkipped = 'skipped' + export interface Query { text: string id: string @@ -26,10 +28,8 @@ export interface QueryConfig { lower?: string upper?: string isQuerySupportedByExplorer?: boolean // doesn't come from server -- is set in CellEditorOverlay - isManuallySubmitted?: boolean // doesn't come from server -- is set in InfluxQLEditor originalQuery?: string - submittedQuery?: string - submittedStatus?: Status + isExcluded?: boolean } export interface QueryStatus { @@ -89,10 +89,12 @@ export interface Namespace { export interface Status { loading?: boolean - wasManuallySubmitted?: boolean + isManuallySubmitted?: boolean error?: string warn?: string success?: string + submittedStatus?: Status + submittedQuery?: string } export interface TimeRange { From 953bfd402da2ffa424244a886bdecca6eea0fdf0 Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:51:31 +0100 Subject: [PATCH 17/18] docs: Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30bb8d26b1..75105a9acb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Bug Fixes 1. [#6103](https://github.com/influxdata/chronograf/pull/6103): Set active database for InfluxQL meta queries. +2. [#6105](https://github.com/influxdata/chronograf/pull/6105): Prevent dangerous InfluxQL statements from auto-execution. ### Other From b427ae3c161765069718dc786a59275ba34add2e Mon Sep 17 00:00:00 2001 From: vlastahajek <29980246+vlastahajek@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:55:53 +0100 Subject: [PATCH 18/18] chore: Using absolute import path --- ui/src/dashboards/components/InfluxQLEditor.tsx | 4 ++-- ui/src/shared/apis/query.ts | 2 +- ui/src/shared/components/TimeMachine/TimeMachine.tsx | 2 +- ui/src/shared/utils/TimeMachineContainer.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/src/dashboards/components/InfluxQLEditor.tsx b/ui/src/dashboards/components/InfluxQLEditor.tsx index d608ca9465..ec05df95f4 100644 --- a/ui/src/dashboards/components/InfluxQLEditor.tsx +++ b/ui/src/dashboards/components/InfluxQLEditor.tsx @@ -32,8 +32,8 @@ import { // Types import {QueryConfig, Template} from 'src/types' import {WrappedCancelablePromise} from 'src/types/promises' -import {isExcludedStatement} from '../../utils/queryFilter' -import {ErrorSkipped} from '../../types/queries' +import {isExcludedStatement} from 'src/utils/queryFilter' +import {ErrorSkipped} from 'src/types/queries' interface TempVar { tempVar: string diff --git a/ui/src/shared/apis/query.ts b/ui/src/shared/apis/query.ts index 0b1117927f..96276bf39f 100644 --- a/ui/src/shared/apis/query.ts +++ b/ui/src/shared/apis/query.ts @@ -6,7 +6,7 @@ import {proxy} from 'src/utils/queryUrlGenerator' import {Query, Source, Template} from 'src/types' import {TimeSeriesResponse} from 'src/types/series' -import {ErrorSkipped} from '../../types/queries' +import {ErrorSkipped} from 'src/types/queries' interface QueryResult { value: TimeSeriesResponse | null diff --git a/ui/src/shared/components/TimeMachine/TimeMachine.tsx b/ui/src/shared/components/TimeMachine/TimeMachine.tsx index f352ee92a2..c377299514 100644 --- a/ui/src/shared/components/TimeMachine/TimeMachine.tsx +++ b/ui/src/shared/components/TimeMachine/TimeMachine.tsx @@ -54,7 +54,7 @@ import { import {SourceOption} from 'src/types/sources' import {Links, ScriptStatus} from 'src/types/flux' import queryBuilderFetcher from './fluxQueryBuilder/apis/queryBuilderFetcher' -import {isExcludedStatement} from '../../../utils/queryFilter' +import {isExcludedStatement} from 'src/utils/queryFilter' interface ConnectedProps { script: string diff --git a/ui/src/shared/utils/TimeMachineContainer.ts b/ui/src/shared/utils/TimeMachineContainer.ts index 9174189d64..a548a364b2 100644 --- a/ui/src/shared/utils/TimeMachineContainer.ts +++ b/ui/src/shared/utils/TimeMachineContainer.ts @@ -27,7 +27,7 @@ import { setLocalStorage, TMLocalStorageKey, } from 'src/shared/utils/timeMachine' -import {isExcludedStatement} from '../../utils/queryFilter' +import {isExcludedStatement} from 'src/utils/queryFilter' // Constants import {TYPE_QUERY_CONFIG} from 'src/dashboards/constants'