Skip to content
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

fix(explore): time picker can not be switched between now and specific #12793

Merged
merged 4 commits into from Jan 29, 2021

Conversation

zhaoyongjie
Copy link
Member

@zhaoyongjie zhaoyongjie commented Jan 27, 2021

SUMMARY

fix time picker can not be switched between "now" and "specific".
closes: #12780

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

before

Screen.Recording.2021-01-26.at.2.07.48.PM.mov

fixed

Jan-27-2021.22-37-25.mp4

TEST PLAN

  1. open new timepicker
  2. switch to custom frame
  3. select "now"(or "midnight") for start(or "end")
  4. able to switch to "specific date/time"

ADDITIONAL INFORMATION

import {
CustomRangeKey,
SelectOptionType,
FrameComponentProps,
} from '../types';

const dttmToMoment = (dttm: string): Moment => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move these to utils.js

@@ -183,31 +197,27 @@ export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
} = { ...customRange };
// specific : specific
if (SPECIFIC_MODE.includes(sinceMode) && SPECIFIC_MODE.includes(untilMode)) {
const since = sinceMode === 'specific' ? sinceDatetime : sinceMode;
const until = untilMode === 'specific' ? untilDatetime : untilMode;
const since = sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode; // eslint-disable-line
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from "now/midnight" switch to "specific", "since" requires materialization from "now" to "YYYY-mm-ddThh:mm:ss".

@adam-stasiak
Copy link
Contributor

Tested manually works fine 🟢
Tested on chrome,safari,firefox - ok

@zhaoyongjie
Copy link
Member Author

zhaoyongjie commented Jan 27, 2021 via email

@codecov-io
Copy link

codecov-io commented Jan 27, 2021

Codecov Report

Merging #12793 (a67906d) into master (34549cb) will increase coverage by 0.13%.
The diff coverage is 86.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #12793      +/-   ##
==========================================
+ Coverage   66.86%   67.00%   +0.13%     
==========================================
  Files        1022     1021       -1     
  Lines       50107    50095      -12     
  Branches     5193     5190       -3     
==========================================
+ Hits        33506    33568      +62     
+ Misses      16470    16393      -77     
- Partials      131      134       +3     
Flag Coverage Δ
cypress 50.86% <16.66%> (-0.05%) ⬇️
javascript 62.00% <86.66%> (+0.26%) ⬆️
python 63.97% <ø> (+0.13%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...ore/components/controls/DateFilterControl/types.ts 100.00% <ø> (ø)
...ore/components/controls/DateFilterControl/utils.ts 93.58% <85.71%> (+45.76%) ⬆️
...s/controls/DateFilterControl/frame/CustomFrame.tsx 40.81% <100.00%> (+1.53%) ⬆️
superset/db_engine_specs/presto.py 82.25% <0.00%> (-6.28%) ⬇️
...frontend/src/explore/components/OptionControls.tsx 74.07% <0.00%> (-2.12%) ⬇️
...set-frontend/src/dashboard/util/getDropPosition.js 92.06% <0.00%> (-1.59%) ⬇️
...tend/src/dashboard/components/DashboardBuilder.jsx 85.89% <0.00%> (-0.53%) ⬇️
superset/models/core.py 88.58% <0.00%> (ø)
superset-frontend/src/explore/App.jsx 100.00% <0.00%> (ø)
superset-frontend/src/dashboard/App.jsx 100.00% <0.00%> (ø)
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 34549cb...a67906d. Read the comment docs.

@junlincc junlincc added the explore:time Related to the time filters in Explore label Jan 27, 2021
Copy link

@graceguo-supercat graceguo-supercat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -183,31 +197,27 @@ export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
} = { ...customRange };
// specific : specific
if (SPECIFIC_MODE.includes(sinceMode) && SPECIFIC_MODE.includes(untilMode)) {
const since = sinceMode === 'specific' ? sinceDatetime : sinceMode;
const until = untilMode === 'specific' ? untilDatetime : untilMode;
const since = sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode; // eslint-disable-line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do all of these lines have eslint-disable-line on them? Can we either not introduce linting errors, or only disable the specific rule that's failing here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this comes down to personal preference (these lines are easier to read as one-liners, but the linter wants to break them up). I've personally come to appreciate uniformity over legibility. I'd vote for removing the eslint-disable-lines here and fixing the linting errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah, if it's only formatting, then 100% let's follow the linter. @zhaoyongjie mind updating?

Copy link
Member Author

@zhaoyongjie zhaoyongjie Jan 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glad to follow to linting rules and make the change, however, I still believe breaking the lines is unnecessary. It makes it harder to read this code, especially in the case where we want to compare since and until side by side.

but I am still willing to follow everyone's conventions.

⇓ disable linting

...
  // specific : specific
  if (SPECIFIC_MODE.includes(sinceMode) && SPECIFIC_MODE.includes(untilMode)) {
    const since = sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode; // eslint-disable-line
    const until = untilMode === 'specific' ? dttmToString(untilDatetime) : untilMode; // eslint-disable-line
    return `${since} : ${until}`;
  }

  // specific : relative
  if (SPECIFIC_MODE.includes(sinceMode) && untilMode === 'relative') {
    const since = sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode; // eslint-disable-line
    const until = `DATEADD(DATETIME("${since}"), ${untilGrainValue}, ${untilGrain})`; // eslint-disable-line
    return `${since} : ${until}`;
  }

  // relative : specific
  if (sinceMode === 'relative' && SPECIFIC_MODE.includes(untilMode)) {
    const until = untilMode === 'specific' ? dttmToString(untilDatetime) : untilMode; // eslint-disable-line
    const since = `DATEADD(DATETIME("${until}"), ${-Math.abs(sinceGrainValue)}, ${sinceGrain})`; // eslint-disable-line
    return `${since} : ${until}`;
  }

  // relative : relative
  const since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(sinceGrainValue)}, ${sinceGrain})`; // eslint-disable-line
  const until = `DATEADD(DATETIME("${anchorValue}"), ${untilGrainValue}, ${untilGrain})`;
  return `${since} : ${until}`;
...

⇓ enable linting

...
  // specific : specific
  if (SPECIFIC_MODE.includes(sinceMode) && SPECIFIC_MODE.includes(untilMode)) {
    const since =
      sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode;
    const until =
      untilMode === 'specific' ? dttmToString(untilDatetime) : untilMode;
    return `${since} : ${until}`;
  }

  // specific : relative
  if (SPECIFIC_MODE.includes(sinceMode) && untilMode === 'relative') {
    const since =
      sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode;
    const until = `DATEADD(DATETIME("${since}"), ${untilGrainValue}, ${untilGrain})`;
    return `${since} : ${until}`;
  }

  // relative : specific
  if (sinceMode === 'relative' && SPECIFIC_MODE.includes(untilMode)) {
    const until =
      untilMode === 'specific' ? dttmToString(untilDatetime) : untilMode;
    const since = `DATEADD(DATETIME("${until}"), ${-Math.abs(
      sinceGrainValue,
    )}, ${sinceGrain})`;
    return `${since} : ${until}`;
  }

  // relative : relative
  const since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(
    sinceGrainValue,
  )}, ${sinceGrain})`;
  const until = `DATEADD(DATETIME("${anchorValue}"), ${untilGrainValue}, ${untilGrain})`;
  return `${since} : ${until}`;
