mirror of
https://github.com/apache/superset.git
synced 2026-05-16 05:15:16 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
286ba5d37d | ||
|
|
457a9e7d21 | ||
|
|
768a1dcc12 | ||
|
|
acda8a68bc | ||
|
|
c53eaaec57 | ||
|
|
b04a9f8ca1 | ||
|
|
ddc01a9b76 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -17,9 +17,16 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
## Change Log
|
||||
### 1.3.1
|
||||
**Database Migrations**
|
||||
### 1.3.2
|
||||
**Fixes**
|
||||
- [#16928](https://github.com/apache/superset/pull/16928) fix: handle mixed time-series error (@yougyoung94)
|
||||
- [#16955](https://github.com/apache/superset/pull/16955) fix: don't log invalid redirect URL sent by user (@dpgaspar)
|
||||
- [#16953](https://github.com/apache/superset/pull/16953) fix(examples): incorrect covid row component id (@villebro)
|
||||
- [#16949](https://github.com/apache/superset/pull/16949) fix(explore): Ensuring parameters key is included (@craig-rueda)
|
||||
- [#16933](https://github.com/apache/superset/pull/16933) fix(dashboard): recursive parent on dashboard components (@villebro)
|
||||
- [#16893](https://github.com/apache/superset/pull/16893) fix: Clear native filters state (@simcha90)
|
||||
|
||||
### 1.3.1
|
||||
**Features**
|
||||
- [#16711](https://github.com/apache/superset/pull/16711) feat(jinja): improve url parameter formatting (@villebro)
|
||||
- [#14955](https://github.com/apache/superset/pull/14955) feat: show build number value in the About if present in the config (@cccs-joel)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "superset",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
|
||||
"license": "Apache-2.0",
|
||||
"directories": {
|
||||
|
||||
@@ -94,7 +94,11 @@ describe('newEntitiesFromDrop', () => {
|
||||
|
||||
expect(result.a.children).toHaveLength(1);
|
||||
expect(Object.keys(result)).toHaveLength(3);
|
||||
expect(result[newRowId].type).toBe(ROW_TYPE);
|
||||
expect(result[newChartId].type).toBe(CHART_TYPE);
|
||||
const newRow = result[newRowId];
|
||||
expect(newRow.type).toBe(ROW_TYPE);
|
||||
expect(newRow.parents).toEqual(['a']);
|
||||
const newChart = result[newChartId];
|
||||
expect(newChart.type).toBe(CHART_TYPE);
|
||||
expect(newChart.parents).toEqual(['a', newRowId]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -395,13 +395,16 @@ export function exploreJSON(
|
||||
.then(({ response, json }) => {
|
||||
if (isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) {
|
||||
// deal with getChartDataRequest transforming the response data
|
||||
const result = 'result' in json ? json.result[0] : json;
|
||||
const result = 'result' in json ? json.result : json;
|
||||
switch (response.status) {
|
||||
case 200:
|
||||
// Query results returned synchronously, meaning query was already cached.
|
||||
return Promise.resolve([result]);
|
||||
return Promise.resolve(result);
|
||||
case 202:
|
||||
// Query is running asynchronously and we must await the results
|
||||
if (shouldUseLegacyApi(formData)) {
|
||||
return waitForAsyncData(result[0]);
|
||||
}
|
||||
return waitForAsyncData(result);
|
||||
default:
|
||||
throw new Error(
|
||||
|
||||
@@ -50,6 +50,7 @@ const propTypes = {
|
||||
removeSliceFromDashboard: PropTypes.func.isRequired,
|
||||
triggerQuery: PropTypes.func.isRequired,
|
||||
logEvent: PropTypes.func.isRequired,
|
||||
clearDataMaskState: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
dashboardInfo: dashboardInfoPropShape.isRequired,
|
||||
dashboardState: dashboardStatePropShape.isRequired,
|
||||
@@ -193,6 +194,7 @@ class Dashboard extends React.PureComponent {
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('visibilitychange', this.onVisibilityChange);
|
||||
this.props.actions.clearDataMaskState();
|
||||
}
|
||||
|
||||
onVisibilityChange() {
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
getAllActiveFilters,
|
||||
getRelevantDataMask,
|
||||
} from 'src/dashboard/util/activeAllDashboardFilters';
|
||||
import { clearDataMaskState } from '../../dataMask/actions';
|
||||
|
||||
function mapStateToProps(state: RootState) {
|
||||
const {
|
||||
@@ -83,6 +84,7 @@ function mapDispatchToProps(dispatch: Dispatch) {
|
||||
actions: bindActionCreators(
|
||||
{
|
||||
setDatasources,
|
||||
clearDataMaskState,
|
||||
addSliceToDashboard,
|
||||
removeSliceFromDashboard,
|
||||
triggerQuery,
|
||||
|
||||
@@ -51,8 +51,8 @@ export default function newEntitiesFromDrop({ dropResult, layout }) {
|
||||
rowWrapper.children = [newDropChild.id];
|
||||
rowWrapper.parents = (dropEntity.parents || []).concat(dropEntity.id);
|
||||
newEntities[rowWrapper.id] = rowWrapper;
|
||||
newDropChild = rowWrapper;
|
||||
newDropChild.parents = rowWrapper.parents.concat(rowWrapper.id);
|
||||
newDropChild = rowWrapper;
|
||||
} else if (dragType === TABS_TYPE) {
|
||||
// create a new tab component
|
||||
const tabChild = newComponentFactory(TAB_TYPE);
|
||||
|
||||
@@ -22,6 +22,11 @@ import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
|
||||
import { Filters } from '../dashboard/reducers/types';
|
||||
import { getInitialDataMask } from './reducer';
|
||||
|
||||
export const CLEAR_DATA_MASK_STATE = 'CLEAR_DATA_MASK_STATE';
|
||||
export interface ClearDataMaskState {
|
||||
type: typeof CLEAR_DATA_MASK_STATE;
|
||||
}
|
||||
|
||||
export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK';
|
||||
export interface UpdateDataMask {
|
||||
type: typeof UPDATE_DATA_MASK;
|
||||
@@ -81,7 +86,14 @@ export function clearDataMask(filterId: string | number) {
|
||||
);
|
||||
}
|
||||
|
||||
export function clearDataMaskState(): ClearDataMaskState {
|
||||
return {
|
||||
type: CLEAR_DATA_MASK_STATE,
|
||||
};
|
||||
}
|
||||
|
||||
export type AnyDataMaskAction =
|
||||
| ClearDataMaskState
|
||||
| UpdateDataMask
|
||||
| SetDataMaskForFilterConfigFail
|
||||
| SetDataMaskForFilterConfigComplete;
|
||||
|
||||
@@ -29,6 +29,7 @@ import { URL_PARAMS } from 'src/constants';
|
||||
import { DataMaskStateWithId, DataMaskWithId } from './types';
|
||||
import {
|
||||
AnyDataMaskAction,
|
||||
CLEAR_DATA_MASK_STATE,
|
||||
SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE,
|
||||
UPDATE_DATA_MASK,
|
||||
} from './actions';
|
||||
@@ -104,6 +105,8 @@ const dataMaskReducer = produce(
|
||||
(draft: DataMaskStateWithId, action: AnyDataMaskAction) => {
|
||||
const cleanState = {};
|
||||
switch (action.type) {
|
||||
case CLEAR_DATA_MASK_STATE:
|
||||
return cleanState;
|
||||
case UPDATE_DATA_MASK:
|
||||
draft[action.filterId] = {
|
||||
...getInitialDataMask(action.filterId),
|
||||
|
||||
@@ -242,7 +242,7 @@ position:
|
||||
- CHART-dCUpAcPsji
|
||||
- CHART-fYo7IyvKZQ
|
||||
- CHART-j4hUvP5dDD
|
||||
id: ROW-xSeNAspgw
|
||||
id: ROW-dieUdkeUw
|
||||
meta:
|
||||
"0": ROOT_ID
|
||||
background: BACKGROUND_TRANSPARENT
|
||||
|
||||
@@ -712,7 +712,8 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
|
||||
@event_logger.log_this
|
||||
@expose("/explore/<datasource_type>/<int:datasource_id>/", methods=["GET", "POST"])
|
||||
@expose("/explore/", methods=["GET", "POST"])
|
||||
def explore( # pylint: disable=too-many-locals,too-many-return-statements,too-many-statements
|
||||
# pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
||||
def explore(
|
||||
self, datasource_type: Optional[str] = None, datasource_id: Optional[int] = None
|
||||
) -> FlaskResponse:
|
||||
user_id = g.user.get_id() if g.user else None
|
||||
@@ -836,6 +837,9 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
|
||||
}
|
||||
try:
|
||||
datasource_data = datasource.data if datasource else dummy_datasource_data
|
||||
datasource_database = datasource_data.get("database")
|
||||
if datasource_database:
|
||||
datasource_database["parameters"] = {}
|
||||
except (SupersetException, SQLAlchemyError):
|
||||
datasource_data = dummy_datasource_data
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class R(BaseSupersetView): # pylint: disable=invalid-name
|
||||
def shortner(self) -> FlaskResponse: # pylint: disable=no-self-use
|
||||
url = request.form.get("data")
|
||||
if not self._validate_url(url):
|
||||
logger.warning("Invalid URL: %s", url)
|
||||
logger.warning("Invalid URL")
|
||||
return Response("Invalid URL", 400)
|
||||
obj = models.Url(url=url)
|
||||
db.session.add(obj)
|
||||
|
||||
Reference in New Issue
Block a user