mirror of
https://github.com/apache/superset.git
synced 2026-04-28 12:34:23 +00:00
Compare commits
9 Commits
docs/testi
...
v2021.34.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
961b9da4f4 | ||
|
|
f6bb1cdd9f | ||
|
|
53dea71832 | ||
|
|
4fce06e7a3 | ||
|
|
79cfad10cf | ||
|
|
5bc6ce8325 | ||
|
|
401cb603d8 | ||
|
|
7d9cb04836 | ||
|
|
a235f5b28e |
@@ -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" />
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -47,7 +47,6 @@ type PickedSelectProps = Pick<
|
||||
AntdSelectAllProps,
|
||||
| 'allowClear'
|
||||
| 'autoFocus'
|
||||
| 'value'
|
||||
| 'disabled'
|
||||
| 'filterOption'
|
||||
| 'notFoundContent'
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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: '',
|
||||
|
||||
@@ -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/');
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user