...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
  const {
    sinceDatetime,
    sinceMode,
    sinceGrain,
    sinceGrainValue,
    untilDatetime,
    untilMode,
    untilGrain,
    untilGrainValue,
    anchorValue,
  } = { ...customRange };
  let since: string = sinceMode;
  let until: string = untilMode;

  if (since === 'specific') {
    since = dttmToString(sinceDatetime);
  }
  if (until === 'specific') {
    until = dttmToString(untilDatetime);
  }

  if (since === 'relative' && until === 'relative') {
    since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(
      sinceGrainValue,
    )}, ${sinceGrain})`;
    until = `DATEADD(DATETIME("${anchorValue}"), ${untilGrainValue}, ${untilGrain})`;
  }

  if (since === 'relative') {
    since = `DATEADD(DATETIME("${until}"), ${-Math.abs(
      sinceGrainValue,
    )}, ${sinceGrain})`;
  }

  if (until === 'relative') {
    until = `DATEADD(DATETIME("${since}"), ${untilGrainValue}, ${untilGrain})`;
  }

  return `${since} : ${until}`;
};

@zhaoyongjie would this be cleaner? It passes all your test cases.

Copy link
Member

@villebro villebro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I'd prefer to reformat according to the linter's preference.

Copy link
Member

@junlincc junlincc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approve as product/design/QA sign off.

tried switching between all different settings ✅
apologize that we didn't catch it earlier ..

@zhaoyongjie
Copy link
Member Author

LGTM, but I'd prefer to reformat according to the linter's preference.

I removed eslint-disable-line and fix this linting issue.


export const dttmToString = (dttm: string): string =>
dttmToMoment(dttm).format(MOMENT_FORMAT);

export const customTimeRangeDecode = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: can we break utils.ts into separate files under a utils folder? These functions are complex enough to warrant a separate file.

@@ -183,31 +197,27 @@ export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
} = { ...customRange };
// specific : specific
if (SPECIFIC_MODE.includes(sinceMode) && SPECIFIC_MODE.includes(untilMode)) {
const since = sinceMode === 'specific' ? sinceDatetime : sinceMode;
const until = untilMode === 'specific' ? untilDatetime : untilMode;
const since = sinceMode === 'specific' ? dttmToString(sinceDatetime) : sinceMode; // eslint-disable-line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export const customTimeRangeEncode = (customRange: CustomRangeType): string => {
  const {
    sinceDatetime,
    sinceMode,
    sinceGrain,
    sinceGrainValue,
    untilDatetime,
    untilMode,
    untilGrain,
    untilGrainValue,
    anchorValue,
  } = { ...customRange };
  let since: string = sinceMode;
  let until: string = untilMode;

  if (since === 'specific') {
    since = dttmToString(sinceDatetime);
  }
  if (until === 'specific') {
    until = dttmToString(untilDatetime);
  }

  if (since === 'relative' && until === 'relative') {
    since = `DATEADD(DATETIME("${anchorValue}"), ${-Math.abs(
      sinceGrainValue,
    )}, ${sinceGrain})`;
    until = `DATEADD(DATETIME("${anchorValue}"), ${untilGrainValue}, ${untilGrain})`;
  }

  if (since === 'relative') {
    since = `DATEADD(DATETIME("${until}"), ${-Math.abs(
      sinceGrainValue,
    )}, ${sinceGrain})`;
  }

  if (until === 'relative') {
    until = `DATEADD(DATETIME("${since}"), ${untilGrainValue}, ${untilGrain})`;
  }

  return `${since} : ${until}`;
};

@zhaoyongjie would this be cleaner? It passes all your test cases.

@ktmud
Copy link
Member

ktmud commented Jan 28, 2021

BTW, I found this line:

untilMode: 'specific' | 'relative' | 'now' | 'today';

could probably be updated to

  untilMode: DateTimeModeType;

),
).toEqual({
customRange: {
sinceDatetime: '2021-01-20T00:00:00',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I fully understand the purpose of the customTimeRangeDecode function. It is supposed to apply the dateadd and datetime functions? However, according to the code, this sinceDatetime seems to always return 7_DAYS_AGO when the input format is relative : specific.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then shouldn't sinceDatetime be set to 2021-01-27T00:00:00 here, just to be more consistent with what is set in the input values?

Do you also do decode/encode when switching between non-advanced modes (i.e. modes that doesn't allow free text)? Not sure how feasible it is, but gut feeling tells me that it might be easier and cleaner to use he same config object internally for all frames and only do decode/encode when the time picker needs to communicate with the outside world.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • customTimeRangeEncode is used only in the CustomFrame.
  • customTimeRangeDecode is used in 2 places: CustomFrame and guessFrame function in DateFilterControl.

customTimeRangeDecode can determine whether an expression can be used in CustomFrame.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sinceDatetime set to 2021-01-27T00:00:00 just to be more consistent in CustomFrame.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

@zhaoyongjie
Copy link
Member Author

BTW, I found this line:

untilMode: 'specific' | 'relative' | 'now' | 'today';

could probably be updated to

  untilMode: DateTimeModeType;

thanks for pointing this out. I will fix it.

Copy link
Member

@etr2460 etr2460 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the updates, lgtm!

@zhaoyongjie zhaoyongjie merged commit 642a76f into apache:master Jan 29, 2021
villebro pushed a commit that referenced this pull request Jan 29, 2021
#12793)

* fix(explore): time picker can not be switched between now and specifc

* fix linting

* fix type

* fix UT
graceguo-supercat pushed a commit to airbnb/superset-fork that referenced this pull request Feb 10, 2021
apache#12793)

* fix(explore): time picker can not be switched between now and specifc

* fix linting

* fix type

* fix UT

(cherry picked from commit 642a76f)
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.2.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels explore:time Related to the time filters in Explore size/L v1.0.1 🍒 1.0.1 🚢 1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[explore]time picker switch from NOW to Specific time range
9 participants