Skip to content
This repository has been archived by the owner on Dec 10, 2021. It is now read-only.

refactor(plugin-chart-table): migrate to API v1 #889

Merged
merged 5 commits into from
Jan 26, 2021

Conversation

ktmud
Copy link
Contributor

@ktmud ktmud commented Jan 7, 2021

🏆 Enhancements

Migrate the table viz to use API v1, along with some refactoring related to QueryContext.

  1. Add typing for post_processing
  2. Allow ChartPlugin to have custom ChartProps
  3. Remove groupby from queryFields as it is deprecated.
  4. Add GenericDataType, the chart data type hints for rendering

This PR is a prerequisite of apache/superset#10270

@ktmud ktmud requested a review from a team as a code owner January 7, 2021 21:35
@vercel
Copy link

vercel bot commented Jan 7, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/superset/superset-ui/6b34umm1l
✅ Preview: https://superset-ui-git-fork-ktmud-table-use-api-v1.superset.vercel.app

@pull-request-size pull-request-size bot removed the size/L label Jan 8, 2021
@ktmud ktmud force-pushed the table-use-api-v1 branch 2 times, most recently from 6f10263 to 7fb0819 Compare January 10, 2021 06:47
packages/superset-ui-core/src/query/extractQueryFields.ts Outdated Show resolved Hide resolved
}
});
return result;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

may be only Set enougph? if I got correctly logic do it like (but not sure):

items.forEach(x => {
    if (!hash || !hash(x));
      seen.add(x);
    }
  });
return [...seen]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does set spread preserve orders?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

MDN says yes, but this still wouldn't work for my needs because I need to check uniqueness by hash, not the item itself.

Copy link
Contributor

Choose a reason for hiding this comment

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

ideas: can short circuit when hash is not used and only check hash once.

function removeDuplicates<T>(items: T[], hash?: (item: T) => unknown): T[] {
  if (hash) {
    const seen = new Set();
    return items.filter(x => {
      const itemHash = hash(x);
      if (seen.has(itemHash)) return false; 
      seen.add(itemHash);
      return true;
    });
  }

  return [...new Set(items)];
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea! Updated.

@codecov
Copy link

codecov bot commented Jan 11, 2021

Codecov Report

Merging #889 (7f2c636) into master (a5ab4c6) will increase coverage by 0.09%.
The diff coverage is 68.06%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #889      +/-   ##
==========================================
+ Coverage   27.04%   27.14%   +0.09%     
==========================================
  Files         407      410       +3     
  Lines        8241     8264      +23     
  Branches     1119     1125       +6     
==========================================
+ Hits         2229     2243      +14     
- Misses       5885     5893       +8     
- Partials      127      128       +1     
Impacted Files Coverage Δ
...registries/ChartTransformPropsRegistrySingleton.ts 100.00% <ø> (ø)
.../superset-ui-core/src/query/types/QueryFormData.ts 100.00% <ø> (ø)
...acy-preset-chart-big-number/src/BigNumber/index.ts 0.00% <ø> (ø)
...t-chart-big-number/src/BigNumber/transformProps.ts 52.00% <ø> (ø)
...reset-chart-big-number/src/BigNumberTotal/index.ts 0.00% <ø> (ø)
.../plugin-chart-echarts/src/Timeseries/buildQuery.ts 50.00% <0.00%> (-7.15%) ⬇️
...ins/plugin-chart-table/src/DataTable/DataTable.tsx 46.15% <0.00%> (-1.47%) ⬇️
plugins/plugin-chart-table/src/buildQuery.ts 0.00% <0.00%> (ø)
plugins/plugin-chart-table/src/controlPanel.tsx 38.46% <ø> (ø)
plugins/plugin-chart-table/src/index.ts 0.00% <ø> (ø)
... and 20 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 a5ab4c6...7f2c636. Read the comment docs.

Copy link
Contributor

@kristw kristw left a comment

Choose a reason for hiding this comment

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

Just a few things here and there. Overall lgtm

if (normalizedKey === 'groupby') {
normalizedKey = 'columns';
}
if (normalizedKey === 'metrics') {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit else if or can also use switch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I try to avoid switch nowadays since Python has taught me switch is just a syntactic sugar for if else's. Plus I hate it when I forgot to call break.

}
});
return result;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

ideas: can short circuit when hash is not used and only check hash once.

function removeDuplicates<T>(items: T[], hash?: (item: T) => unknown): T[] {
  if (hash) {
    const seen = new Set();
    return items.filter(x => {
      const itemHash = hash(x);
      if (seen.has(itemHash)) return false; 
      seen.add(itemHash);
      return true;
    });
  }

  return [...new Set(items)];
}

@@ -3,7 +3,7 @@
"composite": false,
"emitDeclarationOnly": false,
"noEmit": true,
"rootDir": "."
"rootDir": "../../../"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

