in src/components/QueryEditor.tsx [668:944]
render() {
const filters = this.props.query.filters == null ? [] : this.props.query.filters;
const selects = this.props.query.selects == null ? [{ ...EMPTY_SELECT }] : this.props.query.selects;
if (this.props.query.selects === null && this.state.schema != null) {
selects[0].selectedAggregations = [getDefaultFunctionDescription(this.state.schema)];
}
return (
<div className={css({ display: 'flex' })}>
<div className={css({ flexGrow: 1 })}>
{this.props.query.raw ? (
<TextArea
aria-label="query"
rows={3}
spellCheck={false}
placeholder="QQL Query"
onBlur={this.requestData}
onChange={this.onChangeRawQuery}
value={this.props.query.rawQuery}
/>
) : (
<>
<div className={cx('w-100', commonStyles)}>
<SegmentFrame title="STREAM">
<FieldValidation
invalid={!this.state.validStreamControl}
text={getReplacedValue(
`No stream ${this.state.selectedStream?.value}`,
this.props.datasource.scopedVars
)}
>
<Select
backspaceRemovesValue={true}
classNamePrefix="grafana-custom"
className={cx('select width-10 z-100', commonStyles)}
value={this.state.selectedStream}
options={this.state.streams.map(toOption)}
onChange={this.onChangeStream}
onInputChange={this.onStreamInputChange}
></Select>
</FieldValidation>
<div>
<SegmentFrame
className={cx('gf-form mb-0', commonStyles)}
resetTitleWidth={true}
title="WHERE"
hideShadow={true}
options={getFilterFields(this.state.schema?.types)}
onChange={this.addFilter}
>
{filters.length !== 0 ? (
<SegmentFrameFilter
validStreamControl={this.state.validStreamControl}
validSymbolControl={this.state.validSymbolControl}
queryError={this.props.datasource.queryError}
filter={filters[0]}
index={0}
schema={this.state.schema}
invalid={this.state.invalidFieldsMap[filters[0].field]}
onChangeFilter={this.onChangeFilter}
removeFilter={this.removeFilter}
/>
) : null}
</SegmentFrame>
{filters.map((filter, index) => {
return index === 0 ? null : (
<div className={cx('gf-form-inline w-100', commonStyles)}>
<SegmentFrameFilter
title="AND"
validStreamControl={this.state.validStreamControl}
validSymbolControl={this.state.validSymbolControl}
queryError={this.props.datasource.queryError}
filter={filter}
index={index}
schema={this.state.schema}
invalid={this.state.invalidFieldsMap[filter.field]}
onChangeFilter={this.onChangeFilter}
removeFilter={this.removeFilter}
/>
</div>
);
})}
</div>
</SegmentFrame>
</div>
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
<div className="gf-form">
<span className="gf-form-label width-8 query-keyword">SYMBOL</span>
</div>
<FieldValidation
invalid={this.state.validStreamControl && !this.state.validSymbolControl &&
this.state.selectedSymbol?.[0].value !== ALL_KEY }
text={getReplacedValue(
`No symbols [${this.state.selectedSymbol?.[0]?.value}] in ${this.state.selectedStream?.value}.`,
this.props.datasource.scopedVars
)}
>
<MultiSelect
options={this.state.symbols.map(toOption)}
className={cx('mr-4 width-22')}
value={this.state.selectedSymbol}
onKeyDown={this.onKeyPress}
onChange={this.onChangeSymbolList}
onInputChange={this.onInputChange}
/>
</FieldValidation>
<div className="gf-form-label gf-form-label--grow"></div>
</div>
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
{selects.map((select, index) => {
return (
<SegmentFrame
key={index}
index={index}
title={index === 0 ? 'SELECT' : ''}
options={this.getSelectOptions(index)}
onChange={this.addSelectSection}
>
{select.selectedField != null && select.selectedRecordType != null ? (
<FieldValidation
invalid={
this.state.validStreamControl &&
this.state.validSymbolControl &&
this.state.invalidFieldsMap[
getTypeWithField(select.selectedField, select.selectedRecordType)
]
}
text={getErrorForFields(
select.selectedRecordType,
select.selectedField,
this.state.schema?.types,
this.props.datasource.queryError
)}
>
<FieldLabel
value={select.selectedField}
type={select.selectedRecordType}
onRemove={() => this.removeField(index)}
items={getFilteredListFields(
getTypeWithField(select.selectedField, select.selectedRecordType),
getFilterFields(this.state.schema?.types)
)}
onChange={(item: string) => this.onChangeField(item, index)}
/>
</FieldValidation>
) : null}
{select.selectedFunction != null ? (
<FunctionComponent
value={select.selectedFunction}
index={index}
scopedVars={this.props.datasource.scopedVars}
invalidFieldsMap={this.state.invalidFieldsMap}
queryError={this.props.datasource.queryError}
mainValid={this.state.validStreamControl && this.state.validSymbolControl}
schema={this.state.schema as Schema}
onChangeFunction={this.onChangeFunctionByIndex}
description={
this.state.schema?.functions.find(
(f) => f.id === select.selectedFunction?.id
) as FunctionDeclaration
}
onRemove={this.removeField}
/>
) : null}
{select.selectedAggregations.map((aggregation) => (
<FunctionComponent
key={index}
index={index}
disableColoring={true}
scopedVars={this.props.datasource.scopedVars}
schema={this.state.schema as Schema}
description={
this.state.schema?.functions.find((f) => f.id === aggregation.id) as FunctionDeclaration
}
value={aggregation}
invalidFieldsMap={this.state.invalidFieldsMap}
queryError={this.props.datasource.queryError}
mainValid={this.state.validStreamControl && this.state.validSymbolControl}
dependsSelect={select}
onRemove={(index) => this.removeAggregation(aggregation.id, index)}
onChangeFunction={this.changeAggregation}
/>
))}
</SegmentFrame>
);
})}
</div>
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
<SegmentFrame
title="GROUP BY"
options={getGroupsFields(this.state.schema?.types)}
onChange={this.addGroup}
>
<TimeGrouping
scopedVars={this.props.datasource.scopedVars}
value={this.getCurrentInterval()}
intervals={this.props.datasource.intervals}
onChangeInterval={this.onChangeInterval}
/>
{this.props.query.selectedGroups != null
? this.props.query.selectedGroups.map((group, index) => {
return (
<FieldValidation
key={index}
invalid={
this.state.validStreamControl &&
this.state.validSymbolControl &&
(this.state.invalidFieldsMap[group] || this.props.datasource.queryError != null)
}
text={getErrorForFields(
separateTypeAndField(group)[0],
separateTypeAndField(group)[1],
this.state.schema?.types,
this.props.datasource.queryError,
true
)}
>
<FieldLabel
value={separateTypeAndField(group)[1]}
type={separateTypeAndField(group)[0]}
onRemove={() => this.removeGroup(index)}
items={getFilteredListFields(group, getGroupsFields(this.state.schema?.types))}
onChange={(item: string) => this.onChangeGroup(item, index)}
/>
</FieldValidation>
);
})
: null}
</SegmentFrame>
</div>
{this.props.query.selectedGroups == null || this.props.query.selectedGroups.length === 0 ? null : (
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
<SegmentFrame title="OPTION">
<CustomSelect
value={toOption(this.props.query.selectedOption || COLUMN_KEY)}
options={this.state.groupByViewOptions}
onChange={this.onChangeOrientation}
/>
</SegmentFrame>
</div>
)}
</>
)}
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
<SegmentFrame title="VIEW">
<CustomSelect
value={toOption(this.props.query.requestType || DATAFRAME_KEY)}
options={VIEWS.map(toOption)}
onChange={this.onChangeView}
/>
</SegmentFrame>
</div>
<div className={cx('gf-form-inline w-100 ', commonStyles)}>
<SegmentFrame title="MAX RECORDS">
<Input
type="number"
className={cx('input', commonStyles)}
value={this.props.query.maxRecords}
defaultValue={10000}
onChange={this.onChangeMaxRecords}
width={10}
/>
</SegmentFrame>
</div>
</div>
<QueryEditorModeSwitcher
isRaw={this.props.query.raw ?? false}
onChange={(value: any) => {
this.props.onChange({ ...this.props.query, raw: value });
this.requestData();
}}
/>
</div>
);
}