-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add new plugin to generate period over period KPI charts #847
feat: add new plugin to generate period over period KPI charts #847
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6a1ce6a
to
3ee98e9
Compare
3ee98e9
to
6a1ce6a
Compare
Please make this PR against https://github.com/apache/superset as this fork is rebased from there :) |
This is just for testing and cursory review |
// imported from @superset-ui/core. For variables available, please visit | ||
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts | ||
|
||
const Styles = styled.div<PopKPIStylesProps>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, can we use css
here while defining the styles as a variable as detailed in the wiki
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
padding: ${({ theme }) => theme.tdUnit * 4}px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First time I see this tdUnit
, what about gridUnit
instead?
width: ${({ width }) => width}px; | ||
`; | ||
|
||
const BigValueContainer = styled.div` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, let's use css for styled component that do not need to be re-used, either inline or by assigning them to a var
// The following Styles component is a <div> element, which has been styled using Emotion | ||
// For docs, visit https://emotion.sh/docs/styled | ||
|
||
// Theming variables are provided for your use via a ThemeProvider | ||
// imported from @superset-ui/core. For variables available, please visit | ||
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// The following Styles component is a <div> element, which has been styled using Emotion | |
// For docs, visit https://emotion.sh/docs/styled | |
// Theming variables are provided for your use via a ThemeProvider | |
// imported from @superset-ui/core. For variables available, please visit | |
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts |
|
||
const Styles = styled.div<PopKPIStylesProps>` | ||
|
||
font-family: ${({ theme }) => theme.typography.families.sansSerif}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please refer to No need to use theme the hard way
// it's possible to add validators to controls if | ||
// certain selections/types need to be enforced |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// it's possible to add validators to controls if | |
// certain selections/types need to be enforced |
...sharedControls.adhoc_filters, | ||
label: t('FILTERS (Custom)'), | ||
description: | ||
'This only applies when selecting the Range for Comparison Type- Custom', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please localize this
*/ | ||
constructor() { | ||
const metadata = new ChartMetadata({ | ||
description: 'KPI viz for comparing multiple period', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's localize this
width, | ||
height, | ||
data, | ||
// and now your control data, manipulated as needed, and passed through as props! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// and now your control data, manipulated as needed, and passed through as props! |
|
||
let modTimeRange: string | null = timeRange; | ||
|
||
if (timeRange === 'NO_TIME_RANGE' || timeRange === '_(NO_TIME_RANGE)'){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure these are supposed to be strings and not a constant? I am looking at superset/utils/date_parser.py
and it looks like these are being referred to a constant NO_TIME_RANGE = "No filter"
|
||
type MomentTuple = [moment.Moment | null, moment.Moment | null]; | ||
|
||
function getSinceUntil( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like this function does not belong here but to the utils. Maybe time-format
in superset-ui-core
?
); | ||
|
||
const [testSince, testUntil] = getSinceUntil( | ||
timeFilter.comparator.toLowerCase(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a null check here?
startDatePrev = startDate.subtract(1, 'month'); | ||
endDatePrev = endDate.subtract(1, 'month'); | ||
} else if (calcType === 'r') { | ||
startDatePrev = startDate.clone().subtract(daysBetween.valueOf(), 'day'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diff
should already return a number so valueOf
might be redundant here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need clone
here?
|
||
const rootElem = createRef<HTMLDivElement>(); | ||
|
||
useEffect(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for? I don't think we use it anywhere?
* either add additional plugin folders (similar in structure to ./plugin) | ||
* OR export multiple instances of `ChartPlugin` extensions in ./plugin/index.ts | ||
* which in turn load exports from CustomViz.tsx | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need all those comments (in other files too)
return [null, null]; | ||
} | ||
|
||
if (timeRange?.startsWith('last') && !timeRange.includes(separator)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is a copy of superset/utils/date_parser.py::get_since_until
right? If that's the case, could you add a comment here that refers to date_parser.py
, and the other way around - a comment in date_parser.py
that refers to this function. The goal is that when someone tries to make a change to 1 of those functions, they should know that they need to sync that change with the corresponding function
]); | ||
|
||
|
||
const timeFilter: any = formData.adhoc_filters?.find( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wherever possible, please try not to use any
|
||
let formDataB: QueryFormData; | ||
|
||
if (timeComparison!='c'){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can run your code through prettier (npm run format
) to format it to match the style of other files
[ | ||
{ | ||
name: 'metrics', | ||
config: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not necessary to override the config, metrics
control already has non empty validator set. You can just put ['metrics']
here
label: t('Range for Comparison'), | ||
default: 'y', | ||
choices: [ | ||
['y', 'Year'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also localize the names here
const dataA = queriesData[0].data as TimeseriesDataRecord[]; | ||
const dataB = queriesData[1].data as TimeseriesDataRecord[]; | ||
const data = dataA; | ||
const metricName = getMetricLabel(metrics[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we only take the first metric here and ignore the rest? If so, we should use metric
control instead of metrics
in the control panel
const percentDifference: string = formatPercentChange(percentDifferenceNum); | ||
|
||
return { | ||
width, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should only return those values that are used in the main plugin file. I see that don't use for example data, metrics or metricName in PopKPI
so we should remove those from here
@fernando-bytecode I'm going to merge this PR into my branch so that we can add a feature flag on it but go ahead and open a new PR to it when you're ready with the Ci fixes,etc. |
68fe17f
into
preset-io:bytecode/time-shift
SUMMARY
Creating a new chart that allows arbitrary time range comparisons for Key Performance Indicators (KPI). This follows similar multi-value visualizations found in other BI tools.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TESTING INSTRUCTIONS
ADDITIONAL INFORMATION