This is an automated email from the ASF dual-hosted git repository. villebro pushed a commit to branch 0.37 in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
commit 2f2fb47721d83f1bb377ee829532284be28d1753 Author: Erik Ritter <erik.rit...@airbnb.com> AuthorDate: Wed Jul 15 08:38:43 2020 -0700 chore: type welcome (#10317) --- superset-frontend/package-lock.json | 29 +++++++++++++ superset-frontend/package.json | 2 + ...boardTable_spec.jsx => DashboardTable_spec.tsx} | 2 +- .../welcome/{Welcome_spec.jsx => Welcome_spec.tsx} | 14 ++++++- superset-frontend/src/profile/components/App.tsx | 4 +- .../src/profile/components/CreatedContent.tsx | 3 +- .../src/profile/components/Favorites.tsx | 3 +- .../src/profile/components/RecentActivity.tsx | 3 +- .../src/profile/components/Security.tsx | 4 +- .../src/profile/components/UserInfo.tsx | 4 +- superset-frontend/src/profile/types.ts | 24 ----------- .../{profile/types.ts => types/bootstrapTypes.ts} | 28 ++++--------- superset-frontend/src/welcome/{App.jsx => App.tsx} | 2 +- .../{DashboardTable.jsx => DashboardTable.tsx} | 48 ++++++++++++++++++---- .../src/welcome/{Welcome.jsx => Welcome.tsx} | 27 +++++++----- .../src/welcome/{index.jsx => index.tsx} | 0 superset-frontend/webpack.config.js | 2 +- 17 files changed, 121 insertions(+), 78 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 135f6b4..aeabd74 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -7658,6 +7658,11 @@ "resolved": "https://registry.npmjs.org/@types/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha512-mky/O83TXmGY39P1H9YbUpjV6l6voRYlufqfFCvel8l1phuy8HRjdWc1rrPuN53ITBJlbyMSV6z3niOySO5pgQ==" }, + "@types/fetch-mock": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@types/fetch-mock/-/fetch-mock-7.3.2.tgz", + "integrity": "sha512-NCEfv49jmDsBAixjMjEHKVgmVQlJ+uK56FOc+2roYPExnXCZDpi6mJOHQ3v23BiO84hBDStND9R2itJr7PNoow==" + }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", @@ -7678,6 +7683,11 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.6.tgz", + "integrity": "sha512-GRTZLeLJ8ia00ZH8mxMO8t0aC9M1N9bN461Z2eaRurJo6Fpa+utgCwLzI4jQHcrdzuzp5WPN9jRwpsCQ1VhJ5w==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -7837,6 +7847,25 @@ "redux": "^3.6.0" } }, + "@types/react-router": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.8.tgz", + "integrity": "sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg==", + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.5.tgz", + "integrity": "sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw==", + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/react-select": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.0.12.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 17fab51..742e82e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -102,9 +102,11 @@ "@superset-ui/validator": "^0.14.9", "@types/classnames": "^2.2.9", "@types/enzyme": "^3.10.5", + "@types/fetch-mock": "^7.3.2", "@types/react-bootstrap": "^0.32.21", "@types/react-gravatar": "^2.6.8", "@types/react-json-tree": "^0.6.11", + "@types/react-router-dom": "^5.1.5", "@types/react-select": "^3.0.12", "@types/react-virtualized": "^9.21.10", "@types/react-window": "^1.8.2", diff --git a/superset-frontend/spec/javascripts/welcome/DashboardTable_spec.jsx b/superset-frontend/spec/javascripts/welcome/DashboardTable_spec.tsx similarity index 97% rename from superset-frontend/spec/javascripts/welcome/DashboardTable_spec.jsx rename to superset-frontend/spec/javascripts/welcome/DashboardTable_spec.tsx index e9cf957..5ded3fa 100644 --- a/superset-frontend/spec/javascripts/welcome/DashboardTable_spec.jsx +++ b/superset-frontend/spec/javascripts/welcome/DashboardTable_spec.tsx @@ -55,7 +55,7 @@ describe('DashboardTable', () => { expect(fetchMock.calls(dashboardsEndpoint)).toHaveLength(1); // there's a delay between response and updating state, so manually set it // rather than adding a timeout which could introduce flakiness - wrapper.setState({ dashaboards: mockDashboards }); + wrapper.setState({ dashboards: mockDashboards }); expect(wrapper.find(ListView)).toHaveLength(1); done(); }); diff --git a/superset-frontend/spec/javascripts/welcome/Welcome_spec.jsx b/superset-frontend/spec/javascripts/welcome/Welcome_spec.tsx similarity index 81% rename from superset-frontend/spec/javascripts/welcome/Welcome_spec.jsx rename to superset-frontend/spec/javascripts/welcome/Welcome_spec.tsx index 763ff3e..0e7e5e1 100644 --- a/superset-frontend/spec/javascripts/welcome/Welcome_spec.jsx +++ b/superset-frontend/spec/javascripts/welcome/Welcome_spec.tsx @@ -23,11 +23,21 @@ import { shallow } from 'enzyme'; import Welcome from 'src/welcome/Welcome'; describe('Welcome', () => { - const mockedProps = {}; + const mockedProps = { + user: { + username: 'alpha', + firstName: 'alpha', + lastName: 'alpha', + createdOn: '2016-11-11T12:34:17', + userId: 5, + email: 'al...@alpha.com', + isActive: true, + }, + }; it('is valid', () => { expect(React.isValidElement(<Welcome {...mockedProps} />)).toBe(true); }); - it('renders 4 Tab, Panel, and Row components', () => { + it('renders 3 Tab, Panel, and Row components', () => { const wrapper = shallow(<Welcome {...mockedProps} />); expect(wrapper.find(Tab)).toHaveLength(3); expect(wrapper.find(Panel)).toHaveLength(3); diff --git a/superset-frontend/src/profile/components/App.tsx b/superset-frontend/src/profile/components/App.tsx index bde67ac..470bf73 100644 --- a/superset-frontend/src/profile/components/App.tsx +++ b/superset-frontend/src/profile/components/App.tsx @@ -25,10 +25,10 @@ import UserInfo from './UserInfo'; import Security from './Security'; import RecentActivity from './RecentActivity'; import CreatedContent from './CreatedContent'; -import { User } from '../types'; +import { UserWithPermissionsAndRoles } from '../../types/bootstrapTypes'; interface AppProps { - user: User; + user: UserWithPermissionsAndRoles; } export default function App({ user }: AppProps) { diff --git a/superset-frontend/src/profile/components/CreatedContent.tsx b/superset-frontend/src/profile/components/CreatedContent.tsx index 9831e4d..933b3e6 100644 --- a/superset-frontend/src/profile/components/CreatedContent.tsx +++ b/superset-frontend/src/profile/components/CreatedContent.tsx @@ -21,7 +21,8 @@ import moment from 'moment'; import { t } from '@superset-ui/translation'; import TableLoader from '../../components/TableLoader'; -import { User, Dashboard, Slice } from '../types'; +import { Slice } from '../types'; +import { User, Dashboard } from '../../types/bootstrapTypes'; interface CreatedContentProps { user: User; diff --git a/superset-frontend/src/profile/components/Favorites.tsx b/superset-frontend/src/profile/components/Favorites.tsx index 89b4cc4..ca059f4 100644 --- a/superset-frontend/src/profile/components/Favorites.tsx +++ b/superset-frontend/src/profile/components/Favorites.tsx @@ -21,7 +21,8 @@ import moment from 'moment'; import { t } from '@superset-ui/translation'; import TableLoader from '../../components/TableLoader'; -import { User, Dashboard, Slice } from '../types'; +import { Slice } from '../types'; +import { User, Dashboard } from '../../types/bootstrapTypes'; interface FavoritesProps { user: User; diff --git a/superset-frontend/src/profile/components/RecentActivity.tsx b/superset-frontend/src/profile/components/RecentActivity.tsx index 34f419c..30faf97 100644 --- a/superset-frontend/src/profile/components/RecentActivity.tsx +++ b/superset-frontend/src/profile/components/RecentActivity.tsx @@ -20,7 +20,8 @@ import React from 'react'; import moment from 'moment'; import TableLoader from '../../components/TableLoader'; -import { User, Activity } from '../types'; +import { Activity } from '../types'; +import { User } from '../../types/bootstrapTypes'; interface RecentActivityProps { user: User; diff --git a/superset-frontend/src/profile/components/Security.tsx b/superset-frontend/src/profile/components/Security.tsx index 91b0284..9646fa1 100644 --- a/superset-frontend/src/profile/components/Security.tsx +++ b/superset-frontend/src/profile/components/Security.tsx @@ -19,10 +19,10 @@ import React from 'react'; import { Badge, Label } from 'react-bootstrap'; import { t } from '@superset-ui/translation'; -import { User } from '../types'; +import { UserWithPermissionsAndRoles } from '../../types/bootstrapTypes'; interface SecurityProps { - user: User; + user: UserWithPermissionsAndRoles; } export default function Security({ user }: SecurityProps) { diff --git a/superset-frontend/src/profile/components/UserInfo.tsx b/superset-frontend/src/profile/components/UserInfo.tsx index ccc1c89..ffc4179 100644 --- a/superset-frontend/src/profile/components/UserInfo.tsx +++ b/superset-frontend/src/profile/components/UserInfo.tsx @@ -21,10 +21,10 @@ import Gravatar from 'react-gravatar'; import moment from 'moment'; import { Panel } from 'react-bootstrap'; import { t } from '@superset-ui/translation'; -import { User } from '../types'; +import { UserWithPermissionsAndRoles } from '../../types/bootstrapTypes'; interface UserInfoProps { - user: User; + user: UserWithPermissionsAndRoles; } export default function UserInfo({ user }: UserInfoProps) { diff --git a/superset-frontend/src/profile/types.ts b/superset-frontend/src/profile/types.ts index 4e5a7eb..a2433e0 100644 --- a/superset-frontend/src/profile/types.ts +++ b/superset-frontend/src/profile/types.ts @@ -16,21 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -export type User = { - createdOn: string; - email: string; - firstName: string; - isActive: boolean; - lastName: string; - permissions: { - database_access?: string[]; - datasource_access?: string[]; - }; - roles: Record<string, any>; - userId: number; - username: string; -}; - export type Slice = { dttm: number; id: number; @@ -41,15 +26,6 @@ export type Slice = { viz_type: string; }; -export type Dashboard = { - dttm: number; - id: number; - url: string; - title: string; - creator?: string; - creator_url?: string; -}; - export type Activity = { action: string; item_title: string; diff --git a/superset-frontend/src/profile/types.ts b/superset-frontend/src/types/bootstrapTypes.ts similarity index 80% copy from superset-frontend/src/profile/types.ts copy to superset-frontend/src/types/bootstrapTypes.ts index 4e5a7eb..cb8fb1e 100644 --- a/superset-frontend/src/profile/types.ts +++ b/superset-frontend/src/types/bootstrapTypes.ts @@ -22,24 +22,17 @@ export type User = { firstName: string; isActive: boolean; lastName: string; - permissions: { - database_access?: string[]; - datasource_access?: string[]; - }; - roles: Record<string, any>; userId: number; username: string; }; -export type Slice = { - dttm: number; - id: number; - url: string; - title: string; - creator?: string; - creator_url?: string; - viz_type: string; -}; +export interface UserWithPermissionsAndRoles extends User { + permissions: { + database_access?: string[]; + datasource_access?: string[]; + }; + roles: Record<string, string[][]>; +} export type Dashboard = { dttm: number; @@ -49,10 +42,3 @@ export type Dashboard = { creator?: string; creator_url?: string; }; - -export type Activity = { - action: string; - item_title: string; - item_url: string; - time: number; -}; diff --git a/superset-frontend/src/welcome/App.jsx b/superset-frontend/src/welcome/App.tsx similarity index 97% rename from superset-frontend/src/welcome/App.jsx rename to superset-frontend/src/welcome/App.tsx index 42e3f29..267dd5a 100644 --- a/superset-frontend/src/welcome/App.jsx +++ b/superset-frontend/src/welcome/App.tsx @@ -44,7 +44,7 @@ setupApp(); setupPlugins(); const container = document.getElementById('app'); -const bootstrap = JSON.parse(container.getAttribute('data-bootstrap')); +const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}'); const user = { ...bootstrap.user }; const menu = { ...bootstrap.common.menu_data }; const common = { ...bootstrap.common }; diff --git a/superset-frontend/src/welcome/DashboardTable.jsx b/superset-frontend/src/welcome/DashboardTable.tsx similarity index 80% rename from superset-frontend/src/welcome/DashboardTable.jsx rename to superset-frontend/src/welcome/DashboardTable.tsx index 6399064..704cdc3 100644 --- a/superset-frontend/src/welcome/DashboardTable.jsx +++ b/superset-frontend/src/welcome/DashboardTable.tsx @@ -17,35 +17,45 @@ * under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import { t } from '@superset-ui/translation'; import { SupersetClient } from '@superset-ui/connection'; import moment from 'moment'; import { debounce } from 'lodash'; import ListView from 'src/components/ListView/ListView'; import withToasts from 'src/messageToasts/enhancers/withToasts'; +import { Dashboard } from 'src/types/bootstrapTypes'; +import { FetchDataConfig } from 'src/components/ListView/types'; const PAGE_SIZE = 25; -class DashboardTable extends React.PureComponent { - static propTypes = { - addDangerToast: PropTypes.func.isRequired, - search: PropTypes.string, - }; +interface DashboardTableProps { + addDangerToast: (message: string) => void; + search?: string; +} + +interface DashboardTableState { + dashboards: Dashboard[]; + dashboard_count: number; + loading: boolean; +} +class DashboardTable extends React.PureComponent< + DashboardTableProps, + DashboardTableState +> { state = { dashboards: [], dashboard_count: 0, loading: false, }; - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: DashboardTableProps) { if (prevProps.search !== this.props.search) { this.fetchDataDebounced({ pageSize: PAGE_SIZE, pageIndex: 0, sortBy: this.initialSort, - filters: {}, + filters: [], }); } } @@ -58,6 +68,13 @@ class DashboardTable extends React.PureComponent { row: { original: { url, dashboard_title: dashboardTitle }, }, + }: { + row: { + original: { + url: string; + dashboard_title: string; + }; + }; }) => <a href={url}>{dashboardTitle}</a>, }, { @@ -67,6 +84,13 @@ class DashboardTable extends React.PureComponent { row: { original: { changed_by_name: changedByName, changedByUrl }, }, + }: { + row: { + original: { + changed_by_name: string; + changedByUrl: string; + }; + }; }) => <a href={changedByUrl}>{changedByName}</a>, }, { @@ -76,13 +100,19 @@ class DashboardTable extends React.PureComponent { row: { original: { changed_on: changedOn }, }, + }: { + row: { + original: { + changed_on: string; + }; + }; }) => <span className="no-wrap">{moment(changedOn).fromNow()}</span>, }, ]; initialSort = [{ id: 'changed_on', desc: true }]; - fetchData = ({ pageIndex, pageSize, sortBy, filters }) => { + fetchData = ({ pageIndex, pageSize, sortBy, filters }: FetchDataConfig) => { this.setState({ loading: true }); const filterExps = Object.keys(filters) .map(fk => ({ diff --git a/superset-frontend/src/welcome/Welcome.jsx b/superset-frontend/src/welcome/Welcome.tsx similarity index 83% rename from superset-frontend/src/welcome/Welcome.jsx rename to superset-frontend/src/welcome/Welcome.tsx index 97d17f9..3ec66e1 100644 --- a/superset-frontend/src/welcome/Welcome.jsx +++ b/superset-frontend/src/welcome/Welcome.tsx @@ -17,23 +17,30 @@ * under the License. */ import React, { useState } from 'react'; -import PropTypes from 'prop-types'; import { Panel, Row, Col, Tabs, Tab, FormControl } from 'react-bootstrap'; import { t } from '@superset-ui/translation'; -import { useQueryParam, StringParam } from 'use-query-params'; +import { useQueryParam, StringParam, QueryParamConfig } from 'use-query-params'; +import { User } from 'src/types/bootstrapTypes'; import RecentActivity from '../profile/components/RecentActivity'; import Favorites from '../profile/components/Favorites'; import DashboardTable from './DashboardTable'; -const propTypes = { - user: PropTypes.object.isRequired, -}; +interface WelcomeProps { + user: User; +} -function useSyncQueryState(queryParam, queryParamType, defaultState) { +function useSyncQueryState( + queryParam: string, + queryParamType: QueryParamConfig< + string | null | undefined, + string | undefined + >, + defaultState: string, +): [string, (val: string) => void] { const [queryState, setQueryState] = useQueryParam(queryParam, queryParamType); const [state, setState] = useState(queryState || defaultState); - const setQueryStateAndState = val => { + const setQueryStateAndState = (val: string) => { setQueryState(val); setState(val); }; @@ -41,7 +48,7 @@ function useSyncQueryState(queryParam, queryParamType, defaultState) { return [state, setQueryStateAndState]; } -export default function Welcome({ user }) { +export default function Welcome({ user }: WelcomeProps) { const [activeTab, setActiveTab] = useSyncQueryState( 'activeTab', StringParam, @@ -58,6 +65,7 @@ export default function Welcome({ user }) { <div className="container welcome"> <Tabs activeKey={activeTab} + // @ts-ignore React bootstrap types aren't quite right here onSelect={setActiveTab} id="uncontrolled-tab-example" > @@ -75,6 +83,7 @@ export default function Welcome({ user }) { style={{ marginTop: '25px' }} placeholder="Search" value={searchQuery} + // @ts-ignore React bootstrap types aren't quite right here onChange={e => setSearchQuery(e.currentTarget.value)} /> </Col> @@ -114,5 +123,3 @@ export default function Welcome({ user }) { </div> ); } - -Welcome.propTypes = propTypes; diff --git a/superset-frontend/src/welcome/index.jsx b/superset-frontend/src/welcome/index.tsx similarity index 100% rename from superset-frontend/src/welcome/index.jsx rename to superset-frontend/src/welcome/index.tsx diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index 2d3545b..d6295d3 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -181,7 +181,7 @@ const config = { explore: addPreamble('/src/explore/index.jsx'), dashboard: addPreamble('/src/dashboard/index.jsx'), sqllab: addPreamble('/src/SqlLab/index.tsx'), - welcome: addPreamble('/src/welcome/index.jsx'), + welcome: addPreamble('/src/welcome/index.tsx'), profile: addPreamble('/src/profile/index.tsx'), showSavedQuery: [path.join(APP_DIR, '/src/showSavedQuery/index.jsx')], },