forked from apache/superset
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added adhoc filter plugin files * Made sure that adhoc filter uses the adhoc filter object * added adhocfiltercontrol to native adhoc filter * fixed hook that made too many requests * fixed applied filter label * removed duplicate files * Removed uneeded functions * Removed uneeded functions and variables * Removed unused props variables * modifying base image tag * Removed unused config settings * removed column for filter config form * Improved the applied filter(s) modal * Temp update to build image * fixed string formatting issue: * updating superset base image tag * added setFocused hooks to filter when hovering * fixed unused declaration error * updating image * updating superset-base image tag * updating image * Update cccs-build/superset/Dockerfile Co-authored-by: cccs-Dustin <96579982+cccs-Dustin@users.noreply.github.com> * Added ability to certify entities with multiple values (#224) * Added ability to certify entities with multiple values * Update description text to reflect new feature * Add tests for multiple certified by values * [bigdig] updating base image Co-authored-by: cccs-RyanK <102618419+cccs-RyanK@users.noreply.github.com> Co-authored-by: cccs-Dustin <96579982+cccs-Dustin@users.noreply.github.com> Co-authored-by: Reese <10563996+reesercollins@users.noreply.github.com>
- Loading branch information
1 parent
8d26229
commit d052a5c
Showing
19 changed files
with
852 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
448 changes: 226 additions & 222 deletions
448
...board/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
254 changes: 254 additions & 0 deletions
254
superset-frontend/src/filters/components/Adhoc/AdhocFilterPlugin.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
/* eslint-disable no-param-reassign */ | ||
import { | ||
DataMask, | ||
ensureIsArray, | ||
ExtraFormData, | ||
JsonObject, | ||
JsonResponse, | ||
smartDateDetailedFormatter, | ||
SupersetApiError, | ||
SupersetClient, | ||
t, | ||
} from '@superset-ui/core'; | ||
import React, { useCallback, useEffect, useState, useMemo } from 'react'; | ||
import { useImmerReducer } from 'use-immer'; | ||
import AdhocFilterControl from 'src/explore/components/controls/FilterControl/AdhocFilterControl'; | ||
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter'; | ||
// eslint-disable-next-line import/no-unresolved | ||
import { addDangerToast } from 'src/components/MessageToasts/actions'; | ||
// eslint-disable-next-line import/no-unresolved | ||
import { cacheWrapper } from 'src/utils/cacheWrapper'; | ||
// eslint-disable-next-line import/no-unresolved | ||
import { getClientErrorObject } from 'src/utils/getClientErrorObject'; | ||
// eslint-disable-next-line import/no-unresolved | ||
import { useChangeEffect } from 'src/hooks/useChangeEffect'; | ||
import { PluginFilterAdhocProps } from './types'; | ||
import { | ||
StyledFormItem, | ||
FilterPluginStyle, | ||
StatusMessage, | ||
ControlContainer, | ||
} from '../common'; | ||
import { getDataRecordFormatter, getAdhocExtraFormData } from '../../utils'; | ||
|
||
type DataMaskAction = | ||
| { type: 'ownState'; ownState: JsonObject } | ||
| { | ||
type: 'filterState'; | ||
__cache: JsonObject; | ||
extraFormData: ExtraFormData; | ||
filterState: { | ||
label?: string; | ||
filters?: AdhocFilter[]; | ||
value: AdhocFilter[]; | ||
}; | ||
}; | ||
|
||
function reducer( | ||
draft: DataMask & { __cache?: JsonObject }, | ||
action: DataMaskAction, | ||
) { | ||
switch (action.type) { | ||
case 'ownState': | ||
draft.ownState = { | ||
...draft.ownState, | ||
...action.ownState, | ||
}; | ||
return draft; | ||
case 'filterState': | ||
draft.extraFormData = action.extraFormData; | ||
// eslint-disable-next-line no-underscore-dangle | ||
draft.__cache = action.__cache; | ||
draft.filterState = { ...draft.filterState, ...action.filterState }; | ||
return draft; | ||
default: | ||
return draft; | ||
} | ||
} | ||
|
||
export default function PluginFilterAdhoc(props: PluginFilterAdhocProps) { | ||
const { | ||
filterState, | ||
formData, | ||
height, | ||
width, | ||
setDataMask, | ||
setFocusedFilter, | ||
unsetFocusedFilter, | ||
appSection, | ||
} = props; | ||
const { enableEmptyFilter, inverseSelection, defaultToFirstItem } = formData; | ||
const datasetId = useMemo( | ||
() => formData.datasource.split('_')[0], | ||
[formData.datasource], | ||
); | ||
const [datasetDetails, setDatasetDetails] = useState<Record<string, any>>(); | ||
const [columns, setColumns] = useState(); | ||
const [dataMask, dispatchDataMask] = useImmerReducer(reducer, { | ||
extraFormData: {}, | ||
filterState, | ||
}); | ||
const labelFormatter = useMemo( | ||
() => | ||
getDataRecordFormatter({ | ||
timeFormatter: smartDateDetailedFormatter, | ||
}), | ||
[], | ||
); | ||
|
||
const localCache = new Map<string, any>(); | ||
|
||
const cachedSupersetGet = cacheWrapper( | ||
SupersetClient.get, | ||
localCache, | ||
({ endpoint }) => endpoint || '', | ||
); | ||
|
||
useChangeEffect(datasetId, () => { | ||
if (datasetId) { | ||
cachedSupersetGet({ | ||
endpoint: `/api/v1/dataset/${datasetId}`, | ||
}) | ||
.then((response: JsonResponse) => { | ||
const dataset = response.json?.result; | ||
// modify the response to fit structure expected by AdhocFilterControl | ||
dataset.type = dataset.datasource_type; | ||
dataset.filter_select = true; | ||
setDatasetDetails(dataset); | ||
}) | ||
.catch((response: SupersetApiError) => { | ||
addDangerToast(response.message); | ||
}); | ||
} | ||
}); | ||
|
||
useChangeEffect(datasetId, () => { | ||
if (datasetId != null) { | ||
cachedSupersetGet({ | ||
endpoint: `/api/v1/dataset/${datasetId}`, | ||
}).then( | ||
({ json: { result } }) => { | ||
setColumns(result.columns); | ||
}, | ||
async badResponse => { | ||
const { error, message } = await getClientErrorObject(badResponse); | ||
let errorText = message || error || t('An error has occurred'); | ||
if (message === 'Forbidden') { | ||
errorText = t('You do not have permission to edit this dashboard'); | ||
} | ||
addDangerToast(errorText); | ||
}, | ||
); | ||
} | ||
}); | ||
|
||
const labelString: (props: AdhocFilter) => string = (props: AdhocFilter) => { | ||
if (ensureIsArray(props.comparator).length >= 2) { | ||
return `${props.subject} ${props.operator} (${props.comparator.join( | ||
', ', | ||
)})`; | ||
} | ||
return `${props.subject} ${props.operator} ${props.comparator}`; | ||
}; | ||
|
||
const updateDataMask = useCallback( | ||
(adhoc_filters: AdhocFilter[]) => { | ||
const emptyFilter = | ||
enableEmptyFilter && !inverseSelection && !adhoc_filters?.length; | ||
|
||
dispatchDataMask({ | ||
type: 'filterState', | ||
__cache: filterState, | ||
extraFormData: getAdhocExtraFormData( | ||
adhoc_filters, | ||
emptyFilter, | ||
inverseSelection, | ||
), | ||
filterState: { | ||
...filterState, | ||
label: (adhoc_filters || []) | ||
.map(f => | ||
f.sqlExpression ? String(f.sqlExpression) : labelString(f), | ||
) | ||
.join(', '), | ||
value: adhoc_filters, | ||
filters: adhoc_filters, | ||
}, | ||
}); | ||
}, | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[ | ||
appSection, | ||
defaultToFirstItem, | ||
dispatchDataMask, | ||
enableEmptyFilter, | ||
inverseSelection, | ||
JSON.stringify(filterState), | ||
labelFormatter, | ||
], | ||
); | ||
|
||
useEffect(() => { | ||
updateDataMask(filterState.value); | ||
}, [JSON.stringify(filterState.value)]); | ||
|
||
useEffect(() => { | ||
setDataMask(dataMask); | ||
}, [JSON.stringify(dataMask)]); | ||
|
||
const formItemExtra = useMemo(() => { | ||
if (filterState.validateMessage) { | ||
return ( | ||
<StatusMessage status={filterState.validateStatus}> | ||
{filterState.validateMessage} | ||
</StatusMessage> | ||
); | ||
} | ||
return undefined; | ||
}, [filterState.validateMessage, filterState.validateStatus]); | ||
|
||
return ( | ||
<FilterPluginStyle height={height} width={width}> | ||
<StyledFormItem | ||
validateStatus={filterState.validateStatus} | ||
extra={formItemExtra} | ||
> | ||
<ControlContainer | ||
onMouseEnter={setFocusedFilter} | ||
onMouseLeave={unsetFocusedFilter} | ||
validateStatus={filterState.validateStatus} | ||
> | ||
<AdhocFilterControl | ||
columns={columns || []} | ||
savedMetrics={[]} | ||
datasource={datasetDetails} | ||
onChange={(filters: AdhocFilter[]) => { | ||
// New Adhoc Filters Selected | ||
updateDataMask(filters); | ||
}} | ||
label={' '} | ||
value={filterState.filters || []} | ||
/> | ||
</ControlContainer> | ||
</StyledFormItem> | ||
</FilterPluginStyle> | ||
); | ||
} |
43 changes: 43 additions & 0 deletions
43
superset-frontend/src/filters/components/Adhoc/buildQuery.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
import { | ||
buildQueryContext, | ||
QueryObject, | ||
QueryObjectFilterClause, | ||
BuildQuery, | ||
} from '@superset-ui/core'; | ||
import { PluginFilterSelectQueryFormData } from './types'; | ||
|
||
const buildQuery: BuildQuery<PluginFilterSelectQueryFormData> = ( | ||
formData: PluginFilterSelectQueryFormData, | ||
) => | ||
buildQueryContext(formData, baseQueryObject => { | ||
const { filters = [] } = baseQueryObject; | ||
const extraFilters: QueryObjectFilterClause[] = []; | ||
const query: QueryObject[] = [ | ||
{ | ||
...baseQueryObject, | ||
result_type: 'columns', | ||
filters: filters.concat(extraFilters), | ||
}, | ||
]; | ||
return query; | ||
}); | ||
|
||
export default buildQuery; |
Oops, something went wrong.