Compare commits

...

9 Commits

Author SHA1 Message Date
Yongjie Zhao
961b9da4f4 fix: prevent page crash when chart can't render (#16464)
(cherry picked from commit 577ede4b12)
2021-08-26 12:48:37 -07:00
Grace Guo
f6bb1cdd9f fix: setupPlugin in chart list page (#16413)
* fix: setupPlugin in chart list page

* fix the order of setupPlugins call

* Fix jest test on loading geojson

* add jest changes

* fix unit tests

Co-authored-by: Jesse Yang <jesse.yang@airbnb.com>
(cherry picked from commit 08b8aa277f)
2021-08-26 12:47:48 -07:00
Ville Brofeldt
53dea71832 fix(native-filters): handle null values in value filter (#16460)
* fix(native-filters): handle null values in value filter

* lint

(cherry picked from commit 1c71eda70f)
2021-08-26 12:47:28 -07:00
Steven Uray
4fce06e7a3 Revert "Cherrying in content from 16210"
This reverts commit 401cb603d8.
2021-08-25 15:54:56 -07:00
Elizabeth Thompson
79cfad10cf Revert "fix: reverting Dataset names (#16243)"
This reverts commit 4119bb9c1e.

(cherry picked from commit 3feb9d3ff9)
2021-08-24 20:04:54 -07:00
Steven Uray
5bc6ce8325 Cherrying in content from 16242 2021-08-24 20:04:16 -07:00
Steven Uray
401cb603d8 Cherrying in content from 16210 2021-08-24 20:03:10 -07:00
Steven Uray
7d9cb04836 Cherrying in content from 16206 2021-08-24 20:01:56 -07:00
AAfghahi
a235f5b28e feat: Changing Dataset names (#16199)
* added google alert

* changing Dataset Names

(cherry picked from commit 6c304b83a9)
2021-08-24 19:40:28 -07:00
38 changed files with 80 additions and 51 deletions

View File

@@ -66,7 +66,7 @@ Navigate to **Data ‣ Datasets** and select the **+ Dataset** button in the top
A modal window should pop up in front of you. Select your **Database**,
**Schema**, and **Table** using the drop downs that appear. In the following example,
we register the **cleaned_sales_data** table from the **examples** database.
we register the **Vehicle Sales** table from the **examples** database.
<img src="/images/tutorial_09_add_new_table.png" />

View File

@@ -19,8 +19,8 @@
module.exports = {
testRegex: '(\\/spec|\\/src)\\/.*(_spec|\\.test)\\.(j|t)sx?$',
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/spec/__mocks__/styleMock.js',
'\\.(gif|ttf|eot|png|jpg)$': '<rootDir>/spec/__mocks__/fileMock.js',
'\\.(css|less|geojson)$': '<rootDir>/spec/__mocks__/mockExportObject.js',
'\\.(gif|ttf|eot|png|jpg)$': '<rootDir>/spec/__mocks__/mockExportString.js',
'\\.svg$': '<rootDir>/spec/__mocks__/svgrMock.tsx',
'^src/(.*)$': '<rootDir>/src/$1',
'^spec/(.*)$': '<rootDir>/spec/$1',

View File

@@ -23,3 +23,5 @@ import { configure as configureTestingLibrary } from '@testing-library/react';
configureTestingLibrary({
testIdAttribute: 'data-test',
});
document.body.innerHTML = '<div id="app" data-bootstrap="{}"></div>';

View File

@@ -25,6 +25,7 @@ import OmniContainer from './index';
jest.mock('src/featureFlags', () => ({
isFeatureEnabled: jest.fn(),
FeatureFlag: { OMNIBAR: 'OMNIBAR' },
initFeatureFlags: jest.fn(),
}));
test('Do not open Omnibar with the featureflag disabled', () => {

View File

@@ -47,7 +47,6 @@ type PickedSelectProps = Pick<
AntdSelectAllProps,
| 'allowClear'
| 'autoFocus'
| 'value'
| 'disabled'
| 'filterOption'
| 'notFoundContent'

View File

@@ -224,7 +224,7 @@ export const DataTablesPane = ({
}, [queryFormData.adhoc_filters, queryFormData.datasource]);
useEffect(() => {
if (queriesResponse) {
if (queriesResponse && chartStatus === 'success') {
const { colnames } = queriesResponse[0];
setColumnNames([...colnames]);
}

View File

@@ -48,7 +48,7 @@ const createProps = () => ({
cache_timeout: null,
changed_on: '2021-03-19T16:30:56.750230',
changed_on_humanized: '3 days ago',
datasource: 'FCC 2018 Survey',
datasource: 'FCC Survey Results',
description: null,
description_markeddown: '',
edit_url: '/chart/edit/318',

View File

@@ -29,7 +29,7 @@ const createProps = () => ({
cache_timeout: null,
changed_on: '2021-03-19T16:30:56.750230',
changed_on_humanized: '7 days ago',
datasource: 'FCC 2018 Survey',
datasource: 'FCC Survey Results',
description: null,
description_markeddown: '',
edit_url: '/chart/edit/318',

View File

@@ -31,7 +31,7 @@ test('Get ChartUri when allowDomainSharding:false', () => {
duplicateQueryParameters: false,
escapeQuerySpace: true,
fragment: null,
hostname: undefined,
hostname: 'localhost',
password: null,
path: '/path',
port: '',

View File

@@ -33,13 +33,13 @@ const createParams = () => ({
test('Get ExploreUrl with default params', () => {
const params = createParams();
expect(getExploreUrl(params)).toBe('http:///superset/explore/');
expect(getExploreUrl(params)).toBe('http://localhost/superset/explore/');
});
test('Get ExploreUrl with endpointType:full', () => {
const params = createParams();
expect(getExploreUrl({ ...params, endpointType: 'full' })).toBe(
'http:///superset/explore_json/',
'http://localhost/superset/explore_json/',
);
});
@@ -47,5 +47,5 @@ test('Get ExploreUrl with endpointType:full and method:GET', () => {
const params = createParams();
expect(
getExploreUrl({ ...params, endpointType: 'full', method: 'GET' }),
).toBe('http:///superset/explore_json/');
).toBe('http://localhost/superset/explore_json/');
});

View File

@@ -20,6 +20,7 @@
import {
AppSection,
DataMask,
DataRecordValue,
ensureIsArray,
ExtraFormData,
GenericDataType,
@@ -36,7 +37,11 @@ import { useImmerReducer } from 'use-immer';
import { FormItemProps } from 'antd/lib/form';
import { PluginFilterSelectProps, SelectValue } from './types';
import { StyledFormItem, FilterPluginStyle, StatusMessage } from '../common';
import { getDataRecordFormatter, getSelectExtraFormData } from '../../utils';
import {
formatFilterValue,
getDataRecordFormatter,
getSelectExtraFormData,
} from '../../utils';
type DataMaskAction =
| { type: 'ownState'; ownState: JsonObject }
@@ -119,7 +124,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
filterState: {
...filterState,
label: values?.length
? `${(values || []).join(', ')}${suffix}`
? `${(values || []).map(formatFilterValue).join(', ')}${suffix}`
: undefined,
value:
appSection === AppSection.FILTER_CONFIG_MODAL && defaultToFirstItem
@@ -249,12 +254,12 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
}
const options = useMemo(() => {
const options: { label: string; value: string | number }[] = [];
const options: { label: string; value: DataRecordValue }[] = [];
data.forEach(row => {
const [value] = groupby.map(col => row[col]);
options.push({
label: labelFormatter(value, datatype),
value: typeof value === 'number' ? value : String(value),
value,
});
});
return options;
@@ -286,6 +291,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
loading={isRefreshing}
maxTagCount={5}
invertSelection={inverseSelection}
// @ts-ignore
options={options}
/>
</StyledFormItem>

View File

@@ -28,7 +28,7 @@ import { FALSE_STRING, NULL_STRING, TRUE_STRING } from 'src/utils/common';
export const getSelectExtraFormData = (
col: string,
value?: null | (string | number)[],
value?: null | (string | number | boolean | null)[],
emptyFilter = false,
inverseSelection = false,
): ExtraFormData => {
@@ -46,6 +46,7 @@ export const getSelectExtraFormData = (
{
col,
op: inverseSelection ? ('NOT IN' as const) : ('IN' as const),
// @ts-ignore
val: value,
},
];
@@ -116,3 +117,18 @@ export function getDataRecordFormatter({
return String(value);
};
}
export function formatFilterValue(
value: string | number | boolean | null,
): string {
if (value === null) {
return NULL_STRING;
}
if (typeof value === 'string') {
return value;
}
if (typeof value === 'number') {
return String(value);
}
return value ? TRUE_STRING : FALSE_STRING;
}

View File

@@ -57,6 +57,7 @@ import Chart from 'src/types/Chart';
import { Tooltip } from 'src/components/Tooltip';
import Icons from 'src/components/Icons';
import { nativeFilterGate } from 'src/dashboard/components/nativeFilters/utils';
import setupPlugins from 'src/setup/setupPlugins';
import ChartCard from './ChartCard';
const PAGE_SIZE = 25;
@@ -73,6 +74,7 @@ const CONFIRM_OVERWRITE_MESSAGE = t(
'sure you want to overwrite?',
);
setupPlugins();
const registry = getChartMetadataRegistry();
const createFetchDatasets = (handleError: (err: Response) => void) => async (

View File

@@ -27,7 +27,7 @@ from .helpers import get_example_data, get_table_connector_registry
def load_bart_lines(only_metadata: bool = False, force: bool = False) -> None:
tbl_name = "bart_lines"
tbl_name = "San Franciso BART Lines"
database = get_example_database()
table_exists = database.has_table_by_name(tbl_name)

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: FCC 2018 Survey
table_name: FCC Survey Results
main_dttm_col: null
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: channel_members
table_name: Slack Channels and Members
main_dttm_col: null
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: channels
table_name: Slack Channels
main_dttm_col: created
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: cleaned_sales_data
table_name: Vehicle Sales
main_dttm_col: OrderDate
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: covid_vaccines
table_name: COVID Vaccines
main_dttm_col: null
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: exported_stats
table_name: Slack Exported Metrics
main_dttm_col: Date
description: null
default_endpoint: null

View File

@@ -14,15 +14,15 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: members_channels_2
table_name: Slack Members and Channels
main_dttm_col: null
description: null
default_endpoint: null
offset: 0
cache_timeout: null
schema: null
sql: SELECT c.name AS channel_name, u.name AS member_name FROM channel_members cm
JOIN channels c ON cm.channel_id = c.id JOIN users u ON cm.user_id = u.id
sql: SELECT c.name AS channel_name, u.name AS member_name FROM "Slack Channels and Members" cm
JOIN "Slack Channels" c ON cm.channel_id = c.id JOIN "Slack Users" u ON cm.user_id = u.id
params: null
template_params: null
filter_select_enabled: true

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: messages
table_name: Slack Messages
main_dttm_col: bot_profile__updated
description: null
default_endpoint: null

View File

@@ -14,14 +14,14 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: messages_channels
table_name: Slack Messages and Channels
main_dttm_col: null
description: null
default_endpoint: null
offset: 0
cache_timeout: null
schema: null
sql: SELECT m.ts, c.name, m.text FROM messages m JOIN channels c ON m.channel_id =
sql: SELECT m.ts, c.name, m.text FROM "Slack Messages" m JOIN "Slack Channels" c ON m.channel_id =
c.id
params: null
template_params: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: new_members_daily
table_name: Slack Daily Member Count
main_dttm_col: null
description: null
default_endpoint: null
@@ -22,7 +22,7 @@ offset: 0
cache_timeout: null
schema: null
sql: SELECT date, total_membership - lag(total_membership) OVER (ORDER BY date) AS
new_members FROM exported_stats
new_members FROM "Slack Exported Metrics"
params: null
template_params: null
filter_select_enabled: true

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: threads
table_name: Slack Threads
main_dttm_col: ts
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: users
table_name: Slack Users
main_dttm_col: updated
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: users_channels-uzooNNtSRO
table_name: Slack Channel Combinations and Users
main_dttm_col: null
description: null
default_endpoint: null
@@ -23,8 +23,8 @@ cache_timeout: null
schema: null
sql: >
SELECT uc1.name as channel_1, uc2.name as channel_2, count(*) AS cnt
FROM users_channels uc1
JOIN users_channels uc2 ON uc1.user_id = uc2.user_id
FROM "Slack Users and Channels" uc1
JOIN "Slack Users and Channels" uc2 ON uc1.user_id = uc2.user_id
GROUP BY uc1.name, uc2.name
HAVING uc1.name <> uc2.name
params: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: users_channels
table_name: Slack Users and Channels
main_dttm_col: null
description: null
default_endpoint: null

View File

@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
table_name: video_game_sales
table_name: Video Game Sales
main_dttm_col: null
description: null
default_endpoint: null

View File

@@ -176,7 +176,7 @@ def load_deck_dash() -> None:
print("Loading deck.gl dashboard")
slices = []
table = get_table_connector_registry()
tbl = db.session.query(table).filter_by(table_name="long_lat").first()
tbl = db.session.query(table).filter_by(table_name="Sample Geodata").first()
slice_data = {
"spatial": {"type": "latlong", "lonCol": "LON", "latCol": "LAT"},
"color_picker": COLOR_RED,
@@ -324,7 +324,9 @@ def load_deck_dash() -> None:
slices.append(slc)
polygon_tbl = (
db.session.query(table).filter_by(table_name="sf_population_polygons").first()
db.session.query(table)
.filter_by(table_name="San Francisco Population Polygons")
.first()
)
slice_data = {
"datasource": "11__table",
@@ -457,7 +459,7 @@ def load_deck_dash() -> None:
viz_type="deck_arc",
datasource_type="table",
datasource_id=db.session.query(table)
.filter_by(table_name="flights")
.filter_by(table_name="Flights")
.first()
.id,
params=get_slice_json(slice_data),
@@ -509,7 +511,7 @@ def load_deck_dash() -> None:
viz_type="deck_path",
datasource_type="table",
datasource_id=db.session.query(table)
.filter_by(table_name="bart_lines")
.filter_by(table_name="San Franciso BART Lines")
.first()
.id,
params=get_slice_json(slice_data),

View File

@@ -56,7 +56,7 @@ def load_energy(
method="multi",
)
print("Creating table [wb_health_population] reference")
print("Creating table [World Bank Health Data] reference")
table = get_table_connector_registry()
tbl = db.session.query(table).filter_by(table_name=tbl_name).first()
if not tbl:

View File

@@ -25,7 +25,7 @@ from .helpers import get_example_data, get_table_connector_registry
def load_flights(only_metadata: bool = False, force: bool = False) -> None:
"""Loading random time series data from a zip file in the repo"""
tbl_name = "flights"
tbl_name = "Flights"
database = utils.get_example_database()
table_exists = database.has_table_by_name(tbl_name)

View File

@@ -36,7 +36,7 @@ from .helpers import (
def load_long_lat_data(only_metadata: bool = False, force: bool = False) -> None:
"""Loading lat/long data from a csv file in the repo"""
tbl_name = "long_lat"
tbl_name = "Sample Geodata"
database = utils.get_example_database()
table_exists = database.has_table_by_name(tbl_name)

View File

@@ -28,7 +28,7 @@ from .helpers import get_example_data, get_table_connector_registry
def load_sf_population_polygons(
only_metadata: bool = False, force: bool = False
) -> None:
tbl_name = "sf_population_polygons"
tbl_name = "San Francisco Population Polygons"
database = utils.get_example_database()
table_exists = database.has_table_by_name(tbl_name)

View File

@@ -45,7 +45,7 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals
only_metadata: bool = False, force: bool = False, sample: bool = False,
) -> None:
"""Loads the world bank health dataset, slices and a dashboard"""
tbl_name = "wb_health_population"
tbl_name = "World Bank Health Data"
database = utils.get_example_database()
table_exists = database.has_table_by_name(tbl_name)
@@ -76,7 +76,7 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals
index=False,
)
print("Creating table [wb_health_population] reference")
print("Creating table [World Bank Health Data] reference")
table = get_table_connector_registry()
tbl = db.session.query(table).filter_by(table_name=tbl_name).first()
if not tbl:

View File

@@ -457,7 +457,7 @@ def cast_to_num(value: Optional[Union[float, int, str]]) -> Optional[Union[float
return None
def cast_to_boolean(value: Any) -> bool:
def cast_to_boolean(value: Any) -> Optional[bool]:
"""Casts a value to an int/float
>>> cast_to_boolean(1)
@@ -473,12 +473,13 @@ def cast_to_boolean(value: Any) -> bool:
>>> cast_to_boolean('False')
False
>>> cast_to_boolean(None)
False
:param value: value to be converted to boolean representation
:returns: value cast to `bool`. when value is 'true' or value that are not 0
converte into True
converted into True. Return `None` if value is `None`
"""
if value is None:
return None
if isinstance(value, (int, float)):
return value != 0
if isinstance(value, str):