Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
1285d629
Commit
1285d629
authored
Feb 13, 2017
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move change page param to utility function
Add tests Adds folder name in the top of the table
parent
73accafe
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
328 additions
and
72 deletions
+328
-72
app/assets/javascripts/environments/components/environment.js.es6
...ts/javascripts/environments/components/environment.js.es6
+5
-29
app/assets/javascripts/environments/components/environment_item.js.es6
...vascripts/environments/components/environment_item.js.es6
+2
-2
app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
...pts/environments/folder/environments_folder_bundle.js.es6
+1
-0
app/assets/javascripts/environments/folder/environments_folder_view.js.es6
...ripts/environments/folder/environments_folder_view.js.es6
+26
-41
app/assets/javascripts/lib/utils/common_utils.js.es6
app/assets/javascripts/lib/utils/common_utils.js.es6
+40
-0
app/assets/stylesheets/pages/environments.scss
app/assets/stylesheets/pages/environments.scss
+5
-0
spec/javascripts/environments/environment_table_spec.js.es6
spec/javascripts/environments/environment_table_spec.js.es6
+30
-0
spec/javascripts/environments/folder/environments_folder_view_spec.js.es6
.../environments/folder/environments_folder_view_spec.js.es6
+212
-0
spec/javascripts/fixtures/environments/environments_folder_view.html.haml
.../fixtures/environments/environments_folder_view.html.haml
+7
-0
No files found.
app/assets/javascripts/environments/components/environment.js.es6
View file @
1285d629
...
...
@@ -50,15 +50,15 @@ module.exports = Vue.component('environment-component', {
},
canReadEnvironmentParsed() {
return
this.$option
s.convertPermissionToBoolean(this.canReadEnvironment);
return
gl.util
s.convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
return
this.$option
s.convertPermissionToBoolean(this.canCreateDeployment);
return
gl.util
s.convertPermissionToBoolean(this.canCreateDeployment);
},
canCreateEnvironmentParsed() {
return
this.$option
s.convertPermissionToBoolean(this.canCreateEnvironment);
return
gl.util
s.convertPermissionToBoolean(this.canCreateEnvironment);
},
},
...
...
@@ -97,15 +97,6 @@ module.exports = Vue.component('environment-component', {
});
},
/**
* Converts permission provided as strings to booleans.
* @param {String} string
* @returns {Boolean}
*/
convertPermissionToBoolean(string) {
return string === 'true';
},
methods: {
toggleRow(model) {
return this.store.toggleFolder(model.name);
...
...
@@ -114,26 +105,11 @@ module.exports = Vue.component('environment-component', {
/**
* Will change the page number and update the URL.
*
* If no search params are present, we'll add param for page
* If param for page is already present, we'll update it
* If there are params but none for page, we'll add it at the end.
*
* @param {Number} pageNumber desired page to go to.
* @return {String}
*/
changePage(pageNumber) {
let param;
if (window.location.search.length === 0) {
param = `?page=${pageNumber}`;
}
if (window.location.search.indexOf('page') !== -1) {
param = window.location.search.replace(/page=\d/g, `page=${pageNumber}`);
}
if (window.location.search.length &&
window.location.search.indexOf('page') === -1) {
param = `${window.location.search}&page=${pageNumber}`;
}
const param = gl.utils.setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
...
...
app/assets/javascripts/environments/components/environment_item.js.es6
View file @
1285d629
...
...
@@ -99,7 +99,7 @@ module.exports = Vue.component('environment-item', {
* @returns {Boolean}
*/
hasStopAction() {
return this.model.latest['stop_action?'];
return this.model.latest
&& this.model.latest
['stop_action?'];
},
/**
...
...
@@ -414,7 +414,7 @@ module.exports = Vue.component('environment-item', {
* @return {String}
*/
folderUrl() {
return `${window.location.pathname}/folders/${this.model.
latest.id
}`;
return `${window.location.pathname}/folders/${this.model.
name
}`;
},
},
...
...
app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
View file @
1285d629
const EnvironmentsFolderComponent = require('./environments_folder_view');
require('../../vue_shared/vue_resource_interceptor');
$(() => {
window.gl = window.gl || {};
...
...
app/assets/javascripts/environments/folder/environments_folder_view.js.es6
View file @
1285d629
...
...
@@ -6,6 +6,7 @@ Vue.use(require('vue-resource'));
const EnvironmentsService = require('../services/environments_service');
const EnvironmentTable = require('../components/environments_table');
const Store = require('../stores/environments_store');
require('../../vue_shared/components/table_pagination');
require('../../lib/utils/common_utils');
module.exports = Vue.component('environment-folder-view', {
...
...
@@ -19,9 +20,11 @@ module.exports = Vue.component('environment-folder-view', {
const environmentsData = document.querySelector('#environments-folder-list-view').dataset;
const store = new Store();
const endpoint = `${window.location.pathname}.json`;
const folderName = window.location.pathname.substr(window.location.pathname.lastIndexOf('/') + 1);
return {
store,
folderName,
endpoint,
state: store.state,
visibility: 'available',
...
...
@@ -47,21 +50,30 @@ module.exports = Vue.component('environment-folder-view', {
},
canReadEnvironmentParsed() {
return
this.$option
s.convertPermissionToBoolean(this.canReadEnvironment);
return
gl.util
s.convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
return
this.$option
s.convertPermissionToBoolean(this.canCreateDeployment);
return
gl.util
s.convertPermissionToBoolean(this.canCreateDeployment);
},
/**
* URL to link in the stopped tab.
*
* @return {String}
*/
stoppedPath() {
return `${window.location.pathname}?scope=stopped`;
},
/**
* URL to link in the available tab.
*
* @return {String}
*/
availablePath() {
return window.location.pathname;
},
},
/**
...
...
@@ -84,6 +96,8 @@ module.exports = Vue.component('environment-folder-view', {
body: resp.json(),
}))
.then((response) => {
this.store.storeAvailableCount(response.body.available_count);
this.store.storeStoppedCount(response.body.stopped_count);
this.store.storeEnvironments(response.body.environments);
this.store.storePagination(response.headers);
})
...
...
@@ -96,45 +110,14 @@ module.exports = Vue.component('environment-folder-view', {
});
},
/**
* Transforms the url parameter into an object and
* returns the one requested.
*
* @param {String} param
* @returns {String} The value of the requested parameter.
*/
getQueryParameter(parameter) {
return window.location.search.substring(1).split('&').reduce((acc, param) => {
const paramSplited = param.split('=');
acc[paramSplited[0]] = paramSplited[1];
return acc;
}, {})[parameter];
},
methods: {
/**
* Will change the page number and update the URL.
*
* If no search params are present, we'll add param for page
* If param for page is already present, we'll update it
* If there are params but none for page, we'll add it at the end.
*
* @param {Number} pageNumber desired page to go to.
*/
changePage(pageNumber) {
let param;
if (window.location.search.length === 0) {
param = `?page=${pageNumber}`;
}
if (window.location.search.indexOf('page') !== -1) {
param = window.location.search.replace(/page=\d/g, `page=${pageNumber}`);
}
if (window.location.search.length &&
window.location.search.indexOf('page') === -1) {
param = `${window.location.search}&page=${pageNumber}`;
}
const param = gl.utils.setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
...
...
@@ -143,13 +126,15 @@ module.exports = Vue.component('environment-folder-view', {
template: `
<div :class="cssContainerClass">
<div class="top-area">
<div class="top-area"
v-if="!isLoading"
>
<h3>FOLDER NAME</h3>
<h4 class="js-folder-name environments-folder-name">
Environments / <b>{{folderName}}</b>
</h4>
<ul
v-if="!isLoading"
class="nav-links">
<li v-bind:class="{ 'active': scope ===
undefined
|| scope === 'available' }">
<a :href="availablePath">
<ul class="nav-links">
<li v-bind:class="{ 'active': scope ===
null
|| scope === 'available' }">
<a :href="availablePath"
class="js-available-environments-folder-tab"
>
Available
<span class="badge js-available-environments-count">
{{state.availableCounter}}
...
...
@@ -157,7 +142,7 @@ module.exports = Vue.component('environment-folder-view', {
</a>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped' }">
<a :href="stoppedPath">
<a :href="stoppedPath"
class="js-stopped-environments-folder-tab"
>
Stopped
<span class="badge js-stopped-environments-count">
{{state.stoppedCounter}}
...
...
app/assets/javascripts/lib/utils/common_utils.js.es6
View file @
1285d629
...
...
@@ -241,5 +241,45 @@
acc[element] = DOMStringMapObject[element];
return acc;
}, {});
/**
* Updates the search parameter of a URL given the parameter and values provided.
*
* If no search params are present we'll add it.
* If param for page is already present, we'll update it
* If there are params but not for the given one, we'll add it at the end.
* Returns the new search parameters.
*
* @param {String} param
* @param {Number|String|Undefined|Null} value
* @return {String}
*/
w.gl.utils.setParamInURL = (param, value) => {
let search;
if (window.location.search.length === 0) {
search = `?${param}=${value}`;
}
if (window.location.search.indexOf(param) !== -1) {
const regex = new RegExp(param + '=\\d');
search = window.location.search.replace(regex, `${param}=${value}`);
}
if (window.location.search.length &&
window.location.search.indexOf(param) === -1) {
search = `${window.location.search}&${param}=${value}`;
}
return search;
};
/**
* Converts permission provided as strings to booleans.
*
* @param {String} string
* @returns {Boolean}
*/
w.gl.utils.convertPermissionToBoolean = permission => permission === 'true';
})(window);
}).call(this);
app/assets/stylesheets/pages/environments.scss
View file @
1285d629
...
...
@@ -10,6 +10,11 @@
font-size
:
34px
;
}
.environments-folder-name
{
font-weight
:
normal
;
padding-top
:
20px
;
}
@media
(
max-width
:
$screen-xs-max
)
{
.environments-container
{
width
:
100%
;
...
...
spec/javascripts/environments/environment_table_spec.js.es6
0 → 100644
View file @
1285d629
const EnvironmentTable = require('~/environments/components/environments_table');
describe('Environment item', () => {
preloadFixtures('static/environments/element.html.raw');
beforeEach(() => {
loadFixtures('static/environments/element.html.raw');
});
it('Should render a table', () => {
const mockItem = {
name: 'review',
size: 3,
isFolder: true,
latest: {
environment_path: 'url',
},
};
const component = new EnvironmentTable({
el: document.querySelector('.test-dom-element'),
propsData: {
environments: [{ mockItem }],
canCreateDeployment: false,
canReadEnvironment: true,
},
});
expect(component.$el.tagName).toEqual('TABLE');
});
});
spec/javascripts/environments/folder/environments_folder_view_spec.js.es6
0 → 100644
View file @
1285d629
const Vue = require('vue');
require('~/flash');
const EnvironmentsFolderViewComponent = require('~/environments/folder/environments_folder_view');
const { environmentsList } = require('../mock_data');
describe('Environments Folder View', () => {
preloadFixtures('static/environments/environments_folder_view.html.raw');
beforeEach(() => {
loadFixtures('static/environments/environments_folder_view.html.raw');
window.history.pushState({}, null, 'environments/folders/51');
});
let component;
describe('successfull request', () => {
const environmentsResponseInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify({
environments: environmentsList,
stopped_count: 1,
available_count: 0,
}), {
status: 200,
headers: {
'X-nExt-pAge': '2',
'x-page': '1',
'X-Per-Page': '1',
'X-Prev-Page': '',
'X-TOTAL': '37',
'X-Total-Pages': '2',
},
}));
};
beforeEach(() => {
Vue.http.interceptors.push(environmentsResponseInterceptor);
component = new EnvironmentsFolderViewComponent({
el: document.querySelector('#environments-folder-list-view'),
});
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, environmentsResponseInterceptor,
);
});
it('should render a table with environments', (done) => {
setTimeout(() => {
expect(
component.$el.querySelectorAll('table tbody tr').length,
).toEqual(2);
done();
}, 0);
});
it('should render available tab with count', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-available-environments-folder-tab').textContent,
).toContain('Available');
expect(
component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent,
).toContain('0');
done();
}, 0);
});
it('should render stopped tab with count', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-stopped-environments-folder-tab').textContent,
).toContain('Stopped');
expect(
component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent,
).toContain('1');
done();
}, 0);
});
// FIX ME:
it('should render parent folder name', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-folder-name'),
).toBe(null);
done();
}, 0);
});
describe('pagination', () => {
it('should render pagination', (done) => {
setTimeout(() => {
expect(
component.$el.querySelectorAll('.gl-pagination li').length,
).toEqual(5);
done();
}, 0);
});
it('should update url when no search params are present', (done) => {
spyOn(gl.utils, 'visitUrl');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2');
done();
}, 0);
});
it('should update url when page is already present', (done) => {
spyOn(gl.utils, 'visitUrl');
window.history.pushState({}, null, '?page=1');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2');
done();
}, 0);
});
it('should update url when page and scope are already present', (done) => {
spyOn(gl.utils, 'visitUrl');
window.history.pushState({}, null, '?scope=all&page=1');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?scope=all&page=2');
done();
}, 0);
});
it('should update url when page and scope are already present and page is first param', (done) => {
spyOn(gl.utils, 'visitUrl');
window.history.pushState({}, null, '?page=1&scope=all');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2&scope=all');
done();
}, 0);
});
});
});
describe('unsuccessfull request', () => {
const environmentsErrorResponseInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify([]), {
status: 500,
}));
};
beforeEach(() => {
Vue.http.interceptors.push(environmentsErrorResponseInterceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, environmentsErrorResponseInterceptor,
);
});
it('should not render a table', (done) => {
component = new EnvironmentsFolderViewComponent({
el: document.querySelector('#environments-folder-list-view'),
});
setTimeout(() => {
expect(
component.$el.querySelector('table'),
).toBe(null);
done();
}, 0);
});
it('should render available tab with count 0', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-available-environments-folder-tab').textContent,
).toContain('Available');
expect(
component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent,
).toContain('0');
done();
}, 0);
});
it('should render stopped tab with count 0', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-stopped-environments-folder-tab').textContent,
).toContain('Stopped');
expect(
component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent,
).toContain('0');
done();
}, 0);
});
it('should not render parent folder name', (done) => {
setTimeout(() => {
expect(
component.$el.querySelector('.js-folder-name'),
).toBe(null);
done();
}, 0);
});
});
});
spec/javascripts/fixtures/environments/environments_folder_view.html.haml
0 → 100644
View file @
1285d629
%div
#environments-folder-list-view
{
data:
{
"can-create-deployment"
=>
"true"
,
"can-read-environment"
=>
"true"
,
"css-class"
=>
""
,
"commit-icon-svg"
=>
custom_icon
(
"icon_commit"
),
"terminal-icon-svg"
=>
custom_icon
(
"icon_terminal"
),
"play-icon-svg"
=>
custom_icon
(
"icon_play"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment