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')],
   },

Reply via email to