You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ta...@apache.org on 2020/06/04 02:57:24 UTC
[incubator-superset] branch master updated: fix: fetch all owners
for dashboard, chart listview filters and properties modal (#9784)
This is an automated email from the ASF dual-hosted git repository.
tai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new d187d28 fix: fetch all owners for dashboard, chart listview filters and properties modal (#9784)
d187d28 is described below
commit d187d2887ea9348ffbc6de277ab56a1e0abab0f1
Author: ʈᵃᵢ <td...@gmail.com>
AuthorDate: Wed Jun 3 19:57:03 2020 -0700
fix: fetch all owners for dashboard, chart listview filters and properties modal (#9784)
---
.../javascripts/views/chartList/ChartList_spec.jsx | 2 +-
.../views/dashboardList/DashboardList_spec.jsx | 2 +-
.../views/datasetList/DatasetList_spec.jsx | 2 +-
.../src/components/ListView/Filters.tsx | 2 +-
superset-frontend/src/components/ListView/types.ts | 6 +-
superset-frontend/src/components/ListView/utils.ts | 1 +
.../src/explore/components/PropertiesModal.tsx | 6 +-
.../src/views/chartList/ChartList.tsx | 71 +++++++++++-------
.../src/views/dashboardList/DashboardList.tsx | 83 +++++++++++++---------
.../src/views/datasetList/DatasetList.tsx | 9 +--
10 files changed, 116 insertions(+), 68 deletions(-)
diff --git a/superset-frontend/spec/javascripts/views/chartList/ChartList_spec.jsx b/superset-frontend/spec/javascripts/views/chartList/ChartList_spec.jsx
index faf0c09..d5785bf 100644
--- a/superset-frontend/spec/javascripts/views/chartList/ChartList_spec.jsx
+++ b/superset-frontend/spec/javascripts/views/chartList/ChartList_spec.jsx
@@ -102,7 +102,7 @@ describe('ChartList', () => {
const callsD = fetchMock.calls(/chart\/\?q/);
expect(callsD).toHaveLength(1);
expect(callsD[0][0]).toMatchInlineSnapshot(
- `"/http//localhost/api/v1/chart/?q={%22order_column%22:%22changed_on%22,%22order_direction%22:%22desc%22,%22page%22:0,%22page_size%22:25}"`,
+ `"/http//localhost/api/v1/chart/?q=(order_column:changed_on,order_direction:desc,page:0,page_size:25)"`,
);
});
});
diff --git a/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx b/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
index 5dbcb81..086d9d1 100644
--- a/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
+++ b/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
@@ -92,7 +92,7 @@ describe('DashboardList', () => {
const callsD = fetchMock.calls(/dashboard\/\?q/);
expect(callsD).toHaveLength(1);
expect(callsD[0][0]).toMatchInlineSnapshot(
- `"/http//localhost/api/v1/dashboard/?q={%22order_column%22:%22changed_on%22,%22order_direction%22:%22desc%22,%22page%22:0,%22page_size%22:25}"`,
+ `"/http//localhost/api/v1/dashboard/?q=(order_column:changed_on,order_direction:desc,page:0,page_size:25)"`,
);
});
it('edits', () => {
diff --git a/superset-frontend/spec/javascripts/views/datasetList/DatasetList_spec.jsx b/superset-frontend/spec/javascripts/views/datasetList/DatasetList_spec.jsx
index b7b3e58..c393a98 100644
--- a/superset-frontend/spec/javascripts/views/datasetList/DatasetList_spec.jsx
+++ b/superset-frontend/spec/javascripts/views/datasetList/DatasetList_spec.jsx
@@ -92,7 +92,7 @@ describe('DatasetList', () => {
const callsD = fetchMock.calls(/dataset\/\?q/);
expect(callsD).toHaveLength(1);
expect(callsD[0][0]).toMatchInlineSnapshot(
- `"/http//localhost/api/v1/dataset/?q={%22order_column%22:%22changed_on%22,%22order_direction%22:%22desc%22,%22page%22:0,%22page_size%22:25}"`,
+ `"/http//localhost/api/v1/dataset/?q=(order_column:changed_on,order_direction:desc,page:0,page_size:25)"`,
);
});
});
diff --git a/superset-frontend/src/components/ListView/Filters.tsx b/superset-frontend/src/components/ListView/Filters.tsx
index a97e498..69421d5 100644
--- a/superset-frontend/src/components/ListView/Filters.tsx
+++ b/superset-frontend/src/components/ListView/Filters.tsx
@@ -116,7 +116,7 @@ function SelectFilter({
// TODO: allow real async search with `inputValue`
if (optionsCache.current) return optionsCache.current;
if (fetchSelects) {
- const selectValues = await fetchSelects();
+ const selectValues = await fetchSelects(inputValue);
// update matching option at initial load
const matchingOption = result.find(x => x.value === initialValue);
if (matchingOption) {
diff --git a/superset-frontend/src/components/ListView/types.ts b/superset-frontend/src/components/ListView/types.ts
index 0a1cc24..3df36a8 100644
--- a/superset-frontend/src/components/ListView/types.ts
+++ b/superset-frontend/src/components/ListView/types.ts
@@ -37,7 +37,11 @@ export interface Filter {
unfilteredLabel?: string;
selects?: SelectOption[];
onFilterOpen?: () => void;
- fetchSelects?: () => Promise<SelectOption[]>;
+ fetchSelects?: (
+ filterValue?: string,
+ pageIndex?: number,
+ pageSize?: number,
+ ) => Promise<SelectOption[]>;
}
export type Filters = Filter[];
diff --git a/superset-frontend/src/components/ListView/utils.ts b/superset-frontend/src/components/ListView/utils.ts
index 6ce2665..c77d05b 100644
--- a/superset-frontend/src/components/ListView/utils.ts
+++ b/superset-frontend/src/components/ListView/utils.ts
@@ -245,6 +245,7 @@ export function useListViewState({
const updatedFilters = updateInList(internalFilters, index, update);
setInternalFilters(updatedFilters);
setAllFilters(convertFilters(updatedFilters));
+ gotoPage(0); // clear pagination on filter
};
const removeFilterAndApply = (index: number) => {
diff --git a/superset-frontend/src/explore/components/PropertiesModal.tsx b/superset-frontend/src/explore/components/PropertiesModal.tsx
index 3a42cc8..622d5cf 100644
--- a/superset-frontend/src/explore/components/PropertiesModal.tsx
+++ b/superset-frontend/src/explore/components/PropertiesModal.tsx
@@ -120,7 +120,11 @@ function PropertiesModal({ slice, onHide, onSave }: InternalProps) {
}, []);
const loadOptions = (input = '') => {
- const query = rison.encode({ filter: input });
+ const query = rison.encode({
+ filter: input,
+ page_index: -1,
+ page_size: -1,
+ });
return SupersetClient.get({
endpoint: `/api/v1/chart/related/owners?q=${query}`,
}).then(
diff --git a/superset-frontend/src/views/chartList/ChartList.tsx b/superset-frontend/src/views/chartList/ChartList.tsx
index db5ed39..8fed532 100644
--- a/superset-frontend/src/views/chartList/ChartList.tsx
+++ b/superset-frontend/src/views/chartList/ChartList.tsx
@@ -22,6 +22,7 @@ import { getChartMetadataRegistry } from '@superset-ui/chart';
import moment from 'moment';
import PropTypes from 'prop-types';
import React from 'react';
+import rison from 'rison';
// @ts-ignore
import { Panel } from 'react-bootstrap';
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
@@ -281,7 +282,7 @@ class ChartList extends React.PureComponent<Props, State> {
handleBulkChartDelete = (charts: Chart[]) => {
SupersetClient.delete({
- endpoint: `/api/v1/chart/?q=!(${charts.map(({ id }) => id).join(',')})`,
+ endpoint: `/api/v1/chart/?q=${rison.encode(charts.map(({ id }) => id))}`,
}).then(
({ json = {} }) => {
const { lastFetchDataConfig } = this.state;
@@ -338,7 +339,7 @@ class ChartList extends React.PureComponent<Props, State> {
return [...acc, fltr];
}, []);
- const queryParams = JSON.stringify({
+ const queryParams = rison.encode({
order_column: sortBy[0].id,
order_direction: sortBy[0].desc ? 'desc' : 'asc',
page: pageIndex,
@@ -363,39 +364,60 @@ class ChartList extends React.PureComponent<Props, State> {
});
};
- createFetchResource = ({
- resource,
- postProcess,
- }: {
- resource: string;
- postProcess?: (value: []) => any[];
- }) => async () => {
+ fetchOwners = async (filterValue = '', pageIndex = -1, pageSize = -1) => {
+ const resource = '/api/v1/chart/related/owners';
+
try {
+ const queryParams = rison.encode({
+ page: pageIndex,
+ page_size: pageSize,
+ ...(filterValue ? { filter: filterValue } : {}),
+ });
const { json = {} } = await SupersetClient.get({
- endpoint: resource,
+ endpoint: `${resource}?q=${queryParams}`,
});
- return postProcess ? postProcess(json?.result) : json?.result;
+
+ return json?.result?.map(
+ ({ text: label, value }: { text: string; value: any }) => ({
+ label,
+ value,
+ }),
+ );
} catch (e) {
this.props.addDangerToast(
- t('An error occurred while fetching chart filters: %s', e.statusText),
+ t(
+ 'An error occurred while fetching chart owner values: %s',
+ e.statusText,
+ ),
);
}
return [];
};
- convertOwners = (owners: any[]) =>
- owners.map(({ text: label, value }) => ({ label, value }));
+ fetchDatasets = async () => {
+ const resource = '/api/v1/chart/datasources';
+ try {
+ const { json = {} } = await SupersetClient.get({
+ endpoint: `${resource}`,
+ });
- stringifyValues = (datasources: any[]) => {
- return datasources.map(ds => ({ ...ds, value: JSON.stringify(ds.value) }));
+ return json?.result?.map((ds: { label: string; value: any }) => ({
+ ...ds,
+ value: JSON.stringify(ds.value),
+ }));
+ } catch (e) {
+ this.props.addDangerToast(
+ t(
+ 'An error occurred while fetching chart dataset values: %s',
+ e.statusText,
+ ),
+ );
+ }
+ return [];
};
updateFilters = async () => {
const { filterOperators } = this.state;
- const fetchOwners = this.createFetchResource({
- resource: '/api/v1/chart/related/owners',
- postProcess: this.convertOwners,
- });
if (this.isNewUIEnabled) {
this.setState({
@@ -406,7 +428,7 @@ class ChartList extends React.PureComponent<Props, State> {
input: 'select',
operator: 'rel_m_m',
unfilteredLabel: 'All',
- fetchSelects: fetchOwners,
+ fetchSelects: this.fetchOwners,
},
{
Header: 'Viz Type',
@@ -424,10 +446,7 @@ class ChartList extends React.PureComponent<Props, State> {
input: 'select',
operator: 'eq',
unfilteredLabel: 'All',
- fetchSelects: this.createFetchResource({
- resource: '/api/v1/chart/datasources',
- postProcess: this.stringifyValues,
- }),
+ fetchSelects: this.fetchDatasets,
},
{
Header: 'Search',
@@ -448,7 +467,7 @@ class ChartList extends React.PureComponent<Props, State> {
operator: string;
}) => ({ label, value: operator });
- const owners = await fetchOwners();
+ const owners = await this.fetchOwners();
this.setState({
filters: [
{
diff --git a/superset-frontend/src/views/dashboardList/DashboardList.tsx b/superset-frontend/src/views/dashboardList/DashboardList.tsx
index 912c76d..829c6e3 100644
--- a/superset-frontend/src/views/dashboardList/DashboardList.tsx
+++ b/superset-frontend/src/views/dashboardList/DashboardList.tsx
@@ -21,6 +21,7 @@ import { t } from '@superset-ui/translation';
import moment from 'moment';
import PropTypes from 'prop-types';
import React from 'react';
+import rison from 'rison';
// @ts-ignore
import { Panel } from 'react-bootstrap';
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
@@ -48,7 +49,6 @@ interface State {
loading: boolean;
filterOperators: FilterOperatorMap;
filters: Filters;
- owners: Array<{ text: string; value: number }>;
permissions: string[];
lastFetchDataConfig: FetchDataConfig | null;
dashboardToEdit: Dashboard | null;
@@ -77,44 +77,31 @@ class DashboardList extends React.PureComponent<Props, State> {
filters: [],
lastFetchDataConfig: null,
loading: false,
- owners: [],
permissions: [],
dashboardToEdit: null,
};
componentDidMount() {
- Promise.all([
- SupersetClient.get({
- endpoint: `/api/v1/dashboard/_info`,
- }),
- SupersetClient.get({
- endpoint: `/api/v1/dashboard/related/owners`,
- }),
- ]).then(
- ([{ json: infoJson = {} }, { json: ownersJson = {} }]) => {
+ SupersetClient.get({
+ endpoint: `/api/v1/dashboard/_info`,
+ }).then(
+ ({ json: infoJson = {} }) => {
this.setState(
{
filterOperators: infoJson.filters,
- owners: ownersJson.result,
permissions: infoJson.permissions,
},
this.updateFilters,
);
},
- ([e1, e2]) => {
+ e => {
this.props.addDangerToast(
t(
'An error occurred while fetching Dashboards: %s, %s',
- e1.statusText,
- e1.statusText,
+ e.statusText,
),
);
- if (e1) {
- console.error(e1);
- }
- if (e2) {
- console.error(e2);
- }
+ console.error(e);
},
);
}
@@ -330,9 +317,9 @@ class DashboardList extends React.PureComponent<Props, State> {
handleBulkDashboardDelete = (dashboards: Dashboard[]) => {
SupersetClient.delete({
- endpoint: `/api/v1/dashboard/?q=!(${dashboards
- .map(({ id }) => id)
- .join(',')})`,
+ endpoint: `/api/v1/dashboard/?q=${rison.encode(
+ dashboards.map(({ id }) => id),
+ )}`,
}).then(
({ json = {} }) => {
const { lastFetchDataConfig } = this.state;
@@ -355,9 +342,9 @@ class DashboardList extends React.PureComponent<Props, State> {
handleBulkDashboardExport = (dashboards: Dashboard[]) => {
return window.location.assign(
- `/api/v1/dashboard/export/?q=!(${dashboards
- .map(({ id }) => id)
- .join(',')})`,
+ `/api/v1/dashboard/export/?q=${rison.encode(
+ dashboards.map(({ id }) => id).join(','),
+ )}`,
);
};
@@ -378,7 +365,7 @@ class DashboardList extends React.PureComponent<Props, State> {
value,
}));
- const queryParams = JSON.stringify({
+ const queryParams = rison.encode({
order_column: sortBy[0].id,
order_direction: sortBy[0].desc ? 'desc' : 'asc',
page: pageIndex,
@@ -402,8 +389,38 @@ class DashboardList extends React.PureComponent<Props, State> {
});
};
- updateFilters = () => {
- const { filterOperators, owners } = this.state;
+ fetchOwners = async (filterValue = '', pageIndex = -1, pageSize = -1) => {
+ const resource = '/api/v1/dashboard/related/owners';
+
+ try {
+ const queryParams = rison.encode({
+ page: pageIndex,
+ page_size: pageSize,
+ ...(filterValue ? { filter: filterValue } : {}),
+ });
+ const { json = {} } = await SupersetClient.get({
+ endpoint: `${resource}?q=${queryParams}`,
+ });
+
+ return json?.result?.map(
+ ({ text: label, value }: { text: string; value: any }) => ({
+ label,
+ value,
+ }),
+ );
+ } catch (e) {
+ this.props.addDangerToast(
+ t(
+ 'An error occurred while fetching chart owner values: %s',
+ e.statusText,
+ ),
+ );
+ }
+ return [];
+ };
+
+ updateFilters = async () => {
+ const { filterOperators } = this.state;
if (this.isNewUIEnabled) {
return this.setState({
@@ -414,7 +431,7 @@ class DashboardList extends React.PureComponent<Props, State> {
input: 'select',
operator: 'rel_m_m',
unfilteredLabel: 'All',
- selects: owners.map(({ text: label, value }) => ({ label, value })),
+ fetchSelects: this.fetchOwners,
},
{
Header: 'Published',
@@ -445,6 +462,8 @@ class DashboardList extends React.PureComponent<Props, State> {
operator: string;
}) => ({ label, value: operator });
+ const owners = await this.fetchOwners();
+
return this.setState({
filters: [
{
@@ -462,7 +481,7 @@ class DashboardList extends React.PureComponent<Props, State> {
id: 'owners',
input: 'select',
operators: filterOperators.owners.map(convertFilter),
- selects: owners.map(({ text: label, value }) => ({ label, value })),
+ selects: owners,
},
{
Header: 'Published',
diff --git a/superset-frontend/src/views/datasetList/DatasetList.tsx b/superset-frontend/src/views/datasetList/DatasetList.tsx
index 43821b0..c832290 100644
--- a/superset-frontend/src/views/datasetList/DatasetList.tsx
+++ b/superset-frontend/src/views/datasetList/DatasetList.tsx
@@ -21,6 +21,7 @@ import { t } from '@superset-ui/translation';
import moment from 'moment';
import PropTypes from 'prop-types';
import React from 'react';
+import rison from 'rison';
// @ts-ignore
import { Panel } from 'react-bootstrap';
import Link from 'src/components/Link';
@@ -273,9 +274,9 @@ class DatasetList extends React.PureComponent<Props, State> {
handleBulkDatasetDelete = (datasets: Dataset[]) => {
SupersetClient.delete({
- endpoint: `/api/v1/dataset/?q=!(${datasets
- .map(({ id }) => id)
- .join(',')})`,
+ endpoint: `/api/v1/dataset/?q=${rison.encode(
+ datasets.map(({ id }) => id),
+ )}`,
}).then(
({ json = {} }) => {
const { lastFetchDataConfig } = this.state;
@@ -310,7 +311,7 @@ class DatasetList extends React.PureComponent<Props, State> {
value,
}));
- const queryParams = JSON.stringify({
+ const queryParams = rison.encode({
order_column: sortBy[0].id,
order_direction: sortBy[0].desc ? 'desc' : 'asc',
page: pageIndex,