Commit b3309bb2 authored by Filipa Lacerda's avatar Filipa Lacerda

Adjustments to receive new data schema

parent efa05023
...@@ -69,12 +69,10 @@ require('./environment_item'); ...@@ -69,12 +69,10 @@ require('./environment_item');
* Toggles loading property. * Toggles loading property.
*/ */
created() { created() {
gl.environmentsService = new EnvironmentsService(this.endpoint); const scope = this.$options.getQueryParameter('scope') || this.visibility;
const endpoint = `${this.endpoint}?scope=${scope}`;
const scope = this.$options.getQueryParameter('scope'); gl.environmentsService = new EnvironmentsService(endpoint);
if (scope) {
this.store.storeVisibility(scope);
}
this.isLoading = true; this.isLoading = true;
...@@ -82,6 +80,8 @@ require('./environment_item'); ...@@ -82,6 +80,8 @@ require('./environment_item');
.then(resp => resp.json()) .then(resp => resp.json())
.then((json) => { .then((json) => {
this.store.storeEnvironments(json); this.store.storeEnvironments(json);
})
.then(() => {
this.isLoading = false; this.isLoading = false;
}) })
.catch(() => { .catch(() => {
...@@ -165,8 +165,7 @@ require('./environment_item'); ...@@ -165,8 +165,7 @@ require('./environment_item');
</a> </a>
</p> </p>
<a <a v-if="canCreateEnvironmentParsed"
v-if="canCreateEnvironmentParsed"
:href="newEnvironmentPath" :href="newEnvironmentPath"
class="btn btn-create js-new-environment-button"> class="btn btn-create js-new-environment-button">
New Environment New Environment
...@@ -174,7 +173,7 @@ require('./environment_item'); ...@@ -174,7 +173,7 @@ require('./environment_item');
</div> </div>
<div class="table-holder" <div class="table-holder"
v-if="!isLoading && state.filteredEnvironments.length > 0"> v-if="!isLoading && state.environments.length > 0">
<table class="table ci-table environments"> <table class="table ci-table environments">
<thead> <thead>
<tr> <tr>
...@@ -187,31 +186,15 @@ require('./environment_item'); ...@@ -187,31 +186,15 @@ require('./environment_item');
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<template v-for="model in state.filteredEnvironments" <template v-for="model in state.environments"
v-bind:model="model"> v-bind:model="model">
<tr is="environment-item"
<tr
is="environment-item"
:model="model" :model="model"
:toggleRow="toggleRow.bind(model)"
:can-create-deployment="canCreateDeploymentParsed" :can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed" :can-read-environment="canReadEnvironmentParsed"
:play-icon-svg="playIconSvg" :play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg" :terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg"></tr> :commit-icon-svg="commitIconSvg"></tr>
<tr v-if="model.isOpen && model.children && model.children.length > 0"
is="environment-item"
v-for="children in model.children"
:model="children"
:toggleRow="toggleRow.bind(children)"
:can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"
:play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg">
</tr>
</template> </template>
</tbody> </tbody>
</table> </table>
......
...@@ -10,181 +10,41 @@ ...@@ -10,181 +10,41 @@
this.state.environments = []; this.state.environments = [];
this.state.stoppedCounter = 0; this.state.stoppedCounter = 0;
this.state.availableCounter = 0; this.state.availableCounter = 0;
this.state.visibility = 'available';
this.state.filteredEnvironments = []; this.state.filteredEnvironments = [];
return this; return this;
}, },
/** /**
* In order to display a tree view we need to modify the received
* data in to a tree structure based on `environment_type`
* sorted alphabetically.
* In each children a `vue-` property will be added. This property will be
* used to know if an item is a children mostly for css purposes. This is
* needed because the children row is a fragment instance and therfore does
* not accept non-prop attributes.
* *
* Stores the received environments.
* *
* @example * Each environment has the following schema
* it will transform this: * { name: String, size: Number, latest: Object }
* [
* { name: "environment", environment_type: "review" },
* { name: "environment_1", environment_type: null }
* { name: "environment_2, environment_type: "review" }
* ]
* into this:
* [
* { name: "review", children:
* [
* { name: "environment", environment_type: "review", vue-isChildren: true},
* { name: "environment_2", environment_type: "review", vue-isChildren: true}
* ]
* },
* {name: "environment_1", environment_type: null}
* ]
* *
* 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.
* *
* @param {Array} environments List of environments. * @param {Array} environments
* @returns {Array} Tree structured array with the received environments. * @returns {Array}
*/ */
storeEnvironments(environments = []) { storeEnvironments(environments = []) {
this.state.stoppedCounter = this.countByState(environments, 'stopped'); const filteredEnvironments = environments.map((env) => {
this.state.availableCounter = this.countByState(environments, 'available'); if (env.size > 1) {
return Object.assign({}, env, { isFolder: true });
const environmentsTree = environments.reduce((acc, environment) => {
if (environment.environment_type !== null) {
const occurs = acc.filter(element => element.children &&
element.name === environment.environment_type);
environment['vue-isChildren'] = true;
if (occurs.length) {
acc[acc.indexOf(occurs[0])].children.push(environment);
acc[acc.indexOf(occurs[0])].children.slice().sort(this.sortByName);
} else {
acc.push({
name: environment.environment_type,
children: [environment],
isOpen: false,
'vue-isChildren': environment['vue-isChildren'],
});
}
} else {
acc.push(environment);
}
return acc;
}, []).slice().sort(this.sortByName);
this.state.environments = environmentsTree;
this.filterEnvironmentsByVisibility(this.state.environments);
return environmentsTree;
},
storeVisibility(visibility) {
this.state.visibility = visibility;
},
/**
* Given the visibility prop provided by the url query parameter and which
* changes according to the active tab we need to filter which environments
* should be visible.
*
* The environments array is a recursive tree structure and we need to filter
* both root level environments and children environments.
*
* In order to acomplish that, both `filterState` and `filterEnvironmentsByVisibility`
* functions work together.
* The first one works as the filter that verifies if the given environment matches
* the given state.
* The second guarantees both root level and children elements are filtered as well.
*
* Given array of environments will return only
* the environments that match the state stored.
*
* @param {Array} array
* @return {Array}
*/
filterEnvironmentsByVisibility(arr) {
const filteredEnvironments = arr.map((item) => {
if (item.children) {
const filteredChildren = this.filterEnvironmentsByVisibility(
item.children,
).filter(Boolean);
if (filteredChildren.length) {
item.children = filteredChildren;
return item;
}
}
return this.filterState(this.state.visibility, item);
}).filter(Boolean);
this.state.filteredEnvironments = filteredEnvironments;
return filteredEnvironments;
},
/**
* Given the state and the environment,
* returns only if the environment state matches the one provided.
*
* @param {String} state
* @param {Object} environment
* @return {Object}
*/
filterState(state, environment) {
return environment.state === state && environment;
},
/**
* Toggles folder open property given the environment type.
*
* @param {String} envType
* @return {Array}
*/
toggleFolder(envType) {
const environments = this.state.environments;
const environmentsCopy = environments.map((env) => {
if (env['vue-isChildren'] && env.name === envType) {
env.isOpen = !env.isOpen;
} }
return env; return env;
}); });
this.state.environments = environmentsCopy; this.state.environments = filteredEnvironments;
return environmentsCopy; return filteredEnvironments;
}, },
/** storeCounts() {
* Given an array of environments, returns the number of environments //TODO
* that have the given state.
*
* @param {Array} environments
* @param {String} state
* @returns {Number}
*/
countByState(environments, state) {
return environments.filter(env => env.state === state).length;
}, },
/**
* Sorts the two objects provided by their name.
*
* @param {Object} a
* @param {Object} b
* @returns {Number}
*/
sortByName(a, b) {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
return nameA < nameB ? -1 : nameA > nameB ? 1 : 0; // eslint-disable-line
},
}; };
})(); })();
...@@ -110,17 +110,19 @@ ...@@ -110,17 +110,19 @@
} }
} }
.children-row .environment-name {
margin-left: 17px;
margin-right: -17px;
}
.folder-icon { .folder-icon {
padding: 0 5px 0 0; margin-right: 3px;
color: $gl-text-color-secondary;
.fa:nth-child(1) {
margin-right: 3px;
}
} }
.folder-name { .folder-name {
cursor: pointer; cursor: pointer;
text-decoration: none;
color: $gl-text-color-secondary;
} }
} }
...@@ -135,4 +137,4 @@ ...@@ -135,4 +137,4 @@
margin-right: 0; margin-right: 0;
} }
} }
} }
\ No newline at end of file
...@@ -14,33 +14,13 @@ describe('Environment item', () => { ...@@ -14,33 +14,13 @@ describe('Environment item', () => {
beforeEach(() => { beforeEach(() => {
mockItem = { mockItem = {
name: 'review', name: 'review',
children: [ size: 3
{
name: 'review-app',
id: 1,
state: 'available',
external_url: '',
last_deployment: {},
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-10T15:55:58.778Z',
},
{
name: 'production',
id: 2,
state: 'available',
external_url: '',
last_deployment: {},
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-10T15:55:58.778Z',
},
],
}; };
component = new window.gl.environmentsList.EnvironmentItem({ component = new window.gl.environmentsList.EnvironmentItem({
el: document.querySelector('tr#environment-row'), el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: mockItem, model: mockItem,
toggleRow: () => {},
canCreateDeployment: false, canCreateDeployment: false,
canReadEnvironment: true, canReadEnvironment: true,
}, },
...@@ -53,7 +33,7 @@ describe('Environment item', () => { ...@@ -53,7 +33,7 @@ describe('Environment item', () => {
}); });
it('Should render the number of children in a badge', () => { it('Should render the number of children in a badge', () => {
expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(mockItem.children.length); expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(mockItem.size);
}); });
}); });
...@@ -63,38 +43,23 @@ describe('Environment item', () => { ...@@ -63,38 +43,23 @@ describe('Environment item', () => {
beforeEach(() => { beforeEach(() => {
environment = { environment = {
id: 31,
name: 'production', name: 'production',
state: 'stopped', size: 1,
external_url: 'http://external.com', latest: {
environment_type: null, state: 'stopped',
last_deployment: { external_url: 'http://external.com',
id: 66, environment_type: null,
iid: 6, last_deployment: {
sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', id: 66,
ref: { iid: 6,
name: 'master', sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
ref_path: 'root/ci-folders/tree/master', ref: {
}, name: 'master',
tag: true, ref_path: 'root/ci-folders/tree/master',
'last?': true, },
user: { tag: true,
name: 'Administrator', 'last?': true,
username: 'root', user: {
id: 1,
state: 'active',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit: {
id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
short_id: '500aabcb',
title: 'Update .gitlab-ci.yml',
author_name: 'Administrator',
author_email: 'admin@example.com',
created_at: '2016-11-07T18:28:13.000+00:00',
message: 'Update .gitlab-ci.yml',
author: {
name: 'Administrator', name: 'Administrator',
username: 'root', username: 'root',
id: 1, id: 1,
...@@ -102,34 +67,50 @@ describe('Environment item', () => { ...@@ -102,34 +67,50 @@ describe('Environment item', () => {
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root', web_url: 'http://localhost:3000/root',
}, },
commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', commit: {
}, id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
deployable: { short_id: '500aabcb',
id: 1279, title: 'Update .gitlab-ci.yml',
name: 'deploy', author_name: 'Administrator',
build_path: '/root/ci-folders/builds/1279', author_email: 'admin@example.com',
retry_path: '/root/ci-folders/builds/1279/retry', created_at: '2016-11-07T18:28:13.000+00:00',
created_at: '2016-11-29T18:11:58.430Z', message: 'Update .gitlab-ci.yml',
updated_at: '2016-11-29T18:11:58.430Z', author: {
}, name: 'Administrator',
manual_actions: [ username: 'root',
{ id: 1,
name: 'action', state: 'active',
play_path: '/play', avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
}, },
], deployable: {
id: 1279,
name: 'deploy',
build_path: '/root/ci-folders/builds/1279',
retry_path: '/root/ci-folders/builds/1279/retry',
created_at: '2016-11-29T18:11:58.430Z',
updated_at: '2016-11-29T18:11:58.430Z',
},
manual_actions: [
{
name: 'action',
play_path: '/play',
},
],
},
'stop_action?': true,
environment_path: 'root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-10T15:55:58.778Z',
}, },
'stop_action?': true,
environment_path: 'root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-10T15:55:58.778Z',
}; };
component = new window.gl.environmentsList.EnvironmentItem({ component = new window.gl.environmentsList.EnvironmentItem({
el: document.querySelector('tr#environment-row'), el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: environment, model: environment,
toggleRow: () => {},
canCreateDeployment: true, canCreateDeployment: true,
canReadEnvironment: true, canReadEnvironment: true,
}, },
...@@ -144,7 +125,7 @@ describe('Environment item', () => { ...@@ -144,7 +125,7 @@ describe('Environment item', () => {
it('should render deployment internal id', () => { it('should render deployment internal id', () => {
expect( expect(
component.$el.querySelector('.deployment-column span').textContent, component.$el.querySelector('.deployment-column span').textContent,
).toContain(environment.last_deployment.iid); ).toContain(environment.latest.last_deployment.iid);
expect( expect(
component.$el.querySelector('.deployment-column span').textContent, component.$el.querySelector('.deployment-column span').textContent,
...@@ -154,7 +135,7 @@ describe('Environment item', () => { ...@@ -154,7 +135,7 @@ describe('Environment item', () => {
it('should render last deployment date', () => { it('should render last deployment date', () => {
const timeagoInstance = new timeago(); // eslint-disable-line const timeagoInstance = new timeago(); // eslint-disable-line
const formatedDate = timeagoInstance.format( const formatedDate = timeagoInstance.format(
environment.last_deployment.deployable.created_at, environment.latest.last_deployment.deployable.created_at,
); );
expect( expect(
...@@ -166,7 +147,7 @@ describe('Environment item', () => { ...@@ -166,7 +147,7 @@ describe('Environment item', () => {
it('should render user avatar with link to profile', () => { it('should render user avatar with link to profile', () => {
expect( expect(
component.$el.querySelector('.js-deploy-user-container').getAttribute('href'), component.$el.querySelector('.js-deploy-user-container').getAttribute('href'),
).toEqual(environment.last_deployment.user.web_url); ).toEqual(environment.latest.last_deployment.user.web_url);
}); });
}); });
...@@ -174,13 +155,13 @@ describe('Environment item', () => { ...@@ -174,13 +155,13 @@ describe('Environment item', () => {
it('Should link to build url provided', () => { it('Should link to build url provided', () => {
expect( expect(
component.$el.querySelector('.build-link').getAttribute('href'), component.$el.querySelector('.build-link').getAttribute('href'),
).toEqual(environment.last_deployment.deployable.build_path); ).toEqual(environment.latest.last_deployment.deployable.build_path);
}); });
it('Should render deployable name and id', () => { it('Should render deployable name and id', () => {
expect( expect(
component.$el.querySelector('.build-link').getAttribute('href'), component.$el.querySelector('.build-link').getAttribute('href'),
).toEqual(environment.last_deployment.deployable.build_path); ).toEqual(environment.latest.last_deployment.deployable.build_path);
}); });
}); });
......
...@@ -20,50 +20,10 @@ require('./mock_data'); ...@@ -20,50 +20,10 @@ require('./mock_data');
gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList); gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList);
}); });
it('should count stopped environments and save the count in the state', () => { it('should store environments', () => {
expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(1); expect(
}); gl.environmentsList.EnvironmentsStore.state.environments.length
).toBe(environmentsList.length);
it('should count available environments and save the count in the state', () => {
expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(3);
});
it('should store environments with same environment_type as sibilings', () => {
expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(3);
const parentFolder = gl.environmentsList.EnvironmentsStore.state.environments
.filter(env => env.children && env.children.length > 0);
expect(parentFolder[0].children.length).toBe(2);
expect(parentFolder[0].children[0].environment_type).toBe('review');
expect(parentFolder[0].children[1].environment_type).toBe('review');
expect(parentFolder[0].children[0].name).toBe('test-environment');
expect(parentFolder[0].children[1].name).toBe('test-environment-1');
});
it('should sort the environments alphabetically', () => {
const { environments } = gl.environmentsList.EnvironmentsStore.state;
expect(environments[0].name).toBe('production');
expect(environments[1].name).toBe('review');
expect(environments[1].children[0].name).toBe('test-environment');
expect(environments[1].children[1].name).toBe('test-environment-1');
expect(environments[2].name).toBe('review_app');
});
});
describe('toggleFolder', () => {
beforeEach(() => {
gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList);
});
it('should toggle the open property for the given environment', () => {
gl.environmentsList.EnvironmentsStore.toggleFolder('review');
const { environments } = gl.environmentsList.EnvironmentsStore.state;
const environment = environments.filter(env => env['vue-isChildren'] === true && env.name === 'review');
expect(environment[0].isOpen).toBe(true);
}); });
}); });
}); });
......
const environmentsList = [ const environmentsList = [
{ {
id: 31, name: 'DEV',
name: 'production', size: 1,
state: 'available', latest: {
external_url: 'https://www.gitlab.com', id: 7,
environment_type: null, name: 'DEV',
last_deployment: { state: 'available',
id: 64, external_url: null,
iid: 5, environment_type: null,
sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', last_deployment: null,
ref: { 'stop_action?': false,
name: 'master', environment_path: '/root/review-app/environments/7',
ref_url: 'http://localhost:3000/root/ci-folders/tree/master', stop_path: '/root/review-app/environments/7/stop',
}, created_at: '2017-01-31T10:53:46.894Z',
tag: false, updated_at: '2017-01-31T10:53:46.894Z',
'last?': true,
user: {
name: 'Administrator',
username: 'root',
id: 1,
state: 'active',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit: {
id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
short_id: '500aabcb',
title: 'Update .gitlab-ci.yml',
author_name: 'Administrator',
author_email: 'admin@example.com',
created_at: '2016-11-07T18:28:13.000+00:00',
message: 'Update .gitlab-ci.yml',
author: {
name: 'Administrator',
username: 'root',
id: 1,
state: 'active',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
},
deployable: {
id: 1278,
name: 'build',
build_path: '/root/ci-folders/builds/1278',
retry_path: '/root/ci-folders/builds/1278/retry',
},
manual_actions: [],
}, },
'stop_action?': true,
environment_path: '/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
}, },
{ {
id: 32, name: 'build',
name: 'review_app', size: 5,
state: 'stopped', latest: {
external_url: 'https://www.gitlab.com', id: 12,
environment_type: null, name: 'build/update-README',
last_deployment: { state: 'available',
id: 64, external_url: null,
iid: 5, environment_type: 'build',
sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', last_deployment: null,
ref: { 'stop_action?': false,
name: 'master', environment_path: '/root/review-app/environments/12',
ref_url: 'http://localhost:3000/root/ci-folders/tree/master', stop_path: '/root/review-app/environments/12/stop',
}, created_at: '2017-02-01T19:42:18.400Z',
tag: false, updated_at: '2017-02-01T19:42:18.400Z',
'last?': true,
user: {
name: 'Administrator',
username: 'root',
id: 1,
state: 'active',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit: {
id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
short_id: '500aabcb',
title: 'Update .gitlab-ci.yml',
author_name: 'Administrator',
author_email: 'admin@example.com',
created_at: '2016-11-07T18:28:13.000+00:00',
message: 'Update .gitlab-ci.yml',
author: {
name: 'Administrator',
username: 'root',
id: 1,
state: 'active',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
},
deployable: {
id: 1278,
name: 'build',
build_path: '/root/ci-folders/builds/1278',
retry_path: '/root/ci-folders/builds/1278/retry',
},
manual_actions: [],
}, },
'stop_action?': false,
environment_path: '/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
{
id: 33,
name: 'test-environment',
state: 'available',
environment_type: 'review',
last_deployment: null,
'stop_action?': true,
environment_path: '/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
{
id: 34,
name: 'test-environment-1',
state: 'available',
environment_type: 'review',
last_deployment: null,
'stop_action?': true,
environment_path: '/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
}, },
]; ];
window.environmentsList = environmentsList; window.environmentsList = environmentsList;
const environment = { const environment = {
id: 4, name: 'DEV',
name: 'production', size: 1,
state: 'available', latest: {
external_url: 'http://production.', id: 7,
environment_type: null, name: 'DEV',
last_deployment: {}, state: 'available',
'stop_action?': false, external_url: null,
environment_path: '/root/review-app/environments/4', environment_type: null,
stop_path: '/root/review-app/environments/4/stop', last_deployment: null,
created_at: '2016-12-16T11:51:04.690Z', 'stop_action?': false,
updated_at: '2016-12-16T12:04:51.133Z', environment_path: '/root/review-app/environments/7',
stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z',
},
}; };
window.environment = environment; window.environment = environment;
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