getChartComponentRegistry().registerLoader(key as string, this.loadChart);
getChartControlPanelRegistry().registerValue(key as string, this.controlPanel);
getChartTransformPropsRegistry().registerLoader(key as string, this.loadTransformProps);
const key: string = this.config.key || isRequired('config.key');
Copy link
Contributor

Choose a reason for hiding this comment

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

Given we are all in with typescript now. Could also remove the legacy isRequired trick that was before the age of typescript. (No need to do in this pr).

Copy link
Contributor Author

@ktmud ktmud Jan 26, 2021

Choose a reason for hiding this comment

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

Noted. Let's do this when all major plugins (at least their index.js file) are migrated to typescript.

Copy link
Contributor

@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.

This is amazing stuff, thanks so much for all the improvements here. Let's get this in and deal with any potential issues with higi priority, as I feel the improvements here far outweigh any potential regressions caused by it.

Comment on lines 22 to 30
it('should remove duplciages from a simple list', () => {
expect(removeDuplicates([1, 2, 4, 1, 1, 5, 2])).toEqual([1, 2, 4, 5]);
});
it('should remove duplciages by key getter', () => {
expect(removeDuplicates([{ a: 1 }, { a: 1 }, { b: 2 }], x => x.a)).toEqual([
{ a: 1 },
{ b: 2 },
]);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should remove duplciages from a simple list', () => {
expect(removeDuplicates([1, 2, 4, 1, 1, 5, 2])).toEqual([1, 2, 4, 5]);
});
it('should remove duplciages by key getter', () => {
expect(removeDuplicates([{ a: 1 }, { a: 1 }, { b: 2 }], x => x.a)).toEqual([
{ a: 1 },
{ b: 2 },
]);
});
it('should remove duplicates from a simple list', () => {
expect(removeDuplicates([1, 2, 4, 1, 1, 5, 2])).toEqual([1, 2, 4, 5]);
});
it('should remove duplicates by key getter', () => {
expect(removeDuplicates([{ a: 1 }, { a: 1 }, { b: 2 }], x => x.a)).toEqual([
{ a: 1 },
{ b: 2 },
]);
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated!

Copy link
Contributor Author

@ktmud ktmud left a comment

Choose a reason for hiding this comment

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

Adding more comments and replies

@@ -149,7 +154,7 @@ export interface DruidFormData extends BaseFormData {
druid_time_origin?: string;
}

export type QueryFormData = SqlaFormData | DruidFormData;
export type QueryFormData = DruidFormData | SqlaFormData;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching order so if something doesn't add up, it will fallback to SqlaFormData

}
});
return result;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea! Updated.

Comment on lines 22 to 30
it('should remove duplciages from a simple list', () => {
expect(removeDuplicates([1, 2, 4, 1, 1, 5, 2])).toEqual([1, 2, 4, 5]);
});
it('should remove duplciages by key getter', () => {
expect(removeDuplicates([{ a: 1 }, { a: 1 }, { b: 2 }], x => x.a)).toEqual([
{ a: 1 },
{ b: 2 },
]);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated!

metrics: metrics_,
percentMetrics: percentMetrics_,
percent_metrics: percentMetrics_,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm just sick and tire of worrying about casing so I choose to use raw form data here. Should probably gradually deprecating this auto-case-transformation for the final charting API as well...

colorPn?: boolean;
includeSearch?: boolean;
pageLength?: string | number | null; // null means auto-paginate
export type TableChartFormData = QueryFormData & {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The benefit of not doing case transformation is that we can directly reuse this typing for both formData sent to the API and received by the chart renderer (e.g. in both buildQuery and transformProps.)

@ktmud
Copy link
Contributor Author

ktmud commented Jan 26, 2021

This is amazing stuff, thanks so much for all the improvements here. Let's get this in and deal with any potential issues with higi priority, as I feel the improvements here far outweigh any potential regressions caused by it.

Thank you, @villebro ! I've tested ECharts, NVD3, Box plot, Word Cloud and tried to be as comprehensive as I can. Also wanted to add the missing Cypress tests for more chart types (boxplot, time series table, for example) before merging, but didn't have enough time since a lot of my time has been spent on updating Cypress itself..

It would be super nice if someone from Preset could prioritize adding E2E tests for viz types or completing existing ones with more use cases so we can have more confidence in doing bigger viz plugin improvements like this.

cc @junlincc

@ktmud ktmud merged commit 57643c9 into apache-superset:master Jan 26, 2021
@ktmud ktmud deleted the table-use-api-v1 branch January 26, 2021 11:01
@ktmud
Copy link
Contributor Author

ktmud commented Jan 26, 2021

I'm going to a new minor version and update apache/superset#10270

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants