-
Notifications
You must be signed in to change notification settings - Fork 16.5k
feat: home screen mvp #11206
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: home screen mvp #11206
Changes from all commits
9875a0e
aa4c523
b79eced
d75fd9c
c0ec303
57148fc
bcef846
23bb1a4
0d153a1
90cbb62
b5863d3
d99b0af
fac22d9
bd44cae
beea872
ed9f380
4f85f3d
f02968d
c1e0188
b2099dc
ca65ce7
51b8ed2
33bc305
73430bd
d21ff1b
f9c0e17
f25b325
6affb81
f4e9e0c
f54d8d8
ee02a5a
48a061d
5399ccc
5a335e3
3199924
0b72ef8
7af5abb
68d4081
8af7bd2
596471a
2f7744b
ace8055
e3d94c4
ff22e81
09ff645
3af819d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| import React from 'react'; | ||
| import { styledMount as mount } from 'spec/helpers/theming'; | ||
| import thunk from 'redux-thunk'; | ||
| import fetchMock from 'fetch-mock'; | ||
|
|
||
| import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; | ||
| import configureStore from 'redux-mock-store'; | ||
| import ActivityTable from 'src/views/CRUD/welcome/ActivityTable'; | ||
|
|
||
| const mockStore = configureStore([thunk]); | ||
| const store = mockStore({}); | ||
|
|
||
| const chartsEndpoint = 'glob:*/api/v1/chart/?*'; | ||
| const dashboardEndpoint = 'glob:*/api/v1/dashboard/?*'; | ||
| const savedQueryEndpoint = 'glob:*/api/v1/saved_query/?*'; | ||
|
|
||
| fetchMock.get(chartsEndpoint, { | ||
| result: [ | ||
| { | ||
| slice_name: 'ChartyChart', | ||
| changed_on_utc: '24 Feb 2014 10:13:14', | ||
| url: '/fakeUrl/explore', | ||
| id: '4', | ||
| table: {}, | ||
| }, | ||
| ], | ||
| }); | ||
|
|
||
| fetchMock.get(dashboardEndpoint, { | ||
| result: [ | ||
| { | ||
| dashboard_title: 'Dashboard_Test', | ||
| changed_on_utc: '24 Feb 2014 10:13:14', | ||
| url: '/fakeUrl/dashboard', | ||
| id: '3', | ||
| }, | ||
| ], | ||
| }); | ||
|
|
||
| fetchMock.get(savedQueryEndpoint, { | ||
| result: [], | ||
| }); | ||
|
|
||
| describe('ActivityTable', () => { | ||
| const activityProps = { | ||
| user: { | ||
| userId: '1', | ||
| }, | ||
| activityFilter: 'Edited', | ||
| }; | ||
| const wrapper = mount(<ActivityTable {...activityProps} />, { | ||
| context: { store }, | ||
| }); | ||
|
|
||
| beforeAll(async () => { | ||
| await waitForComponentToPaint(wrapper); | ||
| }); | ||
|
|
||
| it('the component renders ', () => { | ||
| expect(wrapper.find(ActivityTable)).toExist(); | ||
| }); | ||
|
|
||
| it('calls batch method and renders ListViewCArd', async () => { | ||
| const chartCall = fetchMock.calls(/chart\/\?q/); | ||
| const dashboardCall = fetchMock.calls(/dashboard\/\?q/); | ||
| expect(chartCall).toHaveLength(2); | ||
| expect(dashboardCall).toHaveLength(2); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @junlincc Does it make sense to render less tabs in on first page load to cut down on these call. Our current implementation does batch call for recent activity, and signle calls for charts, dashboards and saved queries favorites.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ktmud I think there are a few ways we can approach the performance issues... potentially each of the four sections run queries and render separately, and there may be some queries we can combine if they use the same endpoint but different parameters Is the current state a dealbreaker for you, or would you be comfortable enough we merge this as-is then follow up with performance improvements in a new PR or two?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes please address performance issues separately after we get through most of the roadmap items.... |
||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| import React from 'react'; | ||
| import { styledMount as mount } from 'spec/helpers/theming'; | ||
| import thunk from 'redux-thunk'; | ||
| import fetchMock from 'fetch-mock'; | ||
| import configureStore from 'redux-mock-store'; | ||
|
|
||
| import ChartTable from 'src/views/CRUD/welcome/ChartTable'; | ||
| import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; | ||
|
|
||
| const mockStore = configureStore([thunk]); | ||
| const store = mockStore({}); | ||
|
|
||
| const chartsEndpoint = 'glob:*/api/v1/chart/?*'; | ||
| const chartsInfoEndpoint = 'glob:*/api/v1/chart/_info*'; | ||
|
|
||
| const mockCharts = [...new Array(3)].map((_, i) => ({ | ||
| changed_on_utc: new Date().toISOString(), | ||
| created_by: 'super user', | ||
| id: i, | ||
| slice_name: `cool chart ${i}`, | ||
| url: 'url', | ||
| viz_type: 'bar', | ||
| datasource_title: `ds${i}`, | ||
| thumbnail_url: '', | ||
| })); | ||
|
|
||
| fetchMock.get(chartsEndpoint, { | ||
| result: mockCharts, | ||
| }); | ||
|
|
||
| fetchMock.get(chartsInfoEndpoint, { | ||
| permissions: ['can_add', 'can_edit', 'can_delete'], | ||
| }); | ||
|
|
||
| describe('ChartTable', () => { | ||
| const mockedProps = { | ||
| user: { | ||
| userId: '2', | ||
| }, | ||
| }; | ||
| const wrapper = mount(<ChartTable {...mockedProps} />, { | ||
| context: { store }, | ||
| }); | ||
| it('it renders', () => { | ||
| expect(wrapper.find(ChartTable)).toExist(); | ||
| }); | ||
|
|
||
| it('fetches chart favorites and renders chart cards ', async () => { | ||
| expect(fetchMock.calls(chartsEndpoint)).toHaveLength(1); | ||
| await waitForComponentToPaint(wrapper); | ||
| expect(wrapper.find('ChartCard')).toExist(); | ||
| }); | ||
|
|
||
| it('display EmptyState if there is no data', () => { | ||
| fetchMock.resetHistory(); | ||
| const wrapper = mount(<ChartTable {...mockedProps} />, { | ||
| context: { store }, | ||
| }); | ||
| expect(wrapper.find('EmptyState')).toExist(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| import React from 'react'; | ||
| import { styledMount as mount } from 'spec/helpers/theming'; | ||
| import EmptyState from 'src/views/CRUD/welcome/EmptyState'; | ||
|
|
||
| describe('EmptyState', () => { | ||
| const variants = [ | ||
| { | ||
| tab: 'Favorite', | ||
| tableName: 'DASHBOARDS', | ||
| }, | ||
| { | ||
| tab: 'Mine', | ||
| tableName: 'DASHBOARDS', | ||
| }, | ||
| { | ||
| tab: 'Favorite', | ||
| tableName: 'CHARTS', | ||
| }, | ||
| { | ||
| tab: 'Mine', | ||
| tableName: 'CHARTS', | ||
| }, | ||
| { | ||
| tab: 'Favorite', | ||
| tableName: 'SAVED_QUERIES', | ||
| }, | ||
| { | ||
| tab: 'Mine', | ||
| tableName: 'SAVED_QUEREIS', | ||
| }, | ||
| ]; | ||
| const recents = [ | ||
| { | ||
| tab: 'Viewed', | ||
| tableName: 'RECENTS', | ||
| }, | ||
| { | ||
| tab: 'Edited', | ||
| tableName: 'RECENTS', | ||
| }, | ||
| { | ||
| tab: 'Created', | ||
| tableName: 'RECENTS', | ||
| }, | ||
| ]; | ||
pkdotson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| variants.forEach(variant => { | ||
| it(`it renders an ${variant.tab} ${variant.tableName} empty state`, () => { | ||
| const wrapper = mount(<EmptyState {...variant} />); | ||
| expect(wrapper).toExist(); | ||
| const textContainer = wrapper.find('.ant-empty-description'); | ||
| expect(textContainer.text()).toEqual( | ||
| variant.tab === 'Favorite' | ||
| ? "You don't have any favorites yet!" | ||
| : `No ${ | ||
| variant.tableName === 'SAVED_QUERIES' | ||
| ? 'saved queries' | ||
| : variant.tableName.toLowerCase() | ||
| } yet`, | ||
| ); | ||
| expect(wrapper.find('button')).toHaveLength(1); | ||
| }); | ||
| }); | ||
| recents.forEach(recent => { | ||
| it(`it renders an ${recent.tab} ${recent.tableName} empty state`, () => { | ||
| const wrapper = mount(<EmptyState {...recent} />); | ||
| expect(wrapper).toExist(); | ||
| const textContainer = wrapper.find('.ant-empty-description'); | ||
| expect(wrapper.find('.ant-empty-image').children()).toHaveLength(1); | ||
| expect(textContainer.text()).toContain( | ||
| `Recently ${recent.tab.toLowerCase()} charts, dashboards, and saved queries will appear here`, | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||

Uh oh!
There was an error while loading. Please reload this page.