Commit dbb5bc16 authored by Filipa Lacerda's avatar Filipa Lacerda

Removes extra call to fetch deploy boards

Reads 3 states from API response
Removes error state
Set all deploy boards to be opened by default
Updates tests to match new behavior
Adds a changelog entry
parent fc4d3a57
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* - Button Actions. * - Button Actions.
* [Mockup](https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png) * [Mockup](https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
*/ */
import _ from 'underscore';
import deployBoardSvg from 'empty_states/icons/_deploy_board.svg'; import deployBoardSvg from 'empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component.vue'; import instanceComponent from './deploy_board_instance_component.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue'; import loadingIcon from '../../vue_shared/components/loading_icon.vue';
...@@ -26,40 +27,27 @@ ...@@ -26,40 +27,27 @@
type: Boolean, type: Boolean,
required: true, required: true,
}, },
hasError: { isEmpty: {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
}, },
data() {
return {
deployBoardSvg,
};
},
computed: { computed: {
canRenderDeployBoard() { canRenderDeployBoard() {
return !this.isLoading && !this.hasError && this.deployBoardData.valid; return !this.isLoading && !this.isEmpty && !_.isEmpty(this.deployBoardData);
}, },
canRenderEmptyState() { canRenderEmptyState() {
return !this.isLoading && !this.hasError && !this.deployBoardData.valid; return !this.isLoading && this.isEmpty;
},
canRenderErrorState() {
return !this.isLoading && this.hasError;
}, },
instanceTitle() { instanceTitle() {
let title; return gl.text.pluralize('Instance', this.deployBoardData.instances);
if (this.deployBoardData.instances.length === 1) {
title = 'Instance';
} else {
title = 'Instances';
}
return title;
}, },
projectName() { projectName() {
return '<projectname>'; return '<projectname>';
}, },
deployBoardSvg() {
return deployBoardSvg;
},
}, },
}; };
</script> </script>
...@@ -128,11 +116,5 @@ ...@@ -128,11 +116,5 @@
</span> </span>
</section> </section>
</div> </div>
<div
v-if="canRenderErrorState"
class="deploy-board-error-message">
We can't fetch the data right now. Please try again later.
</div>
</div> </div>
</script> </script>
...@@ -127,16 +127,10 @@ export default { ...@@ -127,16 +127,10 @@ export default {
/** /**
* Toggles the visibility of the deploy boards of the clicked environment. * Toggles the visibility of the deploy boards of the clicked environment.
* * @param {Object} model
* @param {Object} model
* @return {Object}
*/ */
toggleDeployBoard(model) { toggleDeployBoard(model) {
this.store.toggleDeployBoard(model.id); this.store.toggleDeployBoard(model.id);
if (!model.isDeployboardVisible) {
this.fetchDeployBoard(model, true);
}
}, },
toggleFolder(folder) { toggleFolder(folder) {
...@@ -203,11 +197,6 @@ export default { ...@@ -203,11 +197,6 @@ export default {
if (openFolders.length) { if (openFolders.length) {
openFolders.forEach(folder => this.fetchChildEnvironments(folder)); openFolders.forEach(folder => this.fetchChildEnvironments(folder));
} }
const openDeployBoards = this.store.getOpenDeployBoards();
if (openDeployBoards.length) {
openDeployBoards.forEach(env => this.fetchDeployBoard(env));
}
}, },
errorCallback() { errorCallback() {
...@@ -215,23 +204,6 @@ export default { ...@@ -215,23 +204,6 @@ export default {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Flash('An error occurred while fetching the environments.'); new Flash('An error occurred while fetching the environments.');
}, },
fetchDeployBoard(environment, showLoader = false) {
this.store.updateEnvironmentProp(environment, 'isLoadingDeployBoard', showLoader);
this.service.getDeployBoard(environment.rollout_status_path)
.then(resp => resp.json())
.then((data) => {
this.store.storeDeployBoard(environment.id, data);
this.store.updateEnvironmentProp(environment, 'isLoadingDeployBoard', false);
})
.catch(() => {
this.store.updateEnvironmentProp(environment, 'isLoadingDeployBoard', false);
this.store.updateEnvironmentProp(environment, 'hasErrorDeployBoard', true);
// eslint-disable-next-line no-new
new Flash('An error occurred while fetching the deploy board.');
});
},
}, },
}; };
</script> </script>
......
...@@ -74,7 +74,7 @@ export default { ...@@ -74,7 +74,7 @@ export default {
<deploy-board <deploy-board
:deploy-board-data="model.deployBoardData" :deploy-board-data="model.deployBoardData"
:is-loading="model.isLoadingDeployBoard" :is-loading="model.isLoadingDeployBoard"
:has-error="model.hasErrorDeployBoard" :is-empty="model.isEmptyDeployBoard"
/> />
</div> </div>
</div> </div>
......
...@@ -30,7 +30,7 @@ export default class EnvironmentsStore { ...@@ -30,7 +30,7 @@ export default class EnvironmentsStore {
* If the `size` is bigger than 1, it means it should be rendered as a folder. * If the `size` is bigger than 1, it means it should be rendered as a folder.
* In those cases we add `isFolder` key in order to render it properly. * In those cases we add `isFolder` key in order to render it properly.
* *
* Top level environments - when the size is 1 - with `rollout_status_path` * Top level environments - when the size is 1 - with `rollout_status`
* can render a deploy board. We add `isDeployBoardVisible` and `deployBoardData` * can render a deploy board. We add `isDeployBoardVisible` and `deployBoardData`
* keys to those environments. * keys to those environments.
* The first key will let's us know if we should or not render the deploy board. * The first key will let's us know if we should or not render the deploy board.
...@@ -65,13 +65,15 @@ export default class EnvironmentsStore { ...@@ -65,13 +65,15 @@ export default class EnvironmentsStore {
filtered = Object.assign(filtered, env); filtered = Object.assign(filtered, env);
} }
if (filtered.size === 1 && filtered.rollout_status_path) { if (filtered.size === 1 && filtered.rollout_status) {
filtered = Object.assign({}, filtered, { filtered = Object.assign({}, filtered, {
hasDeployBoard: true, hasDeployBoard: true,
isDeployBoardVisible: oldEnvironmentState.isDeployBoardVisible || false, isDeployBoardVisible: oldEnvironmentState.isDeployBoardVisible === false ?
deployBoardData: oldEnvironmentState.deployBoardData || {}, oldEnvironmentState.isDeployBoardVisible :
isLoadingDeployBoard: oldEnvironmentState.isLoadingDeployBoard || false, true,
hasErrorDeployBoard: oldEnvironmentState.hasErrorDeployBoard || false, deployBoardData: filtered.rollout_status.status === 'found' ? filtered.rollout_status : {},
isLoadingDeployBoard: filtered.rollout_status.status === 'loading',
isEmptyDeployBoard: filtered.rollout_status.status === 'not_found',
}); });
} }
return filtered; return filtered;
......
---
title: Improves visibility of deploy boards
merge_request:
author:
type: changed
import Vue from 'vue'; import Vue from 'vue';
import DeployBoard from '~/environments/components/deploy_board_component.vue'; import DeployBoard from '~/environments/components/deploy_board_component.vue';
import { deployBoardMockData, invalidDeployBoardMockData } from './mock_data'; import { deployBoardMockData } from './mock_data';
describe('Deploy Board', () => { describe('Deploy Board', () => {
let DeployBoardComponent; let DeployBoardComponent;
...@@ -17,7 +17,7 @@ describe('Deploy Board', () => { ...@@ -17,7 +17,7 @@ describe('Deploy Board', () => {
propsData: { propsData: {
deployBoardData: deployBoardMockData, deployBoardData: deployBoardMockData,
isLoading: false, isLoading: false,
hasError: false, isEmpty: false,
}, },
}).$mount(); }).$mount();
}); });
...@@ -46,15 +46,15 @@ describe('Deploy Board', () => { ...@@ -46,15 +46,15 @@ describe('Deploy Board', () => {
}); });
}); });
describe('without valid data', () => { describe('with empty state', () => {
let component; let component;
beforeEach(() => { beforeEach(() => {
component = new DeployBoardComponent({ component = new DeployBoardComponent({
propsData: { propsData: {
deployBoardData: invalidDeployBoardMockData, deployBoardData: {},
isLoading: false, isLoading: false,
hasError: false, isEmpty: true,
}, },
}).$mount(); }).$mount();
}); });
...@@ -65,21 +65,21 @@ describe('Deploy Board', () => { ...@@ -65,21 +65,21 @@ describe('Deploy Board', () => {
}); });
}); });
describe('with error', () => { describe('with loading state', () => {
let component; let component;
beforeEach(() => { beforeEach(() => {
component = new DeployBoardComponent({ component = new DeployBoardComponent({
propsData: { propsData: {
deployBoardData: {}, deployBoardData: {},
isLoading: false, isLoading: true,
hasError: true, isEmpty: false,
}, },
}).$mount(); }).$mount();
}); });
it('should render empty state', () => { it('should render loading spinner', () => {
expect(component.$el.children.length).toEqual(1); expect(component.$el.querySelector('.fa-spin')).toBeDefined();
}); });
}); });
}); });
...@@ -37,12 +37,11 @@ describe('Environment item', () => { ...@@ -37,12 +37,11 @@ describe('Environment item', () => {
size: 1, size: 1,
environment_path: 'url', environment_path: 'url',
id: 1, id: 1,
rollout_status_path: 'url',
hasDeployBoard: true, hasDeployBoard: true,
deployBoardData: deployBoardMockData, deployBoardData: deployBoardMockData,
isDeployBoardVisible: true, isDeployBoardVisible: true,
isLoadingDeployBoard: false, isLoadingDeployBoard: false,
hasErrorDeployBoard: false, isEmptyDeployBoard: false,
}; };
const component = new EnvironmentTable({ const component = new EnvironmentTable({
...@@ -66,7 +65,6 @@ describe('Environment item', () => { ...@@ -66,7 +65,6 @@ describe('Environment item', () => {
size: 1, size: 1,
environment_path: 'url', environment_path: 'url',
id: 1, id: 1,
rollout_status_path: 'url',
hasDeployBoard: true, hasDeployBoard: true,
deployBoardData: { deployBoardData: {
instances: [ instances: [
......
...@@ -29,12 +29,12 @@ describe('Store', () => { ...@@ -29,12 +29,12 @@ describe('Store', () => {
stop_path: '/root/review-app/environments/7/stop', stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z', created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
rollout_status_path: '/path', rollout_status: {},
hasDeployBoard: true, hasDeployBoard: true,
isDeployBoardVisible: false, isDeployBoardVisible: true,
deployBoardData: {}, deployBoardData: {},
isLoadingDeployBoard: false, isLoadingDeployBoard: false,
hasErrorDeployBoard: false, isEmptyDeployBoard: false,
}; };
store.storeEnvironments(serverData); store.storeEnvironments(serverData);
...@@ -58,20 +58,20 @@ describe('Store', () => { ...@@ -58,20 +58,20 @@ describe('Store', () => {
expect(store.state.environments.length).toEqual(serverData.length); expect(store.state.environments.length).toEqual(serverData.length);
}); });
it('should store a non folder environment with deploy board if rollout_status_path key is provided', () => { it('should store a non folder environment with deploy board if rollout_status key is provided', () => {
const environment = { const environment = {
name: 'foo', name: 'foo',
size: 1, size: 1,
latest: { latest: {
id: 1, id: 1,
rollout_status_path: 'url', rollout_status: deployBoardMockData,
}, },
}; };
store.storeEnvironments([environment]); store.storeEnvironments([environment]);
expect(store.state.environments[0].hasDeployBoard).toEqual(true); expect(store.state.environments[0].hasDeployBoard).toEqual(true);
expect(store.state.environments[0].isDeployBoardVisible).toEqual(false); expect(store.state.environments[0].isDeployBoardVisible).toEqual(true);
expect(store.state.environments[0].deployBoardData).toEqual({}); expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
}); });
it('should add folder keys when environment is a folder', () => { it('should add folder keys when environment is a folder', () => {
...@@ -192,7 +192,7 @@ describe('Store', () => { ...@@ -192,7 +192,7 @@ describe('Store', () => {
latest: { latest: {
id: 1, id: 1,
}, },
rollout_status_path: 'path', rollout_status: deployBoardMockData,
}; };
store.storeEnvironments([environment]); store.storeEnvironments([environment]);
...@@ -201,16 +201,10 @@ describe('Store', () => { ...@@ -201,16 +201,10 @@ describe('Store', () => {
it('should toggle deploy board property for given environment id', () => { it('should toggle deploy board property for given environment id', () => {
store.toggleDeployBoard(1); store.toggleDeployBoard(1);
expect(store.state.environments[0].isDeployBoardVisible).toEqual(true); expect(store.state.environments[0].isDeployBoardVisible).toEqual(false);
});
it('should store deploy board data for given environment id', () => {
store.storeDeployBoard(1, deployBoardMockData);
expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
}); });
it('should keep deploy board data when updating environments', () => { it('should keep deploy board data when updating environments', () => {
store.storeDeployBoard(1, deployBoardMockData);
expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData); expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
const environment = { const environment = {
...@@ -219,7 +213,7 @@ describe('Store', () => { ...@@ -219,7 +213,7 @@ describe('Store', () => {
latest: { latest: {
id: 1, id: 1,
}, },
rollout_status_path: 'path', rollout_status: deployBoardMockData,
}; };
store.storeEnvironments([environment]); store.storeEnvironments([environment]);
expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData); expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
...@@ -243,12 +237,12 @@ describe('Store', () => { ...@@ -243,12 +237,12 @@ describe('Store', () => {
latest: { latest: {
id: 1, id: 1,
}, },
rollout_status_path: 'path', rollout_status: deployBoardMockData,
}; };
store.storeEnvironments([environment]); store.storeEnvironments([environment]);
expect(store.getOpenDeployBoards().length).toEqual(0); expect(store.getOpenDeployBoards().length).toEqual(1);
}); });
}); });
}); });
...@@ -12,7 +12,7 @@ export const environmentsList = [ ...@@ -12,7 +12,7 @@ export const environmentsList = [
stop_path: '/root/review-app/environments/7/stop', stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z', created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
rollout_status_path: '/path', rollout_status: {},
}, },
{ {
folderName: 'build', folderName: 'build',
...@@ -28,7 +28,7 @@ export const environmentsList = [ ...@@ -28,7 +28,7 @@ export const environmentsList = [
stop_path: '/root/review-app/environments/12/stop', stop_path: '/root/review-app/environments/12/stop',
created_at: '2017-02-01T19:42:18.400Z', created_at: '2017-02-01T19:42:18.400Z',
updated_at: '2017-02-01T19:42:18.400Z', updated_at: '2017-02-01T19:42:18.400Z',
rollout_status_path: '/path', rollout_status: {},
}, },
]; ];
...@@ -48,7 +48,7 @@ export const serverData = [ ...@@ -48,7 +48,7 @@ export const serverData = [
stop_path: '/root/review-app/environments/7/stop', stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z', created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
rollout_status_path: '/path', rollout_status: {},
}, },
}, },
{ {
...@@ -100,7 +100,7 @@ export const environment = { ...@@ -100,7 +100,7 @@ export const environment = {
stop_path: '/root/review-app/environments/7/stop', stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z', created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
rollout_status_path: '/path', rollout_status: {},
}; };
export const deployBoardMockData = { export const deployBoardMockData = {
...@@ -136,15 +136,7 @@ export const deployBoardMockData = { ...@@ -136,15 +136,7 @@ export const deployBoardMockData = {
abort_url: 'url', abort_url: 'url',
rollback_url: 'url', rollback_url: 'url',
completion: 100, completion: 100,
valid: true, status: 'found',
};
export const invalidDeployBoardMockData = {
instances: [],
abort_url: 'url',
rollback_url: 'url',
completion: 100,
valid: false,
}; };
export const folder = { export const folder = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment