Compare commits

...

4 Commits

Author SHA1 Message Date
Daniel Vaz Gaspar
ce05a3dde3 fix: database alpha permissions (#12136)
* fix: database alpha permissions

* add test

(cherry picked from commit 2f0add3aec)
2020-12-21 15:18:19 -08:00
Beto Dealmeida
c6a08fdc46 fix: make example table name safe (#12135)
(cherry picked from commit 81f5631fe5)
2020-12-21 15:14:02 -08:00
Jesse Yang
09589059a1 fix: properly render booleans in FilterBox and explore page data preview (#12116)
(cherry picked from commit 8e625e0a64)
2020-12-21 15:13:49 -08:00
Jesse Yang
666e08b819 fix: FilterBox select lose focus when focused (#12114)
(cherry picked from commit af130ea5e9)
2020-12-21 15:13:36 -08:00
9 changed files with 78 additions and 43 deletions

View File

@@ -65,27 +65,21 @@ describe('Dashboard filter', () => {
cy.wait(aliases); cy.wait(aliases);
}); });
}); });
xit('should apply filter', () => {
cy.get('.Select__control input[type=text]') it('should apply filter', () => {
.first() cy.get('.Select__placeholder:first').click();
.should('be.visible')
.focus();
// should open the filter indicator // should open the filter indicator
cy.get('[data-test="filter"]') cy.get('svg[data-test="filter"]')
.should('be.visible', { timeout: 10000 }) .should('be.visible')
.should(nodes => { .should(nodes => {
expect(nodes).to.have.length(9); // this part was not working, xit-ed expect(nodes).to.have.length(9);
}); });
cy.get('[data-test="chart-container"]').find('svg').should('be.visible'); cy.get('.Select__control:first input[type=text]').type('So', {
force: true,
cy.get('.Select__control input[type=text]').first().focus().blur(); delay: 100,
});
cy.get('.Select__control input[type=text]')
.first()
.focus()
.type('So', { force: true, delay: 100 });
cy.get('.Select__menu').first().contains('South Asia').click(); cy.get('.Select__menu').first().contains('South Asia').click();

View File

@@ -19,6 +19,9 @@
"eslint-plugin-cypress": "^2.11.1" "eslint-plugin-cypress": "^2.11.1"
}, },
"nyc": { "nyc": {
"reporter": ["html", "json"] "reporter": [
"html",
"json"
]
} }
} }

View File

@@ -19,3 +19,6 @@
export const DATETIME_WITH_TIME_ZONE = 'YYYY-MM-DD HH:mm:ssZ'; export const DATETIME_WITH_TIME_ZONE = 'YYYY-MM-DD HH:mm:ssZ';
export const TIME_WITH_MS = 'HH:mm:ss.SSS'; export const TIME_WITH_MS = 'HH:mm:ss.SSS';
export const BOOL_TRUE_DISPLAY = 'True';
export const BOOL_FALSE_DISPLAY = 'False';

View File

@@ -19,7 +19,10 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { styled, t } from '@superset-ui/core'; import { styled, t } from '@superset-ui/core';
import { FormControl } from 'react-bootstrap'; import { FormControl } from 'react-bootstrap';
import { Column } from 'react-table';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import { BOOL_FALSE_DISPLAY, BOOL_TRUE_DISPLAY } from 'src/constants';
import Button from 'src/components/Button'; import Button from 'src/components/Button';
import { import {
applyFormattingToTabularData, applyFormattingToTabularData,
@@ -95,11 +98,30 @@ export const useFilteredTableData = (
); );
}, [data, filterText]); }, [data, filterText]);
export const useTableColumns = (data?: Record<string, any>[]) => export const useTableColumns = (
data?: Record<string, any>[],
moreConfigs?: { [key: string]: Partial<Column> },
) =>
useMemo( useMemo(
() => () =>
data?.length data?.length
? Object.keys(data[0]).map(key => ({ accessor: key, Header: key })) ? Object.keys(data[0]).map(
key =>
({
accessor: key,
Header: key,
Cell: ({ value }) => {
if (value === true) {
return BOOL_TRUE_DISPLAY;
}
if (value === false) {
return BOOL_FALSE_DISPLAY;
}
return String(value);
},
...moreConfigs?.[key],
} as Column),
)
: [], : [],
[data], [data, moreConfigs],
); );

View File

