Files
superset2/superset-frontend/src/explore/AdhocMetric.js
Jesse Yang 81ab8dd8b4 feat: upgrade react-select and make multi-select sortable (#9628)
* feat: upgrade react-select v1.3.0 to v3.1.0

Upgrade `react-select`, replace `react-virtualized-select` with a custom
solution implemented with `react-window`.

Future plans include deprecate `react-virtualized` used in other places, too.

Migrate all react-select related components to `src/Components/Select`.

* Fix new list view

* Fix tests

* Address PR comments

* Fix a flacky Cypress test

* Adjust styles for Select in CRUD ListView

* Fix loadOptions for owners select in chart PropertiesModal

TODO: add typing support for AsyncSelect props.

* Address PR comments; allow isMulti in SelectControl, too

* Clean up NaN in table filter values

* Fix flacky test
2020-05-19 16:59:49 -07:00

142 lines
4.4 KiB
JavaScript

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { sqlaAutoGeneratedMetricRegex } from './constants';
export const EXPRESSION_TYPES = {
SIMPLE: 'SIMPLE',
SQL: 'SQL',
};
function inferSqlExpressionColumn(adhocMetric) {
if (
adhocMetric.sqlExpression &&
sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)
) {
const indexFirstCloseParen = adhocMetric.sqlExpression.indexOf(')');
const indexPairedOpenParen = adhocMetric.sqlExpression
.substring(0, indexFirstCloseParen)
.lastIndexOf('(');
if (indexFirstCloseParen > 0 && indexPairedOpenParen > 0) {
return adhocMetric.sqlExpression.substring(
indexPairedOpenParen + 1,
indexFirstCloseParen,
);
}
}
return null;
}
function inferSqlExpressionAggregate(adhocMetric) {
if (
adhocMetric.sqlExpression &&
sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)
) {
const indexFirstOpenParen = adhocMetric.sqlExpression.indexOf('(');
if (indexFirstOpenParen > 0) {
return adhocMetric.sqlExpression.substring(0, indexFirstOpenParen);
}
}
return null;
}
export default class AdhocMetric {
constructor(adhocMetric) {
this.expressionType = adhocMetric.expressionType || EXPRESSION_TYPES.SIMPLE;
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
// try to be clever in the case of transitioning from Sql expression back to simple expression
const inferredColumn = inferSqlExpressionColumn(adhocMetric);
this.column =
adhocMetric.column ||
(inferredColumn && { column_name: inferredColumn });
this.aggregate =
adhocMetric.aggregate || inferSqlExpressionAggregate(adhocMetric);
this.sqlExpression = null;
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
this.sqlExpression = adhocMetric.sqlExpression;
this.column = null;
this.aggregate = null;
}
this.isNew = !!adhocMetric.isNew;
this.hasCustomLabel = !!(adhocMetric.hasCustomLabel && adhocMetric.label);
this.label = this.hasCustomLabel
? adhocMetric.label
: this.getDefaultLabel();
this.optionName =
adhocMetric.optionName ||
`metric_${Math.random()
.toString(36)
.substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
}
getDefaultLabel() {
const label = this.translateToSql();
return label.length < 43 ? label : label.substring(0, 40) + '...';
}
translateToSql() {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
return `${this.aggregate || ''}(${
(this.column && this.column.column_name) || ''
})`;
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
return this.sqlExpression;
}
return '';
}
duplicateWith(nextFields) {
return new AdhocMetric({
...this,
// all duplicate metrics are not considered new by default
isNew: false,
// but still overriddable by nextFields
...nextFields,
});
}
equals(adhocMetric) {
return (
adhocMetric.label === this.label &&
adhocMetric.expressionType === this.expressionType &&
adhocMetric.sqlExpression === this.sqlExpression &&
adhocMetric.aggregate === this.aggregate &&
(adhocMetric.column && adhocMetric.column.column_name) ===
(this.column && this.column.column_name)
);
}
isValid() {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
return !!(this.column && this.aggregate);
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
return !!this.sqlExpression;
}
return false;
}
inferSqlExpressionAggregate() {
return inferSqlExpressionAggregate(this);
}
inferSqlExpressionColumn() {
return inferSqlExpressionColumn(this);
}
}