@@ -235,28 +235,34 @@ const ExploreChartPanel = props => {
}; };
}; };
const panelBody = <div className="panel-body">{renderChart()}</div>;
return ( return (
<Styles className="panel panel-default chart-container"> <Styles className="panel panel-default chart-container">
<div className="panel-heading" ref={panelHeadingRef}> <div className="panel-heading" ref={panelHeadingRef}>
{header} {header}
</div> </div>
<Split {props.vizType === 'filter_box' ? (
sizes={splitSizes} panelBody
minSize={MIN_SIZES} ) : (
direction="vertical" <Split
gutterSize={gutterHeight} sizes={splitSizes}
onDragStart={onDragStart} minSize={MIN_SIZES}
onDragEnd={onDragEnd} direction="vertical"
elementStyle={elementStyle} gutterSize={gutterHeight}
> onDragStart={onDragStart}
<div className="panel-body">{renderChart()}</div> onDragEnd={onDragEnd}
<DataTablesPane elementStyle={elementStyle}
queryFormData={props.chart.latestQueryFormData} >
tableSectionHeight={tableSectionHeight} {panelBody}
onCollapseChange={onCollapseChange} <DataTablesPane
displayBackground={displaySouthPaneBackground} queryFormData={props.chart.latestQueryFormData}
/> tableSectionHeight={tableSectionHeight}
</Split> onCollapseChange={onCollapseChange}
displayBackground={displaySouthPaneBackground}
/>
</Split>
)}
</Styles> </Styles>
); );
}; };

View File

@@ -24,8 +24,8 @@ import { AsyncCreatableSelect, CreatableSelect } from 'src/components/Select';
import Button from 'src/components/Button'; import Button from 'src/components/Button';
import { t, styled, SupersetClient } from '@superset-ui/core'; import { t, styled, SupersetClient } from '@superset-ui/core';
import { BOOL_FALSE_DISPLAY, BOOL_TRUE_DISPLAY } from 'src/constants';
import FormLabel from 'src/components/FormLabel'; import FormLabel from 'src/components/FormLabel';
import DateFilterControl from 'src/explore/components/controls/DateFilterControl'; import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
import ControlRow from 'src/explore/components/ControlRow'; import ControlRow from 'src/explore/components/ControlRow';
import Control from 'src/explore/components/Control'; import Control from 'src/explore/components/Control';
@@ -102,7 +102,7 @@ const Styles = styled.div`
overflow: visible; overflow: visible;
`; `;
class FilterBox extends React.Component { class FilterBox extends React.PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@@ -216,7 +216,13 @@ class FilterBox extends React.Component {
const color = 'lightgrey'; const color = 'lightgrey';
const backgroundImage = `linear-gradient(to right, ${color}, ${color} ${perc}%, rgba(0,0,0,0) ${perc}%`; const backgroundImage = `linear-gradient(to right, ${color}, ${color} ${perc}%, rgba(0,0,0,0) ${perc}%`;
const style = { backgroundImage }; const style = { backgroundImage };
return { value: opt.id, label: opt.id, style }; let label = opt.id;
if (label === true) {
label = BOOL_TRUE_DISPLAY;
} else if (label === false) {
label = BOOL_FALSE_DISPLAY;
}
return { value: opt.id, label, style };
}); });
} }
@@ -424,7 +430,6 @@ class FilterBox extends React.Component {
render() { render() {
const { instantFiltering } = this.props; const { instantFiltering } = this.props;
return ( return (
<Styles> <Styles>
{this.renderDateFilter()} {this.renderDateFilter()}

View File

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

View File

@@ -109,7 +109,7 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods
SecurityManager SecurityManager
): ):
userstatschartview = None userstatschartview = None
READ_ONLY_MODEL_VIEWS = {"DatabaseAsync", "DatabaseView", "DruidClusterModelView"} READ_ONLY_MODEL_VIEWS = {"Database", "DruidClusterModelView", "DynamicPlugin"}
USER_MODEL_VIEWS = { USER_MODEL_VIEWS = {
"UserDBModelView", "UserDBModelView",

View File

@@ -685,6 +685,7 @@ class TestRolePermission(SupersetTestCase):
self.assert_can_all("CssTemplate", perm_set) self.assert_can_all("CssTemplate", perm_set)
self.assert_can_all("Dataset", perm_set) self.assert_can_all("Dataset", perm_set)
self.assert_can_read("Query", perm_set) self.assert_can_read("Query", perm_set)
self.assert_can_read("Database", perm_set)
self.assertIn(("can_import_dashboards", "Superset"), perm_set) self.assertIn(("can_import_dashboards", "Superset"), perm_set)
self.assertIn(("can_this_form_post", "CsvToDatabaseView"), perm_set) self.assertIn(("can_this_form_post", "CsvToDatabaseView"), perm_set)
self.assertIn(("can_this_form_get", "CsvToDatabaseView"), perm_set) self.assertIn(("can_this_form_get", "CsvToDatabaseView"), perm_set)
@@ -701,6 +702,7 @@ class TestRolePermission(SupersetTestCase):
self.assert_cannot_write("Queries", perm_set) self.assert_cannot_write("Queries", perm_set)
self.assert_cannot_write("RoleModelView", perm_set) self.assert_cannot_write("RoleModelView", perm_set)
self.assert_cannot_write("UserDBModelView", perm_set) self.assert_cannot_write("UserDBModelView", perm_set)
self.assert_cannot_write("Database", perm_set)
def assert_can_admin(self, perm_set): def assert_can_admin(self, perm_set):
self.assert_can_all("Database", perm_set) self.assert_can_all("Database", perm_set)